|
87417
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
ServiceTest
Run 'ServiceTest'
Debug 'ServiceTest'
More Actions
JetBrains AI
Search Everywhere
IAlPostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskreplaydscreenpipeWindowServercef_server Helper (Renderer)FirefoxCP Isolated Web ContentcoreaudiodlaunchservicesdFirefoxCP Isolated Web ContentActivity MonitorbluetoothdiTerm2language_server_macos_armFirefoxCP Isolated Web ContentWispr FlowNotionFirefoxCP Isolated Web ContentFirefoxFirefoxCP Isolated Web ContentSlackWispr Flow Helper (Renderer)FirefoxWispr Flowlogdcef_server Helper (GPU)Slack Helper (Renderer)Karabiner-Core-ServiceHelp% CPU175,9115,655,226,014,010,38,65,35,35,13,33,13,02,72,42,32,12,12,01,81,61,41,41,31,21,21,11,1CPU Time4:29:47,3324:13:10,496:43:36,463:52:35,718:09:02,669:48,9341:37,331:02:12,061:04:37,6313:44,719:44,3521:17,621:05:07,3012:15,071:06,244:31,4710:13,1020:10,071:50:11,9317:07,5714:09,195:48,4014:30,081:42,8417:19,918:29,461:00:52,9320:57,05System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+51,24%38,21%10,56%CPUED→Jiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana NetsevaGo Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko Kashinski. Galya Dimitrova: Todor Stamatov. Steliyan Georgievto VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...#: AppsJira Cloud• 0.(all100% <78• Thu 28 May 18:36:02Describe what you are looking forlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
PhpStorm
|
faVsco.js – Hubspot/Service.php
|
NULL
|
87417
|
|
87416
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
ServiceTest
Run 'ServiceTest'
Debug 'ServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
7
149
1
33
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Services\Crm\Hubspot;
use Carbon\Carbon;
use Exception;
use Generator;
use GuzzleHttp\Exception\RequestException;
use HubSpot\Client\Crm\Owners\Model\PublicOwner;
use Illuminate\Support\Facades\Cache;
use InvalidArgumentException;
use Jiminny\Contracts\Repositories\TeamRepository;
use Jiminny\Contracts\Services\Crm\ClientInterface;
use Jiminny\Contracts\Services\Crm\FetchRelatedActivityInterface;
use Jiminny\Contracts\Services\Crm\LayoutManagementInterface;
use Jiminny\Contracts\Services\Crm\MatchCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\Provider\HubspotInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityLookupInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityManipulationInterface;
use Jiminny\Contracts\Services\Crm\SavePlaybackLinkToCrmInterface;
use Jiminny\Contracts\Services\Crm\SendSummaryToCrmInterface;
use Jiminny\Contracts\Services\Crm\SettingsInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmMetadataInterface;
use Jiminny\Contracts\Services\Crm\VerifyTaskExistsInterface;
use Jiminny\Exceptions\CrmException;
use Jiminny\Exceptions\HttpNotFoundException;
use Jiminny\Jobs\Crm\NoteObject;
use Jiminny\Models\Account;
use Jiminny\Models\Activity;
use Jiminny\Models\Contact;
use Jiminny\Models\Contracts\ActivityContract;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldData;
use Jiminny\Models\Crm\Layout;
use Jiminny\Models\Crm\Profile;
use Jiminny\Models\Lead;
use Jiminny\Models\Opportunity;
use Jiminny\Models\Participant;
use Jiminny\Models\Playbook;
use Jiminny\Models\SocialAccount;
use Jiminny\Models\Stage;
use Jiminny\Models\User;
use Jiminny\Repositories\Crm\CrmEntityRepository;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\Crm\ProfileRepository;
use Jiminny\Repositories\ParticipantRepository;
use Jiminny\Services\Avatar\ProspectPhotoPathService;
use Jiminny\Services\Crm\BaseService;
use Jiminny\Services\Crm\Hubspot\Actions\SyncArchivedProfilesAction;
use Jiminny\Services\Crm\Hubspot\Fields\ValueNormalizer;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\OpportunitySyncTrait;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\SyncCrmEntitiesTrait;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\SyncFieldsTrait;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\WriteCrmTrait;
use Jiminny\Services\Crm\MatchDomainByEmailInterface;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Services\Crm\ResolveCompanyNameByEmailTrait;
use Jiminny\Utils\PlaybackUrlBuilder;
use Sentry;
use SevenShores\Hubspot\Exceptions\BadRequest;
use Throwable;
use UnexpectedValueException;
/**
* @phpstan-type CrmFieldDefinition array{
* name: string,
* label: string,
* description: string,
* type: string,
* fieldType: string,
* hidden: bool,
* showCurrencySymbol: bool,
* options: array<array{
* id: string,
* label: string,
* value?: string,
* }
*/
class Service extends BaseService implements
HubspotInterface,
SyncCrmEntitiesInterface,
SyncCrmMetadataInterface,
SendSummaryToCrmInterface,
MatchDomainByEmailInterface,
SavePlaybackLinkToCrmInterface,
RemoteEntityManipulationInterface,
FetchRelatedActivityInterface,
LayoutManagementInterface,
SettingsInterface,
MatchCrmEntitiesInterface,
RemoteEntityLookupInterface,
VerifyTaskExistsInterface
{
use ResolveCompanyNameByEmailTrait;
use SyncCrmEntitiesTrait;
use WriteCrmTrait;
use SyncFieldsTrait;
use OpportunitySyncTrait;
private const int ENGAGEMENT_BODY_MAX_LENGTH = 65536;
private const string LOG_DATE_FORMAT = 'Y-m-d H:i:s';
private const int BATCH_UPDATE_LIMIT = 100;
private const string TEN_SECONDLY_ROLLING_POLICY = 'TEN_SECONDLY_ROLLING';
private const int TEN_SECONDLY_ROLLING_LIMIT = 10;
private const string CALLS_SEARCH_ENDPOINT = '[URL_WITH_CREDENTIALS] ClientInterface|Client
*/
protected $client;
protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
protected CrmEntityRepository $crmEntityRepository;
protected ProspectPhotoPathService $prospectPhotoPathService;
private SyncFieldAction $syncFieldAction;
private PayloadBuilder $payloadBuilder;
private SyncRelatedActivityManager $syncRelatedActivityManager;
private SyncArchivedProfilesAction $syncArchivedProfilesAction;
private WebhookSyncBatchProcessor $batchProcessor;
public function __construct(
Client $client,
SyncFieldAction $syncFieldAction,
PayloadBuilder $payloadBuilder,
ProspectPhotoPathService $prospectPhotoPathService,
SyncArchivedProfilesAction $syncArchivedProfilesAction,
WebhookSyncBatchProcessor $batchProcessor,
) {
parent::__construct();
$this->client = $client;
$this->syncFieldAction = $syncFieldAction;
$this->prospectPhotoPathService = $prospectPhotoPathService;
$this->payloadBuilder = $payloadBuilder;
$this->syncArchivedProfilesAction = $syncArchivedProfilesAction;
$this->batchProcessor = $batchProcessor;
$this->opportunitySyncStrategyResolver = app(OpportunitySyncStrategyResolver::class, [
'client' => $this->client,
]);
$this->syncRelatedActivityManager = app(SyncRelatedActivityManager::class, [
'client' => $this->client,
'payloadBuilder' => $this->payloadBuilder,
'logger' => $this->logger,
]);
$this->crmEntityRepository = app(CrmEntityRepository::class);
$this->dealFieldsService = app(DealFieldsService::class);
}
public function getDisplayName(): string
{
return 'HubSpot';
}
protected function getOAuthAccount(User $user): ?SocialAccount
{
// In this case, the Account Owner is always the connection for any API operations.
$owner = $user->team->owner;
return $owner->getSocialAccount(SocialAccount::PROVIDER_HUBSPOT);
}
public function getClient(): Client
{
/** @var Client */
return $this->client;
}
/**
* Convert raw field data into a format compatible with CRM APIs.
*
* @param bool $internal Direction of the conversion.
* True is pulling from CRM, false normalize before sending to CRM.
*/
public function normalizeValue(string $fieldType, string $fieldValue, bool $internal = false): string
{
return ValueNormalizer::normalize(
fieldType: $fieldType,
fieldValue: $fieldValue,
isInbound: $internal,
);
}
/**
* @inheritdoc
*/
public function getDefaultFields(string $activityType): array
{
$fields = [];
if ($activityType === Playbook::ACTIVITY_TYPE_TASK) {
$defaultFields = FieldDefinitions::defaultTaskFields();
// This lazy creates these fields if not already setup.
foreach ($defaultFields as $defaultField) {
$fields[] = $this->config->fields()->firstOrCreate($defaultField);
}
}
return $fields;
}
/**
* @inheritdoc
*/
public function getDefaultActivityField(string $activityType): Field
{
/** @var Field $activityField */
$activityField = $this->config->fields()->where([
'crm_provider_id' => 'activityType',
'object_type' => $activityType,
])->first();
return $activityField;
}
/**
* @inheritdoc
*/
public function getSupportedPlaybookTypes(): array
{
return [Playbook::ACTIVITY_TYPE_TASK];
}
/**
* @inheritdoc
*/
public function getDefaultActivityLayoutFields(string $activityType, string $layoutType): array
{
$fields = [];
if ($activityType === Playbook::ACTIVITY_TYPE_TASK) {
// Outcome should always be provided calls/meetings.
$fieldData = [
[
'crm_provider_id' => $layoutType === Layout::TYPE_SOFTPHONE_SUMMARY ? 'disposition' : 'meetingOutcome',
'object_type' => Field::OBJECT_TASK,
],
];
foreach ($fieldData as $data) {
$field = $this->config->fields()->where($data)->first();
// Only add the field if it is created, which it should be.
if ($field) {
$fields[] = $field;
}
}
}
return $fields;
}
public function getDealInsightsFields(): array
{
return FieldDefinitions::dealInsightsFields();
}
protected function getDefaultFollowupLayoutFields(string $activityType): array
{
$fields = [];
$fieldRepo = app(FieldRepository::class);
$fieldData = FieldDefinitions::followupFieldsFilter();
foreach ($fieldData as $data) {
$field = $fieldRepo->findOneConfigurationFieldByProperties($this->config, $data);
// Only add the field if it is created, which it should be.
if ($field) {
$fields[] = $field;
}
}
return $fields;
}
/**
* @inheritdoc
*/
public function syncField(Field $field): void
{
switch ($field->object_type) {
case Field::OBJECT_ACCOUNT:
$crmField = $this->client->getInstance()->companyProperties()->get($field->crm_provider_id);
break;
case Field::OBJECT_CONTACT:
$crmField = $this->client->getInstance()->contactProperties()->get($field->crm_provider_id);
break;
case Field::OBJECT_OPPORTUNITY:
$crmField = $this->client->getInstance()->dealProperties()->get($field->crm_provider_id);
break;
case Field::OBJECT_TASK:
$this->syncSingleTaskField($field);
return;
default:
return;
}
$this->syncFieldAction->execute($field, $crmField->toArray());
}
/**
* @param array<array{
* id:string,
* label:string,
* value?:string
* }> $options
*
* @throws CrmException
*
* @return FieldData[]
*
*/
public function importPicklistValues(
Field $field,
array $options = [['id' => '', 'label' => '', 'value' => '']],
): array {
if (! empty($options[0]['id']) || ! empty($options[0]['value'])) {
// We already have the options, no need to fetch them again
return $this->importOptions($field, $options);
}
$options = [];
switch ($field->getObjectType()) {
case Field::OBJECT_ACCOUNT:
$options = $this->getClient()->fetchPropertyOptions('company', $field->getCrmProviderId());
break;
case Field::OBJECT_CONTACT:
$options = $this->getClient()->fetchPropertyOptions('contact', $field->getCrmProviderId());
break;
case Field::OBJECT_OPPORTUNITY:
// Hubspot has different endpoint for stages
$options = $this->getClient()->fetchOpportunityFieldOptions($field);
break;
case Field::OBJECT_TASK:
if ($field->getCrmProviderId() === 'disposition') {
$options = $this->getClient()->fetchDispositionFieldOptions();
} elseif (in_array($field->getCrmProviderId(), ['meetingOutcome', 'activityType'])) {
$options = $this->getClient()->fetchMeetingOutcomeFieldOptions($field);
}
break;
default:
$this->logger->warning('Invalid object type', [
'object_type' => $field->getObjectType(),
'field_id' => $field->getId(),
]);
throw new CrmException('Invalid object type');
}
return $this->importOptions($field, $options);
}
/**
* @inheritdoc
*/
public function importStages(?array $types = null, ?string $missingStageName = null): ?Stage
{
$missingStage = null;
try {
// Use the HubSpot API client instead of the SDK crmPipelines() method
$endpoint = self::getDealsPipelinesEndpoint();
$pipelinesResponse = $this->client->getInstance()->getClient()->request('GET', $endpoint);
$pipelines = $pipelinesResponse->data->results;
} catch (RequestException|BadRequest $exception) {
throw $exception;
}
foreach ($pipelines as $pipeline) {
$stages = [];
// We create a business process to contain the pipeline, and store all stages against it.
$p = ResponseNormalize::normalizePipeline($pipeline);
// Create/update business process for this pipeline
$businessProcess = $this->config->businessProcesses()->updateOrCreate([
'crm_provider_id' => $p['id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($p['label'], 0, 150),
'type' => BusinessProcess::TYPE_OPPORTUNITY,
'is_selectable' => $p['active'],
]);
// A record type is really a clone of the business process, used to store which record uses which pipeline.
// Create/update record type clone
$this->config->recordTypes()->updateOrCreate([
'crm_provider_id' => $p['id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($p['label'], 0, 150),
'is_selectable' => $p['active'],
'business_process_id' => $businessProcess->id ?? null,
]);
// Stages - fetch all existing stages upfront to avoid N+1 queries
$existingStages = $this->config->stages()
->withTrashed()
->where('type', Stage::TYPE_OPPORTUNITY)
->get()
->keyBy('crm_provider_id');
foreach ($p['stages'] as $dealStage) {
$s = ResponseNormalize::normalizeDealStage($dealStage);
/** @var ?Stage $existingStage */
$existingStage = $existingStages->get($s['id']);
// Restore soft-deleted stages that are now active in HubSpot
if ($existingStage?->trashed() && $s['active']) {
$existingStage->restore();
}
// Upsert stage (updates soft-deleted records without restoring them)
$stage = $this->config->stages()->withTrashed()->updateOrCreate([
'crm_provider_id' => $s['id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($s['label'], 0, 50),
'label' => mb_strimwidth($s['label'], 0, 191),
'type' => Stage::TYPE_OPPORTUNITY,
'sequence' => $s['displayOrder'],
'is_selectable' => $s['active'],
'probability' => $s['probability'] * 100,
]);
if ($missingStageName === $s['id']) {
$missingStage = $stage;
}
$stages[] = $stage->id;
}
$businessProcess->stages()->sync($stages);
}
return $missingStage;
}
/**
* @inheritdoc
*/
public function syncOrganization(): void
{
try {
$endpoint = '[URL_WITH_CREDENTIALS]
*/
public function find(string $name, array $scopes): array
{
$count = $this->limit ?? 20;
$offset = $this->offset ?? 0;
/** @var array<int, array<string, mixed>> */
return Cache::remember(
key: $this->team->getId() . $name . $count . $offset,
ttl: 300,
callback: function () use ($name, $offset, $count): array {
$data = [];
// Use the new V3 API to find contacts based on additional fields.
foreach (['companies', 'contacts'] as $objectType) {
$endpoint = '[URL_WITH_CREDENTIALS]
*/
public function findOpportunities(?string $crmAccountId, ?string $crmContactId, ?int $userId = null): array
{
$data = [];
$ownerData = [];
$ownerId = null;
if ($crmAccountId === null) {
return $data;
}
if ($userId) {
$profileRepository = app(ProfileRepository::class);
$profile = $profileRepository->findProfileByUserId($this->config, $userId);
$ownerId = $profile instanceof Profile ? $profile->getCrmProviderId() : null;
}
$closedStages = $this->getClosedDealStages();
$payload = $this->payloadBuilder->generateOpportunitiesSearchPayload(
$this->config,
$crmAccountId,
$closedStages,
);
$results = $this->client->getPaginatedData($payload, 'deals');
foreach ($results['results'] as $object) {
$properties = $object['properties'];
$amount = null;
if (empty($properties['amount']) === false) {
$currency = $properties['deal_currency_code'] ?? $this->config->default_currency;
// Values can contain commas and any junk so strip them.
$value = (float) preg_replace('/[^\d.]/', '', $properties['amount']);
$amount = formatCurrency($value, $currency);
}
$businessProcess = $this->config
->businessProcesses()
->where('crm_provider_id', $properties['pipeline'])
->first();
if ($businessProcess === null) {
// Import it.
$stage = $this->importStages([Stage::TYPE_OPPORTUNITY], $properties['dealstage']);
$businessProcess = $this->config
->businessProcesses()
->where('crm_provider_id', $properties['pipeline'])
->first();
} else {
$stage = $businessProcess
->stages()
->where('crm_provider_id', $properties['dealstage'])
->where('type', Stage::TYPE_OPPORTUNITY)
->first();
if ($stage === null) {
// Import it.
$stage = $this->importStages(null, $properties['dealstage']);
}
}
$recordType = null;
if ($businessProcess) {
$recordType = $businessProcess->recordTypes()->first();
}
$isWon = in_array($properties['dealstage'], $closedStages['won']);
$isLost = in_array($properties['dealstage'], $closedStages['lost']);
$record = [
'crmId' => $object['id'],
'name' => $properties['dealname'] ?? 'Unknown Deal',
'value' => $amount,
'won' => $isWon,
'closed' => $isWon || $isLost,
'stage' => [
'id' => $stage?->getUuid() ?? '',
'name' => $stage?->getName() ?? '',
],
];
if ($recordType) {
$record += [
'recordType' => [
'id' => $recordType->id_string,
'name' => $recordType->name,
],
];
}
if ($ownerId && isset($properties['hubspot_owner_id']) && $properties['hubspot_owner_id'] === $ownerId) {
$ownerData[] = $record;
}
$data[] = $record;
}
if (! empty($ownerData)) {
return $ownerData;
}
return $data;
}
/**
* @inheritdoc
*/
public function getTasks(?string $objectType, string $objectId, ?string $opportunityId): array
{
$data = [];
switch ($objectType) {
case 'contact':
$hsObject = 'contact';
break;
case 'account':
$hsObject = 'company';
break;
default:
// This is a hack to prioritise and override a contact/company with a deal.
if ($opportunityId) {
$hsObject = 'deal';
$objectId = $opportunityId;
} else {
throw new InvalidArgumentException('Object type not supported.');
}
}
$engagementTypes = ['meetings', 'tasks'];
foreach ($engagementTypes as $engagementType) {
$payload = $this->payloadBuilder->getLinkToTaskPayload($hsObject, $objectId, $engagementType);
$this->logger->info('[HubSpot] CRM Search requested', [
'request' => $payload,
]);
$engagements = $this->client->getPaginatedData($payload, $engagementType);
foreach ($engagements['results'] as $engagement) {
if ($engagementType == 'meetings') {
$title = $engagement['properties']['hs_meeting_title'] ?? 'Scheduled meeting';
} elseif ($engagementType == 'tasks') {
$title = $engagement['properties']['hs_task_subject'];
} else {
$title = 'Scheduled meeting';
}
$data[] = [
'crmId' => $engagement['id'],
'subject' => $title,
'due' => $engagement['properties']['hs_timestamp'],
'type' => $engagement['properties']['hs_activity_type'] ?? null,
];
}
}
usort($data, function ($item1, $item2) {
return $item2['due'] <=> $item1['due'];
});
return $data;
}
/**
* Try to find CRM Objects using email address
*
* @return null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
public function matchExactlyByEmail(string $email, ?int $userId = null): ?array
{
$contactProperties = [
'email',
'firstname',
'lastname',
'country',
'phone',
'mobilephone',
'jobtitle',
'hubspot_owner_id',
'associatedcompanyid',
'photo',
];
$contact = null;
$account = null;
try {
$hsContact = $this->getClient()->getContactByEmail($email, $contactProperties);
if ($hsContact) {
$contact = $this->importContact($hsContact);
$account = $contact->account;
}
$data = $this->convertCrmData($contact, $account, $userId);
return ! empty(array_filter($data)) ? $data : null;
} catch (BadRequest $e) {
$this->logger->warning('[HubSpot] Search failed', [
'team_id' => $this->team->getId(),
'search_identifier' => $email,
'reason' => $e->getMessage(),
]);
}
return null;
}
public function getDomain(string $email): ?string
{
return $this->getDomainFromEmail($email);
}
/**
* Try to find CRM objects using domain name of the email address
*
* @return null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
public function matchByDomain(string $domain, ?int $userId = null): ?array
{
$companyName = $domain;
// Try to find a company matching their email domain.
$companyProperties = [
'country',
'phone',
'name',
'hs_avatar_filemanager_key',
'industry',
'hubspot_owner_id',
'domain',
];
try {
$hsAccounts = $this->client
->getInstance()
->companies()
->searchByDomain($companyName, $companyProperties);
} catch (Throwable $e) {
$this->logger->info('[HubSpot] Search failed', [
'error' => $e->getMessage(),
'domain' => $domain,
]);
return null;
}
$account = null;
// If there are multiple accounts, don't guess, we'll ask later.
if (\count($hsAccounts->data->results) === 1) {
// Persist this remote object.
$account = $this->syncAccount($hsAccounts->data->results[0]->companyId);
}
$data = $this->convertCrmData(null, $account, $userId);
return ! empty(array_filter($data)) ? $data : null;
}
/**
* @return array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
protected function convertCrmData(?Contact $contact, ?Account $account, ?int $userId = null): array
{
$countryCode = null;
if ($contact && $contact->country_code) {
$countryCode = $contact->country_code;
} elseif ($account && $account->country_code) {
$countryCode = $account->country_code;
}
try {
$hsOpportunities = $this->findOpportunities(
$account ? $account->crm_provider_id : null,
$contact ? $contact->crm_provider_id : null,
$userId
);
} catch (Exception $e) {
$hsOpportunities = [];
}
// If there are multiple opportunities, don't guess, we'll ask later.
$opportunity = null;
$stage = null;
if (! empty($hsOpportunities)) {
// Persist this remote object.
$opportunity = $this->syncOpportunity($hsOpportunities[0]['crmId']);
$stage = $opportunity?->getStage();
}
return [
null,
$account,
$opportunity,
$contact,
$stage,
$countryCode,
];
}
protected function getCacheKey(string $object, ?int $userId = null): ?string
{
$key = $this->team->getId() . $object;
$keySuffix = $this->getOwnerKeySuffix($userId);
return $key . $keySuffix;
}
private function getOwnerKeySuffix(?int $userId = null): string
{
return $userId === null ? '' : (string) $userId;
}
/**
* @return null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
*}
*/
public function matchByPhone(string $phone, ?string $rawPhoneNumber = null, ?int $userId = null): ?array
{
if (str_contains($phone, '**')) {
return null;
}
// trim all whitespaces if present so the lookup doesn't fail
$phone = str_replace(' ', '', $phone);
// Check if the user is internal.
if ($this->isPhoneNumberOfTeamMember($phone)) {
return null;
}
$response = $this->searchForPhoneNumber($phone);
if (empty($response)) {
return null;
}
// This would ideally importContact instead but the response type differs.
$contact = $this->findAndSyncContact($response['results'][0]['id']);
if (! $contact instanceof Contact) {
return null;
}
$account = $contact->account;
$countryCode = $contact->country_code ?? $account->country_code ?? null;
try {
$hsOpportunities = $this->findOpportunities(
$account?->crm_provider_id,
$contact->crm_provider_id,
$userId
);
} catch (Exception $e) {
$hsOpportunities = [];
}
$opportunity = null;
$stage = null;
try {
if (! empty($hsOpportunities)) {
// Persist this remote object.
$opportunity = $this->syncOpportunity($hsOpportunities[0]['crmId']);
$stage = $opportunity?->getStage();
}
} catch (Exception $e) {
$this->logger->debug('[HubSpot] Opportunity failed to sync.', [
'reason' => $e->getMessage(),
]);
}
return [
null,
$account,
$opportunity,
$contact,
$stage,
$countryCode,
];
}
private function isPhoneNumberOfTeamMember(string $phone): bool
{
$teamRepository = app(TeamRepository::class);
$user = $teamRepository->findTeamMemberByPhone($this->team, $phone);
if ($user instanceof User) {
return true;
}
return false;
}
private function findAndSyncContact(string $crmId): ?Contact
{
try {
return $this->syncContact($crmId);
} catch (Exception $exception) {
$this->logger->info('[HubSpot] Phone match failed', [
'reason' => $exception->getMessage(),
]);
return null;
}
}
private function hasResults(array $response): bool
{
return isset($response['total']) && is_numeric($response['total']) && $response['total'] > 0;
}
private function searchForPhoneNumber(string $phone): array
{
// Normalizes the provided phone number for the API search.
$normalizedPhone = $this->normalizePhoneNumber($phone);
$payload = $this->payloadBuilder->generatePhoneSearchPayload($normalizedPhone);
$this->logger->info('[HubSpot] Phone match search triggered', [
'phone' => $phone,
'normalizedPhone' => $normalizedPhone,
'payload' => $payload,
]);
$response = $this->handlePhoneSearchRequest($normalizedPhone, $payload);
if (! $this->hasResults($response)) {
$nationalPhone = preg_replace('/\D/', '', phone_national(null, $phone));
$payload = $this->payloadBuilder->generatePhoneSearchPayload($nationalPhone);
$this->logger->info('[HubSpot] Phone match national number search triggered', [
'phone' => $phone,
'nationalPhone' => $nationalPhone,
'payload' => $payload,
]);
$response = $this->handlePhoneSearchRequest($phone, $payload);
}
if (! $this->hasResults($response)) {
$payload = $this->payloadBuilder->generatePhoneSearchPayload($normalizedPhone, true);
$this->logger->info('[HubSpot] Phone match alternative search triggered', [
'phone' => $phone,
'normalizedPhone' => $normalizedPhone,
'payload' => $payload,
]);
$response = $this->handlePhoneSearchRequest($phone, $payload);
}
return $this->hasResults($response) ? $response : [];
}
private function handlePhoneSearchRequest(string $phone, array $payload): array
{
$endpoint = '[URL_WITH_CREDENTIALS] null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
public function matchByName(string $name, ?int $userId = null): ?array
{
// Don't waste time searching for single character strings.
if (\strlen($name) <= 1) {
return null;
}
$cacheKey = $this->getCacheKey($name, $userId);
$result = Cache::remember($cacheKey, 60, function () use ($name, $userId) {
$payload = $this->payloadBuilder->generateSearchContactsByNamePayload(
$name,
$this->getContactFields()
);
$hsContacts = $this->client->getPaginatedData($payload, 'contact');
if (empty($hsContacts['results'])) {
return false;
}
$contact = $this->importContact($hsContacts['results'][0]);
if ($contact === null) {
return false;
}
$account = $contact->account;
$countryCode = $contact->country_code ?? $account->country_code ?? null;
try {
$hsOpportunities = $this->findOpportunities(
$account ? $account->crm_provider_id : null,
$contact->crm_provider_id,
$userId
);
} catch (Exception $e) {
$hsOpportunities = [];
}
$opportunity = null;
$stage = null;
if (! empty($hsOpportunities)) {
// Persist this remote object.
$opportunity = $this->syncOpportunity($hsOpportunities[0]['crmId']);
$stage = $opportunity?->getStage();
}
return [
null,
$account,
$opportunity,
$contact,
$stage,
$countryCode,
];
});
return is_array($result) ? $result : null;
}
private function convertActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->account->crm_provider_id] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->opportunity->crm_provider_id] : [],
'ownerIds' => [],
];
}
private function getParticipantsIds(Activity $activity): array
{
$attendees = [];
$participantRepository = app(ParticipantRepository::class);
$participants = $participantRepository->getParticipantsWhoEnteredMeeting($activity);
foreach ($participants as $participant) {
if ($participant->user_id || $participant->isCoach()) {
continue;
}
$contact = $participant->contact()->first();
if ($contact && $contact->crm_provider_id) {
$attendees[] = $contact->crm_provider_id;
} else {
if (! empty($participant->name)) {
$attendeeData = $this->fetchMissingAttendeeInfo($participant);
}
if (! empty($attendeeData['id'])) {
$attendees[] = $attendeeData['id'];
}
}
}
if ($activity->hasContact()) {
$attendees[] = $activity->contact->crm_provider_id;
}
return array_unique($attendees);
}
private function fetchMissingAttendeeInfo(Participant $participant): array
{
// Check if we need to look inside an account context.
$activity = $participant->getActivity();
$companyId = $activity->hasAccount() ? $activity->getAccount()->crm_provider_id : null;
// First check the local data.
/** @var Contact[] $contacts */
$contacts = $this->team->contacts()
->with('account')
->where('name', $participant->name)
->whereNotNull('email')
->get();
foreach ($contacts as $contact) {
// If we have a company in scope, check the contact is associated to it.
if (
$companyId !== null
&& ($contact->account_id === null || $companyId !== $contact->account->crm_provider_id)
) {
continue;
}
return [
'id' => $contact->crm_provider_id,
'email' => $contact->email,
];
}
$payload = $this->generateNameSearchPayload($participant->name, 0, 20);
try {
$response = $this->client->getNewInstance()->crm()->contacts()->searchApi()->doSearch($payload);
// TODO add some logic to choose the most suitable contact if multiple
foreach ($response['results'] as $object) {
$properties = $object['properties'];
if (empty($object['properties']) === false) {
// Check the company matches the contact.
// Todo: Move this check inside the API search.
if ($companyId !== null && $companyId !== $properties['associatedcompanyid']) {
continue;
}
return [
'id' => $object['id'],
'email' => $properties['email'],
];
}
}
} catch (Exception $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Search failed', [
'teamId' => $this->team->id_string,
'request' => $payload,
'reason' => $e->getMessage(),
]);
}
return [];
}
/**
* Store transcripts as note engagement.
*
* @throws Exception
*/
public function createTranscriptNotes(Activity $activity): void
{
// For HS no need to check if Crm profile - Log Notes field is enabled
// We only check if store_transcript toggle is enabled on crm profile.
$engagement = [
'active' => true,
'ownerId' => $this->profile->crm_provider_id,
'timestamp' => $activity->created_at->tz($activity->user->timezone)->getTimestamp() * 1000,
'type' => 'NOTE',
];
// Generate activity tr...
|
PhpStorm
|
faVsco.js – Hubspot/Service.php
|
NULL
|
87416
|
|
87415
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
ServiceTest
Run 'ServiceTest'
Debug 'ServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
7
149
1
33
1
Previous Highlighted Error
IAlPostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskreplaydscreenpipeFirefoxCP Isolated Web ContentWindowServerFirefoxCP Isolated Web Contentcef_server Helper (Renderer)FirefoxcoreaudiodActivity Monitorlaunchservicesdbluetoothdlanguage_server_macos_armFirefoxCP Isolated Web ContentWispr FlowFirefoxCP Isolated Web ContentiTerm2FirefoxCP Isolated Web ContentFirefoxCP Isolated Web Contentcef_server Helper (GPU)Wispr Flow Helper (Renderer)auditdFirefoxCP Isolated Web Contentcef_serverWispr FlowSlack Helper (Renderer)Karabiner-Core-ServiceHelp% CPU156,0148,856,538,624,722,58,27,0CPU Time4:29:38,0324:13:04,376:43:33,543:52:34,3413:44,448:09:01,9241:36,879:48,381:50:11,831:02:11,779:44,171:04:37,3521:17,4612:14,9217:07,474:31,351:06,111:05:07,1410:23,1320:09,978:29,405:48,339:08,226:36,284:24,031:42,771:00:52,8720:56,99System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp ,81%39,22%32,97%CPUWNNNHomeDMsActivityFilesLater..•More+ED→Jiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana Netseva€o Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko Kashinski. Galya Dimitrova: Todor Stamatov. Steliyan Georgievto VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...#: AppsJira Cloud• 0.(all100% <78• Thu 28 May 18:35:58Describe what you are looking forlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
PhpStorm
|
faVsco.js – Hubspot/Service.php
|
NULL
|
87415
|
|
87414
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
ServiceTest
Run 'ServiceTest'
Debug 'ServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
7
149
1
33
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Services\Crm\Hubspot;
use Carbon\Carbon;
use Exception;
use Generator;
use GuzzleHttp\Exception\RequestException;
use HubSpot\Client\Crm\Owners\Model\PublicOwner;
use Illuminate\Support\Facades\Cache;
use InvalidArgumentException;
use Jiminny\Contracts\Repositories\TeamRepository;
use Jiminny\Contracts\Services\Crm\ClientInterface;
use Jiminny\Contracts\Services\Crm\FetchRelatedActivityInterface;
use Jiminny\Contracts\Services\Crm\LayoutManagementInterface;
use Jiminny\Contracts\Services\Crm\MatchCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\Provider\HubspotInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityLookupInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityManipulationInterface;
use Jiminny\Contracts\Services\Crm\SavePlaybackLinkToCrmInterface;
use Jiminny\Contracts\Services\Crm\SendSummaryToCrmInterface;
use Jiminny\Contracts\Services\Crm\SettingsInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmMetadataInterface;
use Jiminny\Contracts\Services\Crm\VerifyTaskExistsInterface;
use Jiminny\Exceptions\CrmException;
use Jiminny\Exceptions\HttpNotFoundException;
use Jiminny\Jobs\Crm\NoteObject;
use Jiminny\Models\Account;
use Jiminny\Models\Activity;
use Jiminny\Models\Contact;
use Jiminny\Models\Contracts\ActivityContract;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldData;
use Jiminny\Models\Crm\Layout;
use Jiminny\Models\Crm\Profile;
use Jiminny\Models\Lead;
use Jiminny\Models\Opportunity;
use Jiminny\Models\Participant;
use Jiminny\Models\Playbook;
use Jiminny\Models\SocialAccount;
use Jiminny\Models\Stage;
use Jiminny\Models\User;
use Jiminny\Repositories\Crm\CrmEntityRepository;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\Crm\ProfileRepository;
use Jiminny\Repositories\ParticipantRepository;
use Jiminny\Services\Avatar\ProspectPhotoPathService;
use Jiminny\Services\Crm\BaseService;
use Jiminny\Services\Crm\Hubspot\Actions\SyncArchivedProfilesAction;
use Jiminny\Services\Crm\Hubspot\Fields\ValueNormalizer;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\OpportunitySyncTrait;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\SyncCrmEntitiesTrait;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\SyncFieldsTrait;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\WriteCrmTrait;
use Jiminny\Services\Crm\MatchDomainByEmailInterface;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Services\Crm\ResolveCompanyNameByEmailTrait;
use Jiminny\Utils\PlaybackUrlBuilder;
use Sentry;
use SevenShores\Hubspot\Exceptions\BadRequest;
use Throwable;
use UnexpectedValueException;
/**
* @phpstan-type CrmFieldDefinition array{
* name: string,
* label: string,
* description: string,
* type: string,
* fieldType: string,
* hidden: bool,
* showCurrencySymbol: bool,
* options: array<array{
* id: string,
* label: string,
* value?: string,
* }
*/
class Service extends BaseService implements
HubspotInterface,
SyncCrmEntitiesInterface,
SyncCrmMetadataInterface,
SendSummaryToCrmInterface,
MatchDomainByEmailInterface,
SavePlaybackLinkToCrmInterface,
RemoteEntityManipulationInterface,
FetchRelatedActivityInterface,
LayoutManagementInterface,
SettingsInterface,
MatchCrmEntitiesInterface,
RemoteEntityLookupInterface,
VerifyTaskExistsInterface
{
use ResolveCompanyNameByEmailTrait;
use SyncCrmEntitiesTrait;
use WriteCrmTrait;
use SyncFieldsTrait;
use OpportunitySyncTrait;
private const int ENGAGEMENT_BODY_MAX_LENGTH = 65536;
private const string LOG_DATE_FORMAT = 'Y-m-d H:i:s';
private const int BATCH_UPDATE_LIMIT = 100;
private const string TEN_SECONDLY_ROLLING_POLICY = 'TEN_SECONDLY_ROLLING';
private const int TEN_SECONDLY_ROLLING_LIMIT = 10;
private const string CALLS_SEARCH_ENDPOINT = '[URL_WITH_CREDENTIALS] ClientInterface|Client
*/
protected $client;
protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
protected CrmEntityRepository $crmEntityRepository;
protected ProspectPhotoPathService $prospectPhotoPathService;
private SyncFieldAction $syncFieldAction;
private PayloadBuilder $payloadBuilder;
private SyncRelatedActivityManager $syncRelatedActivityManager;
private SyncArchivedProfilesAction $syncArchivedProfilesAction;
private WebhookSyncBatchProcessor $batchProcessor;
public function __construct(
Client $client,
SyncFieldAction $syncFieldAction,
PayloadBuilder $payloadBuilder,
ProspectPhotoPathService $prospectPhotoPathService,
SyncArchivedProfilesAction $syncArchivedProfilesAction,
WebhookSyncBatchProcessor $batchProcessor,
) {
parent::__construct();
$this->client = $client;
$this->syncFieldAction = $syncFieldAction;
$this->prospectPhotoPathService = $prospectPhotoPathService;
$this->payloadBuilder = $payloadBuilder;
$this->syncArchivedProfilesAction = $syncArchivedProfilesAction;
$this->batchProcessor = $batchProcessor;
$this->opportunitySyncStrategyResolver = app(OpportunitySyncStrategyResolver::class, [
'client' => $this->client,
]);
$this->syncRelatedActivityManager = app(SyncRelatedActivityManager::class, [
'client' => $this->client,
'payloadBuilder' => $this->payloadBuilder,
'logger' => $this->logger,
]);
$this->crmEntityRepository = app(CrmEntityRepository::class);
$this->dealFieldsService = app(DealFieldsService::class);
}
public function getDisplayName(): string
{
return 'HubSpot';
}
protected function getOAuthAccount(User $user): ?SocialAccount
{
// In this case, the Account Owner is always the connection for any API operations.
$owner = $user->team->owner;
return $owner->getSocialAccount(SocialAccount::PROVIDER_HUBSPOT);
}
public function getClient(): Client
{
/** @var Client */
return $this->client;
}
/**
* Convert raw field data into a format compatible with CRM APIs.
*
* @param bool $internal Direction of the conversion.
* True is pulling from CRM, false normalize before sending to CRM.
*/
public function normalizeValue(string $fieldType, string $fieldValue, bool $internal = false): string
{
return ValueNormalizer::normalize(
fieldType: $fieldType,
fieldValue: $fieldValue,
isInbound: $internal,
);
}
/**
* @inheritdoc
*/
public function getDefaultFields(string $activityType): array
{
$fields = [];
if ($activityType === Playbook::ACTIVITY_TYPE_TASK) {
$defaultFields = FieldDefinitions::defaultTaskFields();
// This lazy creates these fields if not already setup.
foreach ($defaultFields as $defaultField) {
$fields[] = $this->config->fields()->firstOrCreate($defaultField);
}
}
return $fields;
}
/**
* @inheritdoc
*/
public function getDefaultActivityField(string $activityType): Field
{
/** @var Field $activityField */
$activityField = $this->config->fields()->where([
'crm_provider_id' => 'activityType',
'object_type' => $activityType,
])->first();
return $activityField;
}
/**
* @inheritdoc
*/
public function getSupportedPlaybookTypes(): array
{
return [Playbook::ACTIVITY_TYPE_TASK];
}
/**
* @inheritdoc
*/
public function getDefaultActivityLayoutFields(string $activityType, string $layoutType): array
{
$fields = [];
if ($activityType === Playbook::ACTIVITY_TYPE_TASK) {
// Outcome should always be provided calls/meetings.
$fieldData = [
[
'crm_provider_id' => $layoutType === Layout::TYPE_SOFTPHONE_SUMMARY ? 'disposition' : 'meetingOutcome',
'object_type' => Field::OBJECT_TASK,
],
];
foreach ($fieldData as $data) {
$field = $this->config->fields()->where($data)->first();
// Only add the field if it is created, which it should be.
if ($field) {
$fields[] = $field;
}
}
}
return $fields;
}
public function getDealInsightsFields(): array
{
return FieldDefinitions::dealInsightsFields();
}
protected function getDefaultFollowupLayoutFields(string $activityType): array
{
$fields = [];
$fieldRepo = app(FieldRepository::class);
$fieldData = FieldDefinitions::followupFieldsFilter();
foreach ($fieldData as $data) {
$field = $fieldRepo->findOneConfigurationFieldByProperties($this->config, $data);
// Only add the field if it is created, which it should be.
if ($field) {
$fields[] = $field;
}
}
return $fields;
}
/**
* @inheritdoc
*/
public function syncField(Field $field): void
{
switch ($field->object_type) {
case Field::OBJECT_ACCOUNT:
$crmField = $this->client->getInstance()->companyProperties()->get($field->crm_provider_id);
break;
case Field::OBJECT_CONTACT:
$crmField = $this->client->getInstance()->contactProperties()->get($field->crm_provider_id);
break;
case Field::OBJECT_OPPORTUNITY:
$crmField = $this->client->getInstance()->dealProperties()->get($field->crm_provider_id);
break;
case Field::OBJECT_TASK:
$this->syncSingleTaskField($field);
return;
default:
return;
}
$this->syncFieldAction->execute($field, $crmField->toArray());
}
/**
* @param array<array{
* id:string,
* label:string,
* value?:string
* }> $options
*
* @throws CrmException
*
* @return FieldData[]
*
*/
public function importPicklistValues(
Field $field,
array $options = [['id' => '', 'label' => '', 'value' => '']],
): array {
if (! empty($options[0]['id']) || ! empty($options[0]['value'])) {
// We already have the options, no need to fetch them again
return $this->importOptions($field, $options);
}
$options = [];
switch ($field->getObjectType()) {
case Field::OBJECT_ACCOUNT:
$options = $this->getClient()->fetchPropertyOptions('company', $field->getCrmProviderId());
break;
case Field::OBJECT_CONTACT:
$options = $this->getClient()->fetchPropertyOptions('contact', $field->getCrmProviderId());
break;
case Field::OBJECT_OPPORTUNITY:
// Hubspot has different endpoint for stages
$options = $this->getClient()->fetchOpportunityFieldOptions($field);
break;
case Field::OBJECT_TASK:
if ($field->getCrmProviderId() === 'disposition') {
$options = $this->getClient()->fetchDispositionFieldOptions();
} elseif (in_array($field->getCrmProviderId(), ['meetingOutcome', 'activityType'])) {
$options = $this->getClient()->fetchMeetingOutcomeFieldOptions($field);
}
break;
default:
$this->logger->warning('Invalid object type', [
'object_type' => $field->getObjectType(),
'field_id' => $field->getId(),
]);
throw new CrmException('Invalid object type');
}
return $this->importOptions($field, $options);
}
/**
* @inheritdoc
*/
public function importStages(?array $types = null, ?string $missingStageName = null): ?Stage
{
$missingStage = null;
try {
// Use the HubSpot API client instead of the SDK crmPipelines() method
$endpoint = self::getDealsPipelinesEndpoint();
$pipelinesResponse = $this->client->getInstance()->getClient()->request('GET', $endpoint);
$pipelines = $pipelinesResponse->data->results;
} catch (RequestException|BadRequest $exception) {
throw $exception;
}
foreach ($pipelines as $pipeline) {
$stages = [];
// We create a business process to contain the pipeline, and store all stages against it.
$p = ResponseNormalize::normalizePipeline($pipeline);
// Create/update business process for this pipeline
$businessProcess = $this->config->businessProcesses()->updateOrCreate([
'crm_provider_id' => $p['id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($p['label'], 0, 150),
'type' => BusinessProcess::TYPE_OPPORTUNITY,
'is_selectable' => $p['active'],
]);
// A record type is really a clone of the business process, used to store which record uses which pipeline.
// Create/update record type clone
$this->config->recordTypes()->updateOrCreate([
'crm_provider_id' => $p['id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($p['label'], 0, 150),
'is_selectable' => $p['active'],
'business_process_id' => $businessProcess->id ?? null,
]);
// Stages - fetch all existing stages upfront to avoid N+1 queries
$existingStages = $this->config->stages()
->withTrashed()
->where('type', Stage::TYPE_OPPORTUNITY)
->get()
->keyBy('crm_provider_id');
foreach ($p['stages'] as $dealStage) {
$s = ResponseNormalize::normalizeDealStage($dealStage);
/** @var ?Stage $existingStage */
$existingStage = $existingStages->get($s['id']);
// Restore soft-deleted stages that are now active in HubSpot
if ($existingStage?->trashed() && $s['active']) {
$existingStage->restore();
}
// Upsert stage (updates soft-deleted records without restoring them)
$stage = $this->config->stages()->withTrashed()->updateOrCreate([
'crm_provider_id' => $s['id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($s['label'], 0, 50),
'label' => mb_strimwidth($s['label'], 0, 191),
'type' => Stage::TYPE_OPPORTUNITY,
'sequence' => $s['displayOrder'],
'is_selectable' => $s['active'],
'probability' => $s['probability'] * 100,
]);
if ($missingStageName === $s['id']) {
$missingStage = $stage;
}
$stages[] = $stage->id;
}
$businessProcess->stages()->sync($stages);
}
return $missingStage;
}
/**
* @inheritdoc
*/
public function syncOrganization(): void
{
try {
$endpoint = '[URL_WITH_CREDENTIALS]
*/
public function find(string $name, array $scopes): array
{
$count = $this->limit ?? 20;
$offset = $this->offset ?? 0;
/** @var array<int, array<string, mixed>> */
return Cache::remember(
key: $this->team->getId() . $name . $count . $offset,
ttl: 300,
callback: function () use ($name, $offset, $count): array {
$data = [];
// Use the new V3 API to find contacts based on additional fields.
foreach (['companies', 'contacts'] as $objectType) {
$endpoint = '[URL_WITH_CREDENTIALS]
*/
public function findOpportunities(?string $crmAccountId, ?string $crmContactId, ?int $userId = null): array
{
$data = [];
$ownerData = [];
$ownerId = null;
if ($crmAccountId === null) {
return $data;
}
if ($userId) {
$profileRepository = app(ProfileRepository::class);
$profile = $profileRepository->findProfileByUserId($this->config, $userId);
$ownerId = $profile instanceof Profile ? $profile->getCrmProviderId() : null;
}
$closedStages = $this->getClosedDealStages();
$payload = $this->payloadBuilder->generateOpportunitiesSearchPayload(
$this->config,
$crmAccountId,
$closedStages,
);
$results = $this->client->getPaginatedData($payload, 'deals');
foreach ($results['results'] as $object) {
$properties = $object['properties'];
$amount = null;
if (empty($properties['amount']) === false) {
$currency = $properties['deal_currency_code'] ?? $this->config->default_currency;
// Values can contain commas and any junk so strip them.
$value = (float) preg_replace('/[^\d.]/', '', $properties['amount']);
$amount = formatCurrency($value, $currency);
}
$businessProcess = $this->config
->businessProcesses()
->where('crm_provider_id', $properties['pipeline'])
->first();
if ($businessProcess === null) {
// Import it.
$stage = $this->importStages([Stage::TYPE_OPPORTUNITY], $properties['dealstage']);
$businessProcess = $this->config
->businessProcesses()
->where('crm_provider_id', $properties['pipeline'])
->first();
} else {
$stage = $businessProcess
->stages()
->where('crm_provider_id', $properties['dealstage'])
->where('type', Stage::TYPE_OPPORTUNITY)
->first();
if ($stage === null) {
// Import it.
$stage = $this->importStages(null, $properties['dealstage']);
}
}
$recordType = null;
if ($businessProcess) {
$recordType = $businessProcess->recordTypes()->first();
}
$isWon = in_array($properties['dealstage'], $closedStages['won']);
$isLost = in_array($properties['dealstage'], $closedStages['lost']);
$record = [
'crmId' => $object['id'],
'name' => $properties['dealname'] ?? 'Unknown Deal',
'value' => $amount,
'won' => $isWon,
'closed' => $isWon || $isLost,
'stage' => [
'id' => $stage?->getUuid() ?? '',
'name' => $stage?->getName() ?? '',
],
];
if ($recordType) {
$record += [
'recordType' => [
'id' => $recordType->id_string,
'name' => $recordType->name,
],
];
}
if ($ownerId && isset($properties['hubspot_owner_id']) && $properties['hubspot_owner_id'] === $ownerId) {
$ownerData[] = $record;
}
$data[] = $record;
}
if (! empty($ownerData)) {
return $ownerData;
}
return $data;
}
/**
* @inheritdoc
*/
public function getTasks(?string $objectType, string $objectId, ?string $opportunityId): array
{
$data = [];
switch ($objectType) {
case 'contact':
$hsObject = 'contact';
break;
case 'account':
$hsObject = 'company';
break;
default:
// This is a hack to prioritise and override a contact/company with a deal.
if ($opportunityId) {
$hsObject = 'deal';
$objectId = $opportunityId;
} else {
throw new InvalidArgumentException('Object type not supported.');
}
}
$engagementTypes = ['meetings', 'tasks'];
foreach ($engagementTypes as $engagementType) {
$payload = $this->payloadBuilder->getLinkToTaskPayload($hsObject, $objectId, $engagementType);
$this->logger->info('[HubSpot] CRM Search requested', [
'request' => $payload,
]);
$engagements = $this->client->getPaginatedData($payload, $engagementType);
foreach ($engagements['results'] as $engagement) {
if ($engagementType == 'meetings') {
$title = $engagement['properties']['hs_meeting_title'] ?? 'Scheduled meeting';
} elseif ($engagementType == 'tasks') {
$title = $engagement['properties']['hs_task_subject'];
} else {
$title = 'Scheduled meeting';
}
$data[] = [
'crmId' => $engagement['id'],
'subject' => $title,
'due' => $engagement['properties']['hs_timestamp'],
'type' => $engagement['properties']['hs_activity_type'] ?? null,
];
}
}
usort($data, function ($item1, $item2) {
return $item2['due'] <=> $item1['due'];
});
return $data;
}
/**
* Try to find CRM Objects using email address
*
* @return null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
public function matchExactlyByEmail(string $email, ?int $userId = null): ?array
{
$contactProperties = [
'email',
'firstname',
'lastname',
'country',
'phone',
'mobilephone',
'jobtitle',
'hubspot_owner_id',
'associatedcompanyid',
'photo',
];
$contact = null;
$account = null;
try {
$hsContact = $this->getClient()->getContactByEmail($email, $contactProperties);
if ($hsContact) {
$contact = $this->importContact($hsContact);
$account = $contact->account;
}
$data = $this->convertCrmData($contact, $account, $userId);
return ! empty(array_filter($data)) ? $data : null;
} catch (BadRequest $e) {
$this->logger->warning('[HubSpot] Search failed', [
'team_id' => $this->team->getId(),
'search_identifier' => $email,
'reason' => $e->getMessage(),
]);
}
return null;
}
public function getDomain(string $email): ?string
{
return $this->getDomainFromEmail($email);
}
/**
* Try to find CRM objects using domain name of the email address
*
* @return null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
public function matchByDomain(string $domain, ?int $userId = null): ?array
{
$companyName = $domain;
// Try to find a company matching their email domain.
$companyProperties = [
'country',
'phone',
'name',
'hs_avatar_filemanager_key',
'industry',
'hubspot_owner_id',
'domain',
];
try {
$hsAccounts = $this->client
->getInstance()
->companies()
->searchByDomain($companyName, $companyProperties);
} catch (Throwable $e) {
$this->logger->info('[HubSpot] Search failed', [
'error' => $e->getMessage(),
'domain' => $domain,
]);
return null;
}
$account = null;
// If there are multiple accounts, don't guess, we'll ask later.
if (\count($hsAccounts->data->results) === 1) {
// Persist this remote object.
$account = $this->syncAccount($hsAccounts->data->results[0]->companyId);
}
$data = $this->convertCrmData(null, $account, $userId);
return ! empty(array_filter($data)) ? $data : null;
}
/**
* @return array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
protected function convertCrmData(?Contact $contact, ?Account $account, ?int $userId = null): array
{
$countryCode = null;
if ($contact && $contact->country_code) {
$countryCode = $contact->country_code;
} elseif ($account && $account->country_code) {
$countryCode = $account->country_code;
}
try {
$hsOpportunities = $this->findOpportunities(
$account ? $account->crm_provider_id : null,
$contact ? $contact->crm_provider_id : null,
$userId
);
} catch (Exception $e) {
$hsOpportunities = [];
}
// If there are multiple opportunities, don't guess, we'll ask later.
$opportunity = null;
$stage = null;
if (! empty($hsOpportunities)) {
// Persist this remote object.
$opportunity = $this->syncOpportunity($hsOpportunities[0]['crmId']);
$stage = $opportunity?->getStage();
}
return [
null,
$account,
$opportunity,
$contact,
$stage,
$countryCode,
];
}
protected function getCacheKey(string $object, ?int $userId = null): ?string
{
$key = $this->team->getId() . $object;
$keySuffix = $this->getOwnerKeySuffix($userId);
return $key . $keySuffix;
}
private function getOwnerKeySuffix(?int $userId = null): string
{
return $userId === null ? '' : (string) $userId;
}
/**
* @return null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
*}
*/
public function matchByPhone(string $phone, ?string $rawPhoneNumber = null, ?int $userId = null): ?array
{
if (str_contains($phone, '**')) {
return null;
}
// trim all whitespaces if present so the lookup doesn't fail
$phone = str_replace(' ', '', $phone);
// Check if the user is internal.
if ($this->isPhoneNumberOfTeamMember($phone)) {
return null;
}
$response = $this->searchForPhoneNumber($phone);
if (empty($response)) {
return null;
}
// This would ideally importContact instead but the response type differs.
$contact = $this->findAndSyncContact($response['results'][0]['id']);
if (! $contact instanceof Contact) {
return null;
}
$account = $contact->account;
$countryCode = $contact->country_code ?? $account->country_code ?? null;
try {
$hsOpportunities = $this->findOpportunities(
$account?->crm_provider_id,
$contact->crm_provider_id,
$userId
);
} catch (Exception $e) {
$hsOpportunities = [];
}
$opportunity = null;
$stage = null;
try {
if (! empty($hsOpportunities)) {
// Persist this remote object.
$opportunity = $this->syncOpportunity($hsOpportunities[0]['crmId']);
$stage = $opportunity?->getStage();
}
} catch (Exception $e) {
$this->logger->debug('[HubSpot] Opportunity failed to sync.', [
'reason' => $e->getMessage(),
]);
}
return [
null,
$account,
$opportunity,
$contact,
$stage,
$countryCode,
];
}
private function isPhoneNumberOfTeamMember(string $phone): bool
{
$teamRepository = app(TeamRepository::class);
$user = $teamRepository->findTeamMemberByPhone($this->team, $phone);
if ($user instanceof User) {
return true;
}
return false;
}
private function findAndSyncContact(string $crmId): ?Contact
{
try {
return $this->syncContact($crmId);
} catch (Exception $exception) {
$this->logger->info('[HubSpot] Phone match failed', [
'reason' => $exception->getMessage(),
]);
return null;
}
}
private function hasResults(array $response): bool
{
return isset($response['total']) && is_numeric($response['total']) && $response['total'] > 0;
}
private function searchForPhoneNumber(string $phone): array
{
// Normalizes the provided phone number for the API search.
$normalizedPhone = $this->normalizePhoneNumber($phone);
$payload = $this->payloadBuilder->generatePhoneSearchPayload($normalizedPhone);
$this->logger->info('[HubSpot] Phone match search triggered', [
'phone' => $phone,
'normalizedPhone' => $normalizedPhone,
'payload' => $payload,
]);
$response = $this->handlePhoneSearchRequest($normalizedPhone, $payload);
if (! $this->hasResults($response)) {
$nationalPhone = preg_replace('/\D/', '', phone_national(null, $phone));
$payload = $this->payloadBuilder->generatePhoneSearchPayload($nationalPhone);
$this->logger->info('[HubSpot] Phone match national number search triggered', [
'phone' => $phone,
'nationalPhone' => $nationalPhone,
'payload' => $payload,
]);
$response = $this->handlePhoneSearchRequest($phone, $payload);
}
if (! $this->hasResults($response)) {
$payload = $this->payloadBuilder->generatePhoneSearchPayload($normalizedPhone, true);
$this->logger->info('[HubSpot] Phone match alternative search triggered', [
'phone' => $phone,
'normalizedPhone' => $normalizedPhone,
'payload' => $payload,
]);
$response = $this->handlePhoneSearchRequest($phone, $payload);
}
return $this->hasResults($response) ? $response : [];
}
private function handlePhoneSearchRequest(string $phone, array $payload): array
{
$endpoint = '[URL_WITH_CREDENTIALS] null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
public function matchByName(string $name, ?int $userId = null): ?array
{
// Don't waste time searching for single character strings.
if (\strlen($name) <= 1) {
return null;
}
$cacheKey = $this->getCacheKey($name, $userId);
$result = Cache::remember($cacheKey, 60, function () use ($name, $userId) {
$payload = $this->payloadBuilder->generateSearchContactsByNamePayload(
$name,
$this->getContactFields()
);
$hsContacts = $this->client->getPaginatedData($payload, 'contact');
if (empty($hsContacts['results'])) {
return false;
}
$contact = $this->importContact($hsContacts['results'][0]);
if ($contact === null) {
return false;
}
$account = $contact->account;
$countryCode = $contact->country_code ?? $account->country_code ?? null;
try {
$hsOpportunities = $this->findOpportunities(
$account ? $account->crm_provider_id : null,
$contact->crm_provider_id,
$userId
);
} catch (Exception $e) {
$hsOpportunities = [];
}
$opportunity = null;
$stage = null;
if (! empty($hsOpportunities)) {
// Persist this remote object.
$opportunity = $this->syncOpportunity($hsOpportunities[0]['crmId']);
$stage = $opportunity?->getStage();
}
return [
null,
$account,
$opportunity,
$contact,
$stage,
$countryCode,
];
});
return is_array($result) ? $result : null;
}
private function convertActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->account->crm_provider_id] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->opportunity->crm_provider_id] : [],
'ownerIds' => [],
];
}
private function getParticipantsIds(Activity $activity): array
{
$attendees = [];
$participantRepository = app(ParticipantRepository::class);
$participants = $participantRepository->getParticipantsWhoEnteredMeeting($activity);
foreach ($participants as $participant) {
if ($participant->user_id || $participant->isCoach()) {
continue;
}
$contact = $participant->contact()->first();
if ($contact && $contact->crm_provider_id) {
$attendees[] = $contact->crm_provider_id;
} else {
if (! empty($participant->name)) {
$attendeeData = $this->fetchMissingAttendeeInfo($participant);
}
if (! empty($attendeeData['id'])) {
$attendees[] = $attendeeData['id'];
}
}
}
if ($activity->hasContact()) {
$attendees[] = $activity->contact->crm_provider_id;
}
return array_unique($attendees);
}
private function fetchMissingAttendeeInfo(Participant $participant): array
{
// Check if we need to look inside an account context.
$activity = $participant->getActivity();
$companyId = $activity->hasAccount() ? $activity->getAccount()->crm_provider_id : null;
// First check the local data.
/** @var Contact[] $contacts */
$contacts = $this->team->contacts()
->with('account')
->where('name', $participant->name)
->whereNotNull('email')
->get();
foreach ($contacts as $contact) {
// If we have a company in scope, check the contact is associated to it.
if (
$companyId !== null
&& ($contact->account_id === null || $companyId !== $contact->account->crm_provider_id)
) {
continue;
}
return [
'id' => $contact->crm_provider_id,
'email' => $contact->email,
];
}
$payload = $this->generateNameSearchPayload($participant->name, 0, 20);
try {
$response = $this->client->getNewInstance()->crm()->contacts()->searchApi()->doSearch($payload);
// TODO add some logic to choose the most suitable contact if multiple
foreach ($response['results'] as $object) {
$properties = $object['properties'];
if (empty($object['properties']) === false) {
// Check the company matches the contact.
// Todo: Move this check inside the API search.
if ($companyId !== null && $companyId !== $properties['associatedcompanyid']) {
continue;
}
return [
'id' => $object['id'],
'email' => $properties['email'],
];
}
}
} catch (Exception $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Search failed', [
'teamId' => $this->team->id_string,
'request' => $payload,
'reason' => $e->getMessage(),
]);
}
return [];
}
/**
* Store transcripts as note engagement.
*
* @throws Exception
*/
public function createTranscriptNotes(Activity $activity): void
{
// For HS no need to check if Crm profile - Log Notes field is enabled
// We only check if store_transcript toggle is enabled on crm profile.
$engagement = [
'active' => true,
'ownerId' => $this->profile->crm_provider_id,
'timestamp' => $activity->created_at->tz($activity->user->timezone)->getTimestamp() * 1000,
'type' => 'NOTE',
];
// Generate activity tr...
|
PhpStorm
|
faVsco.js – Hubspot/Service.php
|
NULL
|
87414
|
|
87413
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
ServiceTest
PostmanFileEditViewWindowActivity MonitorAll ProcessesProcess Namekernel_taskPhpStormreplaydscreenpipeWindowServerFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentFirefoxcef_server Helper (Renderer)coreaudiodActivity Monitormds_storeslaunchservicesdFirefoxCP Isolated Web Contentlanguage_server_macos_armbluetoothdFirefoxCP Isolated Web ContentWispr FlowiTerm2FirefoxCP Isolated Web ContentHelp% CPUCursorUlViewService (Not Responding)ClaudeFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentControl CentreSlack Helper (Renderer)FirefoxCP Isolated Web Contentcef_server Helper (GPU)172,5167,157,348,132,48,98,98,27,6CPU Time24:12:56,544:29:29,826:43:30,563:52:32,318:09:00,7441:36,4413:43,141:50:11,469:48,021:02:11,469:43,971:10:43,031:04:37,1544:02,7412:14,7521:17,2817:07,314:31,211:05:07,041:05,986:06,7029:50,7220:09,8832:35,6220:51,551:00:52,7925:35,718:29,32System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+47,93%38,60%13,47%CPUED→Jiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana Netseva€o Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko KashinskiGalya Dimitrova: Todor Stamatov. Steliyan Georgievto VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...#: AppsJira Cloud• 0.(all100% <78• Thu 28 May 18:35:52Describe what you are looking forlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
PhpStorm
|
faVsco.js – Hubspot/Service.php
|
NULL
|
87413
|
|
87412
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
rapstomEV favscojs ~ProjectvViewCooc#12121 on JY-20963-fx-ImTOOI-Windoweteamoremo tewins© ResponseNormalize.phpgsevice.on:esunchiorcdon.onGSUNCKOlOhCWWWKeweonooinlneochhoe2133› E IntegrationApp>O Listeners› E MetadataMmacuryochyict.on© CachedCrmServiceDecorator.php© ServiceTest.php© DeleteObjects Trait.phpu rottoniuorrid.pnpRecordSelector.php(C) Hubspot/Service.php X OpportunitySyncTrait.phg© Activity.php©CrmEntityRepository.php1038g0public function natchActivityEngagementType(Activity Sactivity): stringf...1 usageprivate function assignCrn0wner(User Suser, ActivityContract Sactivity): PProfile(...}› E Pipedrivev SalesforceaFelds2157a opoortunitvVatchenOpportunitySyncStrategy2159> ProspectsearchStrategyServiceTraits2161 @ >C) e entond©[EMAIL]© PayloadBuilder.php© Profile.php© QueryBullder.phpprevore sroee Tunceion gecuestsrape einescnopotncloe odrangreturn self::API_URL . self::ENDPOINT_PIPELINES . self::PIPELINE_OBJECT_TYPE_DEALS;public function venifyTaskExists(Activity Sactivity): bool...ServicasOutpujiminny.opportunities 4tii jiminny stagesGin PauuttvaaamsaBagase4 console 1 s 650 msEUSOrSS5% mev A|iminny@localhostHSllocallASFv pRODA consoleSTAGINGA consoleDockerDuvid (UUID with time-low and time-high swapped)( tean_id@crn_configuration_idHr account& stage_idstage_updated_at@record_type_idcrn_provider_idousenTo768142384a9cfad-2c87-4453-9e72-20aeb78ccf8d5SS475BB3aT8:8428612826-85-20 18:36:59455649485819984518121lonnen38848855naneCentiva Capital - EU HY/IGvalue28608.88currency_codeDis_closediis nooMelose dateprobability100Wew out ren naet today RayTO0У L78• Thu 28 May 18:35:52U ServiceTest ~+0.E custom.logA console (PROD)DMO00-1725E laravel.logA SF (iminny@localhost)HSJocal ([jminny@localhost)A console (EU] * (B users (EU]A console [STAGING)createo,at > 2020-09-2d8 jiminny~031 49 A29 X3 X109 A Vsallect *mm acutes onden hy sadese1727-L120,1729Т 000 0 10000 1000 000 00 Г 80DТ В17331733 vBEE21746MІIN11ІРНIsAllec * mn llsang nhene nane uke WsthnaSELECT * FROM opportunities WHERE uuid_to_Din('04a9cfad-2C87-4453-9e72-20aeb78ccf8d*)=select * from teams where id = 555;select * from stages nhere tean_id = 555;SELECTCONCAT(U.$d, GASE WHEN U.1d = t.omner_id THEN • (ouner)' ELSE "* END) AS user_1d=sa.*t.ouner_id FROM social_accounts saJOIN users on u.id = sa.sociable_idJOTN teams + 1..n<->1: on taid = u.tean ioWHERE v.team_id = 100 and sa-provider = 'hubspot":ПВТЕ ПІРеНCascadeles Orcnnworeebeeionhnves dohtine OooondNow look at ResponseNoren ize::norms Tipeoea Staoe)orobabuty" s Tloat (Coatal"cetadata""nrobabto tyteohThis ks the root causdRoot eause: moorStages overwmes D3 probability with tuoSpots valueThe fow is,"probabllty: "0.0"*default': falseJ it hasn't been changed recently. The changes forl"Code$ AdaptiveNwneuleime"hhek hiresensnd....
|
PhpStorm
|
faVsco.js – Hubspot/Service.php
|
NULL
|
87412
|
|
87411
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
ServiceTest
Run 'ServiceTest'
Debug 'ServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
7
149
1
33
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Services\Crm\Hubspot;
use Carbon\Carbon;
use Exception;
use Generator;
use GuzzleHttp\Exception\RequestException;
use HubSpot\Client\Crm\Owners\Model\PublicOwner;
use Illuminate\Support\Facades\Cache;
use InvalidArgumentException;
use Jiminny\Contracts\Repositories\TeamRepository;
use Jiminny\Contracts\Services\Crm\ClientInterface;
use Jiminny\Contracts\Services\Crm\FetchRelatedActivityInterface;
use Jiminny\Contracts\Services\Crm\LayoutManagementInterface;
use Jiminny\Contracts\Services\Crm\MatchCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\Provider\HubspotInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityLookupInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityManipulationInterface;
use Jiminny\Contracts\Services\Crm\SavePlaybackLinkToCrmInterface;
use Jiminny\Contracts\Services\Crm\SendSummaryToCrmInterface;
use Jiminny\Contracts\Services\Crm\SettingsInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmMetadataInterface;
use Jiminny\Contracts\Services\Crm\VerifyTaskExistsInterface;
use Jiminny\Exceptions\CrmException;
use Jiminny\Exceptions\HttpNotFoundException;
use Jiminny\Jobs\Crm\NoteObject;
use Jiminny\Models\Account;
use Jiminny\Models\Activity;
use Jiminny\Models\Contact;
use Jiminny\Models\Contracts\ActivityContract;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldData;
use Jiminny\Models\Crm\Layout;
use Jiminny\Models\Crm\Profile;
use Jiminny\Models\Lead;
use Jiminny\Models\Opportunity;
use Jiminny\Models\Participant;
use Jiminny\Models\Playbook;
use Jiminny\Models\SocialAccount;
use Jiminny\Models\Stage;
use Jiminny\Models\User;
use Jiminny\Repositories\Crm\CrmEntityRepository;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\Crm\ProfileRepository;
use Jiminny\Repositories\ParticipantRepository;
use Jiminny\Services\Avatar\ProspectPhotoPathService;
use Jiminny\Services\Crm\BaseService;
use Jiminny\Services\Crm\Hubspot\Actions\SyncArchivedProfilesAction;
use Jiminny\Services\Crm\Hubspot\Fields\ValueNormalizer;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\OpportunitySyncTrait;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\SyncCrmEntitiesTrait;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\SyncFieldsTrait;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\WriteCrmTrait;
use Jiminny\Services\Crm\MatchDomainByEmailInterface;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Services\Crm\ResolveCompanyNameByEmailTrait;
use Jiminny\Utils\PlaybackUrlBuilder;
use Sentry;
use SevenShores\Hubspot\Exceptions\BadRequest;
use Throwable;
use UnexpectedValueException;
/**
* @phpstan-type CrmFieldDefinition array{
* name: string,
* label: string,
* description: string,
* type: string,
* fieldType: string,
* hidden: bool,
* showCurrencySymbol: bool,
* options: array<array{
* id: string,
* label: string,
* value?: string,
* }
*/
class Service extends BaseService implements
HubspotInterface,
SyncCrmEntitiesInterface,
SyncCrmMetadataInterface,
SendSummaryToCrmInterface,
MatchDomainByEmailInterface,
SavePlaybackLinkToCrmInterface,
RemoteEntityManipulationInterface,
FetchRelatedActivityInterface,
LayoutManagementInterface,
SettingsInterface,
MatchCrmEntitiesInterface,
RemoteEntityLookupInterface,
VerifyTaskExistsInterface
{
use ResolveCompanyNameByEmailTrait;
use SyncCrmEntitiesTrait;
use WriteCrmTrait;
use SyncFieldsTrait;
use OpportunitySyncTrait;
private const int ENGAGEMENT_BODY_MAX_LENGTH = 65536;
private const string LOG_DATE_FORMAT = 'Y-m-d H:i:s';
private const int BATCH_UPDATE_LIMIT = 100;
private const string TEN_SECONDLY_ROLLING_POLICY = 'TEN_SECONDLY_ROLLING';
private const int TEN_SECONDLY_ROLLING_LIMIT = 10;
private const string CALLS_SEARCH_ENDPOINT = '[URL_WITH_CREDENTIALS] ClientInterface|Client
*/
protected $client;
protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
protected CrmEntityRepository $crmEntityRepository;
protected ProspectPhotoPathService $prospectPhotoPathService;
private SyncFieldAction $syncFieldAction;
private PayloadBuilder $payloadBuilder;
private SyncRelatedActivityManager $syncRelatedActivityManager;
private SyncArchivedProfilesAction $syncArchivedProfilesAction;
private WebhookSyncBatchProcessor $batchProcessor;
public function __construct(
Client $client,
SyncFieldAction $syncFieldAction,
PayloadBuilder $payloadBuilder,
ProspectPhotoPathService $prospectPhotoPathService,
SyncArchivedProfilesAction $syncArchivedProfilesAction,
WebhookSyncBatchProcessor $batchProcessor,
) {
parent::__construct();
$this->client = $client;
$this->syncFieldAction = $syncFieldAction;
$this->prospectPhotoPathService = $prospectPhotoPathService;
$this->payloadBuilder = $payloadBuilder;
$this->syncArchivedProfilesAction = $syncArchivedProfilesAction;
$this->batchProcessor = $batchProcessor;
$this->opportunitySyncStrategyResolver = app(OpportunitySyncStrategyResolver::class, [
'client' => $this->client,
]);
$this->syncRelatedActivityManager = app(SyncRelatedActivityManager::class, [
'client' => $this->client,
'payloadBuilder' => $this->payloadBuilder,
'logger' => $this->logger,
]);
$this->crmEntityRepository = app(CrmEntityRepository::class);
$this->dealFieldsService = app(DealFieldsService::class);
}
public function getDisplayName(): string
{
return 'HubSpot';
}
protected function getOAuthAccount(User $user): ?SocialAccount
{
// In this case, the Account Owner is always the connection for any API operations.
$owner = $user->team->owner;
return $owner->getSocialAccount(SocialAccount::PROVIDER_HUBSPOT);
}
public function getClient(): Client
{
/** @var Client */
return $this->client;
}
/**
* Convert raw field data into a format compatible with CRM APIs.
*
* @param bool $internal Direction of the conversion.
* True is pulling from CRM, false normalize before sending to CRM.
*/
public function normalizeValue(string $fieldType, string $fieldValue, bool $internal = false): string
{
return ValueNormalizer::normalize(
fieldType: $fieldType,
fieldValue: $fieldValue,
isInbound: $internal,
);
}
/**
* @inheritdoc
*/
public function getDefaultFields(string $activityType): array
{
$fields = [];
if ($activityType === Playbook::ACTIVITY_TYPE_TASK) {
$defaultFields = FieldDefinitions::defaultTaskFields();
// This lazy creates these fields if not already setup.
foreach ($defaultFields as $defaultField) {
$fields[] = $this->config->fields()->firstOrCreate($defaultField);
}
}
return $fields;
}
/**
* @inheritdoc
*/
public function getDefaultActivityField(string $activityType): Field
{
/** @var Field $activityField */
$activityField = $this->config->fields()->where([
'crm_provider_id' => 'activityType',
'object_type' => $activityType,
])->first();
return $activityField;
}
/**
* @inheritdoc
*/
public function getSupportedPlaybookTypes(): array
{
return [Playbook::ACTIVITY_TYPE_TASK];
}
/**
* @inheritdoc
*/
public function getDefaultActivityLayoutFields(string $activityType, string $layoutType): array
{
$fields = [];
if ($activityType === Playbook::ACTIVITY_TYPE_TASK) {
// Outcome should always be provided calls/meetings.
$fieldData = [
[
'crm_provider_id' => $layoutType === Layout::TYPE_SOFTPHONE_SUMMARY ? 'disposition' : 'meetingOutcome',
'object_type' => Field::OBJECT_TASK,
],
];
foreach ($fieldData as $data) {
$field = $this->config->fields()->where($data)->first();
// Only add the field if it is created, which it should be.
if ($field) {
$fields[] = $field;
}
}
}
return $fields;
}
public function getDealInsightsFields(): array
{
return FieldDefinitions::dealInsightsFields();
}
protected function getDefaultFollowupLayoutFields(string $activityType): array
{
$fields = [];
$fieldRepo = app(FieldRepository::class);
$fieldData = FieldDefinitions::followupFieldsFilter();
foreach ($fieldData as $data) {
$field = $fieldRepo->findOneConfigurationFieldByProperties($this->config, $data);
// Only add the field if it is created, which it should be.
if ($field) {
$fields[] = $field;
}
}
return $fields;
}
/**
* @inheritdoc
*/
public function syncField(Field $field): void
{
switch ($field->object_type) {
case Field::OBJECT_ACCOUNT:
$crmField = $this->client->getInstance()->companyProperties()->get($field->crm_provider_id);
break;
case Field::OBJECT_CONTACT:
$crmField = $this->client->getInstance()->contactProperties()->get($field->crm_provider_id);
break;
case Field::OBJECT_OPPORTUNITY:
$crmField = $this->client->getInstance()->dealProperties()->get($field->crm_provider_id);
break;
case Field::OBJECT_TASK:
$this->syncSingleTaskField($field);
return;
default:
return;
}
$this->syncFieldAction->execute($field, $crmField->toArray());
}
/**
* @param array<array{
* id:string,
* label:string,
* value?:string
* }> $options
*
* @throws CrmException
*
* @return FieldData[]
*
*/
public function importPicklistValues(
Field $field,
array $options = [['id' => '', 'label' => '', 'value' => '']],
): array {
if (! empty($options[0]['id']) || ! empty($options[0]['value'])) {
// We already have the options, no need to fetch them again
return $this->importOptions($field, $options);
}
$options = [];
switch ($field->getObjectType()) {
case Field::OBJECT_ACCOUNT:
$options = $this->getClient()->fetchPropertyOptions('company', $field->getCrmProviderId());
break;
case Field::OBJECT_CONTACT:
$options = $this->getClient()->fetchPropertyOptions('contact', $field->getCrmProviderId());
break;
case Field::OBJECT_OPPORTUNITY:
// Hubspot has different endpoint for stages
$options = $this->getClient()->fetchOpportunityFieldOptions($field);
break;
case Field::OBJECT_TASK:
if ($field->getCrmProviderId() === 'disposition') {
$options = $this->getClient()->fetchDispositionFieldOptions();
} elseif (in_array($field->getCrmProviderId(), ['meetingOutcome', 'activityType'])) {
$options = $this->getClient()->fetchMeetingOutcomeFieldOptions($field);
}
break;
default:
$this->logger->warning('Invalid object type', [
'object_type' => $field->getObjectType(),
'field_id' => $field->getId(),
]);
throw new CrmException('Invalid object type');
}
return $this->importOptions($field, $options);
}
/**
* @inheritdoc
*/
public function importStages(?array $types = null, ?string $missingStageName = null): ?Stage
{
$missingStage = null;
try {
// Use the HubSpot API client instead of the SDK crmPipelines() method
$endpoint = self::getDealsPipelinesEndpoint();
$pipelinesResponse = $this->client->getInstance()->getClient()->request('GET', $endpoint);
$pipelines = $pipelinesResponse->data->results;
} catch (RequestException|BadRequest $exception) {
throw $exception;
}
foreach ($pipelines as $pipeline) {
$stages = [];
// We create a business process to contain the pipeline, and store all stages against it.
$p = ResponseNormalize::normalizePipeline($pipeline);
// Create/update business process for this pipeline
$businessProcess = $this->config->businessProcesses()->updateOrCreate([
'crm_provider_id' => $p['id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($p['label'], 0, 150),
'type' => BusinessProcess::TYPE_OPPORTUNITY,
'is_selectable' => $p['active'],
]);
// A record type is really a clone of the business process, used to store which record uses which pipeline.
// Create/update record type clone
$this->config->recordTypes()->updateOrCreate([
'crm_provider_id' => $p['id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($p['label'], 0, 150),
'is_selectable' => $p['active'],
'business_process_id' => $businessProcess->id ?? null,
]);
// Stages - fetch all existing stages upfront to avoid N+1 queries
$existingStages = $this->config->stages()
->withTrashed()
->where('type', Stage::TYPE_OPPORTUNITY)
->get()
->keyBy('crm_provider_id');
foreach ($p['stages'] as $dealStage) {
$s = ResponseNormalize::normalizeDealStage($dealStage);
/** @var ?Stage $existingStage */
$existingStage = $existingStages->get($s['id']);
// Restore soft-deleted stages that are now active in HubSpot
if ($existingStage?->trashed() && $s['active']) {
$existingStage->restore();
}
// Upsert stage (updates soft-deleted records without restoring them)
$stage = $this->config->stages()->withTrashed()->updateOrCreate([
'crm_provider_id' => $s['id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($s['label'], 0, 50),
'label' => mb_strimwidth($s['label'], 0, 191),
'type' => Stage::TYPE_OPPORTUNITY,
'sequence' => $s['displayOrder'],
'is_selectable' => $s['active'],
'probability' => $s['probability'] * 100,
]);
if ($missingStageName === $s['id']) {
$missingStage = $stage;
}
$stages[] = $stage->id;
}
$businessProcess->stages()->sync($stages);
}
return $missingStage;
}
/**
* @inheritdoc
*/
public function syncOrganization(): void
{
try {
$endpoint = '[URL_WITH_CREDENTIALS]
*/
public function find(string $name, array $scopes): array
{
$count = $this->limit ?? 20;
$offset = $this->offset ?? 0;
/** @var array<int, array<string, mixed>> */
return Cache::remember(
key: $this->team->getId() . $name . $count . $offset,
ttl: 300,
callback: function () use ($name, $offset, $count): array {
$data = [];
// Use the new V3 API to find contacts based on additional fields.
foreach (['companies', 'contacts'] as $objectType) {
$endpoint = '[URL_WITH_CREDENTIALS]
*/
public function findOpportunities(?string $crmAccountId, ?string $crmContactId, ?int $userId = null): array
{
$data = [];
$ownerData = [];
$ownerId = null;
if ($crmAccountId === null) {
return $data;
}
if ($userId) {
$profileRepository = app(ProfileRepository::class);
$profile = $profileRepository->findProfileByUserId($this->config, $userId);
$ownerId = $profile instanceof Profile ? $profile->getCrmProviderId() : null;
}
$closedStages = $this->getClosedDealStages();
$payload = $this->payloadBuilder->generateOpportunitiesSearchPayload(
$this->config,
$crmAccountId,
$closedStages,
);
$results = $this->client->getPaginatedData($payload, 'deals');
foreach ($results['results'] as $object) {
$properties = $object['properties'];
$amount = null;
if (empty($properties['amount']) === false) {
$currency = $properties['deal_currency_code'] ?? $this->config->default_currency;
// Values can contain commas and any junk so strip them.
$value = (float) preg_replace('/[^\d.]/', '', $properties['amount']);
$amount = formatCurrency($value, $currency);
}
$businessProcess = $this->config
->businessProcesses()
->where('crm_provider_id', $properties['pipeline'])
->first();
if ($businessProcess === null) {
// Import it.
$stage = $this->importStages([Stage::TYPE_OPPORTUNITY], $properties['dealstage']);
$businessProcess = $this->config
->businessProcesses()
->where('crm_provider_id', $properties['pipeline'])
->first();
} else {
$stage = $businessProcess
->stages()
->where('crm_provider_id', $properties['dealstage'])
->where('type', Stage::TYPE_OPPORTUNITY)
->first();
if ($stage === null) {
// Import it.
$stage = $this->importStages(null, $properties['dealstage']);
}
}
$recordType = null;
if ($businessProcess) {
$recordType = $businessProcess->recordTypes()->first();
}
$isWon = in_array($properties['dealstage'], $closedStages['won']);
$isLost = in_array($properties['dealstage'], $closedStages['lost']);
$record = [
'crmId' => $object['id'],
'name' => $properties['dealname'] ?? 'Unknown Deal',
'value' => $amount,
'won' => $isWon,
'closed' => $isWon || $isLost,
'stage' => [
'id' => $stage?->getUuid() ?? '',
'name' => $stage?->getName() ?? '',
],
];
if ($recordType) {
$record += [
'recordType' => [
'id' => $recordType->id_string,
'name' => $recordType->name,
],
];
}
if ($ownerId && isset($properties['hubspot_owner_id']) && $properties['hubspot_owner_id'] === $ownerId) {
$ownerData[] = $record;
}
$data[] = $record;
}
if (! empty($ownerData)) {
return $ownerData;
}
return $data;
}
/**
* @inheritdoc
*/
public function getTasks(?string $objectType, string $objectId, ?string $opportunityId): array
{
$data = [];
switch ($objectType) {
case 'contact':
$hsObject = 'contact';
break;
case 'account':
$hsObject = 'company';
break;
default:
// This is a hack to prioritise and override a contact/company with a deal.
if ($opportunityId) {
$hsObject = 'deal';
$objectId = $opportunityId;
} else {
throw new InvalidArgumentException('Object type not supported.');
}
}
$engagementTypes = ['meetings', 'tasks'];
foreach ($engagementTypes as $engagementType) {
$payload = $this->payloadBuilder->getLinkToTaskPayload($hsObject, $objectId, $engagementType);
$this->logger->info('[HubSpot] CRM Search requested', [
'request' => $payload,
]);
$engagements = $this->client->getPaginatedData($payload, $engagementType);
foreach ($engagements['results'] as $engagement) {
if ($engagementType == 'meetings') {
$title = $engagement['properties']['hs_meeting_title'] ?? 'Scheduled meeting';
} elseif ($engagementType == 'tasks') {
$title = $engagement['properties']['hs_task_subject'];
} else {
$title = 'Scheduled meeting';
}
$data[] = [
'crmId' => $engagement['id'],
'subject' => $title,
'due' => $engagement['properties']['hs_timestamp'],
'type' => $engagement['properties']['hs_activity_type'] ?? null,
];
}
}
usort($data, function ($item1, $item2) {
return $item2['due'] <=> $item1['due'];
});
return $data;
}
/**
* Try to find CRM Objects using email address
*
* @return null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
public function matchExactlyByEmail(string $email, ?int $userId = null): ?array
{
$contactProperties = [
'email',
'firstname',
'lastname',
'country',
'phone',
'mobilephone',
'jobtitle',
'hubspot_owner_id',
'associatedcompanyid',
'photo',
];
$contact = null;
$account = null;
try {
$hsContact = $this->getClient()->getContactByEmail($email, $contactProperties);
if ($hsContact) {
$contact = $this->importContact($hsContact);
$account = $contact->account;
}
$data = $this->convertCrmData($contact, $account, $userId);
return ! empty(array_filter($data)) ? $data : null;
} catch (BadRequest $e) {
$this->logger->warning('[HubSpot] Search failed', [
'team_id' => $this->team->getId(),
'search_identifier' => $email,
'reason' => $e->getMessage(),
]);
}
return null;
}
public function getDomain(string $email): ?string
{
return $this->getDomainFromEmail($email);
}
/**
* Try to find CRM objects using domain name of the email address
*
* @return null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
public function matchByDomain(string $domain, ?int $userId = null): ?array
{
$companyName = $domain;
// Try to find a company matching their email domain.
$companyProperties = [
'country',
'phone',
'name',
'hs_avatar_filemanager_key',
'industry',
'hubspot_owner_id',
'domain',
];
try {
$hsAccounts = $this->client
->getInstance()
->companies()
->searchByDomain($companyName, $companyProperties);
} catch (Throwable $e) {
$this->logger->info('[HubSpot] Search failed', [
'error' => $e->getMessage(),
'domain' => $domain,
]);
return null;
}
$account = null;
// If there are multiple accounts, don't guess, we'll ask later.
if (\count($hsAccounts->data->results) === 1) {
// Persist this remote object.
$account = $this->syncAccount($hsAccounts->data->results[0]->companyId);
}
$data = $this->convertCrmData(null, $account, $userId);
return ! empty(array_filter($data)) ? $data : null;
}
/**
* @return array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
protected function convertCrmData(?Contact $contact, ?Account $account, ?int $userId = null): array
{
$countryCode = null;
if ($contact && $contact->country_code) {
$countryCode = $contact->country_code;
} elseif ($account && $account->country_code) {
$countryCode = $account->country_code;
}
try {
$hsOpportunities = $this->findOpportunities(
$account ? $account->crm_provider_id : null,
$contact ? $contact->crm_provider_id : null,
$userId
);
} catch (Exception $e) {
$hsOpportunities = [];
}
// If there are multiple opportunities, don't guess, we'll ask later.
$opportunity = null;
$stage = null;
if (! empty($hsOpportunities)) {
// Persist this remote object.
$opportunity = $this->syncOpportunity($hsOpportunities[0]['crmId']);
$stage = $opportunity?->getStage();
}
return [
null,
$account,
$opportunity,
$contact,
$stage,
$countryCode,
];
}
protected function getCacheKey(string $object, ?int $userId = null): ?string
{
$key = $this->team->getId() . $object;
$keySuffix = $this->getOwnerKeySuffix($userId);
return $key . $keySuffix;
}
private function getOwnerKeySuffix(?int $userId = null): string
{
return $userId === null ? '' : (string) $userId;
}
/**
* @return null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
*}
*/
public function matchByPhone(string $phone, ?string $rawPhoneNumber = null, ?int $userId = null): ?array
{
if (str_contains($phone, '**')) {
return null;
}
// trim all whitespaces if present so the lookup doesn't fail
$phone = str_replace(' ', '', $phone);
// Check if the user is internal.
if ($this->isPhoneNumberOfTeamMember($phone)) {
return null;
}
$response = $this->searchForPhoneNumber($phone);
if (empty($response)) {
return null;
}
// This would ideally importContact instead but the response type differs.
$contact = $this->findAndSyncContact($response['results'][0]['id']);
if (! $contact instanceof Contact) {
return null;
}
$account = $contact->account;
$countryCode = $contact->country_code ?? $account->country_code ?? null;
try {
$hsOpportunities = $this->findOpportunities(
$account?->crm_provider_id,
$contact->crm_provider_id,
$userId
);
} catch (Exception $e) {
$hsOpportunities = [];
}
$opportunity = null;
$stage = null;
try {
if (! empty($hsOpportunities)) {
// Persist this remote object.
$opportunity = $this->syncOpportunity($hsOpportunities[0]['crmId']);
$stage = $opportunity?->getStage();
}
} catch (Exception $e) {
$this->logger->debug('[HubSpot] Opportunity failed to sync.', [
'reason' => $e->getMessage(),
]);
}
return [
null,
$account,
$opportunity,
$contact,
$stage,
$countryCode,
];
}
private function isPhoneNumberOfTeamMember(string $phone): bool
{
$teamRepository = app(TeamRepository::class);
$user = $teamRepository->findTeamMemberByPhone($this->team, $phone);
if ($user instanceof User) {
return true;
}
return false;
}
private function findAndSyncContact(string $crmId): ?Contact
{
try {
return $this->syncContact($crmId);
} catch (Exception $exception) {
$this->logger->info('[HubSpot] Phone match failed', [
'reason' => $exception->getMessage(),
]);
return null;
}
}
private function hasResults(array $response): bool
{
return isset($response['total']) && is_numeric($response['total']) && $response['total'] > 0;
}
private function searchForPhoneNumber(string $phone): array
{
// Normalizes the provided phone number for the API search.
$normalizedPhone = $this->normalizePhoneNumber($phone);
$payload = $this->payloadBuilder->generatePhoneSearchPayload($normalizedPhone);
$this->logger->info('[HubSpot] Phone match search triggered', [
'phone' => $phone,
'normalizedPhone' => $normalizedPhone,
'payload' => $payload,
]);
$response = $this->handlePhoneSearchRequest($normalizedPhone, $payload);
if (! $this->hasResults($response)) {
$nationalPhone = preg_replace('/\D/', '', phone_national(null, $phone));
$payload = $this->payloadBuilder->generatePhoneSearchPayload($nationalPhone);
$this->logger->info('[HubSpot] Phone match national number search triggered', [
'phone' => $phone,
'nationalPhone' => $nationalPhone,
'payload' => $payload,
]);
$response = $this->handlePhoneSearchRequest($phone, $payload);
}
if (! $this->hasResults($response)) {
$payload = $this->payloadBuilder->generatePhoneSearchPayload($normalizedPhone, true);
$this->logger->info('[HubSpot] Phone match alternative search triggered', [
'phone' => $phone,
'normalizedPhone' => $normalizedPhone,
'payload' => $payload,
]);
$response = $this->handlePhoneSearchRequest($phone, $payload);
}
return $this->hasResults($response) ? $response : [];
}
private function handlePhoneSearchRequest(string $phone, array $payload): array
{
$endpoint = '[URL_WITH_CREDENTIALS] null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
public function matchByName(string $name, ?int $userId = null): ?array
{
// Don't waste time searching for single character strings.
if (\strlen($name) <= 1) {
return null;
}
$cacheKey = $this->getCacheKey($name, $userId);
$result = Cache::remember($cacheKey, 60, function () use ($name, $userId) {
$payload = $this->payloadBuilder->generateSearchContactsByNamePayload(
$name,
$this->getContactFields()
);
$hsContacts = $this->client->getPaginatedData($payload, 'contact');
if (empty($hsContacts['results'])) {
return false;
}
$contact = $this->importContact($hsContacts['results'][0]);
if ($contact === null) {
return false;
}
$account = $contact->account;
$countryCode = $contact->country_code ?? $account->country_code ?? null;
try {
$hsOpportunities = $this->findOpportunities(
$account ? $account->crm_provider_id : null,
$contact->crm_provider_id,
$userId
);
} catch (Exception $e) {
$hsOpportunities = [];
}
$opportunity = null;
$stage = null;
if (! empty($hsOpportunities)) {
// Persist this remote object.
$opportunity = $this->syncOpportunity($hsOpportunities[0]['crmId']);
$stage = $opportunity?->getStage();
}
return [
null,
$account,
$opportunity,
$contact,
$stage,
$countryCode,
];
});
return is_array($result) ? $result : null;
}
private function convertActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->account->crm_provider_id] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->opportunity->crm_provider_id] : [],
'ownerIds' => [],
];
}
private function getParticipantsIds(Activity $activity): array
{
$attendees = [];
$participantRepository = app(ParticipantRepository::class);
$participants = $participantRepository->getParticipantsWhoEnteredMeeting($activity);
foreach ($participants as $participant) {
if ($participant->user_id || $participant->isCoach()) {
continue;
}
$contact = $participant->contact()->first();
if ($contact && $contact->crm_provider_id) {
$attendees[] = $contact->crm_provider_id;
} else {
if (! empty($participant->name)) {
$attendeeData = $this->fetchMissingAttendeeInfo($participant);
}
if (! empty($attendeeData['id'])) {
$attendees[] = $attendeeData['id'];
}
}
}
if ($activity->hasContact()) {
$attendees[] = $activity->contact->crm_provider_id;
}
return array_unique($attendees);
}
private function fetchMissingAttendeeInfo(Participant $participant): array
{
// Check if we need to look inside an account context.
$activity = $participant->getActivity();
$companyId = $activity->hasAccount() ? $activity->getAccount()->crm_provider_id : null;
// First check the local data.
/** @var Contact[] $contacts */
$contacts = $this->team->contacts()
->with('account')
->where('name', $participant->name)
->whereNotNull('email')
->get();
foreach ($contacts as $contact) {
// If we have a company in scope, check the contact is associated to it.
if (
$companyId !== null
&& ($contact->account_id === null || $companyId !== $contact->account->crm_provider_id)
) {
continue;
}
return [
'id' => $contact->crm_provider_id,
'email' => $contact->email,
];
}
$payload = $this->generateNameSearchPayload($participant->name, 0, 20);
try {
$response = $this->client->getNewInstance()->crm()->contacts()->searchApi()->doSearch($payload);
// TODO add some logic to choose the most suitable contact if multiple
foreach ($response['results'] as $object) {
$properties = $object['properties'];
if (empty($object['properties']) === false) {
// Check the company matches the contact.
// Todo: Move this check inside the API search.
if ($companyId !== null && $companyId !== $properties['associatedcompanyid']) {
continue;
}
return [
'id' => $object['id'],
'email' => $properties['email'],
];
}
}
} catch (Exception $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Search failed', [
'teamId' => $this->team->id_string,
'request' => $payload,
'reason' => $e->getMessage(),
]);
}
return [];
}
/**
* Store transcripts as note engagement.
*
* @throws Exception
*/
public function createTranscriptNotes(Activity $activity): void
{
// For HS no need to check if Crm profile - Log Notes field is enabled
// We only check if store_transcript toggle is enabled on crm profile.
$engagement = [
'active' => true,
'ownerId' => $this->profile->crm_provider_id,
'timestamp' => $activity->created_at->tz($activity->user->timezone)->getTimestamp() * 1000,
'type' => 'NOTE',
];
// Generate activity tr...
|
PhpStorm
|
faVsco.js – Hubspot/Service.php
|
NULL
|
87411
|
|
87410
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
ServiceTest
Run 'ServiceTest'
Debug 'ServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
7
149
JAlPostmanFileEditViewWindowHelpActivity MonitorAll ProcessesProcess Name% CPUkernel_taskPhpStormWindowServerreplaydscreenpipeFirefoxCP Isolated Web ContentPostman Helper (Renderer)FirefoxCP Isolated Web Contentmds_storescoreaudiodCursorUlViewService (Not Responding)launchservicesdlaunchdClaudeActivity MonitorbluetoothdFirefoxcef_server Helper (Renderer)language_server_macos_armFirefoxCP Isolated Web ContentPostman Helper (GPU)FirefoxCP Isolated Web Contentcef_server Helper (GPU)PostmaniTerm2Wispr FlowFirefoxCP Isolated Web ContentFirefoxCP Isolated Web Content160,2139,055,839,631,310,59,08,67,26,15,94,94,34,13,93,83,83,53,42,82,62,52,52,42,42,32,32,2CPU Time24:12:47,414:29:20,988:08:59,026:43:27,533:52:29,772:41,517:47,8441:35,971:10:42,771:02:11,146:06,571:04:36,9219:40,1529:50,609:43,7121:17,101:50:11,039:47,6112:14,571:05,8444,8617:07,158:29,223:57,671:05:06,904:31,0632:35,5244:02,55System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+41,57%43,04%15,40%CPUED→Jiminny...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana Netseva€o Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko KashinskiGalya Dimitrova: Todor StamatovRo Steliyan GeorgievEo VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...::: AppsJira Cloud• 0.(all100% <78• Thu 28 May 18:35:47Describe what you are looking forlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
PhpStorm
|
faVsco.js – Hubspot/Service.php
|
NULL
|
87410
|
|
87409
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
ServiceTest
Run 'ServiceTest'
Debug 'ServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
Code changed:
Hide
Sync Changes
Hide This Notification
7
149
1
33
1
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Services\Crm\Hubspot;
use Carbon\Carbon;
use Exception;
use Generator;
use GuzzleHttp\Exception\RequestException;
use HubSpot\Client\Crm\Owners\Model\PublicOwner;
use Illuminate\Support\Facades\Cache;
use InvalidArgumentException;
use Jiminny\Contracts\Repositories\TeamRepository;
use Jiminny\Contracts\Services\Crm\ClientInterface;
use Jiminny\Contracts\Services\Crm\FetchRelatedActivityInterface;
use Jiminny\Contracts\Services\Crm\LayoutManagementInterface;
use Jiminny\Contracts\Services\Crm\MatchCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\Provider\HubspotInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityLookupInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityManipulationInterface;
use Jiminny\Contracts\Services\Crm\SavePlaybackLinkToCrmInterface;
use Jiminny\Contracts\Services\Crm\SendSummaryToCrmInterface;
use Jiminny\Contracts\Services\Crm\SettingsInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmMetadataInterface;
use Jiminny\Contracts\Services\Crm\VerifyTaskExistsInterface;
use Jiminny\Exceptions\CrmException;
use Jiminny\Exceptions\HttpNotFoundException;
use Jiminny\Jobs\Crm\NoteObject;
use Jiminny\Models\Account;
use Jiminny\Models\Activity;
use Jiminny\Models\Contact;
use Jiminny\Models\Contracts\ActivityContract;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\FieldData;
use Jiminny\Models\Crm\Layout;
use Jiminny\Models\Crm\Profile;
use Jiminny\Models\Lead;
use Jiminny\Models\Opportunity;
use Jiminny\Models\Participant;
use Jiminny\Models\Playbook;
use Jiminny\Models\SocialAccount;
use Jiminny\Models\Stage;
use Jiminny\Models\User;
use Jiminny\Repositories\Crm\CrmEntityRepository;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\Crm\ProfileRepository;
use Jiminny\Repositories\ParticipantRepository;
use Jiminny\Services\Avatar\ProspectPhotoPathService;
use Jiminny\Services\Crm\BaseService;
use Jiminny\Services\Crm\Hubspot\Actions\SyncArchivedProfilesAction;
use Jiminny\Services\Crm\Hubspot\Fields\ValueNormalizer;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\OpportunitySyncTrait;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\SyncCrmEntitiesTrait;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\SyncFieldsTrait;
use Jiminny\Services\Crm\Hubspot\ServiceTraits\WriteCrmTrait;
use Jiminny\Services\Crm\MatchDomainByEmailInterface;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Services\Crm\ResolveCompanyNameByEmailTrait;
use Jiminny\Utils\PlaybackUrlBuilder;
use Sentry;
use SevenShores\Hubspot\Exceptions\BadRequest;
use Throwable;
use UnexpectedValueException;
/**
* @phpstan-type CrmFieldDefinition array{
* name: string,
* label: string,
* description: string,
* type: string,
* fieldType: string,
* hidden: bool,
* showCurrencySymbol: bool,
* options: array<array{
* id: string,
* label: string,
* value?: string,
* }
*/
class Service extends BaseService implements
HubspotInterface,
SyncCrmEntitiesInterface,
SyncCrmMetadataInterface,
SendSummaryToCrmInterface,
MatchDomainByEmailInterface,
SavePlaybackLinkToCrmInterface,
RemoteEntityManipulationInterface,
FetchRelatedActivityInterface,
LayoutManagementInterface,
SettingsInterface,
MatchCrmEntitiesInterface,
RemoteEntityLookupInterface,
VerifyTaskExistsInterface
{
use ResolveCompanyNameByEmailTrait;
use SyncCrmEntitiesTrait;
use WriteCrmTrait;
use SyncFieldsTrait;
use OpportunitySyncTrait;
private const int ENGAGEMENT_BODY_MAX_LENGTH = 65536;
private const string LOG_DATE_FORMAT = 'Y-m-d H:i:s';
private const int BATCH_UPDATE_LIMIT = 100;
private const string TEN_SECONDLY_ROLLING_POLICY = 'TEN_SECONDLY_ROLLING';
private const int TEN_SECONDLY_ROLLING_LIMIT = 10;
private const string CALLS_SEARCH_ENDPOINT = '[URL_WITH_CREDENTIALS] ClientInterface|Client
*/
protected $client;
protected OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
protected CrmEntityRepository $crmEntityRepository;
protected ProspectPhotoPathService $prospectPhotoPathService;
private SyncFieldAction $syncFieldAction;
private PayloadBuilder $payloadBuilder;
private SyncRelatedActivityManager $syncRelatedActivityManager;
private SyncArchivedProfilesAction $syncArchivedProfilesAction;
private WebhookSyncBatchProcessor $batchProcessor;
public function __construct(
Client $client,
SyncFieldAction $syncFieldAction,
PayloadBuilder $payloadBuilder,
ProspectPhotoPathService $prospectPhotoPathService,
SyncArchivedProfilesAction $syncArchivedProfilesAction,
WebhookSyncBatchProcessor $batchProcessor,
) {
parent::__construct();
$this->client = $client;
$this->syncFieldAction = $syncFieldAction;
$this->prospectPhotoPathService = $prospectPhotoPathService;
$this->payloadBuilder = $payloadBuilder;
$this->syncArchivedProfilesAction = $syncArchivedProfilesAction;
$this->batchProcessor = $batchProcessor;
$this->opportunitySyncStrategyResolver = app(OpportunitySyncStrategyResolver::class, [
'client' => $this->client,
]);
$this->syncRelatedActivityManager = app(SyncRelatedActivityManager::class, [
'client' => $this->client,
'payloadBuilder' => $this->payloadBuilder,
'logger' => $this->logger,
]);
$this->crmEntityRepository = app(CrmEntityRepository::class);
$this->dealFieldsService = app(DealFieldsService::class);
}
public function getDisplayName(): string
{
return 'HubSpot';
}
protected function getOAuthAccount(User $user): ?SocialAccount
{
// In this case, the Account Owner is always the connection for any API operations.
$owner = $user->team->owner;
return $owner->getSocialAccount(SocialAccount::PROVIDER_HUBSPOT);
}
public function getClient(): Client
{
/** @var Client */
return $this->client;
}
/**
* Convert raw field data into a format compatible with CRM APIs.
*
* @param bool $internal Direction of the conversion.
* True is pulling from CRM, false normalize before sending to CRM.
*/
public function normalizeValue(string $fieldType, string $fieldValue, bool $internal = false): string
{
return ValueNormalizer::normalize(
fieldType: $fieldType,
fieldValue: $fieldValue,
isInbound: $internal,
);
}
/**
* @inheritdoc
*/
public function getDefaultFields(string $activityType): array
{
$fields = [];
if ($activityType === Playbook::ACTIVITY_TYPE_TASK) {
$defaultFields = FieldDefinitions::defaultTaskFields();
// This lazy creates these fields if not already setup.
foreach ($defaultFields as $defaultField) {
$fields[] = $this->config->fields()->firstOrCreate($defaultField);
}
}
return $fields;
}
/**
* @inheritdoc
*/
public function getDefaultActivityField(string $activityType): Field
{
/** @var Field $activityField */
$activityField = $this->config->fields()->where([
'crm_provider_id' => 'activityType',
'object_type' => $activityType,
])->first();
return $activityField;
}
/**
* @inheritdoc
*/
public function getSupportedPlaybookTypes(): array
{
return [Playbook::ACTIVITY_TYPE_TASK];
}
/**
* @inheritdoc
*/
public function getDefaultActivityLayoutFields(string $activityType, string $layoutType): array
{
$fields = [];
if ($activityType === Playbook::ACTIVITY_TYPE_TASK) {
// Outcome should always be provided calls/meetings.
$fieldData = [
[
'crm_provider_id' => $layoutType === Layout::TYPE_SOFTPHONE_SUMMARY ? 'disposition' : 'meetingOutcome',
'object_type' => Field::OBJECT_TASK,
],
];
foreach ($fieldData as $data) {
$field = $this->config->fields()->where($data)->first();
// Only add the field if it is created, which it should be.
if ($field) {
$fields[] = $field;
}
}
}
return $fields;
}
public function getDealInsightsFields(): array
{
return FieldDefinitions::dealInsightsFields();
}
protected function getDefaultFollowupLayoutFields(string $activityType): array
{
$fields = [];
$fieldRepo = app(FieldRepository::class);
$fieldData = FieldDefinitions::followupFieldsFilter();
foreach ($fieldData as $data) {
$field = $fieldRepo->findOneConfigurationFieldByProperties($this->config, $data);
// Only add the field if it is created, which it should be.
if ($field) {
$fields[] = $field;
}
}
return $fields;
}
/**
* @inheritdoc
*/
public function syncField(Field $field): void
{
switch ($field->object_type) {
case Field::OBJECT_ACCOUNT:
$crmField = $this->client->getInstance()->companyProperties()->get($field->crm_provider_id);
break;
case Field::OBJECT_CONTACT:
$crmField = $this->client->getInstance()->contactProperties()->get($field->crm_provider_id);
break;
case Field::OBJECT_OPPORTUNITY:
$crmField = $this->client->getInstance()->dealProperties()->get($field->crm_provider_id);
break;
case Field::OBJECT_TASK:
$this->syncSingleTaskField($field);
return;
default:
return;
}
$this->syncFieldAction->execute($field, $crmField->toArray());
}
/**
* @param array<array{
* id:string,
* label:string,
* value?:string
* }> $options
*
* @throws CrmException
*
* @return FieldData[]
*
*/
public function importPicklistValues(
Field $field,
array $options = [['id' => '', 'label' => '', 'value' => '']],
): array {
if (! empty($options[0]['id']) || ! empty($options[0]['value'])) {
// We already have the options, no need to fetch them again
return $this->importOptions($field, $options);
}
$options = [];
switch ($field->getObjectType()) {
case Field::OBJECT_ACCOUNT:
$options = $this->getClient()->fetchPropertyOptions('company', $field->getCrmProviderId());
break;
case Field::OBJECT_CONTACT:
$options = $this->getClient()->fetchPropertyOptions('contact', $field->getCrmProviderId());
break;
case Field::OBJECT_OPPORTUNITY:
// Hubspot has different endpoint for stages
$options = $this->getClient()->fetchOpportunityFieldOptions($field);
break;
case Field::OBJECT_TASK:
if ($field->getCrmProviderId() === 'disposition') {
$options = $this->getClient()->fetchDispositionFieldOptions();
} elseif (in_array($field->getCrmProviderId(), ['meetingOutcome', 'activityType'])) {
$options = $this->getClient()->fetchMeetingOutcomeFieldOptions($field);
}
break;
default:
$this->logger->warning('Invalid object type', [
'object_type' => $field->getObjectType(),
'field_id' => $field->getId(),
]);
throw new CrmException('Invalid object type');
}
return $this->importOptions($field, $options);
}
/**
* @inheritdoc
*/
public function importStages(?array $types = null, ?string $missingStageName = null): ?Stage
{
$missingStage = null;
try {
// Use the HubSpot API client instead of the SDK crmPipelines() method
$endpoint = self::getDealsPipelinesEndpoint();
$pipelinesResponse = $this->client->getInstance()->getClient()->request('GET', $endpoint);
$pipelines = $pipelinesResponse->data->results;
} catch (RequestException|BadRequest $exception) {
throw $exception;
}
foreach ($pipelines as $pipeline) {
$stages = [];
// We create a business process to contain the pipeline, and store all stages against it.
$p = ResponseNormalize::normalizePipeline($pipeline);
// Create/update business process for this pipeline
$businessProcess = $this->config->businessProcesses()->updateOrCreate([
'crm_provider_id' => $p['id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($p['label'], 0, 150),
'type' => BusinessProcess::TYPE_OPPORTUNITY,
'is_selectable' => $p['active'],
]);
// A record type is really a clone of the business process, used to store which record uses which pipeline.
// Create/update record type clone
$this->config->recordTypes()->updateOrCreate([
'crm_provider_id' => $p['id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($p['label'], 0, 150),
'is_selectable' => $p['active'],
'business_process_id' => $businessProcess->id ?? null,
]);
// Stages - fetch all existing stages upfront to avoid N+1 queries
$existingStages = $this->config->stages()
->withTrashed()
->where('type', Stage::TYPE_OPPORTUNITY)
->get()
->keyBy('crm_provider_id');
foreach ($p['stages'] as $dealStage) {
$s = ResponseNormalize::normalizeDealStage($dealStage);
/** @var ?Stage $existingStage */
$existingStage = $existingStages->get($s['id']);
// Restore soft-deleted stages that are now active in HubSpot
if ($existingStage?->trashed() && $s['active']) {
$existingStage->restore();
}
// Upsert stage (updates soft-deleted records without restoring them)
$stage = $this->config->stages()->withTrashed()->updateOrCreate([
'crm_provider_id' => $s['id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($s['label'], 0, 50),
'label' => mb_strimwidth($s['label'], 0, 191),
'type' => Stage::TYPE_OPPORTUNITY,
'sequence' => $s['displayOrder'],
'is_selectable' => $s['active'],
'probability' => $s['probability'] * 100,
]);
if ($missingStageName === $s['id']) {
$missingStage = $stage;
}
$stages[] = $stage->id;
}
$businessProcess->stages()->sync($stages);
}
return $missingStage;
}
/**
* @inheritdoc
*/
public function syncOrganization(): void
{
try {
$endpoint = '[URL_WITH_CREDENTIALS]
*/
public function find(string $name, array $scopes): array
{
$count = $this->limit ?? 20;
$offset = $this->offset ?? 0;
/** @var array<int, array<string, mixed>> */
return Cache::remember(
key: $this->team->getId() . $name . $count . $offset,
ttl: 300,
callback: function () use ($name, $offset, $count): array {
$data = [];
// Use the new V3 API to find contacts based on additional fields.
foreach (['companies', 'contacts'] as $objectType) {
$endpoint = '[URL_WITH_CREDENTIALS]
*/
public function findOpportunities(?string $crmAccountId, ?string $crmContactId, ?int $userId = null): array
{
$data = [];
$ownerData = [];
$ownerId = null;
if ($crmAccountId === null) {
return $data;
}
if ($userId) {
$profileRepository = app(ProfileRepository::class);
$profile = $profileRepository->findProfileByUserId($this->config, $userId);
$ownerId = $profile instanceof Profile ? $profile->getCrmProviderId() : null;
}
$closedStages = $this->getClosedDealStages();
$payload = $this->payloadBuilder->generateOpportunitiesSearchPayload(
$this->config,
$crmAccountId,
$closedStages,
);
$results = $this->client->getPaginatedData($payload, 'deals');
foreach ($results['results'] as $object) {
$properties = $object['properties'];
$amount = null;
if (empty($properties['amount']) === false) {
$currency = $properties['deal_currency_code'] ?? $this->config->default_currency;
// Values can contain commas and any junk so strip them.
$value = (float) preg_replace('/[^\d.]/', '', $properties['amount']);
$amount = formatCurrency($value, $currency);
}
$businessProcess = $this->config
->businessProcesses()
->where('crm_provider_id', $properties['pipeline'])
->first();
if ($businessProcess === null) {
// Import it.
$stage = $this->importStages([Stage::TYPE_OPPORTUNITY], $properties['dealstage']);
$businessProcess = $this->config
->businessProcesses()
->where('crm_provider_id', $properties['pipeline'])
->first();
} else {
$stage = $businessProcess
->stages()
->where('crm_provider_id', $properties['dealstage'])
->where('type', Stage::TYPE_OPPORTUNITY)
->first();
if ($stage === null) {
// Import it.
$stage = $this->importStages(null, $properties['dealstage']);
}
}
$recordType = null;
if ($businessProcess) {
$recordType = $businessProcess->recordTypes()->first();
}
$isWon = in_array($properties['dealstage'], $closedStages['won']);
$isLost = in_array($properties['dealstage'], $closedStages['lost']);
$record = [
'crmId' => $object['id'],
'name' => $properties['dealname'] ?? 'Unknown Deal',
'value' => $amount,
'won' => $isWon,
'closed' => $isWon || $isLost,
'stage' => [
'id' => $stage?->getUuid() ?? '',
'name' => $stage?->getName() ?? '',
],
];
if ($recordType) {
$record += [
'recordType' => [
'id' => $recordType->id_string,
'name' => $recordType->name,
],
];
}
if ($ownerId && isset($properties['hubspot_owner_id']) && $properties['hubspot_owner_id'] === $ownerId) {
$ownerData[] = $record;
}
$data[] = $record;
}
if (! empty($ownerData)) {
return $ownerData;
}
return $data;
}
/**
* @inheritdoc
*/
public function getTasks(?string $objectType, string $objectId, ?string $opportunityId): array
{
$data = [];
switch ($objectType) {
case 'contact':
$hsObject = 'contact';
break;
case 'account':
$hsObject = 'company';
break;
default:
// This is a hack to prioritise and override a contact/company with a deal.
if ($opportunityId) {
$hsObject = 'deal';
$objectId = $opportunityId;
} else {
throw new InvalidArgumentException('Object type not supported.');
}
}
$engagementTypes = ['meetings', 'tasks'];
foreach ($engagementTypes as $engagementType) {
$payload = $this->payloadBuilder->getLinkToTaskPayload($hsObject, $objectId, $engagementType);
$this->logger->info('[HubSpot] CRM Search requested', [
'request' => $payload,
]);
$engagements = $this->client->getPaginatedData($payload, $engagementType);
foreach ($engagements['results'] as $engagement) {
if ($engagementType == 'meetings') {
$title = $engagement['properties']['hs_meeting_title'] ?? 'Scheduled meeting';
} elseif ($engagementType == 'tasks') {
$title = $engagement['properties']['hs_task_subject'];
} else {
$title = 'Scheduled meeting';
}
$data[] = [
'crmId' => $engagement['id'],
'subject' => $title,
'due' => $engagement['properties']['hs_timestamp'],
'type' => $engagement['properties']['hs_activity_type'] ?? null,
];
}
}
usort($data, function ($item1, $item2) {
return $item2['due'] <=> $item1['due'];
});
return $data;
}
/**
* Try to find CRM Objects using email address
*
* @return null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
public function matchExactlyByEmail(string $email, ?int $userId = null): ?array
{
$contactProperties = [
'email',
'firstname',
'lastname',
'country',
'phone',
'mobilephone',
'jobtitle',
'hubspot_owner_id',
'associatedcompanyid',
'photo',
];
$contact = null;
$account = null;
try {
$hsContact = $this->getClient()->getContactByEmail($email, $contactProperties);
if ($hsContact) {
$contact = $this->importContact($hsContact);
$account = $contact->account;
}
$data = $this->convertCrmData($contact, $account, $userId);
return ! empty(array_filter($data)) ? $data : null;
} catch (BadRequest $e) {
$this->logger->warning('[HubSpot] Search failed', [
'team_id' => $this->team->getId(),
'search_identifier' => $email,
'reason' => $e->getMessage(),
]);
}
return null;
}
public function getDomain(string $email): ?string
{
return $this->getDomainFromEmail($email);
}
/**
* Try to find CRM objects using domain name of the email address
*
* @return null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
public function matchByDomain(string $domain, ?int $userId = null): ?array
{
$companyName = $domain;
// Try to find a company matching their email domain.
$companyProperties = [
'country',
'phone',
'name',
'hs_avatar_filemanager_key',
'industry',
'hubspot_owner_id',
'domain',
];
try {
$hsAccounts = $this->client
->getInstance()
->companies()
->searchByDomain($companyName, $companyProperties);
} catch (Throwable $e) {
$this->logger->info('[HubSpot] Search failed', [
'error' => $e->getMessage(),
'domain' => $domain,
]);
return null;
}
$account = null;
// If there are multiple accounts, don't guess, we'll ask later.
if (\count($hsAccounts->data->results) === 1) {
// Persist this remote object.
$account = $this->syncAccount($hsAccounts->data->results[0]->companyId);
}
$data = $this->convertCrmData(null, $account, $userId);
return ! empty(array_filter($data)) ? $data : null;
}
/**
* @return array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
protected function convertCrmData(?Contact $contact, ?Account $account, ?int $userId = null): array
{
$countryCode = null;
if ($contact && $contact->country_code) {
$countryCode = $contact->country_code;
} elseif ($account && $account->country_code) {
$countryCode = $account->country_code;
}
try {
$hsOpportunities = $this->findOpportunities(
$account ? $account->crm_provider_id : null,
$contact ? $contact->crm_provider_id : null,
$userId
);
} catch (Exception $e) {
$hsOpportunities = [];
}
// If there are multiple opportunities, don't guess, we'll ask later.
$opportunity = null;
$stage = null;
if (! empty($hsOpportunities)) {
// Persist this remote object.
$opportunity = $this->syncOpportunity($hsOpportunities[0]['crmId']);
$stage = $opportunity?->getStage();
}
return [
null,
$account,
$opportunity,
$contact,
$stage,
$countryCode,
];
}
protected function getCacheKey(string $object, ?int $userId = null): ?string
{
$key = $this->team->getId() . $object;
$keySuffix = $this->getOwnerKeySuffix($userId);
return $key . $keySuffix;
}
private function getOwnerKeySuffix(?int $userId = null): string
{
return $userId === null ? '' : (string) $userId;
}
/**
* @return null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
*}
*/
public function matchByPhone(string $phone, ?string $rawPhoneNumber = null, ?int $userId = null): ?array
{
if (str_contains($phone, '**')) {
return null;
}
// trim all whitespaces if present so the lookup doesn't fail
$phone = str_replace(' ', '', $phone);
// Check if the user is internal.
if ($this->isPhoneNumberOfTeamMember($phone)) {
return null;
}
$response = $this->searchForPhoneNumber($phone);
if (empty($response)) {
return null;
}
// This would ideally importContact instead but the response type differs.
$contact = $this->findAndSyncContact($response['results'][0]['id']);
if (! $contact instanceof Contact) {
return null;
}
$account = $contact->account;
$countryCode = $contact->country_code ?? $account->country_code ?? null;
try {
$hsOpportunities = $this->findOpportunities(
$account?->crm_provider_id,
$contact->crm_provider_id,
$userId
);
} catch (Exception $e) {
$hsOpportunities = [];
}
$opportunity = null;
$stage = null;
try {
if (! empty($hsOpportunities)) {
// Persist this remote object.
$opportunity = $this->syncOpportunity($hsOpportunities[0]['crmId']);
$stage = $opportunity?->getStage();
}
} catch (Exception $e) {
$this->logger->debug('[HubSpot] Opportunity failed to sync.', [
'reason' => $e->getMessage(),
]);
}
return [
null,
$account,
$opportunity,
$contact,
$stage,
$countryCode,
];
}
private function isPhoneNumberOfTeamMember(string $phone): bool
{
$teamRepository = app(TeamRepository::class);
$user = $teamRepository->findTeamMemberByPhone($this->team, $phone);
if ($user instanceof User) {
return true;
}
return false;
}
private function findAndSyncContact(string $crmId): ?Contact
{
try {
return $this->syncContact($crmId);
} catch (Exception $exception) {
$this->logger->info('[HubSpot] Phone match failed', [
'reason' => $exception->getMessage(),
]);
return null;
}
}
private function hasResults(array $response): bool
{
return isset($response['total']) && is_numeric($response['total']) && $response['total'] > 0;
}
private function searchForPhoneNumber(string $phone): array
{
// Normalizes the provided phone number for the API search.
$normalizedPhone = $this->normalizePhoneNumber($phone);
$payload = $this->payloadBuilder->generatePhoneSearchPayload($normalizedPhone);
$this->logger->info('[HubSpot] Phone match search triggered', [
'phone' => $phone,
'normalizedPhone' => $normalizedPhone,
'payload' => $payload,
]);
$response = $this->handlePhoneSearchRequest($normalizedPhone, $payload);
if (! $this->hasResults($response)) {
$nationalPhone = preg_replace('/\D/', '', phone_national(null, $phone));
$payload = $this->payloadBuilder->generatePhoneSearchPayload($nationalPhone);
$this->logger->info('[HubSpot] Phone match national number search triggered', [
'phone' => $phone,
'nationalPhone' => $nationalPhone,
'payload' => $payload,
]);
$response = $this->handlePhoneSearchRequest($phone, $payload);
}
if (! $this->hasResults($response)) {
$payload = $this->payloadBuilder->generatePhoneSearchPayload($normalizedPhone, true);
$this->logger->info('[HubSpot] Phone match alternative search triggered', [
'phone' => $phone,
'normalizedPhone' => $normalizedPhone,
'payload' => $payload,
]);
$response = $this->handlePhoneSearchRequest($phone, $payload);
}
return $this->hasResults($response) ? $response : [];
}
private function handlePhoneSearchRequest(string $phone, array $payload): array
{
$endpoint = '[URL_WITH_CREDENTIALS] null|array{
* Lead|null,
* Account|null,
* Opportunity|null,
* Contact|null,
* Stage|null,
* string|null
* }
*/
public function matchByName(string $name, ?int $userId = null): ?array
{
// Don't waste time searching for single character strings.
if (\strlen($name) <= 1) {
return null;
}
$cacheKey = $this->getCacheKey($name, $userId);
$result = Cache::remember($cacheKey, 60, function () use ($name, $userId) {
$payload = $this->payloadBuilder->generateSearchContactsByNamePayload(
$name,
$this->getContactFields()
);
$hsContacts = $this->client->getPaginatedData($payload, 'contact');
if (empty($hsContacts['results'])) {
return false;
}
$contact = $this->importContact($hsContacts['results'][0]);
if ($contact === null) {
return false;
}
$account = $contact->account;
$countryCode = $contact->country_code ?? $account->country_code ?? null;
try {
$hsOpportunities = $this->findOpportunities(
$account ? $account->crm_provider_id : null,
$contact->crm_provider_id,
$userId
);
} catch (Exception $e) {
$hsOpportunities = [];
}
$opportunity = null;
$stage = null;
if (! empty($hsOpportunities)) {
// Persist this remote object.
$opportunity = $this->syncOpportunity($hsOpportunities[0]['crmId']);
$stage = $opportunity?->getStage();
}
return [
null,
$account,
$opportunity,
$contact,
$stage,
$countryCode,
];
});
return is_array($result) ? $result : null;
}
private function convertActivityAssociations(Activity $activity): array
{
return [
'contactIds' => $this->getParticipantsIds($activity),
'companyIds' => $activity->hasAccount() ? [$activity->account->crm_provider_id] : [],
'dealIds' => $activity->hasOpportunity() ? [$activity->opportunity->crm_provider_id] : [],
'ownerIds' => [],
];
}
private function getParticipantsIds(Activity $activity): array
{
$attendees = [];
$participantRepository = app(ParticipantRepository::class);
$participants = $participantRepository->getParticipantsWhoEnteredMeeting($activity);
foreach ($participants as $participant) {
if ($participant->user_id || $participant->isCoach()) {
continue;
}
$contact = $participant->contact()->first();
if ($contact && $contact->crm_provider_id) {
$attendees[] = $contact->crm_provider_id;
} else {
if (! empty($participant->name)) {
$attendeeData = $this->fetchMissingAttendeeInfo($participant);
}
if (! empty($attendeeData['id'])) {
$attendees[] = $attendeeData['id'];
}
}
}
if ($activity->hasContact()) {
$attendees[] = $activity->contact->crm_provider_id;
}
return array_unique($attendees);
}
private function fetchMissingAttendeeInfo(Participant $participant): array
{
// Check if we need to look inside an account context.
$activity = $participant->getActivity();
$companyId = $activity->hasAccount() ? $activity->getAccount()->crm_provider_id : null;
// First check the local data.
/** @var Contact[] $contacts */
$contacts = $this->team->contacts()
->with('account')
->where('name', $participant->name)
->whereNotNull('email')
->get();
foreach ($contacts as $contact) {
// If we have a company in scope, check the contact is associated to it.
if (
$companyId !== null
&& ($contact->account_id === null || $companyId !== $contact->account->crm_provider_id)
) {
continue;
}
return [
'id' => $contact->crm_provider_id,
'email' => $contact->email,
];
}
$payload = $this->generateNameSearchPayload($participant->name, 0, 20);
try {
$response = $this->client->getNewInstance()->crm()->contacts()->searchApi()->doSearch($payload);
// TODO add some logic to choose the most suitable contact if multiple
foreach ($response['results'] as $object) {
$properties = $object['properties'];
if (empty($object['properties']) === false) {
// Check the company matches the contact.
// Todo: Move this check inside the API search.
if ($companyId !== null && $companyId !== $properties['associatedcompanyid']) {
continue;
}
return [
'id' => $object['id'],
'email' => $properties['email'],
];
}
}
} catch (Exception $e) {
$this->logger->warning('[' . $this->getDisplayName() . '] Search failed', [
'teamId' => $this->team->id_string,
'request' => $payload,
'reason' => $e->getMessage(),
]);
}
return [];
}
/**
* Store transcripts as note engagement.
*
* @throws Exception
*/
public function createTranscriptNotes(Activity $activity): void
{
// For HS no need to check if Crm profile - Log Notes field is enabled
// We only check if store_transcript toggle is enabled on crm profile.
$engagement = [
'active' => true,
'ownerId' => $this->profile->crm_provider_id,
'timestamp' => $activity->created_at->tz($activity->user->timezone)->getTimestamp() * 1000,
'type' => 'NOTE',
];
// Generate activity tr...
|
PhpStorm
|
faVsco.js – Hubspot/Service.php
|
NULL
|
87409
|
|
87408
|
rapstomEV favscojs ~ProjectvViewCooc#12121 on JY-2 rapstomEV favscojs ~ProjectvViewCooc#12121 on JY-20963-fx-ImTOOI-Windoweteamoremo tewins© ResponseNormalize.phpgsevice.on:esunchiorcdon.onGSUNCKOlOhCWWWKeweonooinlneochhoe2133› E IntegrationApp>O Listeners› E MetadataCmkcurayocryict.on© CachedCrmServiceDecorator.php© ServiceTest.php© DeleteObjects Trait.phpu rottoniuorrid.pnpRecordSelector.php(C) Hubspot/Service.php X OpportunitySyncTrait.phg© Activity.php©CrmEntityRepository.php1038g0public function natchActivityEngagementType(Activity Sactivity): stringf...1 usageprivate function assignCrn0wner(User Suser, ActivityContract Sactivity): PProfile(...}› E Pipedrivev SalesforceaFelds>aopoortunityVatchen2157OpportunitySyncStrategy2159> ProspectsearchStrategyServiceTraits2161 @ >C) e entond©[EMAIL]© PayloadBuilder.php© Profile.php© QueryBullder.phpprevore sroee Tunceion gecuestsrape einescnopotncloe odrangreturn self::API_URL . self::ENDPOINT_PIPELINES . self::PIPELINE_OBJECT_TYPE_DEALS;public function venifyTaskExists(Activity Sactivity): bool...ServicasOutpujiminny.opportunities 4tii jiminny stagesGin PauuttvaaramssBagase4 console 1 s 650 msEUSOrSS5% mev A|iminny@localhostHS localASFv pROpA consoleSTAGINGA consoleDockerDuvid (UUID with time-low and time-high swapped)( tean_id@crn_configuration_idHr account& stage_idstage_updated_at@record_type_idcrn_provider_idousenToouner_idnanevaluecurrency_codeDis_closediis nooMelose date768142384a9cfad-2c87-4453-9e72-20aeb78ccf8d5SS475BB3aT8:8428612826-85-20 18:36:594556494858198845]1812138848855Centiva Capital - EU HY/IG28608.88enscadeeommandtprobability100Wew out ren naet today Rayo nu comoy 10:50.4eU ServiceTest ~+0.E custom.logA console (PROD)DMO00-1725E laravel.logA SF (iminny@localhost)HSJocal ([jminny@localhost)A console (EU] * (B users (EU]A console [STAGING)1727-L120,17291 [CREDIT_CARD] v1739d8 liminny* Trom text_retays wnere createo_at > 2020-09-3031 49 A29 X3 X109 A Vsallect *mm acruites onden nu a deseesallec * mm llsang nhene nene uke "tona.sSELECT * FROM opportunities WHERE uuid_to_Din('04a9cfad-2C87-4453-9e72-20aeb78ccf8d*)=select * from teams mhere id = 555;select * from stages nhere tean_id = 555;SELECTCONCAT(U.$d, GASE WHEN U.1d = t.omner_id THEN • (ouner) ' ELSE "* END) AS user_1d=sa.*t.ouner_id FROM social_accounts saJOIN users on u.id = sa.sociable_idJOTN teams + 1..n<->1: on taid = u.tean ioWHERE v.team_id = 100 and sa-provider = 'hubspot":Cascadeles Orcnnworeeoeionhnves dohtine OooondNow look at ResponseNores Tize::nores Tireoea Stage)orobabuty" s Tloat (Coatal"cetadata""nrobabto tyteohThis ks the root causdRoot eause: moorStages overwmes D3 probability with tuoSpots valueThe fow is,"probabllty: "0.0"MІIN11ІРНIПВТЕ ПІРеН*default': falseit nasn't been chaneed recenu"Code$ Adaptive• •• :A1+00SiX:04048001SKtwodehime"hhokwhiresahensad,...
|
PhpStorm
|
faVsco.js – Hubspot/Service.php
|
NULL
|
87408
|
|
87407
|
JAlPostmanFileEditViewWindowHelpActivity MonitorAl JAlPostmanFileEditViewWindowHelpActivity MonitorAll ProcessesProcess Name% CPUkernel_taskPhpStormWindowServerreplaydscreenpipeFirefoxCP Isolated Web ContentPostman Helper (Renderer)FirefoxCP Isolated Web Contentmds_storescoreaudiodCursorUlViewService (Not Responding)launchservicesdlaunchdClaudeActivity MonitorbluetoothdFirefoxcef_server Helper (Renderer)language_server_macos_armFirefoxCP Isolated Web ContentPostman Helper (GPU)FirefoxCP Isolated Web Contentcef_server Helper (GPU)PostmaniTerm2Wispr FlowFirefoxCP Isolated Web ContentFirefoxCP Isolated Web Content160,2139,055,839,631,310,59,08,67,26,15,94,94,34,13,93,83,83,53,42,82,62,52,52,42,42,32,32,2CPU Time24:12:47,414:29:20,988:08:59,026:43:27,533:52:29,772:41,517:47,8441:35,971:10:42,771:02:11,146:06,571:04:36,9219:40,1529:50,609:43,7121:17,101:50:11,039:47,6112:14,571:05,8444,8617:07,158:29,223:57,671:05:06,904:31,0632:35,5244:02,55System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp ,49%46,78%8,73%CPUwwwHomeDMsActivityFilesLater..•More+ED→Jiminny...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana Netseva€o Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko KashinskiGalya Dimitrova: Todor StamatovRo Steliyan GeorgievEo VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...::: AppsJira Cloud• 0.(all100% <78• Thu 28 May 18:35:45Describe what you are looking forlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
PhpStorm
|
faVsco.js – Hubspot/Service.php
|
NULL
|
87407
|
|
87406
|
winoowX HubspotYour team is now on the Free plan w winoowX HubspotYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationerpendoneUseful › get history of property - deal stage((baseUri))/deats/V1/deal/494058190045?includePropertyVersionstrucE Docs Params • Authorization • Headers 12)SettinasQuery ParamsinciuderropertyverstonsobiectTyeV COLLECYIONS> HubsootKeration tun hsteration run Searchts› Journal & webhocoks v4• Poperiesv a crm/vs xoverties ob ect tvoe> (t batchacouos> (a(property Name)y ut Resd all propertiesca successful operationAn ertor occurredroneresle a properRESSAREH• СЕAРCH> Tckev Useful> rost tilter per comoanyonly ooen deal staoes.cEt engagements old associated by deawenanacmmnts dd nscocintnd oy comasnv сEt get history of property - deal stagenosuccasstul operation55. An error occurred.at get usersCET SF osuthauweeting cutcomes cer mectinowpond all aranortios nou.> ct Resd all properties okeсT old call dispositionset list with associationscEt list engagements okuuirecentencsaementCET get dealcEt Get Engagement (v1)PATCH https://api.hubapi.com/engagements/V1/engagements/2492739S231Parckhttos:/api.hubaoi.com/crm/vs/co.ects/meet.nos/2497k5x3%wTchttosdllanihubani. com/ancacamantslaoonoamaatc/240273052811Ciodstedessa00CMMIDANIENTCSPECS> FLOWSOConndettCoasde em aniooRoduKEJSONvPreview Visualize"hs deal stage probability".useTinestaspAsPersistenceTimestamp": true,"sourceUpstreanDeployable*:-"ForecastingKafka-deal-stage-probability-workezdenu stare oroodosbstty"DealStageProbabilityHandler",Huserrswrsi@ Searcha menim m sordCoe hitoroore eCEr RendCedet meetino4o7o0sLXThu 28 May 18:35:47et eonther with mhR SaveDetcrictionSondCookiesp.YKEOValuttruestad.700 ok. 270ms. 41.76 KRen Save Resnons?=019As ab.* 70122kHIGiobnts Montt Tookenem...
|
iTerm2
|
NULL
|
NULL
|
87406
|
|
87405
|
wunicowX HubspotwYour team is now on the Free plan wunicowX HubspotwYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stage((baseUri))/deats/V1/deal/494058190045?includePropertyVersionstrucE Docs Params • Authorization • Headers 12Body Scriots SettingsQuery ParamsinciuderropertyversconobiectTye@ Searchttetathon fun Sentchollietmnn sayeCoe hitoroore eOET ReadCr det meetinoet eonther with mh7o0sLXThu 28 May 18:35:40R SaveV COLLECYIONS> HubsootKeration tun Hoteration run Searchts› Journal & webhocoks v4• Poperiesv a crmvs/xoverteskob ect lvoe> (t batchacouos> (a(property Name)y ut Resd all propertiesca successful operationAn ertor occurredroneresle a properRESSAREH• СЕAРCH> Tckev Useful> rost tilter per comoanyonly ooen deal staoes.cEt engagements old associated by deawenanacments dld nscocntedloy comasn.v сEt get history of property - deal stagenosuccasstul operation55. An error occurred.at get usersCET SF osuthuuMeeting cutcomes cer mectinoaPond all nranortioe nou.> ct Resd all properties oldсT old call dispositionset list with associationscEt list engagements okuuirecentencsaementCET get dealcEt Get Engagement (v1)PATCH https://api.hubapi.com/engagements/V1/engagements/24927395231Patckhttos:api.hubaoi.com/crm/vs//colects/meet.nos/t4971s5xxwTchttosdllanihubani. com/ancacamantslaoonoamaatc/240273052811Ciodstedessa00CMMIDANIENTCSPECS> FLOWSOlConnnetteCoasole em antooDetcrictionSondCookiesp.YKEOSJSON vAВВВВВВВсВсВВсВсТEVisualizestad.200ok:270ms. 41.76 KRAs ab.* 70122ken Save Resnons?MAAALEEALGI0310599020011915834454101543*019d2825-e5f6-7296-98bc-2d517b787a88*.uselznescaspnspersistencelamestanpi crue,souxceupstxeamDeplovable: Foxecastingkaxka-deal•stage-prooabsl1ty-worker"nane": "hs_deal_stage_probability".sourceid*: "DealStageProbabilityHandler",oxecast/ngkatka•deal-stage-probab/lfty-norker--Giobnts Montt Tookemem...
|
iTerm2
|
NULL
|
NULL
|
87405
|
|
87404
|
PostmanFileEditViewWindowActivity MonitorAll Proce PostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskPostman Helper (Renderer)WindowServerreplaydscreenpipeFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentPostman Helper (GPU)coreaudiodPostmanClaudebluetoothdActivity Monitorlanguage_server_macos_armFirefoxCP Isolated Web ContentsyspolicydtccdFirefoxFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentKarabiner-Core-ServiceWispr FlowNotion Helper (Renderer)FirefoxCP Isolated Web ContentiTerm2Help% CPU137,5110,763,955,054,141,89,38,17,46,65,54,63,73,53,43,23,12,72,72,11,91,91,91,81,81,71,61,5CPU Time4:29:13,6324:12:38,947:47,368:08:56,076:43:25,433:52:28,1141:35,5244:02,4444,721:02:10,823:57,5429:50,3921:16,909:43,5012:14,3924:14,0417:31,669:19,971:50:10,8217:07,011:05,7032:35,4020:09,6820:56,774:30,9425:20,9213:42,571:05:06,77System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+31,07%54,36%14,56%CPUED→Jiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana Netseva€o Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko KashinskiGalya Dimitrova: Todor StamatovRo Steliyan GeorgievEo VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...#: AppsJira Cloud• 0.(all100% <78• Thu 28 May 18:35:40Describe what you are looking forlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87404
|
|
87403
|
Thu 28 May 18:35:39X HubspotYour team is now on th Thu 28 May 18:35:39X HubspotYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stage((baseUri))/deats/V1/deal/494058190045?includePropertyVersionstrucE Docs Params • Authorization • Headers 12Body Scriots SettingsQuery ParamsinciuderropertyversconobiectTye© ScarchCoe hitoroore eCEr RendCr det meetinoct eonthet with ihR SaveV COLLECYIONS> HubsootKeration tun Hoteration run Search HS› Journal & webhocoks v4• Poperiesv a crm/vs/xoverties kob ect tvoe> (t batchacouos> (a(property Name)y ut Resd all propertiesca successful operationAn ertor occurredroneresle a properRESSAREH• СЕAРCH> Tckev Useful> rost tilter per comoanyonly ooen deal staoes.cEt engagements old associated by deawenanacments dld nscocntedloy comasn.v сEt get history of property - deal stagenosuccasstul operation55. An error occurred.at getusersCET SF osuthauweatind cutcomes permectindaPond all nranortioe nou.> ct Resd all properties oldсT old call dispositionset list with associationscEt list engagements okuuirecentencsaementCET get dealcEt Get Engagement (v1)PATCH https://api.hubapi.com/engagements/V1/engagements/2492739S231Parckhttos:/api.hubaoi.com/crm/vs/co.ects/meet.nos/2497k5x3%wTchttosdllanihubani. com/ancacamantslaoonoamaatc/240273052811Ciodstedessa00CMMIDANIENTCSPECS> FLOWSOConnnettCoasdleem antooDetcrictionSondCookiesp.YKEOSJSON vVisualize *.16s0: 114500840582sourceld*: *DealStageProbab/iWitvHandl.ox*SOURCeVO"ASHrequestid*: *019d2825-e516-7296-98bc-2d517b787a88*,UKATCAstacoAsPersfstencothnastano"»orue.sourceUpstreanDeployable*: "ForecastingKafka-deal-stage-probability-workezne*: *hs deal stage orobability",Probabartyhandl.or"+019d005c-c292-7920-b3d4-a4640199709a*,useltecscrpas rerssrenceltnescuieoue"souxcellostzeamdeo)lovable*: "Foxecastingkafka«dea) estage-probabilfty«norker""contanct tex"."souxceld*: *usexid:59933091°stad.700 ok. 270ms. 41.76 KRAs ab.* 70122wn Save Resnons,JE X--Giobnts Montt Tookenem...
|
iTerm2
|
NULL
|
NULL
|
87403
|
|
87402
|
IAlPostmanFileEditViewWindowHelpActivity MonitorAl IAlPostmanFileEditViewWindowHelpActivity MonitorAll ProcessesProcess Name% CPUPhpStormkernel_taskreplaydWindowServerPostman Helper (Renderer)screenpipeFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentcoreaudiodNotion Calendar Helper (Renderer)Postman Helper (GPU)PostmanbluetoothdClaudeActivity MonitorFirefoxlanguage_server_macos_armlaunchservicesdFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentWispr FlowFirefoxCP Isolated Web ContentWispr Flow Helper (Renderer)Karabiner-Core-ServiceiTerm2FirefoxCP Isolated Web ContentNotion CalendarSlack Helper (Renderer)140,7118,756,229,620,49,08,95,75,45,24,64,03,73,23,12,82,72,72,32,21,91,71,51,51,31,31,31,2CPU Time4:29:06,3424:12:33,086:43:22,578:08:53,167:43,983:52:25,9041:35,0232:35,301:02:10,4710:05,8244,333:57,2521:16,7129:50,159:43,311:50:10,6812:14,211:04:36,641:05,6017:06,904:30,8444:02,015:48,0120:56,671:05:06,6920:09,583:24,291:00:52,54System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+28,66%47,65%23,69%CPU• 0.(all100% <78• Thu 28 May 18:35:36ED→Describe what you are looking forJiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana Netseva€o Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko Kashinski. Galya Dimitrova: Todor Stamatov. Steliyan GeorgievEo VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...#: AppsJira Cloudlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87402
|
|
87401
|
VieWwunicowX HubspotYour team is now on the Free p VieWwunicowX HubspotYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stage((baseUri))/deats/V1/deal/494058190045?includePropertyVersionstrucE Docs Params • Authorization • Headers 12Body Scriots SettingsQuery ParamsinciuderropertyversconobiectTyeTO0%7AThu 28 May 18:35:36@ Searchollietmnn sayeeoehtorooeOET ReadCedet meetinoct eonthet with ihR SaveV COLLECYIONS> HubsootKeration tun hsteration run Searchts› Journal & webhocoks v4• Poperiesv a crmvs/xoverteskob ect lvoe> (t batchacouos> (a(property Name)y ut Resd all propertiesca successful operationAn ertor occurredroneresle a properRESSAREH• СЕAРCH> Tckev Useful> rost tilter per comoanyonly ooen deal staoes.cEt engagements old associated by deawenanacments dld nscocntedloy comasn.v сEt get history of property - deal stagenosuccasstul operation55. An error occurred.at get usersCET SF osuthuuMeeting cutcomes cer mectinoaPond all nranortioe nou.> ct Resd all properties oldсT old call dispositionset list with associationscEt list engagements okuuirecentencsaementCET get dealcEt Get Engagement (v1)PATCH [URL_WITH_CREDENTIALS] d": 47072355"useisinestaroicPers istence pirestano"true,stad.700 ok. 270ms. 41.76 KR.an Save Resnons?As ab.* 70122kJE XProbabil{tyHandler*,updatedByUsezid*: null,"hs deal stage probabilfty"sestaro:77938965775"sourcold": "DoslStaseProbabilitvHandlor".l"xequestId": *019e46a9-51b8-7e69-9db6-153e5c1b1529*.STieWeOSAWANATeAtaen"e trIsouxcellostreamDeplovable*: *Foxocastingkafka«deal •stage-probability-norkeHIGiobnts Montt Tookemem...
|
iTerm2
|
NULL
|
NULL
|
87401
|
|
87400
|
PostmanFileEditViewWindowHelpActivity MonitorAll P PostmanFileEditViewWindowHelpActivity MonitorAll ProcessesProcess Name% CPUPhpStormkernel_taskreplaydscreenpipemds_storesWindowServerFirefoxCP Isolated Web ContentcoreaudiodlaunchdCursorUlViewService (Not Responding)Activity MonitorFirefoxbluetoothdAlfredsysmondlanguage_server_macos_armFirefoxCP Isolated Web ContentWispr FlowlaunchservicesdFirefoxCP Isolated Web ContentmdsiTerm2Postman Helper (Renderer)FirefoxCP Isolated Web ContentSlackFirefoxCP Isolated Web ContentlogdWispr Flow Helper (Renderer)145,8126,745,135,928,423,89,77,04,74,04,03,43,22,92,82,72,62,42,22,12,01,91,81,61,61,51,51,5CPU Time4:28:36,1924:12:13,876:43:10,033:52:22,441:10:42,338:08:47,3041:33,201:02:09,3719:39,756:06,129:42,681:50:10,1421:15,981:42,752:20,1212:13,691:05,114:30,441:04:35,8217:06,4832:17,161:05:06,437:40,3620:09,2514:08,7513:42,2817:19,365:47,70System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+31,06%25,46%43,48%CPUED→Jiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana Netseva€o Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko KashinskiGalya Dimitrova: Todor StamatovRo Steliyan Georgievto VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...::: AppsJira Cloud(all100% <78• Thu 28 May 18:35:18Describe what you are looking forlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87400
|
|
87399
|
PostmanFileEditViewWindowHelpActivity MonitorAll P PostmanFileEditViewWindowHelpActivity MonitorAll ProcessesProcess Name% CPUPhpStormkernel_taskreplaydscreenpipemds_storesWindowServerFirefoxCP Isolated Web ContentcoreaudiodlaunchdCursorUlViewService (Not Responding)Activity MonitorFirefoxbluetoothdAlfredsysmondlanguage_server_macos_armFirefoxCP Isolated Web ContentWispr FlowlaunchservicesdFirefoxCP Isolated Web ContentmdsiTerm2Postman Helper (Renderer)FirefoxCP Isolated Web ContentSlackFirefoxCP Isolated Web ContentlogdWispr Flow Helper (Renderer)145,812€1,81,61,61,51,51,5CPUMemoryCPU TimeThreadsIdle Wake-Ups4:28:36,19263533ts 17793019657751779301965Unix Timestamp (seconds)1779301965775Unix Timestamp (milliseconds)2026-05-20 18:32:45UTC datetime2026-05-20 21:32:45Local datetime (EEST)2026-05-20Date only (EEST)21:32:45Time only (24-hour)20260520Compact date (YYYYMMDD)2026-05-20T18:32:45ZISO 8601 UTC (Salesforce)20260520183245Bullhorn format (YYYYMMDDHHmmss)7:40,36291720:09,252414:08,75547213:42,2817:19,36255:47,702166System:User:Idle:21,78%38,08%40,14%EnelKDED→Jiminny ...# infrastructure_dev+:Todor StamatovRo Steliyan GeorgievCo Ves8. MiraP. Nikolay Yankovdo James GrahamE Lukas Kovalik y... O::: AppsJira Cloud(all100% <8• Thu 28 May 18:35:17Describe what you are looking forlliyana Netseva6 0• MessagesAdd canvas+Jk, thank youv 2 new messagesliyana Netseva 5.45 PM1мам питане и се чудя към кого мога да сеобърна?₴2883₴84285₴6$7488става дума за deal insightsJukas Kovalik 5:54 PMПитай, ако мога ще отговоряliyana Netseva 5:56 PMчмам сделка която е сьс статус won но е вclosed lostova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataJukas Kovalik 6:00 PMJS или EU (edited)liyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMзиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva+...
|
iTerm2
|
NULL
|
NULL
|
87399
|
|
87398
|
wunicowX HubspotwYour team is now on the Free plan wunicowX HubspotwYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stage((baseUri))/deats/V1/deal/494058190045?includePropertyVersionstrucE Docs Params • Authorization • Headers 12)Body Scriots SettingsQuery ParamsinciuderropertyverstonsobiectTye7o0sLXThu 28 May 18:35:16© Scarchlollietmnr sayeCoe hitoroore eOET ReadCr det meetinoet eonther with mhR SaveV COLLECYIONSEngsgements› HubspotKera don run› Iteration run Search HSOaRWeonocoksVeOAuthcrm/v3/properties/(object Type>a groups?-olOoery Namev ut Read all oronartiesee successtul operationen An error occurred> SEARCHTicketsv Uselupest lilter por comanny /onty ocen dent stnoeywnendademens oo associa.tovoCit anandsmante did actocitid on comode.verceinisto or docciy - oedeooewsuccesstul oneration5e An error occurred.EET aCtUSOreCET SF oauthetr Mentind cntcomac cat mastied> сt Read all properties new> ct Road all oronertios olaal call disnositionscrtlist with aesociation.cet list engagements okCTTACAOT Anoadementct get dealet Got Enaagement (vllPATCи httos://api.hubapi.com/engagements/V1/engagements/24927395231PaTCHhttos:/api.hubapi.com/engagements/v1/enoaoements/24927395231CTUonAte deslicharCMMIDANIENTCSPECS> FLOWSOlConnnettCoasdle em antooDetcrictionSondCookiesp.YKEOSJSON vPreview Visualizesourceld": "DealStageProbabilityHandler",upd.eo-wseonuue"nane": "hs deal stage probability",tanp*: 1779301965775Id*: *DealStageProbabil{tyHandler*.(3, Сп0-2010-00h6-15305c1b1529*souxceUpstreanDeployable*: "ForecastingKafka-deal•stage-probability-worker"Р0. °sourcoid": *DoalStageProbabllitvHandl.or*"requestId": *019e07d7-b83d-78be-bc7b-ccf524e62eb6*,"sourceUpstrea=Deployable*: *Forecastingkafka-deal-stage-probabilfty-workers dersaRe oxoonbseaysouxceId": "DealStageProbabilityHandler",stad.700 ok. 270ms. 41.76 KRAs ab.* 70122kwn Save Resnons,Giobnts Montt Tookemed...
|
iTerm2
|
NULL
|
NULL
|
87398
|
|
87397
|
ts 1779301965775
PostmanFileEditViewWindowHelpActi ts 1779301965775
PostmanFileEditViewWindowHelpActivity MonitorAll ProcessesProcess Name% CPUPhpStormkernel_taskreplaydscreenpipemds_storesWindowServerFirefoxCP Isolated Web ContentcoreaudiodlaunchdCursorUlViewService (Not Responding)Activity MonitorFirefoxbluetoothdAlfredsysmondlanguage_server_macos_armFirefoxCP Isolated Web ContentWispr FlowlaunchservicesdFirefoxCP Isolated Web ContentmdsiTerm2Postman Helper (Renderer)FirefoxCP Isolated Web ContentSlackFirefoxCP Isolated Web ContentlogdWispr Flow Helper (Renderer)145,812€1,81,61,61,51,51,5CPUMemoryCPU TimeThreadsIdle Wake-Ups4:28:36,19263533ts 17793019657751779301965Unix Timestamp (seconds)1779301965775Unix Timestamp (milliseconds)2026-05-20 18:32:45UTC datetime2026-05-20 21:32:45Local datetime (EEST)2026-05-20Date only (EEST)21:32:45Time only (24-hour)20260520Compact date (YYYYMMDD)2026-05-20T18:32:45ZISO 8601 UTC (Salesforce)20260520183245Bullhorn format (YYYYMMDDHHmmss)7:40,36291720:09,252414:08,75547213:42,2817:19,36255:47,702166System:User:Idle:12,44%31,45%56,11%EnelKDED→Jiminny ...# infrastructure_dev+:Todor StamatovRo Steliyan GeorgievCo Ves8. MiraP. Nikolay Yankovdo James GrahamE Lukas Kovalik y... O::: AppsJira Cloud(all100% <8• Thu 28 May 18:35:14Describe what you are looking forlliyana Netseva6 0• MessagesAdd canvas+Jk, thank youv 2 new messagesliyana Netseva 5.45 PM1мам питане и се чудя към кого мога да сеобърна?₴2883₴84285₴6$7488става дума за deal insightsJukas Kovalik 5:54 PMПитай, ако мога ще отговоряliyana Netseva 5:56 PMчмам сделка която е сьс статус won но е вclosed lostova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataJukas Kovalik 6:00 PMJS или EU (edited)liyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMзиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva+...
|
Alfred
|
Alfred
|
NULL
|
87397
|
|
87396
|
ts
wunicowX HubspotwYour team is now on the Free p ts
wunicowX HubspotwYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stage((baseUri))/deats/V1/deal/494058190045?includePropertyVersionstrucE Docs Params • Authorization • Headers 12)Body Scriots SettingsQuery ParamsinciuderropertyverstonsobiectTye7o0sLXThu 28 May 18:35:12© Scarchlollietmnr sayeCoe hitoroore eOET ReadCr det meetinoet eonther with mhR SaveV COLLECYIONSEngsgements› HubspotKera don run› Iteration run Search HSOaRWeonocoksVeOAuthcrm/v3/properties/(object Type>a groups?-olOoery Namev ut Read all oronartiesee successtul operationen An error occurred> SEARCHTicketsv Uselupest lilter por comanny /onty ocen dent stnoeywnendademens oo associa.tovoCit anandsmante did actocitid on comode.verceinisto or docciy - oedeooewsuccesstul oneration5e An error occurred.EET aCtUSOreCET SF oauthetr Mentind cntcomac cat mastied> сt Read all properties new> ct Road all oronertios olaal call disnositionscrtlist with aesociation.cet list engagements okCTTACAOT Anoadementct get dealet Got Enaagement (vllPATCи httos://api.hubapi.com/engagements/V1/engagements/24927395231PaTCHhttos:/api.hubapi.com/engagements/v1/enoaoements/24927395231CTUonAte deslicharCMMIDANIENTCSPECS> FLOWSOlConnnettCoasdle em antooDetcrictionSondCookiesp.YKEOSJSON vPreview Visualizesourceld": "DealStageProbabilityHandler",upd.eo-wseonuue"nane": "hs deal stage probability",tanp*: 1779301965775Id*: *DealStageProbabil{tyHandler*.(3, Сп0-2010-00h6-15305c1b1529*souxceUpstreanDeployable*: "ForecastingKafka-deal•stage-probability-worker"Р0. °sourcoid": *DoalStageProbabllitvHandl.or*"requestId": *019e07d7-b83d-78be-bc7b-ccf524e62eb6*,"sourceUpstrea=Deployable*: *Forecastingkafka-deal-stage-probabilfty-workers dersaRe oxoonbseaysouxceId": "DealStageProbabilityHandler",stad.700 ok. 270ms. 41.76 KRAs ab.* 70122kwn Save Resnons,Giobnts Montt Tookemed...
|
Alfred
|
Alfred
|
NULL
|
87396
|
|
87395
|
ts
JAlPostmanFileEditViewWindowActivity MonitorAll ts
JAlPostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskreplaydWindowServerPostman Helper (Renderer)screenpipeFirefoxCP Isolated Web ContentcoreaudiodFirefoxsyspolicydPostmantccdbluetoothdlaunchservicesdClaudeActivity Monitorlanguage_server_macos_armNotion Calendar Helper (Renderer)Postman Helper (GPU)FirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentWispr FlowSlack Helper (Renderer)iTerm2Help% CPUCursorUlViewService (Not Responding)trustdFirefoxCP Isolated Web ContentWispr Flow Helper (Renderer)136,611/22,518,98,36,54,54,03,53,43,33,13,13,02,72,42,01,91,91,81,81,71,61,51,41,4CPU Time4:28:28,527:40,273:52:20,5541:32,691:02:09,001:50:09,9617:31,393:56,509:19,7521:15,811:04:35,7029:49,509:42,4712:13,5510:05,5343,6117:06,371:04,984:30,321:00:52,221:05:06,336:05,9115:06,0820:09,175:47,62System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKD DMsActivityFilesLater..•More+36,25%39,54%24,21%CPUED→Jiminny ...# infrastructure_dev# piatrorm-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana Netseva€o Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko KashinskiGalya Dimitrova: Todor Stamatov. Steliyan Georgievto VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...::: AppsJira Cloud(all100% <78• Thu 28 May 18:35:11Describe what you are looking forlliyana Netseva6 0• MessagesAdd canvas+ok, thank youv 2 new messagesliyana Netseva 5.45 PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
Alfred
|
Alfred
|
NULL
|
87395
|
|
87394
|
IAlPostmanFileEditViewWindowActivity MonitorAll Pr IAlPostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskreplaydscreenpipeWindowServerFirefoxCP Isolated Web ContentPostman Helper (Renderer)coreaudiodFirefoxbluetoothdActivity Monitorlaunchservicesdlanguage_server_macos_armFirefoxCP Isolated Web ContentWispr FlowFirefoxCP Isolated Web ContentiTerm2FirefoxCP Isolated Web ContentPostman Helper (GPU)PostmanWispr Flow Helper (Renderer)FirefoxCP Isolated Web ContentClaudeSlacklogdFirefoxCP Isolated Web ContentControl CentreKarabiner-Core-ServiceHelp% CPU146,276,058,340,516,98,95,45,04,03,53,22,92,42,41,91,81,71,71,51,51,41,31,31,31,21,21,21,1CPU Time4:28:21,3024:12:01,136:43:04,643:52:19,568:08:44,3541:32,257:39,081:02:08,661:50:09,7321:15,639:42,311:04:35,5412:13,4117:06,274:30,221:04,881:05:06,2425:35,3443,513:56,325:47,5520:09,0929:49,3414:08,6417:19,224:25,5020:50,9720:56,26System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+34,07%42,63%23,31%CPU• 0.(all100% <78• Thu 28 May 18:35:07ED→Describe what you are looking forJiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana Netseva€o Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko KashinskiGalya Dimitrova: Todor StamatovRo Steliyan Georgievto VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...::: AppsJira Cloudlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87394
|
|
87393
|
X HubspotwYour team is now on the Free plan with 1 X HubspotwYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stage((baseUri))/deats/V1/deal/494058190045?includePropertyVersionstrucE Docs Params • Authorization • Headers 12)Body Scriots SettingsQuery ParamsinciuderropertyverstonsobiectTyescarchettecation run Santchlollietmnr sayeCoe hitoroore eOET ReadCedet meetino4o7o0sLXet eonther with mhThu 28 May 18:35:07R SaveV COLLECYIONSEngsgements› HubspotKera don run› Iteration run Search HSOaRWeonocoksVeOAuthcrm/v3/properties/(object Type>a groups?-olOoery Namev ut Read all orooartiesee successtul operationen An error occurred> SEARCHTicketsv Uselupest lilter por comanny /onty ocen dent stnoeywnendademens oo associa.tovoCit anandsmante did actocitid on comode.verceinisto or docciy - oedeooewsuccesstul oneration5e. An error occurred.EET aCtUSOreCET SF oauthetr Mentind cntcomac cat mastied> сt Read all properties new> cy Road all oronertios olalaar call disoosttionscrtlist with aesociation.cet list engagements okCTTACAOT Anoadementct get dealet Got Enaagement (vllPATCи httos://api.hubapi.com/engagements/V1/engagements/24927395231PaTCHhttos:/api.hubapi.com/engagements/v1/enoaoements/24927395231CTUonAte deslicharCMMIDANIENTCSPECS> FLOWSOlConnnettCoasdle em antooDetcrictionSondCookiesp.YKEORoduJSONPreview Visualizesouxceld*: "DealStaseProbabil/tyHandlex"upd.eo-wseonuue"nane": "hs deal stage probability",Id": *DealStageProbabilityHandler".(. С00010-00h6.45305c1b1529*.souxceUpstreanDeployable*: "ForecastingKafka-deal•stage-probability-worker"Р0. °sourcoid": *DoalStageProbabllitvHandl.or*requestId*: *019e07d7-b83d-78be-bc7b-ccf524e62eb6*."sourceUpstrea=Deployable*: *Forecastingkafka-deal-stage-probabilfty-workernens cesaRe oxoonbeatysouxceId": "DealStageProbabilityHandler",stad.200ok:270ms. 41.76 KRAs ab.* 70122ken Save Resnons?+UE xHIGiobnts Montt Tookemem...
|
iTerm2
|
NULL
|
NULL
|
87393
|
|
87392
|
7o0sLXThu 28 May 18:34:49X HubspotYour team is now 7o0sLXThu 28 May 18:34:49X HubspotYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stage((baseUri))/deats/V1/deal/494058190045?includePropertyVersionstrucE Docs Params • Authorization • Headers 12Body Scriots SettingsQuery Paramsv includePropertyVersionsobiectTyescarchlollietmnr sayeCoe hitoroore eCEr RendCr det meetinoet eonther with mhR SaveV COLLECYIONSEngsgements› HubspotKera don runttaration nin Sastch HeOaRWeonocoksVeOAuthcrm/v3/properties/(object Type>a groups?-olOoery Namev ut Read all orooartiesea successful operationenAn error occurred> SEARCHTicketsv Uselupest lilter por comanny /onty ocen dent stnoeywnendademens oo associa.tovoCit anandsmante did actocitid on comode.veroeinistomv or docchy eoou sooewsuccesstul oneration5e. An error occurred.EET aCtUSOreCET SF oauthCir Mentind outcomac car maste.> сt Read all properties newcy Road all oronertios.oldaald call dispositionscrtliet with aesociationscet list engagements oldCnrecaot ancadementct get dealet Got Enaagement (vllPATCи httos://api.hubapi.com/engagements/V1/engagements/24927395231PaTCHhttos:/api.hubapi.com/engagements/v1/enoaoements/24927395231CTUoAAte dolCAaCMMIDANIENTCSPECS> FLOWSOlConnnettCoasdle em antooDetcrictionSondCookiesp.YKEORoduKEJSONvPreviewpy Visualizestad.700 ok. 270ms. 41.76 KRen Save Resnons?As ab. * 60122*• JE x8888588858888388un of associated ling itons".Rol lunProoerties"LCULAIEUrequestid*: *019005c-bf10-724d-9caf-82afdde9b8c5*.uewirenroAcperelsrence wirestanoateqesouxcelost reardeo ovabie: "Creooiect8u deyRocServer-usereths deal stage probability": "eProbabsl{tyHandlerdeal stage probability*ourcold": "DealStaseProbabilityHandlor""CALCULATED"eVid".nh*019e4629-5168-7e60-9db6-153e5c1b1529*.•A.AIMALIARAATISRAIIR A--Giobnts Montt Tookenem...
|
iTerm2
|
NULL
|
NULL
|
87392
|
|
87391
|
IAlPostmanFileEditViewWindowActivity MonitorAll Pr IAlPostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskreplaydscreenpipeWindowServerPostman Helper (Renderer)mds_storesFirefoxCP Isolated Web ContentcoreaudiodFirefoxClaudePostmanbluetoothdActivity MonitorFirefoxCP Isolated Web ContentlaunchservicesdFirefoxCP Isolated Web ContentPostman Helper (GPU)FirefoxCP Isolated Web Contentlanguage_server_macos_armFirefoxCP Isolated Web ContentiTerm2Wispr FlowFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentNotion Helper (Renderer)Wispr Flow Helper (Renderer)FirefoxCP Isolated Web ContentHelp% CPU163,0116,343,340,530,010,99,88,65,44,64,44,43,53,53,43,23,13,12,92,82,12,02,01,91,61,51,41,4CPU Time4:27:57,9924:11:44,466:42:55,863:52:13,388:08:40,477:36,931:10:40,7741:30,831:02:07,821:50:08,9929:49,053:55,9321:15,079:41,7744:01,711:04:35,0911:54,1143,101:04,5412:12,9820:08,781:05:05,994:29,9217:05,8832:34,7725:20,345:47,126:35,75System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+24,66%33,14%42,21%CPUED→Jiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana Netseva€o Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko Kashinski. Galya Dimitrova: Todor Stamatov. Steliyan Georgievto VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...::: AppsJira Cloud• 0.(all100% <78• Thu 28 May 18:34:49Describe what you are looking forlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87391
|
|
87390
|
4o7o0sLXThu 28 May 18:34:488R HubspotYour team is 4o7o0sLXThu 28 May 18:34:488R HubspotYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stage((baseUri)/deats/V1/deal/494058190045?includePropertyVersionstrucE Docs Params • Authorization • Headers 12)Body Scriots SettingsQuery Paramsv includePropertyVersionsobiectTye© ScarcheoehtorooeCEr RendCedet meetinocet eonthet with hR SaveV COLLECYIONEEngsgements› HubspotKera don run› Iteration run Search HSOaRWeonocoksVeOAuthcrm/v3/properties/(object Type> 0 batch>a groups?orooery namev ut Read all orooartiesea successful operationenAn error occurred> SEARCHTicketsv Uselupest lilter por comanny /onty ocen dent stnoeycEt engagements old associated by deaCin anandamsnte did aetocitkd on comode.verceinisto or docciy - oedeooewsuccesstul oneration5e An error occurred.EET act usereCET SF oauthetr Mentind cntcomac cat mastied> сt Read all properties newcey Road all oronertios.olaaar call disoosttionsertliet with aesocistioncet list engagements okCnracaot ancadementct get dealet Got Enaagement (vllPATCи httos://api.hubapi.com/engagements/V1/engagements/24927395231PaTCHhttos:/api.hubapi.com/engagements/v1/enoaoements/24927395231CTUoAAte dolCAaCMMIDANIENTCSPECS> FLOWSOConndettCoasde em aniooDetcrictionSondCookiespulkEotRoduKEJSONvEE IEẠI> PreviewX Visualizestad.200ok:270ms. 41.76 KRAsab.* 50122xan Save Resnons?JE xouner_duration_in_current_stage*."StalledDealUpdateProcessor:userId:Optional.empty*.ANIEKNAL PRULESSINGrcoucst7d*: *919d4034-9918-2621-befb-071d0da42aac*useT sestasoAsPers istencet mestamo"a truencouzcallostxcardeollovabile". "Sollsineka kaostallled-den -undateenoriker"nane*: "hs average deal ouner duxation in current stage*.keactne". 477/606944609cstaro": 1774586987244"StallodDealsw23ob--"souxceld*. *enxoltrent1d[PHONE]49act3ionSxacutiontndoxe2*.Giobnts Montt Tookemem...
|
iTerm2
|
NULL
|
NULL
|
87390
|
|
87389
|
IAlPostmanFileEditViewWindowActivity MonitorAll Pr IAlPostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskreplaydscreenpipeWindowServerPostman Helper (Renderer)mds_storesFirefoxCP Isolated Web ContentcoreaudiodFirefoxClaudePostmanbluetoothdActivity MonitorFirefoxCP Isolated Web ContentlaunchservicesdFirefoxCP Isolated Web ContentPostman Helper (GPU)FirefoxCP Isolated Web Contentlanguage_server_macos_armFirefoxCP Isolated Web ContentiTerm2Wispr FlowFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentNotion Helper (Renderer)Wispr Flow Helper (Renderer)FirefoxCP Isolated Web ContentHelp% CPU163,0116,343,340,530,010,99,88,65,44,64,44,43,53,53,43,23,13,12,92,82,12,02,01,91,61,51,41,4CPU Time4:27:57,9924:11:44,466:42:55,863:52:13,388:08:40,477:36,931:10:40,7741:30,831:02:07,821:50:08,9929:49,053:55,9321:15,079:41,7744:01,711:04:35,0911:54,1143,101:04,5412:12,9820:08,781:05:05,994:29,9217:05,8832:34,7725:20,345:47,126:35,75System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp ,64%39,39%34,97%CPUMNWHomeDMsActivityFilesLater..•More+ED→Jiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana NetsevaGo Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko Kashinski. Galya Dimitrova: Todor Stamatov. Steliyan Georgievto VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...::: AppsJira Cloud• 0.(all100% <78• Thu 28 May 18:34:48Describe what you are looking forlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87389
|
|
87388
|
X HubspotYour team is now on the Free plan with 1 X HubspotYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stage((baseUri))/deats/V1/deal/494058190045?includePropertyVersionstrucE Docs Params • Authorization • Headers 12Body Scriots SettingsQuery Paramsv includePropertyVersionsobiectTye@ Searchollietmnn sayeeoehtorooeCEr RendCr det meetinoet eonther with mh7o0sLXThu 28 May 18:34:46R SaveV COLLECYIONE› HubspotKera don runttaration nin Sastch HeOaRWeonocoksVeOAuthcrm/v3/properties/(object Type>a groups?-olOoery Namev ut Read all orooartiesea successful operationen An error occurredCEAGANTicketsv Uselupest lilter por comanny /onty ocen dent stnoeycEt engagements old associated by deaCin anandamsnte did aetocitkd on comode.verceinisto or docciy - oedeooewsuccesstul oneration5e An error occurred.EET aCtUSOreCET SF oauthCir Mentind outcomac car maste.> сt Read all properties newcey Road all oronertios.olaaald call dispositionscrtliet with aesociationscet list engagements okCnrecaot ancadementct get dealet Got Enaagement (vllPATCи httos://api.hubapi.com/engagements/V1/engagements/24927395231PaTCHhttos:/api.hubapi.com/engagements/v1/enoaoements/24927395231CTUonAte deslicharCMMIDANIENTCSPECS> FLOWSOConndettCoasde em aniooDetcrictionSondCookiesRYKEdRoduKEJSONv88088869986668994993999998591PreviewpX Visualizesame*: "hs has last mecting follonups".cedPropertyComputer*,CULAIEUrequestid*: *0190005c-bf10-724d-9caf-82afdde9b0c5*uewirenroAcperelsrence wirestanoateqesouxcelost reardeo ovabie: "Creooiect8u deyRocServer-useretaverage deal ouner duration in current stage*: {ocessox:usey d:Dotonalrecoty-)ouner duxation in current stage*."StalledDea/UodateProcessox:userId:0otional.eaoty*.[PHONE]-262 -befb-671d0da42aac"KeT restacoA Pers istencetnestamo"»tamue.stad.700 ok. 270ms. 41.76 KRTwn Save Resnons,Asab.* 401.22xAE X----Giobnts Montt Tookenem...
|
iTerm2
|
NULL
|
NULL
|
87388
|
|
87387
|
JAlPostmanFileEditViewWindowActivity MonitorAll Pr JAlPostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskreplaydWindowServerscreenpipePostman Helper (Renderer)FirefoxCP Isolated Web ContentcoreaudiodPostmanClaudePostman Helper (GPU)bluetoothdlaunchdActivity Monitorlanguage_server_macos_armFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentFirefoxFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentWispr FlowKarabiner-Core-ServiceFirefoxCP Isolated Web ContentiTerm2Wispr Flow Helper (Renderer)FirefoxCP Isolated Web ContentNotion Helper (Renderer)Help% CPU130,6100,451,339,024,814,18,15,35,25,04,43,63,53,02,62,22,12,02,02,01,81,81,71,71,51,41,31,2CPU Time4:27:49,4424:11:38,366:42:53,598:08:38,893:52:11,267:36,3641:30,381:02:07,533:55,7029:48,8142,9321:14,8919:39,369:41,5912:12,8324:13,5211:53,941:04,391:50:08,7432:34,6917:05,784:29,8220:56,0020:08,671:05:05,885:47,0410:22,6025:20,26System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+35,53%34,53%29,94%CPU• 0.(all100% <78• Thu 28 May 18:34:46ED→Describe what you are looking forJiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana NetsevaGo Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko Kashinski. Galya Dimitrova: Todor Stamatov. Steliyan Georgievto VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...#: AppsJira Cloudlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87387
|
|
87386
|
7o0sLXThu 28 May 18:34:46X HubspotYour team is now 7o0sLXThu 28 May 18:34:46X HubspotYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stage((baseUri))/deats/V1/deal/494058190045?includePropertyVersionstrucE Docs Params • Authorization • Headers 12Body Scriots SettingsQuery Paramsv includePropertyVersionsobiectTye@ Searchollietmnn sayeCoe hitoroore eCEr RendCedet meetinoet eonther with mhR SaveV COLLECYIONSEngsgements› HubspotKera don runttaration nin Sastch HeOaRWeonocoksVeOAuthcrm/v3/properties/(object Type>a groups?-olOoery Namev ut Read all orooartiesee successtul operationen An error occurredCEAGANTicketsv Uselupest lilter por comanny /onty ocen dent stnoeycEt engagements old associated by deaCin anandamsnte did aetocitkd on comode.verceinisto or docciy - oedeooewsuccasstul .onerat.or5e An error occurred.EET aCtUSOreCET SF oauthetr Mentind cntcomac cat mastied> сt Read all properties newcey Road all oronertios.olaanald call dispositionscrtliet with aesociationscer list engagements okCnrecaot ancadementcEt get dealet Got Enaagement (vllPATCи httos://api.hubapi.com/engagements/V1/engagements/24927395231PaTCHhttos:/api.hubapi.com/engagements/v1/enoaoements/24927395231CTUoAAte dolCAaCMMIDANIENTCSPECS> FLOWSOConndettCoasde em aniooDetcrictionSondCookiespulkEotRoduKEJSONvВССЕВЕЕЛАВЕВАССЕСЕОВВВВВВАЯАТPreviewP% Visualizesame*: "hs has last mecting follonups".CULAIEUrequestid*: *0190005c-bf10-724d-9caf-82afdde9b0c5*uewirenroAcperelsrence wirestanoateqesouxcelost reardeo ovabie: "Creooiect8u deyRocServer-userets average deal ouner duration in current stage*: {"sourceld": "StalledDealUodateProcessoxsuser7d:0otsional.enoty*ouner duration in current stage*.«StalledDea/UodateProcessox:userId:0otional.caoty*,[PHONE]-262--bofb-071d0da42aac"KeT restacoA Pers istenceT mestamo"» taue.stad.700 ok. 270ms. 41.76 KRAs ab.* 30122xan Save Resnons?• JE x--Giobnts Montt Tookenem...
|
iTerm2
|
NULL
|
NULL
|
87386
|
|
87385
|
TO0%7AThu 28 May 18:34:44X HubspotYour team is now TO0%7AThu 28 May 18:34:44X HubspotYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stage((baseUri))/deats/V1/deal/494058190045?includePropertyVersionstrucE Docs Params • Authorization • Headers 12Body Scriots SettingsQuery Paramsv includePropertyVersionsobiectTye© Scarchlollietmnr sayedet get history of prceCEr RendCr det meetinoet eonther with mhR SaveV COLLECYIONS› HubspotKera don runttaration nin Sastch HeOaRWeonocoksVeOAuthcrm/v3/properties/(object Type>a groups?-olOoery Namev ut Read all orooartiesee successtul operationen An error occurredCEAGANTicketsv Uselupest lilter por comanny /onty ocen dent stnoeywwendademens do associtoyoCin anandamsnte did aetocitkd on comode.verceinisto or docciy - oedeooewsuccasstul .onerat.or5e An error occurred.EET aCtUSOreCET SF oauthetr Mentind cntcomac cat mastied> сt Read all properties new> cy Road all oronertios olalaald call dispositionscrtliet with aesociationscer list engagements oldCnrecaot ancadementcEt get dealet Got Enaagement (vllPATCи httos://api.hubapi.com/engagements/V1/engagements/24927395231PaTCHhttos:/api.hubapi.com/engagements/v1/enoaoements/24927395231CTUonAte deslicharCMMIDANIENTCSPECS> FLOWSOConndettCoasde em aniooDetcrictionSondCookiespulkEotRoduJSON6а580г8Вг866бдатавтазазхалаваа> Previewpy VisualizedPropoxtvCoroutor"uselzoosca paspersiscencelanes capoeueSouxceUpscrcanbeployable: CrnPublzcobnects-service•webhew cusuintle thelochdtont."sourceld": "StageCalculatedPropertiesRollup*,"osae sy cuematve oime sinelos on ton eStageCalculatedPropertiesRollup",LOULAIEUosteoceDeisanows0yreoynstad.700 ok. 270ms. 41.76 KRwn Save Resnons,Asab# 10122AJE XGiobnts Montt Tookenem...
|
iTerm2
|
NULL
|
NULL
|
87385
|
|
87384
|
JAlPostmanFileEditViewWindowActivity MonitorAll Pr JAlPostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskreplaydWindowServerscreenpipePostman Helper (Renderer)FirefoxCP Isolated Web ContentcoreaudiodPostmanClaudePostman Helper (GPU)bluetoothdlaunchdActivity Monitorlanguage_server_macos_armFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentFirefoxFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentWispr FlowKarabiner-Core-ServiceFirefoxCP Isolated Web ContentiTerm2Wispr Flow Helper (Renderer)FirefoxCP Isolated Web ContentNotion Helper (Renderer)Help% CPU130,6100,451,339,024,814,18,15,35,25,04,43,63,53,02,62,22,12,02,02,01,81,81,71,71,51,41,31,2CPU Time4:27:49,4424:11:38,366:42:53,598:08:38,893:52:11,267:36,3641:30,381:02:07,533:55,7029:48,8142,9321:14,8919:39,369:41,5912:12,8324:13,5211:53,941:04,391:50:08,7432:34,6917:05,784:29,8220:56,0020:08,671:05:05,885:47,0410:22,6025:20,26System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+18,10%34,40%47,50%CPU• 0.(all100% <78• Thu 28 May 18:34:44ED→Describe what you are looking forJiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana NetsevaGo Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko Kashinski. Galya Dimitrova: Todor Stamatov. Steliyan GeorgievEo VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...::: AppsJira Cloudlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87384
|
|
87383
|
JAlPostmanFileEditViewWindowActivity MonitorAll Pr JAlPostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskreplaydWindowServerscreenpipePostman Helper (Renderer)FirefoxCP Isolated Web ContentcoreaudiodPostmanClaudePostman Helper (GPU)bluetoothdlaunchdActivity Monitorlanguage_server_macos_armFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentFirefoxFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentWispr FlowKarabiner-Core-ServiceFirefoxCP Isolated Web ContentiTerm2Wispr Flow Helper (Renderer)FirefoxCP Isolated Web ContentNotion Helper (Renderer)Help% CPU130,6100,451,339,024,814,18,15,35,25,04,43,63,53,02,62,22,12,02,02,01,81,81,71,71,51,41,31,2CPU Time4:27:49,4424:11:38,366:42:53,598:08:38,893:52:11,267:36,3641:30,381:02:07,533:55,7029:48,8142,9321:14,8919:39,369:41,5912:12,8324:13,5211:53,941:04,391:50:08,7432:34,6917:05,784:29,8220:56,0020:08,671:05:05,885:47,0410:22,6025:20,26System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp ,63%35,02%35,35%CPUMiMHomeDMsActivityFilesLater..•More+• 0.(all100% <78• Thu 28 May 18:34:42ED→Describe what you are looking forJiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana NetsevaGo Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko Kashinski. Galya Dimitrova: Todor Stamatov. Steliyan GeorgievEo VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...#: AppsJira Cloudlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87383
|
|
87382
|
PostmanFileEditViewWindowActivity MonitorAll Proce PostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskreplaydscreenpipePostman Helper (Renderer)WindowServerFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentcoreaudiodFirefoxActivity MonitorPostman Helper (GPU)bluetoothdsyspolicydPostmanlaunchservicesdlanguage_server_macos_armtccdFirefoxCP Isolated Web ContentWispr FlowiTerm2FirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentRescueTimeFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContenttrustdWispr Flow Helper (Renderer)Help% CPU145,5113,557,653,625,223,09,56,86,2CPU Time4:27:42,5024:11:33,036:42:50,863:52:09,947:35,618:08:36,8241:29,9532:34,581:02:07,251:50:08,649:41,4342,7021:14,6917:31,073:55,421:04:34,9112:12,709:19,5217:05,684:29,721:05:05,811:04,2820:08,587:51,6444:01,4713:41,8415:05,875:46,97System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+17,55%24,65%57,80%CPUED→Jiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana Netseva€o Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko KashinskiGalya Dimitrova: Todor Stamatov. Steliyan Georgievto VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...#: AppsJira Cloud• 0.(all100% <78• Thu 28 May 18:34:39Describe what you are looking forlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87382
|
|
87381
|
PostmanFileEditViewWindowActivity MonitorAll Proce PostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskreplaydscreenpipePostman Helper (Renderer)WindowServerFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentcoreaudiodFirefoxActivity MonitorPostman Helper (GPU)bluetoothdsyspolicydPostmanlaunchservicesdlanguage_server_macos_armtccdFirefoxCP Isolated Web ContentWispr Flowierm2FirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentRescueTimeFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContenttrustdWispr Flow Helper (Renderer)Help% CPU145,5113,557,653,625,223,09,56,86,2CPU Time4:27:42,5024:11:33,036:42:50,863:52:09,947:35,618:08:36,8241:29,9532:34,581:02:07,251:50:08,649:41,4342,7021:14,6917:31,073:55,421:04:34,9112:12,709:19,5217:05,684:29,721:05:05,811:04,2820:08,587:51,6444:01,4713:41,8415:05,875:46,97System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+25,06%30,20%44,74%CPUED→Jiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana NetsevaGo Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko KashinskiGalya Dimitrova: Todor Stamatov. Steliyan GeorgievCo VesG. MiraP.. Nikolay Yankov4o James GrahamLukas Kovalik y...#: AppsJira Cloud• 0.(all100% <78• Thu 28 May 18:34:36Describe what you are looking forlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva+...
|
iTerm2
|
NULL
|
NULL
|
87381
|
|
87380
|
8R Hubspot ~Your team is now on the Free plan with 8R Hubspot ~Your team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stage((baseUri))/deats/V1/deal/494058190045?includePropertyVersions=trucE Docs Params • Authorization • Headers 12Body Scriots SettingsQuery Paramsv includePropertyVersionsobiectTyescarchlollietmnr sayeeoehtorooeGET ReadCr det meetino4oo0sLXThu 28 May 18:34:34ct eonthet with ihR SaveV COLLECYIONE› HubspotKera don runttaration nin Sastch HeOaRWeonocoksVeOAuthcrm/v3/properties/(object Type>E groups?orooery namev at Read all oropartiesea successful operationenAn error occurredCEAGANTicketsv Uselupest lilter por comanny / onty ocen dent sthoeycEt engagements old associated by deaCin anandamante did aetocitkd on comode.eroeiinistom or docciy eoeaertetwsuccesstul oneratione. An error occurred.CET GCtUROreCET SF oauthCir Menrind outcomac car maste.> сt Read all properties newcey Road all oronertios.oldaald call dispositionscrtliet with aesociationscet list engagements okCnracaot ancadementct get dealet Got Enaagement (vllPATCи [URL_WITH_CREDENTIALS] *StageCalculatedPropertiesRollup*,culatedPropertiesRollup",CULAIEUpersistenceTimestano*: 1779301974209,sourcellostreandeolovable*: *Pioclineskafka-pioclinesesco-ue-xollup-listener--Giobnts Montt Tookenem...
|
iTerm2
|
NULL
|
NULL
|
87380
|
|
87379
|
IAIPostmanFileEditViewWindowActivity MonitorAll Pr IAIPostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskreplaydPostman Helper (Renderer)WindowServerscreenpipeFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentPostman Helper (GPU)coreaudiodFirefoxPostmanbluetoothdActivity Monitorlaunchservicesdlanguage_server_macos_armFirefoxCP Isolated Web ContentClaudeFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentWispr FlowKarabiner-Core-ServiceWispr Flow Helper (Renderer)FirefoxCP Isolated Web ContentiTerm2FirefoxCP Isolated Web ContentSlackFirefoxHelp% CPU142,984,458,741,336,610,28,78,06,35,55,44,23,73,53,22,62,32,12,12,01,91,61,51,51,41,41,31,2CPU Time4:27:34,8224:11:27,036:42:47,827:34,288:08:35,613:52:07,1141:29,4444:01,3842,491:02:06,921:50:08,373:55,2621:14,539:41,221:04:34,7512:12,5517:05,5529:48,4820:08,471:04,174:29,6020:55,865:46,8925:35,151:05:05,6913:41,7514:08,3914:29,49System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+17,44%30,63%51,94%CPUED→Jiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi.Direct messages(L. Iliyana NetsevaGo Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko KashinskiGalya Dimitrova: Todor Stamatov. Steliyan Georgievto VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...#: AppsJira Cloud• 0.(all100% <78• Thu 28 May 18:34:33Describe what you are looking forlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87379
|
|
87378
|
IAIPostmanFileEditViewWindowActivity MonitorAll Pr IAIPostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskreplaydPostman Helper (Renderer)WindowServerscreenpipeFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentPostman Helper (GPU)coreaudiodFirefoxPostmanbluetoothdActivity Monitorlaunchservicesdlanguage_server_macos_armFirefoxCP Isolated Web ContentClaudeFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentWispr FlowKarabiner-Core-ServiceWispr Flow Helper (Renderer)FirefoxCP Isolated Web ContentiTerm2FirefoxCP Isolated Web ContentSlackFirefoxHelp% CPU142,984,458,741,336,610,28,78,06,35,55,44,23,73,53,22,62,32,12,12,01,91,61,51,51,41,41,31,2CPU Time4:27:34,8224:11:27,036:42:47,827:34,288:08:35,613:52:07,1141:29,4444:01,3842,491:02:06,921:50:08,373:55,2621:14,539:41,221:04:34,7512:12,5517:05,5529:48,4820:08,471:04,174:29,6020:55,865:46,8925:35,151:05:05,6913:41,7514:08,3914:29,49System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+20,25%27,39%52,35%CPUED→Jiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi.Direct messages(L. Iliyana NetsevaGo Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko KashinskiGalya Dimitrova: Todor Stamatov. Steliyan Georgievto VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...#: AppsJira Cloud• 0.(all100% <78• Thu 28 May 18:34:31Describe what you are looking forlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87378
|
|
87377
|
wunicowX HubspotYour team is now on the Free plan wunicowX HubspotYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stage((baseUri))/deats/V1/deal/494058190045?includePropertyVersionstrucE Docs Params • Authorization • Headers 12)Body Scriots SettingsQuery ParamsinciuderropertyversconobiectTyeerpendoneV COLLECYIONSEngsgements› HubspotKera don run› Iteration run Search HSOaRWeonocoksVeOAuthcrm/v3/properties/(object Type>a groups?-olOoery Namev ut Read all orooartiesee successtul operationen An error occurred• ЗLАKCHTicketsv Uselupest lilter por comanny /onty ocen dent stnoeywwendademens do associtoyoCin anandamsnte did aetocitkd on comode.verceinisto or docciy - oedeooewsuccesstul oneration5e An error occurred.EET aCtUSOreCET SF oauth> сt Read all properties new> cy Road all oronertios olalaald call dispositionscrtlist with aesociation.cet list engagements okCTTACAOT Anoadementct get dealet Got Enaagement (vllPATCи httos://api.hubapi.com/engagements/V1/engagements/24927395231PaTCHhttos:/api.hubapi.com/engagements/v1/enoaoements/24927395231CTUoAAte dolCAaCMMIDANIENTCSPECS> FLOWSOlConnnettCoasdle em antooKEJSONv60B8Preview VisualizePAWWAITAS, 46396305"dealid*: 494058196645.as":1opanysos.assocfatedbealds*: marsocintedTicketide". mtimestamo*: 1779301965149,CalculatedPropertyComputer",wwwono.sckc.rnno8hho.songoddcdbn7o0sLXThu 28 May 18:34:30@ Searcha menim m sordCoe hitoroore eOET ReadCedet meetinoR SaveCookiesRuk EOtValuttrueValueDetcriction700 ok. 270ms. 41.76 KRan Save Resnons?Giobnts Montt Tookemem...
|
iTerm2
|
NULL
|
NULL
|
87377
|
|
87376
|
PostmanFileEditViewWindowActivity MonitorAll Proce PostmanFileEditViewWindowActivity MonitorAll ProcessesProcess Namekernel_taskPhpStormreplaydWindowServerscreenpipePostman Helper (Renderer)PostmanFirefoxCP Isolated Web ContentlaunchservicesdcoreaudiodClaudePostman Helper (GPU)FirefoxbluetoothdActivity MonitorFirefoxCP Isolated Web Contentlanguage_server_macos_armFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentWispr FlowFirefoxCP Isolated Web ContentKarabiner-Core-ServiceFirefoxCP Isolated Web ContentSlack Helper (Renderer)iTerm2Wispr Flow Helper (Renderer)FirefoxBitwardenHelp% CPU121,4111,374,251,146,645,512,29,56,65,7CPU Time24:11:22,574:27:27,266:42:44,728:08:33,673:52:06,577:32,093:55,0441:28,981:04:34,581:02:06,6329:48,3742,161:50:08,0821:14,339:41,034:25,1912:12,4120:08,3617:05,434:29,501:04,0620:55,7725:35,081:00:51,661:05:05,625:46,8114:29,422:33,61System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+24,11%30,99%44,90%CPUED→Jiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana NetsevaGo Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko Kashinski. Galya Dimitrova: Todor StamatovRo Steliyan Georgievto VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...#: AppsJira Cloud(all100% <78• Thu 28 May 18:34:30Describe what you are looking forlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87376
|
|
87375
|
wurcowX HubspotwYour team is now on the Free plan wurcowX HubspotwYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stage((baseUri))/deats/V1/deal/494058190045?includePropertyVersionstrucE Docs Params • Authorization • Headers 12Body Scriots SettingsQuery ParamsinciuderrodertyverstonobiectTyeerpendoneV COLLECYIONSEngsgements› HubspotKera don run› Iteration run Search HSOaRWeonocoksVeOAuthcrm/v3/properties/(object Type>a groups?-olOoery Namev ut Read all orooartiesee successtul operationenAn error occurred• ЗLАKCHTicketsv Uselupest lilter por comanny /onty ocen dent stnoeywnendademens oo associa.tovoCii anandsmante did actocitid ou comodeyveroeinistomv or docchy eoou sooewsuccasstul .onerat.or5e An error occurred.EET aCtUSOreCET SF oauthCit Meatind outconac cat mastied> сt Read all properties new> cy Road all oronertios olalanald call dispositionscrtliet with aesociationscet list engagements okCTTACAOT Anoadementct get dealet Got Enaagement (vllPATCи httos://api.hubapi.com/engagements/V1/engagements/24927395231PaTCHhttos:/api.hubapi.com/engagements/v1/enoaoements/24927395231CTUoAAte dolCAaCMMIDANIENTCSPECS> FLOWSOlConnnettCoasdle em antooBodyCookies1SJSON v8683608888> Previewpy VisualizePAWWAITAS, 46396305*dealId*: 494058190645as":1iatedCompanyIds*: [assocfatedbealds*: m"arsocintedhsicketide": mtimestamo*: 1779301965149,CalculatedPropertyComputer",wwwono.sckc.rnno8hho.songoddcdbnThu 28 May 18:34:23@ Searcha menim m sordCoe hitoroore eOET Readcedet meetinoR SaveCookiesValuttrueValueDetcrictionRuk EOt700 0K • 270mg • 41.76 KR -# en Save Resconsa= 0100Giobnts Montt Tookemem...
|
iTerm2
|
NULL
|
NULL
|
87375
|
|
87374
|
IAlPostmanFileEditViewWindowActivity MonitorAll Pr IAlPostmanFileEditViewWindowActivity MonitorAll ProcessesProcess Namekernel_taskPhpStormscreenpipeWindowServerreplaydPostman Helper (Renderer)FirefoxFirefoxCP Isolated Web ContentFirefoxcoreaudiodClaudelaunchservicesdbluetoothdActivity Monitorlanguage_server_macos_armPostmanFirefoxCP Isolated Web ContentSlackFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentPostman Helper (GPU)FirefoxCP Isolated Web ContentWispr FlowiTerm2FirefoxCP Isolated Web ContentlaunchdlogdNotion Helper (Renderer)Help% CPU163,1142,460,952,639,023,910,39,87,36,25,04,24,23,83,43,43,02,72,52,32,32,22,12,11,91,81,71,6CPU Time24:11:16,194:27:21,413:52:04,128:08:30,986:42:40,827:29,701:50:07,8841:28,4814:29,351:02:06,3329:48,081:04:34,2421:14,139:40,8512:12,243:54,4013:41,6414:08,301:03,9617:05,3041,9620:08,234:29,391:05:05,5425:35,0019:39,1117:18,7625:20,05System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+30,04%41,42%28,54%CPU• 0.(all100% <78• Thu 28 May 18:34:22ED→Describe what you are looking forJiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana Netseva€o Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko KashinskiGalya Dimitrova: Todor StamatovRo Steliyan Georgievto VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...::: AppsJira Cloudlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87374
|
|
87373
|
VieWwurcowX HubspotwYour team is now on the Free p VieWwurcowX HubspotwYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stagebaseUrill/deats/V1/deal/49405819004SPincludePropertyVersionsntrucE Docs Params • Authorization • Headers 12 Body • ScriotsSettinasQuery Paramsv includePropertyVersionsobiectTye@ SearchCtpendeoeollietmnn sayeCoe hitoroore eCEr RendV COLLECYIONSEngsgements› HubspotKera don runttaration nin Sastch HeOaRWeonocoksVeOAuthcrm/v3/properties/(object Type>a groups?-olOoery Namev ut Read all orooartiesee successtul operationen An error occurredRotcteae8 orooey• ЗLАKCHTickarsv Uselupest lilter por comanny /onty ocen dent stnoeywwendademens do associtoyoCin anandamsnte did aetocitkd on comodeyverceinisto or docciy - oedeooewsuccasstul .onerat.or5e. An error occurred.EET aCtUSOreAT SE ASntk> сt Read all properties new> cy Road all oronertios olalcet old call dispositionscrtliet with aesociationscer list engagements oldCnrecaot ancadementat get dealet Got Enaagement (vllPATCи httos://api.hubapi.com/engagements/V1/engagements/24927395231PaTCHhttos:/api.hubapi.com/engagements/v1/enoaoements/24927395231CTUonAte deslicharCMMIDANIENTCSPECS> FLOWSOlConnnettCoasdle em antooDetcrictionValuRescanse" Hнom yt Sand e Get a upcessful resoons2) Send + Visualize respons)% Send + Write test:40 17o0sLXThu 28 May 18:34:22cedet meetinoR SaveSondCookiesBulk EditGlobals Vault Toos ,d=g...
|
iTerm2
|
NULL
|
NULL
|
87373
|
|
87372
|
VieWwurcowX HubspotwYour team is now on the Free p VieWwurcowX HubspotwYour team is now on the Free plan with 1 admin. You retain editing access and other members are read-only. View team permissicas to see who can edit, or ungrade to restore collaborationUseful › get history of property - deal stagebaseUrill/deats/V1/deal/253868114162?includePropertyVersionstrucE Docs Params • Authorization • Headers 12 Body • ScriotsSettinasQuery Paramsv includePropertyVersionsobiectTye@ SearchCtpendeoeollietmnn sayeCoe hitoroore eCEr RendV COLLECYIONSEngsgements› HubspotKera don runttaration nin Sastch HeOaRWeonocoksVeOAuthcrm/v3/properties/(object Type>a groups?-olOoery Namev ut Read all orooartiesee successtul operationen An error occurredRotcteae8 orooey• ЗLАKCHTickarsv Uselupest lilter por comanny /onty ocen dent stnoeywwendademens do associtoyoCin anandamsnte did aetocitkd on comodeyverceinisto or docciy - oedeooewsuccasstul .onerat.or5e. An error occurred.EET aCtUSOreAT SE ASntk> сt Read all properties new> cy Road all oronertios olalcet old call dispositionscrtliet with aesociationscer list engagements oldCnrecaot ancadementat get dealet Got Enaagement (vllPATCи httos://api.hubapi.com/engagements/V1/engagements/24927395231PaTCHhttos:/api.hubapi.com/engagements/v1/enoaoements/24927395231CTUonAte deslicharCMMIDANIENTCSPECS> FLOWSOlConnnettCoasdle em antooDetcrictionValuRescanse" Hнom yt Sand e Get a upcessful resoons2) Send + Visualize respons)% Send + Write test:40 17o0sLXThu 28 May 18:34:19cedet meetinoR SaveCookiesBulk EditGlobals Vault Toos ,d=g...
|
iTerm2
|
NULL
|
NULL
|
87372
|
|
87371
|
IAlPostmanFileEditViewWindowActivity MonitorAll Pr IAlPostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskWindowServerreplaydClaude Helper (Renderer)ClaudeFirefoxCP Isolated Web ContentscreenpipecoreaudiodFirefoxbluetoothdlaunchdActivity Monitorlanguage_server_macos_armFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentKarabiner-Core-ServiceWispr FlowFirefoxCP Isolated Web ContentiTerm2WindowManagerWispr Flow Helper (Renderer)Slack Helper (Renderer)Control CentrelogdBitwardenPostman Helper (Renderer)Help% CPU166,0109,854,050,410,79,18,5CPU Time4:27:13,8924:11:07,578:08:28,216:42:38,7611:30,6929:47,8241:27,963:52:00,901:02:06,011:50:07,3421:13,9119:39,019:40,6512:12,0613:41,481:03,8217:05,1820:55,604:29,2820:08,111:05:05,433:28,235:46,651:00:51,5020:50,4117:18,672:33,547:28,44System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp HomeDMsActivityFilesLater..•More+35,34%34,36%30,31%CPU(all100% <78• Thu 28 May 18:34:19ED→Describe what you are looking forJiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana Netseva€o Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko KashinskiGalya Dimitrova: Todor StamatovRo Steliyan GeorgievEo VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...::: AppsJira Cloudlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
iTerm2
|
NULL
|
NULL
|
87371
|
|
87370
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
ServiceTest
Run 'ServiceTest'
IAlPostmanFileEditViewWindowActivity MonitorAll ProcessesProcess NamePhpStormkernel_taskWindowServerreplaydClaude Helper (Renderer)ClaudeFirefoxCP Isolated Web ContentscreenpipecoreaudiodFirefoxbluetoothdlaunchdActivity Monitorlanguage_server_macos_armFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentFirefoxCP Isolated Web ContentKarabiner-Core-ServiceWispr FlowFirefoxCP Isolated Web ContentiTerm2WindowManagerWispr Flow Helper (Renderer)Slack Helper (Renderer)Control CentrelogdBitwardenPostman Helper (Renderer)Help% CPU166,0109,854,050,410,79,18,5CPU Time4:27:13,8924:11:07,578:08:28,216:42:38,7611:30,6929:47,8241:27,963:52:00,901:02:06,011:50:07,3421:13,9119:39,019:40,6512:12,0613:41,481:03,8217:05,1820:55,604:29,2820:08,111:05:05,433:28,235:46,651:00:51,5020:50,4117:18,672:33,547:28,44System:User:Idle:Threads CPUMemoryEnelIdle Wake-UpsKp ,08%40,09%27,83%HomeDMsActivityFilesLater..•More+(all100% <78• Thu 28 May 18:34:16ED→Describe what you are looking forJiminny ...# infrastructure_dev# jbu-team-info# jiminny-bg# platform-team# platform-tickets# product_launches# random# releases# support# thank-yous# the_people_of jimi...Direct messages(L. Iliyana Netseva€o Vasil Vasilev&. Stefka Stoyanovao Stoyan TomovEo Petko KashinskiGalya Dimitrova: Todor StamatovRo Steliyan GeorgievEo VesG. MiraP.. Nikolay Yankovdo James GrahamE Lukas Kovalik y...#: AppsJira Cloudlliyana Netseva6 0MessagesAdd canvas+ok, thank yo.v 2 new messageslliyana Netseva 5:45PMИмам питане и се чудя към кого мога да сеобърна?става дума за deal insightsLukas Kovalik 5:54 PMПитай, ако мога ще отговоряlliyana Netseva 5:56 PMимам сделка която е със статус won но е вclosed losttova e ID-to 04a9cfad-2c87-4453-9e72-20aeb78ccf8d na sdelkataLukas Kovalik 6:00 PMUS или EU (edited)Iliyana Netseva 6:01 PMeuLukas Kovalik 6:27 PMвиждам че си отворила тикет, ще го видя утренещо се умазало sync на stagesмисля клиент е променил нещо трябва да говидя в самия hubspotlliyana Netseva 6:32 PMNo worries, thank you!Newи приятна почивкаMessage Iliyana Netseva...
|
PhpStorm
|
faVsco.js – Hubspot/Service.php
|
NULL
|
87370
|
|
87369
|
Project: faVsco.js, menu
#12121 on JY-20963-fix-im Project: faVsco.js, menu
#12121 on JY-20963-fix-import-on-deleted-entity, menu
Start Listening for PHP Debug Connections
ServiceTest
Run 'ServiceTest'
Debug 'ServiceTest'
More Actions
JetBrains AI
Search Everywhere
IDE and Project Settings
rapstomEV faVsco,ls ~ProjectvViewCooc#12121 on JY-20963-fx-ImWindoweteamoremo tewins© ResponseNormalize.phpgsevice.on:esunchiorcdon.onGSUNCKOlOhCWWWKeweonooinlneochhoe2133› E IntegrationApp>O Listeners› E MetadataMmkeurayocryict.on© CachedCrmServiceDecorator.php© ServiceTest.php© DeleteObjects Trait.phpu rottoniuorrid.pnpRecordSelector.php(C) Hubspot/Service.php X OpportunitySyncTrait.phg© Activity.php©CrmEntityRepository.php1Usogdpublic function natchActivityEngagementtype(Activity Sactivity): stringf...1 usageprivate function assignCrn0wner(User Suser, ActivityContract Sactivity): PProfile(...}› E Pipedrivev SalesforceaFelds>aopoortunityVatchen2157OpportunitySyncStrategy2159> ProspectsearchStrategyServiceTraits2161 @ >C) e entond©[EMAIL]© PayloadBuilder.php© Profile.php© QueryBullder.phpprevore sroee Tunceion gecuestsrape einescnopotncloe odrangreturn self::API_URL . self::ENDPOINT_PIPELINES . self::PIPELINE_OBJECT_TYPE_DEALS;public function venifyTaskExists(Activity Sactivity): bool...ServicasOutpujiminny.opportunities 4tii jiminny stagesGin PauuttvaaamsaBagase4 console 1 s 650 msEUSOrSS5% mev A|iminny@localhostHS localASFv pRODA consoleSTAGINGA consoleDockerDuvid (UUID with time-low and time-high swapped)( tean_id@crn_configuration_idHr account& stage_1dstage_updated_at@record_type_idcrn_provider_idousenToouner_idnanevaluecurrency_codeDis_closediis nooMelose date768142384a9cfad-2c87-4453-9e72-20aeb78ccf8d5SS475BB3aT8:8428612826-85-20 18:36:59455649485819984538848855Centiva Capital - EU HY/IG28608.88probability100Wew oulteoneet today RayE custom.logA console (PROD)DMO00-1725E laravel.logA SF (iminny@localhost)HSJocal ([iminny@localhost)A console (EU] * (B users (EU]A console [STAGING)createo,at > 2020-09-2d8 jiminny~031 49 A29 X3 X109 A Vsallect *mm acutes onden hy sadese1727-4120,17291 000 0 100M00 1800 000 00 1 8001 8117331733 vBEE21746MІIN11ІРНIsAllec * mn llsang nhene nane uke WsthnaSELECT * FROM opportunities WHERE Uuid_to_bin('04a9cfad-2C87-4453-9e72-20aeb78ccf8d')=select * from teams mhere id = 555;select * from stages nhere tean_id = 555;SELECTCONCAT(U.$d, GASE WHEN U.1d = t.omner_id THEN • (ouner) ' ELSE "* END) AS user_1d=sa.*t.ouner_id FROM social_accounts saJOIN users on u.id = sa.sociable_idJOIN teans t 1.n<->1: on t.id = u.tean_idWHERE v.team_id = 100 and sa-provider = 'hubspot":ПВТЕ ПІРеНCascadeles Orcnnworeebeeionhnves dohtine OooondNow look at ResponseNoren ize::norms Tipeoea Staoe)orobabuty" s Tloat (Coatal"cetadata""nrobabto tyteohRoot eause: moorStages overwmes D3 probability with tuoSpots valueThe fow is,4 (sGodhU ServiceTest ~TO0У L7Inu cowoy 1o:s4.1+0.• •• :¿4-0Nwneuleime"hhek hiresensnd....
|
PhpStorm
|
faVsco.js – Hubspot/Service.php
|
NULL
|
87369
|
|
87368
|
rapstomEV favscojs ~ProjectvView#12121 on JY-20963 rapstomEV favscojs ~ProjectvView#12121 on JY-20963-fix-InCoocWindowcteamoremo tewine© ResponseNormalize.phpMmAeuryochyict.ongsevice.on:esunchicracoon.onGSUNCKOlOhCWWWKeweonooinlneochhoe2133› E IntegrationApp>O Listeners1 usage› E Metadata© CachedCrmServiceDecorator.php© ServiceTest.phpRecordSelector.php(C) Hubspot/Service.php X OpportunitySyncTrait.phg© CrmEntityRepository.phgclass service excenos baseservace olesencs1Usogdpublic function natchActivityEngagementType(Activity Sactivity): stringf...private function assignCrnOwner(User Suser, ActivityContract Sactivity): ?Rcof$le(...}› E Pipedrivev SalesforceaFelds>aopoortunityVatchen2157OpportunitySyncStrategy2159> ProspectsearchStrategyServiceTraitsCeentone2161 @ >©[EMAIL]© PayloadBuilder.php© Profile.php© QueryBullder.phpprevore sroee Tunceion gecuestsrape einescnopotncloe odrangreturn self::API_URL . self::ENDPOINT_PIPELINES . self::PIPELINE_OBJECT_TYPE_DEALS;public function venifyTaskExists(Activity Sactivity): bool...Servicas+oc exvaaramss4 console 1 s 650 mgEUSOrSS5% mev A|iminny@localhostHS localASFv pRODA consoleSTAGINGA consoleDockerU ServiceTest ~E custom.logA console (PROD)DMO00-[CREDIT_CARD],1729ПMIM TII TE laravel.logA SF (iminny@localhost)HSJocal ([iminny@localhost)A console (EU] * (B users (EU)A console [STAGING)1733 v175%a- aamainticreateo,at > 2020-09-2d8 jiminny~031 49 A29 X3 X109 A Vsallect *mm acutes onden hy sadesesaller * mmllisans nhene nane uke WsthnaSELECT * FROM opportunities WHERE uuid_to_Din('04a9cfad-2C87-4453-9e72-20aeb78ccf8d*)=select * from teams where id = 555;select * from stages nhere tean_id = 555;SELECTCONCAT(U.$d, GASE WHEN U.1d = t.omner_id THEN • (ouner) ' ELSE "* END) AS user_1d=sa.*t.ouner_id FROM social_accounts saJOIN users on u.id = sa.sociable_idJOTN teams + 1..n<->1: on taid = u.tean ioWHERE v.team_id = 100 and sa-provider = 'hubspot":1III]HIGНE BIBITCascadeles Orcnnworeeoeionhnves dohtine OooondTO0%7Ao nu comoy 1o:54.14+0.orobabuty" s Tloat (Coatal"cetadata""nrobabto tyteohThis ks the root causdRoot eause: moorStages overwmes D3 probability with tuoSpots valueThe fow is,4 (sGodh• •• :¿4-0Outpujiminny.opportunities 4tii jiminny stage:(B Result 12 xDuser_idenailDidMsociable stoOprovider_user_idprovider_user_tokenprovider_refresh_tokenexpires18026 (ouner)alexroocunecoonelwecreocon38581882%47027227eu1-8b33-482c-4414-aae8-588da6a092eb1779982947CPnpgfrnMxIZQLNQML8kQEwrAgиACAKUAhIJBB4BAQE0BxjZso0MIJuothYo1KwCMhSF0ZwJpK24mUzeGLZeL2wGD97itToyQLNQML8KQEwrA1UACBkGawEFThwBARIBAQEEATEEAQEBAQEBAQEBAQUBE99BAQEBAYLCFEpBVL0P2jpiRhN0cP4bCtvZyBULSgNLdTFSAFoAYABon612FnAAeAAererrech token exos resproviderstateconnectedauth_scope<null>Dretry_after<null>created_at2025-11-18 14:08:10updated_at2826-05-28 15:12:27provider_user_token_encryptedLeyJpdst6TLNXeFRWDTZRb61yZUE2eVp0QnE4a6c9PSIsInzhbHVUJ|OidktIMnZ2U6Y3L0t423B1T=VJNkxDDU9XW/TRTSnVDcmhBKzc2UkSHTL.hmYU9rbkM2ZHFvSWRNU1LMR61HH2tERU43SHRORHJRVStvYBdKK3FnUFF{WFhpV21GWnTvVHRVZ2B40kxXM61YCBRSaHZ=Y304UL2WBDSTOprovider_refresh_token_encryptedeyJpd¡[6InMгUHhGZzF«Z18xUFZT0HN3ZEtEVWс9РSIsInZhbHVLIjOÍaUsSLzBX™₩9GT2dqZ®dhd™Q2a1Q5SWgгNjB1eHFCaTkSTENпVnNPV2h0YяFQb1U3eWV=YæsґU0hwVzVKсEp2dCIsIв1hYy[6ImU3NTN{NjgиNnIxNWE1M2NkNOI1ZWNnMGUSY2F{YnYSOTB£YTZnZGFnMnYyZTY3ZT_Mencrvotion key (Hex)8x010283007822673352371526FE0C9FS17F790F4CCE3FCC2CEECFA48AF34D52AAB42113A7A601283254F21349E978AB1232AAD295315F0000886E386C86092A864886F780018786A85F3050020100305886092A864886F700010701301E8689688648016583848123011848C_y Il View pull request (today 16:12)Woderd Thsms 215878 UTE-R AiA enano...
|
PhpStorm
|
faVsco.js – Hubspot/Service.php
|
NULL
|
87368
|