|
85917
|
2949
|
6
|
2026-05-28T13:28:55.314911+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974935314_m2.jpg...
|
PhpStorm
|
faVsco.js – Service.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
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
Sync Changes
Hide This Notification
Code changed:
Hide
12
246
3
21
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Services\Crm\Salesforce;
use Carbon\Carbon;
use Exception;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Events\Dispatcher;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Jiminny\Component\Country\CountriesMap;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Contracts\Repositories\TeamRepository;
use Jiminny\Contracts\Services\Crm\FetchRelatedActivityInterface;
use Jiminny\Contracts\Services\Crm\ImportsBusinessProcessesInterface;
use Jiminny\Contracts\Services\Crm\LayoutManagementInterface;
use Jiminny\Contracts\Services\Crm\MatchCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\Provider\SalesforceBatchSyncInterface;
use Jiminny\Contracts\Services\Crm\Provider\SalesforceInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityLookupInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityManipulationInterface;
use Jiminny\Contracts\Services\Crm\RemoteNoteEntityManipulationInterface;
use Jiminny\Contracts\Services\Crm\SearchTaskInterface;
use Jiminny\Contracts\Services\Crm\SendSummaryToCrmInterface;
use Jiminny\Contracts\Services\Crm\SettingsInterface;
use Jiminny\Contracts\Services\Crm\SupportsObjectTypeParseInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmProfileRecordTypesInterface;
use Jiminny\Contracts\Services\Crm\VerifyTaskExistsInterface;
use Jiminny\Enums\CrmObject;
use Jiminny\Events\Activities\Crm\LeadConverted;
use Jiminny\Exceptions\CrmException;
use Jiminny\Exceptions\HttpBadRequestException;
use Jiminny\Exceptions\HttpNotFoundException;
use Jiminny\Exceptions\NoResultsException;
use Jiminny\Exceptions\ServiceUnavailableException;
use Jiminny\Jobs\Crm\NoteObject;
use Jiminny\Jobs\Crm\MatchActivitiesToNewOpportunity;
use Jiminny\Models\Account;
use Jiminny\Models\Activity;
use Jiminny\Models\Calendar\CalendarEvent;
use Jiminny\Models\Contact;
use Jiminny\Models\Contracts\ActivityContract;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Models\Crm\Configuration;
use Jiminny\Models\Crm\ContactRole;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\Profile;
use Jiminny\Models\Crm\RecordType;
use Jiminny\Models\Lead;
use Jiminny\Models\Opportunity;
use Jiminny\Models\Playbook;
use Jiminny\Models\SocialAccount;
use Jiminny\Models\Stage;
use Jiminny\Models\TeamSettings;
use Jiminny\Models\User;
use Jiminny\Repositories\Crm\ContactRoleRepository;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\Crm\ProfileRepository;
use Jiminny\Repositories\Crm\RecordTypeFieldValuesRepository;
use Jiminny\Services\Avatar\ProspectPhotoPathService;
use Jiminny\Services\Crm\BaseService;
use Jiminny\Services\Crm\Helpers\ArrayIterator;
use Jiminny\Services\Crm\MatchDomainByEmailInterface;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Services\Crm\ResolveCompanyNameByEmailTrait;
use Jiminny\Services\Crm\Salesforce\Fields\FieldHelper;
use Jiminny\Services\Crm\Salesforce\Fields\FieldTypeConverter;
use Jiminny\Services\Crm\Salesforce\Fields\ValueNormalizer;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\FollowupActivityTrait;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\LogActivityTrait;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\RecordManipulationsTrait;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\SyncFieldsTrait;
use Jiminny\Utils\CurrencyFormatter;
use Jiminny\Utils\StringUtil;
use Ramsey\Uuid\Uuid;
use Sentry\Laravel\Facade as Sentry;
class Service extends BaseService implements
SalesforceInterface,
SalesforceBatchSyncInterface,
SyncCrmEntitiesInterface,
SyncCrmProfileRecordTypesInterface,
ImportsBusinessProcessesInterface,
RemoteEntityManipulationInterface,
FetchRelatedActivityInterface,
SendSummaryToCrmInterface,
MatchDomainByEmailInterface,
SearchTaskInterface,
LayoutManagementInterface,
SettingsInterface,
MatchCrmEntitiesInterface,
RemoteEntityLookupInterface,
SupportsObjectTypeParseInterface,
RemoteNoteEntityManipulationInterface,
VerifyTaskExistsInterface
{
use ResolveCompanyNameByEmailTrait;
use SyncFieldsTrait;
use DeleteObjectsTrait;
use RecordManipulationsTrait;
use ServiceTraits\BatchSyncTrait;
use FollowupActivityTrait;
use LogActivityTrait;
/**
* Note Body Limit for the Old Note-Taking Tool
*
* @var int
*/
private const int CLASSIC_NOTE_MAX_LENGTH = 32000;
/**
* Note Content Limit for the New Notes
*
* @var int
*/
private const int ENHANCED_NOTE_MAX_LENGTH = 50000000;
private const string INSTALLED_PACKAGE_ID = '033Tw0000007bKbIAI';
private const int CACHE_TTL = 600;
private const int TASK_VERIFICATION_CACHE_TTL = 86400; // 1 day - 86400
/**
* @var Client
*/
protected $client;
protected PayloadBuilder $payloadBuilder;
protected QueryHandler $queryHandler;
private OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
public function __construct(
Client $client,
PayloadBuilder $payloadBuilder,
protected Dispatcher $eventDispatcher,
private readonly CountriesMap $countriesMap,
private readonly ProspectPhotoPathService $prospectPhotoPathService,
) {
parent::__construct();
$this->client = $client;
$this->payloadBuilder = $payloadBuilder;
$this->queryHandler = app(QueryHandler::class, [
'client' => $this->client,
'logger' => $this->logger,
]);
$this->opportunitySyncStrategyResolver = app(OpportunitySyncStrategyResolver::class, [
'client' => $this->client,
]);
}
public function getDisplayName(): string
{
return 'Salesforce';
}
public function getJobDelay(): int
{
return 1;
}
protected function getOAuthAccount(User $user): ?SocialAccount
{
return $user->getSocialAccount(SocialAccount::PROVIDER_SALESFORCE);
}
public function verifyTaskExists(Activity $activity): bool
{
$crmProviderId = $activity->getCrmProviderId();
$cacheKey = "crm_task_exists:{$this->config->getId()}:$crmProviderId";
return Cache::remember($cacheKey, self::TASK_VERIFICATION_CACHE_TTL, function () use ($activity, $crmProviderId) {
$playbook = $this->getPlaybookFromActivity($activity);
if ($playbook === null) {
$this->logger->warning('[Salesforce] Cannot verify task - no playbook found', [
'activity' => $activity->getId(),
'crm_provider_id' => $crmProviderId,
]);
return false;
}
$objectType = $playbook->getActivityType() === Playbook::ACTIVITY_TYPE_EVENT ? 'Event' : 'Task';
try {
$record = $this->getRecord($objectType, $crmProviderId, ['Id', 'IsDeleted']);
return ! empty($record) && ($record['IsDeleted'] ?? false) === false;
} catch (HttpNotFoundException|HttpBadRequestException) {
$this->logger->info('[Salesforce] Activity record not found during verification', [
'activity' => $activity->getId(),
'object_type' => $objectType,
'crm_provider_id' => $crmProviderId,
'config_id' => $this->config->getId(),
]);
return false;
}
});
}
public function query(string $queryToRun, array $parameters = []): QueryIterator
{
// Due to poorly designed external calls, this method cannot be entirely removed
return $this->queryHandler->query($queryToRun, $parameters);
}
/*=========== Organization Information ===============*/
/**
* Get a list of all the API Versions for the instance.
*
* @throws CrmException
*
* @return mixed
*
*/
public function getApiVersions()
{
$url = $this->config->crm_base_url . '/services/data';
$response = $this->client->get($url);
return json_decode($response->getBody(), true);
}
/**
* Gets the valid recordTypes for a given Salesforce Object via the describe API.
*/
private function getRecordTypes(string $crmObject): array
{
$url = $this->client->getObjectsUrl() . $crmObject . '/describe';
$response = $this->client->get($url);
$jsonResponse = json_decode($response->getBody(), true);
$fields = [];
foreach ($jsonResponse['recordTypeInfos'] as $row) {
$fields[] = ['recordTypeId' => $row['recordTypeId'], 'default' => $row['defaultRecordTypeMapping']];
}
return $fields;
}
/**
* Convert raw field data into a format compatible with CRM APIs.
*/
public function normalizeValue(string $fieldType, string $fieldValue, bool $internal = false): string
{
return ValueNormalizer::normalize($fieldType, $fieldValue, $internal);
}
/**
* @inheritdoc
*/
public function getDefaultFields(string $activityType): array
{
$fields = [];
$defaultFields = ($activityType === Playbook::ACTIVITY_TYPE_TASK)
? FieldDefinitions::defaultTaskFields()
: FieldDefinitions::defaultEventFields();
// 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
{
// Setup the activity field as the default Type.
/** @var Field $activityField */
$activityField = $this->config->fields()->where([
'crm_provider_id' => 'Type',
'object_type' => $activityType,
])->first();
return $activityField;
}
/**
* @inheritdoc
*/
public function getSupportedPlaybookTypes(): array
{
return [Playbook::ACTIVITY_TYPE_TASK, Playbook::ACTIVITY_TYPE_EVENT];
}
protected function getDefaultFollowupLayoutFields(string $activityType): array
{
$fields = [];
$fieldRepo = app(FieldRepository::class);
$fieldFilter = ($activityType === Playbook::ACTIVITY_TYPE_TASK)
? FieldDefinitions::taskFollowupFieldsFilter()
: FieldDefinitions::eventFollowupFieldsFilter();
foreach ($fieldFilter as $eachFilter) {
$field = $fieldRepo->findOneConfigurationFieldByProperties($this->config, $eachFilter);
// 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();
}
/**
* This one is now called only when ImportActivityTypes is triggered or SyncFieldMetadata executed manually
* Regular sync now uses SharedSyncFieldsTrait -> syncSingleObjectType
* Needs to be replaced later on
*/
public function syncField(Field $field): void
{
try {
if (FieldHelper::isCustomField($field)) {
$query = '
SELECT
Id, Metadata, TableEnumOrId
FROM
CustomField
WHERE
DeveloperName = :fieldName
AND
TableEnumOrId = :fieldType
AND
NamespacePrefix = :namespacePrefix';
// We need to constrain the field lookup to the object, in case it's used in multiple places.
$objectType = \in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true)
? 'activity'
: $field->object_type;
$sfFields = $this->queryHandler->metadata($query, [
'fieldName' => substr($field->crm_provider_id, 0, -\strlen('__c')),
'fieldType' => ucfirst($objectType),
// This is used to ensure we only consider the field within the org, not installed packages.
'namespacePrefix' => 'null',
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
// Sync field metadata.
$metadata = $sfField['Metadata'];
$field->description = mb_strimwidth($metadata['description'] ?? '', 0, 191);
$field->label = mb_strimwidth($metadata['label'] ?? '', 0, Field::LABEL_MAX_LENGTH);
$field->type = $this->convertFieldType($metadata['type'], $field->getEntityName());
$field->is_mandatory = ($metadata['required'] === true);
$field->length = $metadata['length'];
$field->default_value = mb_strimwidth(trim($metadata['defaultValue'] ?? '', '"'), 0, 191);
$field->save();
} else {
$query = '
SELECT
Id, DataType, DeveloperName, Label, Length, Description
FROM
FieldDefinition
WHERE
DurableId = :entityName';
$entityName = $field->getEntityName();
$sfFields = $this->queryHandler->metadata($query, [
'entityName' => $entityName,
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
$convertedType = $this->convertFieldType($sfField['DataType'], $entityName);
$label = mb_strimwidth($sfField['Label'], 0, Field::LABEL_MAX_LENGTH);
if ($field->isBusinessType()) {
$label = 'Opportunity Type';
}
$field->description = mb_strimwidth($sfField['Description'], 0, Field::DESCRIPTION_MAX_LENGTH);
$field->label = $label;
$field->type = $convertedType;
$field->length = $sfField['Length'];
$field->save();
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
private function convertFieldType(string $from, ?string $entityName = null): string
{
$converter = new FieldTypeConverter();
return $converter->convert($from, $entityName);
}
/**
* @inheritdoc
*/
public function importPicklistValues(Field $field): array
{
$values = [];
$fieldValues = [];
try {
if (FieldHelper::isCustomField($field)) {
$query = '
SELECT
Id, Metadata, TableEnumOrId
FROM
CustomField
WHERE
DeveloperName = :fieldName
AND
TableEnumOrId = :fieldType
AND
NamespacePrefix = :namespacePrefix';
// We need to constrain the field lookup to the object, in case it's used in multiple places.
$objectType = \in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true) ?
'activity' : $field->object_type;
$sfFields = $this->queryHandler->metadata($query, [
'fieldName' => substr($field->crm_provider_id, 0, -\strlen('__c')),
'fieldType' => ucfirst($objectType),
// This is used to ensure we only consider the field within the org, not installed packages.
'namespacePrefix' => 'null',
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
$valueSet = $sfField['Metadata']['valueSet'];
if ($valueSet['valueSetName'] === null) {
// Local picklist values can be obtained easily.
$picklistValues = $valueSet['valueSetDefinition']['value'];
} else {
// But for some fields, we just get the Global Value Picklist pointer so need to do more work.
$picklistValues = $this->importGlobalValuePicklistValues($valueSet['valueSetName']);
}
// Import all active values.
foreach ($picklistValues as $i => $sfFieldValue) {
// Setup default value.
if ($sfFieldValue['default']) {
$field->update(['default_value' => $sfFieldValue['valueName']]);
}
// This comes through as null if active (lol).
if ($sfFieldValue['isActive'] !== false) {
$values[] = [
'value' => $sfFieldValue['valueName'],
'label' => $sfFieldValue['valueName'],
'sequence' => $i,
'is_default' => $sfFieldValue['default'],
];
}
}
} else {
$objectFields = $this->getObjectFields($field->object_type);
$fieldId = $field->crm_provider_id;
// Only work with our field of interest.
$objectField = array_filter($objectFields, function ($item) use ($fieldId) {
return $item['name'] === $fieldId;
});
$objectField = array_shift($objectField);
if (empty($objectField['picklistValues']) === false) {
foreach ($objectField['picklistValues'] as $i => $sfFieldValue) {
// Skip inactive values.
if ($sfFieldValue['active'] === false) {
continue;
}
// Setup default value.
if ($sfFieldValue['defaultValue']) {
$field->update(['default_value' => $sfFieldValue['value']]);
}
$values[] = [
'value' => $sfFieldValue['value'],
'label' => $sfFieldValue['label'],
'sequence' => $i,
'is_default' => $sfFieldValue['defaultValue'],
];
}
}
}
$fieldsToPurge = $field->values()->get()->pluck('value')->toArray();
foreach ($values as $value) {
$value['value'] = substr($value['value'] ?? '', 0, 255);
$fieldValues[] = $field->values()->updateOrCreate([
'value' => $value['value'],
], $value);
// Remove this value from the ones we are going to purge.
if (($key = array_search($value['value'], $fieldsToPurge, true)) !== false) {
unset($fieldsToPurge[$key]);
}
}
// Delete the old values that are no longer used.
// Get IDs of the values to be deleted
$valuesToDelete = $field->values()->whereIn('value', $fieldsToPurge);
$valuesToDeleteIds = $valuesToDelete->pluck('id');
if (! $valuesToDeleteIds->isEmpty()) {
$recordTypeFieldValuesRepository = app(RecordTypeFieldValuesRepository::class);
$recordTypeFieldValuesRepository->deleteForCrmFieldValueIds($valuesToDeleteIds->toArray());
// Now safely delete from crm_field_values
$valuesToDelete->delete();
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
return $fieldValues;
}
/**
* Gets values from Global Value Picklists.
*/
private function importGlobalValuePicklistValues(string $picklistName): array
{
$query = '
SELECT
Metadata
FROM
GlobalValueSet
WHERE
DeveloperName = :picklistName
LIMIT 1';
try {
$sfValues = $this->queryHandler->metadata($query, [
'picklistName' => $picklistName,
]);
// There is always 1 result at this point.
$sfValue = $sfValues->current();
return $sfValue['Metadata']['customValue'];
} catch (NoResultsException $noResultsException) {
// Nothing returned.
return [];
}
}
/**
* @inheritdoc
*/
public function syncProfileRecordTypes(): void
{
$objectTypes = [
'lead',
'account',
'contact',
'opportunity',
'task',
'event',
];
foreach ($objectTypes as $objectType) {
try {
$crmRecordTypes = $this->getRecordTypes(ucfirst($objectType));
foreach ($crmRecordTypes as $crmRecordType) {
// If the record type is default and not the Master type, set this.
if ($crmRecordType['default'] && $crmRecordType['recordTypeId'] !== '012000000000000AAA') {
$recordType = $this->config->recordTypes()
->where('crm_provider_id', $crmRecordType['recordTypeId'])
->first();
if ($recordType) {
$this->profile->{$objectType . '_record_type_id'} = $recordType->id;
}
}
}
} catch (HttpNotFoundException $exception) {
Log::error('No access to ' . $objectType . ' object, skipping...');
// XXX: should we log this fact somewhere?
continue;
}
}
if ($this->profile->isDirty()) {
$this->profile->save();
}
}
/**
* Gets business processes.
*/
public function importBusinessProcesses(): void
{
$query = '
SELECT
Id, IsActive, Name, TableEnumOrId
FROM
BusinessProcess
WHERE
TableEnumOrId IN (\'Lead\',\'Opportunity\')';
try {
$sfProcesses = $this->queryHandler->query($query);
// Upsert all processes for the team.
foreach ($sfProcesses as $sfProcess) {
/** @var BusinessProcess $businessProcess */
$businessProcess = $this->config->businessProcesses()->updateOrCreate([
'crm_provider_id' => $sfProcess['Id'],
], [
'team_id' => $this->team->id,
'name' => $sfProcess['Name'],
'type' => $sfProcess['TableEnumOrId'] === 'Lead' ? 'lead' : 'opportunity',
'is_selectable' => $sfProcess['IsActive'],
]);
$this->importBusinessProcessStages($businessProcess);
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
/**
* Gets business process stages.
*/
private function importBusinessProcessStages(BusinessProcess $businessProcess): void
{
$query = '
SELECT
Metadata
FROM
BusinessProcess
WHERE
Id = :processId';
try {
$stages = [];
$sfProcessStages = $this->queryHandler->metadata($query, [
'processId' => $businessProcess->crm_provider_id,
]);
// There is always 1 result at this point.
$sfProcessStage = $sfProcessStages->current();
// Upsert all processes for the team.
foreach ($sfProcessStage['Metadata']['values'] as $sfProcessStage) {
$sanitizedName = urldecode($sfProcessStage['valueName']); // Must decode: "%2C" becomes "," etc.
$stage = $businessProcess->crm->stages()
// This MUST match on label because this API doesn't use API Name.
->where('label', $sanitizedName)
->where('type', $businessProcess->type)
->where('is_selectable', 1)
->first();
if ($stage) {
$stages[] = $stage->id;
}
}
$businessProcess->stages()->sync($stages);
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
/**
* Gets record types.
*/
public function importRecordTypes(): void
{
$query = '
SELECT
Id, IsActive, Name, BusinessProcessId, SobjectType
FROM
RecordType';
try {
$sfRecordTypes = $this->queryHandler->query($query);
// Upsert all record types for the process.
foreach ($sfRecordTypes as $sfRecordType) {
$businessProcess = null;
if ($sfRecordType['BusinessProcessId']) {
$businessProcess = $this->config->businessProcesses()
->where('crm_provider_id', $sfRecordType['BusinessProcessId'])
->first();
}
/** @var RecordType $recordType */
$recordType = $this->config->recordTypes()->updateOrCreate([
'crm_provider_id' => $sfRecordType['Id'],
], [
'team_id' => $this->team->id,
'type' => mb_strtolower($sfRecordType['SobjectType']),
'name' => $sfRecordType['Name'],
'is_selectable' => $sfRecordType['IsActive'],
'business_process_id' => $businessProcess->id ?? null,
]);
$this->importRecordTypeFieldValues($recordType);
}
} catch (NoResultsException $noResultsException) {
// Do nothing.
}
}
/**
* Import record type - field value mappings. This only works for standard fields.
*/
private function importRecordTypeFieldValues(RecordType $recordType): void
{
try {
$query = '
SELECT
Metadata
FROM
RecordType
WHERE
Id = :recordTypeId';
$sfFields = $this->queryHandler->metadata($query, [
'recordTypeId' => $recordType->crm_provider_id,
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
// Sync field metadata.
$picklists = $sfField['Metadata']['picklistValues'];
foreach ($picklists as $picklist) {
$field = $this->config->fields()->where([
'type' => Field::TYPE_PICKLIST,
'object_type' => $recordType->type,
'crm_provider_id' => $picklist['picklist'],
])->first();
if ($field) {
$fieldValues = [];
foreach ($picklist['values'] as $value) {
// Must decode: "%2C" becomes "," etc.
$fieldValue = $field->values()
->where('value', urldecode($value['valueName']))
->first();
if ($fieldValue) {
$fieldValues[] = $fieldValue->id;
}
}
$recordType->fieldValues()->sync($fieldValues);
}
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
/**
* @inheritdoc
*/
public function importStages(?array $types = null, ?string $missingStageName = null): ?Stage
{
$params = [];
$missingStage = null;
if ($types === null) {
$types = [Stage::TYPE_LEAD, Stage::TYPE_OPPORTUNITY];
}
foreach ($types as $type) {
if ($type === Stage::TYPE_LEAD) {
$query = '
SELECT
Id, ApiName, MasterLabel, SortOrder
FROM
LeadStatus';
} else {
$query = '
SELECT
Id, ApiName, MasterLabel, IsActive, SortOrder, DefaultProbability
FROM
OpportunityStage';
}
if ($missingStageName) {
$escapedStageName = ValueNormalizer::replaceQueryWithStringLiterals($missingStageName);
$query .= ' WHERE ApiName = :stageName';
$params = [
'stageName' => $escapedStageName,
];
}
try {
$sfStages = $this->queryHandler->query($query, $params);
} catch (NoResultsException $exception) {
$sfStages = [];
}
$missingStage = null;
// Upsert all stages for the team.
foreach ($sfStages as $sfStage) {
$selectable = true;
if (array_key_exists('IsActive', $sfStage)) {
$selectable = $sfStage['IsActive'];
}
$this->restoreAnyTrashedEntity($this->config->stages(), $sfStage['Id']);
$stage = $this->config->stages()->updateOrCreate([
'crm_provider_id' => $sfStage['Id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($sfStage['ApiName'], 0, 50),
'label' => mb_strimwidth($sfStage['MasterLabel'], 0, 191),
'type' => $type,
'sequence' => $sfStage['SortOrder'] ?? 0,
'is_selectable' => $selectable,
'probability' => $sfStage['DefaultProbability'] ?? null,
]);
if ($missingStageName && $missingStageName === $sfStage['ApiName']) {
$missingStage = $stage;
}
}
if ($missingStageName && $missingStage === null) {
// If they requested a stage that still doesn't exist, it must be inactive so lazy create it.
$missingStage = $this->config->stages()->create([
'crm_provider_id' => Uuid::uuid4(),
'team_id' => $this->team->id,
'name' => mb_strimwidth($missingStageName, 0, 50),
'label' => mb_strimwidth($missingStageName, 0, 191),
'type' => $type,
'sequence' => 0,
'is_selectable' => 0,
]);
}
}
return $missingStage;
}
/**
* @inheritdoc
*/
public function syncLeads(Carbon $since, ?Carbon $to = null, ?string $crmProfileId = null): int
{
$syncCount = 0;
$fields = $this->getAllFieldsAsArray('lead');
if (\in_array('Id', $fields, true) === false) {
return $syncCount;
}
$query = '
SELECT ' . rtrim(implode(',', $fields), ',') . '
FROM Lead
WHERE LastModifiedDate > :since
ORDER BY LastModifiedDate ASC';
try {
$sfLeads = $this->queryHandler->query($query, [
'since' => $since->format('Y-m-d\TH:i:s\Z'),
]);
foreach ($sfLeads as $sfLead) {
// Only sync if previously imported.
if ($this->hasLead($sfLead['Id'])) {
$this->importLead($sfLead);
$syncCount++;
}
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
$this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::LEAD);
return $syncCount;
}
/**
* @inheritdoc
*/
public function syncLead(string $crmId): ?Lead
{
$fields = $this->getAllFieldsAsArray('lead');
$sfLead = $this->getRecord('Lead', $crmId, $fields);
return $this->importLead($sfLead);
}
private function importLead($crmData): ?Lead
{
/** @var ?Stage $stage */
$stage = null;
if (isset($crmData['Status'])) {
// Get the current stage.
$stage = $this->config
->stages()
->where('name', $crmData['Status'])
->where('type', Stage::TYPE_LEAD)
->first();
if ($stage === null) {
// Import it.
$stage = $this->importStages([Stage::TYPE_LEAD], $crmData['Status']);
}
}
// If we have no way of importing this, just return null :(
if ($stage === null) {
return null;
}
$countryCode = $crmData['CountryCode'] ?? null;
// Salesforce allows custom "countries" to be created. Disregard these.
if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {
$countryCode = null;
}
// If we have no country code, try to parse it from the country name.
if ($countryCode === null && empty($crmData['Country']) !== false) {
$countryCode = $this->convertCountryNameToCode($crmData['Country']);
}
// Trim to our width and attempt to parse it.
$number = mb_strimwidth($crmData['Phone'] ?? '', 0, 25);
$parsedNumber = parsePhoneNumber($countryCode, $number);
$mobilePhone = null;
if (empty($crmData['MobilePhone']) === false) {
// Trim to our width and attempt to parse it.
$number = mb_strimwidth($crmData['MobilePhone'], 0, 25);
$mobilePhone = phone_e164($countryCode, $number);
}
$convertedDate = null;
$convertedAccount = null;
$convertedOpportunity = null;
$convertedContact = null;
if ($crmData['IsConverted'] == 'true') {
$convertedDate = $crmData['ConvertedDate'];
if (empty($crmData['ConvertedAccountId']) === false) {
$convertedAccount = $this->config
->accounts()
->where('crm_provider_id', $crmData['ConvertedAccountId'])
->first();
if ($convertedAccount === null) {
try {
$convertedAccount = $this->syncAccount($crmData['ConvertedAccountId']);
} catch (HttpNotFoundException $exception) {
// Probably the user has no permissions to access the converted data.
}
}
}
if (empty($crmData['ConvertedOpportunityId']) === false) {
$convertedOpportunity = $this->config
->opportunities()
->where('crm_provider_id', $crmData['ConvertedOpportunityId'])
->first();
if ($convertedOpportunity === null) {
try {
$convertedOpportunity = $this->syncOpportunity($crmData['ConvertedOpportunityId']);
} catch (HttpNotFoundException $exception) {
// Probably the user has no permissions to access the converted data.
}
}
}
if (empty($crmData['ConvertedContactId']) === false) {
$convertedContact = $this->team
->crm
->contacts()
->where('crm_provider_id', $crmData['ConvertedContactId'])
->first();
if ($convertedContact === null) {
try {
$convertedContact = $this->syncContact($crmData['ConvertedContactId']);
} catch (HttpNotFoundException $exception) {
// Probably the user has no permissions to access the converted data.
}
}
}
}
if (empty($crmData['Company'])) {
$company = 'Unknown';
} else {
$company = mb_strimwidth($crmData['Company'], 0, 191);
}
$domain = null;
if (empty($crmData['Website']) === false) {
$domain = mb_strimwidth($crmData['Website'], 0, 191);
$domain = StringUtil::resolveDomain($domain);
}
$createdDate = null;
if (empty($crmData['CreatedDate']) === false) {
$createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');
}
$profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);
$data = [
'team_id' => $this->team->id,
'user_id' => $profile?->user_id,
'owner_id' => $crmData['OwnerId'] ?? '',
'company' => $company,
'domain' => $domain,
'name' => $crmData['Name'] ? mb_strimwidth($crmData['Name'], 0, 191) : '',
'title' => $crmData['Title'] ? mb_strimwidth($crmData['Title'], 0, 128) : null,
'email' => $crmData['Email'] ? mb_strimwidth($crmData['Email'], 0, 80) : null,
'phone' => $parsedNumber['phone'],
'ext' => $parsedNumber['ext'] ?? null,
'mobile_phone' => $mobilePhone,
'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(
crmConfiguration: $this->config,
crmProviderId: $crmData['Id'],
modelType: Lead::class,
fileName: $crmData['Id'],
avatarText: $crmData['Name']
),
'stage_id' => $stage->id,
'record_type_id' => null,
'converted_at' => $convertedDate,
'converted_account_id' => $convertedAccount->id ?? null,
'converted_opportunity_id' => $convertedOpportunity->id ?? null,
'converted_contact_id' => $convertedContact->id ?? null,
'country_code' => $countryCode,
'remotely_created_at' => $createdDate,
];
$this->restoreAnyTrashedEntity($this->config->leads(), $crmData['Id']);
/** @var Lead $lead */
$lead = $this->config->leads()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);
if ($lead->wasChanged('converted_at') && $lead->getConvertedAt() !== null) {
$this->eventDispatcher->dispatch(new LeadConverted($lead));
}
$this->handleObjectDeletion($lead, $crmData);
if ($lead->trashed()) {
return null;
}
return $lead;
}
/**
* @inheritdoc
*/
public function syncAccounts(Carbon $since, ?Carbon $to = null): int
{
$syncCount = 0;
$fields = $this->getAllFieldsAsArray('account');
if (\in_array('Id', $fields, true) === false) {
return $syncCount;
}
$query = '
SELECT ' . rtrim(implode(',', $fields), ',') . '
FROM Account
WHERE LastModifiedDate > :since
ORDER BY LastModifiedDate ASC';
try {
$sfAccounts = $this->queryHandler->query($query, [
'since' => $since->format('Y-m-d\TH:i:s\Z'),
]);
foreach ($sfAccounts as $sfAccount) {
// Only sync if previously imported.
if ($this->hasAccount($sfAccount['Id'])) {
$this->importAccount($sfAccount);
$syncCount++;
}
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
$this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::ACCOUNT);
return $syncCount;
}
/**
* @inheritdoc
*/
public function syncAccount(string $crmId): ?Account
{
$fields = $this->getAllFieldsAsArray('account');
if (! in_array('Id', $fields, true)) {
$this->logger->info('[Salesforce] Sync account cancelled. Fields are not available.', [
'crmId' => $crmId,
'userId' => $this->profile->getUserId(),
]);
return null;
}
$sfAccount = $this->getRecord('Account', $crmId, $fields);
return $this->importAccount($sfAccount);
}
private function importAccount($crmData): ?Account
{
if (! empty($crmData['IsDeleted'])) {
$this->handleEntityDeletionByProviderId($this->config->accounts(), $crmData);
return null;
}
$countryCode = $crmData['BillingCountryCode'] ?? $crmData['ShippingCountryCode'] ?? null;
// Salesforce allows custom "countries" to be created. Disregard these.
if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {
$countryCode = null;
}
// If we have no country code, try to parse it from the country names.
if ($countryCode === null && empty($crmData['BillingCountry']) === false) {
$countryCode = $this->convertCountryNameToCode($crmData['BillingCountry']);
}
if ($countryCode === null && empty($crmData['ShippingCountry']) === false) {
$countryCode = $this->convertCountryNameToCode($crmData['ShippingCountry']);
}
if (empty($crmData['Phone']) === false) {
// Trim to our width and attempt to parse it.
$number = mb_strimwidth($crmData['Phone'], 0, 25);
$parsedNumber = parsePhoneNumber($countryCode, $number);
} else {
$parsedNumber = [];
}
$industry = null;
if (empty($crmData['Industry']) === false) {
$industry = mb_strimwidth($crmData['Industry'], 0, 40);
}
$domain = null;
if (empty($crmData['Website']) === false) {
$domain = mb_strimwidth($crmData['Website'], 0, 191);
$domain = StringUtil::resolveDomain($domain);
}
$createdDate = null;
if (empty($crmData['CreatedDate']) === false) {
$createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');
}
$profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);
$data = [
'team_id' => $this->team->id,
'user_id' => $profile?->user_id,
'owner_id' => $crmData['OwnerId'],
'name' => mb_strimwidth($crmData['Name'], 0, 191),
'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(
crmConfiguration: $this->config,
crmProviderId: $crmData['Id'],
modelType: Account::class,
fileName: $crmData['Id'],
avatarText: $crmData['Name']
),
'industry' => $industry,
'domain' => $domain,
'phone' => $parsedNumber['phone'] ?? null,
'ext' => $parsedNumber['ext'] ?? null,
'country_code' => $countryCode,
'remotely_created_at' => $createdDate,
];
$this->restoreAnyTrashedEntity($this->config->accounts(), $crmData['Id']);
/** @var Account $account */
$account = $this->config->accounts()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);
$this->handleObjectDeletion($account, $crmData);
return $account->trashed() ? null : $account;
}
/**
* @inheritdoc
*/
public function syncOpportunities(array $parameters, ?string $strategy = null): int
{
$strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);
$syncCount = 0;
$logParams = $parameters;
$parameters['profile'] = $this->profile;
$logParams['user'] = $this->profile->getUserId();
if (count($strategies) > 1) {
$this->logger->warning('[' . $this->getDisplayName() . '] Multiple sync strategies used', [
'teamId' => $this->team->getUuid(),
'params' => $logParams,
'strategies_count' => count($strategies),
]);
}
foreach ($strategies as $syncStrategy) {
$name = $syncStrategy->getStrategyName();
try {
$sfOpportunities = $syncStrategy->fetchOpportunities($parameters);
$totalRecords = $sfOpportunities->count();
foreach ($sfOpportunities as $sfOpportunity) {
$this->importOpportunity($sfOpportunity);
$syncCount++;
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
$this->logger->warning('[' . $this->getDisplayName() . '] No opportunities found', [
'teamId' => $this->team->getUuid(),
'name' => $name,
'params' => $logParams,
'reason' => $noResultsException->getMessage(),
]);
} catch (CrmException $crmException) {
// Nothing to sync.
$this->logger->warning('[' . $this->getDisplayName() . '] Opportunity sync failed', [
'teamId' => $this->team->getUuid(),
'name' => $name,
'params' => $logParams,
'reason' => $crmException->getMessage(),
]);
}
}
$this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::OPPORTUNITY, ['params' => $logParams]);
// debug to see how if count of opportunities reaches 1000
if ($syncCount >= 1000) {
$this->logger->info(
'[' . $this->getDisplayName() . '] Sync Opportunities - count warning',
[
'team_id' => $this->team->getId(),
'params' => $logParams,
'count' => $syncCount,
'strategies_count' => count($strategies),
'total_records' => $totalRecords ?? null,
]
);
}
return $syncCount;
}
/**
* @inheritdoc
*/
public function syncOpportunity(string $crmId): ?Opportunity
{
$strategy = $this->opportunitySyncStrategyResolver->resolve(
$this->config,
OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY
);
$parameters = [
'profile' => $this->profile,
'crm_id' => $crmId,
];
try {
$sfOpportunity = $strategy->fetchOpportunities($parameters);
} catch (HttpNotFoundException $e) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [
'teamId' => $this->team->id_string,
'crmId' => $crmId,
]);
return null;
} catch (CrmException $crmException) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity sync failed', [
'teamId' => $this->team->id_string,
'crmId' => $crmId,
'exception' => $crmException->getMessage(),
]);
return null;
}
if ($sfOpportunity instanceof ArrayIterator) {
return $this->importOpportunity($sfOpportunity->getItems());
}
return $this->importOpportunity($sfOpportunity);
}
/**
* @throws HttpNotFoundException
*/
private function importOpportunity($crmData): ?Opportunity
{
$profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);
$account = null;
if (empty($crmData['AccountId']) === false) {
/** @var ?Account $account */
$account = $this->config->accounts()
->where('crm_provider_id', (string) $crmData['AccountId'])
->first();
if ($account === null) {
$account = $this->syncAccount($crmData['AccountId']);
}
}
$userId = $profile?->getUserId() ?? $account?->getUserId();
if ($userId === null) {
$this->logger->error('[Salesforce] | Skip import, no user_id found', [
'id' => $crmData['Id'],
]);
return null;
}
/** @var ?Stage $stage */
$stage = null;
if (isset($crmData['StageName'])...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12121 on JY-20963-fix-import-on-deleted-entity, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.11569149,"height":0.025538707},"on_screen":true,"help_text":"Pull request #12121 exists for current branch JY-20963-fix-import-on-deleted-entity, but pull request details loading failed","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.85638297,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"ServiceTest","depth":6,"bounds":{"left":0.87167555,"top":0.019952115,"width":0.043882977,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'ServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'ServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12","depth":4,"bounds":{"left":0.35272607,"top":0.12529927,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"246","depth":4,"bounds":{"left":0.3643617,"top":0.12529927,"width":0.012632979,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"bounds":{"left":0.37898937,"top":0.12529927,"width":0.007978723,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"21","depth":4,"bounds":{"left":0.38896278,"top":0.12529927,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.40026596,"top":0.123703115,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.40757978,"top":0.123703115,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Services\\Crm\\Salesforce;\n\nuse Carbon\\Carbon;\nuse Exception;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany;\nuse Illuminate\\Events\\Dispatcher;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Illuminate\\Support\\Facades\\Log;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Component\\Country\\CountriesMap;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Contracts\\Repositories\\TeamRepository;\nuse Jiminny\\Contracts\\Services\\Crm\\FetchRelatedActivityInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\ImportsBusinessProcessesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\LayoutManagementInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\MatchCrmEntitiesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\Provider\\SalesforceBatchSyncInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\Provider\\SalesforceInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\RemoteEntityLookupInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\RemoteEntityManipulationInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\RemoteNoteEntityManipulationInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SearchTaskInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SendSummaryToCrmInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SettingsInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SupportsObjectTypeParseInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SyncCrmEntitiesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SyncCrmProfileRecordTypesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\VerifyTaskExistsInterface;\nuse Jiminny\\Enums\\CrmObject;\nuse Jiminny\\Events\\Activities\\Crm\\LeadConverted;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Exceptions\\HttpBadRequestException;\nuse Jiminny\\Exceptions\\HttpNotFoundException;\nuse Jiminny\\Exceptions\\NoResultsException;\nuse Jiminny\\Exceptions\\ServiceUnavailableException;\nuse Jiminny\\Jobs\\Crm\\NoteObject;\nuse Jiminny\\Jobs\\Crm\\MatchActivitiesToNewOpportunity;\nuse Jiminny\\Models\\Account;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Calendar\\CalendarEvent;\nuse Jiminny\\Models\\Contact;\nuse Jiminny\\Models\\Contracts\\ActivityContract;\nuse Jiminny\\Models\\Crm\\BusinessProcess;\nuse Jiminny\\Models\\Crm\\Configuration;\nuse Jiminny\\Models\\Crm\\ContactRole;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\Profile;\nuse Jiminny\\Models\\Crm\\RecordType;\nuse Jiminny\\Models\\Lead;\nuse Jiminny\\Models\\Opportunity;\nuse Jiminny\\Models\\Playbook;\nuse Jiminny\\Models\\SocialAccount;\nuse Jiminny\\Models\\Stage;\nuse Jiminny\\Models\\TeamSettings;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\Crm\\ContactRoleRepository;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\Crm\\ProfileRepository;\nuse Jiminny\\Repositories\\Crm\\RecordTypeFieldValuesRepository;\nuse Jiminny\\Services\\Avatar\\ProspectPhotoPathService;\nuse Jiminny\\Services\\Crm\\BaseService;\nuse Jiminny\\Services\\Crm\\Helpers\\ArrayIterator;\nuse Jiminny\\Services\\Crm\\MatchDomainByEmailInterface;\nuse Jiminny\\Services\\Crm\\OpportunitySyncStrategyResolver;\nuse Jiminny\\Services\\Crm\\ResolveCompanyNameByEmailTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\Fields\\FieldHelper;\nuse Jiminny\\Services\\Crm\\Salesforce\\Fields\\FieldTypeConverter;\nuse Jiminny\\Services\\Crm\\Salesforce\\Fields\\ValueNormalizer;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\FollowupActivityTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\LogActivityTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\RecordManipulationsTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\SyncFieldsTrait;\nuse Jiminny\\Utils\\CurrencyFormatter;\nuse Jiminny\\Utils\\StringUtil;\nuse Ramsey\\Uuid\\Uuid;\nuse Sentry\\Laravel\\Facade as Sentry;\n\nclass Service extends BaseService implements\n SalesforceInterface,\n SalesforceBatchSyncInterface,\n SyncCrmEntitiesInterface,\n SyncCrmProfileRecordTypesInterface,\n ImportsBusinessProcessesInterface,\n RemoteEntityManipulationInterface,\n FetchRelatedActivityInterface,\n SendSummaryToCrmInterface,\n MatchDomainByEmailInterface,\n SearchTaskInterface,\n LayoutManagementInterface,\n SettingsInterface,\n MatchCrmEntitiesInterface,\n RemoteEntityLookupInterface,\n SupportsObjectTypeParseInterface,\n RemoteNoteEntityManipulationInterface,\n VerifyTaskExistsInterface\n{\n use ResolveCompanyNameByEmailTrait;\n use SyncFieldsTrait;\n use DeleteObjectsTrait;\n use RecordManipulationsTrait;\n use ServiceTraits\\BatchSyncTrait;\n use FollowupActivityTrait;\n use LogActivityTrait;\n\n /**\n * Note Body Limit for the Old Note-Taking Tool\n *\n * @var int\n */\n private const int CLASSIC_NOTE_MAX_LENGTH = 32000;\n\n /**\n * Note Content Limit for the New Notes\n *\n * @var int\n */\n private const int ENHANCED_NOTE_MAX_LENGTH = 50000000;\n\n private const string INSTALLED_PACKAGE_ID = '033Tw0000007bKbIAI';\n\n private const int CACHE_TTL = 600;\n\n private const int TASK_VERIFICATION_CACHE_TTL = 86400; // 1 day - 86400\n\n /**\n * @var Client\n */\n protected $client;\n\n protected PayloadBuilder $payloadBuilder;\n protected QueryHandler $queryHandler;\n\n private OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;\n\n public function __construct(\n Client $client,\n PayloadBuilder $payloadBuilder,\n protected Dispatcher $eventDispatcher,\n private readonly CountriesMap $countriesMap,\n private readonly ProspectPhotoPathService $prospectPhotoPathService,\n ) {\n parent::__construct();\n\n $this->client = $client;\n $this->payloadBuilder = $payloadBuilder;\n $this->queryHandler = app(QueryHandler::class, [\n 'client' => $this->client,\n 'logger' => $this->logger,\n ]);\n $this->opportunitySyncStrategyResolver = app(OpportunitySyncStrategyResolver::class, [\n 'client' => $this->client,\n ]);\n }\n\n public function getDisplayName(): string\n {\n return 'Salesforce';\n }\n\n public function getJobDelay(): int\n {\n return 1;\n }\n\n protected function getOAuthAccount(User $user): ?SocialAccount\n {\n return $user->getSocialAccount(SocialAccount::PROVIDER_SALESFORCE);\n }\n\n public function verifyTaskExists(Activity $activity): bool\n {\n $crmProviderId = $activity->getCrmProviderId();\n $cacheKey = \"crm_task_exists:{$this->config->getId()}:$crmProviderId\";\n\n return Cache::remember($cacheKey, self::TASK_VERIFICATION_CACHE_TTL, function () use ($activity, $crmProviderId) {\n $playbook = $this->getPlaybookFromActivity($activity);\n\n if ($playbook === null) {\n $this->logger->warning('[Salesforce] Cannot verify task - no playbook found', [\n 'activity' => $activity->getId(),\n 'crm_provider_id' => $crmProviderId,\n ]);\n\n return false;\n }\n\n $objectType = $playbook->getActivityType() === Playbook::ACTIVITY_TYPE_EVENT ? 'Event' : 'Task';\n\n try {\n $record = $this->getRecord($objectType, $crmProviderId, ['Id', 'IsDeleted']);\n\n return ! empty($record) && ($record['IsDeleted'] ?? false) === false;\n } catch (HttpNotFoundException|HttpBadRequestException) {\n $this->logger->info('[Salesforce] Activity record not found during verification', [\n 'activity' => $activity->getId(),\n 'object_type' => $objectType,\n 'crm_provider_id' => $crmProviderId,\n 'config_id' => $this->config->getId(),\n ]);\n\n return false;\n }\n });\n }\n\n public function query(string $queryToRun, array $parameters = []): QueryIterator\n {\n // Due to poorly designed external calls, this method cannot be entirely removed\n return $this->queryHandler->query($queryToRun, $parameters);\n }\n\n /*=========== Organization Information ===============*/\n\n /**\n * Get a list of all the API Versions for the instance.\n *\n * @throws CrmException\n *\n * @return mixed\n *\n */\n public function getApiVersions()\n {\n $url = $this->config->crm_base_url . '/services/data';\n\n $response = $this->client->get($url);\n\n return json_decode($response->getBody(), true);\n }\n\n /**\n * Gets the valid recordTypes for a given Salesforce Object via the describe API.\n */\n private function getRecordTypes(string $crmObject): array\n {\n $url = $this->client->getObjectsUrl() . $crmObject . '/describe';\n\n $response = $this->client->get($url);\n $jsonResponse = json_decode($response->getBody(), true);\n\n $fields = [];\n foreach ($jsonResponse['recordTypeInfos'] as $row) {\n $fields[] = ['recordTypeId' => $row['recordTypeId'], 'default' => $row['defaultRecordTypeMapping']];\n }\n\n return $fields;\n }\n\n /**\n * Convert raw field data into a format compatible with CRM APIs.\n */\n public function normalizeValue(string $fieldType, string $fieldValue, bool $internal = false): string\n {\n return ValueNormalizer::normalize($fieldType, $fieldValue, $internal);\n }\n\n /**\n * @inheritdoc\n */\n public function getDefaultFields(string $activityType): array\n {\n $fields = [];\n\n $defaultFields = ($activityType === Playbook::ACTIVITY_TYPE_TASK)\n ? FieldDefinitions::defaultTaskFields()\n : FieldDefinitions::defaultEventFields();\n\n // This lazy creates these fields if not already setup.\n foreach ($defaultFields as $defaultField) {\n $fields[] = $this->config->fields()->firstOrCreate($defaultField);\n }\n\n return $fields;\n }\n\n /**\n * @inheritdoc\n */\n public function getDefaultActivityField(string $activityType): Field\n {\n // Setup the activity field as the default Type.\n /** @var Field $activityField */\n $activityField = $this->config->fields()->where([\n 'crm_provider_id' => 'Type',\n 'object_type' => $activityType,\n ])->first();\n\n return $activityField;\n }\n\n /**\n * @inheritdoc\n */\n public function getSupportedPlaybookTypes(): array\n {\n return [Playbook::ACTIVITY_TYPE_TASK, Playbook::ACTIVITY_TYPE_EVENT];\n }\n\n protected function getDefaultFollowupLayoutFields(string $activityType): array\n {\n $fields = [];\n $fieldRepo = app(FieldRepository::class);\n\n $fieldFilter = ($activityType === Playbook::ACTIVITY_TYPE_TASK)\n ? FieldDefinitions::taskFollowupFieldsFilter()\n : FieldDefinitions::eventFollowupFieldsFilter();\n\n foreach ($fieldFilter as $eachFilter) {\n $field = $fieldRepo->findOneConfigurationFieldByProperties($this->config, $eachFilter);\n\n // Only add the field if it is created, which it should be.\n if ($field) {\n $fields[] = $field;\n }\n }\n\n return $fields;\n }\n\n public function getDealInsightsFields(): array\n {\n return FieldDefinitions::dealInsightsFields();\n }\n\n /**\n * This one is now called only when ImportActivityTypes is triggered or SyncFieldMetadata executed manually\n * Regular sync now uses SharedSyncFieldsTrait -> syncSingleObjectType\n * Needs to be replaced later on\n */\n public function syncField(Field $field): void\n {\n try {\n if (FieldHelper::isCustomField($field)) {\n $query = '\n SELECT\n Id, Metadata, TableEnumOrId\n FROM\n CustomField\n WHERE\n DeveloperName = :fieldName\n AND\n TableEnumOrId = :fieldType\n AND\n NamespacePrefix = :namespacePrefix';\n\n // We need to constrain the field lookup to the object, in case it's used in multiple places.\n $objectType = \\in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true)\n ? 'activity'\n : $field->object_type;\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'fieldName' => substr($field->crm_provider_id, 0, -\\strlen('__c')),\n 'fieldType' => ucfirst($objectType),\n\n // This is used to ensure we only consider the field within the org, not installed packages.\n 'namespacePrefix' => 'null',\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n // Sync field metadata.\n $metadata = $sfField['Metadata'];\n\n $field->description = mb_strimwidth($metadata['description'] ?? '', 0, 191);\n $field->label = mb_strimwidth($metadata['label'] ?? '', 0, Field::LABEL_MAX_LENGTH);\n $field->type = $this->convertFieldType($metadata['type'], $field->getEntityName());\n $field->is_mandatory = ($metadata['required'] === true);\n $field->length = $metadata['length'];\n $field->default_value = mb_strimwidth(trim($metadata['defaultValue'] ?? '', '\"'), 0, 191);\n $field->save();\n } else {\n $query = '\n SELECT\n Id, DataType, DeveloperName, Label, Length, Description\n FROM\n FieldDefinition\n WHERE\n DurableId = :entityName';\n\n $entityName = $field->getEntityName();\n $sfFields = $this->queryHandler->metadata($query, [\n 'entityName' => $entityName,\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n $convertedType = $this->convertFieldType($sfField['DataType'], $entityName);\n $label = mb_strimwidth($sfField['Label'], 0, Field::LABEL_MAX_LENGTH);\n\n if ($field->isBusinessType()) {\n $label = 'Opportunity Type';\n }\n\n $field->description = mb_strimwidth($sfField['Description'], 0, Field::DESCRIPTION_MAX_LENGTH);\n $field->label = $label;\n $field->type = $convertedType;\n $field->length = $sfField['Length'];\n $field->save();\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n private function convertFieldType(string $from, ?string $entityName = null): string\n {\n $converter = new FieldTypeConverter();\n\n return $converter->convert($from, $entityName);\n }\n\n /**\n * @inheritdoc\n */\n public function importPicklistValues(Field $field): array\n {\n $values = [];\n $fieldValues = [];\n\n try {\n if (FieldHelper::isCustomField($field)) {\n $query = '\n SELECT\n Id, Metadata, TableEnumOrId\n FROM\n CustomField\n WHERE\n DeveloperName = :fieldName\n AND\n TableEnumOrId = :fieldType\n AND\n NamespacePrefix = :namespacePrefix';\n\n // We need to constrain the field lookup to the object, in case it's used in multiple places.\n $objectType = \\in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true) ?\n 'activity' : $field->object_type;\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'fieldName' => substr($field->crm_provider_id, 0, -\\strlen('__c')),\n 'fieldType' => ucfirst($objectType),\n // This is used to ensure we only consider the field within the org, not installed packages.\n 'namespacePrefix' => 'null',\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n $valueSet = $sfField['Metadata']['valueSet'];\n\n if ($valueSet['valueSetName'] === null) {\n // Local picklist values can be obtained easily.\n $picklistValues = $valueSet['valueSetDefinition']['value'];\n } else {\n // But for some fields, we just get the Global Value Picklist pointer so need to do more work.\n $picklistValues = $this->importGlobalValuePicklistValues($valueSet['valueSetName']);\n }\n\n // Import all active values.\n foreach ($picklistValues as $i => $sfFieldValue) {\n // Setup default value.\n if ($sfFieldValue['default']) {\n $field->update(['default_value' => $sfFieldValue['valueName']]);\n }\n\n // This comes through as null if active (lol).\n if ($sfFieldValue['isActive'] !== false) {\n $values[] = [\n 'value' => $sfFieldValue['valueName'],\n 'label' => $sfFieldValue['valueName'],\n 'sequence' => $i,\n 'is_default' => $sfFieldValue['default'],\n ];\n }\n }\n } else {\n $objectFields = $this->getObjectFields($field->object_type);\n $fieldId = $field->crm_provider_id;\n\n // Only work with our field of interest.\n $objectField = array_filter($objectFields, function ($item) use ($fieldId) {\n return $item['name'] === $fieldId;\n });\n\n $objectField = array_shift($objectField);\n if (empty($objectField['picklistValues']) === false) {\n foreach ($objectField['picklistValues'] as $i => $sfFieldValue) {\n // Skip inactive values.\n if ($sfFieldValue['active'] === false) {\n continue;\n }\n\n // Setup default value.\n if ($sfFieldValue['defaultValue']) {\n $field->update(['default_value' => $sfFieldValue['value']]);\n }\n\n $values[] = [\n 'value' => $sfFieldValue['value'],\n 'label' => $sfFieldValue['label'],\n 'sequence' => $i,\n 'is_default' => $sfFieldValue['defaultValue'],\n ];\n }\n }\n }\n\n $fieldsToPurge = $field->values()->get()->pluck('value')->toArray();\n\n foreach ($values as $value) {\n $value['value'] = substr($value['value'] ?? '', 0, 255);\n $fieldValues[] = $field->values()->updateOrCreate([\n 'value' => $value['value'],\n ], $value);\n\n // Remove this value from the ones we are going to purge.\n if (($key = array_search($value['value'], $fieldsToPurge, true)) !== false) {\n unset($fieldsToPurge[$key]);\n }\n }\n\n // Delete the old values that are no longer used.\n // Get IDs of the values to be deleted\n $valuesToDelete = $field->values()->whereIn('value', $fieldsToPurge);\n $valuesToDeleteIds = $valuesToDelete->pluck('id');\n if (! $valuesToDeleteIds->isEmpty()) {\n $recordTypeFieldValuesRepository = app(RecordTypeFieldValuesRepository::class);\n $recordTypeFieldValuesRepository->deleteForCrmFieldValueIds($valuesToDeleteIds->toArray());\n\n // Now safely delete from crm_field_values\n $valuesToDelete->delete();\n }\n\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n return $fieldValues;\n }\n\n /**\n * Gets values from Global Value Picklists.\n */\n private function importGlobalValuePicklistValues(string $picklistName): array\n {\n $query = '\n SELECT\n Metadata\n FROM\n GlobalValueSet\n WHERE\n DeveloperName = :picklistName\n LIMIT 1';\n\n try {\n $sfValues = $this->queryHandler->metadata($query, [\n 'picklistName' => $picklistName,\n ]);\n\n // There is always 1 result at this point.\n $sfValue = $sfValues->current();\n\n return $sfValue['Metadata']['customValue'];\n } catch (NoResultsException $noResultsException) {\n // Nothing returned.\n\n return [];\n }\n }\n\n /**\n * @inheritdoc\n */\n public function syncProfileRecordTypes(): void\n {\n $objectTypes = [\n 'lead',\n 'account',\n 'contact',\n 'opportunity',\n 'task',\n 'event',\n ];\n\n foreach ($objectTypes as $objectType) {\n try {\n $crmRecordTypes = $this->getRecordTypes(ucfirst($objectType));\n\n foreach ($crmRecordTypes as $crmRecordType) {\n // If the record type is default and not the Master type, set this.\n if ($crmRecordType['default'] && $crmRecordType['recordTypeId'] !== '012000000000000AAA') {\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $crmRecordType['recordTypeId'])\n ->first();\n\n if ($recordType) {\n $this->profile->{$objectType . '_record_type_id'} = $recordType->id;\n }\n }\n }\n } catch (HttpNotFoundException $exception) {\n Log::error('No access to ' . $objectType . ' object, skipping...');\n\n // XXX: should we log this fact somewhere?\n continue;\n }\n }\n\n if ($this->profile->isDirty()) {\n $this->profile->save();\n }\n }\n\n /**\n * Gets business processes.\n */\n public function importBusinessProcesses(): void\n {\n $query = '\n SELECT\n Id, IsActive, Name, TableEnumOrId\n FROM\n BusinessProcess\n WHERE\n TableEnumOrId IN (\\'Lead\\',\\'Opportunity\\')';\n\n try {\n $sfProcesses = $this->queryHandler->query($query);\n\n // Upsert all processes for the team.\n foreach ($sfProcesses as $sfProcess) {\n /** @var BusinessProcess $businessProcess */\n $businessProcess = $this->config->businessProcesses()->updateOrCreate([\n 'crm_provider_id' => $sfProcess['Id'],\n ], [\n 'team_id' => $this->team->id,\n 'name' => $sfProcess['Name'],\n 'type' => $sfProcess['TableEnumOrId'] === 'Lead' ? 'lead' : 'opportunity',\n 'is_selectable' => $sfProcess['IsActive'],\n ]);\n\n $this->importBusinessProcessStages($businessProcess);\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n /**\n * Gets business process stages.\n */\n private function importBusinessProcessStages(BusinessProcess $businessProcess): void\n {\n $query = '\n SELECT\n Metadata\n FROM\n BusinessProcess\n WHERE\n Id = :processId';\n\n try {\n $stages = [];\n $sfProcessStages = $this->queryHandler->metadata($query, [\n 'processId' => $businessProcess->crm_provider_id,\n ]);\n\n // There is always 1 result at this point.\n $sfProcessStage = $sfProcessStages->current();\n\n // Upsert all processes for the team.\n foreach ($sfProcessStage['Metadata']['values'] as $sfProcessStage) {\n $sanitizedName = urldecode($sfProcessStage['valueName']); // Must decode: \"%2C\" becomes \",\" etc.\n\n $stage = $businessProcess->crm->stages()\n // This MUST match on label because this API doesn't use API Name.\n ->where('label', $sanitizedName)\n ->where('type', $businessProcess->type)\n ->where('is_selectable', 1)\n ->first();\n\n if ($stage) {\n $stages[] = $stage->id;\n }\n }\n\n $businessProcess->stages()->sync($stages);\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n /**\n * Gets record types.\n */\n public function importRecordTypes(): void\n {\n $query = '\n SELECT\n Id, IsActive, Name, BusinessProcessId, SobjectType\n FROM\n RecordType';\n\n try {\n $sfRecordTypes = $this->queryHandler->query($query);\n\n // Upsert all record types for the process.\n foreach ($sfRecordTypes as $sfRecordType) {\n $businessProcess = null;\n if ($sfRecordType['BusinessProcessId']) {\n $businessProcess = $this->config->businessProcesses()\n ->where('crm_provider_id', $sfRecordType['BusinessProcessId'])\n ->first();\n }\n\n /** @var RecordType $recordType */\n $recordType = $this->config->recordTypes()->updateOrCreate([\n 'crm_provider_id' => $sfRecordType['Id'],\n ], [\n 'team_id' => $this->team->id,\n 'type' => mb_strtolower($sfRecordType['SobjectType']),\n 'name' => $sfRecordType['Name'],\n 'is_selectable' => $sfRecordType['IsActive'],\n 'business_process_id' => $businessProcess->id ?? null,\n ]);\n\n $this->importRecordTypeFieldValues($recordType);\n }\n } catch (NoResultsException $noResultsException) {\n // Do nothing.\n }\n }\n\n /**\n * Import record type - field value mappings. This only works for standard fields.\n */\n private function importRecordTypeFieldValues(RecordType $recordType): void\n {\n try {\n $query = '\n SELECT\n Metadata\n FROM\n RecordType\n WHERE\n Id = :recordTypeId';\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'recordTypeId' => $recordType->crm_provider_id,\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n // Sync field metadata.\n $picklists = $sfField['Metadata']['picklistValues'];\n\n foreach ($picklists as $picklist) {\n $field = $this->config->fields()->where([\n 'type' => Field::TYPE_PICKLIST,\n 'object_type' => $recordType->type,\n 'crm_provider_id' => $picklist['picklist'],\n ])->first();\n\n if ($field) {\n $fieldValues = [];\n\n foreach ($picklist['values'] as $value) {\n // Must decode: \"%2C\" becomes \",\" etc.\n $fieldValue = $field->values()\n ->where('value', urldecode($value['valueName']))\n ->first();\n\n if ($fieldValue) {\n $fieldValues[] = $fieldValue->id;\n }\n }\n\n $recordType->fieldValues()->sync($fieldValues);\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n /**\n * @inheritdoc\n */\n public function importStages(?array $types = null, ?string $missingStageName = null): ?Stage\n {\n $params = [];\n $missingStage = null;\n if ($types === null) {\n $types = [Stage::TYPE_LEAD, Stage::TYPE_OPPORTUNITY];\n }\n\n foreach ($types as $type) {\n if ($type === Stage::TYPE_LEAD) {\n $query = '\n SELECT\n Id, ApiName, MasterLabel, SortOrder\n FROM\n LeadStatus';\n } else {\n $query = '\n SELECT\n Id, ApiName, MasterLabel, IsActive, SortOrder, DefaultProbability\n FROM\n OpportunityStage';\n }\n\n if ($missingStageName) {\n $escapedStageName = ValueNormalizer::replaceQueryWithStringLiterals($missingStageName);\n\n $query .= ' WHERE ApiName = :stageName';\n\n $params = [\n 'stageName' => $escapedStageName,\n ];\n }\n\n try {\n $sfStages = $this->queryHandler->query($query, $params);\n } catch (NoResultsException $exception) {\n $sfStages = [];\n }\n\n $missingStage = null;\n\n // Upsert all stages for the team.\n foreach ($sfStages as $sfStage) {\n $selectable = true;\n if (array_key_exists('IsActive', $sfStage)) {\n $selectable = $sfStage['IsActive'];\n }\n\n $this->restoreAnyTrashedEntity($this->config->stages(), $sfStage['Id']);\n\n $stage = $this->config->stages()->updateOrCreate([\n 'crm_provider_id' => $sfStage['Id'],\n ], [\n 'team_id' => $this->team->id,\n 'name' => mb_strimwidth($sfStage['ApiName'], 0, 50),\n 'label' => mb_strimwidth($sfStage['MasterLabel'], 0, 191),\n 'type' => $type,\n 'sequence' => $sfStage['SortOrder'] ?? 0,\n 'is_selectable' => $selectable,\n 'probability' => $sfStage['DefaultProbability'] ?? null,\n ]);\n\n if ($missingStageName && $missingStageName === $sfStage['ApiName']) {\n $missingStage = $stage;\n }\n }\n\n if ($missingStageName && $missingStage === null) {\n // If they requested a stage that still doesn't exist, it must be inactive so lazy create it.\n $missingStage = $this->config->stages()->create([\n 'crm_provider_id' => Uuid::uuid4(),\n 'team_id' => $this->team->id,\n 'name' => mb_strimwidth($missingStageName, 0, 50),\n 'label' => mb_strimwidth($missingStageName, 0, 191),\n 'type' => $type,\n 'sequence' => 0,\n 'is_selectable' => 0,\n ]);\n }\n }\n\n return $missingStage;\n }\n\n /**\n * @inheritdoc\n */\n public function syncLeads(Carbon $since, ?Carbon $to = null, ?string $crmProfileId = null): int\n {\n $syncCount = 0;\n $fields = $this->getAllFieldsAsArray('lead');\n if (\\in_array('Id', $fields, true) === false) {\n return $syncCount;\n }\n\n $query = '\n SELECT ' . rtrim(implode(',', $fields), ',') . '\n FROM Lead\n WHERE LastModifiedDate > :since\n ORDER BY LastModifiedDate ASC';\n\n try {\n $sfLeads = $this->queryHandler->query($query, [\n 'since' => $since->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($sfLeads as $sfLead) {\n // Only sync if previously imported.\n if ($this->hasLead($sfLead['Id'])) {\n $this->importLead($sfLead);\n $syncCount++;\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::LEAD);\n\n return $syncCount;\n }\n\n /**\n * @inheritdoc\n */\n public function syncLead(string $crmId): ?Lead\n {\n $fields = $this->getAllFieldsAsArray('lead');\n\n $sfLead = $this->getRecord('Lead', $crmId, $fields);\n\n return $this->importLead($sfLead);\n }\n\n private function importLead($crmData): ?Lead\n {\n /** @var ?Stage $stage */\n $stage = null;\n if (isset($crmData['Status'])) {\n // Get the current stage.\n $stage = $this->config\n ->stages()\n ->where('name', $crmData['Status'])\n ->where('type', Stage::TYPE_LEAD)\n ->first();\n\n if ($stage === null) {\n // Import it.\n $stage = $this->importStages([Stage::TYPE_LEAD], $crmData['Status']);\n }\n }\n\n // If we have no way of importing this, just return null :(\n if ($stage === null) {\n return null;\n }\n\n $countryCode = $crmData['CountryCode'] ?? null;\n\n // Salesforce allows custom \"countries\" to be created. Disregard these.\n if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {\n $countryCode = null;\n }\n\n // If we have no country code, try to parse it from the country name.\n if ($countryCode === null && empty($crmData['Country']) !== false) {\n $countryCode = $this->convertCountryNameToCode($crmData['Country']);\n }\n\n // Trim to our width and attempt to parse it.\n $number = mb_strimwidth($crmData['Phone'] ?? '', 0, 25);\n $parsedNumber = parsePhoneNumber($countryCode, $number);\n\n $mobilePhone = null;\n if (empty($crmData['MobilePhone']) === false) {\n // Trim to our width and attempt to parse it.\n $number = mb_strimwidth($crmData['MobilePhone'], 0, 25);\n $mobilePhone = phone_e164($countryCode, $number);\n }\n\n $convertedDate = null;\n $convertedAccount = null;\n $convertedOpportunity = null;\n $convertedContact = null;\n\n if ($crmData['IsConverted'] == 'true') {\n $convertedDate = $crmData['ConvertedDate'];\n\n if (empty($crmData['ConvertedAccountId']) === false) {\n $convertedAccount = $this->config\n ->accounts()\n ->where('crm_provider_id', $crmData['ConvertedAccountId'])\n ->first();\n\n if ($convertedAccount === null) {\n try {\n $convertedAccount = $this->syncAccount($crmData['ConvertedAccountId']);\n } catch (HttpNotFoundException $exception) {\n // Probably the user has no permissions to access the converted data.\n }\n }\n }\n\n if (empty($crmData['ConvertedOpportunityId']) === false) {\n $convertedOpportunity = $this->config\n ->opportunities()\n ->where('crm_provider_id', $crmData['ConvertedOpportunityId'])\n ->first();\n\n if ($convertedOpportunity === null) {\n try {\n $convertedOpportunity = $this->syncOpportunity($crmData['ConvertedOpportunityId']);\n } catch (HttpNotFoundException $exception) {\n // Probably the user has no permissions to access the converted data.\n }\n }\n }\n\n if (empty($crmData['ConvertedContactId']) === false) {\n $convertedContact = $this->team\n ->crm\n ->contacts()\n ->where('crm_provider_id', $crmData['ConvertedContactId'])\n ->first();\n\n if ($convertedContact === null) {\n try {\n $convertedContact = $this->syncContact($crmData['ConvertedContactId']);\n } catch (HttpNotFoundException $exception) {\n // Probably the user has no permissions to access the converted data.\n }\n }\n }\n }\n\n if (empty($crmData['Company'])) {\n $company = 'Unknown';\n } else {\n $company = mb_strimwidth($crmData['Company'], 0, 191);\n }\n\n $domain = null;\n if (empty($crmData['Website']) === false) {\n $domain = mb_strimwidth($crmData['Website'], 0, 191);\n $domain = StringUtil::resolveDomain($domain);\n }\n\n $createdDate = null;\n if (empty($crmData['CreatedDate']) === false) {\n $createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n }\n\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $data = [\n 'team_id' => $this->team->id,\n 'user_id' => $profile?->user_id,\n 'owner_id' => $crmData['OwnerId'] ?? '',\n 'company' => $company,\n 'domain' => $domain,\n 'name' => $crmData['Name'] ? mb_strimwidth($crmData['Name'], 0, 191) : '',\n 'title' => $crmData['Title'] ? mb_strimwidth($crmData['Title'], 0, 128) : null,\n 'email' => $crmData['Email'] ? mb_strimwidth($crmData['Email'], 0, 80) : null,\n 'phone' => $parsedNumber['phone'],\n 'ext' => $parsedNumber['ext'] ?? null,\n 'mobile_phone' => $mobilePhone,\n 'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(\n crmConfiguration: $this->config,\n crmProviderId: $crmData['Id'],\n modelType: Lead::class,\n fileName: $crmData['Id'],\n avatarText: $crmData['Name']\n ),\n 'stage_id' => $stage->id,\n 'record_type_id' => null,\n 'converted_at' => $convertedDate,\n 'converted_account_id' => $convertedAccount->id ?? null,\n 'converted_opportunity_id' => $convertedOpportunity->id ?? null,\n 'converted_contact_id' => $convertedContact->id ?? null,\n 'country_code' => $countryCode,\n 'remotely_created_at' => $createdDate,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->leads(), $crmData['Id']);\n\n /** @var Lead $lead */\n $lead = $this->config->leads()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n if ($lead->wasChanged('converted_at') && $lead->getConvertedAt() !== null) {\n $this->eventDispatcher->dispatch(new LeadConverted($lead));\n }\n\n $this->handleObjectDeletion($lead, $crmData);\n\n if ($lead->trashed()) {\n return null;\n }\n\n return $lead;\n }\n\n /**\n * @inheritdoc\n */\n public function syncAccounts(Carbon $since, ?Carbon $to = null): int\n {\n $syncCount = 0;\n $fields = $this->getAllFieldsAsArray('account');\n\n if (\\in_array('Id', $fields, true) === false) {\n return $syncCount;\n }\n\n $query = '\n SELECT ' . rtrim(implode(',', $fields), ',') . '\n FROM Account\n WHERE LastModifiedDate > :since\n ORDER BY LastModifiedDate ASC';\n\n try {\n $sfAccounts = $this->queryHandler->query($query, [\n 'since' => $since->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($sfAccounts as $sfAccount) {\n // Only sync if previously imported.\n if ($this->hasAccount($sfAccount['Id'])) {\n $this->importAccount($sfAccount);\n $syncCount++;\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::ACCOUNT);\n\n return $syncCount;\n }\n\n /**\n * @inheritdoc\n */\n public function syncAccount(string $crmId): ?Account\n {\n $fields = $this->getAllFieldsAsArray('account');\n if (! in_array('Id', $fields, true)) {\n $this->logger->info('[Salesforce] Sync account cancelled. Fields are not available.', [\n 'crmId' => $crmId,\n 'userId' => $this->profile->getUserId(),\n ]);\n\n return null;\n }\n\n $sfAccount = $this->getRecord('Account', $crmId, $fields);\n\n return $this->importAccount($sfAccount);\n }\n\n private function importAccount($crmData): ?Account\n {\n if (! empty($crmData['IsDeleted'])) {\n $this->handleEntityDeletionByProviderId($this->config->accounts(), $crmData);\n\n return null;\n }\n\n $countryCode = $crmData['BillingCountryCode'] ?? $crmData['ShippingCountryCode'] ?? null;\n\n // Salesforce allows custom \"countries\" to be created. Disregard these.\n if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {\n $countryCode = null;\n }\n\n // If we have no country code, try to parse it from the country names.\n if ($countryCode === null && empty($crmData['BillingCountry']) === false) {\n $countryCode = $this->convertCountryNameToCode($crmData['BillingCountry']);\n }\n\n if ($countryCode === null && empty($crmData['ShippingCountry']) === false) {\n $countryCode = $this->convertCountryNameToCode($crmData['ShippingCountry']);\n }\n\n if (empty($crmData['Phone']) === false) {\n // Trim to our width and attempt to parse it.\n $number = mb_strimwidth($crmData['Phone'], 0, 25);\n $parsedNumber = parsePhoneNumber($countryCode, $number);\n } else {\n $parsedNumber = [];\n }\n\n $industry = null;\n if (empty($crmData['Industry']) === false) {\n $industry = mb_strimwidth($crmData['Industry'], 0, 40);\n }\n\n $domain = null;\n if (empty($crmData['Website']) === false) {\n $domain = mb_strimwidth($crmData['Website'], 0, 191);\n $domain = StringUtil::resolveDomain($domain);\n }\n\n $createdDate = null;\n if (empty($crmData['CreatedDate']) === false) {\n $createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n }\n\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $data = [\n 'team_id' => $this->team->id,\n 'user_id' => $profile?->user_id,\n 'owner_id' => $crmData['OwnerId'],\n 'name' => mb_strimwidth($crmData['Name'], 0, 191),\n 'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(\n crmConfiguration: $this->config,\n crmProviderId: $crmData['Id'],\n modelType: Account::class,\n fileName: $crmData['Id'],\n avatarText: $crmData['Name']\n ),\n 'industry' => $industry,\n 'domain' => $domain,\n 'phone' => $parsedNumber['phone'] ?? null,\n 'ext' => $parsedNumber['ext'] ?? null,\n 'country_code' => $countryCode,\n 'remotely_created_at' => $createdDate,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->accounts(), $crmData['Id']);\n\n /** @var Account $account */\n $account = $this->config->accounts()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n $this->handleObjectDeletion($account, $crmData);\n\n return $account->trashed() ? null : $account;\n }\n\n /**\n * @inheritdoc\n */\n public function syncOpportunities(array $parameters, ?string $strategy = null): int\n {\n $strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);\n\n $syncCount = 0;\n $logParams = $parameters;\n $parameters['profile'] = $this->profile;\n $logParams['user'] = $this->profile->getUserId();\n\n if (count($strategies) > 1) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Multiple sync strategies used', [\n 'teamId' => $this->team->getUuid(),\n 'params' => $logParams,\n 'strategies_count' => count($strategies),\n ]);\n }\n\n foreach ($strategies as $syncStrategy) {\n $name = $syncStrategy->getStrategyName();\n\n try {\n $sfOpportunities = $syncStrategy->fetchOpportunities($parameters);\n $totalRecords = $sfOpportunities->count();\n\n foreach ($sfOpportunities as $sfOpportunity) {\n $this->importOpportunity($sfOpportunity);\n $syncCount++;\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n $this->logger->warning('[' . $this->getDisplayName() . '] No opportunities found', [\n 'teamId' => $this->team->getUuid(),\n 'name' => $name,\n 'params' => $logParams,\n 'reason' => $noResultsException->getMessage(),\n ]);\n } catch (CrmException $crmException) {\n // Nothing to sync.\n $this->logger->warning('[' . $this->getDisplayName() . '] Opportunity sync failed', [\n 'teamId' => $this->team->getUuid(),\n 'name' => $name,\n 'params' => $logParams,\n 'reason' => $crmException->getMessage(),\n ]);\n }\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::OPPORTUNITY, ['params' => $logParams]);\n\n // debug to see how if count of opportunities reaches 1000\n if ($syncCount >= 1000) {\n $this->logger->info(\n '[' . $this->getDisplayName() . '] Sync Opportunities - count warning',\n [\n 'team_id' => $this->team->getId(),\n 'params' => $logParams,\n 'count' => $syncCount,\n 'strategies_count' => count($strategies),\n 'total_records' => $totalRecords ?? null,\n ]\n );\n }\n\n return $syncCount;\n }\n\n\n /**\n * @inheritdoc\n */\n public function syncOpportunity(string $crmId): ?Opportunity\n {\n $strategy = $this->opportunitySyncStrategyResolver->resolve(\n $this->config,\n OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY\n );\n\n $parameters = [\n 'profile' => $this->profile,\n 'crm_id' => $crmId,\n ];\n\n try {\n $sfOpportunity = $strategy->fetchOpportunities($parameters);\n } catch (HttpNotFoundException $e) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [\n 'teamId' => $this->team->id_string,\n 'crmId' => $crmId,\n ]);\n\n return null;\n } catch (CrmException $crmException) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity sync failed', [\n 'teamId' => $this->team->id_string,\n 'crmId' => $crmId,\n 'exception' => $crmException->getMessage(),\n ]);\n\n return null;\n }\n\n if ($sfOpportunity instanceof ArrayIterator) {\n return $this->importOpportunity($sfOpportunity->getItems());\n }\n\n return $this->importOpportunity($sfOpportunity);\n }\n\n /**\n * @throws HttpNotFoundException\n */\n private function importOpportunity($crmData): ?Opportunity\n {\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $account = null;\n if (empty($crmData['AccountId']) === false) {\n /** @var ?Account $account */\n $account = $this->config->accounts()\n ->where('crm_provider_id', (string) $crmData['AccountId'])\n ->first();\n\n if ($account === null) {\n $account = $this->syncAccount($crmData['AccountId']);\n }\n }\n\n $userId = $profile?->getUserId() ?? $account?->getUserId();\n if ($userId === null) {\n $this->logger->error('[Salesforce] | Skip import, no user_id found', [\n 'id' => $crmData['Id'],\n ]);\n\n return null;\n }\n\n /** @var ?Stage $stage */\n $stage = null;\n if (isset($crmData['StageName'])) {\n $stage = $this->config\n ->stages()\n ->where('name', $crmData['StageName'])\n ->where('type', Stage::TYPE_OPPORTUNITY)\n ->orderBy('is_selectable', 'DESC')\n ->orderBy('id')\n ->first();\n\n if ($stage === null) {\n // Import it.\n $stage = $this->importStages([Stage::TYPE_OPPORTUNITY], $crmData['StageName']);\n }\n }\n\n $recordType = null;\n if (empty($crmData['RecordTypeId']) === false) {\n /** @var ?RecordType $recordType */\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $crmData['RecordTypeId'])\n ->first();\n }\n\n $createdDate = null;\n if (empty($crmData['CreatedDate']) === false) {\n $createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n }\n\n $closeDate = null;\n if (empty($crmData['CloseDate']) === false) {\n $closeDate = Carbon::parse($crmData['CloseDate'])->format('Y-m-d');\n }\n\n $valueFieldName = 'Amount';\n if ($this->config->opportunity_value_field_id) {\n $valueFieldName = $this->config->opportunityValueField->crm_provider_id;\n }\n\n $data = [\n 'team_id' => $this->team->id,\n 'account_id' => $account->id ?? null,\n 'user_id' => $userId,\n 'owner_id' => $crmData['OwnerId'] ?? null,\n 'name' => mb_strimwidth($crmData['Name'] ?? '', 0, 128),\n 'value' => $crmData[$valueFieldName],\n 'currency_code' => CurrencyFormatter::formatCode($crmData['CurrencyIsoCode'] ?? null),\n 'close_date' => $closeDate,\n 'is_closed' => $crmData['IsClosed'],\n 'is_won' => $crmData['IsWon'],\n 'stage_id' => $stage?->id ?? null,\n 'record_type_id' => $recordType->id ?? null,\n 'remotely_created_at' => $createdDate,\n 'probability' => $crmData['Probability'] ?? null,\n 'forecast_category' => $crmData['ForecastCategoryName'] ?? null,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->opportunities(), $crmData['Id']);\n\n // Do not allow locked DB tables & other errors\n // to interrupt the process of reverting the trashed opportunities\n try {\n /** @var Opportunity $opportunity */\n $opportunity = $this->config->opportunities()\n ->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n // import external fields into crm_field_data if present\n $crmFields = $this->getOpportunitySyncableFields();\n\n $this->importOpportunityCrmFieldData($crmData, $crmFields, $opportunity->id);\n\n $this->handleObjectDeletion($opportunity, $crmData);\n\n if ($opportunity->trashed()) {\n return null;\n }\n\n if ($opportunity->wasRecentlyCreated) {\n MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());\n }\n\n return $opportunity;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->error('[Salesforce] importOpportunity failure.', [\n 'crm_provider_id' => $crmData['Id'],\n 'team_id' => $this->team->id,\n 'exception' => $exception->getMessage(),\n ]);\n\n $this->handleEntityDeletionByProviderId($this->config->opportunities(), $crmData);\n }\n\n return null;\n }\n\n /**\n * @inheritdoc\n */\n public function syncContacts(Carbon $since, ?Carbon $to = null): int\n {\n $syncCount = 0;\n $fields = $this->getAllFieldsAsArray('contact');\n if (\\in_array('Id', $fields, true) === false) {\n return $syncCount;\n }\n\n $query = '\n SELECT ' . rtrim(implode(',', $fields), ',') . '\n FROM Contact\n WHERE LastModifiedDate > :since\n ORDER BY LastModifiedDate ASC';\n\n try {\n $sfContacts = $this->queryHandler->query($query, [\n 'since' => $since->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($sfContacts as $sfContact) {\n // Only sync if previously imported.\n if ($this->hasContact($sfContact['Id'])) {\n $this->importContact($sfContact);\n $syncCount++;\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::CONTACT);\n\n return $syncCount;\n }\n\n /**\n * @inheritdoc\n */\n public function syncContact(string $crmId): ?Contact\n {\n $fields = $this->getAllFieldsAsArray('contact');\n if (! in_array('Id', $fields, true)) {\n $this->logger->info('[Salesforce] Sync contact cancelled. Fields are not available.', [\n 'crmId' => $crmId,\n 'userId' => $this->profile->getUserId(),\n ]);\n\n return null;\n }\n\n $sfContact = $this->getRecord('Contact', $crmId, $fields);\n\n return $this->importContact($sfContact);\n }\n\n private function importContact($crmData): ?Contact\n {\n if (! empty($crmData['IsDeleted'])) {\n $this->handleEntityDeletionByProviderId($this->config->contacts(), $crmData);\n\n return null;\n }\n\n $account = $this->resolveContactAccount($crmData);\n $countryCode = $this->resolveContactCountryCode($crmData, $account);\n [$parsedNumber, $ext] = $this->parseContactPhone($countryCode, $crmData);\n $mobileNumber = $this->parseContactMobile($countryCode, $crmData);\n $createdDate = empty($crmData['CreatedDate'])\n ? null\n : Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $data = [\n 'team_id' => $this->team->id,\n 'account_id' => $account->id ?? null,\n 'user_id' => $profile?->user_id,\n 'owner_id' => $crmData['OwnerId'] ?? null,\n 'name' => ($crmData['Name'] ?? null) !== null ? mb_strimwidth($crmData['Name'], 0, 100) : '',\n 'title' => ($crmData['Title'] ?? null) !== null ? mb_strimwidth($crmData['Title'], 0, 128) : null,\n 'email' => ($crmData['Email'] ?? null) !== null ? mb_strimwidth($crmData['Email'], 0, 191) : null,\n 'country_code' => $countryCode,\n 'phone' => $parsedNumber['phone'] ?? null,\n 'ext' => $ext,\n 'mobile_phone' => $mobileNumber,\n 'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(\n crmConfiguration: $this->config,\n crmProviderId: $crmData['Id'],\n modelType: Contact::class,\n fileName: $crmData['Id'],\n avatarText: $crmData['Name']\n ),\n 'remotely_created_at' => $createdDate,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->contacts(), $crmData['Id']);\n\n /** @var Contact $contact */\n $contact = $this->config->contacts()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n $this->handleObjectDeletion($contact, $crmData);\n\n return $contact->trashed() ? null : $contact;\n }\n\n private function resolveContactAccount(array $crmData): ?Account\n {\n if (! isset($crmData['AccountId'])) {\n return null;\n }\n\n return $this->config->accounts()\n ->where('crm_provider_id', (string) $crmData['AccountId'])\n ->first() ?? $this->syncAccount($crmData['AccountId']);\n }\n\n private function resolveContactCountryCode(array $crmData, ?Account $account): ?string\n {\n $countryCode = $crmData['MailingCountryCode'] ?? null;\n\n if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {\n $countryCode = null;\n }\n\n if ($countryCode === null && empty($crmData['MailingCountry']) === false) {\n $countryCode = $this->convertCountryNameToCode($crmData['MailingCountry'])\n ?? ($account?->country_code);\n }\n\n return $countryCode;\n }\n\n private function parseContactPhone(?string $countryCode, array $crmData): array\n {\n if (empty($crmData['Phone'])) {\n return [[], null];\n }\n\n $parsedNumber = parsePhoneNumber($countryCode, Str::limit($crmData['Phone'], 25, ''));\n $ext = empty($parsedNumber['ext']) ? null : Str::limit($parsedNumber['ext'], 10, '');\n\n return [$parsedNumber, $ext];\n }\n\n private function parseContactMobile(?string $countryCode, array $crmData): ?string\n {\n if (empty($crmData['MobilePhone'])) {\n return null;\n }\n\n return Str::limit(phone_e164($countryCode, $crmData['MobilePhone']), 25, '');\n }\n\n /**\n * @inheritdoc\n */\n public function syncOrganization(): void\n {\n $fields = [\n 'InstanceName',\n 'OrganizationType',\n 'IsSandbox',\n ];\n\n $orgValues = $this->getRecord('Organization', $this->config->crm_provider_id, $fields);\n\n $edition = null;\n switch ($orgValues['OrganizationType']) {\n case 'Developer Edition':\n $edition = Configuration::EDITION_DEVELOPER;\n\n break;\n\n case 'Professional Edition':\n $edition = Configuration::EDITION_PROFESSIONAL;\n\n break;\n\n case 'Enterprise Edition':\n $edition = Configuration::EDITION_ENTERPRISE;\n\n break;\n }\n\n $this->config->edition = $edition;\n $this->config->instance = $orgValues['InstanceName'];\n\n // XXX: How can this state be possible?\n if ($this->config->version === null) {\n $this->config->version = Client::MIN_API_VERSION;\n }\n\n $installedVersion = $this->getInstalledAppVersion();\n if ($installedVersion !== null) {\n $installedVersion = (string) $this->getInstalledAppVersion();\n }\n\n $this->config->installed_app_version = $installedVersion;\n\n $this->config->save();\n }\n\n public function getInstalledAppVersion(): ?string\n {\n try {\n $query = '\n SELECT\n SubscriberPackageVersion.MajorVersion,\n SubscriberPackageVersion.MinorVersion,\n SubscriberPackageVersion.PatchVersion,\n SubscriberPackageVersion.BuildNumber\n FROM\n InstalledSubscriberPackage\n WHERE\n SubscriberPackageId = :packageId\n ';\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'packageId' => self::INSTALLED_PACKAGE_ID,\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n // Grab version number.\n $version = $sfField['SubscriberPackageVersion']['MajorVersion'] .\n $sfField['SubscriberPackageVersion']['MinorVersion'] .\n $sfField['SubscriberPackageVersion']['PatchVersion'] .\n $sfField['SubscriberPackageVersion']['BuildNumber'];\n } catch (\\Exception) {\n $version = null;\n }\n\n return $version;\n }\n\n /**\n * Store transcripts as note.\n *\n * @throws \\Exception\n */\n public function createTranscriptNotes(Activity $activity): void\n {\n // For SF we also check if Log Notes is enabled.\n if ($this->profile->log_notes === Profile::LOG_NOTE_NONE) {\n return;\n }\n\n if ($activity->opportunity_id && $activity->prospect === null) {\n return;\n }\n\n try {\n $transcriptionData = $this->generateTranscription($activity);\n\n $noteMaxLength = $this->profile->log_notes === Profile::LOG_NOTE_ENHANCED\n ? self::ENHANCED_NOTE_MAX_LENGTH\n : self::CLASSIC_NOTE_MAX_LENGTH;\n\n $title = 'Transcript for ';\n $title .= $activity->title ?? $activity->activity_title;\n\n // Truncate Notes with max notes length because transcription text could be very long.\n $body = mb_strimwidth($transcriptionData, 0, $noteMaxLength);\n\n if ($activity->opportunity_id) {\n $objectId = $activity->opportunity->crm_provider_id;\n } else {\n $objectId = $activity->prospect->crm_provider_id;\n }\n\n $noteId = $this->saveNote($title, $body, $objectId);\n\n // Store crm logged id in transcription.\n $transcription = $activity->getTranscription();\n $transcription->crm_activity_id = $noteId;\n $transcription->save();\n } catch (\\Exception $e) {\n \\Sentry::captureException($e);\n }\n }\n\n public function saveNote(string $title, string $body, string $objectId, ?NoteObject $noteObject = null): ?string\n {\n $noteId = null;\n\n try {\n if ($this->profile->log_notes === Profile::LOG_NOTE_ENHANCED) {\n $noteId = $this->buildEnhancedNote($title, $body, $objectId);\n } else {\n $noteId = $this->buildClassicNote($title, $body, $objectId);\n }\n } catch (HttpNotFoundException $exception) {\n // The profile not having access to create Enhanced Notes. Set their preference to Classic.\n if ($this->profile->log_notes === Profile::LOG_NOTE_ENHANCED) {\n $this->profile->update([\n 'log_notes' => Profile::LOG_NOTE_CLASSIC,\n ]);\n }\n }\n\n return $noteId;\n }\n\n /**\n * This is using the \"Enhanced\" Notes feature, NOT the \"Notes & Attachments\" feature being deprecated.\n *\n * @url https://salesforce.stackexchange.com/questions/104408/how-can-i-create-an-account-note-or-contact-note-via-api-that-is-visible-in-sale\n */\n private function buildEnhancedNote(string $title, string $body, string $objectId): string\n {\n // Decode stored entities, escape HTML (without quoting), then convert line breaks for Salesforce formatting\n $decodedBody = html_entity_decode($body, ENT_QUOTES | ENT_HTML5);\n $sanitizedBody = htmlspecialchars($decodedBody, ENT_NOQUOTES, 'UTF-8', false);\n $content = nl2br($sanitizedBody, false);\n $note = [\n 'OwnerId' => $this->profile->crm_provider_id,\n 'Title' => $title,\n 'Content' => base64_encode($content),\n ];\n\n $noteId = $this->createRecord('ContentNote', $note);\n\n $link = [\n 'ContentDocumentId' => $noteId,\n 'LinkedEntityId' => $objectId,\n 'ShareType' => 'I',\n ];\n\n $this->createRecord('ContentDocumentLink', $link);\n\n return $noteId;\n }\n\n private function buildClassicNote(string $title, string $body, string $objectId): string\n {\n if (in_array($this->parseObjectType($objectId), [Field::OBJECT_TASK, Field::OBJECT_EVENT])) {\n $this->logger->info('[Salesforce] Summary not sent', [\n 'profile_id' => $this->profile->id,\n 'objectId' => $objectId,\n 'reason' => 'Classical Note does not support Task/Event relation',\n ]);\n\n return '';\n }\n\n $titleTrimmed = null;\n\n if (mb_strlen($title) > 80) {\n $titleTrimmed = substr($title, 0, 77) . '...';\n }\n $payload = [\n 'OwnerId' => $this->profile->crm_provider_id,\n 'IsPrivate' => false,\n 'Title' => $titleTrimmed ?? $title,\n 'Body' => $titleTrimmed ? $title . PHP_EOL . $body : $body,\n 'ParentId' => $objectId,\n ];\n\n return $this->createRecord('Note', $payload);\n }\n\n /**\n * @inheritdoc\n */\n public function find(string $name, array $scopes): array\n {\n if ($this->profile === null) {\n return [];\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $limitValues = ['limit' => $this->limit, 'offset' => $this->offset];\n $sosl = $queryBuilder->buildFindQuery($name, $scopes, $limitValues);\n\n $this->logger->info('[Salesforce] Find prospects', [\n 'profile_id' => $this->profile->id,\n 'sosl_query' => $sosl,\n 'search_string' => $name,\n 'scopes' => $scopes,\n ]);\n\n $data = Cache::remember($this->profile->id . $sosl, self::CACHE_TTL, function () use ($sosl) {\n $data = [];\n\n try {\n // Hit remote API.\n $objects = $this->queryHandler->search($sosl);\n\n // Build mapped list.\n foreach ($objects as $object) {\n $type = strtolower($object['attributes']['type']);\n\n $record = [\n 'crmId' => $object['Id'],\n 'name' => $object['Name'],\n 'prospectType' => $type,\n 'phoneNumbers' => [],\n 'crmUrl' => $this->generateProviderUrl($object['Id'], $type),\n ];\n\n switch ($type) {\n case 'lead':\n if (empty($object['Company']) === false) {\n $record['organization'] = $object['Company'];\n }\n\n if (empty($object['Title']) === false) {\n $record['title'] = $object['Title'];\n }\n\n $stage = $this->config->stages()\n ->where('type', Stage::TYPE_LEAD)\n ->where('name', $object['Status'])\n ->first();\n\n // Lazy create the stage.\n if ($stage === null) {\n $stage = $this->importStages([Stage::TYPE_LEAD], $object['Status']);\n }\n\n if ($stage) {\n $record += [\n 'stage' => [\n 'id' => $stage->id_string,\n 'name' => $stage->name,\n ],\n ];\n }\n\n if (empty($object['RecordTypeId']) === false) {\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $object['RecordTypeId'])\n ->first();\n\n if ($recordType) {\n $record += [\n 'recordType' => [\n 'id' => $recordType->id_string,\n 'name' => $recordType->name,\n ],\n ];\n }\n }\n\n break;\n\n case 'account':\n if (empty($object['Industry']) === false) {\n $record['industry'] = $object['Industry'];\n $record['detailsLine'] = $object['Industry'];\n }\n if (! empty($object['PersonEmail'])) {\n $record['detailsLine'] = $object['PersonEmail'];\n }\n\n break;\n\n case 'contact':\n // For contacts, we should try and fetch their account name too.\n if ($object['AccountId']) {\n // Cheaper to get this locally.\n $account = $this->config->accounts()\n ->where('crm_provider_id', $object['AccountId'])\n ->first(['name']);\n\n if ($account) {\n $record['organization'] = $account->name;\n }\n }\n\n if (! empty($object['IsPersonAccount']) && $object['Email']) {\n $record['detailsLine'] = $object['Email'];\n } else {\n if (empty($object['Title']) === false) {\n $record['title'] = $object['Title'];\n }\n }\n\n break;\n }\n\n // Add phone numbers to record.\n if (empty($object['Phone']) === false && $object['Phone']) {\n $record['phoneNumbers'][] = [\n 'number' => $object['Phone'],\n 'nationalFormat' => phone_national($this->profile->user->country_code, $object['Phone']),\n 'type' => 'phone',\n ];\n }\n\n if (empty($object['MobilePhone']) === false && $object['MobilePhone']) {\n $record['phoneNumbers'][] = [\n 'number' => $object['MobilePhone'],\n 'nationalFormat' => phone_national(\n $this->profile->user->country_code,\n $object['MobilePhone']\n ),\n 'type' => 'mobile',\n ];\n }\n\n $data[] = $record;\n }\n } catch (NoResultsException $e) {\n $data = [];\n }\n\n return $data;\n });\n\n return $data;\n }\n\n /**\n * @inheritdoc\n */\n public function findOpportunities(?string $crmAccountId, ?string $crmContactId, ?int $userId = null): array\n {\n $data = [];\n $ownerData = [];\n $ownerId = null;\n\n if ($crmAccountId === null) {\n return $data;\n }\n\n if ($userId) {\n $profileRepository = app(ProfileRepository::class);\n $profile = $profileRepository->findProfileByUserId($this->config, $userId);\n\n $ownerId = $profile instanceof Profile ? $profile->getCrmProviderId() : null;\n }\n\n try {\n // Perhaps their profile has no opportunity permissions.\n if ($this->profile === null || $this->profile->opportunity_fields === null) {\n return $data;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $query = $queryBuilder->buildFindOpportunitiesQuery();\n\n $objects = $this->queryHandler->query($query, ['accountId' => $crmAccountId]);\n\n foreach ($objects as $object) {\n $record = [\n 'crmId' => $object['Id'],\n 'name' => $object['Name'],\n 'won' => $object['IsWon'],\n 'closed' => $object['IsClosed'],\n ];\n\n $valueFieldName = 'Amount';\n if ($this->config->opportunity_value_field_id) {\n $valueFieldName = $this->config->opportunityValueField->crm_provider_id;\n }\n\n if (empty($object[$valueFieldName]) === false) {\n $currency = $object['CurrencyIsoCode'] ?? $this->config->default_currency;\n $value = formatCurrency($object[$valueFieldName], $currency);\n\n $record += [\n 'value' => $value,\n ];\n }\n\n $stage = $this->config->stages()\n ->where('type', Stage::TYPE_OPPORTUNITY)\n ->where('name', $object['StageName'])\n ->first();\n\n // Lazy create the stage.\n if ($stage === null) {\n $stage = $this->importStages([Stage::TYPE_OPPORTUNITY], $object['StageName']);\n }\n\n $record += [\n 'stage' => [\n 'id' => $stage->id_string,\n 'name' => $stage->name,\n ],\n ];\n\n if (empty($object['RecordTypeId']) === false) {\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $object['RecordTypeId'])\n ->first();\n\n if ($recordType) {\n $record += [\n 'recordType' => [\n 'id' => $recordType->id_string,\n 'name' => $recordType->name,\n ],\n ];\n }\n }\n\n if ($ownerId && isset($object['OwnerId']) && $object['OwnerId'] === $ownerId) {\n $ownerData[] = $record;\n }\n\n $data[] = $record;\n }\n } catch (NoResultsException $e) {\n return $data;\n }\n\n if (! empty($ownerData)) {\n return $ownerData;\n }\n\n return $data;\n }\n\n public function getContactRolesFromCrm(?Carbon $since = null): array\n {\n $roles = [];\n\n if ($this->profile === null) {\n return $roles;\n }\n\n $queryBuilder = app(QueryBuilder::class, ['profile' => $this->profile]);\n\n $query = $queryBuilder->buildGetContactRolesQuery($since);\n\n try {\n $objects = $this->queryHandler->query($query);\n\n foreach ($objects as $object) {\n $roles[] = [\n 'id' => $object['Id'],\n 'contactId' => $object['ContactId'],\n 'opportunityId' => $object['OpportunityId'],\n 'ownerId' => $object['Opportunity']['OwnerId'] ?? null,\n 'isPrimary' => $object['IsPrimary'],\n 'role' => $object['Role'],\n ];\n }\n } catch (NoResultsException) {\n // Just return an empty array.\n $this->logger->info('[Salesforce] No contact roles found', [\n 'since' => $since?->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n }\n\n return $roles;\n }\n\n public function syncContactRoles(Carbon $since): int\n {\n $contactRoleRepository = app(ContactRoleRepository::class);\n\n $crmContactRoles = $this->getContactRolesFromCrm(since: $since);\n $syncCount = 0;\n $contactRoles = [];\n\n foreach ($crmContactRoles as $crmContactRole) {\n $contactRoles[] = $this->importContactRole($crmContactRole);\n $syncCount++;\n }\n\n $contactRoleRepository->saveContactRoles($contactRoles);\n\n $this->syncRemotelyDeletedContactRoles();\n\n return $syncCount;\n }\n\n private function importContactRole(array $contactRole): array\n {\n $contact = $this->config->contacts()\n ->where('crm_provider_id', $contactRole['contactId'])\n ->first();\n\n if ($contact === null) {\n $contact = $this->syncContact($contactRole['contactId']);\n }\n\n $opportunity = $this->config->opportunities()\n ->where('crm_provider_id', $contactRole['opportunityId'])\n ->first();\n\n if ($opportunity === null) {\n $opportunity = $this->syncOpportunity($contactRole['opportunityId']);\n }\n\n $role = null;\n if (! empty($contactRole['role'])) {\n $role = mb_strimwidth($contactRole['role'], 0, 191);\n }\n\n return [\n 'crm_configuration_id' => $this->config->getId(),\n 'contact_id' => $contact->getId(),\n 'crm_provider_id' => $contactRole['id'],\n 'subject_type' => ContactRole::SUBJECT_TYPE_OPPORTUNITY,\n 'subject_id' => $opportunity->getId(),\n 'is_primary' => $contactRole['isPrimary'],\n 'role' => $role,\n ];\n }\n\n protected function syncRemotelyDeletedContactRoles(): bool\n {\n try {\n $deletedRemotely = $this->queryHandler->queryDeleted('OpportunityContactRole');\n } catch (NoResultsException $e) {\n return false;\n }\n\n $deletedOpportunities = $deletedRemotely->getResults();\n $deletedIds = array_column($deletedOpportunities, 'id');\n\n $contactRoleRepository = app(ContactRoleRepository::class);\n\n foreach (array_chunk($deletedIds, self::HARD_DELETE_CHUNK) as $chunk) {\n $contactRoleRepository->deleteContactRoles($chunk);\n\n $this->logger->info('[' . $this->getDisplayName() . '] Remotely deleted opportunities synced', [\n 'teamId' => $this->team->id_string,\n 'remotelyDeletedOpportunities' => $chunk,\n 'count' => count($chunk),\n ]);\n }\n\n return true;\n }\n\n /**\n * @inheritdoc\n */\n public function getTasks(string $objectType, string $objectId, ?string $opportunityId): array\n {\n $data = $objects = [];\n\n $hasWho = \\in_array($objectType, ['lead', 'contact']);\n $playbook = $this->getPlaybook($this->profile->user);\n $fields = array_merge(\n $this->profile->getFieldsAsArray(parent::OBJECT_TASK),\n $playbook && $playbook->activityField ? [$playbook->activityField->crm_provider_id] : []\n );\n\n // Query should default to any open call for that user.\n $query = '\n SELECT ' . implode(',', array_unique($fields)) . '\n FROM Task\n WHERE OwnerId = :ownerId\n AND IsArchived = false\n AND IsDeleted = false\n AND IsClosed = false\n AND (';\n\n if ($objectType === 'account') {\n // This covers tasks tied to a related contact or opportunity too.\n $query .= '\n AccountId = :accountId';\n }\n\n if ($hasWho) {\n $query .= '\n WhoId = :whoId';\n\n // If we are also going to check on a specific opportunity, set that up.\n if ($opportunityId) {\n $query .= ' OR WhatId = :whatId';\n }\n }\n\n $query .= ' ) ORDER BY LastModifiedDate DESC';\n\n try {\n $objects = $this->queryHandler->query($query, [\n 'ownerId' => $this->profile->crm_provider_id,\n 'whoId' => $objectId,\n 'whatId' => $opportunityId,\n 'accountId' => $objectId,\n ]);\n } catch (NoResultsException $e) {\n return $data;\n } finally {\n $this->logger->debug(sprintf('[Salesforce] Found %s tasks for query \"%s\"', count($objects), $query));\n }\n\n foreach ($objects as $object) {\n $dueDate = $object['ActivityDate'] ? Carbon::parse($object['ActivityDate'])->toIso8601String() : null;\n $data[] = [\n 'crmId' => $object['Id'],\n 'subject' => $object['Subject'],\n 'due' => $dueDate,\n 'type' => $object[$playbook->activityField->crm_provider_id],\n ];\n }\n\n return $data;\n }\n\n /**\n * @inheritdoc\n */\n public function getEvents(string $objectType, string $objectId, ?string $opportunityId): array\n {\n $data = $objects = [];\n $user = $this->profile?->user;\n if ($this->profile === null || $user === null) {\n return $data;\n }\n\n $hasWho = \\in_array($objectType, ['lead', 'contact']);\n $playbook = $this->getPlaybook($user);\n $fields = array_merge(\n $this->profile->getFieldsAsArray(parent::OBJECT_EVENT),\n $playbook && $playbook->activityField ? [$playbook->activityField->crm_provider_id] : []\n );\n\n // Query should default to any event starting in the last week and ending up until today owned by the user.\n $query = '\n SELECT ' . implode(',', array_unique($fields)) . '\n FROM Event\n WHERE OwnerId = :ownerId\n AND IsArchived = false\n AND IsAllDayEvent = false\n AND StartDateTime >= LAST_N_DAYS:7\n AND EndDateTime <= TODAY\n AND (';\n\n if ($objectType === 'account') {\n // This covers events tied to a related contact or opportunity too.\n $query .= '\n AccountId = :accountId';\n }\n\n if ($hasWho) {\n $query .= '\n WhoId = :whoId';\n\n // If we are also going to check on a specific opportunity, set that up.\n if ($opportunityId) {\n $query .= ' OR WhatId = :whatId';\n }\n }\n\n $query .= ' ) ORDER BY LastModifiedDate DESC';\n\n try {\n $objects = $this->queryHandler->query($query, [\n 'ownerId' => $this->profile->crm_provider_id,\n 'whoId' => $objectId,\n 'whatId' => $opportunityId,\n 'accountId' => $objectId,\n ]);\n } catch (NoResultsException $e) {\n return $data;\n } finally {\n $this->logger->debug(sprintf('[Salesforce] Found %s tasks for query \"%s\"', count($objects), $query));\n }\n\n foreach ($objects as $object) {\n $dueDate = $object['StartDateTime'] ? Carbon::parse($object['StartDateTime'])->toIso8601String() : null;\n\n $data[] = [\n 'crmId' => $object['Id'],\n 'subject' => $object['Subject'],\n 'due' => $dueDate,\n 'type' => $object[$playbook->activityField->crm_provider_id],\n ];\n }\n\n return $data;\n }\n\n /**\n * Try to find CRM Objects using email address\n *\n * @return null|array{\n * Lead|null,\n * Account|null,\n * Opportunity|null,\n * Contact|null,\n * Stage|null,\n * string|null\n * }\n */\n public function matchExactlyByEmail(string $email, ?int $userId = null): ?array\n {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $sosl = $queryBuilder->buildMatchByQuery($email, Field::TYPE_EMAIL);\n if ($sosl === null) {\n return null;\n }\n\n try {\n $objects = $this->queryHandler->search($sosl);\n $objects = $this->queryHandler->prioritiseResults(\n $objects,\n $email,\n QueryHandler::PRIORITISE_EMAIL\n );\n\n $data = $this->convertCrmData($objects, $userId);\n\n return ! empty(array_filter($data)) ? $data : null;\n } catch (NoResultsException $e) {\n // Try the account next.\n if ($this->profile->account_fields === null) {\n return null;\n }\n }\n\n return null;\n }\n\n public function getDomain(string $email): ?string\n {\n // SF improved search - strip the domain extension, min domain name length 4\n return $this->getCompanyNameFromEmail(email: $email, minNameLength: 4);\n }\n\n /**\n * Try to find CRM objects using domain name of the email address\n *\n * @return null|array{\n * Lead|null,\n * Account|null,\n * Opportunity|null,\n * Contact|null,\n * Stage|null,\n * string|null\n * }\n */\n public function matchByDomain(string $domain, ?int $userId = null): ?array\n {\n $companyName = $domain;\n\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $sosl = $queryBuilder->buildMatchByDomainQuery($companyName);\n\n try {\n $objects = $this->queryHandler->search($sosl);\n\n $data = $this->convertCrmData($objects, $userId);\n\n return ! empty(array_filter($data)) ? $data : null;\n } catch (NoResultsException) {\n return null;\n }\n }\n\n public function matchByPhone(string $phone, ?string $rawPhoneNumber = null, ?int $userId = null): ?array\n {\n // Don't bother looking up numbers that are masked.\n if (str_contains($phone, '**')) {\n return null;\n }\n\n if ($this->isPhoneNumberOfTeamMember($phone)) {\n return null;\n }\n\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $phoneNational = phone_national(null, $phone) ?? '';\n $possiblePhoneFormats = collect([\n preg_replace('/\\D/', '', ltrim($phone, '0+')),\n preg_replace('/\\D/', '', $phoneNational),\n formatDashPhoneNumber($phone),\n $phoneNational,\n ])\n ->filter() // Removes null and empty strings\n ->unique()\n ->values();\n\n foreach ($possiblePhoneFormats as $phone) {\n $sosl = $queryBuilder->buildMatchByQuery($phone, Field::TYPE_PHONE);\n if ($sosl === null) {\n continue;\n }\n\n try {\n $objects = $this->queryHandler->search($sosl);\n $objects = $this->queryHandler->prioritiseResults(\n $objects,\n $phone,\n QueryHandler::PRIORITISE_PHONE\n );\n\n return $this->convertCrmData($objects, $userId);\n } catch (NoResultsException) {\n continue;\n }\n }\n\n return null;\n }\n\n private function isPhoneNumberOfTeamMember(string $phone): bool\n {\n $teamRepository = app(TeamRepository::class);\n $user = $teamRepository->findTeamMemberByPhone($this->team, $phone);\n\n if ($user instanceof User) {\n return true;\n }\n\n return false;\n }\n\n protected function getCacheKey(string $object, ?int $userId = null): ?string\n {\n $key = $this->profile->id . $object;\n $keySuffix = $this->getOwnerKeySuffix($userId);\n\n return $key . $keySuffix;\n }\n\n private function getOwnerKeySuffix(?int $userId = null): string\n {\n return $userId === null ? '' : (string) $userId;\n }\n\n /** Determine the CRM Objects which represent the call activity. */\n public function matchByName(string $name, ?int $userId = null): ?array\n {\n // Don't waste time searching for single character strings.\n if (\\strlen($name) <= 1) {\n return null;\n }\n\n if ($this->profile === null) {\n return null;\n }\n\n $cacheKey = $this->getCacheKey($name, $userId);\n\n $result = Cache::remember($cacheKey, 60, function () use ($name, $userId) {\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $sosl = $queryBuilder->buildMatchByQuery($name, 'name');\n if ($sosl === null) {\n return false;\n }\n\n try {\n $objects = $this->queryHandler->search($sosl);\n } catch (NoResultsException $e) {\n return false;\n }\n\n $objects = $this->queryHandler->prioritiseResults(\n $objects,\n $name,\n QueryHandler::PRIORITISE_NAME\n );\n\n $data = $this->convertCrmData($objects, $userId);\n\n return (! empty(array_filter($data))) ? $data : false;\n });\n\n return is_array($result) ? $result : null;\n }\n\n /**\n * @return array{\n * Lead|null,\n * Account|null,\n * Opportunity|null,\n * Contact|null,\n * Stage|null,\n * string|null\n * }\n */\n protected function convertCrmData(QueryIterator $objects, ?int $userId = null): array\n {\n $lead = null;\n $contact = null;\n $opportunity = null;\n $account = null;\n $stage = null;\n $countryCode = null;\n\n if ($objects->count() > 0) {\n $object = $objects->current();\n\n if ($object['attributes']['type'] === 'Lead') {\n $lead = $this->importLead($object);\n\n // Lead might not be imported if the Stage is null for example.\n if ($lead) {\n $countryCode = $lead->country_code;\n $stage = $lead->stage;\n }\n } else {\n if ($object['attributes']['type'] === 'Contact') {\n $contact = $this->importContact($object);\n $account = $contact?->account;\n } else {\n $account = $this->importAccount($object);\n }\n\n if ($contact && $contact->country_code) {\n $countryCode = $contact->country_code;\n } elseif ($account) {\n $countryCode = $account->country_code;\n }\n\n try {\n $sfOpportunities = $this->findOpportunities(\n $account?->getCrmProviderId(),\n $contact?->getCrmProviderId(),\n $userId\n );\n\n // Take the first opportunity, which will be ordered as priority based on their settings.\n if (! empty($sfOpportunities)) {\n // Persist this remote object.\n $opportunity = $this->syncOpportunity($sfOpportunities[0]['crmId']);\n $stage = $opportunity?->stage;\n }\n } catch (Exception) {\n // Nothing to see here.\n }\n }\n }\n\n return [\n $lead,\n $account,\n $opportunity,\n $contact,\n $stage,\n $countryCode,\n ];\n }\n\n /**\n * @inheritdoc\n */\n public function updateStage($crmObject, Stage $stage): void\n {\n if ($stage->type === Stage::TYPE_LEAD) {\n $objectType = 'Lead';\n $objectId = $crmObject->crm_provider_id;\n $objectStageType = 'Status';\n } else {\n $objectType = 'Opportunity';\n $objectId = $crmObject->crm_provider_id;\n $objectStageType = 'StageName';\n }\n\n $headers = [];\n if ($this->config->trigger_assignment_rules === false) {\n // @see: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/headers_autoassign.htm\n $headers = [\n 'Sforce-Auto-Assign' => 'false',\n ];\n }\n\n $this->updateRecord($objectType, $objectId, [$objectStageType => $stage->name], $headers);\n }\n\n public function parseObjectType(string $objectId): string\n {\n if (Str::startsWith($objectId, '001')) {\n return 'account';\n }\n\n if (Str::startsWith($objectId, '003')) {\n return 'contact';\n }\n\n if (Str::startsWith($objectId, '00Q')) {\n return 'lead';\n }\n\n if (Str::startsWith($objectId, '006')) {\n return 'opportunity';\n }\n\n if (Str::startsWith($objectId, '00U')) {\n return 'event';\n }\n\n if (Str::startsWith($objectId, '00T')) {\n return 'task';\n }\n\n throw new \\InvalidArgumentException('Unsupported Object Type');\n }\n\n public function syncProfiles(?User $userToSearch = null): ?Profile\n {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, ['profile' => $this->profile]);\n $query = $queryBuilder->buildGetUsersQuery($userToSearch);\n\n try {\n $salesforceUsers = $this->queryHandler->query($query, [\n 'active' => true,\n ]);\n } catch (NoResultsException $e) {\n $this->logger->info('[Salesforce] Sync Profiles. No users found', [\n 'query' => $query,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $teamRepository = app(TeamRepository::class);\n $customRules = $this->getCustomProfileRules($teamRepository);\n\n foreach ($salesforceUsers as $crmUser) {\n if ($crmUser['Email'] === null) {\n continue;\n }\n\n if (! $this->customProfileValidation($crmUser, $customRules)) {\n continue;\n }\n\n $user = $teamRepository->findActiveTeamMemberByEmail($this->team, $crmUser['Email']);\n\n if (! $user instanceof User) {\n continue;\n }\n\n $edition = $crmUser['UserPreferencesLightningExperiencePreferred']\n ? Profile::EDITION_LIGHTNING\n : Profile::EDITION_CLASSIC;\n\n $profileRepository = app(ProfileRepository::class);\n $profile = $profileRepository->updateOrCreateProfile(\n $user,\n [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmUser['Id'],\n ],\n [\n 'user_id' => $user->getId(),\n 'edition' => $edition,\n 'has_external_cti' => ! empty($crmUser['CallCenterId']),\n 'crm_profile_id' => $crmUser['ProfileId'],\n ]\n );\n\n if ($userToSearch instanceof User && $userToSearch->getId() === $user->getId()) {\n return $profile;\n }\n }\n\n // Clean up inactive profiles\n try {\n $this->archiveInactiveProfiles();\n } catch (\\Exception $e) {\n $this->logger->warning('[Salesforce] Profile archiving failed', [\n 'teamId' => $this->team->getUuid(),\n 'reason' => $e->getMessage(),\n ]);\n }\n\n return null;\n }\n\n public function generateProviderUrl(string $providerId, string $objectType): ?string\n {\n $url = null;\n\n // For Salesforce it's easy, we just point every object to the apex domain and they handle it.\n switch ($objectType) {\n case 'lead':\n case 'account':\n case 'contact':\n case 'opportunity':\n case 'task':\n case 'event':\n case 'activity':\n\n $url = $this->config->crm_base_url . '/' . $providerId;\n\n break;\n }\n\n return $url;\n }\n\n public function buildTaskSearchFields(): array\n {\n return ['Id', 'WhoId', 'WhatId', 'AccountId'];\n }\n\n public function getTaskByFilterConditions(\n array $fields,\n array $filters,\n bool $bulkSearch = false,\n bool $strictFilters = true\n ): ?array {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $query = $queryBuilder->buildSearchTaskQuery($fields, $filters, $bulkSearch, $strictFilters);\n\n try {\n if (! $bulkSearch) {\n $objects = $this->queryHandler->query($query, $filters);\n if ($objects->count() === 1) {\n return $objects->current();\n }\n }\n\n if ($bulkSearch) {\n $objects = $this->queryHandler->query($query);\n $records = [];\n foreach ($objects as $record) {\n $key = $record[end($fields)];\n $records[$key] = $record;\n }\n\n return $records;\n }\n } catch (\\Exception $e) {\n $this->logger->info('[Salesforce] Failed to execute query', [\n 'query' => $query,\n 'error' => $e->getMessage(),\n ]);\n }\n\n return null;\n }\n\n public function mapCrmObjects(array $task): array\n {\n $activityData = [];\n\n if (! empty($task['WhoId'])) {\n $type = $this->parseObjectType($task['WhoId']);\n $activityData[$type] = $task['WhoId'];\n }\n if (! empty($task['AccountId'])) {\n $activityData['account'] = $task['AccountId'];\n }\n if (! empty($task['WhatId'])) {\n $activityData['opportunity'] = $task['WhatId'];\n }\n\n return $activityData;\n }\n\n /**\n * Get SF task by Outreach call id.\n */\n public function getTaskByFilter(\n string $activityFieldType,\n array $filters,\n string $operator = '=',\n array $additionalFields = []\n ): ?array {\n $data = [];\n\n try {\n // Default (base) fields.\n $fields = ['Id', 'Subject', 'Description', 'ActivityDate', 'WhoId', 'WhatId', $activityFieldType];\n\n foreach ($additionalFields as $additionalField) {\n $fields[] = $additionalField->crm_provider_id;\n }\n\n $fields = array_unique($fields);\n\n // Find task with the same Outreach id as the call id.\n $query = 'SELECT ' . implode(',', $fields) . '\n FROM Task\n WHERE IsArchived = false AND IsDeleted = false';\n\n foreach ($filters as $key => $value) {\n $key = preg_quote($key, '/');\n $key = str_replace(['\\'', '\"'], '', $key);\n // Prepare the substitution.\n $strKey = \":$key\";\n\n $query .= \" AND $key $operator $strKey\";\n }\n\n $query .= ' ORDER BY LastModifiedDate DESC LIMIT 1';\n\n $objects = $this->queryHandler->query($query, $filters);\n\n // There should be only one task related to this call if any.\n if ($objects->count() === 1) {\n $object = $objects->current();\n\n $dueDate = $object['ActivityDate'] ? Carbon::parse($object['ActivityDate'])->toIso8601String() : null;\n\n $data = array_merge($object, [\n 'crmId' => $object['Id'],\n 'subject' => $object['Subject'],\n 'summary' => $object['Description'],\n 'due' => $dueDate,\n 'Type' => $object[$activityFieldType],\n ]);\n }\n } catch (NoResultsException $e) {\n // Filters don't match any records.\n } catch (ServiceUnavailableException $serviceUnavailableException) {\n // Service cannot be queried. We should probably log this.\n }\n\n return $data;\n }\n\n /**\n * Get Salesforce fields including datetime fields\n *\n * @param $objectType\n */\n private function getAllFieldsAsArray($objectType): array\n {\n $basicFields = [];\n // Not all users have access to all object fields.\n if ($this->profile->{$objectType . '_fields'}) {\n $basicFields = explode(',', $this->profile->{$objectType . '_fields'});\n }\n\n $extraFields = [\n 'CreatedDate',\n 'LastModifiedDate',\n 'IsDeleted',\n ];\n\n if ($objectType === self::OBJECT_OPPORTUNITY\n && $this->config->opportunity_value_field_id\n && ! in_array($this->config->opportunityValueField->crm_provider_id, $basicFields)\n ) {\n $extraFields[] = $this->config->opportunityValueField->crm_provider_id;\n }\n\n return array_unique(array_merge($basicFields, $extraFields));\n }\n\n /**\n * Generate transcription for activity description.\n */\n private function generateTranscription(Activity $activity): string\n {\n if (! ($this->config->store_transcript)) {\n // If sending transcription to activity toggle is disabled\n return '';\n }\n\n return $this->transcriptionService\n ->findTranscriptionByActivity($activity)\n ->map(static function (array $transcriptionSegment): string {\n return $transcriptionSegment['formattedStartsAt'] . ' | ' . $transcriptionSegment['transcript'];\n })\n ->implode(PHP_EOL);\n }\n\n /**\n * Find related Salesforce event based on activity data\n *\n * @return array<string>\n */\n public function fetchRelatedActivity(Activity $activity): array\n {\n $this->logger->info('[Salesforce] Searching for related activity', [\n 'activityId' => $activity->getUuid(),\n 'ownerId' => $this->profile?->crm_provider_id,\n ]);\n\n $sfEvent = $this->fetchRelatedEvent($activity);\n if (empty($sfEvent)) {\n $this->logger->info('[Salesforce] No related activity found', [\n 'activityId' => $activity->getUuid(),\n 'ownerId' => $this->profile?->crm_provider_id,\n 'account' => $activity->hasAccount()\n ? $activity->getAccount()->getCrmProviderId()\n : null,\n ]);\n\n return [];\n }\n\n return $sfEvent;\n }\n\n public function fetchAndAssociateRelatedActivity(Activity $activity): ?Activity\n {\n if ($activity->isTypeConference() === false) {\n return null;\n }\n\n if ($activity->hasActualStartTime() === false && $activity->hasScheduledStartTime() === false) {\n return null;\n }\n\n if (! $activity->hasProspect()) {\n $this->logger->info('[Salesforce] Skip look up, Activity not linked to Lead, Contact or Account', [\n 'activityId' => $activity->getUuid(),\n ]);\n\n return null;\n }\n\n $playbook = $this->getPlaybook($activity->getUser());\n if ($playbook !== null && $playbook->getActivityType() === Playbook::ACTIVITY_TYPE_TASK) {\n $this->logger->info('[Salesforce] Skip auto-sync for task-based playbook', [\n 'activityUuid' => $activity->getUuid(),\n 'playbookId' => $playbook->getId(),\n 'playbookType' => $playbook->getActivityType(),\n ]);\n\n return null;\n }\n\n try {\n $sfEvent = $this->fetchRelatedActivity($activity);\n if (empty($sfEvent)) {\n return null;\n }\n\n [$activityField, $activityType] = $this->resolveActivityTypeFromEvent($activity, $sfEvent);\n\n $this->logger->info('[Salesforce] Found related activity', [\n 'activityId' => $activity->getUuid(),\n 'sfEvent' => $sfEvent['Id'],\n 'activityFieldName' => $activityField,\n 'crmActivityType' => ($activityField !== null && isset($sfEvent[$activityField]))\n ? $sfEvent[$activityField]\n : null,\n 'activityType' => $activityType,\n ]);\n\n $userId = $this->findRelatedActivityUserId($activity, $sfEvent);\n\n if ($activity->getUserId() !== $userId) {\n $this->logger->info('[Salesforce] Updating meeting owner', [\n 'activityId' => $activity->getUuid(),\n 'oldUserId' => $activity->getUserId(),\n 'newUserId' => $userId,\n ]);\n }\n\n $this->updateSfEventDescription($activity, $sfEvent);\n\n $activity->update([\n 'user_id' => $userId,\n 'crm_provider_id' => $sfEvent['Id'],\n 'playbook_category_id' => $activityType->id ?? $activity->getCategory()?->getId(),\n ]);\n\n $this->logger->info('[Salesforce] Activity updated', [\n 'activityId' => $activity->getUuid(),\n ]);\n\n return $activity;\n } catch (\\Exception $exception) {\n \\Sentry::captureException($exception);\n\n throw $exception;\n }\n }\n\n /**\n * @param array<string, mixed> $sfEvent\n *\n * @return array{0: string|null, 1: mixed}\n */\n private function resolveActivityTypeFromEvent(Activity $activity, array $sfEvent): array\n {\n $activityField = $this->getActivityFieldName($activity);\n $activityType = null;\n\n if ($activityField !== null && ! empty($sfEvent[$activityField])) {\n $playbook = $this->getPlaybook($activity->getUser());\n $activityType = $this->getPlaybookCategory($playbook, strval($sfEvent[$activityField]));\n }\n\n return [$activityField, $activityType];\n }\n\n /**\n * @param array<string> $sfEvent\n */\n private function findRelatedActivityUserId(Activity $activity, array $sfEvent): int\n {\n $userId = $activity->getUserId();\n\n if (empty($sfEvent['OwnerId']) === false) {\n $profile = $this\n ->config\n ->profiles()\n ->where('crm_provider_id', $sfEvent['OwnerId'])\n ->get()\n ->filter(static function (Profile $profile) use ($activity): bool {\n if (! $activity->isTypeConference()) {\n return ! empty($profile->user) ? $profile->user->isStatusActive() : false;\n }\n\n $participants = $activity->getParticipants();\n\n return ! empty($profile->user)\n ? $profile->user->isStatusActive()\n && $profile->user->hasPermission(PermissionEnum::RECORD_MEETING)\n && $participants->contains('user_id', $profile->user_id)\n : false;\n })\n ->first();\n\n if ($profile) {\n $userId = $profile->user_id;\n }\n }\n\n return $userId;\n }\n\n /**\n * @param array<string, mixed> $sfEvent\n */\n private function updateSfEventDescription(Activity $activity, array $sfEvent): void\n {\n try {\n if (str_contains($sfEvent['Description'], $activity->id_string)) {\n return;\n }\n\n $payload = [\n 'Description' => $sfEvent['Description']\n . PHP_EOL\n . PHP_EOL\n . new DecorateActivity()->generateDescription($activity),\n ];\n\n $this->logger->info('[Salesforce] Update record', [\n 'activityId' => $activity->getUuid(),\n 'sfEvent' => $sfEvent['Id'],\n 'payload' => $payload,\n ]);\n\n $payload = array_merge(\n $payload,\n $this->payloadBuilder->fetchCustomFieldData($activity, Field::OBJECT_EVENT)\n );\n\n $this->updateRecord('Event', $sfEvent['Id'], $payload);\n } catch (\\Exception) {\n $this->logger->error('[Salesforce] Failed to update record', [\n 'activityUuid' => $activity->getUuid(),\n 'sfEvent' => $sfEvent['Id'],\n ]);\n }\n }\n\n /**\n * Returns the most recently modified Event within time range (if any).\n *\n * @return array|null An Event record from Salesforce.\n */\n private function fetchRelatedEvent(Activity $activity): ?array\n {\n $ownerId = $this->profile?->crm_provider_id;\n if ($ownerId === null) {\n return [];\n }\n\n /** @var ?Carbon $from */\n /** @var ?Carbon $to */\n [$from, $to] = $this->getFromToDates($activity);\n\n try {\n $whoId = null;\n $hasWho = $activity->lead_id || $activity->contact_id;\n if ($hasWho) {\n $whoId = $activity->hasLead()\n ? $activity->getLead()->crm_provider_id\n : $activity->getContact()->crm_provider_id;\n }\n\n if ($hasWho === false && $activity->account_id === null) {\n return null;\n }\n\n $query = $this->buildFetchRelatedEventQuery($activity);\n\n $objects = $this->queryHandler->query($query, [\n 'ownerId' => $ownerId,\n 'whoId' => $whoId,\n 'whatId' => $activity->hasOpportunity() ? $activity->getOpportunity()->crm_provider_id : null,\n 'accountId' => $activity->hasAccount() ? $activity->getAccount()->crm_provider_id : null,\n 'from' => $from?->format('Y-m-d\\TH:i:s\\Z'),\n 'to' => $to?->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($objects as $object) {\n return $object;\n }\n } catch (NoResultsException $e) {\n return [];\n }\n\n return [];\n }\n\n private function getFromToDates(Activity $activity): array\n {\n $from = null;\n $to = null;\n\n /** @var ?CalendarEvent $calendarEvent */\n $calendarEvent = $activity->calendarEvent()->first();\n if ($calendarEvent !== null) {\n $from = $calendarEvent->getStartTime();\n $to = $calendarEvent->getEndTime();\n }\n\n // For non-calendar imported activities\n // Also double check if calendar event dates could be null?\n // If null use what we've got so far\n if ($from === null || $to === null) {\n $from = $activity->hasScheduledStartTime()\n ? $activity->getScheduledStartTime()\n : $activity->getActualStartTime();\n $to = $activity->hasScheduledEndTime()\n ? $activity->getScheduledEndTime()->addMinutes(15)\n : $activity->getActualEndTime();\n }\n\n return [$from, $to];\n }\n\n /**\n * Determines the appropriate activity field name for querying Salesforce events.\n *\n * This method follows a hierarchy to determine the field name:\n * 1. Uses the playbook's activity field if it exists and is in the profile's accessible fields\n * 2. Falls back to the default activity field if the profile has no event fields configured\n * 3. Returns null if no suitable field is found\n *\n * @param Activity $activity The activity to determine the field for\n *\n * @return string|null The field name to use in queries, or null if none is available\n */\n private function getActivityFieldName(Activity $activity): ?string\n {\n if ($this->profile === null) {\n $this->logger->warning('[Salesforce] Cannot determine activity field - profile not found', [\n 'activityId' => $activity->getUuid(),\n ]);\n\n return null;\n }\n\n $profileEventFields = $this->profile->getFieldsAsArray('event');\n\n if (empty($profileEventFields)) {\n $defaultActivityField = $this->getDefaultActivityField(Field::OBJECT_EVENT);\n $defaultFieldName = $defaultActivityField?->getAttribute('crm_provider_id');\n // Profile not yet synced — fall back to the default activity field.\n // There is a small chance that the profile won't have Default Activity Type field access\n // in which case the query will fail.\n // This is however an edge case and should be reviewed for profile sync issues.\n Sentry::withScope(function (\\Sentry\\State\\Scope $scope) use ($defaultFieldName): void {\n $scope->setContext('details', [\n 'profileId' => $this->profile->id,\n 'defaultField' => $defaultFieldName,\n ]);\n Sentry::captureMessage(\n '[Salesforce] Profile event fields empty, falling back to default activity field.',\n \\Sentry\\Severity::warning()\n );\n });\n\n return $defaultFieldName;\n }\n\n $playbook = $this->getPlaybook($activity->getUser());\n\n if (! is_null($playbook) && ! is_null($playbook->getActivityField())) {\n $playbookFieldName = $playbook->getActivityField()->getAttribute('crm_provider_id');\n\n if (in_array($playbookFieldName, $profileEventFields, true)) {\n return $playbookFieldName;\n }\n\n $this->logger->warning('[Salesforce] Playbook activity field not found in profile fields', [\n 'activityId' => $activity->getUuid(),\n 'playbookField' => $playbookFieldName,\n 'profileId' => $this->profile->id,\n ]);\n }\n\n return null;\n }\n\n private function buildFetchRelatedEventQuery(Activity $activity): string\n {\n $hasWho = $activity->lead_id || $activity->contact_id;\n\n $activityFieldName = $this->getActivityFieldName($activity);\n $fields = array_filter(['Id', 'Description', 'OwnerId', $activityFieldName]);\n\n $ownerCondition = '(OwnerId = :ownerId OR CreatedById = :ownerId)';\n\n $query = '\n SELECT ' . implode(',', $fields) . '\n FROM Event\n WHERE ' . $ownerCondition . '\n AND IsArchived = false\n AND IsAllDayEvent = false\n AND StartDateTime >= :from\n AND EndDateTime <= :to\n AND (';\n\n $operator = '';\n if ($activity->account_id) {\n // This covers events tied to a related contact or opportunity too.\n $query .= 'AccountId = :accountId';\n\n $operator = ' OR ';\n }\n\n if ($hasWho) {\n $query .= $operator . 'WhoId = :whoId';\n\n // If we are also going to check on a specific opportunity, set that up.\n if ($activity->opportunity_id) {\n $query .= ' OR WhatId = :whatId';\n }\n }\n\n $query .= ') ORDER BY LastModifiedDate DESC';\n\n return $query;\n }\n\n public function fetchProspect(array $task): array\n {\n $lead = $account = $opportunity = $contact = $stage = $countryCode = null;\n $externalId = $task['WhoId'] ?? null;\n\n // Lead or Contact\n if ($externalId) {\n try {\n [$lead, $account, $opportunity, $contact, $stage, $countryCode] = $this->parseRecords($externalId);\n } catch (\\InvalidArgumentException $exception) {\n // Invalid object type.\n }\n }\n\n // If we happen to know the opportunity or account from the Task, figure that out.\n if (empty($task['WhatId']) === false) {\n // WhatId could be either Account ID or Opportunity ID.\n // If WhatId is Opportunity ID, get the opportunity and stage from the CRM.\n try {\n [, $account, $opportunity, , $stage, ] = $this->parseRecords($task['WhatId']);\n } catch (\\InvalidArgumentException $exception) {\n // Invalid object type.\n }\n }\n\n return [$lead, $account, $opportunity, $contact, $stage, $countryCode];\n }\n\n /**\n * Save activity transcription summary as note\n */\n public function saveTranscriptionSummaryAsNote(\n ActivityContract $activity,\n string $title,\n string $body,\n ?string $objectId,\n ?NoteObject $noteObject = null,\n ): ?string {\n return $this->saveNote($title, $body, (string) $objectId);\n }\n\n public function getObjectByFilterConditions(string $objectType, array $fields, array $filters): ?array\n {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $query = $queryBuilder->buildObjectSearchQuery($objectType, $fields, $filters);\n\n try {\n $objects = $this->queryHandler->query($query, $filters);\n if ($objects->count() === 1) {\n return $objects->current();\n }\n } catch (\\Exception $e) {\n $this->logger->info('[Salesforce] Failed to execute query', [\n 'query' => $query,\n 'error' => $e->getMessage(),\n ]);\n }\n\n return null;\n }\n\n private function getCustomProfileRules(TeamRepository $teamRepository): array\n {\n $teamSettings = $teamRepository->getTeamSetting($this->team, 'custom_profile_validation');\n\n if ($teamSettings instanceof TeamSettings && $teamSettings->getValueType() === 'array') {\n $customRules = json_decode($teamSettings->getValue(), true);\n if (is_array($customRules)) {\n return $customRules;\n }\n }\n\n return [];\n }\n\n private function customProfileValidation(array $crmUser, array $customRules): bool\n {\n foreach ($customRules as $customRule) {\n if ($crmUser[$customRule['field']] !== $customRule['value']) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * When syncing Contact / Lead / Account / Opportunity / Stage crm entities,\n * validate and restore locally trashed objects,\n * before updating them. Objects are identified by CrmProviderId\n */\n private function restoreAnyTrashedEntity(HasMany $targetEntity, string $crmProviderId): void\n {\n $recordExists = $targetEntity->withTrashed()->where(['crm_provider_id' => $crmProviderId])->first();\n if ($recordExists && $recordExists->trashed()) {\n $recordExists->restore();\n }\n }\n\n #[\\Override] public function supportsNotes(): bool\n {\n return true;\n }\n\n private function getOwnerProfile(?string $ownerId): ?Profile\n {\n if ($ownerId === null) {\n return null;\n }\n\n return $this->config->profiles()\n ->where('crm_provider_id', $ownerId)\n ->first();\n }\n}","depth":4,"bounds":{"left":0.13863032,"top":0.070231445,"width":0.38597074,"height":0.92976856},"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Services\\Crm\\Salesforce;\n\nuse Carbon\\Carbon;\nuse Exception;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany;\nuse Illuminate\\Events\\Dispatcher;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Illuminate\\Support\\Facades\\Log;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Component\\Country\\CountriesMap;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Contracts\\Repositories\\TeamRepository;\nuse Jiminny\\Contracts\\Services\\Crm\\FetchRelatedActivityInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\ImportsBusinessProcessesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\LayoutManagementInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\MatchCrmEntitiesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\Provider\\SalesforceBatchSyncInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\Provider\\SalesforceInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\RemoteEntityLookupInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\RemoteEntityManipulationInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\RemoteNoteEntityManipulationInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SearchTaskInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SendSummaryToCrmInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SettingsInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SupportsObjectTypeParseInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SyncCrmEntitiesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SyncCrmProfileRecordTypesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\VerifyTaskExistsInterface;\nuse Jiminny\\Enums\\CrmObject;\nuse Jiminny\\Events\\Activities\\Crm\\LeadConverted;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Exceptions\\HttpBadRequestException;\nuse Jiminny\\Exceptions\\HttpNotFoundException;\nuse Jiminny\\Exceptions\\NoResultsException;\nuse Jiminny\\Exceptions\\ServiceUnavailableException;\nuse Jiminny\\Jobs\\Crm\\NoteObject;\nuse Jiminny\\Jobs\\Crm\\MatchActivitiesToNewOpportunity;\nuse Jiminny\\Models\\Account;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Calendar\\CalendarEvent;\nuse Jiminny\\Models\\Contact;\nuse Jiminny\\Models\\Contracts\\ActivityContract;\nuse Jiminny\\Models\\Crm\\BusinessProcess;\nuse Jiminny\\Models\\Crm\\Configuration;\nuse Jiminny\\Models\\Crm\\ContactRole;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\Profile;\nuse Jiminny\\Models\\Crm\\RecordType;\nuse Jiminny\\Models\\Lead;\nuse Jiminny\\Models\\Opportunity;\nuse Jiminny\\Models\\Playbook;\nuse Jiminny\\Models\\SocialAccount;\nuse Jiminny\\Models\\Stage;\nuse Jiminny\\Models\\TeamSettings;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\Crm\\ContactRoleRepository;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\Crm\\ProfileRepository;\nuse Jiminny\\Repositories\\Crm\\RecordTypeFieldValuesRepository;\nuse Jiminny\\Services\\Avatar\\ProspectPhotoPathService;\nuse Jiminny\\Services\\Crm\\BaseService;\nuse Jiminny\\Services\\Crm\\Helpers\\ArrayIterator;\nuse Jiminny\\Services\\Crm\\MatchDomainByEmailInterface;\nuse Jiminny\\Services\\Crm\\OpportunitySyncStrategyResolver;\nuse Jiminny\\Services\\Crm\\ResolveCompanyNameByEmailTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\Fields\\FieldHelper;\nuse Jiminny\\Services\\Crm\\Salesforce\\Fields\\FieldTypeConverter;\nuse Jiminny\\Services\\Crm\\Salesforce\\Fields\\ValueNormalizer;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\FollowupActivityTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\LogActivityTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\RecordManipulationsTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\SyncFieldsTrait;\nuse Jiminny\\Utils\\CurrencyFormatter;\nuse Jiminny\\Utils\\StringUtil;\nuse Ramsey\\Uuid\\Uuid;\nuse Sentry\\Laravel\\Facade as Sentry;\n\nclass Service extends BaseService implements\n SalesforceInterface,\n SalesforceBatchSyncInterface,\n SyncCrmEntitiesInterface,\n SyncCrmProfileRecordTypesInterface,\n ImportsBusinessProcessesInterface,\n RemoteEntityManipulationInterface,\n FetchRelatedActivityInterface,\n SendSummaryToCrmInterface,\n MatchDomainByEmailInterface,\n SearchTaskInterface,\n LayoutManagementInterface,\n SettingsInterface,\n MatchCrmEntitiesInterface,\n RemoteEntityLookupInterface,\n SupportsObjectTypeParseInterface,\n RemoteNoteEntityManipulationInterface,\n VerifyTaskExistsInterface\n{\n use ResolveCompanyNameByEmailTrait;\n use SyncFieldsTrait;\n use DeleteObjectsTrait;\n use RecordManipulationsTrait;\n use ServiceTraits\\BatchSyncTrait;\n use FollowupActivityTrait;\n use LogActivityTrait;\n\n /**\n * Note Body Limit for the Old Note-Taking Tool\n *\n * @var int\n */\n private const int CLASSIC_NOTE_MAX_LENGTH = 32000;\n\n /**\n * Note Content Limit for the New Notes\n *\n * @var int\n */\n private const int ENHANCED_NOTE_MAX_LENGTH = 50000000;\n\n private const string INSTALLED_PACKAGE_ID = '033Tw0000007bKbIAI';\n\n private const int CACHE_TTL = 600;\n\n private const int TASK_VERIFICATION_CACHE_TTL = 86400; // 1 day - 86400\n\n /**\n * @var Client\n */\n protected $client;\n\n protected PayloadBuilder $payloadBuilder;\n protected QueryHandler $queryHandler;\n\n private OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;\n\n public function __construct(\n Client $client,\n PayloadBuilder $payloadBuilder,\n protected Dispatcher $eventDispatcher,\n private readonly CountriesMap $countriesMap,\n private readonly ProspectPhotoPathService $prospectPhotoPathService,\n ) {\n parent::__construct();\n\n $this->client = $client;\n $this->payloadBuilder = $payloadBuilder;\n $this->queryHandler = app(QueryHandler::class, [\n 'client' => $this->client,\n 'logger' => $this->logger,\n ]);\n $this->opportunitySyncStrategyResolver = app(OpportunitySyncStrategyResolver::class, [\n 'client' => $this->client,\n ]);\n }\n\n public function getDisplayName(): string\n {\n return 'Salesforce';\n }\n\n public function getJobDelay(): int\n {\n return 1;\n }\n\n protected function getOAuthAccount(User $user): ?SocialAccount\n {\n return $user->getSocialAccount(SocialAccount::PROVIDER_SALESFORCE);\n }\n\n public function verifyTaskExists(Activity $activity): bool\n {\n $crmProviderId = $activity->getCrmProviderId();\n $cacheKey = \"crm_task_exists:{$this->config->getId()}:$crmProviderId\";\n\n return Cache::remember($cacheKey, self::TASK_VERIFICATION_CACHE_TTL, function () use ($activity, $crmProviderId) {\n $playbook = $this->getPlaybookFromActivity($activity);\n\n if ($playbook === null) {\n $this->logger->warning('[Salesforce] Cannot verify task - no playbook found', [\n 'activity' => $activity->getId(),\n 'crm_provider_id' => $crmProviderId,\n ]);\n\n return false;\n }\n\n $objectType = $playbook->getActivityType() === Playbook::ACTIVITY_TYPE_EVENT ? 'Event' : 'Task';\n\n try {\n $record = $this->getRecord($objectType, $crmProviderId, ['Id', 'IsDeleted']);\n\n return ! empty($record) && ($record['IsDeleted'] ?? false) === false;\n } catch (HttpNotFoundException|HttpBadRequestException) {\n $this->logger->info('[Salesforce] Activity record not found during verification', [\n 'activity' => $activity->getId(),\n 'object_type' => $objectType,\n 'crm_provider_id' => $crmProviderId,\n 'config_id' => $this->config->getId(),\n ]);\n\n return false;\n }\n });\n }\n\n public function query(string $queryToRun, array $parameters = []): QueryIterator\n {\n // Due to poorly designed external calls, this method cannot be entirely removed\n return $this->queryHandler->query($queryToRun, $parameters);\n }\n\n /*=========== Organization Information ===============*/\n\n /**\n * Get a list of all the API Versions for the instance.\n *\n * @throws CrmException\n *\n * @return mixed\n *\n */\n public function getApiVersions()\n {\n $url = $this->config->crm_base_url . '/services/data';\n\n $response = $this->client->get($url);\n\n return json_decode($response->getBody(), true);\n }\n\n /**\n * Gets the valid recordTypes for a given Salesforce Object via the describe API.\n */\n private function getRecordTypes(string $crmObject): array\n {\n $url = $this->client->getObjectsUrl() . $crmObject . '/describe';\n\n $response = $this->client->get($url);\n $jsonResponse = json_decode($response->getBody(), true);\n\n $fields = [];\n foreach ($jsonResponse['recordTypeInfos'] as $row) {\n $fields[] = ['recordTypeId' => $row['recordTypeId'], 'default' => $row['defaultRecordTypeMapping']];\n }\n\n return $fields;\n }\n\n /**\n * Convert raw field data into a format compatible with CRM APIs.\n */\n public function normalizeValue(string $fieldType, string $fieldValue, bool $internal = false): string\n {\n return ValueNormalizer::normalize($fieldType, $fieldValue, $internal);\n }\n\n /**\n * @inheritdoc\n */\n public function getDefaultFields(string $activityType): array\n {\n $fields = [];\n\n $defaultFields = ($activityType === Playbook::ACTIVITY_TYPE_TASK)\n ? FieldDefinitions::defaultTaskFields()\n : FieldDefinitions::defaultEventFields();\n\n // This lazy creates these fields if not already setup.\n foreach ($defaultFields as $defaultField) {\n $fields[] = $this->config->fields()->firstOrCreate($defaultField);\n }\n\n return $fields;\n }\n\n /**\n * @inheritdoc\n */\n public function getDefaultActivityField(string $activityType): Field\n {\n // Setup the activity field as the default Type.\n /** @var Field $activityField */\n $activityField = $this->config->fields()->where([\n 'crm_provider_id' => 'Type',\n 'object_type' => $activityType,\n ])->first();\n\n return $activityField;\n }\n\n /**\n * @inheritdoc\n */\n public function getSupportedPlaybookTypes(): array\n {\n return [Playbook::ACTIVITY_TYPE_TASK, Playbook::ACTIVITY_TYPE_EVENT];\n }\n\n protected function getDefaultFollowupLayoutFields(string $activityType): array\n {\n $fields = [];\n $fieldRepo = app(FieldRepository::class);\n\n $fieldFilter = ($activityType === Playbook::ACTIVITY_TYPE_TASK)\n ? FieldDefinitions::taskFollowupFieldsFilter()\n : FieldDefinitions::eventFollowupFieldsFilter();\n\n foreach ($fieldFilter as $eachFilter) {\n $field = $fieldRepo->findOneConfigurationFieldByProperties($this->config, $eachFilter);\n\n // Only add the field if it is created, which it should be.\n if ($field) {\n $fields[] = $field;\n }\n }\n\n return $fields;\n }\n\n public function getDealInsightsFields(): array\n {\n return FieldDefinitions::dealInsightsFields();\n }\n\n /**\n * This one is now called only when ImportActivityTypes is triggered or SyncFieldMetadata executed manually\n * Regular sync now uses SharedSyncFieldsTrait -> syncSingleObjectType\n * Needs to be replaced later on\n */\n public function syncField(Field $field): void\n {\n try {\n if (FieldHelper::isCustomField($field)) {\n $query = '\n SELECT\n Id, Metadata, TableEnumOrId\n FROM\n CustomField\n WHERE\n DeveloperName = :fieldName\n AND\n TableEnumOrId = :fieldType\n AND\n NamespacePrefix = :namespacePrefix';\n\n // We need to constrain the field lookup to the object, in case it's used in multiple places.\n $objectType = \\in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true)\n ? 'activity'\n : $field->object_type;\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'fieldName' => substr($field->crm_provider_id, 0, -\\strlen('__c')),\n 'fieldType' => ucfirst($objectType),\n\n // This is used to ensure we only consider the field within the org, not installed packages.\n 'namespacePrefix' => 'null',\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n // Sync field metadata.\n $metadata = $sfField['Metadata'];\n\n $field->description = mb_strimwidth($metadata['description'] ?? '', 0, 191);\n $field->label = mb_strimwidth($metadata['label'] ?? '', 0, Field::LABEL_MAX_LENGTH);\n $field->type = $this->convertFieldType($metadata['type'], $field->getEntityName());\n $field->is_mandatory = ($metadata['required'] === true);\n $field->length = $metadata['length'];\n $field->default_value = mb_strimwidth(trim($metadata['defaultValue'] ?? '', '\"'), 0, 191);\n $field->save();\n } else {\n $query = '\n SELECT\n Id, DataType, DeveloperName, Label, Length, Description\n FROM\n FieldDefinition\n WHERE\n DurableId = :entityName';\n\n $entityName = $field->getEntityName();\n $sfFields = $this->queryHandler->metadata($query, [\n 'entityName' => $entityName,\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n $convertedType = $this->convertFieldType($sfField['DataType'], $entityName);\n $label = mb_strimwidth($sfField['Label'], 0, Field::LABEL_MAX_LENGTH);\n\n if ($field->isBusinessType()) {\n $label = 'Opportunity Type';\n }\n\n $field->description = mb_strimwidth($sfField['Description'], 0, Field::DESCRIPTION_MAX_LENGTH);\n $field->label = $label;\n $field->type = $convertedType;\n $field->length = $sfField['Length'];\n $field->save();\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n private function convertFieldType(string $from, ?string $entityName = null): string\n {\n $converter = new FieldTypeConverter();\n\n return $converter->convert($from, $entityName);\n }\n\n /**\n * @inheritdoc\n */\n public function importPicklistValues(Field $field): array\n {\n $values = [];\n $fieldValues = [];\n\n try {\n if (FieldHelper::isCustomField($field)) {\n $query = '\n SELECT\n Id, Metadata, TableEnumOrId\n FROM\n CustomField\n WHERE\n DeveloperName = :fieldName\n AND\n TableEnumOrId = :fieldType\n AND\n NamespacePrefix = :namespacePrefix';\n\n // We need to constrain the field lookup to the object, in case it's used in multiple places.\n $objectType = \\in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true) ?\n 'activity' : $field->object_type;\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'fieldName' => substr($field->crm_provider_id, 0, -\\strlen('__c')),\n 'fieldType' => ucfirst($objectType),\n // This is used to ensure we only consider the field within the org, not installed packages.\n 'namespacePrefix' => 'null',\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n $valueSet = $sfField['Metadata']['valueSet'];\n\n if ($valueSet['valueSetName'] === null) {\n // Local picklist values can be obtained easily.\n $picklistValues = $valueSet['valueSetDefinition']['value'];\n } else {\n // But for some fields, we just get the Global Value Picklist pointer so need to do more work.\n $picklistValues = $this->importGlobalValuePicklistValues($valueSet['valueSetName']);\n }\n\n // Import all active values.\n foreach ($picklistValues as $i => $sfFieldValue) {\n // Setup default value.\n if ($sfFieldValue['default']) {\n $field->update(['default_value' => $sfFieldValue['valueName']]);\n }\n\n // This comes through as null if active (lol).\n if ($sfFieldValue['isActive'] !== false) {\n $values[] = [\n 'value' => $sfFieldValue['valueName'],\n 'label' => $sfFieldValue['valueName'],\n 'sequence' => $i,\n 'is_default' => $sfFieldValue['default'],\n ];\n }\n }\n } else {\n $objectFields = $this->getObjectFields($field->object_type);\n $fieldId = $field->crm_provider_id;\n\n // Only work with our field of interest.\n $objectField = array_filter($objectFields, function ($item) use ($fieldId) {\n return $item['name'] === $fieldId;\n });\n\n $objectField = array_shift($objectField);\n if (empty($objectField['picklistValues']) === false) {\n foreach ($objectField['picklistValues'] as $i => $sfFieldValue) {\n // Skip inactive values.\n if ($sfFieldValue['active'] === false) {\n continue;\n }\n\n // Setup default value.\n if ($sfFieldValue['defaultValue']) {\n $field->update(['default_value' => $sfFieldValue['value']]);\n }\n\n $values[] = [\n 'value' => $sfFieldValue['value'],\n 'label' => $sfFieldValue['label'],\n 'sequence' => $i,\n 'is_default' => $sfFieldValue['defaultValue'],\n ];\n }\n }\n }\n\n $fieldsToPurge = $field->values()->get()->pluck('value')->toArray();\n\n foreach ($values as $value) {\n $value['value'] = substr($value['value'] ?? '', 0, 255);\n $fieldValues[] = $field->values()->updateOrCreate([\n 'value' => $value['value'],\n ], $value);\n\n // Remove this value from the ones we are going to purge.\n if (($key = array_search($value['value'], $fieldsToPurge, true)) !== false) {\n unset($fieldsToPurge[$key]);\n }\n }\n\n // Delete the old values that are no longer used.\n // Get IDs of the values to be deleted\n $valuesToDelete = $field->values()->whereIn('value', $fieldsToPurge);\n $valuesToDeleteIds = $valuesToDelete->pluck('id');\n if (! $valuesToDeleteIds->isEmpty()) {\n $recordTypeFieldValuesRepository = app(RecordTypeFieldValuesRepository::class);\n $recordTypeFieldValuesRepository->deleteForCrmFieldValueIds($valuesToDeleteIds->toArray());\n\n // Now safely delete from crm_field_values\n $valuesToDelete->delete();\n }\n\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n return $fieldValues;\n }\n\n /**\n * Gets values from Global Value Picklists.\n */\n private function importGlobalValuePicklistValues(string $picklistName): array\n {\n $query = '\n SELECT\n Metadata\n FROM\n GlobalValueSet\n WHERE\n DeveloperName = :picklistName\n LIMIT 1';\n\n try {\n $sfValues = $this->queryHandler->metadata($query, [\n 'picklistName' => $picklistName,\n ]);\n\n // There is always 1 result at this point.\n $sfValue = $sfValues->current();\n\n return $sfValue['Metadata']['customValue'];\n } catch (NoResultsException $noResultsException) {\n // Nothing returned.\n\n return [];\n }\n }\n\n /**\n * @inheritdoc\n */\n public function syncProfileRecordTypes(): void\n {\n $objectTypes = [\n 'lead',\n 'account',\n 'contact',\n 'opportunity',\n 'task',\n 'event',\n ];\n\n foreach ($objectTypes as $objectType) {\n try {\n $crmRecordTypes = $this->getRecordTypes(ucfirst($objectType));\n\n foreach ($crmRecordTypes as $crmRecordType) {\n // If the record type is default and not the Master type, set this.\n if ($crmRecordType['default'] && $crmRecordType['recordTypeId'] !== '012000000000000AAA') {\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $crmRecordType['recordTypeId'])\n ->first();\n\n if ($recordType) {\n $this->profile->{$objectType . '_record_type_id'} = $recordType->id;\n }\n }\n }\n } catch (HttpNotFoundException $exception) {\n Log::error('No access to ' . $objectType . ' object, skipping...');\n\n // XXX: should we log this fact somewhere?\n continue;\n }\n }\n\n if ($this->profile->isDirty()) {\n $this->profile->save();\n }\n }\n\n /**\n * Gets business processes.\n */\n public function importBusinessProcesses(): void\n {\n $query = '\n SELECT\n Id, IsActive, Name, TableEnumOrId\n FROM\n BusinessProcess\n WHERE\n TableEnumOrId IN (\\'Lead\\',\\'Opportunity\\')';\n\n try {\n $sfProcesses = $this->queryHandler->query($query);\n\n // Upsert all processes for the team.\n foreach ($sfProcesses as $sfProcess) {\n /** @var BusinessProcess $businessProcess */\n $businessProcess = $this->config->businessProcesses()->updateOrCreate([\n 'crm_provider_id' => $sfProcess['Id'],\n ], [\n 'team_id' => $this->team->id,\n 'name' => $sfProcess['Name'],\n 'type' => $sfProcess['TableEnumOrId'] === 'Lead' ? 'lead' : 'opportunity',\n 'is_selectable' => $sfProcess['IsActive'],\n ]);\n\n $this->importBusinessProcessStages($businessProcess);\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n /**\n * Gets business process stages.\n */\n private function importBusinessProcessStages(BusinessProcess $businessProcess): void\n {\n $query = '\n SELECT\n Metadata\n FROM\n BusinessProcess\n WHERE\n Id = :processId';\n\n try {\n $stages = [];\n $sfProcessStages = $this->queryHandler->metadata($query, [\n 'processId' => $businessProcess->crm_provider_id,\n ]);\n\n // There is always 1 result at this point.\n $sfProcessStage = $sfProcessStages->current();\n\n // Upsert all processes for the team.\n foreach ($sfProcessStage['Metadata']['values'] as $sfProcessStage) {\n $sanitizedName = urldecode($sfProcessStage['valueName']); // Must decode: \"%2C\" becomes \",\" etc.\n\n $stage = $businessProcess->crm->stages()\n // This MUST match on label because this API doesn't use API Name.\n ->where('label', $sanitizedName)\n ->where('type', $businessProcess->type)\n ->where('is_selectable', 1)\n ->first();\n\n if ($stage) {\n $stages[] = $stage->id;\n }\n }\n\n $businessProcess->stages()->sync($stages);\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n /**\n * Gets record types.\n */\n public function importRecordTypes(): void\n {\n $query = '\n SELECT\n Id, IsActive, Name, BusinessProcessId, SobjectType\n FROM\n RecordType';\n\n try {\n $sfRecordTypes = $this->queryHandler->query($query);\n\n // Upsert all record types for the process.\n foreach ($sfRecordTypes as $sfRecordType) {\n $businessProcess = null;\n if ($sfRecordType['BusinessProcessId']) {\n $businessProcess = $this->config->businessProcesses()\n ->where('crm_provider_id', $sfRecordType['BusinessProcessId'])\n ->first();\n }\n\n /** @var RecordType $recordType */\n $recordType = $this->config->recordTypes()->updateOrCreate([\n 'crm_provider_id' => $sfRecordType['Id'],\n ], [\n 'team_id' => $this->team->id,\n 'type' => mb_strtolower($sfRecordType['SobjectType']),\n 'name' => $sfRecordType['Name'],\n 'is_selectable' => $sfRecordType['IsActive'],\n 'business_process_id' => $businessProcess->id ?? null,\n ]);\n\n $this->importRecordTypeFieldValues($recordType);\n }\n } catch (NoResultsException $noResultsException) {\n // Do nothing.\n }\n }\n\n /**\n * Import record type - field value mappings. This only works for standard fields.\n */\n private function importRecordTypeFieldValues(RecordType $recordType): void\n {\n try {\n $query = '\n SELECT\n Metadata\n FROM\n RecordType\n WHERE\n Id = :recordTypeId';\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'recordTypeId' => $recordType->crm_provider_id,\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n // Sync field metadata.\n $picklists = $sfField['Metadata']['picklistValues'];\n\n foreach ($picklists as $picklist) {\n $field = $this->config->fields()->where([\n 'type' => Field::TYPE_PICKLIST,\n 'object_type' => $recordType->type,\n 'crm_provider_id' => $picklist['picklist'],\n ])->first();\n\n if ($field) {\n $fieldValues = [];\n\n foreach ($picklist['values'] as $value) {\n // Must decode: \"%2C\" becomes \",\" etc.\n $fieldValue = $field->values()\n ->where('value', urldecode($value['valueName']))\n ->first();\n\n if ($fieldValue) {\n $fieldValues[] = $fieldValue->id;\n }\n }\n\n $recordType->fieldValues()->sync($fieldValues);\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n /**\n * @inheritdoc\n */\n public function importStages(?array $types = null, ?string $missingStageName = null): ?Stage\n {\n $params = [];\n $missingStage = null;\n if ($types === null) {\n $types = [Stage::TYPE_LEAD, Stage::TYPE_OPPORTUNITY];\n }\n\n foreach ($types as $type) {\n if ($type === Stage::TYPE_LEAD) {\n $query = '\n SELECT\n Id, ApiName, MasterLabel, SortOrder\n FROM\n LeadStatus';\n } else {\n $query = '\n SELECT\n Id, ApiName, MasterLabel, IsActive, SortOrder, DefaultProbability\n FROM\n OpportunityStage';\n }\n\n if ($missingStageName) {\n $escapedStageName = ValueNormalizer::replaceQueryWithStringLiterals($missingStageName);\n\n $query .= ' WHERE ApiName = :stageName';\n\n $params = [\n 'stageName' => $escapedStageName,\n ];\n }\n\n try {\n $sfStages = $this->queryHandler->query($query, $params);\n } catch (NoResultsException $exception) {\n $sfStages = [];\n }\n\n $missingStage = null;\n\n // Upsert all stages for the team.\n foreach ($sfStages as $sfStage) {\n $selectable = true;\n if (array_key_exists('IsActive', $sfStage)) {\n $selectable = $sfStage['IsActive'];\n }\n\n $this->restoreAnyTrashedEntity($this->config->stages(), $sfStage['Id']);\n\n $stage = $this->config->stages()->updateOrCreate([\n 'crm_provider_id' => $sfStage['Id'],\n ], [\n 'team_id' => $this->team->id,\n 'name' => mb_strimwidth($sfStage['ApiName'], 0, 50),\n 'label' => mb_strimwidth($sfStage['MasterLabel'], 0, 191),\n 'type' => $type,\n 'sequence' => $sfStage['SortOrder'] ?? 0,\n 'is_selectable' => $selectable,\n 'probability' => $sfStage['DefaultProbability'] ?? null,\n ]);\n\n if ($missingStageName && $missingStageName === $sfStage['ApiName']) {\n $missingStage = $stage;\n }\n }\n\n if ($missingStageName && $missingStage === null) {\n // If they requested a stage that still doesn't exist, it must be inactive so lazy create it.\n $missingStage = $this->config->stages()->create([\n 'crm_provider_id' => Uuid::uuid4(),\n 'team_id' => $this->team->id,\n 'name' => mb_strimwidth($missingStageName, 0, 50),\n 'label' => mb_strimwidth($missingStageName, 0, 191),\n 'type' => $type,\n 'sequence' => 0,\n 'is_selectable' => 0,\n ]);\n }\n }\n\n return $missingStage;\n }\n\n /**\n * @inheritdoc\n */\n public function syncLeads(Carbon $since, ?Carbon $to = null, ?string $crmProfileId = null): int\n {\n $syncCount = 0;\n $fields = $this->getAllFieldsAsArray('lead');\n if (\\in_array('Id', $fields, true) === false) {\n return $syncCount;\n }\n\n $query = '\n SELECT ' . rtrim(implode(',', $fields), ',') . '\n FROM Lead\n WHERE LastModifiedDate > :since\n ORDER BY LastModifiedDate ASC';\n\n try {\n $sfLeads = $this->queryHandler->query($query, [\n 'since' => $since->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($sfLeads as $sfLead) {\n // Only sync if previously imported.\n if ($this->hasLead($sfLead['Id'])) {\n $this->importLead($sfLead);\n $syncCount++;\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::LEAD);\n\n return $syncCount;\n }\n\n /**\n * @inheritdoc\n */\n public function syncLead(string $crmId): ?Lead\n {\n $fields = $this->getAllFieldsAsArray('lead');\n\n $sfLead = $this->getRecord('Lead', $crmId, $fields);\n\n return $this->importLead($sfLead);\n }\n\n private function importLead($crmData): ?Lead\n {\n /** @var ?Stage $stage */\n $stage = null;\n if (isset($crmData['Status'])) {\n // Get the current stage.\n $stage = $this->config\n ->stages()\n ->where('name', $crmData['Status'])\n ->where('type', Stage::TYPE_LEAD)\n ->first();\n\n if ($stage === null) {\n // Import it.\n $stage = $this->importStages([Stage::TYPE_LEAD], $crmData['Status']);\n }\n }\n\n // If we have no way of importing this, just return null :(\n if ($stage === null) {\n return null;\n }\n\n $countryCode = $crmData['CountryCode'] ?? null;\n\n // Salesforce allows custom \"countries\" to be created. Disregard these.\n if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {\n $countryCode = null;\n }\n\n // If we have no country code, try to parse it from the country name.\n if ($countryCode === null && empty($crmData['Country']) !== false) {\n $countryCode = $this->convertCountryNameToCode($crmData['Country']);\n }\n\n // Trim to our width and attempt to parse it.\n $number = mb_strimwidth($crmData['Phone'] ?? '', 0, 25);\n $parsedNumber = parsePhoneNumber($countryCode, $number);\n\n $mobilePhone = null;\n if (empty($crmData['MobilePhone']) === false) {\n // Trim to our width and attempt to parse it.\n $number = mb_strimwidth($crmData['MobilePhone'], 0, 25);\n $mobilePhone = phone_e164($countryCode, $number);\n }\n\n $convertedDate = null;\n $convertedAccount = null;\n $convertedOpportunity = null;\n $convertedContact = null;\n\n if ($crmData['IsConverted'] == 'true') {\n $convertedDate = $crmData['ConvertedDate'];\n\n if (empty($crmData['ConvertedAccountId']) === false) {\n $convertedAccount = $this->config\n ->accounts()\n ->where('crm_provider_id', $crmData['ConvertedAccountId'])\n ->first();\n\n if ($convertedAccount === null) {\n try {\n $convertedAccount = $this->syncAccount($crmData['ConvertedAccountId']);\n } catch (HttpNotFoundException $exception) {\n // Probably the user has no permissions to access the converted data.\n }\n }\n }\n\n if (empty($crmData['ConvertedOpportunityId']) === false) {\n $convertedOpportunity = $this->config\n ->opportunities()\n ->where('crm_provider_id', $crmData['ConvertedOpportunityId'])\n ->first();\n\n if ($convertedOpportunity === null) {\n try {\n $convertedOpportunity = $this->syncOpportunity($crmData['ConvertedOpportunityId']);\n } catch (HttpNotFoundException $exception) {\n // Probably the user has no permissions to access the converted data.\n }\n }\n }\n\n if (empty($crmData['ConvertedContactId']) === false) {\n $convertedContact = $this->team\n ->crm\n ->contacts()\n ->where('crm_provider_id', $crmData['ConvertedContactId'])\n ->first();\n\n if ($convertedContact === null) {\n try {\n $convertedContact = $this->syncContact($crmData['ConvertedContactId']);\n } catch (HttpNotFoundException $exception) {\n // Probably the user has no permissions to access the converted data.\n }\n }\n }\n }\n\n if (empty($crmData['Company'])) {\n $company = 'Unknown';\n } else {\n $company = mb_strimwidth($crmData['Company'], 0, 191);\n }\n\n $domain = null;\n if (empty($crmData['Website']) === false) {\n $domain = mb_strimwidth($crmData['Website'], 0, 191);\n $domain = StringUtil::resolveDomain($domain);\n }\n\n $createdDate = null;\n if (empty($crmData['CreatedDate']) === false) {\n $createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n }\n\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $data = [\n 'team_id' => $this->team->id,\n 'user_id' => $profile?->user_id,\n 'owner_id' => $crmData['OwnerId'] ?? '',\n 'company' => $company,\n 'domain' => $domain,\n 'name' => $crmData['Name'] ? mb_strimwidth($crmData['Name'], 0, 191) : '',\n 'title' => $crmData['Title'] ? mb_strimwidth($crmData['Title'], 0, 128) : null,\n 'email' => $crmData['Email'] ? mb_strimwidth($crmData['Email'], 0, 80) : null,\n 'phone' => $parsedNumber['phone'],\n 'ext' => $parsedNumber['ext'] ?? null,\n 'mobile_phone' => $mobilePhone,\n 'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(\n crmConfiguration: $this->config,\n crmProviderId: $crmData['Id'],\n modelType: Lead::class,\n fileName: $crmData['Id'],\n avatarText: $crmData['Name']\n ),\n 'stage_id' => $stage->id,\n 'record_type_id' => null,\n 'converted_at' => $convertedDate,\n 'converted_account_id' => $convertedAccount->id ?? null,\n 'converted_opportunity_id' => $convertedOpportunity->id ?? null,\n 'converted_contact_id' => $convertedContact->id ?? null,\n 'country_code' => $countryCode,\n 'remotely_created_at' => $createdDate,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->leads(), $crmData['Id']);\n\n /** @var Lead $lead */\n $lead = $this->config->leads()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n if ($lead->wasChanged('converted_at') && $lead->getConvertedAt() !== null) {\n $this->eventDispatcher->dispatch(new LeadConverted($lead));\n }\n\n $this->handleObjectDeletion($lead, $crmData);\n\n if ($lead->trashed()) {\n return null;\n }\n\n return $lead;\n }\n\n /**\n * @inheritdoc\n */\n public function syncAccounts(Carbon $since, ?Carbon $to = null): int\n {\n $syncCount = 0;\n $fields = $this->getAllFieldsAsArray('account');\n\n if (\\in_array('Id', $fields, true) === false) {\n return $syncCount;\n }\n\n $query = '\n SELECT ' . rtrim(implode(',', $fields), ',') . '\n FROM Account\n WHERE LastModifiedDate > :since\n ORDER BY LastModifiedDate ASC';\n\n try {\n $sfAccounts = $this->queryHandler->query($query, [\n 'since' => $since->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($sfAccounts as $sfAccount) {\n // Only sync if previously imported.\n if ($this->hasAccount($sfAccount['Id'])) {\n $this->importAccount($sfAccount);\n $syncCount++;\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::ACCOUNT);\n\n return $syncCount;\n }\n\n /**\n * @inheritdoc\n */\n public function syncAccount(string $crmId): ?Account\n {\n $fields = $this->getAllFieldsAsArray('account');\n if (! in_array('Id', $fields, true)) {\n $this->logger->info('[Salesforce] Sync account cancelled. Fields are not available.', [\n 'crmId' => $crmId,\n 'userId' => $this->profile->getUserId(),\n ]);\n\n return null;\n }\n\n $sfAccount = $this->getRecord('Account', $crmId, $fields);\n\n return $this->importAccount($sfAccount);\n }\n\n private function importAccount($crmData): ?Account\n {\n if (! empty($crmData['IsDeleted'])) {\n $this->handleEntityDeletionByProviderId($this->config->accounts(), $crmData);\n\n return null;\n }\n\n $countryCode = $crmData['BillingCountryCode'] ?? $crmData['ShippingCountryCode'] ?? null;\n\n // Salesforce allows custom \"countries\" to be created. Disregard these.\n if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {\n $countryCode = null;\n }\n\n // If we have no country code, try to parse it from the country names.\n if ($countryCode === null && empty($crmData['BillingCountry']) === false) {\n $countryCode = $this->convertCountryNameToCode($crmData['BillingCountry']);\n }\n\n if ($countryCode === null && empty($crmData['ShippingCountry']) === false) {\n $countryCode = $this->convertCountryNameToCode($crmData['ShippingCountry']);\n }\n\n if (empty($crmData['Phone']) === false) {\n // Trim to our width and attempt to parse it.\n $number = mb_strimwidth($crmData['Phone'], 0, 25);\n $parsedNumber = parsePhoneNumber($countryCode, $number);\n } else {\n $parsedNumber = [];\n }\n\n $industry = null;\n if (empty($crmData['Industry']) === false) {\n $industry = mb_strimwidth($crmData['Industry'], 0, 40);\n }\n\n $domain = null;\n if (empty($crmData['Website']) === false) {\n $domain = mb_strimwidth($crmData['Website'], 0, 191);\n $domain = StringUtil::resolveDomain($domain);\n }\n\n $createdDate = null;\n if (empty($crmData['CreatedDate']) === false) {\n $createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n }\n\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $data = [\n 'team_id' => $this->team->id,\n 'user_id' => $profile?->user_id,\n 'owner_id' => $crmData['OwnerId'],\n 'name' => mb_strimwidth($crmData['Name'], 0, 191),\n 'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(\n crmConfiguration: $this->config,\n crmProviderId: $crmData['Id'],\n modelType: Account::class,\n fileName: $crmData['Id'],\n avatarText: $crmData['Name']\n ),\n 'industry' => $industry,\n 'domain' => $domain,\n 'phone' => $parsedNumber['phone'] ?? null,\n 'ext' => $parsedNumber['ext'] ?? null,\n 'country_code' => $countryCode,\n 'remotely_created_at' => $createdDate,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->accounts(), $crmData['Id']);\n\n /** @var Account $account */\n $account = $this->config->accounts()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n $this->handleObjectDeletion($account, $crmData);\n\n return $account->trashed() ? null : $account;\n }\n\n /**\n * @inheritdoc\n */\n public function syncOpportunities(array $parameters, ?string $strategy = null): int\n {\n $strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);\n\n $syncCount = 0;\n $logParams = $parameters;\n $parameters['profile'] = $this->profile;\n $logParams['user'] = $this->profile->getUserId();\n\n if (count($strategies) > 1) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Multiple sync strategies used', [\n 'teamId' => $this->team->getUuid(),\n 'params' => $logParams,\n 'strategies_count' => count($strategies),\n ]);\n }\n\n foreach ($strategies as $syncStrategy) {\n $name = $syncStrategy->getStrategyName();\n\n try {\n $sfOpportunities = $syncStrategy->fetchOpportunities($parameters);\n $totalRecords = $sfOpportunities->count();\n\n foreach ($sfOpportunities as $sfOpportunity) {\n $this->importOpportunity($sfOpportunity);\n $syncCount++;\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n $this->logger->warning('[' . $this->getDisplayName() . '] No opportunities found', [\n 'teamId' => $this->team->getUuid(),\n 'name' => $name,\n 'params' => $logParams,\n 'reason' => $noResultsException->getMessage(),\n ]);\n } catch (CrmException $crmException) {\n // Nothing to sync.\n $this->logger->warning('[' . $this->getDisplayName() . '] Opportunity sync failed', [\n 'teamId' => $this->team->getUuid(),\n 'name' => $name,\n 'params' => $logParams,\n 'reason' => $crmException->getMessage(),\n ]);\n }\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::OPPORTUNITY, ['params' => $logParams]);\n\n // debug to see how if count of opportunities reaches 1000\n if ($syncCount >= 1000) {\n $this->logger->info(\n '[' . $this->getDisplayName() . '] Sync Opportunities - count warning',\n [\n 'team_id' => $this->team->getId(),\n 'params' => $logParams,\n 'count' => $syncCount,\n 'strategies_count' => count($strategies),\n 'total_records' => $totalRecords ?? null,\n ]\n );\n }\n\n return $syncCount;\n }\n\n\n /**\n * @inheritdoc\n */\n public function syncOpportunity(string $crmId): ?Opportunity\n {\n $strategy = $this->opportunitySyncStrategyResolver->resolve(\n $this->config,\n OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY\n );\n\n $parameters = [\n 'profile' => $this->profile,\n 'crm_id' => $crmId,\n ];\n\n try {\n $sfOpportunity = $strategy->fetchOpportunities($parameters);\n } catch (HttpNotFoundException $e) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [\n 'teamId' => $this->team->id_string,\n 'crmId' => $crmId,\n ]);\n\n return null;\n } catch (CrmException $crmException) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity sync failed', [\n 'teamId' => $this->team->id_string,\n 'crmId' => $crmId,\n 'exception' => $crmException->getMessage(),\n ]);\n\n return null;\n }\n\n if ($sfOpportunity instanceof ArrayIterator) {\n return $this->importOpportunity($sfOpportunity->getItems());\n }\n\n return $this->importOpportunity($sfOpportunity);\n }\n\n /**\n * @throws HttpNotFoundException\n */\n private function importOpportunity($crmData): ?Opportunity\n {\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $account = null;\n if (empty($crmData['AccountId']) === false) {\n /** @var ?Account $account */\n $account = $this->config->accounts()\n ->where('crm_provider_id', (string) $crmData['AccountId'])\n ->first();\n\n if ($account === null) {\n $account = $this->syncAccount($crmData['AccountId']);\n }\n }\n\n $userId = $profile?->getUserId() ?? $account?->getUserId();\n if ($userId === null) {\n $this->logger->error('[Salesforce] | Skip import, no user_id found', [\n 'id' => $crmData['Id'],\n ]);\n\n return null;\n }\n\n /** @var ?Stage $stage */\n $stage = null;\n if (isset($crmData['StageName'])) {\n $stage = $this->config\n ->stages()\n ->where('name', $crmData['StageName'])\n ->where('type', Stage::TYPE_OPPORTUNITY)\n ->orderBy('is_selectable', 'DESC')\n ->orderBy('id')\n ->first();\n\n if ($stage === null) {\n // Import it.\n $stage = $this->importStages([Stage::TYPE_OPPORTUNITY], $crmData['StageName']);\n }\n }\n\n $recordType = null;\n if (empty($crmData['RecordTypeId']) === false) {\n /** @var ?RecordType $recordType */\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $crmData['RecordTypeId'])\n ->first();\n }\n\n $createdDate = null;\n if (empty($crmData['CreatedDate']) === false) {\n $createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n }\n\n $closeDate = null;\n if (empty($crmData['CloseDate']) === false) {\n $closeDate = Carbon::parse($crmData['CloseDate'])->format('Y-m-d');\n }\n\n $valueFieldName = 'Amount';\n if ($this->config->opportunity_value_field_id) {\n $valueFieldName = $this->config->opportunityValueField->crm_provider_id;\n }\n\n $data = [\n 'team_id' => $this->team->id,\n 'account_id' => $account->id ?? null,\n 'user_id' => $userId,\n 'owner_id' => $crmData['OwnerId'] ?? null,\n 'name' => mb_strimwidth($crmData['Name'] ?? '', 0, 128),\n 'value' => $crmData[$valueFieldName],\n 'currency_code' => CurrencyFormatter::formatCode($crmData['CurrencyIsoCode'] ?? null),\n 'close_date' => $closeDate,\n 'is_closed' => $crmData['IsClosed'],\n 'is_won' => $crmData['IsWon'],\n 'stage_id' => $stage?->id ?? null,\n 'record_type_id' => $recordType->id ?? null,\n 'remotely_created_at' => $createdDate,\n 'probability' => $crmData['Probability'] ?? null,\n 'forecast_category' => $crmData['ForecastCategoryName'] ?? null,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->opportunities(), $crmData['Id']);\n\n // Do not allow locked DB tables & other errors\n // to interrupt the process of reverting the trashed opportunities\n try {\n /** @var Opportunity $opportunity */\n $opportunity = $this->config->opportunities()\n ->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n // import external fields into crm_field_data if present\n $crmFields = $this->getOpportunitySyncableFields();\n\n $this->importOpportunityCrmFieldData($crmData, $crmFields, $opportunity->id);\n\n $this->handleObjectDeletion($opportunity, $crmData);\n\n if ($opportunity->trashed()) {\n return null;\n }\n\n if ($opportunity->wasRecentlyCreated) {\n MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());\n }\n\n return $opportunity;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->error('[Salesforce] importOpportunity failure.', [\n 'crm_provider_id' => $crmData['Id'],\n 'team_id' => $this->team->id,\n 'exception' => $exception->getMessage(),\n ]);\n\n $this->handleEntityDeletionByProviderId($this->config->opportunities(), $crmData);\n }\n\n return null;\n }\n\n /**\n * @inheritdoc\n */\n public function syncContacts(Carbon $since, ?Carbon $to = null): int\n {\n $syncCount = 0;\n $fields = $this->getAllFieldsAsArray('contact');\n if (\\in_array('Id', $fields, true) === false) {\n return $syncCount;\n }\n\n $query = '\n SELECT ' . rtrim(implode(',', $fields), ',') . '\n FROM Contact\n WHERE LastModifiedDate > :since\n ORDER BY LastModifiedDate ASC';\n\n try {\n $sfContacts = $this->queryHandler->query($query, [\n 'since' => $since->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($sfContacts as $sfContact) {\n // Only sync if previously imported.\n if ($this->hasContact($sfContact['Id'])) {\n $this->importContact($sfContact);\n $syncCount++;\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::CONTACT);\n\n return $syncCount;\n }\n\n /**\n * @inheritdoc\n */\n public function syncContact(string $crmId): ?Contact\n {\n $fields = $this->getAllFieldsAsArray('contact');\n if (! in_array('Id', $fields, true)) {\n $this->logger->info('[Salesforce] Sync contact cancelled. Fields are not available.', [\n 'crmId' => $crmId,\n 'userId' => $this->profile->getUserId(),\n ]);\n\n return null;\n }\n\n $sfContact = $this->getRecord('Contact', $crmId, $fields);\n\n return $this->importContact($sfContact);\n }\n\n private function importContact($crmData): ?Contact\n {\n if (! empty($crmData['IsDeleted'])) {\n $this->handleEntityDeletionByProviderId($this->config->contacts(), $crmData);\n\n return null;\n }\n\n $account = $this->resolveContactAccount($crmData);\n $countryCode = $this->resolveContactCountryCode($crmData, $account);\n [$parsedNumber, $ext] = $this->parseContactPhone($countryCode, $crmData);\n $mobileNumber = $this->parseContactMobile($countryCode, $crmData);\n $createdDate = empty($crmData['CreatedDate'])\n ? null\n : Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $data = [\n 'team_id' => $this->team->id,\n 'account_id' => $account->id ?? null,\n 'user_id' => $profile?->user_id,\n 'owner_id' => $crmData['OwnerId'] ?? null,\n 'name' => ($crmData['Name'] ?? null) !== null ? mb_strimwidth($crmData['Name'], 0, 100) : '',\n 'title' => ($crmData['Title'] ?? null) !== null ? mb_strimwidth($crmData['Title'], 0, 128) : null,\n 'email' => ($crmData['Email'] ?? null) !== null ? mb_strimwidth($crmData['Email'], 0, 191) : null,\n 'country_code' => $countryCode,\n 'phone' => $parsedNumber['phone'] ?? null,\n 'ext' => $ext,\n 'mobile_phone' => $mobileNumber,\n 'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(\n crmConfiguration: $this->config,\n crmProviderId: $crmData['Id'],\n modelType: Contact::class,\n fileName: $crmData['Id'],\n avatarText: $crmData['Name']\n ),\n 'remotely_created_at' => $createdDate,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->contacts(), $crmData['Id']);\n\n /** @var Contact $contact */\n $contact = $this->config->contacts()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n $this->handleObjectDeletion($contact, $crmData);\n\n return $contact->trashed() ? null : $contact;\n }\n\n private function resolveContactAccount(array $crmData): ?Account\n {\n if (! isset($crmData['AccountId'])) {\n return null;\n }\n\n return $this->config->accounts()\n ->where('crm_provider_id', (string) $crmData['AccountId'])\n ->first() ?? $this->syncAccount($crmData['AccountId']);\n }\n\n private function resolveContactCountryCode(array $crmData, ?Account $account): ?string\n {\n $countryCode = $crmData['MailingCountryCode'] ?? null;\n\n if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {\n $countryCode = null;\n }\n\n if ($countryCode === null && empty($crmData['MailingCountry']) === false) {\n $countryCode = $this->convertCountryNameToCode($crmData['MailingCountry'])\n ?? ($account?->country_code);\n }\n\n return $countryCode;\n }\n\n private function parseContactPhone(?string $countryCode, array $crmData): array\n {\n if (empty($crmData['Phone'])) {\n return [[], null];\n }\n\n $parsedNumber = parsePhoneNumber($countryCode, Str::limit($crmData['Phone'], 25, ''));\n $ext = empty($parsedNumber['ext']) ? null : Str::limit($parsedNumber['ext'], 10, '');\n\n return [$parsedNumber, $ext];\n }\n\n private function parseContactMobile(?string $countryCode, array $crmData): ?string\n {\n if (empty($crmData['MobilePhone'])) {\n return null;\n }\n\n return Str::limit(phone_e164($countryCode, $crmData['MobilePhone']), 25, '');\n }\n\n /**\n * @inheritdoc\n */\n public function syncOrganization(): void\n {\n $fields = [\n 'InstanceName',\n 'OrganizationType',\n 'IsSandbox',\n ];\n\n $orgValues = $this->getRecord('Organization', $this->config->crm_provider_id, $fields);\n\n $edition = null;\n switch ($orgValues['OrganizationType']) {\n case 'Developer Edition':\n $edition = Configuration::EDITION_DEVELOPER;\n\n break;\n\n case 'Professional Edition':\n $edition = Configuration::EDITION_PROFESSIONAL;\n\n break;\n\n case 'Enterprise Edition':\n $edition = Configuration::EDITION_ENTERPRISE;\n\n break;\n }\n\n $this->config->edition = $edition;\n $this->config->instance = $orgValues['InstanceName'];\n\n // XXX: How can this state be possible?\n if ($this->config->version === null) {\n $this->config->version = Client::MIN_API_VERSION;\n }\n\n $installedVersion = $this->getInstalledAppVersion();\n if ($installedVersion !== null) {\n $installedVersion = (string) $this->getInstalledAppVersion();\n }\n\n $this->config->installed_app_version = $installedVersion;\n\n $this->config->save();\n }\n\n public function getInstalledAppVersion(): ?string\n {\n try {\n $query = '\n SELECT\n SubscriberPackageVersion.MajorVersion,\n SubscriberPackageVersion.MinorVersion,\n SubscriberPackageVersion.PatchVersion,\n SubscriberPackageVersion.BuildNumber\n FROM\n InstalledSubscriberPackage\n WHERE\n SubscriberPackageId = :packageId\n ';\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'packageId' => self::INSTALLED_PACKAGE_ID,\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n // Grab version number.\n $version = $sfField['SubscriberPackageVersion']['MajorVersion'] .\n $sfField['SubscriberPackageVersion']['MinorVersion'] .\n $sfField['SubscriberPackageVersion']['PatchVersion'] .\n $sfField['SubscriberPackageVersion']['BuildNumber'];\n } catch (\\Exception) {\n $version = null;\n }\n\n return $version;\n }\n\n /**\n * Store transcripts as note.\n *\n * @throws \\Exception\n */\n public function createTranscriptNotes(Activity $activity): void\n {\n // For SF we also check if Log Notes is enabled.\n if ($this->profile->log_notes === Profile::LOG_NOTE_NONE) {\n return;\n }\n\n if ($activity->opportunity_id && $activity->prospect === null) {\n return;\n }\n\n try {\n $transcriptionData = $this->generateTranscription($activity);\n\n $noteMaxLength = $this->profile->log_notes === Profile::LOG_NOTE_ENHANCED\n ? self::ENHANCED_NOTE_MAX_LENGTH\n : self::CLASSIC_NOTE_MAX_LENGTH;\n\n $title = 'Transcript for ';\n $title .= $activity->title ?? $activity->activity_title;\n\n // Truncate Notes with max notes length because transcription text could be very long.\n $body = mb_strimwidth($transcriptionData, 0, $noteMaxLength);\n\n if ($activity->opportunity_id) {\n $objectId = $activity->opportunity->crm_provider_id;\n } else {\n $objectId = $activity->prospect->crm_provider_id;\n }\n\n $noteId = $this->saveNote($title, $body, $objectId);\n\n // Store crm logged id in transcription.\n $transcription = $activity->getTranscription();\n $transcription->crm_activity_id = $noteId;\n $transcription->save();\n } catch (\\Exception $e) {\n \\Sentry::captureException($e);\n }\n }\n\n public function saveNote(string $title, string $body, string $objectId, ?NoteObject $noteObject = null): ?string\n {\n $noteId = null;\n\n try {\n if ($this->profile->log_notes === Profile::LOG_NOTE_ENHANCED) {\n $noteId = $this->buildEnhancedNote($title, $body, $objectId);\n } else {\n $noteId = $this->buildClassicNote($title, $body, $objectId);\n }\n } catch (HttpNotFoundException $exception) {\n // The profile not having access to create Enhanced Notes. Set their preference to Classic.\n if ($this->profile->log_notes === Profile::LOG_NOTE_ENHANCED) {\n $this->profile->update([\n 'log_notes' => Profile::LOG_NOTE_CLASSIC,\n ]);\n }\n }\n\n return $noteId;\n }\n\n /**\n * This is using the \"Enhanced\" Notes feature, NOT the \"Notes & Attachments\" feature being deprecated.\n *\n * @url https://salesforce.stackexchange.com/questions/104408/how-can-i-create-an-account-note-or-contact-note-via-api-that-is-visible-in-sale\n */\n private function buildEnhancedNote(string $title, string $body, string $objectId): string\n {\n // Decode stored entities, escape HTML (without quoting), then convert line breaks for Salesforce formatting\n $decodedBody = html_entity_decode($body, ENT_QUOTES | ENT_HTML5);\n $sanitizedBody = htmlspecialchars($decodedBody, ENT_NOQUOTES, 'UTF-8', false);\n $content = nl2br($sanitizedBody, false);\n $note = [\n 'OwnerId' => $this->profile->crm_provider_id,\n 'Title' => $title,\n 'Content' => base64_encode($content),\n ];\n\n $noteId = $this->createRecord('ContentNote', $note);\n\n $link = [\n 'ContentDocumentId' => $noteId,\n 'LinkedEntityId' => $objectId,\n 'ShareType' => 'I',\n ];\n\n $this->createRecord('ContentDocumentLink', $link);\n\n return $noteId;\n }\n\n private function buildClassicNote(string $title, string $body, string $objectId): string\n {\n if (in_array($this->parseObjectType($objectId), [Field::OBJECT_TASK, Field::OBJECT_EVENT])) {\n $this->logger->info('[Salesforce] Summary not sent', [\n 'profile_id' => $this->profile->id,\n 'objectId' => $objectId,\n 'reason' => 'Classical Note does not support Task/Event relation',\n ]);\n\n return '';\n }\n\n $titleTrimmed = null;\n\n if (mb_strlen($title) > 80) {\n $titleTrimmed = substr($title, 0, 77) . '...';\n }\n $payload = [\n 'OwnerId' => $this->profile->crm_provider_id,\n 'IsPrivate' => false,\n 'Title' => $titleTrimmed ?? $title,\n 'Body' => $titleTrimmed ? $title . PHP_EOL . $body : $body,\n 'ParentId' => $objectId,\n ];\n\n return $this->createRecord('Note', $payload);\n }\n\n /**\n * @inheritdoc\n */\n public function find(string $name, array $scopes): array\n {\n if ($this->profile === null) {\n return [];\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $limitValues = ['limit' => $this->limit, 'offset' => $this->offset];\n $sosl = $queryBuilder->buildFindQuery($name, $scopes, $limitValues);\n\n $this->logger->info('[Salesforce] Find prospects', [\n 'profile_id' => $this->profile->id,\n 'sosl_query' => $sosl,\n 'search_string' => $name,\n 'scopes' => $scopes,\n ]);\n\n $data = Cache::remember($this->profile->id . $sosl, self::CACHE_TTL, function () use ($sosl) {\n $data = [];\n\n try {\n // Hit remote API.\n $objects = $this->queryHandler->search($sosl);\n\n // Build mapped list.\n foreach ($objects as $object) {\n $type = strtolower($object['attributes']['type']);\n\n $record = [\n 'crmId' => $object['Id'],\n 'name' => $object['Name'],\n 'prospectType' => $type,\n 'phoneNumbers' => [],\n 'crmUrl' => $this->generateProviderUrl($object['Id'], $type),\n ];\n\n switch ($type) {\n case 'lead':\n if (empty($object['Company']) === false) {\n $record['organization'] = $object['Company'];\n }\n\n if (empty($object['Title']) === false) {\n $record['title'] = $object['Title'];\n }\n\n $stage = $this->config->stages()\n ->where('type', Stage::TYPE_LEAD)\n ->where('name', $object['Status'])\n ->first();\n\n // Lazy create the stage.\n if ($stage === null) {\n $stage = $this->importStages([Stage::TYPE_LEAD], $object['Status']);\n }\n\n if ($stage) {\n $record += [\n 'stage' => [\n 'id' => $stage->id_string,\n 'name' => $stage->name,\n ],\n ];\n }\n\n if (empty($object['RecordTypeId']) === false) {\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $object['RecordTypeId'])\n ->first();\n\n if ($recordType) {\n $record += [\n 'recordType' => [\n 'id' => $recordType->id_string,\n 'name' => $recordType->name,\n ],\n ];\n }\n }\n\n break;\n\n case 'account':\n if (empty($object['Industry']) === false) {\n $record['industry'] = $object['Industry'];\n $record['detailsLine'] = $object['Industry'];\n }\n if (! empty($object['PersonEmail'])) {\n $record['detailsLine'] = $object['PersonEmail'];\n }\n\n break;\n\n case 'contact':\n // For contacts, we should try and fetch their account name too.\n if ($object['AccountId']) {\n // Cheaper to get this locally.\n $account = $this->config->accounts()\n ->where('crm_provider_id', $object['AccountId'])\n ->first(['name']);\n\n if ($account) {\n $record['organization'] = $account->name;\n }\n }\n\n if (! empty($object['IsPersonAccount']) && $object['Email']) {\n $record['detailsLine'] = $object['Email'];\n } else {\n if (empty($object['Title']) === false) {\n $record['title'] = $object['Title'];\n }\n }\n\n break;\n }\n\n // Add phone numbers to record.\n if (empty($object['Phone']) === false && $object['Phone']) {\n $record['phoneNumbers'][] = [\n 'number' => $object['Phone'],\n 'nationalFormat' => phone_national($this->profile->user->country_code, $object['Phone']),\n 'type' => 'phone',\n ];\n }\n\n if (empty($object['MobilePhone']) === false && $object['MobilePhone']) {\n $record['phoneNumbers'][] = [\n 'number' => $object['MobilePhone'],\n 'nationalFormat' => phone_national(\n $this->profile->user->country_code,\n $object['MobilePhone']\n ),\n 'type' => 'mobile',\n ];\n }\n\n $data[] = $record;\n }\n } catch (NoResultsException $e) {\n $data = [];\n }\n\n return $data;\n });\n\n return $data;\n }\n\n /**\n * @inheritdoc\n */\n public function findOpportunities(?string $crmAccountId, ?string $crmContactId, ?int $userId = null): array\n {\n $data = [];\n $ownerData = [];\n $ownerId = null;\n\n if ($crmAccountId === null) {\n return $data;\n }\n\n if ($userId) {\n $profileRepository = app(ProfileRepository::class);\n $profile = $profileRepository->findProfileByUserId($this->config, $userId);\n\n $ownerId = $profile instanceof Profile ? $profile->getCrmProviderId() : null;\n }\n\n try {\n // Perhaps their profile has no opportunity permissions.\n if ($this->profile === null || $this->profile->opportunity_fields === null) {\n return $data;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $query = $queryBuilder->buildFindOpportunitiesQuery();\n\n $objects = $this->queryHandler->query($query, ['accountId' => $crmAccountId]);\n\n foreach ($objects as $object) {\n $record = [\n 'crmId' => $object['Id'],\n 'name' => $object['Name'],\n 'won' => $object['IsWon'],\n 'closed' => $object['IsClosed'],\n ];\n\n $valueFieldName = 'Amount';\n if ($this->config->opportunity_value_field_id) {\n $valueFieldName = $this->config->opportunityValueField->crm_provider_id;\n }\n\n if (empty($object[$valueFieldName]) === false) {\n $currency = $object['CurrencyIsoCode'] ?? $this->config->default_currency;\n $value = formatCurrency($object[$valueFieldName], $currency);\n\n $record += [\n 'value' => $value,\n ];\n }\n\n $stage = $this->config->stages()\n ->where('type', Stage::TYPE_OPPORTUNITY)\n ->where('name', $object['StageName'])\n ->first();\n\n // Lazy create the stage.\n if ($stage === null) {\n $stage = $this->importStages([Stage::TYPE_OPPORTUNITY], $object['StageName']);\n }\n\n $record += [\n 'stage' => [\n 'id' => $stage->id_string,\n 'name' => $stage->name,\n ],\n ];\n\n if (empty($object['RecordTypeId']) === false) {\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $object['RecordTypeId'])\n ->first();\n\n if ($recordType) {\n $record += [\n 'recordType' => [\n 'id' => $recordType->id_string,\n 'name' => $recordType->name,\n ],\n ];\n }\n }\n\n if ($ownerId && isset($object['OwnerId']) && $object['OwnerId'] === $ownerId) {\n $ownerData[] = $record;\n }\n\n $data[] = $record;\n }\n } catch (NoResultsException $e) {\n return $data;\n }\n\n if (! empty($ownerData)) {\n return $ownerData;\n }\n\n return $data;\n }\n\n public function getContactRolesFromCrm(?Carbon $since = null): array\n {\n $roles = [];\n\n if ($this->profile === null) {\n return $roles;\n }\n\n $queryBuilder = app(QueryBuilder::class, ['profile' => $this->profile]);\n\n $query = $queryBuilder->buildGetContactRolesQuery($since);\n\n try {\n $objects = $this->queryHandler->query($query);\n\n foreach ($objects as $object) {\n $roles[] = [\n 'id' => $object['Id'],\n 'contactId' => $object['ContactId'],\n 'opportunityId' => $object['OpportunityId'],\n 'ownerId' => $object['Opportunity']['OwnerId'] ?? null,\n 'isPrimary' => $object['IsPrimary'],\n 'role' => $object['Role'],\n ];\n }\n } catch (NoResultsException) {\n // Just return an empty array.\n $this->logger->info('[Salesforce] No contact roles found', [\n 'since' => $since?->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n }\n\n return $roles;\n }\n\n public function syncContactRoles(Carbon $since): int\n {\n $contactRoleRepository = app(ContactRoleRepository::class);\n\n $crmContactRoles = $this->getContactRolesFromCrm(since: $since);\n $syncCount = 0;\n $contactRoles = [];\n\n foreach ($crmContactRoles as $crmContactRole) {\n $contactRoles[] = $this->importContactRole($crmContactRole);\n $syncCount++;\n }\n\n $contactRoleRepository->saveContactRoles($contactRoles);\n\n $this->syncRemotelyDeletedContactRoles();\n\n return $syncCount;\n }\n\n private function importContactRole(array $contactRole): array\n {\n $contact = $this->config->contacts()\n ->where('crm_provider_id', $contactRole['contactId'])\n ->first();\n\n if ($contact === null) {\n $contact = $this->syncContact($contactRole['contactId']);\n }\n\n $opportunity = $this->config->opportunities()\n ->where('crm_provider_id', $contactRole['opportunityId'])\n ->first();\n\n if ($opportunity === null) {\n $opportunity = $this->syncOpportunity($contactRole['opportunityId']);\n }\n\n $role = null;\n if (! empty($contactRole['role'])) {\n $role = mb_strimwidth($contactRole['role'], 0, 191);\n }\n\n return [\n 'crm_configuration_id' => $this->config->getId(),\n 'contact_id' => $contact->getId(),\n 'crm_provider_id' => $contactRole['id'],\n 'subject_type' => ContactRole::SUBJECT_TYPE_OPPORTUNITY,\n 'subject_id' => $opportunity->getId(),\n 'is_primary' => $contactRole['isPrimary'],\n 'role' => $role,\n ];\n }\n\n protected function syncRemotelyDeletedContactRoles(): bool\n {\n try {\n $deletedRemotely = $this->queryHandler->queryDeleted('OpportunityContactRole');\n } catch (NoResultsException $e) {\n return false;\n }\n\n $deletedOpportunities = $deletedRemotely->getResults();\n $deletedIds = array_column($deletedOpportunities, 'id');\n\n $contactRoleRepository = app(ContactRoleRepository::class);\n\n foreach (array_chunk($deletedIds, self::HARD_DELETE_CHUNK) as $chunk) {\n $contactRoleRepository->deleteContactRoles($chunk);\n\n $this->logger->info('[' . $this->getDisplayName() . '] Remotely deleted opportunities synced', [\n 'teamId' => $this->team->id_string,\n 'remotelyDeletedOpportunities' => $chunk,\n 'count' => count($chunk),\n ]);\n }\n\n return true;\n }\n\n /**\n * @inheritdoc\n */\n public function getTasks(string $objectType, string $objectId, ?string $opportunityId): array\n {\n $data = $objects = [];\n\n $hasWho = \\in_array($objectType, ['lead', 'contact']);\n $playbook = $this->getPlaybook($this->profile->user);\n $fields = array_merge(\n $this->profile->getFieldsAsArray(parent::OBJECT_TASK),\n $playbook && $playbook->activityField ? [$playbook->activityField->crm_provider_id] : []\n );\n\n // Query should default to any open call for that user.\n $query = '\n SELECT ' . implode(',', array_unique($fields)) . '\n FROM Task\n WHERE OwnerId = :ownerId\n AND IsArchived = false\n AND IsDeleted = false\n AND IsClosed = false\n AND (';\n\n if ($objectType === 'account') {\n // This covers tasks tied to a related contact or opportunity too.\n $query .= '\n AccountId = :accountId';\n }\n\n if ($hasWho) {\n $query .= '\n WhoId = :whoId';\n\n // If we are also going to check on a specific opportunity, set that up.\n if ($opportunityId) {\n $query .= ' OR WhatId = :whatId';\n }\n }\n\n $query .= ' ) ORDER BY LastModifiedDate DESC';\n\n try {\n $objects = $this->queryHandler->query($query, [\n 'ownerId' => $this->profile->crm_provider_id,\n 'whoId' => $objectId,\n 'whatId' => $opportunityId,\n 'accountId' => $objectId,\n ]);\n } catch (NoResultsException $e) {\n return $data;\n } finally {\n $this->logger->debug(sprintf('[Salesforce] Found %s tasks for query \"%s\"', count($objects), $query));\n }\n\n foreach ($objects as $object) {\n $dueDate = $object['ActivityDate'] ? Carbon::parse($object['ActivityDate'])->toIso8601String() : null;\n $data[] = [\n 'crmId' => $object['Id'],\n 'subject' => $object['Subject'],\n 'due' => $dueDate,\n 'type' => $object[$playbook->activityField->crm_provider_id],\n ];\n }\n\n return $data;\n }\n\n /**\n * @inheritdoc\n */\n public function getEvents(string $objectType, string $objectId, ?string $opportunityId): array\n {\n $data = $objects = [];\n $user = $this->profile?->user;\n if ($this->profile === null || $user === null) {\n return $data;\n }\n\n $hasWho = \\in_array($objectType, ['lead', 'contact']);\n $playbook = $this->getPlaybook($user);\n $fields = array_merge(\n $this->profile->getFieldsAsArray(parent::OBJECT_EVENT),\n $playbook && $playbook->activityField ? [$playbook->activityField->crm_provider_id] : []\n );\n\n // Query should default to any event starting in the last week and ending up until today owned by the user.\n $query = '\n SELECT ' . implode(',', array_unique($fields)) . '\n FROM Event\n WHERE OwnerId = :ownerId\n AND IsArchived = false\n AND IsAllDayEvent = false\n AND StartDateTime >= LAST_N_DAYS:7\n AND EndDateTime <= TODAY\n AND (';\n\n if ($objectType === 'account') {\n // This covers events tied to a related contact or opportunity too.\n $query .= '\n AccountId = :accountId';\n }\n\n if ($hasWho) {\n $query .= '\n WhoId = :whoId';\n\n // If we are also going to check on a specific opportunity, set that up.\n if ($opportunityId) {\n $query .= ' OR WhatId = :whatId';\n }\n }\n\n $query .= ' ) ORDER BY LastModifiedDate DESC';\n\n try {\n $objects = $this->queryHandler->query($query, [\n 'ownerId' => $this->profile->crm_provider_id,\n 'whoId' => $objectId,\n 'whatId' => $opportunityId,\n 'accountId' => $objectId,\n ]);\n } catch (NoResultsException $e) {\n return $data;\n } finally {\n $this->logger->debug(sprintf('[Salesforce] Found %s tasks for query \"%s\"', count($objects), $query));\n }\n\n foreach ($objects as $object) {\n $dueDate = $object['StartDateTime'] ? Carbon::parse($object['StartDateTime'])->toIso8601String() : null;\n\n $data[] = [\n 'crmId' => $object['Id'],\n 'subject' => $object['Subject'],\n 'due' => $dueDate,\n 'type' => $object[$playbook->activityField->crm_provider_id],\n ];\n }\n\n return $data;\n }\n\n /**\n * Try to find CRM Objects using email address\n *\n * @return null|array{\n * Lead|null,\n * Account|null,\n * Opportunity|null,\n * Contact|null,\n * Stage|null,\n * string|null\n * }\n */\n public function matchExactlyByEmail(string $email, ?int $userId = null): ?array\n {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $sosl = $queryBuilder->buildMatchByQuery($email, Field::TYPE_EMAIL);\n if ($sosl === null) {\n return null;\n }\n\n try {\n $objects = $this->queryHandler->search($sosl);\n $objects = $this->queryHandler->prioritiseResults(\n $objects,\n $email,\n QueryHandler::PRIORITISE_EMAIL\n );\n\n $data = $this->convertCrmData($objects, $userId);\n\n return ! empty(array_filter($data)) ? $data : null;\n } catch (NoResultsException $e) {\n // Try the account next.\n if ($this->profile->account_fields === null) {\n return null;\n }\n }\n\n return null;\n }\n\n public function getDomain(string $email): ?string\n {\n // SF improved search - strip the domain extension, min domain name length 4\n return $this->getCompanyNameFromEmail(email: $email, minNameLength: 4);\n }\n\n /**\n * Try to find CRM objects using domain name of the email address\n *\n * @return null|array{\n * Lead|null,\n * Account|null,\n * Opportunity|null,\n * Contact|null,\n * Stage|null,\n * string|null\n * }\n */\n public function matchByDomain(string $domain, ?int $userId = null): ?array\n {\n $companyName = $domain;\n\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $sosl = $queryBuilder->buildMatchByDomainQuery($companyName);\n\n try {\n $objects = $this->queryHandler->search($sosl);\n\n $data = $this->convertCrmData($objects, $userId);\n\n return ! empty(array_filter($data)) ? $data : null;\n } catch (NoResultsException) {\n return null;\n }\n }\n\n public function matchByPhone(string $phone, ?string $rawPhoneNumber = null, ?int $userId = null): ?array\n {\n // Don't bother looking up numbers that are masked.\n if (str_contains($phone, '**')) {\n return null;\n }\n\n if ($this->isPhoneNumberOfTeamMember($phone)) {\n return null;\n }\n\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $phoneNational = phone_national(null, $phone) ?? '';\n $possiblePhoneFormats = collect([\n preg_replace('/\\D/', '', ltrim($phone, '0+')),\n preg_replace('/\\D/', '', $phoneNational),\n formatDashPhoneNumber($phone),\n $phoneNational,\n ])\n ->filter() // Removes null and empty strings\n ->unique()\n ->values();\n\n foreach ($possiblePhoneFormats as $phone) {\n $sosl = $queryBuilder->buildMatchByQuery($phone, Field::TYPE_PHONE);\n if ($sosl === null) {\n continue;\n }\n\n try {\n $objects = $this->queryHandler->search($sosl);\n $objects = $this->queryHandler->prioritiseResults(\n $objects,\n $phone,\n QueryHandler::PRIORITISE_PHONE\n );\n\n return $this->convertCrmData($objects, $userId);\n } catch (NoResultsException) {\n continue;\n }\n }\n\n return null;\n }\n\n private function isPhoneNumberOfTeamMember(string $phone): bool\n {\n $teamRepository = app(TeamRepository::class);\n $user = $teamRepository->findTeamMemberByPhone($this->team, $phone);\n\n if ($user instanceof User) {\n return true;\n }\n\n return false;\n }\n\n protected function getCacheKey(string $object, ?int $userId = null): ?string\n {\n $key = $this->profile->id . $object;\n $keySuffix = $this->getOwnerKeySuffix($userId);\n\n return $key . $keySuffix;\n }\n\n private function getOwnerKeySuffix(?int $userId = null): string\n {\n return $userId === null ? '' : (string) $userId;\n }\n\n /** Determine the CRM Objects which represent the call activity. */\n public function matchByName(string $name, ?int $userId = null): ?array\n {\n // Don't waste time searching for single character strings.\n if (\\strlen($name) <= 1) {\n return null;\n }\n\n if ($this->profile === null) {\n return null;\n }\n\n $cacheKey = $this->getCacheKey($name, $userId);\n\n $result = Cache::remember($cacheKey, 60, function () use ($name, $userId) {\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $sosl = $queryBuilder->buildMatchByQuery($name, 'name');\n if ($sosl === null) {\n return false;\n }\n\n try {\n $objects = $this->queryHandler->search($sosl);\n } catch (NoResultsException $e) {\n return false;\n }\n\n $objects = $this->queryHandler->prioritiseResults(\n $objects,\n $name,\n QueryHandler::PRIORITISE_NAME\n );\n\n $data = $this->convertCrmData($objects, $userId);\n\n return (! empty(array_filter($data))) ? $data : false;\n });\n\n return is_array($result) ? $result : null;\n }\n\n /**\n * @return array{\n * Lead|null,\n * Account|null,\n * Opportunity|null,\n * Contact|null,\n * Stage|null,\n * string|null\n * }\n */\n protected function convertCrmData(QueryIterator $objects, ?int $userId = null): array\n {\n $lead = null;\n $contact = null;\n $opportunity = null;\n $account = null;\n $stage = null;\n $countryCode = null;\n\n if ($objects->count() > 0) {\n $object = $objects->current();\n\n if ($object['attributes']['type'] === 'Lead') {\n $lead = $this->importLead($object);\n\n // Lead might not be imported if the Stage is null for example.\n if ($lead) {\n $countryCode = $lead->country_code;\n $stage = $lead->stage;\n }\n } else {\n if ($object['attributes']['type'] === 'Contact') {\n $contact = $this->importContact($object);\n $account = $contact?->account;\n } else {\n $account = $this->importAccount($object);\n }\n\n if ($contact && $contact->country_code) {\n $countryCode = $contact->country_code;\n } elseif ($account) {\n $countryCode = $account->country_code;\n }\n\n try {\n $sfOpportunities = $this->findOpportunities(\n $account?->getCrmProviderId(),\n $contact?->getCrmProviderId(),\n $userId\n );\n\n // Take the first opportunity, which will be ordered as priority based on their settings.\n if (! empty($sfOpportunities)) {\n // Persist this remote object.\n $opportunity = $this->syncOpportunity($sfOpportunities[0]['crmId']);\n $stage = $opportunity?->stage;\n }\n } catch (Exception) {\n // Nothing to see here.\n }\n }\n }\n\n return [\n $lead,\n $account,\n $opportunity,\n $contact,\n $stage,\n $countryCode,\n ];\n }\n\n /**\n * @inheritdoc\n */\n public function updateStage($crmObject, Stage $stage): void\n {\n if ($stage->type === Stage::TYPE_LEAD) {\n $objectType = 'Lead';\n $objectId = $crmObject->crm_provider_id;\n $objectStageType = 'Status';\n } else {\n $objectType = 'Opportunity';\n $objectId = $crmObject->crm_provider_id;\n $objectStageType = 'StageName';\n }\n\n $headers = [];\n if ($this->config->trigger_assignment_rules === false) {\n // @see: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/headers_autoassign.htm\n $headers = [\n 'Sforce-Auto-Assign' => 'false',\n ];\n }\n\n $this->updateRecord($objectType, $objectId, [$objectStageType => $stage->name], $headers);\n }\n\n public function parseObjectType(string $objectId): string\n {\n if (Str::startsWith($objectId, '001')) {\n return 'account';\n }\n\n if (Str::startsWith($objectId, '003')) {\n return 'contact';\n }\n\n if (Str::startsWith($objectId, '00Q')) {\n return 'lead';\n }\n\n if (Str::startsWith($objectId, '006')) {\n return 'opportunity';\n }\n\n if (Str::startsWith($objectId, '00U')) {\n return 'event';\n }\n\n if (Str::startsWith($objectId, '00T')) {\n return 'task';\n }\n\n throw new \\InvalidArgumentException('Unsupported Object Type');\n }\n\n public function syncProfiles(?User $userToSearch = null): ?Profile\n {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, ['profile' => $this->profile]);\n $query = $queryBuilder->buildGetUsersQuery($userToSearch);\n\n try {\n $salesforceUsers = $this->queryHandler->query($query, [\n 'active' => true,\n ]);\n } catch (NoResultsException $e) {\n $this->logger->info('[Salesforce] Sync Profiles. No users found', [\n 'query' => $query,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $teamRepository = app(TeamRepository::class);\n $customRules = $this->getCustomProfileRules($teamRepository);\n\n foreach ($salesforceUsers as $crmUser) {\n if ($crmUser['Email'] === null) {\n continue;\n }\n\n if (! $this->customProfileValidation($crmUser, $customRules)) {\n continue;\n }\n\n $user = $teamRepository->findActiveTeamMemberByEmail($this->team, $crmUser['Email']);\n\n if (! $user instanceof User) {\n continue;\n }\n\n $edition = $crmUser['UserPreferencesLightningExperiencePreferred']\n ? Profile::EDITION_LIGHTNING\n : Profile::EDITION_CLASSIC;\n\n $profileRepository = app(ProfileRepository::class);\n $profile = $profileRepository->updateOrCreateProfile(\n $user,\n [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmUser['Id'],\n ],\n [\n 'user_id' => $user->getId(),\n 'edition' => $edition,\n 'has_external_cti' => ! empty($crmUser['CallCenterId']),\n 'crm_profile_id' => $crmUser['ProfileId'],\n ]\n );\n\n if ($userToSearch instanceof User && $userToSearch->getId() === $user->getId()) {\n return $profile;\n }\n }\n\n // Clean up inactive profiles\n try {\n $this->archiveInactiveProfiles();\n } catch (\\Exception $e) {\n $this->logger->warning('[Salesforce] Profile archiving failed', [\n 'teamId' => $this->team->getUuid(),\n 'reason' => $e->getMessage(),\n ]);\n }\n\n return null;\n }\n\n public function generateProviderUrl(string $providerId, string $objectType): ?string\n {\n $url = null;\n\n // For Salesforce it's easy, we just point every object to the apex domain and they handle it.\n switch ($objectType) {\n case 'lead':\n case 'account':\n case 'contact':\n case 'opportunity':\n case 'task':\n case 'event':\n case 'activity':\n\n $url = $this->config->crm_base_url . '/' . $providerId;\n\n break;\n }\n\n return $url;\n }\n\n public function buildTaskSearchFields(): array\n {\n return ['Id', 'WhoId', 'WhatId', 'AccountId'];\n }\n\n public function getTaskByFilterConditions(\n array $fields,\n array $filters,\n bool $bulkSearch = false,\n bool $strictFilters = true\n ): ?array {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $query = $queryBuilder->buildSearchTaskQuery($fields, $filters, $bulkSearch, $strictFilters);\n\n try {\n if (! $bulkSearch) {\n $objects = $this->queryHandler->query($query, $filters);\n if ($objects->count() === 1) {\n return $objects->current();\n }\n }\n\n if ($bulkSearch) {\n $objects = $this->queryHandler->query($query);\n $records = [];\n foreach ($objects as $record) {\n $key = $record[end($fields)];\n $records[$key] = $record;\n }\n\n return $records;\n }\n } catch (\\Exception $e) {\n $this->logger->info('[Salesforce] Failed to execute query', [\n 'query' => $query,\n 'error' => $e->getMessage(),\n ]);\n }\n\n return null;\n }\n\n public function mapCrmObjects(array $task): array\n {\n $activityData = [];\n\n if (! empty($task['WhoId'])) {\n $type = $this->parseObjectType($task['WhoId']);\n $activityData[$type] = $task['WhoId'];\n }\n if (! empty($task['AccountId'])) {\n $activityData['account'] = $task['AccountId'];\n }\n if (! empty($task['WhatId'])) {\n $activityData['opportunity'] = $task['WhatId'];\n }\n\n return $activityData;\n }\n\n /**\n * Get SF task by Outreach call id.\n */\n public function getTaskByFilter(\n string $activityFieldType,\n array $filters,\n string $operator = '=',\n array $additionalFields = []\n ): ?array {\n $data = [];\n\n try {\n // Default (base) fields.\n $fields = ['Id', 'Subject', 'Description', 'ActivityDate', 'WhoId', 'WhatId', $activityFieldType];\n\n foreach ($additionalFields as $additionalField) {\n $fields[] = $additionalField->crm_provider_id;\n }\n\n $fields = array_unique($fields);\n\n // Find task with the same Outreach id as the call id.\n $query = 'SELECT ' . implode(',', $fields) . '\n FROM Task\n WHERE IsArchived = false AND IsDeleted = false';\n\n foreach ($filters as $key => $value) {\n $key = preg_quote($key, '/');\n $key = str_replace(['\\'', '\"'], '', $key);\n // Prepare the substitution.\n $strKey = \":$key\";\n\n $query .= \" AND $key $operator $strKey\";\n }\n\n $query .= ' ORDER BY LastModifiedDate DESC LIMIT 1';\n\n $objects = $this->queryHandler->query($query, $filters);\n\n // There should be only one task related to this call if any.\n if ($objects->count() === 1) {\n $object = $objects->current();\n\n $dueDate = $object['ActivityDate'] ? Carbon::parse($object['ActivityDate'])->toIso8601String() : null;\n\n $data = array_merge($object, [\n 'crmId' => $object['Id'],\n 'subject' => $object['Subject'],\n 'summary' => $object['Description'],\n 'due' => $dueDate,\n 'Type' => $object[$activityFieldType],\n ]);\n }\n } catch (NoResultsException $e) {\n // Filters don't match any records.\n } catch (ServiceUnavailableException $serviceUnavailableException) {\n // Service cannot be queried. We should probably log this.\n }\n\n return $data;\n }\n\n /**\n * Get Salesforce fields including datetime fields\n *\n * @param $objectType\n */\n private function getAllFieldsAsArray($objectType): array\n {\n $basicFields = [];\n // Not all users have access to all object fields.\n if ($this->profile->{$objectType . '_fields'}) {\n $basicFields = explode(',', $this->profile->{$objectType . '_fields'});\n }\n\n $extraFields = [\n 'CreatedDate',\n 'LastModifiedDate',\n 'IsDeleted',\n ];\n\n if ($objectType === self::OBJECT_OPPORTUNITY\n && $this->config->opportunity_value_field_id\n && ! in_array($this->config->opportunityValueField->crm_provider_id, $basicFields)\n ) {\n $extraFields[] = $this->config->opportunityValueField->crm_provider_id;\n }\n\n return array_unique(array_merge($basicFields, $extraFields));\n }\n\n /**\n * Generate transcription for activity description.\n */\n private function generateTranscription(Activity $activity): string\n {\n if (! ($this->config->store_transcript)) {\n // If sending transcription to activity toggle is disabled\n return '';\n }\n\n return $this->transcriptionService\n ->findTranscriptionByActivity($activity)\n ->map(static function (array $transcriptionSegment): string {\n return $transcriptionSegment['formattedStartsAt'] . ' | ' . $transcriptionSegment['transcript'];\n })\n ->implode(PHP_EOL);\n }\n\n /**\n * Find related Salesforce event based on activity data\n *\n * @return array<string>\n */\n public function fetchRelatedActivity(Activity $activity): array\n {\n $this->logger->info('[Salesforce] Searching for related activity', [\n 'activityId' => $activity->getUuid(),\n 'ownerId' => $this->profile?->crm_provider_id,\n ]);\n\n $sfEvent = $this->fetchRelatedEvent($activity);\n if (empty($sfEvent)) {\n $this->logger->info('[Salesforce] No related activity found', [\n 'activityId' => $activity->getUuid(),\n 'ownerId' => $this->profile?->crm_provider_id,\n 'account' => $activity->hasAccount()\n ? $activity->getAccount()->getCrmProviderId()\n : null,\n ]);\n\n return [];\n }\n\n return $sfEvent;\n }\n\n public function fetchAndAssociateRelatedActivity(Activity $activity): ?Activity\n {\n if ($activity->isTypeConference() === false) {\n return null;\n }\n\n if ($activity->hasActualStartTime() === false && $activity->hasScheduledStartTime() === false) {\n return null;\n }\n\n if (! $activity->hasProspect()) {\n $this->logger->info('[Salesforce] Skip look up, Activity not linked to Lead, Contact or Account', [\n 'activityId' => $activity->getUuid(),\n ]);\n\n return null;\n }\n\n $playbook = $this->getPlaybook($activity->getUser());\n if ($playbook !== null && $playbook->getActivityType() === Playbook::ACTIVITY_TYPE_TASK) {\n $this->logger->info('[Salesforce] Skip auto-sync for task-based playbook', [\n 'activityUuid' => $activity->getUuid(),\n 'playbookId' => $playbook->getId(),\n 'playbookType' => $playbook->getActivityType(),\n ]);\n\n return null;\n }\n\n try {\n $sfEvent = $this->fetchRelatedActivity($activity);\n if (empty($sfEvent)) {\n return null;\n }\n\n [$activityField, $activityType] = $this->resolveActivityTypeFromEvent($activity, $sfEvent);\n\n $this->logger->info('[Salesforce] Found related activity', [\n 'activityId' => $activity->getUuid(),\n 'sfEvent' => $sfEvent['Id'],\n 'activityFieldName' => $activityField,\n 'crmActivityType' => ($activityField !== null && isset($sfEvent[$activityField]))\n ? $sfEvent[$activityField]\n : null,\n 'activityType' => $activityType,\n ]);\n\n $userId = $this->findRelatedActivityUserId($activity, $sfEvent);\n\n if ($activity->getUserId() !== $userId) {\n $this->logger->info('[Salesforce] Updating meeting owner', [\n 'activityId' => $activity->getUuid(),\n 'oldUserId' => $activity->getUserId(),\n 'newUserId' => $userId,\n ]);\n }\n\n $this->updateSfEventDescription($activity, $sfEvent);\n\n $activity->update([\n 'user_id' => $userId,\n 'crm_provider_id' => $sfEvent['Id'],\n 'playbook_category_id' => $activityType->id ?? $activity->getCategory()?->getId(),\n ]);\n\n $this->logger->info('[Salesforce] Activity updated', [\n 'activityId' => $activity->getUuid(),\n ]);\n\n return $activity;\n } catch (\\Exception $exception) {\n \\Sentry::captureException($exception);\n\n throw $exception;\n }\n }\n\n /**\n * @param array<string, mixed> $sfEvent\n *\n * @return array{0: string|null, 1: mixed}\n */\n private function resolveActivityTypeFromEvent(Activity $activity, array $sfEvent): array\n {\n $activityField = $this->getActivityFieldName($activity);\n $activityType = null;\n\n if ($activityField !== null && ! empty($sfEvent[$activityField])) {\n $playbook = $this->getPlaybook($activity->getUser());\n $activityType = $this->getPlaybookCategory($playbook, strval($sfEvent[$activityField]));\n }\n\n return [$activityField, $activityType];\n }\n\n /**\n * @param array<string> $sfEvent\n */\n private function findRelatedActivityUserId(Activity $activity, array $sfEvent): int\n {\n $userId = $activity->getUserId();\n\n if (empty($sfEvent['OwnerId']) === false) {\n $profile = $this\n ->config\n ->profiles()\n ->where('crm_provider_id', $sfEvent['OwnerId'])\n ->get()\n ->filter(static function (Profile $profile) use ($activity): bool {\n if (! $activity->isTypeConference()) {\n return ! empty($profile->user) ? $profile->user->isStatusActive() : false;\n }\n\n $participants = $activity->getParticipants();\n\n return ! empty($profile->user)\n ? $profile->user->isStatusActive()\n && $profile->user->hasPermission(PermissionEnum::RECORD_MEETING)\n && $participants->contains('user_id', $profile->user_id)\n : false;\n })\n ->first();\n\n if ($profile) {\n $userId = $profile->user_id;\n }\n }\n\n return $userId;\n }\n\n /**\n * @param array<string, mixed> $sfEvent\n */\n private function updateSfEventDescription(Activity $activity, array $sfEvent): void\n {\n try {\n if (str_contains($sfEvent['Description'], $activity->id_string)) {\n return;\n }\n\n $payload = [\n 'Description' => $sfEvent['Description']\n . PHP_EOL\n . PHP_EOL\n . new DecorateActivity()->generateDescription($activity),\n ];\n\n $this->logger->info('[Salesforce] Update record', [\n 'activityId' => $activity->getUuid(),\n 'sfEvent' => $sfEvent['Id'],\n 'payload' => $payload,\n ]);\n\n $payload = array_merge(\n $payload,\n $this->payloadBuilder->fetchCustomFieldData($activity, Field::OBJECT_EVENT)\n );\n\n $this->updateRecord('Event', $sfEvent['Id'], $payload);\n } catch (\\Exception) {\n $this->logger->error('[Salesforce] Failed to update record', [\n 'activityUuid' => $activity->getUuid(),\n 'sfEvent' => $sfEvent['Id'],\n ]);\n }\n }\n\n /**\n * Returns the most recently modified Event within time range (if any).\n *\n * @return array|null An Event record from Salesforce.\n */\n private function fetchRelatedEvent(Activity $activity): ?array\n {\n $ownerId = $this->profile?->crm_provider_id;\n if ($ownerId === null) {\n return [];\n }\n\n /** @var ?Carbon $from */\n /** @var ?Carbon $to */\n [$from, $to] = $this->getFromToDates($activity);\n\n try {\n $whoId = null;\n $hasWho = $activity->lead_id || $activity->contact_id;\n if ($hasWho) {\n $whoId = $activity->hasLead()\n ? $activity->getLead()->crm_provider_id\n : $activity->getContact()->crm_provider_id;\n }\n\n if ($hasWho === false && $activity->account_id === null) {\n return null;\n }\n\n $query = $this->buildFetchRelatedEventQuery($activity);\n\n $objects = $this->queryHandler->query($query, [\n 'ownerId' => $ownerId,\n 'whoId' => $whoId,\n 'whatId' => $activity->hasOpportunity() ? $activity->getOpportunity()->crm_provider_id : null,\n 'accountId' => $activity->hasAccount() ? $activity->getAccount()->crm_provider_id : null,\n 'from' => $from?->format('Y-m-d\\TH:i:s\\Z'),\n 'to' => $to?->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($objects as $object) {\n return $object;\n }\n } catch (NoResultsException $e) {\n return [];\n }\n\n return [];\n }\n\n private function getFromToDates(Activity $activity): array\n {\n $from = null;\n $to = null;\n\n /** @var ?CalendarEvent $calendarEvent */\n $calendarEvent = $activity->calendarEvent()->first();\n if ($calendarEvent !== null) {\n $from = $calendarEvent->getStartTime();\n $to = $calendarEvent->getEndTime();\n }\n\n // For non-calendar imported activities\n // Also double check if calendar event dates could be null?\n // If null use what we've got so far\n if ($from === null || $to === null) {\n $from = $activity->hasScheduledStartTime()\n ? $activity->getScheduledStartTime()\n : $activity->getActualStartTime();\n $to = $activity->hasScheduledEndTime()\n ? $activity->getScheduledEndTime()->addMinutes(15)\n : $activity->getActualEndTime();\n }\n\n return [$from, $to];\n }\n\n /**\n * Determines the appropriate activity field name for querying Salesforce events.\n *\n * This method follows a hierarchy to determine the field name:\n * 1. Uses the playbook's activity field if it exists and is in the profile's accessible fields\n * 2. Falls back to the default activity field if the profile has no event fields configured\n * 3. Returns null if no suitable field is found\n *\n * @param Activity $activity The activity to determine the field for\n *\n * @return string|null The field name to use in queries, or null if none is available\n */\n private function getActivityFieldName(Activity $activity): ?string\n {\n if ($this->profile === null) {\n $this->logger->warning('[Salesforce] Cannot determine activity field - profile not found', [\n 'activityId' => $activity->getUuid(),\n ]);\n\n return null;\n }\n\n $profileEventFields = $this->profile->getFieldsAsArray('event');\n\n if (empty($profileEventFields)) {\n $defaultActivityField = $this->getDefaultActivityField(Field::OBJECT_EVENT);\n $defaultFieldName = $defaultActivityField?->getAttribute('crm_provider_id');\n // Profile not yet synced — fall back to the default activity field.\n // There is a small chance that the profile won't have Default Activity Type field access\n // in which case the query will fail.\n // This is however an edge case and should be reviewed for profile sync issues.\n Sentry::withScope(function (\\Sentry\\State\\Scope $scope) use ($defaultFieldName): void {\n $scope->setContext('details', [\n 'profileId' => $this->profile->id,\n 'defaultField' => $defaultFieldName,\n ]);\n Sentry::captureMessage(\n '[Salesforce] Profile event fields empty, falling back to default activity field.',\n \\Sentry\\Severity::warning()\n );\n });\n\n return $defaultFieldName;\n }\n\n $playbook = $this->getPlaybook($activity->getUser());\n\n if (! is_null($playbook) && ! is_null($playbook->getActivityField())) {\n $playbookFieldName = $playbook->getActivityField()->getAttribute('crm_provider_id');\n\n if (in_array($playbookFieldName, $profileEventFields, true)) {\n return $playbookFieldName;\n }\n\n $this->logger->warning('[Salesforce] Playbook activity field not found in profile fields', [\n 'activityId' => $activity->getUuid(),\n 'playbookField' => $playbookFieldName,\n 'profileId' => $this->profile->id,\n ]);\n }\n\n return null;\n }\n\n private function buildFetchRelatedEventQuery(Activity $activity): string\n {\n $hasWho = $activity->lead_id || $activity->contact_id;\n\n $activityFieldName = $this->getActivityFieldName($activity);\n $fields = array_filter(['Id', 'Description', 'OwnerId', $activityFieldName]);\n\n $ownerCondition = '(OwnerId = :ownerId OR CreatedById = :ownerId)';\n\n $query = '\n SELECT ' . implode(',', $fields) . '\n FROM Event\n WHERE ' . $ownerCondition . '\n AND IsArchived = false\n AND IsAllDayEvent = false\n AND StartDateTime >= :from\n AND EndDateTime <= :to\n AND (';\n\n $operator = '';\n if ($activity->account_id) {\n // This covers events tied to a related contact or opportunity too.\n $query .= 'AccountId = :accountId';\n\n $operator = ' OR ';\n }\n\n if ($hasWho) {\n $query .= $operator . 'WhoId = :whoId';\n\n // If we are also going to check on a specific opportunity, set that up.\n if ($activity->opportunity_id) {\n $query .= ' OR WhatId = :whatId';\n }\n }\n\n $query .= ') ORDER BY LastModifiedDate DESC';\n\n return $query;\n }\n\n public function fetchProspect(array $task): array\n {\n $lead = $account = $opportunity = $contact = $stage = $countryCode = null;\n $externalId = $task['WhoId'] ?? null;\n\n // Lead or Contact\n if ($externalId) {\n try {\n [$lead, $account, $opportunity, $contact, $stage, $countryCode] = $this->parseRecords($externalId);\n } catch (\\InvalidArgumentException $exception) {\n // Invalid object type.\n }\n }\n\n // If we happen to know the opportunity or account from the Task, figure that out.\n if (empty($task['WhatId']) === false) {\n // WhatId could be either Account ID or Opportunity ID.\n // If WhatId is Opportunity ID, get the opportunity and stage from the CRM.\n try {\n [, $account, $opportunity, , $stage, ] = $this->parseRecords($task['WhatId']);\n } catch (\\InvalidArgumentException $exception) {\n // Invalid object type.\n }\n }\n\n return [$lead, $account, $opportunity, $contact, $stage, $countryCode];\n }\n\n /**\n * Save activity transcription summary as note\n */\n public function saveTranscriptionSummaryAsNote(\n ActivityContract $activity,\n string $title,\n string $body,\n ?string $objectId,\n ?NoteObject $noteObject = null,\n ): ?string {\n return $this->saveNote($title, $body, (string) $objectId);\n }\n\n public function getObjectByFilterConditions(string $objectType, array $fields, array $filters): ?array\n {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $query = $queryBuilder->buildObjectSearchQuery($objectType, $fields, $filters);\n\n try {\n $objects = $this->queryHandler->query($query, $filters);\n if ($objects->count() === 1) {\n return $objects->current();\n }\n } catch (\\Exception $e) {\n $this->logger->info('[Salesforce] Failed to execute query', [\n 'query' => $query,\n 'error' => $e->getMessage(),\n ]);\n }\n\n return null;\n }\n\n private function getCustomProfileRules(TeamRepository $teamRepository): array\n {\n $teamSettings = $teamRepository->getTeamSetting($this->team, 'custom_profile_validation');\n\n if ($teamSettings instanceof TeamSettings && $teamSettings->getValueType() === 'array') {\n $customRules = json_decode($teamSettings->getValue(), true);\n if (is_array($customRules)) {\n return $customRules;\n }\n }\n\n return [];\n }\n\n private function customProfileValidation(array $crmUser, array $customRules): bool\n {\n foreach ($customRules as $customRule) {\n if ($crmUser[$customRule['field']] !== $customRule['value']) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * When syncing Contact / Lead / Account / Opportunity / Stage crm entities,\n * validate and restore locally trashed objects,\n * before updating them. Objects are identified by CrmProviderId\n */\n private function restoreAnyTrashedEntity(HasMany $targetEntity, string $crmProviderId): void\n {\n $recordExists = $targetEntity->withTrashed()->where(['crm_provider_id' => $crmProviderId])->first();\n if ($recordExists && $recordExists->trashed()) {\n $recordExists->restore();\n }\n }\n\n #[\\Override] public function supportsNotes(): bool\n {\n return true;\n }\n\n private function getOwnerProfile(?string $ownerId): ?Profile\n {\n if ($ownerId === null) {\n return null;\n }\n\n return $this->config->profiles()\n ->where('crm_provider_id', $ownerId)\n ->first();\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"bounds":{"left":0.41589096,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"bounds":{"left":0.4245346,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"bounds":{"left":0.43550533,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"bounds":{"left":0.44414893,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"bounds":{"left":0.45279256,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"bounds":{"left":0.4637633,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"bounds":{"left":0.47473404,"top":0.09896249,"width":0.024268618,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"bounds":{"left":0.5013298,"top":0.09896249,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"bounds":{"left":0.51230055,"top":0.09896249,"width":0.029587766,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"bounds":{"left":0.7237367,"top":0.09896249,"width":0.02825798,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.042220745,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"45","depth":4,"bounds":{"left":0.6938165,"top":0.123703115,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"bounds":{"left":0.70611703,"top":0.123703115,"width":0.00731383,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"41","depth":4,"bounds":{"left":0.71542555,"top":0.123703115,"width":0.009640957,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"66","depth":4,"bounds":{"left":0.72706115,"top":0.123703115,"width":0.010305851,"height":0.015163607},"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"bounds":{"left":0.7390292,"top":0.12210695,"width":0.00731383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"bounds":{"left":0.7463431,"top":0.12210695,"width":0.006981383,"height":0.018355945},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01';\nand id IN (32415, 32416);\n# and id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;\n\nSELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436\n\nSELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses\nFROM text_relays\nWHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')\nGROUP BY email_provider_id;\nSELECT id, status, telephony_provider_id, created_at\nFROM activities\nWHERE id IN (80028719, 80028846);\nSELECT id, status, code, email_sent_at, created_at, updated_at\nFROM text_relays\nWHERE id IN (32415, 32416);\nSELECT id, status, code, sender, recipient, created_at\nFROM text_relays\nWHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'\nORDER BY created_at DESC\nLIMIT 10;\n\nSELECT id, uuid, status, code, sender, recipient, created_at, updated_at\nFROM text_relays\nWHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');\n\n# ***************\nSELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count\nFROM users u\nINNER JOIN activities a ON u.id = .user_id\nWHERE a.type LIKE 'sms%'\nAND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.email, u.name, u.softphone_number\nORDER BY sms_count DESC;\n\nselect * from teams where id = 1;\n\nselect * from roles;\n\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1117 and sa.provider = 'hubspot';\nSELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES\nSELECT * FROM activities WHERE uuid_to_bin('25529043-8094-4781-927f-4f4da2a8185c') = uuid; # 80186192 NO\nSELECT * FROM crm_configurations WHERE id = 1053;\nSELECT * FROM teams WHERE id = 1117;\nselect * from users where id = 30249;\nselect * from playbooks where id = 5473;\nselect * from playbook_categories where id = 43783;\nselect * from playbook_categories where playbook_id = 5473;\nselect * from crm_fields where id = 659242;\nselect * from crm_field_values where crm_field_id = 659242;\n\nSELECT * FROM crm_field_data fd\n# JOIN crm_fields f ON fd.crm_field_id = f.id\n# JOIN activities a ON fd.activity_id = a.id\nWHERE activity_id = 79933459\n# AND f.crm_provider_id = 'hs_activity_type';\n\n\nSELECT * FROM activity_messages;\nselect * from text_relays where created_at > '2026-05-01';\nselect * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;\nselect * from users where team_id = 1 and id IN (18608, 13934, 7160);\nselect * from activities where user_id = 7160 order by id desc limit 10;\n\nselect * from accounts where team_id = 1 and name = 'Column5';\n\nselect * from users where name like '%Subra%'; # 31054, 1117\nselect * from teams where id = 1117;\nselect * from activity_searches where user_id = 31054;\nselect * from activity_search_filters where activity_search_id IN (88882, 88902);","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01';\nand id IN (32415, 32416);\n# and id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;\n\nSELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436\n\nSELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses\nFROM text_relays\nWHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')\nGROUP BY email_provider_id;\nSELECT id, status, telephony_provider_id, created_at\nFROM activities\nWHERE id IN (80028719, 80028846);\nSELECT id, status, code, email_sent_at, created_at, updated_at\nFROM text_relays\nWHERE id IN (32415, 32416);\nSELECT id, status, code, sender, recipient, created_at\nFROM text_relays\nWHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'\nORDER BY created_at DESC\nLIMIT 10;\n\nSELECT id, uuid, status, code, sender, recipient, created_at, updated_at\nFROM text_relays\nWHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');\n\n# ***************\nSELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count\nFROM users u\nINNER JOIN activities a ON u.id = .user_id\nWHERE a.type LIKE 'sms%'\nAND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.email, u.name, u.softphone_number\nORDER BY sms_count DESC;\n\nselect * from teams where id = 1;\n\nselect * from roles;\n\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1117 and sa.provider = 'hubspot';\nSELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES\nSELECT * FROM activities WHERE uuid_to_bin('25529043-8094-4781-927f-4f4da2a8185c') = uuid; # 80186192 NO\nSELECT * FROM crm_configurations WHERE id = 1053;\nSELECT * FROM teams WHERE id = 1117;\nselect * from users where id = 30249;\nselect * from playbooks where id = 5473;\nselect * from playbook_categories where id = 43783;\nselect * from playbook_categories where playbook_id = 5473;\nselect * from crm_fields where id = 659242;\nselect * from crm_field_values where crm_field_id = 659242;\n\nSELECT * FROM crm_field_data fd\n# JOIN crm_fields f ON fd.crm_field_id = f.id\n# JOIN activities a ON fd.activity_id = a.id\nWHERE activity_id = 79933459\n# AND f.crm_provider_id = 'hs_activity_type';\n\n\nSELECT * FROM activity_messages;\nselect * from text_relays where created_at > '2026-05-01';\nselect * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;\nselect * from users where team_id = 1 and id IN (18608, 13934, 7160);\nselect * from activities where user_id = 7160 order by id desc limit 10;\n\nselect * from accounts where team_id = 1 and name = 'Column5';\n\nselect * from users where name like '%Subra%'; # 31054, 1117\nselect * from teams where id = 1117;\nselect * from activity_searches where user_id = 31054;\nselect * from activity_search_filters where activity_search_id IN (88882, 88902);","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"bounds":{"left":0.011968086,"top":0.047885075,"width":0.024268618,"height":0.024740623},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.27027926,"top":1.0,"width":0.008643617,"height":0.0},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-1556586073691613239
|
-7851921920897086523
|
idle
|
accessibility
|
NULL
|
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
Sync Changes
Hide This Notification
Code changed:
Hide
12
246
3
21
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Services\Crm\Salesforce;
use Carbon\Carbon;
use Exception;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Events\Dispatcher;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Jiminny\Component\Country\CountriesMap;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Contracts\Repositories\TeamRepository;
use Jiminny\Contracts\Services\Crm\FetchRelatedActivityInterface;
use Jiminny\Contracts\Services\Crm\ImportsBusinessProcessesInterface;
use Jiminny\Contracts\Services\Crm\LayoutManagementInterface;
use Jiminny\Contracts\Services\Crm\MatchCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\Provider\SalesforceBatchSyncInterface;
use Jiminny\Contracts\Services\Crm\Provider\SalesforceInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityLookupInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityManipulationInterface;
use Jiminny\Contracts\Services\Crm\RemoteNoteEntityManipulationInterface;
use Jiminny\Contracts\Services\Crm\SearchTaskInterface;
use Jiminny\Contracts\Services\Crm\SendSummaryToCrmInterface;
use Jiminny\Contracts\Services\Crm\SettingsInterface;
use Jiminny\Contracts\Services\Crm\SupportsObjectTypeParseInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmProfileRecordTypesInterface;
use Jiminny\Contracts\Services\Crm\VerifyTaskExistsInterface;
use Jiminny\Enums\CrmObject;
use Jiminny\Events\Activities\Crm\LeadConverted;
use Jiminny\Exceptions\CrmException;
use Jiminny\Exceptions\HttpBadRequestException;
use Jiminny\Exceptions\HttpNotFoundException;
use Jiminny\Exceptions\NoResultsException;
use Jiminny\Exceptions\ServiceUnavailableException;
use Jiminny\Jobs\Crm\NoteObject;
use Jiminny\Jobs\Crm\MatchActivitiesToNewOpportunity;
use Jiminny\Models\Account;
use Jiminny\Models\Activity;
use Jiminny\Models\Calendar\CalendarEvent;
use Jiminny\Models\Contact;
use Jiminny\Models\Contracts\ActivityContract;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Models\Crm\Configuration;
use Jiminny\Models\Crm\ContactRole;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\Profile;
use Jiminny\Models\Crm\RecordType;
use Jiminny\Models\Lead;
use Jiminny\Models\Opportunity;
use Jiminny\Models\Playbook;
use Jiminny\Models\SocialAccount;
use Jiminny\Models\Stage;
use Jiminny\Models\TeamSettings;
use Jiminny\Models\User;
use Jiminny\Repositories\Crm\ContactRoleRepository;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\Crm\ProfileRepository;
use Jiminny\Repositories\Crm\RecordTypeFieldValuesRepository;
use Jiminny\Services\Avatar\ProspectPhotoPathService;
use Jiminny\Services\Crm\BaseService;
use Jiminny\Services\Crm\Helpers\ArrayIterator;
use Jiminny\Services\Crm\MatchDomainByEmailInterface;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Services\Crm\ResolveCompanyNameByEmailTrait;
use Jiminny\Services\Crm\Salesforce\Fields\FieldHelper;
use Jiminny\Services\Crm\Salesforce\Fields\FieldTypeConverter;
use Jiminny\Services\Crm\Salesforce\Fields\ValueNormalizer;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\FollowupActivityTrait;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\LogActivityTrait;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\RecordManipulationsTrait;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\SyncFieldsTrait;
use Jiminny\Utils\CurrencyFormatter;
use Jiminny\Utils\StringUtil;
use Ramsey\Uuid\Uuid;
use Sentry\Laravel\Facade as Sentry;
class Service extends BaseService implements
SalesforceInterface,
SalesforceBatchSyncInterface,
SyncCrmEntitiesInterface,
SyncCrmProfileRecordTypesInterface,
ImportsBusinessProcessesInterface,
RemoteEntityManipulationInterface,
FetchRelatedActivityInterface,
SendSummaryToCrmInterface,
MatchDomainByEmailInterface,
SearchTaskInterface,
LayoutManagementInterface,
SettingsInterface,
MatchCrmEntitiesInterface,
RemoteEntityLookupInterface,
SupportsObjectTypeParseInterface,
RemoteNoteEntityManipulationInterface,
VerifyTaskExistsInterface
{
use ResolveCompanyNameByEmailTrait;
use SyncFieldsTrait;
use DeleteObjectsTrait;
use RecordManipulationsTrait;
use ServiceTraits\BatchSyncTrait;
use FollowupActivityTrait;
use LogActivityTrait;
/**
* Note Body Limit for the Old Note-Taking Tool
*
* @var int
*/
private const int CLASSIC_NOTE_MAX_LENGTH = 32000;
/**
* Note Content Limit for the New Notes
*
* @var int
*/
private const int ENHANCED_NOTE_MAX_LENGTH = 50000000;
private const string INSTALLED_PACKAGE_ID = '033Tw0000007bKbIAI';
private const int CACHE_TTL = 600;
private const int TASK_VERIFICATION_CACHE_TTL = 86400; // 1 day - 86400
/**
* @var Client
*/
protected $client;
protected PayloadBuilder $payloadBuilder;
protected QueryHandler $queryHandler;
private OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
public function __construct(
Client $client,
PayloadBuilder $payloadBuilder,
protected Dispatcher $eventDispatcher,
private readonly CountriesMap $countriesMap,
private readonly ProspectPhotoPathService $prospectPhotoPathService,
) {
parent::__construct();
$this->client = $client;
$this->payloadBuilder = $payloadBuilder;
$this->queryHandler = app(QueryHandler::class, [
'client' => $this->client,
'logger' => $this->logger,
]);
$this->opportunitySyncStrategyResolver = app(OpportunitySyncStrategyResolver::class, [
'client' => $this->client,
]);
}
public function getDisplayName(): string
{
return 'Salesforce';
}
public function getJobDelay(): int
{
return 1;
}
protected function getOAuthAccount(User $user): ?SocialAccount
{
return $user->getSocialAccount(SocialAccount::PROVIDER_SALESFORCE);
}
public function verifyTaskExists(Activity $activity): bool
{
$crmProviderId = $activity->getCrmProviderId();
$cacheKey = "crm_task_exists:{$this->config->getId()}:$crmProviderId";
return Cache::remember($cacheKey, self::TASK_VERIFICATION_CACHE_TTL, function () use ($activity, $crmProviderId) {
$playbook = $this->getPlaybookFromActivity($activity);
if ($playbook === null) {
$this->logger->warning('[Salesforce] Cannot verify task - no playbook found', [
'activity' => $activity->getId(),
'crm_provider_id' => $crmProviderId,
]);
return false;
}
$objectType = $playbook->getActivityType() === Playbook::ACTIVITY_TYPE_EVENT ? 'Event' : 'Task';
try {
$record = $this->getRecord($objectType, $crmProviderId, ['Id', 'IsDeleted']);
return ! empty($record) && ($record['IsDeleted'] ?? false) === false;
} catch (HttpNotFoundException|HttpBadRequestException) {
$this->logger->info('[Salesforce] Activity record not found during verification', [
'activity' => $activity->getId(),
'object_type' => $objectType,
'crm_provider_id' => $crmProviderId,
'config_id' => $this->config->getId(),
]);
return false;
}
});
}
public function query(string $queryToRun, array $parameters = []): QueryIterator
{
// Due to poorly designed external calls, this method cannot be entirely removed
return $this->queryHandler->query($queryToRun, $parameters);
}
/*=========== Organization Information ===============*/
/**
* Get a list of all the API Versions for the instance.
*
* @throws CrmException
*
* @return mixed
*
*/
public function getApiVersions()
{
$url = $this->config->crm_base_url . '/services/data';
$response = $this->client->get($url);
return json_decode($response->getBody(), true);
}
/**
* Gets the valid recordTypes for a given Salesforce Object via the describe API.
*/
private function getRecordTypes(string $crmObject): array
{
$url = $this->client->getObjectsUrl() . $crmObject . '/describe';
$response = $this->client->get($url);
$jsonResponse = json_decode($response->getBody(), true);
$fields = [];
foreach ($jsonResponse['recordTypeInfos'] as $row) {
$fields[] = ['recordTypeId' => $row['recordTypeId'], 'default' => $row['defaultRecordTypeMapping']];
}
return $fields;
}
/**
* Convert raw field data into a format compatible with CRM APIs.
*/
public function normalizeValue(string $fieldType, string $fieldValue, bool $internal = false): string
{
return ValueNormalizer::normalize($fieldType, $fieldValue, $internal);
}
/**
* @inheritdoc
*/
public function getDefaultFields(string $activityType): array
{
$fields = [];
$defaultFields = ($activityType === Playbook::ACTIVITY_TYPE_TASK)
? FieldDefinitions::defaultTaskFields()
: FieldDefinitions::defaultEventFields();
// 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
{
// Setup the activity field as the default Type.
/** @var Field $activityField */
$activityField = $this->config->fields()->where([
'crm_provider_id' => 'Type',
'object_type' => $activityType,
])->first();
return $activityField;
}
/**
* @inheritdoc
*/
public function getSupportedPlaybookTypes(): array
{
return [Playbook::ACTIVITY_TYPE_TASK, Playbook::ACTIVITY_TYPE_EVENT];
}
protected function getDefaultFollowupLayoutFields(string $activityType): array
{
$fields = [];
$fieldRepo = app(FieldRepository::class);
$fieldFilter = ($activityType === Playbook::ACTIVITY_TYPE_TASK)
? FieldDefinitions::taskFollowupFieldsFilter()
: FieldDefinitions::eventFollowupFieldsFilter();
foreach ($fieldFilter as $eachFilter) {
$field = $fieldRepo->findOneConfigurationFieldByProperties($this->config, $eachFilter);
// 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();
}
/**
* This one is now called only when ImportActivityTypes is triggered or SyncFieldMetadata executed manually
* Regular sync now uses SharedSyncFieldsTrait -> syncSingleObjectType
* Needs to be replaced later on
*/
public function syncField(Field $field): void
{
try {
if (FieldHelper::isCustomField($field)) {
$query = '
SELECT
Id, Metadata, TableEnumOrId
FROM
CustomField
WHERE
DeveloperName = :fieldName
AND
TableEnumOrId = :fieldType
AND
NamespacePrefix = :namespacePrefix';
// We need to constrain the field lookup to the object, in case it's used in multiple places.
$objectType = \in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true)
? 'activity'
: $field->object_type;
$sfFields = $this->queryHandler->metadata($query, [
'fieldName' => substr($field->crm_provider_id, 0, -\strlen('__c')),
'fieldType' => ucfirst($objectType),
// This is used to ensure we only consider the field within the org, not installed packages.
'namespacePrefix' => 'null',
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
// Sync field metadata.
$metadata = $sfField['Metadata'];
$field->description = mb_strimwidth($metadata['description'] ?? '', 0, 191);
$field->label = mb_strimwidth($metadata['label'] ?? '', 0, Field::LABEL_MAX_LENGTH);
$field->type = $this->convertFieldType($metadata['type'], $field->getEntityName());
$field->is_mandatory = ($metadata['required'] === true);
$field->length = $metadata['length'];
$field->default_value = mb_strimwidth(trim($metadata['defaultValue'] ?? '', '"'), 0, 191);
$field->save();
} else {
$query = '
SELECT
Id, DataType, DeveloperName, Label, Length, Description
FROM
FieldDefinition
WHERE
DurableId = :entityName';
$entityName = $field->getEntityName();
$sfFields = $this->queryHandler->metadata($query, [
'entityName' => $entityName,
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
$convertedType = $this->convertFieldType($sfField['DataType'], $entityName);
$label = mb_strimwidth($sfField['Label'], 0, Field::LABEL_MAX_LENGTH);
if ($field->isBusinessType()) {
$label = 'Opportunity Type';
}
$field->description = mb_strimwidth($sfField['Description'], 0, Field::DESCRIPTION_MAX_LENGTH);
$field->label = $label;
$field->type = $convertedType;
$field->length = $sfField['Length'];
$field->save();
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
private function convertFieldType(string $from, ?string $entityName = null): string
{
$converter = new FieldTypeConverter();
return $converter->convert($from, $entityName);
}
/**
* @inheritdoc
*/
public function importPicklistValues(Field $field): array
{
$values = [];
$fieldValues = [];
try {
if (FieldHelper::isCustomField($field)) {
$query = '
SELECT
Id, Metadata, TableEnumOrId
FROM
CustomField
WHERE
DeveloperName = :fieldName
AND
TableEnumOrId = :fieldType
AND
NamespacePrefix = :namespacePrefix';
// We need to constrain the field lookup to the object, in case it's used in multiple places.
$objectType = \in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true) ?
'activity' : $field->object_type;
$sfFields = $this->queryHandler->metadata($query, [
'fieldName' => substr($field->crm_provider_id, 0, -\strlen('__c')),
'fieldType' => ucfirst($objectType),
// This is used to ensure we only consider the field within the org, not installed packages.
'namespacePrefix' => 'null',
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
$valueSet = $sfField['Metadata']['valueSet'];
if ($valueSet['valueSetName'] === null) {
// Local picklist values can be obtained easily.
$picklistValues = $valueSet['valueSetDefinition']['value'];
} else {
// But for some fields, we just get the Global Value Picklist pointer so need to do more work.
$picklistValues = $this->importGlobalValuePicklistValues($valueSet['valueSetName']);
}
// Import all active values.
foreach ($picklistValues as $i => $sfFieldValue) {
// Setup default value.
if ($sfFieldValue['default']) {
$field->update(['default_value' => $sfFieldValue['valueName']]);
}
// This comes through as null if active (lol).
if ($sfFieldValue['isActive'] !== false) {
$values[] = [
'value' => $sfFieldValue['valueName'],
'label' => $sfFieldValue['valueName'],
'sequence' => $i,
'is_default' => $sfFieldValue['default'],
];
}
}
} else {
$objectFields = $this->getObjectFields($field->object_type);
$fieldId = $field->crm_provider_id;
// Only work with our field of interest.
$objectField = array_filter($objectFields, function ($item) use ($fieldId) {
return $item['name'] === $fieldId;
});
$objectField = array_shift($objectField);
if (empty($objectField['picklistValues']) === false) {
foreach ($objectField['picklistValues'] as $i => $sfFieldValue) {
// Skip inactive values.
if ($sfFieldValue['active'] === false) {
continue;
}
// Setup default value.
if ($sfFieldValue['defaultValue']) {
$field->update(['default_value' => $sfFieldValue['value']]);
}
$values[] = [
'value' => $sfFieldValue['value'],
'label' => $sfFieldValue['label'],
'sequence' => $i,
'is_default' => $sfFieldValue['defaultValue'],
];
}
}
}
$fieldsToPurge = $field->values()->get()->pluck('value')->toArray();
foreach ($values as $value) {
$value['value'] = substr($value['value'] ?? '', 0, 255);
$fieldValues[] = $field->values()->updateOrCreate([
'value' => $value['value'],
], $value);
// Remove this value from the ones we are going to purge.
if (($key = array_search($value['value'], $fieldsToPurge, true)) !== false) {
unset($fieldsToPurge[$key]);
}
}
// Delete the old values that are no longer used.
// Get IDs of the values to be deleted
$valuesToDelete = $field->values()->whereIn('value', $fieldsToPurge);
$valuesToDeleteIds = $valuesToDelete->pluck('id');
if (! $valuesToDeleteIds->isEmpty()) {
$recordTypeFieldValuesRepository = app(RecordTypeFieldValuesRepository::class);
$recordTypeFieldValuesRepository->deleteForCrmFieldValueIds($valuesToDeleteIds->toArray());
// Now safely delete from crm_field_values
$valuesToDelete->delete();
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
return $fieldValues;
}
/**
* Gets values from Global Value Picklists.
*/
private function importGlobalValuePicklistValues(string $picklistName): array
{
$query = '
SELECT
Metadata
FROM
GlobalValueSet
WHERE
DeveloperName = :picklistName
LIMIT 1';
try {
$sfValues = $this->queryHandler->metadata($query, [
'picklistName' => $picklistName,
]);
// There is always 1 result at this point.
$sfValue = $sfValues->current();
return $sfValue['Metadata']['customValue'];
} catch (NoResultsException $noResultsException) {
// Nothing returned.
return [];
}
}
/**
* @inheritdoc
*/
public function syncProfileRecordTypes(): void
{
$objectTypes = [
'lead',
'account',
'contact',
'opportunity',
'task',
'event',
];
foreach ($objectTypes as $objectType) {
try {
$crmRecordTypes = $this->getRecordTypes(ucfirst($objectType));
foreach ($crmRecordTypes as $crmRecordType) {
// If the record type is default and not the Master type, set this.
if ($crmRecordType['default'] && $crmRecordType['recordTypeId'] !== '012000000000000AAA') {
$recordType = $this->config->recordTypes()
->where('crm_provider_id', $crmRecordType['recordTypeId'])
->first();
if ($recordType) {
$this->profile->{$objectType . '_record_type_id'} = $recordType->id;
}
}
}
} catch (HttpNotFoundException $exception) {
Log::error('No access to ' . $objectType . ' object, skipping...');
// XXX: should we log this fact somewhere?
continue;
}
}
if ($this->profile->isDirty()) {
$this->profile->save();
}
}
/**
* Gets business processes.
*/
public function importBusinessProcesses(): void
{
$query = '
SELECT
Id, IsActive, Name, TableEnumOrId
FROM
BusinessProcess
WHERE
TableEnumOrId IN (\'Lead\',\'Opportunity\')';
try {
$sfProcesses = $this->queryHandler->query($query);
// Upsert all processes for the team.
foreach ($sfProcesses as $sfProcess) {
/** @var BusinessProcess $businessProcess */
$businessProcess = $this->config->businessProcesses()->updateOrCreate([
'crm_provider_id' => $sfProcess['Id'],
], [
'team_id' => $this->team->id,
'name' => $sfProcess['Name'],
'type' => $sfProcess['TableEnumOrId'] === 'Lead' ? 'lead' : 'opportunity',
'is_selectable' => $sfProcess['IsActive'],
]);
$this->importBusinessProcessStages($businessProcess);
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
/**
* Gets business process stages.
*/
private function importBusinessProcessStages(BusinessProcess $businessProcess): void
{
$query = '
SELECT
Metadata
FROM
BusinessProcess
WHERE
Id = :processId';
try {
$stages = [];
$sfProcessStages = $this->queryHandler->metadata($query, [
'processId' => $businessProcess->crm_provider_id,
]);
// There is always 1 result at this point.
$sfProcessStage = $sfProcessStages->current();
// Upsert all processes for the team.
foreach ($sfProcessStage['Metadata']['values'] as $sfProcessStage) {
$sanitizedName = urldecode($sfProcessStage['valueName']); // Must decode: "%2C" becomes "," etc.
$stage = $businessProcess->crm->stages()
// This MUST match on label because this API doesn't use API Name.
->where('label', $sanitizedName)
->where('type', $businessProcess->type)
->where('is_selectable', 1)
->first();
if ($stage) {
$stages[] = $stage->id;
}
}
$businessProcess->stages()->sync($stages);
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
/**
* Gets record types.
*/
public function importRecordTypes(): void
{
$query = '
SELECT
Id, IsActive, Name, BusinessProcessId, SobjectType
FROM
RecordType';
try {
$sfRecordTypes = $this->queryHandler->query($query);
// Upsert all record types for the process.
foreach ($sfRecordTypes as $sfRecordType) {
$businessProcess = null;
if ($sfRecordType['BusinessProcessId']) {
$businessProcess = $this->config->businessProcesses()
->where('crm_provider_id', $sfRecordType['BusinessProcessId'])
->first();
}
/** @var RecordType $recordType */
$recordType = $this->config->recordTypes()->updateOrCreate([
'crm_provider_id' => $sfRecordType['Id'],
], [
'team_id' => $this->team->id,
'type' => mb_strtolower($sfRecordType['SobjectType']),
'name' => $sfRecordType['Name'],
'is_selectable' => $sfRecordType['IsActive'],
'business_process_id' => $businessProcess->id ?? null,
]);
$this->importRecordTypeFieldValues($recordType);
}
} catch (NoResultsException $noResultsException) {
// Do nothing.
}
}
/**
* Import record type - field value mappings. This only works for standard fields.
*/
private function importRecordTypeFieldValues(RecordType $recordType): void
{
try {
$query = '
SELECT
Metadata
FROM
RecordType
WHERE
Id = :recordTypeId';
$sfFields = $this->queryHandler->metadata($query, [
'recordTypeId' => $recordType->crm_provider_id,
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
// Sync field metadata.
$picklists = $sfField['Metadata']['picklistValues'];
foreach ($picklists as $picklist) {
$field = $this->config->fields()->where([
'type' => Field::TYPE_PICKLIST,
'object_type' => $recordType->type,
'crm_provider_id' => $picklist['picklist'],
])->first();
if ($field) {
$fieldValues = [];
foreach ($picklist['values'] as $value) {
// Must decode: "%2C" becomes "," etc.
$fieldValue = $field->values()
->where('value', urldecode($value['valueName']))
->first();
if ($fieldValue) {
$fieldValues[] = $fieldValue->id;
}
}
$recordType->fieldValues()->sync($fieldValues);
}
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
/**
* @inheritdoc
*/
public function importStages(?array $types = null, ?string $missingStageName = null): ?Stage
{
$params = [];
$missingStage = null;
if ($types === null) {
$types = [Stage::TYPE_LEAD, Stage::TYPE_OPPORTUNITY];
}
foreach ($types as $type) {
if ($type === Stage::TYPE_LEAD) {
$query = '
SELECT
Id, ApiName, MasterLabel, SortOrder
FROM
LeadStatus';
} else {
$query = '
SELECT
Id, ApiName, MasterLabel, IsActive, SortOrder, DefaultProbability
FROM
OpportunityStage';
}
if ($missingStageName) {
$escapedStageName = ValueNormalizer::replaceQueryWithStringLiterals($missingStageName);
$query .= ' WHERE ApiName = :stageName';
$params = [
'stageName' => $escapedStageName,
];
}
try {
$sfStages = $this->queryHandler->query($query, $params);
} catch (NoResultsException $exception) {
$sfStages = [];
}
$missingStage = null;
// Upsert all stages for the team.
foreach ($sfStages as $sfStage) {
$selectable = true;
if (array_key_exists('IsActive', $sfStage)) {
$selectable = $sfStage['IsActive'];
}
$this->restoreAnyTrashedEntity($this->config->stages(), $sfStage['Id']);
$stage = $this->config->stages()->updateOrCreate([
'crm_provider_id' => $sfStage['Id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($sfStage['ApiName'], 0, 50),
'label' => mb_strimwidth($sfStage['MasterLabel'], 0, 191),
'type' => $type,
'sequence' => $sfStage['SortOrder'] ?? 0,
'is_selectable' => $selectable,
'probability' => $sfStage['DefaultProbability'] ?? null,
]);
if ($missingStageName && $missingStageName === $sfStage['ApiName']) {
$missingStage = $stage;
}
}
if ($missingStageName && $missingStage === null) {
// If they requested a stage that still doesn't exist, it must be inactive so lazy create it.
$missingStage = $this->config->stages()->create([
'crm_provider_id' => Uuid::uuid4(),
'team_id' => $this->team->id,
'name' => mb_strimwidth($missingStageName, 0, 50),
'label' => mb_strimwidth($missingStageName, 0, 191),
'type' => $type,
'sequence' => 0,
'is_selectable' => 0,
]);
}
}
return $missingStage;
}
/**
* @inheritdoc
*/
public function syncLeads(Carbon $since, ?Carbon $to = null, ?string $crmProfileId = null): int
{
$syncCount = 0;
$fields = $this->getAllFieldsAsArray('lead');
if (\in_array('Id', $fields, true) === false) {
return $syncCount;
}
$query = '
SELECT ' . rtrim(implode(',', $fields), ',') . '
FROM Lead
WHERE LastModifiedDate > :since
ORDER BY LastModifiedDate ASC';
try {
$sfLeads = $this->queryHandler->query($query, [
'since' => $since->format('Y-m-d\TH:i:s\Z'),
]);
foreach ($sfLeads as $sfLead) {
// Only sync if previously imported.
if ($this->hasLead($sfLead['Id'])) {
$this->importLead($sfLead);
$syncCount++;
}
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
$this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::LEAD);
return $syncCount;
}
/**
* @inheritdoc
*/
public function syncLead(string $crmId): ?Lead
{
$fields = $this->getAllFieldsAsArray('lead');
$sfLead = $this->getRecord('Lead', $crmId, $fields);
return $this->importLead($sfLead);
}
private function importLead($crmData): ?Lead
{
/** @var ?Stage $stage */
$stage = null;
if (isset($crmData['Status'])) {
// Get the current stage.
$stage = $this->config
->stages()
->where('name', $crmData['Status'])
->where('type', Stage::TYPE_LEAD)
->first();
if ($stage === null) {
// Import it.
$stage = $this->importStages([Stage::TYPE_LEAD], $crmData['Status']);
}
}
// If we have no way of importing this, just return null :(
if ($stage === null) {
return null;
}
$countryCode = $crmData['CountryCode'] ?? null;
// Salesforce allows custom "countries" to be created. Disregard these.
if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {
$countryCode = null;
}
// If we have no country code, try to parse it from the country name.
if ($countryCode === null && empty($crmData['Country']) !== false) {
$countryCode = $this->convertCountryNameToCode($crmData['Country']);
}
// Trim to our width and attempt to parse it.
$number = mb_strimwidth($crmData['Phone'] ?? '', 0, 25);
$parsedNumber = parsePhoneNumber($countryCode, $number);
$mobilePhone = null;
if (empty($crmData['MobilePhone']) === false) {
// Trim to our width and attempt to parse it.
$number = mb_strimwidth($crmData['MobilePhone'], 0, 25);
$mobilePhone = phone_e164($countryCode, $number);
}
$convertedDate = null;
$convertedAccount = null;
$convertedOpportunity = null;
$convertedContact = null;
if ($crmData['IsConverted'] == 'true') {
$convertedDate = $crmData['ConvertedDate'];
if (empty($crmData['ConvertedAccountId']) === false) {
$convertedAccount = $this->config
->accounts()
->where('crm_provider_id', $crmData['ConvertedAccountId'])
->first();
if ($convertedAccount === null) {
try {
$convertedAccount = $this->syncAccount($crmData['ConvertedAccountId']);
} catch (HttpNotFoundException $exception) {
// Probably the user has no permissions to access the converted data.
}
}
}
if (empty($crmData['ConvertedOpportunityId']) === false) {
$convertedOpportunity = $this->config
->opportunities()
->where('crm_provider_id', $crmData['ConvertedOpportunityId'])
->first();
if ($convertedOpportunity === null) {
try {
$convertedOpportunity = $this->syncOpportunity($crmData['ConvertedOpportunityId']);
} catch (HttpNotFoundException $exception) {
// Probably the user has no permissions to access the converted data.
}
}
}
if (empty($crmData['ConvertedContactId']) === false) {
$convertedContact = $this->team
->crm
->contacts()
->where('crm_provider_id', $crmData['ConvertedContactId'])
->first();
if ($convertedContact === null) {
try {
$convertedContact = $this->syncContact($crmData['ConvertedContactId']);
} catch (HttpNotFoundException $exception) {
// Probably the user has no permissions to access the converted data.
}
}
}
}
if (empty($crmData['Company'])) {
$company = 'Unknown';
} else {
$company = mb_strimwidth($crmData['Company'], 0, 191);
}
$domain = null;
if (empty($crmData['Website']) === false) {
$domain = mb_strimwidth($crmData['Website'], 0, 191);
$domain = StringUtil::resolveDomain($domain);
}
$createdDate = null;
if (empty($crmData['CreatedDate']) === false) {
$createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');
}
$profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);
$data = [
'team_id' => $this->team->id,
'user_id' => $profile?->user_id,
'owner_id' => $crmData['OwnerId'] ?? '',
'company' => $company,
'domain' => $domain,
'name' => $crmData['Name'] ? mb_strimwidth($crmData['Name'], 0, 191) : '',
'title' => $crmData['Title'] ? mb_strimwidth($crmData['Title'], 0, 128) : null,
'email' => $crmData['Email'] ? mb_strimwidth($crmData['Email'], 0, 80) : null,
'phone' => $parsedNumber['phone'],
'ext' => $parsedNumber['ext'] ?? null,
'mobile_phone' => $mobilePhone,
'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(
crmConfiguration: $this->config,
crmProviderId: $crmData['Id'],
modelType: Lead::class,
fileName: $crmData['Id'],
avatarText: $crmData['Name']
),
'stage_id' => $stage->id,
'record_type_id' => null,
'converted_at' => $convertedDate,
'converted_account_id' => $convertedAccount->id ?? null,
'converted_opportunity_id' => $convertedOpportunity->id ?? null,
'converted_contact_id' => $convertedContact->id ?? null,
'country_code' => $countryCode,
'remotely_created_at' => $createdDate,
];
$this->restoreAnyTrashedEntity($this->config->leads(), $crmData['Id']);
/** @var Lead $lead */
$lead = $this->config->leads()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);
if ($lead->wasChanged('converted_at') && $lead->getConvertedAt() !== null) {
$this->eventDispatcher->dispatch(new LeadConverted($lead));
}
$this->handleObjectDeletion($lead, $crmData);
if ($lead->trashed()) {
return null;
}
return $lead;
}
/**
* @inheritdoc
*/
public function syncAccounts(Carbon $since, ?Carbon $to = null): int
{
$syncCount = 0;
$fields = $this->getAllFieldsAsArray('account');
if (\in_array('Id', $fields, true) === false) {
return $syncCount;
}
$query = '
SELECT ' . rtrim(implode(',', $fields), ',') . '
FROM Account
WHERE LastModifiedDate > :since
ORDER BY LastModifiedDate ASC';
try {
$sfAccounts = $this->queryHandler->query($query, [
'since' => $since->format('Y-m-d\TH:i:s\Z'),
]);
foreach ($sfAccounts as $sfAccount) {
// Only sync if previously imported.
if ($this->hasAccount($sfAccount['Id'])) {
$this->importAccount($sfAccount);
$syncCount++;
}
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
$this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::ACCOUNT);
return $syncCount;
}
/**
* @inheritdoc
*/
public function syncAccount(string $crmId): ?Account
{
$fields = $this->getAllFieldsAsArray('account');
if (! in_array('Id', $fields, true)) {
$this->logger->info('[Salesforce] Sync account cancelled. Fields are not available.', [
'crmId' => $crmId,
'userId' => $this->profile->getUserId(),
]);
return null;
}
$sfAccount = $this->getRecord('Account', $crmId, $fields);
return $this->importAccount($sfAccount);
}
private function importAccount($crmData): ?Account
{
if (! empty($crmData['IsDeleted'])) {
$this->handleEntityDeletionByProviderId($this->config->accounts(), $crmData);
return null;
}
$countryCode = $crmData['BillingCountryCode'] ?? $crmData['ShippingCountryCode'] ?? null;
// Salesforce allows custom "countries" to be created. Disregard these.
if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {
$countryCode = null;
}
// If we have no country code, try to parse it from the country names.
if ($countryCode === null && empty($crmData['BillingCountry']) === false) {
$countryCode = $this->convertCountryNameToCode($crmData['BillingCountry']);
}
if ($countryCode === null && empty($crmData['ShippingCountry']) === false) {
$countryCode = $this->convertCountryNameToCode($crmData['ShippingCountry']);
}
if (empty($crmData['Phone']) === false) {
// Trim to our width and attempt to parse it.
$number = mb_strimwidth($crmData['Phone'], 0, 25);
$parsedNumber = parsePhoneNumber($countryCode, $number);
} else {
$parsedNumber = [];
}
$industry = null;
if (empty($crmData['Industry']) === false) {
$industry = mb_strimwidth($crmData['Industry'], 0, 40);
}
$domain = null;
if (empty($crmData['Website']) === false) {
$domain = mb_strimwidth($crmData['Website'], 0, 191);
$domain = StringUtil::resolveDomain($domain);
}
$createdDate = null;
if (empty($crmData['CreatedDate']) === false) {
$createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');
}
$profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);
$data = [
'team_id' => $this->team->id,
'user_id' => $profile?->user_id,
'owner_id' => $crmData['OwnerId'],
'name' => mb_strimwidth($crmData['Name'], 0, 191),
'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(
crmConfiguration: $this->config,
crmProviderId: $crmData['Id'],
modelType: Account::class,
fileName: $crmData['Id'],
avatarText: $crmData['Name']
),
'industry' => $industry,
'domain' => $domain,
'phone' => $parsedNumber['phone'] ?? null,
'ext' => $parsedNumber['ext'] ?? null,
'country_code' => $countryCode,
'remotely_created_at' => $createdDate,
];
$this->restoreAnyTrashedEntity($this->config->accounts(), $crmData['Id']);
/** @var Account $account */
$account = $this->config->accounts()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);
$this->handleObjectDeletion($account, $crmData);
return $account->trashed() ? null : $account;
}
/**
* @inheritdoc
*/
public function syncOpportunities(array $parameters, ?string $strategy = null): int
{
$strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);
$syncCount = 0;
$logParams = $parameters;
$parameters['profile'] = $this->profile;
$logParams['user'] = $this->profile->getUserId();
if (count($strategies) > 1) {
$this->logger->warning('[' . $this->getDisplayName() . '] Multiple sync strategies used', [
'teamId' => $this->team->getUuid(),
'params' => $logParams,
'strategies_count' => count($strategies),
]);
}
foreach ($strategies as $syncStrategy) {
$name = $syncStrategy->getStrategyName();
try {
$sfOpportunities = $syncStrategy->fetchOpportunities($parameters);
$totalRecords = $sfOpportunities->count();
foreach ($sfOpportunities as $sfOpportunity) {
$this->importOpportunity($sfOpportunity);
$syncCount++;
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
$this->logger->warning('[' . $this->getDisplayName() . '] No opportunities found', [
'teamId' => $this->team->getUuid(),
'name' => $name,
'params' => $logParams,
'reason' => $noResultsException->getMessage(),
]);
} catch (CrmException $crmException) {
// Nothing to sync.
$this->logger->warning('[' . $this->getDisplayName() . '] Opportunity sync failed', [
'teamId' => $this->team->getUuid(),
'name' => $name,
'params' => $logParams,
'reason' => $crmException->getMessage(),
]);
}
}
$this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::OPPORTUNITY, ['params' => $logParams]);
// debug to see how if count of opportunities reaches 1000
if ($syncCount >= 1000) {
$this->logger->info(
'[' . $this->getDisplayName() . '] Sync Opportunities - count warning',
[
'team_id' => $this->team->getId(),
'params' => $logParams,
'count' => $syncCount,
'strategies_count' => count($strategies),
'total_records' => $totalRecords ?? null,
]
);
}
return $syncCount;
}
/**
* @inheritdoc
*/
public function syncOpportunity(string $crmId): ?Opportunity
{
$strategy = $this->opportunitySyncStrategyResolver->resolve(
$this->config,
OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY
);
$parameters = [
'profile' => $this->profile,
'crm_id' => $crmId,
];
try {
$sfOpportunity = $strategy->fetchOpportunities($parameters);
} catch (HttpNotFoundException $e) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [
'teamId' => $this->team->id_string,
'crmId' => $crmId,
]);
return null;
} catch (CrmException $crmException) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity sync failed', [
'teamId' => $this->team->id_string,
'crmId' => $crmId,
'exception' => $crmException->getMessage(),
]);
return null;
}
if ($sfOpportunity instanceof ArrayIterator) {
return $this->importOpportunity($sfOpportunity->getItems());
}
return $this->importOpportunity($sfOpportunity);
}
/**
* @throws HttpNotFoundException
*/
private function importOpportunity($crmData): ?Opportunity
{
$profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);
$account = null;
if (empty($crmData['AccountId']) === false) {
/** @var ?Account $account */
$account = $this->config->accounts()
->where('crm_provider_id', (string) $crmData['AccountId'])
->first();
if ($account === null) {
$account = $this->syncAccount($crmData['AccountId']);
}
}
$userId = $profile?->getUserId() ?? $account?->getUserId();
if ($userId === null) {
$this->logger->error('[Salesforce] | Skip import, no user_id found', [
'id' => $crmData['Id'],
]);
return null;
}
/** @var ?Stage $stage */
$stage = null;
if (isset($crmData['StageName'])...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85916
|
2948
|
5
|
2026-05-28T13:28:51.241328+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974931241_m1.jpg...
|
PhpStorm
|
faVsco.js – Service.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
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
Sync Changes
Hide This Notification
Code changed:
Hide
12
246
3
21
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Services\Crm\Salesforce;
use Carbon\Carbon;
use Exception;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Events\Dispatcher;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Jiminny\Component\Country\CountriesMap;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Contracts\Repositories\TeamRepository;
use Jiminny\Contracts\Services\Crm\FetchRelatedActivityInterface;
use Jiminny\Contracts\Services\Crm\ImportsBusinessProcessesInterface;
use Jiminny\Contracts\Services\Crm\LayoutManagementInterface;
use Jiminny\Contracts\Services\Crm\MatchCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\Provider\SalesforceBatchSyncInterface;
use Jiminny\Contracts\Services\Crm\Provider\SalesforceInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityLookupInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityManipulationInterface;
use Jiminny\Contracts\Services\Crm\RemoteNoteEntityManipulationInterface;
use Jiminny\Contracts\Services\Crm\SearchTaskInterface;
use Jiminny\Contracts\Services\Crm\SendSummaryToCrmInterface;
use Jiminny\Contracts\Services\Crm\SettingsInterface;
use Jiminny\Contracts\Services\Crm\SupportsObjectTypeParseInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmProfileRecordTypesInterface;
use Jiminny\Contracts\Services\Crm\VerifyTaskExistsInterface;
use Jiminny\Enums\CrmObject;
use Jiminny\Events\Activities\Crm\LeadConverted;
use Jiminny\Exceptions\CrmException;
use Jiminny\Exceptions\HttpBadRequestException;
use Jiminny\Exceptions\HttpNotFoundException;
use Jiminny\Exceptions\NoResultsException;
use Jiminny\Exceptions\ServiceUnavailableException;
use Jiminny\Jobs\Crm\NoteObject;
use Jiminny\Jobs\Crm\MatchActivitiesToNewOpportunity;
use Jiminny\Models\Account;
use Jiminny\Models\Activity;
use Jiminny\Models\Calendar\CalendarEvent;
use Jiminny\Models\Contact;
use Jiminny\Models\Contracts\ActivityContract;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Models\Crm\Configuration;
use Jiminny\Models\Crm\ContactRole;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\Profile;
use Jiminny\Models\Crm\RecordType;
use Jiminny\Models\Lead;
use Jiminny\Models\Opportunity;
use Jiminny\Models\Playbook;
use Jiminny\Models\SocialAccount;
use Jiminny\Models\Stage;
use Jiminny\Models\TeamSettings;
use Jiminny\Models\User;
use Jiminny\Repositories\Crm\ContactRoleRepository;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\Crm\ProfileRepository;
use Jiminny\Repositories\Crm\RecordTypeFieldValuesRepository;
use Jiminny\Services\Avatar\ProspectPhotoPathService;
use Jiminny\Services\Crm\BaseService;
use Jiminny\Services\Crm\Helpers\ArrayIterator;
use Jiminny\Services\Crm\MatchDomainByEmailInterface;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Services\Crm\ResolveCompanyNameByEmailTrait;
use Jiminny\Services\Crm\Salesforce\Fields\FieldHelper;
use Jiminny\Services\Crm\Salesforce\Fields\FieldTypeConverter;
use Jiminny\Services\Crm\Salesforce\Fields\ValueNormalizer;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\FollowupActivityTrait;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\LogActivityTrait;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\RecordManipulationsTrait;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\SyncFieldsTrait;
use Jiminny\Utils\CurrencyFormatter;
use Jiminny\Utils\StringUtil;
use Ramsey\Uuid\Uuid;
use Sentry\Laravel\Facade as Sentry;
class Service extends BaseService implements
SalesforceInterface,
SalesforceBatchSyncInterface,
SyncCrmEntitiesInterface,
SyncCrmProfileRecordTypesInterface,
ImportsBusinessProcessesInterface,
RemoteEntityManipulationInterface,
FetchRelatedActivityInterface,
SendSummaryToCrmInterface,
MatchDomainByEmailInterface,
SearchTaskInterface,
LayoutManagementInterface,
SettingsInterface,
MatchCrmEntitiesInterface,
RemoteEntityLookupInterface,
SupportsObjectTypeParseInterface,
RemoteNoteEntityManipulationInterface,
VerifyTaskExistsInterface
{
use ResolveCompanyNameByEmailTrait;
use SyncFieldsTrait;
use DeleteObjectsTrait;
use RecordManipulationsTrait;
use ServiceTraits\BatchSyncTrait;
use FollowupActivityTrait;
use LogActivityTrait;
/**
* Note Body Limit for the Old Note-Taking Tool
*
* @var int
*/
private const int CLASSIC_NOTE_MAX_LENGTH = 32000;
/**
* Note Content Limit for the New Notes
*
* @var int
*/
private const int ENHANCED_NOTE_MAX_LENGTH = 50000000;
private const string INSTALLED_PACKAGE_ID = '033Tw0000007bKbIAI';
private const int CACHE_TTL = 600;
private const int TASK_VERIFICATION_CACHE_TTL = 86400; // 1 day - 86400
/**
* @var Client
*/
protected $client;
protected PayloadBuilder $payloadBuilder;
protected QueryHandler $queryHandler;
private OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
public function __construct(
Client $client,
PayloadBuilder $payloadBuilder,
protected Dispatcher $eventDispatcher,
private readonly CountriesMap $countriesMap,
private readonly ProspectPhotoPathService $prospectPhotoPathService,
) {
parent::__construct();
$this->client = $client;
$this->payloadBuilder = $payloadBuilder;
$this->queryHandler = app(QueryHandler::class, [
'client' => $this->client,
'logger' => $this->logger,
]);
$this->opportunitySyncStrategyResolver = app(OpportunitySyncStrategyResolver::class, [
'client' => $this->client,
]);
}
public function getDisplayName(): string
{
return 'Salesforce';
}
public function getJobDelay(): int
{
return 1;
}
protected function getOAuthAccount(User $user): ?SocialAccount
{
return $user->getSocialAccount(SocialAccount::PROVIDER_SALESFORCE);
}
public function verifyTaskExists(Activity $activity): bool
{
$crmProviderId = $activity->getCrmProviderId();
$cacheKey = "crm_task_exists:{$this->config->getId()}:$crmProviderId";
return Cache::remember($cacheKey, self::TASK_VERIFICATION_CACHE_TTL, function () use ($activity, $crmProviderId) {
$playbook = $this->getPlaybookFromActivity($activity);
if ($playbook === null) {
$this->logger->warning('[Salesforce] Cannot verify task - no playbook found', [
'activity' => $activity->getId(),
'crm_provider_id' => $crmProviderId,
]);
return false;
}
$objectType = $playbook->getActivityType() === Playbook::ACTIVITY_TYPE_EVENT ? 'Event' : 'Task';
try {
$record = $this->getRecord($objectType, $crmProviderId, ['Id', 'IsDeleted']);
return ! empty($record) && ($record['IsDeleted'] ?? false) === false;
} catch (HttpNotFoundException|HttpBadRequestException) {
$this->logger->info('[Salesforce] Activity record not found during verification', [
'activity' => $activity->getId(),
'object_type' => $objectType,
'crm_provider_id' => $crmProviderId,
'config_id' => $this->config->getId(),
]);
return false;
}
});
}
public function query(string $queryToRun, array $parameters = []): QueryIterator
{
// Due to poorly designed external calls, this method cannot be entirely removed
return $this->queryHandler->query($queryToRun, $parameters);
}
/*=========== Organization Information ===============*/
/**
* Get a list of all the API Versions for the instance.
*
* @throws CrmException
*
* @return mixed
*
*/
public function getApiVersions()
{
$url = $this->config->crm_base_url . '/services/data';
$response = $this->client->get($url);
return json_decode($response->getBody(), true);
}
/**
* Gets the valid recordTypes for a given Salesforce Object via the describe API.
*/
private function getRecordTypes(string $crmObject): array
{
$url = $this->client->getObjectsUrl() . $crmObject . '/describe';
$response = $this->client->get($url);
$jsonResponse = json_decode($response->getBody(), true);
$fields = [];
foreach ($jsonResponse['recordTypeInfos'] as $row) {
$fields[] = ['recordTypeId' => $row['recordTypeId'], 'default' => $row['defaultRecordTypeMapping']];
}
return $fields;
}
/**
* Convert raw field data into a format compatible with CRM APIs.
*/
public function normalizeValue(string $fieldType, string $fieldValue, bool $internal = false): string
{
return ValueNormalizer::normalize($fieldType, $fieldValue, $internal);
}
/**
* @inheritdoc
*/
public function getDefaultFields(string $activityType): array
{
$fields = [];
$defaultFields = ($activityType === Playbook::ACTIVITY_TYPE_TASK)
? FieldDefinitions::defaultTaskFields()
: FieldDefinitions::defaultEventFields();
// 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
{
// Setup the activity field as the default Type.
/** @var Field $activityField */
$activityField = $this->config->fields()->where([
'crm_provider_id' => 'Type',
'object_type' => $activityType,
])->first();
return $activityField;
}
/**
* @inheritdoc
*/
public function getSupportedPlaybookTypes(): array
{
return [Playbook::ACTIVITY_TYPE_TASK, Playbook::ACTIVITY_TYPE_EVENT];
}
protected function getDefaultFollowupLayoutFields(string $activityType): array
{
$fields = [];
$fieldRepo = app(FieldRepository::class);
$fieldFilter = ($activityType === Playbook::ACTIVITY_TYPE_TASK)
? FieldDefinitions::taskFollowupFieldsFilter()
: FieldDefinitions::eventFollowupFieldsFilter();
foreach ($fieldFilter as $eachFilter) {
$field = $fieldRepo->findOneConfigurationFieldByProperties($this->config, $eachFilter);
// 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();
}
/**
* This one is now called only when ImportActivityTypes is triggered or SyncFieldMetadata executed manually
* Regular sync now uses SharedSyncFieldsTrait -> syncSingleObjectType
* Needs to be replaced later on
*/
public function syncField(Field $field): void
{
try {
if (FieldHelper::isCustomField($field)) {
$query = '
SELECT
Id, Metadata, TableEnumOrId
FROM
CustomField
WHERE
DeveloperName = :fieldName
AND
TableEnumOrId = :fieldType
AND
NamespacePrefix = :namespacePrefix';
// We need to constrain the field lookup to the object, in case it's used in multiple places.
$objectType = \in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true)
? 'activity'
: $field->object_type;
$sfFields = $this->queryHandler->metadata($query, [
'fieldName' => substr($field->crm_provider_id, 0, -\strlen('__c')),
'fieldType' => ucfirst($objectType),
// This is used to ensure we only consider the field within the org, not installed packages.
'namespacePrefix' => 'null',
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
// Sync field metadata.
$metadata = $sfField['Metadata'];
$field->description = mb_strimwidth($metadata['description'] ?? '', 0, 191);
$field->label = mb_strimwidth($metadata['label'] ?? '', 0, Field::LABEL_MAX_LENGTH);
$field->type = $this->convertFieldType($metadata['type'], $field->getEntityName());
$field->is_mandatory = ($metadata['required'] === true);
$field->length = $metadata['length'];
$field->default_value = mb_strimwidth(trim($metadata['defaultValue'] ?? '', '"'), 0, 191);
$field->save();
} else {
$query = '
SELECT
Id, DataType, DeveloperName, Label, Length, Description
FROM
FieldDefinition
WHERE
DurableId = :entityName';
$entityName = $field->getEntityName();
$sfFields = $this->queryHandler->metadata($query, [
'entityName' => $entityName,
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
$convertedType = $this->convertFieldType($sfField['DataType'], $entityName);
$label = mb_strimwidth($sfField['Label'], 0, Field::LABEL_MAX_LENGTH);
if ($field->isBusinessType()) {
$label = 'Opportunity Type';
}
$field->description = mb_strimwidth($sfField['Description'], 0, Field::DESCRIPTION_MAX_LENGTH);
$field->label = $label;
$field->type = $convertedType;
$field->length = $sfField['Length'];
$field->save();
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
private function convertFieldType(string $from, ?string $entityName = null): string
{
$converter = new FieldTypeConverter();
return $converter->convert($from, $entityName);
}
/**
* @inheritdoc
*/
public function importPicklistValues(Field $field): array
{
$values = [];
$fieldValues = [];
try {
if (FieldHelper::isCustomField($field)) {
$query = '
SELECT
Id, Metadata, TableEnumOrId
FROM
CustomField
WHERE
DeveloperName = :fieldName
AND
TableEnumOrId = :fieldType
AND
NamespacePrefix = :namespacePrefix';
// We need to constrain the field lookup to the object, in case it's used in multiple places.
$objectType = \in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true) ?
'activity' : $field->object_type;
$sfFields = $this->queryHandler->metadata($query, [
'fieldName' => substr($field->crm_provider_id, 0, -\strlen('__c')),
'fieldType' => ucfirst($objectType),
// This is used to ensure we only consider the field within the org, not installed packages.
'namespacePrefix' => 'null',
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
$valueSet = $sfField['Metadata']['valueSet'];
if ($valueSet['valueSetName'] === null) {
// Local picklist values can be obtained easily.
$picklistValues = $valueSet['valueSetDefinition']['value'];
} else {
// But for some fields, we just get the Global Value Picklist pointer so need to do more work.
$picklistValues = $this->importGlobalValuePicklistValues($valueSet['valueSetName']);
}
// Import all active values.
foreach ($picklistValues as $i => $sfFieldValue) {
// Setup default value.
if ($sfFieldValue['default']) {
$field->update(['default_value' => $sfFieldValue['valueName']]);
}
// This comes through as null if active (lol).
if ($sfFieldValue['isActive'] !== false) {
$values[] = [
'value' => $sfFieldValue['valueName'],
'label' => $sfFieldValue['valueName'],
'sequence' => $i,
'is_default' => $sfFieldValue['default'],
];
}
}
} else {
$objectFields = $this->getObjectFields($field->object_type);
$fieldId = $field->crm_provider_id;
// Only work with our field of interest.
$objectField = array_filter($objectFields, function ($item) use ($fieldId) {
return $item['name'] === $fieldId;
});
$objectField = array_shift($objectField);
if (empty($objectField['picklistValues']) === false) {
foreach ($objectField['picklistValues'] as $i => $sfFieldValue) {
// Skip inactive values.
if ($sfFieldValue['active'] === false) {
continue;
}
// Setup default value.
if ($sfFieldValue['defaultValue']) {
$field->update(['default_value' => $sfFieldValue['value']]);
}
$values[] = [
'value' => $sfFieldValue['value'],
'label' => $sfFieldValue['label'],
'sequence' => $i,
'is_default' => $sfFieldValue['defaultValue'],
];
}
}
}
$fieldsToPurge = $field->values()->get()->pluck('value')->toArray();
foreach ($values as $value) {
$value['value'] = substr($value['value'] ?? '', 0, 255);
$fieldValues[] = $field->values()->updateOrCreate([
'value' => $value['value'],
], $value);
// Remove this value from the ones we are going to purge.
if (($key = array_search($value['value'], $fieldsToPurge, true)) !== false) {
unset($fieldsToPurge[$key]);
}
}
// Delete the old values that are no longer used.
// Get IDs of the values to be deleted
$valuesToDelete = $field->values()->whereIn('value', $fieldsToPurge);
$valuesToDeleteIds = $valuesToDelete->pluck('id');
if (! $valuesToDeleteIds->isEmpty()) {
$recordTypeFieldValuesRepository = app(RecordTypeFieldValuesRepository::class);
$recordTypeFieldValuesRepository->deleteForCrmFieldValueIds($valuesToDeleteIds->toArray());
// Now safely delete from crm_field_values
$valuesToDelete->delete();
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
return $fieldValues;
}
/**
* Gets values from Global Value Picklists.
*/
private function importGlobalValuePicklistValues(string $picklistName): array
{
$query = '
SELECT
Metadata
FROM
GlobalValueSet
WHERE
DeveloperName = :picklistName
LIMIT 1';
try {
$sfValues = $this->queryHandler->metadata($query, [
'picklistName' => $picklistName,
]);
// There is always 1 result at this point.
$sfValue = $sfValues->current();
return $sfValue['Metadata']['customValue'];
} catch (NoResultsException $noResultsException) {
// Nothing returned.
return [];
}
}
/**
* @inheritdoc
*/
public function syncProfileRecordTypes(): void
{
$objectTypes = [
'lead',
'account',
'contact',
'opportunity',
'task',
'event',
];
foreach ($objectTypes as $objectType) {
try {
$crmRecordTypes = $this->getRecordTypes(ucfirst($objectType));
foreach ($crmRecordTypes as $crmRecordType) {
// If the record type is default and not the Master type, set this.
if ($crmRecordType['default'] && $crmRecordType['recordTypeId'] !== '012000000000000AAA') {
$recordType = $this->config->recordTypes()
->where('crm_provider_id', $crmRecordType['recordTypeId'])
->first();
if ($recordType) {
$this->profile->{$objectType . '_record_type_id'} = $recordType->id;
}
}
}
} catch (HttpNotFoundException $exception) {
Log::error('No access to ' . $objectType . ' object, skipping...');
// XXX: should we log this fact somewhere?
continue;
}
}
if ($this->profile->isDirty()) {
$this->profile->save();
}
}
/**
* Gets business processes.
*/
public function importBusinessProcesses(): void
{
$query = '
SELECT
Id, IsActive, Name, TableEnumOrId
FROM
BusinessProcess
WHERE
TableEnumOrId IN (\'Lead\',\'Opportunity\')';
try {
$sfProcesses = $this->queryHandler->query($query);
// Upsert all processes for the team.
foreach ($sfProcesses as $sfProcess) {
/** @var BusinessProcess $businessProcess */
$businessProcess = $this->config->businessProcesses()->updateOrCreate([
'crm_provider_id' => $sfProcess['Id'],
], [
'team_id' => $this->team->id,
'name' => $sfProcess['Name'],
'type' => $sfProcess['TableEnumOrId'] === 'Lead' ? 'lead' : 'opportunity',
'is_selectable' => $sfProcess['IsActive'],
]);
$this->importBusinessProcessStages($businessProcess);
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
/**
* Gets business process stages.
*/
private function importBusinessProcessStages(BusinessProcess $businessProcess): void
{
$query = '
SELECT
Metadata
FROM
BusinessProcess
WHERE
Id = :processId';
try {
$stages = [];
$sfProcessStages = $this->queryHandler->metadata($query, [
'processId' => $businessProcess->crm_provider_id,
]);
// There is always 1 result at this point.
$sfProcessStage = $sfProcessStages->current();
// Upsert all processes for the team.
foreach ($sfProcessStage['Metadata']['values'] as $sfProcessStage) {
$sanitizedName = urldecode($sfProcessStage['valueName']); // Must decode: "%2C" becomes "," etc.
$stage = $businessProcess->crm->stages()
// This MUST match on label because this API doesn't use API Name.
->where('label', $sanitizedName)
->where('type', $businessProcess->type)
->where('is_selectable', 1)
->first();
if ($stage) {
$stages[] = $stage->id;
}
}
$businessProcess->stages()->sync($stages);
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
/**
* Gets record types.
*/
public function importRecordTypes(): void
{
$query = '
SELECT
Id, IsActive, Name, BusinessProcessId, SobjectType
FROM
RecordType';
try {
$sfRecordTypes = $this->queryHandler->query($query);
// Upsert all record types for the process.
foreach ($sfRecordTypes as $sfRecordType) {
$businessProcess = null;
if ($sfRecordType['BusinessProcessId']) {
$businessProcess = $this->config->businessProcesses()
->where('crm_provider_id', $sfRecordType['BusinessProcessId'])
->first();
}
/** @var RecordType $recordType */
$recordType = $this->config->recordTypes()->updateOrCreate([
'crm_provider_id' => $sfRecordType['Id'],
], [
'team_id' => $this->team->id,
'type' => mb_strtolower($sfRecordType['SobjectType']),
'name' => $sfRecordType['Name'],
'is_selectable' => $sfRecordType['IsActive'],
'business_process_id' => $businessProcess->id ?? null,
]);
$this->importRecordTypeFieldValues($recordType);
}
} catch (NoResultsException $noResultsException) {
// Do nothing.
}
}
/**
* Import record type - field value mappings. This only works for standard fields.
*/
private function importRecordTypeFieldValues(RecordType $recordType): void
{
try {
$query = '
SELECT
Metadata
FROM
RecordType
WHERE
Id = :recordTypeId';
$sfFields = $this->queryHandler->metadata($query, [
'recordTypeId' => $recordType->crm_provider_id,
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
// Sync field metadata.
$picklists = $sfField['Metadata']['picklistValues'];
foreach ($picklists as $picklist) {
$field = $this->config->fields()->where([
'type' => Field::TYPE_PICKLIST,
'object_type' => $recordType->type,
'crm_provider_id' => $picklist['picklist'],
])->first();
if ($field) {
$fieldValues = [];
foreach ($picklist['values'] as $value) {
// Must decode: "%2C" becomes "," etc.
$fieldValue = $field->values()
->where('value', urldecode($value['valueName']))
->first();
if ($fieldValue) {
$fieldValues[] = $fieldValue->id;
}
}
$recordType->fieldValues()->sync($fieldValues);
}
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
/**
* @inheritdoc
*/
public function importStages(?array $types = null, ?string $missingStageName = null): ?Stage
{
$params = [];
$missingStage = null;
if ($types === null) {
$types = [Stage::TYPE_LEAD, Stage::TYPE_OPPORTUNITY];
}
foreach ($types as $type) {
if ($type === Stage::TYPE_LEAD) {
$query = '
SELECT
Id, ApiName, MasterLabel, SortOrder
FROM
LeadStatus';
} else {
$query = '
SELECT
Id, ApiName, MasterLabel, IsActive, SortOrder, DefaultProbability
FROM
OpportunityStage';
}
if ($missingStageName) {
$escapedStageName = ValueNormalizer::replaceQueryWithStringLiterals($missingStageName);
$query .= ' WHERE ApiName = :stageName';
$params = [
'stageName' => $escapedStageName,
];
}
try {
$sfStages = $this->queryHandler->query($query, $params);
} catch (NoResultsException $exception) {
$sfStages = [];
}
$missingStage = null;
// Upsert all stages for the team.
foreach ($sfStages as $sfStage) {
$selectable = true;
if (array_key_exists('IsActive', $sfStage)) {
$selectable = $sfStage['IsActive'];
}
$this->restoreAnyTrashedEntity($this->config->stages(), $sfStage['Id']);
$stage = $this->config->stages()->updateOrCreate([
'crm_provider_id' => $sfStage['Id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($sfStage['ApiName'], 0, 50),
'label' => mb_strimwidth($sfStage['MasterLabel'], 0, 191),
'type' => $type,
'sequence' => $sfStage['SortOrder'] ?? 0,
'is_selectable' => $selectable,
'probability' => $sfStage['DefaultProbability'] ?? null,
]);
if ($missingStageName && $missingStageName === $sfStage['ApiName']) {
$missingStage = $stage;
}
}
if ($missingStageName && $missingStage === null) {
// If they requested a stage that still doesn't exist, it must be inactive so lazy create it.
$missingStage = $this->config->stages()->create([
'crm_provider_id' => Uuid::uuid4(),
'team_id' => $this->team->id,
'name' => mb_strimwidth($missingStageName, 0, 50),
'label' => mb_strimwidth($missingStageName, 0, 191),
'type' => $type,
'sequence' => 0,
'is_selectable' => 0,
]);
}
}
return $missingStage;
}
/**
* @inheritdoc
*/
public function syncLeads(Carbon $since, ?Carbon $to = null, ?string $crmProfileId = null): int
{
$syncCount = 0;
$fields = $this->getAllFieldsAsArray('lead');
if (\in_array('Id', $fields, true) === false) {
return $syncCount;
}
$query = '
SELECT ' . rtrim(implode(',', $fields), ',') . '
FROM Lead
WHERE LastModifiedDate > :since
ORDER BY LastModifiedDate ASC';
try {
$sfLeads = $this->queryHandler->query($query, [
'since' => $since->format('Y-m-d\TH:i:s\Z'),
]);
foreach ($sfLeads as $sfLead) {
// Only sync if previously imported.
if ($this->hasLead($sfLead['Id'])) {
$this->importLead($sfLead);
$syncCount++;
}
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
$this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::LEAD);
return $syncCount;
}
/**
* @inheritdoc
*/
public function syncLead(string $crmId): ?Lead
{
$fields = $this->getAllFieldsAsArray('lead');
$sfLead = $this->getRecord('Lead', $crmId, $fields);
return $this->importLead($sfLead);
}
private function importLead($crmData): ?Lead
{
/** @var ?Stage $stage */
$stage = null;
if (isset($crmData['Status'])) {
// Get the current stage.
$stage = $this->config
->stages()
->where('name', $crmData['Status'])
->where('type', Stage::TYPE_LEAD)
->first();
if ($stage === null) {
// Import it.
$stage = $this->importStages([Stage::TYPE_LEAD], $crmData['Status']);
}
}
// If we have no way of importing this, just return null :(
if ($stage === null) {
return null;
}
$countryCode = $crmData['CountryCode'] ?? null;
// Salesforce allows custom "countries" to be created. Disregard these.
if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {
$countryCode = null;
}
// If we have no country code, try to parse it from the country name.
if ($countryCode === null && empty($crmData['Country']) !== false) {
$countryCode = $this->convertCountryNameToCode($crmData['Country']);
}
// Trim to our width and attempt to parse it.
$number = mb_strimwidth($crmData['Phone'] ?? '', 0, 25);
$parsedNumber = parsePhoneNumber($countryCode, $number);
$mobilePhone = null;
if (empty($crmData['MobilePhone']) === false) {
// Trim to our width and attempt to parse it.
$number = mb_strimwidth($crmData['MobilePhone'], 0, 25);
$mobilePhone = phone_e164($countryCode, $number);
}
$convertedDate = null;
$convertedAccount = null;
$convertedOpportunity = null;
$convertedContact = null;
if ($crmData['IsConverted'] == 'true') {
$convertedDate = $crmData['ConvertedDate'];
if (empty($crmData['ConvertedAccountId']) === false) {
$convertedAccount = $this->config
->accounts()
->where('crm_provider_id', $crmData['ConvertedAccountId'])
->first();
if ($convertedAccount === null) {
try {
$convertedAccount = $this->syncAccount($crmData['ConvertedAccountId']);
} catch (HttpNotFoundException $exception) {
// Probably the user has no permissions to access the converted data.
}
}
}
if (empty($crmData['ConvertedOpportunityId']) === false) {
$convertedOpportunity = $this->config
->opportunities()
->where('crm_provider_id', $crmData['ConvertedOpportunityId'])
->first();
if ($convertedOpportunity === null) {
try {
$convertedOpportunity = $this->syncOpportunity($crmData['ConvertedOpportunityId']);
} catch (HttpNotFoundException $exception) {
// Probably the user has no permissions to access the converted data.
}
}
}
if (empty($crmData['ConvertedContactId']) === false) {
$convertedContact = $this->team
->crm
->contacts()
->where('crm_provider_id', $crmData['ConvertedContactId'])
->first();
if ($convertedContact === null) {
try {
$convertedContact = $this->syncContact($crmData['ConvertedContactId']);
} catch (HttpNotFoundException $exception) {
// Probably the user has no permissions to access the converted data.
}
}
}
}
if (empty($crmData['Company'])) {
$company = 'Unknown';
} else {
$company = mb_strimwidth($crmData['Company'], 0, 191);
}
$domain = null;
if (empty($crmData['Website']) === false) {
$domain = mb_strimwidth($crmData['Website'], 0, 191);
$domain = StringUtil::resolveDomain($domain);
}
$createdDate = null;
if (empty($crmData['CreatedDate']) === false) {
$createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');
}
$profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);
$data = [
'team_id' => $this->team->id,
'user_id' => $profile?->user_id,
'owner_id' => $crmData['OwnerId'] ?? '',
'company' => $company,
'domain' => $domain,
'name' => $crmData['Name'] ? mb_strimwidth($crmData['Name'], 0, 191) : '',
'title' => $crmData['Title'] ? mb_strimwidth($crmData['Title'], 0, 128) : null,
'email' => $crmData['Email'] ? mb_strimwidth($crmData['Email'], 0, 80) : null,
'phone' => $parsedNumber['phone'],
'ext' => $parsedNumber['ext'] ?? null,
'mobile_phone' => $mobilePhone,
'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(
crmConfiguration: $this->config,
crmProviderId: $crmData['Id'],
modelType: Lead::class,
fileName: $crmData['Id'],
avatarText: $crmData['Name']
),
'stage_id' => $stage->id,
'record_type_id' => null,
'converted_at' => $convertedDate,
'converted_account_id' => $convertedAccount->id ?? null,
'converted_opportunity_id' => $convertedOpportunity->id ?? null,
'converted_contact_id' => $convertedContact->id ?? null,
'country_code' => $countryCode,
'remotely_created_at' => $createdDate,
];
$this->restoreAnyTrashedEntity($this->config->leads(), $crmData['Id']);
/** @var Lead $lead */
$lead = $this->config->leads()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);
if ($lead->wasChanged('converted_at') && $lead->getConvertedAt() !== null) {
$this->eventDispatcher->dispatch(new LeadConverted($lead));
}
$this->handleObjectDeletion($lead, $crmData);
if ($lead->trashed()) {
return null;
}
return $lead;
}
/**
* @inheritdoc
*/
public function syncAccounts(Carbon $since, ?Carbon $to = null): int
{
$syncCount = 0;
$fields = $this->getAllFieldsAsArray('account');
if (\in_array('Id', $fields, true) === false) {
return $syncCount;
}
$query = '
SELECT ' . rtrim(implode(',', $fields), ',') . '
FROM Account
WHERE LastModifiedDate > :since
ORDER BY LastModifiedDate ASC';
try {
$sfAccounts = $this->queryHandler->query($query, [
'since' => $since->format('Y-m-d\TH:i:s\Z'),
]);
foreach ($sfAccounts as $sfAccount) {
// Only sync if previously imported.
if ($this->hasAccount($sfAccount['Id'])) {
$this->importAccount($sfAccount);
$syncCount++;
}
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
$this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::ACCOUNT);
return $syncCount;
}
/**
* @inheritdoc
*/
public function syncAccount(string $crmId): ?Account
{
$fields = $this->getAllFieldsAsArray('account');
if (! in_array('Id', $fields, true)) {
$this->logger->info('[Salesforce] Sync account cancelled. Fields are not available.', [
'crmId' => $crmId,
'userId' => $this->profile->getUserId(),
]);
return null;
}
$sfAccount = $this->getRecord('Account', $crmId, $fields);
return $this->importAccount($sfAccount);
}
private function importAccount($crmData): ?Account
{
if (! empty($crmData['IsDeleted'])) {
$this->handleEntityDeletionByProviderId($this->config->accounts(), $crmData);
return null;
}
$countryCode = $crmData['BillingCountryCode'] ?? $crmData['ShippingCountryCode'] ?? null;
// Salesforce allows custom "countries" to be created. Disregard these.
if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {
$countryCode = null;
}
// If we have no country code, try to parse it from the country names.
if ($countryCode === null && empty($crmData['BillingCountry']) === false) {
$countryCode = $this->convertCountryNameToCode($crmData['BillingCountry']);
}
if ($countryCode === null && empty($crmData['ShippingCountry']) === false) {
$countryCode = $this->convertCountryNameToCode($crmData['ShippingCountry']);
}
if (empty($crmData['Phone']) === false) {
// Trim to our width and attempt to parse it.
$number = mb_strimwidth($crmData['Phone'], 0, 25);
$parsedNumber = parsePhoneNumber($countryCode, $number);
} else {
$parsedNumber = [];
}
$industry = null;
if (empty($crmData['Industry']) === false) {
$industry = mb_strimwidth($crmData['Industry'], 0, 40);
}
$domain = null;
if (empty($crmData['Website']) === false) {
$domain = mb_strimwidth($crmData['Website'], 0, 191);
$domain = StringUtil::resolveDomain($domain);
}
$createdDate = null;
if (empty($crmData['CreatedDate']) === false) {
$createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');
}
$profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);
$data = [
'team_id' => $this->team->id,
'user_id' => $profile?->user_id,
'owner_id' => $crmData['OwnerId'],
'name' => mb_strimwidth($crmData['Name'], 0, 191),
'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(
crmConfiguration: $this->config,
crmProviderId: $crmData['Id'],
modelType: Account::class,
fileName: $crmData['Id'],
avatarText: $crmData['Name']
),
'industry' => $industry,
'domain' => $domain,
'phone' => $parsedNumber['phone'] ?? null,
'ext' => $parsedNumber['ext'] ?? null,
'country_code' => $countryCode,
'remotely_created_at' => $createdDate,
];
$this->restoreAnyTrashedEntity($this->config->accounts(), $crmData['Id']);
/** @var Account $account */
$account = $this->config->accounts()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);
$this->handleObjectDeletion($account, $crmData);
return $account->trashed() ? null : $account;
}
/**
* @inheritdoc
*/
public function syncOpportunities(array $parameters, ?string $strategy = null): int
{
$strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);
$syncCount = 0;
$logParams = $parameters;
$parameters['profile'] = $this->profile;
$logParams['user'] = $this->profile->getUserId();
if (count($strategies) > 1) {
$this->logger->warning('[' . $this->getDisplayName() . '] Multiple sync strategies used', [
'teamId' => $this->team->getUuid(),
'params' => $logParams,
'strategies_count' => count($strategies),
]);
}
foreach ($strategies as $syncStrategy) {
$name = $syncStrategy->getStrategyName();
try {
$sfOpportunities = $syncStrategy->fetchOpportunities($parameters);
$totalRecords = $sfOpportunities->count();
foreach ($sfOpportunities as $sfOpportunity) {
$this->importOpportunity($sfOpportunity);
$syncCount++;
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
$this->logger->warning('[' . $this->getDisplayName() . '] No opportunities found', [
'teamId' => $this->team->getUuid(),
'name' => $name,
'params' => $logParams,
'reason' => $noResultsException->getMessage(),
]);
} catch (CrmException $crmException) {
// Nothing to sync.
$this->logger->warning('[' . $this->getDisplayName() . '] Opportunity sync failed', [
'teamId' => $this->team->getUuid(),
'name' => $name,
'params' => $logParams,
'reason' => $crmException->getMessage(),
]);
}
}
$this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::OPPORTUNITY, ['params' => $logParams]);
// debug to see how if count of opportunities reaches 1000
if ($syncCount >= 1000) {
$this->logger->info(
'[' . $this->getDisplayName() . '] Sync Opportunities - count warning',
[
'team_id' => $this->team->getId(),
'params' => $logParams,
'count' => $syncCount,
'strategies_count' => count($strategies),
'total_records' => $totalRecords ?? null,
]
);
}
return $syncCount;
}
/**
* @inheritdoc
*/
public function syncOpportunity(string $crmId): ?Opportunity
{
$strategy = $this->opportunitySyncStrategyResolver->resolve(
$this->config,
OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY
);
$parameters = [
'profile' => $this->profile,
'crm_id' => $crmId,
];
try {
$sfOpportunity = $strategy->fetchOpportunities($parameters);
} catch (HttpNotFoundException $e) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [
'teamId' => $this->team->id_string,
'crmId' => $crmId,
]);
return null;
} catch (CrmException $crmException) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity sync failed', [
'teamId' => $this->team->id_string,
'crmId' => $crmId,
'exception' => $crmException->getMessage(),
]);
return null;
}
if ($sfOpportunity instanceof ArrayIterator) {
return $this->importOpportunity($sfOpportunity->getItems());
}
return $this->importOpportunity($sfOpportunity);
}
/**
* @throws HttpNotFoundException
*/
private function importOpportunity($crmData): ?Opportunity
{
$profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);
$account = null;
if (empty($crmData['AccountId']) === false) {
/** @var ?Account $account */
$account = $this->config->accounts()
->where('crm_provider_id', (string) $crmData['AccountId'])
->first();
if ($account === null) {
$account = $this->syncAccount($crmData['AccountId']);
}
}
$userId = $profile?->getUserId() ?? $account?->getUserId();
if ($userId === null) {
$this->logger->error('[Salesforce] | Skip import, no user_id found', [
'id' => $crmData['Id'],
]);
return null;
}
/** @var ?Stage $stage */
$stage = null;
if (isset($crmData['StageName'])...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12121 on JY-20963-fix-import-on-deleted-entity, menu","depth":5,"on_screen":true,"help_text":"Pull request #12121 exists for current branch JY-20963-fix-import-on-deleted-entity, but pull request details loading failed","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"ServiceTest","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'ServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'ServiceTest'","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"12","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"246","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"3","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"21","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"<?php\n\nnamespace Jiminny\\Services\\Crm\\Salesforce;\n\nuse Carbon\\Carbon;\nuse Exception;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany;\nuse Illuminate\\Events\\Dispatcher;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Illuminate\\Support\\Facades\\Log;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Component\\Country\\CountriesMap;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Contracts\\Repositories\\TeamRepository;\nuse Jiminny\\Contracts\\Services\\Crm\\FetchRelatedActivityInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\ImportsBusinessProcessesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\LayoutManagementInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\MatchCrmEntitiesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\Provider\\SalesforceBatchSyncInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\Provider\\SalesforceInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\RemoteEntityLookupInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\RemoteEntityManipulationInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\RemoteNoteEntityManipulationInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SearchTaskInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SendSummaryToCrmInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SettingsInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SupportsObjectTypeParseInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SyncCrmEntitiesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SyncCrmProfileRecordTypesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\VerifyTaskExistsInterface;\nuse Jiminny\\Enums\\CrmObject;\nuse Jiminny\\Events\\Activities\\Crm\\LeadConverted;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Exceptions\\HttpBadRequestException;\nuse Jiminny\\Exceptions\\HttpNotFoundException;\nuse Jiminny\\Exceptions\\NoResultsException;\nuse Jiminny\\Exceptions\\ServiceUnavailableException;\nuse Jiminny\\Jobs\\Crm\\NoteObject;\nuse Jiminny\\Jobs\\Crm\\MatchActivitiesToNewOpportunity;\nuse Jiminny\\Models\\Account;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Calendar\\CalendarEvent;\nuse Jiminny\\Models\\Contact;\nuse Jiminny\\Models\\Contracts\\ActivityContract;\nuse Jiminny\\Models\\Crm\\BusinessProcess;\nuse Jiminny\\Models\\Crm\\Configuration;\nuse Jiminny\\Models\\Crm\\ContactRole;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\Profile;\nuse Jiminny\\Models\\Crm\\RecordType;\nuse Jiminny\\Models\\Lead;\nuse Jiminny\\Models\\Opportunity;\nuse Jiminny\\Models\\Playbook;\nuse Jiminny\\Models\\SocialAccount;\nuse Jiminny\\Models\\Stage;\nuse Jiminny\\Models\\TeamSettings;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\Crm\\ContactRoleRepository;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\Crm\\ProfileRepository;\nuse Jiminny\\Repositories\\Crm\\RecordTypeFieldValuesRepository;\nuse Jiminny\\Services\\Avatar\\ProspectPhotoPathService;\nuse Jiminny\\Services\\Crm\\BaseService;\nuse Jiminny\\Services\\Crm\\Helpers\\ArrayIterator;\nuse Jiminny\\Services\\Crm\\MatchDomainByEmailInterface;\nuse Jiminny\\Services\\Crm\\OpportunitySyncStrategyResolver;\nuse Jiminny\\Services\\Crm\\ResolveCompanyNameByEmailTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\Fields\\FieldHelper;\nuse Jiminny\\Services\\Crm\\Salesforce\\Fields\\FieldTypeConverter;\nuse Jiminny\\Services\\Crm\\Salesforce\\Fields\\ValueNormalizer;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\FollowupActivityTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\LogActivityTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\RecordManipulationsTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\SyncFieldsTrait;\nuse Jiminny\\Utils\\CurrencyFormatter;\nuse Jiminny\\Utils\\StringUtil;\nuse Ramsey\\Uuid\\Uuid;\nuse Sentry\\Laravel\\Facade as Sentry;\n\nclass Service extends BaseService implements\n SalesforceInterface,\n SalesforceBatchSyncInterface,\n SyncCrmEntitiesInterface,\n SyncCrmProfileRecordTypesInterface,\n ImportsBusinessProcessesInterface,\n RemoteEntityManipulationInterface,\n FetchRelatedActivityInterface,\n SendSummaryToCrmInterface,\n MatchDomainByEmailInterface,\n SearchTaskInterface,\n LayoutManagementInterface,\n SettingsInterface,\n MatchCrmEntitiesInterface,\n RemoteEntityLookupInterface,\n SupportsObjectTypeParseInterface,\n RemoteNoteEntityManipulationInterface,\n VerifyTaskExistsInterface\n{\n use ResolveCompanyNameByEmailTrait;\n use SyncFieldsTrait;\n use DeleteObjectsTrait;\n use RecordManipulationsTrait;\n use ServiceTraits\\BatchSyncTrait;\n use FollowupActivityTrait;\n use LogActivityTrait;\n\n /**\n * Note Body Limit for the Old Note-Taking Tool\n *\n * @var int\n */\n private const int CLASSIC_NOTE_MAX_LENGTH = 32000;\n\n /**\n * Note Content Limit for the New Notes\n *\n * @var int\n */\n private const int ENHANCED_NOTE_MAX_LENGTH = 50000000;\n\n private const string INSTALLED_PACKAGE_ID = '033Tw0000007bKbIAI';\n\n private const int CACHE_TTL = 600;\n\n private const int TASK_VERIFICATION_CACHE_TTL = 86400; // 1 day - 86400\n\n /**\n * @var Client\n */\n protected $client;\n\n protected PayloadBuilder $payloadBuilder;\n protected QueryHandler $queryHandler;\n\n private OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;\n\n public function __construct(\n Client $client,\n PayloadBuilder $payloadBuilder,\n protected Dispatcher $eventDispatcher,\n private readonly CountriesMap $countriesMap,\n private readonly ProspectPhotoPathService $prospectPhotoPathService,\n ) {\n parent::__construct();\n\n $this->client = $client;\n $this->payloadBuilder = $payloadBuilder;\n $this->queryHandler = app(QueryHandler::class, [\n 'client' => $this->client,\n 'logger' => $this->logger,\n ]);\n $this->opportunitySyncStrategyResolver = app(OpportunitySyncStrategyResolver::class, [\n 'client' => $this->client,\n ]);\n }\n\n public function getDisplayName(): string\n {\n return 'Salesforce';\n }\n\n public function getJobDelay(): int\n {\n return 1;\n }\n\n protected function getOAuthAccount(User $user): ?SocialAccount\n {\n return $user->getSocialAccount(SocialAccount::PROVIDER_SALESFORCE);\n }\n\n public function verifyTaskExists(Activity $activity): bool\n {\n $crmProviderId = $activity->getCrmProviderId();\n $cacheKey = \"crm_task_exists:{$this->config->getId()}:$crmProviderId\";\n\n return Cache::remember($cacheKey, self::TASK_VERIFICATION_CACHE_TTL, function () use ($activity, $crmProviderId) {\n $playbook = $this->getPlaybookFromActivity($activity);\n\n if ($playbook === null) {\n $this->logger->warning('[Salesforce] Cannot verify task - no playbook found', [\n 'activity' => $activity->getId(),\n 'crm_provider_id' => $crmProviderId,\n ]);\n\n return false;\n }\n\n $objectType = $playbook->getActivityType() === Playbook::ACTIVITY_TYPE_EVENT ? 'Event' : 'Task';\n\n try {\n $record = $this->getRecord($objectType, $crmProviderId, ['Id', 'IsDeleted']);\n\n return ! empty($record) && ($record['IsDeleted'] ?? false) === false;\n } catch (HttpNotFoundException|HttpBadRequestException) {\n $this->logger->info('[Salesforce] Activity record not found during verification', [\n 'activity' => $activity->getId(),\n 'object_type' => $objectType,\n 'crm_provider_id' => $crmProviderId,\n 'config_id' => $this->config->getId(),\n ]);\n\n return false;\n }\n });\n }\n\n public function query(string $queryToRun, array $parameters = []): QueryIterator\n {\n // Due to poorly designed external calls, this method cannot be entirely removed\n return $this->queryHandler->query($queryToRun, $parameters);\n }\n\n /*=========== Organization Information ===============*/\n\n /**\n * Get a list of all the API Versions for the instance.\n *\n * @throws CrmException\n *\n * @return mixed\n *\n */\n public function getApiVersions()\n {\n $url = $this->config->crm_base_url . '/services/data';\n\n $response = $this->client->get($url);\n\n return json_decode($response->getBody(), true);\n }\n\n /**\n * Gets the valid recordTypes for a given Salesforce Object via the describe API.\n */\n private function getRecordTypes(string $crmObject): array\n {\n $url = $this->client->getObjectsUrl() . $crmObject . '/describe';\n\n $response = $this->client->get($url);\n $jsonResponse = json_decode($response->getBody(), true);\n\n $fields = [];\n foreach ($jsonResponse['recordTypeInfos'] as $row) {\n $fields[] = ['recordTypeId' => $row['recordTypeId'], 'default' => $row['defaultRecordTypeMapping']];\n }\n\n return $fields;\n }\n\n /**\n * Convert raw field data into a format compatible with CRM APIs.\n */\n public function normalizeValue(string $fieldType, string $fieldValue, bool $internal = false): string\n {\n return ValueNormalizer::normalize($fieldType, $fieldValue, $internal);\n }\n\n /**\n * @inheritdoc\n */\n public function getDefaultFields(string $activityType): array\n {\n $fields = [];\n\n $defaultFields = ($activityType === Playbook::ACTIVITY_TYPE_TASK)\n ? FieldDefinitions::defaultTaskFields()\n : FieldDefinitions::defaultEventFields();\n\n // This lazy creates these fields if not already setup.\n foreach ($defaultFields as $defaultField) {\n $fields[] = $this->config->fields()->firstOrCreate($defaultField);\n }\n\n return $fields;\n }\n\n /**\n * @inheritdoc\n */\n public function getDefaultActivityField(string $activityType): Field\n {\n // Setup the activity field as the default Type.\n /** @var Field $activityField */\n $activityField = $this->config->fields()->where([\n 'crm_provider_id' => 'Type',\n 'object_type' => $activityType,\n ])->first();\n\n return $activityField;\n }\n\n /**\n * @inheritdoc\n */\n public function getSupportedPlaybookTypes(): array\n {\n return [Playbook::ACTIVITY_TYPE_TASK, Playbook::ACTIVITY_TYPE_EVENT];\n }\n\n protected function getDefaultFollowupLayoutFields(string $activityType): array\n {\n $fields = [];\n $fieldRepo = app(FieldRepository::class);\n\n $fieldFilter = ($activityType === Playbook::ACTIVITY_TYPE_TASK)\n ? FieldDefinitions::taskFollowupFieldsFilter()\n : FieldDefinitions::eventFollowupFieldsFilter();\n\n foreach ($fieldFilter as $eachFilter) {\n $field = $fieldRepo->findOneConfigurationFieldByProperties($this->config, $eachFilter);\n\n // Only add the field if it is created, which it should be.\n if ($field) {\n $fields[] = $field;\n }\n }\n\n return $fields;\n }\n\n public function getDealInsightsFields(): array\n {\n return FieldDefinitions::dealInsightsFields();\n }\n\n /**\n * This one is now called only when ImportActivityTypes is triggered or SyncFieldMetadata executed manually\n * Regular sync now uses SharedSyncFieldsTrait -> syncSingleObjectType\n * Needs to be replaced later on\n */\n public function syncField(Field $field): void\n {\n try {\n if (FieldHelper::isCustomField($field)) {\n $query = '\n SELECT\n Id, Metadata, TableEnumOrId\n FROM\n CustomField\n WHERE\n DeveloperName = :fieldName\n AND\n TableEnumOrId = :fieldType\n AND\n NamespacePrefix = :namespacePrefix';\n\n // We need to constrain the field lookup to the object, in case it's used in multiple places.\n $objectType = \\in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true)\n ? 'activity'\n : $field->object_type;\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'fieldName' => substr($field->crm_provider_id, 0, -\\strlen('__c')),\n 'fieldType' => ucfirst($objectType),\n\n // This is used to ensure we only consider the field within the org, not installed packages.\n 'namespacePrefix' => 'null',\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n // Sync field metadata.\n $metadata = $sfField['Metadata'];\n\n $field->description = mb_strimwidth($metadata['description'] ?? '', 0, 191);\n $field->label = mb_strimwidth($metadata['label'] ?? '', 0, Field::LABEL_MAX_LENGTH);\n $field->type = $this->convertFieldType($metadata['type'], $field->getEntityName());\n $field->is_mandatory = ($metadata['required'] === true);\n $field->length = $metadata['length'];\n $field->default_value = mb_strimwidth(trim($metadata['defaultValue'] ?? '', '\"'), 0, 191);\n $field->save();\n } else {\n $query = '\n SELECT\n Id, DataType, DeveloperName, Label, Length, Description\n FROM\n FieldDefinition\n WHERE\n DurableId = :entityName';\n\n $entityName = $field->getEntityName();\n $sfFields = $this->queryHandler->metadata($query, [\n 'entityName' => $entityName,\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n $convertedType = $this->convertFieldType($sfField['DataType'], $entityName);\n $label = mb_strimwidth($sfField['Label'], 0, Field::LABEL_MAX_LENGTH);\n\n if ($field->isBusinessType()) {\n $label = 'Opportunity Type';\n }\n\n $field->description = mb_strimwidth($sfField['Description'], 0, Field::DESCRIPTION_MAX_LENGTH);\n $field->label = $label;\n $field->type = $convertedType;\n $field->length = $sfField['Length'];\n $field->save();\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n private function convertFieldType(string $from, ?string $entityName = null): string\n {\n $converter = new FieldTypeConverter();\n\n return $converter->convert($from, $entityName);\n }\n\n /**\n * @inheritdoc\n */\n public function importPicklistValues(Field $field): array\n {\n $values = [];\n $fieldValues = [];\n\n try {\n if (FieldHelper::isCustomField($field)) {\n $query = '\n SELECT\n Id, Metadata, TableEnumOrId\n FROM\n CustomField\n WHERE\n DeveloperName = :fieldName\n AND\n TableEnumOrId = :fieldType\n AND\n NamespacePrefix = :namespacePrefix';\n\n // We need to constrain the field lookup to the object, in case it's used in multiple places.\n $objectType = \\in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true) ?\n 'activity' : $field->object_type;\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'fieldName' => substr($field->crm_provider_id, 0, -\\strlen('__c')),\n 'fieldType' => ucfirst($objectType),\n // This is used to ensure we only consider the field within the org, not installed packages.\n 'namespacePrefix' => 'null',\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n $valueSet = $sfField['Metadata']['valueSet'];\n\n if ($valueSet['valueSetName'] === null) {\n // Local picklist values can be obtained easily.\n $picklistValues = $valueSet['valueSetDefinition']['value'];\n } else {\n // But for some fields, we just get the Global Value Picklist pointer so need to do more work.\n $picklistValues = $this->importGlobalValuePicklistValues($valueSet['valueSetName']);\n }\n\n // Import all active values.\n foreach ($picklistValues as $i => $sfFieldValue) {\n // Setup default value.\n if ($sfFieldValue['default']) {\n $field->update(['default_value' => $sfFieldValue['valueName']]);\n }\n\n // This comes through as null if active (lol).\n if ($sfFieldValue['isActive'] !== false) {\n $values[] = [\n 'value' => $sfFieldValue['valueName'],\n 'label' => $sfFieldValue['valueName'],\n 'sequence' => $i,\n 'is_default' => $sfFieldValue['default'],\n ];\n }\n }\n } else {\n $objectFields = $this->getObjectFields($field->object_type);\n $fieldId = $field->crm_provider_id;\n\n // Only work with our field of interest.\n $objectField = array_filter($objectFields, function ($item) use ($fieldId) {\n return $item['name'] === $fieldId;\n });\n\n $objectField = array_shift($objectField);\n if (empty($objectField['picklistValues']) === false) {\n foreach ($objectField['picklistValues'] as $i => $sfFieldValue) {\n // Skip inactive values.\n if ($sfFieldValue['active'] === false) {\n continue;\n }\n\n // Setup default value.\n if ($sfFieldValue['defaultValue']) {\n $field->update(['default_value' => $sfFieldValue['value']]);\n }\n\n $values[] = [\n 'value' => $sfFieldValue['value'],\n 'label' => $sfFieldValue['label'],\n 'sequence' => $i,\n 'is_default' => $sfFieldValue['defaultValue'],\n ];\n }\n }\n }\n\n $fieldsToPurge = $field->values()->get()->pluck('value')->toArray();\n\n foreach ($values as $value) {\n $value['value'] = substr($value['value'] ?? '', 0, 255);\n $fieldValues[] = $field->values()->updateOrCreate([\n 'value' => $value['value'],\n ], $value);\n\n // Remove this value from the ones we are going to purge.\n if (($key = array_search($value['value'], $fieldsToPurge, true)) !== false) {\n unset($fieldsToPurge[$key]);\n }\n }\n\n // Delete the old values that are no longer used.\n // Get IDs of the values to be deleted\n $valuesToDelete = $field->values()->whereIn('value', $fieldsToPurge);\n $valuesToDeleteIds = $valuesToDelete->pluck('id');\n if (! $valuesToDeleteIds->isEmpty()) {\n $recordTypeFieldValuesRepository = app(RecordTypeFieldValuesRepository::class);\n $recordTypeFieldValuesRepository->deleteForCrmFieldValueIds($valuesToDeleteIds->toArray());\n\n // Now safely delete from crm_field_values\n $valuesToDelete->delete();\n }\n\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n return $fieldValues;\n }\n\n /**\n * Gets values from Global Value Picklists.\n */\n private function importGlobalValuePicklistValues(string $picklistName): array\n {\n $query = '\n SELECT\n Metadata\n FROM\n GlobalValueSet\n WHERE\n DeveloperName = :picklistName\n LIMIT 1';\n\n try {\n $sfValues = $this->queryHandler->metadata($query, [\n 'picklistName' => $picklistName,\n ]);\n\n // There is always 1 result at this point.\n $sfValue = $sfValues->current();\n\n return $sfValue['Metadata']['customValue'];\n } catch (NoResultsException $noResultsException) {\n // Nothing returned.\n\n return [];\n }\n }\n\n /**\n * @inheritdoc\n */\n public function syncProfileRecordTypes(): void\n {\n $objectTypes = [\n 'lead',\n 'account',\n 'contact',\n 'opportunity',\n 'task',\n 'event',\n ];\n\n foreach ($objectTypes as $objectType) {\n try {\n $crmRecordTypes = $this->getRecordTypes(ucfirst($objectType));\n\n foreach ($crmRecordTypes as $crmRecordType) {\n // If the record type is default and not the Master type, set this.\n if ($crmRecordType['default'] && $crmRecordType['recordTypeId'] !== '012000000000000AAA') {\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $crmRecordType['recordTypeId'])\n ->first();\n\n if ($recordType) {\n $this->profile->{$objectType . '_record_type_id'} = $recordType->id;\n }\n }\n }\n } catch (HttpNotFoundException $exception) {\n Log::error('No access to ' . $objectType . ' object, skipping...');\n\n // XXX: should we log this fact somewhere?\n continue;\n }\n }\n\n if ($this->profile->isDirty()) {\n $this->profile->save();\n }\n }\n\n /**\n * Gets business processes.\n */\n public function importBusinessProcesses(): void\n {\n $query = '\n SELECT\n Id, IsActive, Name, TableEnumOrId\n FROM\n BusinessProcess\n WHERE\n TableEnumOrId IN (\\'Lead\\',\\'Opportunity\\')';\n\n try {\n $sfProcesses = $this->queryHandler->query($query);\n\n // Upsert all processes for the team.\n foreach ($sfProcesses as $sfProcess) {\n /** @var BusinessProcess $businessProcess */\n $businessProcess = $this->config->businessProcesses()->updateOrCreate([\n 'crm_provider_id' => $sfProcess['Id'],\n ], [\n 'team_id' => $this->team->id,\n 'name' => $sfProcess['Name'],\n 'type' => $sfProcess['TableEnumOrId'] === 'Lead' ? 'lead' : 'opportunity',\n 'is_selectable' => $sfProcess['IsActive'],\n ]);\n\n $this->importBusinessProcessStages($businessProcess);\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n /**\n * Gets business process stages.\n */\n private function importBusinessProcessStages(BusinessProcess $businessProcess): void\n {\n $query = '\n SELECT\n Metadata\n FROM\n BusinessProcess\n WHERE\n Id = :processId';\n\n try {\n $stages = [];\n $sfProcessStages = $this->queryHandler->metadata($query, [\n 'processId' => $businessProcess->crm_provider_id,\n ]);\n\n // There is always 1 result at this point.\n $sfProcessStage = $sfProcessStages->current();\n\n // Upsert all processes for the team.\n foreach ($sfProcessStage['Metadata']['values'] as $sfProcessStage) {\n $sanitizedName = urldecode($sfProcessStage['valueName']); // Must decode: \"%2C\" becomes \",\" etc.\n\n $stage = $businessProcess->crm->stages()\n // This MUST match on label because this API doesn't use API Name.\n ->where('label', $sanitizedName)\n ->where('type', $businessProcess->type)\n ->where('is_selectable', 1)\n ->first();\n\n if ($stage) {\n $stages[] = $stage->id;\n }\n }\n\n $businessProcess->stages()->sync($stages);\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n /**\n * Gets record types.\n */\n public function importRecordTypes(): void\n {\n $query = '\n SELECT\n Id, IsActive, Name, BusinessProcessId, SobjectType\n FROM\n RecordType';\n\n try {\n $sfRecordTypes = $this->queryHandler->query($query);\n\n // Upsert all record types for the process.\n foreach ($sfRecordTypes as $sfRecordType) {\n $businessProcess = null;\n if ($sfRecordType['BusinessProcessId']) {\n $businessProcess = $this->config->businessProcesses()\n ->where('crm_provider_id', $sfRecordType['BusinessProcessId'])\n ->first();\n }\n\n /** @var RecordType $recordType */\n $recordType = $this->config->recordTypes()->updateOrCreate([\n 'crm_provider_id' => $sfRecordType['Id'],\n ], [\n 'team_id' => $this->team->id,\n 'type' => mb_strtolower($sfRecordType['SobjectType']),\n 'name' => $sfRecordType['Name'],\n 'is_selectable' => $sfRecordType['IsActive'],\n 'business_process_id' => $businessProcess->id ?? null,\n ]);\n\n $this->importRecordTypeFieldValues($recordType);\n }\n } catch (NoResultsException $noResultsException) {\n // Do nothing.\n }\n }\n\n /**\n * Import record type - field value mappings. This only works for standard fields.\n */\n private function importRecordTypeFieldValues(RecordType $recordType): void\n {\n try {\n $query = '\n SELECT\n Metadata\n FROM\n RecordType\n WHERE\n Id = :recordTypeId';\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'recordTypeId' => $recordType->crm_provider_id,\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n // Sync field metadata.\n $picklists = $sfField['Metadata']['picklistValues'];\n\n foreach ($picklists as $picklist) {\n $field = $this->config->fields()->where([\n 'type' => Field::TYPE_PICKLIST,\n 'object_type' => $recordType->type,\n 'crm_provider_id' => $picklist['picklist'],\n ])->first();\n\n if ($field) {\n $fieldValues = [];\n\n foreach ($picklist['values'] as $value) {\n // Must decode: \"%2C\" becomes \",\" etc.\n $fieldValue = $field->values()\n ->where('value', urldecode($value['valueName']))\n ->first();\n\n if ($fieldValue) {\n $fieldValues[] = $fieldValue->id;\n }\n }\n\n $recordType->fieldValues()->sync($fieldValues);\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n /**\n * @inheritdoc\n */\n public function importStages(?array $types = null, ?string $missingStageName = null): ?Stage\n {\n $params = [];\n $missingStage = null;\n if ($types === null) {\n $types = [Stage::TYPE_LEAD, Stage::TYPE_OPPORTUNITY];\n }\n\n foreach ($types as $type) {\n if ($type === Stage::TYPE_LEAD) {\n $query = '\n SELECT\n Id, ApiName, MasterLabel, SortOrder\n FROM\n LeadStatus';\n } else {\n $query = '\n SELECT\n Id, ApiName, MasterLabel, IsActive, SortOrder, DefaultProbability\n FROM\n OpportunityStage';\n }\n\n if ($missingStageName) {\n $escapedStageName = ValueNormalizer::replaceQueryWithStringLiterals($missingStageName);\n\n $query .= ' WHERE ApiName = :stageName';\n\n $params = [\n 'stageName' => $escapedStageName,\n ];\n }\n\n try {\n $sfStages = $this->queryHandler->query($query, $params);\n } catch (NoResultsException $exception) {\n $sfStages = [];\n }\n\n $missingStage = null;\n\n // Upsert all stages for the team.\n foreach ($sfStages as $sfStage) {\n $selectable = true;\n if (array_key_exists('IsActive', $sfStage)) {\n $selectable = $sfStage['IsActive'];\n }\n\n $this->restoreAnyTrashedEntity($this->config->stages(), $sfStage['Id']);\n\n $stage = $this->config->stages()->updateOrCreate([\n 'crm_provider_id' => $sfStage['Id'],\n ], [\n 'team_id' => $this->team->id,\n 'name' => mb_strimwidth($sfStage['ApiName'], 0, 50),\n 'label' => mb_strimwidth($sfStage['MasterLabel'], 0, 191),\n 'type' => $type,\n 'sequence' => $sfStage['SortOrder'] ?? 0,\n 'is_selectable' => $selectable,\n 'probability' => $sfStage['DefaultProbability'] ?? null,\n ]);\n\n if ($missingStageName && $missingStageName === $sfStage['ApiName']) {\n $missingStage = $stage;\n }\n }\n\n if ($missingStageName && $missingStage === null) {\n // If they requested a stage that still doesn't exist, it must be inactive so lazy create it.\n $missingStage = $this->config->stages()->create([\n 'crm_provider_id' => Uuid::uuid4(),\n 'team_id' => $this->team->id,\n 'name' => mb_strimwidth($missingStageName, 0, 50),\n 'label' => mb_strimwidth($missingStageName, 0, 191),\n 'type' => $type,\n 'sequence' => 0,\n 'is_selectable' => 0,\n ]);\n }\n }\n\n return $missingStage;\n }\n\n /**\n * @inheritdoc\n */\n public function syncLeads(Carbon $since, ?Carbon $to = null, ?string $crmProfileId = null): int\n {\n $syncCount = 0;\n $fields = $this->getAllFieldsAsArray('lead');\n if (\\in_array('Id', $fields, true) === false) {\n return $syncCount;\n }\n\n $query = '\n SELECT ' . rtrim(implode(',', $fields), ',') . '\n FROM Lead\n WHERE LastModifiedDate > :since\n ORDER BY LastModifiedDate ASC';\n\n try {\n $sfLeads = $this->queryHandler->query($query, [\n 'since' => $since->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($sfLeads as $sfLead) {\n // Only sync if previously imported.\n if ($this->hasLead($sfLead['Id'])) {\n $this->importLead($sfLead);\n $syncCount++;\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::LEAD);\n\n return $syncCount;\n }\n\n /**\n * @inheritdoc\n */\n public function syncLead(string $crmId): ?Lead\n {\n $fields = $this->getAllFieldsAsArray('lead');\n\n $sfLead = $this->getRecord('Lead', $crmId, $fields);\n\n return $this->importLead($sfLead);\n }\n\n private function importLead($crmData): ?Lead\n {\n /** @var ?Stage $stage */\n $stage = null;\n if (isset($crmData['Status'])) {\n // Get the current stage.\n $stage = $this->config\n ->stages()\n ->where('name', $crmData['Status'])\n ->where('type', Stage::TYPE_LEAD)\n ->first();\n\n if ($stage === null) {\n // Import it.\n $stage = $this->importStages([Stage::TYPE_LEAD], $crmData['Status']);\n }\n }\n\n // If we have no way of importing this, just return null :(\n if ($stage === null) {\n return null;\n }\n\n $countryCode = $crmData['CountryCode'] ?? null;\n\n // Salesforce allows custom \"countries\" to be created. Disregard these.\n if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {\n $countryCode = null;\n }\n\n // If we have no country code, try to parse it from the country name.\n if ($countryCode === null && empty($crmData['Country']) !== false) {\n $countryCode = $this->convertCountryNameToCode($crmData['Country']);\n }\n\n // Trim to our width and attempt to parse it.\n $number = mb_strimwidth($crmData['Phone'] ?? '', 0, 25);\n $parsedNumber = parsePhoneNumber($countryCode, $number);\n\n $mobilePhone = null;\n if (empty($crmData['MobilePhone']) === false) {\n // Trim to our width and attempt to parse it.\n $number = mb_strimwidth($crmData['MobilePhone'], 0, 25);\n $mobilePhone = phone_e164($countryCode, $number);\n }\n\n $convertedDate = null;\n $convertedAccount = null;\n $convertedOpportunity = null;\n $convertedContact = null;\n\n if ($crmData['IsConverted'] == 'true') {\n $convertedDate = $crmData['ConvertedDate'];\n\n if (empty($crmData['ConvertedAccountId']) === false) {\n $convertedAccount = $this->config\n ->accounts()\n ->where('crm_provider_id', $crmData['ConvertedAccountId'])\n ->first();\n\n if ($convertedAccount === null) {\n try {\n $convertedAccount = $this->syncAccount($crmData['ConvertedAccountId']);\n } catch (HttpNotFoundException $exception) {\n // Probably the user has no permissions to access the converted data.\n }\n }\n }\n\n if (empty($crmData['ConvertedOpportunityId']) === false) {\n $convertedOpportunity = $this->config\n ->opportunities()\n ->where('crm_provider_id', $crmData['ConvertedOpportunityId'])\n ->first();\n\n if ($convertedOpportunity === null) {\n try {\n $convertedOpportunity = $this->syncOpportunity($crmData['ConvertedOpportunityId']);\n } catch (HttpNotFoundException $exception) {\n // Probably the user has no permissions to access the converted data.\n }\n }\n }\n\n if (empty($crmData['ConvertedContactId']) === false) {\n $convertedContact = $this->team\n ->crm\n ->contacts()\n ->where('crm_provider_id', $crmData['ConvertedContactId'])\n ->first();\n\n if ($convertedContact === null) {\n try {\n $convertedContact = $this->syncContact($crmData['ConvertedContactId']);\n } catch (HttpNotFoundException $exception) {\n // Probably the user has no permissions to access the converted data.\n }\n }\n }\n }\n\n if (empty($crmData['Company'])) {\n $company = 'Unknown';\n } else {\n $company = mb_strimwidth($crmData['Company'], 0, 191);\n }\n\n $domain = null;\n if (empty($crmData['Website']) === false) {\n $domain = mb_strimwidth($crmData['Website'], 0, 191);\n $domain = StringUtil::resolveDomain($domain);\n }\n\n $createdDate = null;\n if (empty($crmData['CreatedDate']) === false) {\n $createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n }\n\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $data = [\n 'team_id' => $this->team->id,\n 'user_id' => $profile?->user_id,\n 'owner_id' => $crmData['OwnerId'] ?? '',\n 'company' => $company,\n 'domain' => $domain,\n 'name' => $crmData['Name'] ? mb_strimwidth($crmData['Name'], 0, 191) : '',\n 'title' => $crmData['Title'] ? mb_strimwidth($crmData['Title'], 0, 128) : null,\n 'email' => $crmData['Email'] ? mb_strimwidth($crmData['Email'], 0, 80) : null,\n 'phone' => $parsedNumber['phone'],\n 'ext' => $parsedNumber['ext'] ?? null,\n 'mobile_phone' => $mobilePhone,\n 'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(\n crmConfiguration: $this->config,\n crmProviderId: $crmData['Id'],\n modelType: Lead::class,\n fileName: $crmData['Id'],\n avatarText: $crmData['Name']\n ),\n 'stage_id' => $stage->id,\n 'record_type_id' => null,\n 'converted_at' => $convertedDate,\n 'converted_account_id' => $convertedAccount->id ?? null,\n 'converted_opportunity_id' => $convertedOpportunity->id ?? null,\n 'converted_contact_id' => $convertedContact->id ?? null,\n 'country_code' => $countryCode,\n 'remotely_created_at' => $createdDate,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->leads(), $crmData['Id']);\n\n /** @var Lead $lead */\n $lead = $this->config->leads()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n if ($lead->wasChanged('converted_at') && $lead->getConvertedAt() !== null) {\n $this->eventDispatcher->dispatch(new LeadConverted($lead));\n }\n\n $this->handleObjectDeletion($lead, $crmData);\n\n if ($lead->trashed()) {\n return null;\n }\n\n return $lead;\n }\n\n /**\n * @inheritdoc\n */\n public function syncAccounts(Carbon $since, ?Carbon $to = null): int\n {\n $syncCount = 0;\n $fields = $this->getAllFieldsAsArray('account');\n\n if (\\in_array('Id', $fields, true) === false) {\n return $syncCount;\n }\n\n $query = '\n SELECT ' . rtrim(implode(',', $fields), ',') . '\n FROM Account\n WHERE LastModifiedDate > :since\n ORDER BY LastModifiedDate ASC';\n\n try {\n $sfAccounts = $this->queryHandler->query($query, [\n 'since' => $since->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($sfAccounts as $sfAccount) {\n // Only sync if previously imported.\n if ($this->hasAccount($sfAccount['Id'])) {\n $this->importAccount($sfAccount);\n $syncCount++;\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::ACCOUNT);\n\n return $syncCount;\n }\n\n /**\n * @inheritdoc\n */\n public function syncAccount(string $crmId): ?Account\n {\n $fields = $this->getAllFieldsAsArray('account');\n if (! in_array('Id', $fields, true)) {\n $this->logger->info('[Salesforce] Sync account cancelled. Fields are not available.', [\n 'crmId' => $crmId,\n 'userId' => $this->profile->getUserId(),\n ]);\n\n return null;\n }\n\n $sfAccount = $this->getRecord('Account', $crmId, $fields);\n\n return $this->importAccount($sfAccount);\n }\n\n private function importAccount($crmData): ?Account\n {\n if (! empty($crmData['IsDeleted'])) {\n $this->handleEntityDeletionByProviderId($this->config->accounts(), $crmData);\n\n return null;\n }\n\n $countryCode = $crmData['BillingCountryCode'] ?? $crmData['ShippingCountryCode'] ?? null;\n\n // Salesforce allows custom \"countries\" to be created. Disregard these.\n if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {\n $countryCode = null;\n }\n\n // If we have no country code, try to parse it from the country names.\n if ($countryCode === null && empty($crmData['BillingCountry']) === false) {\n $countryCode = $this->convertCountryNameToCode($crmData['BillingCountry']);\n }\n\n if ($countryCode === null && empty($crmData['ShippingCountry']) === false) {\n $countryCode = $this->convertCountryNameToCode($crmData['ShippingCountry']);\n }\n\n if (empty($crmData['Phone']) === false) {\n // Trim to our width and attempt to parse it.\n $number = mb_strimwidth($crmData['Phone'], 0, 25);\n $parsedNumber = parsePhoneNumber($countryCode, $number);\n } else {\n $parsedNumber = [];\n }\n\n $industry = null;\n if (empty($crmData['Industry']) === false) {\n $industry = mb_strimwidth($crmData['Industry'], 0, 40);\n }\n\n $domain = null;\n if (empty($crmData['Website']) === false) {\n $domain = mb_strimwidth($crmData['Website'], 0, 191);\n $domain = StringUtil::resolveDomain($domain);\n }\n\n $createdDate = null;\n if (empty($crmData['CreatedDate']) === false) {\n $createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n }\n\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $data = [\n 'team_id' => $this->team->id,\n 'user_id' => $profile?->user_id,\n 'owner_id' => $crmData['OwnerId'],\n 'name' => mb_strimwidth($crmData['Name'], 0, 191),\n 'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(\n crmConfiguration: $this->config,\n crmProviderId: $crmData['Id'],\n modelType: Account::class,\n fileName: $crmData['Id'],\n avatarText: $crmData['Name']\n ),\n 'industry' => $industry,\n 'domain' => $domain,\n 'phone' => $parsedNumber['phone'] ?? null,\n 'ext' => $parsedNumber['ext'] ?? null,\n 'country_code' => $countryCode,\n 'remotely_created_at' => $createdDate,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->accounts(), $crmData['Id']);\n\n /** @var Account $account */\n $account = $this->config->accounts()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n $this->handleObjectDeletion($account, $crmData);\n\n return $account->trashed() ? null : $account;\n }\n\n /**\n * @inheritdoc\n */\n public function syncOpportunities(array $parameters, ?string $strategy = null): int\n {\n $strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);\n\n $syncCount = 0;\n $logParams = $parameters;\n $parameters['profile'] = $this->profile;\n $logParams['user'] = $this->profile->getUserId();\n\n if (count($strategies) > 1) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Multiple sync strategies used', [\n 'teamId' => $this->team->getUuid(),\n 'params' => $logParams,\n 'strategies_count' => count($strategies),\n ]);\n }\n\n foreach ($strategies as $syncStrategy) {\n $name = $syncStrategy->getStrategyName();\n\n try {\n $sfOpportunities = $syncStrategy->fetchOpportunities($parameters);\n $totalRecords = $sfOpportunities->count();\n\n foreach ($sfOpportunities as $sfOpportunity) {\n $this->importOpportunity($sfOpportunity);\n $syncCount++;\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n $this->logger->warning('[' . $this->getDisplayName() . '] No opportunities found', [\n 'teamId' => $this->team->getUuid(),\n 'name' => $name,\n 'params' => $logParams,\n 'reason' => $noResultsException->getMessage(),\n ]);\n } catch (CrmException $crmException) {\n // Nothing to sync.\n $this->logger->warning('[' . $this->getDisplayName() . '] Opportunity sync failed', [\n 'teamId' => $this->team->getUuid(),\n 'name' => $name,\n 'params' => $logParams,\n 'reason' => $crmException->getMessage(),\n ]);\n }\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::OPPORTUNITY, ['params' => $logParams]);\n\n // debug to see how if count of opportunities reaches 1000\n if ($syncCount >= 1000) {\n $this->logger->info(\n '[' . $this->getDisplayName() . '] Sync Opportunities - count warning',\n [\n 'team_id' => $this->team->getId(),\n 'params' => $logParams,\n 'count' => $syncCount,\n 'strategies_count' => count($strategies),\n 'total_records' => $totalRecords ?? null,\n ]\n );\n }\n\n return $syncCount;\n }\n\n\n /**\n * @inheritdoc\n */\n public function syncOpportunity(string $crmId): ?Opportunity\n {\n $strategy = $this->opportunitySyncStrategyResolver->resolve(\n $this->config,\n OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY\n );\n\n $parameters = [\n 'profile' => $this->profile,\n 'crm_id' => $crmId,\n ];\n\n try {\n $sfOpportunity = $strategy->fetchOpportunities($parameters);\n } catch (HttpNotFoundException $e) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [\n 'teamId' => $this->team->id_string,\n 'crmId' => $crmId,\n ]);\n\n return null;\n } catch (CrmException $crmException) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity sync failed', [\n 'teamId' => $this->team->id_string,\n 'crmId' => $crmId,\n 'exception' => $crmException->getMessage(),\n ]);\n\n return null;\n }\n\n if ($sfOpportunity instanceof ArrayIterator) {\n return $this->importOpportunity($sfOpportunity->getItems());\n }\n\n return $this->importOpportunity($sfOpportunity);\n }\n\n /**\n * @throws HttpNotFoundException\n */\n private function importOpportunity($crmData): ?Opportunity\n {\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $account = null;\n if (empty($crmData['AccountId']) === false) {\n /** @var ?Account $account */\n $account = $this->config->accounts()\n ->where('crm_provider_id', (string) $crmData['AccountId'])\n ->first();\n\n if ($account === null) {\n $account = $this->syncAccount($crmData['AccountId']);\n }\n }\n\n $userId = $profile?->getUserId() ?? $account?->getUserId();\n if ($userId === null) {\n $this->logger->error('[Salesforce] | Skip import, no user_id found', [\n 'id' => $crmData['Id'],\n ]);\n\n return null;\n }\n\n /** @var ?Stage $stage */\n $stage = null;\n if (isset($crmData['StageName'])) {\n $stage = $this->config\n ->stages()\n ->where('name', $crmData['StageName'])\n ->where('type', Stage::TYPE_OPPORTUNITY)\n ->orderBy('is_selectable', 'DESC')\n ->orderBy('id')\n ->first();\n\n if ($stage === null) {\n // Import it.\n $stage = $this->importStages([Stage::TYPE_OPPORTUNITY], $crmData['StageName']);\n }\n }\n\n $recordType = null;\n if (empty($crmData['RecordTypeId']) === false) {\n /** @var ?RecordType $recordType */\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $crmData['RecordTypeId'])\n ->first();\n }\n\n $createdDate = null;\n if (empty($crmData['CreatedDate']) === false) {\n $createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n }\n\n $closeDate = null;\n if (empty($crmData['CloseDate']) === false) {\n $closeDate = Carbon::parse($crmData['CloseDate'])->format('Y-m-d');\n }\n\n $valueFieldName = 'Amount';\n if ($this->config->opportunity_value_field_id) {\n $valueFieldName = $this->config->opportunityValueField->crm_provider_id;\n }\n\n $data = [\n 'team_id' => $this->team->id,\n 'account_id' => $account->id ?? null,\n 'user_id' => $userId,\n 'owner_id' => $crmData['OwnerId'] ?? null,\n 'name' => mb_strimwidth($crmData['Name'] ?? '', 0, 128),\n 'value' => $crmData[$valueFieldName],\n 'currency_code' => CurrencyFormatter::formatCode($crmData['CurrencyIsoCode'] ?? null),\n 'close_date' => $closeDate,\n 'is_closed' => $crmData['IsClosed'],\n 'is_won' => $crmData['IsWon'],\n 'stage_id' => $stage?->id ?? null,\n 'record_type_id' => $recordType->id ?? null,\n 'remotely_created_at' => $createdDate,\n 'probability' => $crmData['Probability'] ?? null,\n 'forecast_category' => $crmData['ForecastCategoryName'] ?? null,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->opportunities(), $crmData['Id']);\n\n // Do not allow locked DB tables & other errors\n // to interrupt the process of reverting the trashed opportunities\n try {\n /** @var Opportunity $opportunity */\n $opportunity = $this->config->opportunities()\n ->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n // import external fields into crm_field_data if present\n $crmFields = $this->getOpportunitySyncableFields();\n\n $this->importOpportunityCrmFieldData($crmData, $crmFields, $opportunity->id);\n\n $this->handleObjectDeletion($opportunity, $crmData);\n\n if ($opportunity->trashed()) {\n return null;\n }\n\n if ($opportunity->wasRecentlyCreated) {\n MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());\n }\n\n return $opportunity;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->error('[Salesforce] importOpportunity failure.', [\n 'crm_provider_id' => $crmData['Id'],\n 'team_id' => $this->team->id,\n 'exception' => $exception->getMessage(),\n ]);\n\n $this->handleEntityDeletionByProviderId($this->config->opportunities(), $crmData);\n }\n\n return null;\n }\n\n /**\n * @inheritdoc\n */\n public function syncContacts(Carbon $since, ?Carbon $to = null): int\n {\n $syncCount = 0;\n $fields = $this->getAllFieldsAsArray('contact');\n if (\\in_array('Id', $fields, true) === false) {\n return $syncCount;\n }\n\n $query = '\n SELECT ' . rtrim(implode(',', $fields), ',') . '\n FROM Contact\n WHERE LastModifiedDate > :since\n ORDER BY LastModifiedDate ASC';\n\n try {\n $sfContacts = $this->queryHandler->query($query, [\n 'since' => $since->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($sfContacts as $sfContact) {\n // Only sync if previously imported.\n if ($this->hasContact($sfContact['Id'])) {\n $this->importContact($sfContact);\n $syncCount++;\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::CONTACT);\n\n return $syncCount;\n }\n\n /**\n * @inheritdoc\n */\n public function syncContact(string $crmId): ?Contact\n {\n $fields = $this->getAllFieldsAsArray('contact');\n if (! in_array('Id', $fields, true)) {\n $this->logger->info('[Salesforce] Sync contact cancelled. Fields are not available.', [\n 'crmId' => $crmId,\n 'userId' => $this->profile->getUserId(),\n ]);\n\n return null;\n }\n\n $sfContact = $this->getRecord('Contact', $crmId, $fields);\n\n return $this->importContact($sfContact);\n }\n\n private function importContact($crmData): ?Contact\n {\n if (! empty($crmData['IsDeleted'])) {\n $this->handleEntityDeletionByProviderId($this->config->contacts(), $crmData);\n\n return null;\n }\n\n $account = $this->resolveContactAccount($crmData);\n $countryCode = $this->resolveContactCountryCode($crmData, $account);\n [$parsedNumber, $ext] = $this->parseContactPhone($countryCode, $crmData);\n $mobileNumber = $this->parseContactMobile($countryCode, $crmData);\n $createdDate = empty($crmData['CreatedDate'])\n ? null\n : Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $data = [\n 'team_id' => $this->team->id,\n 'account_id' => $account->id ?? null,\n 'user_id' => $profile?->user_id,\n 'owner_id' => $crmData['OwnerId'] ?? null,\n 'name' => ($crmData['Name'] ?? null) !== null ? mb_strimwidth($crmData['Name'], 0, 100) : '',\n 'title' => ($crmData['Title'] ?? null) !== null ? mb_strimwidth($crmData['Title'], 0, 128) : null,\n 'email' => ($crmData['Email'] ?? null) !== null ? mb_strimwidth($crmData['Email'], 0, 191) : null,\n 'country_code' => $countryCode,\n 'phone' => $parsedNumber['phone'] ?? null,\n 'ext' => $ext,\n 'mobile_phone' => $mobileNumber,\n 'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(\n crmConfiguration: $this->config,\n crmProviderId: $crmData['Id'],\n modelType: Contact::class,\n fileName: $crmData['Id'],\n avatarText: $crmData['Name']\n ),\n 'remotely_created_at' => $createdDate,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->contacts(), $crmData['Id']);\n\n /** @var Contact $contact */\n $contact = $this->config->contacts()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n $this->handleObjectDeletion($contact, $crmData);\n\n return $contact->trashed() ? null : $contact;\n }\n\n private function resolveContactAccount(array $crmData): ?Account\n {\n if (! isset($crmData['AccountId'])) {\n return null;\n }\n\n return $this->config->accounts()\n ->where('crm_provider_id', (string) $crmData['AccountId'])\n ->first() ?? $this->syncAccount($crmData['AccountId']);\n }\n\n private function resolveContactCountryCode(array $crmData, ?Account $account): ?string\n {\n $countryCode = $crmData['MailingCountryCode'] ?? null;\n\n if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {\n $countryCode = null;\n }\n\n if ($countryCode === null && empty($crmData['MailingCountry']) === false) {\n $countryCode = $this->convertCountryNameToCode($crmData['MailingCountry'])\n ?? ($account?->country_code);\n }\n\n return $countryCode;\n }\n\n private function parseContactPhone(?string $countryCode, array $crmData): array\n {\n if (empty($crmData['Phone'])) {\n return [[], null];\n }\n\n $parsedNumber = parsePhoneNumber($countryCode, Str::limit($crmData['Phone'], 25, ''));\n $ext = empty($parsedNumber['ext']) ? null : Str::limit($parsedNumber['ext'], 10, '');\n\n return [$parsedNumber, $ext];\n }\n\n private function parseContactMobile(?string $countryCode, array $crmData): ?string\n {\n if (empty($crmData['MobilePhone'])) {\n return null;\n }\n\n return Str::limit(phone_e164($countryCode, $crmData['MobilePhone']), 25, '');\n }\n\n /**\n * @inheritdoc\n */\n public function syncOrganization(): void\n {\n $fields = [\n 'InstanceName',\n 'OrganizationType',\n 'IsSandbox',\n ];\n\n $orgValues = $this->getRecord('Organization', $this->config->crm_provider_id, $fields);\n\n $edition = null;\n switch ($orgValues['OrganizationType']) {\n case 'Developer Edition':\n $edition = Configuration::EDITION_DEVELOPER;\n\n break;\n\n case 'Professional Edition':\n $edition = Configuration::EDITION_PROFESSIONAL;\n\n break;\n\n case 'Enterprise Edition':\n $edition = Configuration::EDITION_ENTERPRISE;\n\n break;\n }\n\n $this->config->edition = $edition;\n $this->config->instance = $orgValues['InstanceName'];\n\n // XXX: How can this state be possible?\n if ($this->config->version === null) {\n $this->config->version = Client::MIN_API_VERSION;\n }\n\n $installedVersion = $this->getInstalledAppVersion();\n if ($installedVersion !== null) {\n $installedVersion = (string) $this->getInstalledAppVersion();\n }\n\n $this->config->installed_app_version = $installedVersion;\n\n $this->config->save();\n }\n\n public function getInstalledAppVersion(): ?string\n {\n try {\n $query = '\n SELECT\n SubscriberPackageVersion.MajorVersion,\n SubscriberPackageVersion.MinorVersion,\n SubscriberPackageVersion.PatchVersion,\n SubscriberPackageVersion.BuildNumber\n FROM\n InstalledSubscriberPackage\n WHERE\n SubscriberPackageId = :packageId\n ';\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'packageId' => self::INSTALLED_PACKAGE_ID,\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n // Grab version number.\n $version = $sfField['SubscriberPackageVersion']['MajorVersion'] .\n $sfField['SubscriberPackageVersion']['MinorVersion'] .\n $sfField['SubscriberPackageVersion']['PatchVersion'] .\n $sfField['SubscriberPackageVersion']['BuildNumber'];\n } catch (\\Exception) {\n $version = null;\n }\n\n return $version;\n }\n\n /**\n * Store transcripts as note.\n *\n * @throws \\Exception\n */\n public function createTranscriptNotes(Activity $activity): void\n {\n // For SF we also check if Log Notes is enabled.\n if ($this->profile->log_notes === Profile::LOG_NOTE_NONE) {\n return;\n }\n\n if ($activity->opportunity_id && $activity->prospect === null) {\n return;\n }\n\n try {\n $transcriptionData = $this->generateTranscription($activity);\n\n $noteMaxLength = $this->profile->log_notes === Profile::LOG_NOTE_ENHANCED\n ? self::ENHANCED_NOTE_MAX_LENGTH\n : self::CLASSIC_NOTE_MAX_LENGTH;\n\n $title = 'Transcript for ';\n $title .= $activity->title ?? $activity->activity_title;\n\n // Truncate Notes with max notes length because transcription text could be very long.\n $body = mb_strimwidth($transcriptionData, 0, $noteMaxLength);\n\n if ($activity->opportunity_id) {\n $objectId = $activity->opportunity->crm_provider_id;\n } else {\n $objectId = $activity->prospect->crm_provider_id;\n }\n\n $noteId = $this->saveNote($title, $body, $objectId);\n\n // Store crm logged id in transcription.\n $transcription = $activity->getTranscription();\n $transcription->crm_activity_id = $noteId;\n $transcription->save();\n } catch (\\Exception $e) {\n \\Sentry::captureException($e);\n }\n }\n\n public function saveNote(string $title, string $body, string $objectId, ?NoteObject $noteObject = null): ?string\n {\n $noteId = null;\n\n try {\n if ($this->profile->log_notes === Profile::LOG_NOTE_ENHANCED) {\n $noteId = $this->buildEnhancedNote($title, $body, $objectId);\n } else {\n $noteId = $this->buildClassicNote($title, $body, $objectId);\n }\n } catch (HttpNotFoundException $exception) {\n // The profile not having access to create Enhanced Notes. Set their preference to Classic.\n if ($this->profile->log_notes === Profile::LOG_NOTE_ENHANCED) {\n $this->profile->update([\n 'log_notes' => Profile::LOG_NOTE_CLASSIC,\n ]);\n }\n }\n\n return $noteId;\n }\n\n /**\n * This is using the \"Enhanced\" Notes feature, NOT the \"Notes & Attachments\" feature being deprecated.\n *\n * @url https://salesforce.stackexchange.com/questions/104408/how-can-i-create-an-account-note-or-contact-note-via-api-that-is-visible-in-sale\n */\n private function buildEnhancedNote(string $title, string $body, string $objectId): string\n {\n // Decode stored entities, escape HTML (without quoting), then convert line breaks for Salesforce formatting\n $decodedBody = html_entity_decode($body, ENT_QUOTES | ENT_HTML5);\n $sanitizedBody = htmlspecialchars($decodedBody, ENT_NOQUOTES, 'UTF-8', false);\n $content = nl2br($sanitizedBody, false);\n $note = [\n 'OwnerId' => $this->profile->crm_provider_id,\n 'Title' => $title,\n 'Content' => base64_encode($content),\n ];\n\n $noteId = $this->createRecord('ContentNote', $note);\n\n $link = [\n 'ContentDocumentId' => $noteId,\n 'LinkedEntityId' => $objectId,\n 'ShareType' => 'I',\n ];\n\n $this->createRecord('ContentDocumentLink', $link);\n\n return $noteId;\n }\n\n private function buildClassicNote(string $title, string $body, string $objectId): string\n {\n if (in_array($this->parseObjectType($objectId), [Field::OBJECT_TASK, Field::OBJECT_EVENT])) {\n $this->logger->info('[Salesforce] Summary not sent', [\n 'profile_id' => $this->profile->id,\n 'objectId' => $objectId,\n 'reason' => 'Classical Note does not support Task/Event relation',\n ]);\n\n return '';\n }\n\n $titleTrimmed = null;\n\n if (mb_strlen($title) > 80) {\n $titleTrimmed = substr($title, 0, 77) . '...';\n }\n $payload = [\n 'OwnerId' => $this->profile->crm_provider_id,\n 'IsPrivate' => false,\n 'Title' => $titleTrimmed ?? $title,\n 'Body' => $titleTrimmed ? $title . PHP_EOL . $body : $body,\n 'ParentId' => $objectId,\n ];\n\n return $this->createRecord('Note', $payload);\n }\n\n /**\n * @inheritdoc\n */\n public function find(string $name, array $scopes): array\n {\n if ($this->profile === null) {\n return [];\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $limitValues = ['limit' => $this->limit, 'offset' => $this->offset];\n $sosl = $queryBuilder->buildFindQuery($name, $scopes, $limitValues);\n\n $this->logger->info('[Salesforce] Find prospects', [\n 'profile_id' => $this->profile->id,\n 'sosl_query' => $sosl,\n 'search_string' => $name,\n 'scopes' => $scopes,\n ]);\n\n $data = Cache::remember($this->profile->id . $sosl, self::CACHE_TTL, function () use ($sosl) {\n $data = [];\n\n try {\n // Hit remote API.\n $objects = $this->queryHandler->search($sosl);\n\n // Build mapped list.\n foreach ($objects as $object) {\n $type = strtolower($object['attributes']['type']);\n\n $record = [\n 'crmId' => $object['Id'],\n 'name' => $object['Name'],\n 'prospectType' => $type,\n 'phoneNumbers' => [],\n 'crmUrl' => $this->generateProviderUrl($object['Id'], $type),\n ];\n\n switch ($type) {\n case 'lead':\n if (empty($object['Company']) === false) {\n $record['organization'] = $object['Company'];\n }\n\n if (empty($object['Title']) === false) {\n $record['title'] = $object['Title'];\n }\n\n $stage = $this->config->stages()\n ->where('type', Stage::TYPE_LEAD)\n ->where('name', $object['Status'])\n ->first();\n\n // Lazy create the stage.\n if ($stage === null) {\n $stage = $this->importStages([Stage::TYPE_LEAD], $object['Status']);\n }\n\n if ($stage) {\n $record += [\n 'stage' => [\n 'id' => $stage->id_string,\n 'name' => $stage->name,\n ],\n ];\n }\n\n if (empty($object['RecordTypeId']) === false) {\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $object['RecordTypeId'])\n ->first();\n\n if ($recordType) {\n $record += [\n 'recordType' => [\n 'id' => $recordType->id_string,\n 'name' => $recordType->name,\n ],\n ];\n }\n }\n\n break;\n\n case 'account':\n if (empty($object['Industry']) === false) {\n $record['industry'] = $object['Industry'];\n $record['detailsLine'] = $object['Industry'];\n }\n if (! empty($object['PersonEmail'])) {\n $record['detailsLine'] = $object['PersonEmail'];\n }\n\n break;\n\n case 'contact':\n // For contacts, we should try and fetch their account name too.\n if ($object['AccountId']) {\n // Cheaper to get this locally.\n $account = $this->config->accounts()\n ->where('crm_provider_id', $object['AccountId'])\n ->first(['name']);\n\n if ($account) {\n $record['organization'] = $account->name;\n }\n }\n\n if (! empty($object['IsPersonAccount']) && $object['Email']) {\n $record['detailsLine'] = $object['Email'];\n } else {\n if (empty($object['Title']) === false) {\n $record['title'] = $object['Title'];\n }\n }\n\n break;\n }\n\n // Add phone numbers to record.\n if (empty($object['Phone']) === false && $object['Phone']) {\n $record['phoneNumbers'][] = [\n 'number' => $object['Phone'],\n 'nationalFormat' => phone_national($this->profile->user->country_code, $object['Phone']),\n 'type' => 'phone',\n ];\n }\n\n if (empty($object['MobilePhone']) === false && $object['MobilePhone']) {\n $record['phoneNumbers'][] = [\n 'number' => $object['MobilePhone'],\n 'nationalFormat' => phone_national(\n $this->profile->user->country_code,\n $object['MobilePhone']\n ),\n 'type' => 'mobile',\n ];\n }\n\n $data[] = $record;\n }\n } catch (NoResultsException $e) {\n $data = [];\n }\n\n return $data;\n });\n\n return $data;\n }\n\n /**\n * @inheritdoc\n */\n public function findOpportunities(?string $crmAccountId, ?string $crmContactId, ?int $userId = null): array\n {\n $data = [];\n $ownerData = [];\n $ownerId = null;\n\n if ($crmAccountId === null) {\n return $data;\n }\n\n if ($userId) {\n $profileRepository = app(ProfileRepository::class);\n $profile = $profileRepository->findProfileByUserId($this->config, $userId);\n\n $ownerId = $profile instanceof Profile ? $profile->getCrmProviderId() : null;\n }\n\n try {\n // Perhaps their profile has no opportunity permissions.\n if ($this->profile === null || $this->profile->opportunity_fields === null) {\n return $data;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $query = $queryBuilder->buildFindOpportunitiesQuery();\n\n $objects = $this->queryHandler->query($query, ['accountId' => $crmAccountId]);\n\n foreach ($objects as $object) {\n $record = [\n 'crmId' => $object['Id'],\n 'name' => $object['Name'],\n 'won' => $object['IsWon'],\n 'closed' => $object['IsClosed'],\n ];\n\n $valueFieldName = 'Amount';\n if ($this->config->opportunity_value_field_id) {\n $valueFieldName = $this->config->opportunityValueField->crm_provider_id;\n }\n\n if (empty($object[$valueFieldName]) === false) {\n $currency = $object['CurrencyIsoCode'] ?? $this->config->default_currency;\n $value = formatCurrency($object[$valueFieldName], $currency);\n\n $record += [\n 'value' => $value,\n ];\n }\n\n $stage = $this->config->stages()\n ->where('type', Stage::TYPE_OPPORTUNITY)\n ->where('name', $object['StageName'])\n ->first();\n\n // Lazy create the stage.\n if ($stage === null) {\n $stage = $this->importStages([Stage::TYPE_OPPORTUNITY], $object['StageName']);\n }\n\n $record += [\n 'stage' => [\n 'id' => $stage->id_string,\n 'name' => $stage->name,\n ],\n ];\n\n if (empty($object['RecordTypeId']) === false) {\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $object['RecordTypeId'])\n ->first();\n\n if ($recordType) {\n $record += [\n 'recordType' => [\n 'id' => $recordType->id_string,\n 'name' => $recordType->name,\n ],\n ];\n }\n }\n\n if ($ownerId && isset($object['OwnerId']) && $object['OwnerId'] === $ownerId) {\n $ownerData[] = $record;\n }\n\n $data[] = $record;\n }\n } catch (NoResultsException $e) {\n return $data;\n }\n\n if (! empty($ownerData)) {\n return $ownerData;\n }\n\n return $data;\n }\n\n public function getContactRolesFromCrm(?Carbon $since = null): array\n {\n $roles = [];\n\n if ($this->profile === null) {\n return $roles;\n }\n\n $queryBuilder = app(QueryBuilder::class, ['profile' => $this->profile]);\n\n $query = $queryBuilder->buildGetContactRolesQuery($since);\n\n try {\n $objects = $this->queryHandler->query($query);\n\n foreach ($objects as $object) {\n $roles[] = [\n 'id' => $object['Id'],\n 'contactId' => $object['ContactId'],\n 'opportunityId' => $object['OpportunityId'],\n 'ownerId' => $object['Opportunity']['OwnerId'] ?? null,\n 'isPrimary' => $object['IsPrimary'],\n 'role' => $object['Role'],\n ];\n }\n } catch (NoResultsException) {\n // Just return an empty array.\n $this->logger->info('[Salesforce] No contact roles found', [\n 'since' => $since?->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n }\n\n return $roles;\n }\n\n public function syncContactRoles(Carbon $since): int\n {\n $contactRoleRepository = app(ContactRoleRepository::class);\n\n $crmContactRoles = $this->getContactRolesFromCrm(since: $since);\n $syncCount = 0;\n $contactRoles = [];\n\n foreach ($crmContactRoles as $crmContactRole) {\n $contactRoles[] = $this->importContactRole($crmContactRole);\n $syncCount++;\n }\n\n $contactRoleRepository->saveContactRoles($contactRoles);\n\n $this->syncRemotelyDeletedContactRoles();\n\n return $syncCount;\n }\n\n private function importContactRole(array $contactRole): array\n {\n $contact = $this->config->contacts()\n ->where('crm_provider_id', $contactRole['contactId'])\n ->first();\n\n if ($contact === null) {\n $contact = $this->syncContact($contactRole['contactId']);\n }\n\n $opportunity = $this->config->opportunities()\n ->where('crm_provider_id', $contactRole['opportunityId'])\n ->first();\n\n if ($opportunity === null) {\n $opportunity = $this->syncOpportunity($contactRole['opportunityId']);\n }\n\n $role = null;\n if (! empty($contactRole['role'])) {\n $role = mb_strimwidth($contactRole['role'], 0, 191);\n }\n\n return [\n 'crm_configuration_id' => $this->config->getId(),\n 'contact_id' => $contact->getId(),\n 'crm_provider_id' => $contactRole['id'],\n 'subject_type' => ContactRole::SUBJECT_TYPE_OPPORTUNITY,\n 'subject_id' => $opportunity->getId(),\n 'is_primary' => $contactRole['isPrimary'],\n 'role' => $role,\n ];\n }\n\n protected function syncRemotelyDeletedContactRoles(): bool\n {\n try {\n $deletedRemotely = $this->queryHandler->queryDeleted('OpportunityContactRole');\n } catch (NoResultsException $e) {\n return false;\n }\n\n $deletedOpportunities = $deletedRemotely->getResults();\n $deletedIds = array_column($deletedOpportunities, 'id');\n\n $contactRoleRepository = app(ContactRoleRepository::class);\n\n foreach (array_chunk($deletedIds, self::HARD_DELETE_CHUNK) as $chunk) {\n $contactRoleRepository->deleteContactRoles($chunk);\n\n $this->logger->info('[' . $this->getDisplayName() . '] Remotely deleted opportunities synced', [\n 'teamId' => $this->team->id_string,\n 'remotelyDeletedOpportunities' => $chunk,\n 'count' => count($chunk),\n ]);\n }\n\n return true;\n }\n\n /**\n * @inheritdoc\n */\n public function getTasks(string $objectType, string $objectId, ?string $opportunityId): array\n {\n $data = $objects = [];\n\n $hasWho = \\in_array($objectType, ['lead', 'contact']);\n $playbook = $this->getPlaybook($this->profile->user);\n $fields = array_merge(\n $this->profile->getFieldsAsArray(parent::OBJECT_TASK),\n $playbook && $playbook->activityField ? [$playbook->activityField->crm_provider_id] : []\n );\n\n // Query should default to any open call for that user.\n $query = '\n SELECT ' . implode(',', array_unique($fields)) . '\n FROM Task\n WHERE OwnerId = :ownerId\n AND IsArchived = false\n AND IsDeleted = false\n AND IsClosed = false\n AND (';\n\n if ($objectType === 'account') {\n // This covers tasks tied to a related contact or opportunity too.\n $query .= '\n AccountId = :accountId';\n }\n\n if ($hasWho) {\n $query .= '\n WhoId = :whoId';\n\n // If we are also going to check on a specific opportunity, set that up.\n if ($opportunityId) {\n $query .= ' OR WhatId = :whatId';\n }\n }\n\n $query .= ' ) ORDER BY LastModifiedDate DESC';\n\n try {\n $objects = $this->queryHandler->query($query, [\n 'ownerId' => $this->profile->crm_provider_id,\n 'whoId' => $objectId,\n 'whatId' => $opportunityId,\n 'accountId' => $objectId,\n ]);\n } catch (NoResultsException $e) {\n return $data;\n } finally {\n $this->logger->debug(sprintf('[Salesforce] Found %s tasks for query \"%s\"', count($objects), $query));\n }\n\n foreach ($objects as $object) {\n $dueDate = $object['ActivityDate'] ? Carbon::parse($object['ActivityDate'])->toIso8601String() : null;\n $data[] = [\n 'crmId' => $object['Id'],\n 'subject' => $object['Subject'],\n 'due' => $dueDate,\n 'type' => $object[$playbook->activityField->crm_provider_id],\n ];\n }\n\n return $data;\n }\n\n /**\n * @inheritdoc\n */\n public function getEvents(string $objectType, string $objectId, ?string $opportunityId): array\n {\n $data = $objects = [];\n $user = $this->profile?->user;\n if ($this->profile === null || $user === null) {\n return $data;\n }\n\n $hasWho = \\in_array($objectType, ['lead', 'contact']);\n $playbook = $this->getPlaybook($user);\n $fields = array_merge(\n $this->profile->getFieldsAsArray(parent::OBJECT_EVENT),\n $playbook && $playbook->activityField ? [$playbook->activityField->crm_provider_id] : []\n );\n\n // Query should default to any event starting in the last week and ending up until today owned by the user.\n $query = '\n SELECT ' . implode(',', array_unique($fields)) . '\n FROM Event\n WHERE OwnerId = :ownerId\n AND IsArchived = false\n AND IsAllDayEvent = false\n AND StartDateTime >= LAST_N_DAYS:7\n AND EndDateTime <= TODAY\n AND (';\n\n if ($objectType === 'account') {\n // This covers events tied to a related contact or opportunity too.\n $query .= '\n AccountId = :accountId';\n }\n\n if ($hasWho) {\n $query .= '\n WhoId = :whoId';\n\n // If we are also going to check on a specific opportunity, set that up.\n if ($opportunityId) {\n $query .= ' OR WhatId = :whatId';\n }\n }\n\n $query .= ' ) ORDER BY LastModifiedDate DESC';\n\n try {\n $objects = $this->queryHandler->query($query, [\n 'ownerId' => $this->profile->crm_provider_id,\n 'whoId' => $objectId,\n 'whatId' => $opportunityId,\n 'accountId' => $objectId,\n ]);\n } catch (NoResultsException $e) {\n return $data;\n } finally {\n $this->logger->debug(sprintf('[Salesforce] Found %s tasks for query \"%s\"', count($objects), $query));\n }\n\n foreach ($objects as $object) {\n $dueDate = $object['StartDateTime'] ? Carbon::parse($object['StartDateTime'])->toIso8601String() : null;\n\n $data[] = [\n 'crmId' => $object['Id'],\n 'subject' => $object['Subject'],\n 'due' => $dueDate,\n 'type' => $object[$playbook->activityField->crm_provider_id],\n ];\n }\n\n return $data;\n }\n\n /**\n * Try to find CRM Objects using email address\n *\n * @return null|array{\n * Lead|null,\n * Account|null,\n * Opportunity|null,\n * Contact|null,\n * Stage|null,\n * string|null\n * }\n */\n public function matchExactlyByEmail(string $email, ?int $userId = null): ?array\n {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $sosl = $queryBuilder->buildMatchByQuery($email, Field::TYPE_EMAIL);\n if ($sosl === null) {\n return null;\n }\n\n try {\n $objects = $this->queryHandler->search($sosl);\n $objects = $this->queryHandler->prioritiseResults(\n $objects,\n $email,\n QueryHandler::PRIORITISE_EMAIL\n );\n\n $data = $this->convertCrmData($objects, $userId);\n\n return ! empty(array_filter($data)) ? $data : null;\n } catch (NoResultsException $e) {\n // Try the account next.\n if ($this->profile->account_fields === null) {\n return null;\n }\n }\n\n return null;\n }\n\n public function getDomain(string $email): ?string\n {\n // SF improved search - strip the domain extension, min domain name length 4\n return $this->getCompanyNameFromEmail(email: $email, minNameLength: 4);\n }\n\n /**\n * Try to find CRM objects using domain name of the email address\n *\n * @return null|array{\n * Lead|null,\n * Account|null,\n * Opportunity|null,\n * Contact|null,\n * Stage|null,\n * string|null\n * }\n */\n public function matchByDomain(string $domain, ?int $userId = null): ?array\n {\n $companyName = $domain;\n\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $sosl = $queryBuilder->buildMatchByDomainQuery($companyName);\n\n try {\n $objects = $this->queryHandler->search($sosl);\n\n $data = $this->convertCrmData($objects, $userId);\n\n return ! empty(array_filter($data)) ? $data : null;\n } catch (NoResultsException) {\n return null;\n }\n }\n\n public function matchByPhone(string $phone, ?string $rawPhoneNumber = null, ?int $userId = null): ?array\n {\n // Don't bother looking up numbers that are masked.\n if (str_contains($phone, '**')) {\n return null;\n }\n\n if ($this->isPhoneNumberOfTeamMember($phone)) {\n return null;\n }\n\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $phoneNational = phone_national(null, $phone) ?? '';\n $possiblePhoneFormats = collect([\n preg_replace('/\\D/', '', ltrim($phone, '0+')),\n preg_replace('/\\D/', '', $phoneNational),\n formatDashPhoneNumber($phone),\n $phoneNational,\n ])\n ->filter() // Removes null and empty strings\n ->unique()\n ->values();\n\n foreach ($possiblePhoneFormats as $phone) {\n $sosl = $queryBuilder->buildMatchByQuery($phone, Field::TYPE_PHONE);\n if ($sosl === null) {\n continue;\n }\n\n try {\n $objects = $this->queryHandler->search($sosl);\n $objects = $this->queryHandler->prioritiseResults(\n $objects,\n $phone,\n QueryHandler::PRIORITISE_PHONE\n );\n\n return $this->convertCrmData($objects, $userId);\n } catch (NoResultsException) {\n continue;\n }\n }\n\n return null;\n }\n\n private function isPhoneNumberOfTeamMember(string $phone): bool\n {\n $teamRepository = app(TeamRepository::class);\n $user = $teamRepository->findTeamMemberByPhone($this->team, $phone);\n\n if ($user instanceof User) {\n return true;\n }\n\n return false;\n }\n\n protected function getCacheKey(string $object, ?int $userId = null): ?string\n {\n $key = $this->profile->id . $object;\n $keySuffix = $this->getOwnerKeySuffix($userId);\n\n return $key . $keySuffix;\n }\n\n private function getOwnerKeySuffix(?int $userId = null): string\n {\n return $userId === null ? '' : (string) $userId;\n }\n\n /** Determine the CRM Objects which represent the call activity. */\n public function matchByName(string $name, ?int $userId = null): ?array\n {\n // Don't waste time searching for single character strings.\n if (\\strlen($name) <= 1) {\n return null;\n }\n\n if ($this->profile === null) {\n return null;\n }\n\n $cacheKey = $this->getCacheKey($name, $userId);\n\n $result = Cache::remember($cacheKey, 60, function () use ($name, $userId) {\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $sosl = $queryBuilder->buildMatchByQuery($name, 'name');\n if ($sosl === null) {\n return false;\n }\n\n try {\n $objects = $this->queryHandler->search($sosl);\n } catch (NoResultsException $e) {\n return false;\n }\n\n $objects = $this->queryHandler->prioritiseResults(\n $objects,\n $name,\n QueryHandler::PRIORITISE_NAME\n );\n\n $data = $this->convertCrmData($objects, $userId);\n\n return (! empty(array_filter($data))) ? $data : false;\n });\n\n return is_array($result) ? $result : null;\n }\n\n /**\n * @return array{\n * Lead|null,\n * Account|null,\n * Opportunity|null,\n * Contact|null,\n * Stage|null,\n * string|null\n * }\n */\n protected function convertCrmData(QueryIterator $objects, ?int $userId = null): array\n {\n $lead = null;\n $contact = null;\n $opportunity = null;\n $account = null;\n $stage = null;\n $countryCode = null;\n\n if ($objects->count() > 0) {\n $object = $objects->current();\n\n if ($object['attributes']['type'] === 'Lead') {\n $lead = $this->importLead($object);\n\n // Lead might not be imported if the Stage is null for example.\n if ($lead) {\n $countryCode = $lead->country_code;\n $stage = $lead->stage;\n }\n } else {\n if ($object['attributes']['type'] === 'Contact') {\n $contact = $this->importContact($object);\n $account = $contact?->account;\n } else {\n $account = $this->importAccount($object);\n }\n\n if ($contact && $contact->country_code) {\n $countryCode = $contact->country_code;\n } elseif ($account) {\n $countryCode = $account->country_code;\n }\n\n try {\n $sfOpportunities = $this->findOpportunities(\n $account?->getCrmProviderId(),\n $contact?->getCrmProviderId(),\n $userId\n );\n\n // Take the first opportunity, which will be ordered as priority based on their settings.\n if (! empty($sfOpportunities)) {\n // Persist this remote object.\n $opportunity = $this->syncOpportunity($sfOpportunities[0]['crmId']);\n $stage = $opportunity?->stage;\n }\n } catch (Exception) {\n // Nothing to see here.\n }\n }\n }\n\n return [\n $lead,\n $account,\n $opportunity,\n $contact,\n $stage,\n $countryCode,\n ];\n }\n\n /**\n * @inheritdoc\n */\n public function updateStage($crmObject, Stage $stage): void\n {\n if ($stage->type === Stage::TYPE_LEAD) {\n $objectType = 'Lead';\n $objectId = $crmObject->crm_provider_id;\n $objectStageType = 'Status';\n } else {\n $objectType = 'Opportunity';\n $objectId = $crmObject->crm_provider_id;\n $objectStageType = 'StageName';\n }\n\n $headers = [];\n if ($this->config->trigger_assignment_rules === false) {\n // @see: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/headers_autoassign.htm\n $headers = [\n 'Sforce-Auto-Assign' => 'false',\n ];\n }\n\n $this->updateRecord($objectType, $objectId, [$objectStageType => $stage->name], $headers);\n }\n\n public function parseObjectType(string $objectId): string\n {\n if (Str::startsWith($objectId, '001')) {\n return 'account';\n }\n\n if (Str::startsWith($objectId, '003')) {\n return 'contact';\n }\n\n if (Str::startsWith($objectId, '00Q')) {\n return 'lead';\n }\n\n if (Str::startsWith($objectId, '006')) {\n return 'opportunity';\n }\n\n if (Str::startsWith($objectId, '00U')) {\n return 'event';\n }\n\n if (Str::startsWith($objectId, '00T')) {\n return 'task';\n }\n\n throw new \\InvalidArgumentException('Unsupported Object Type');\n }\n\n public function syncProfiles(?User $userToSearch = null): ?Profile\n {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, ['profile' => $this->profile]);\n $query = $queryBuilder->buildGetUsersQuery($userToSearch);\n\n try {\n $salesforceUsers = $this->queryHandler->query($query, [\n 'active' => true,\n ]);\n } catch (NoResultsException $e) {\n $this->logger->info('[Salesforce] Sync Profiles. No users found', [\n 'query' => $query,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $teamRepository = app(TeamRepository::class);\n $customRules = $this->getCustomProfileRules($teamRepository);\n\n foreach ($salesforceUsers as $crmUser) {\n if ($crmUser['Email'] === null) {\n continue;\n }\n\n if (! $this->customProfileValidation($crmUser, $customRules)) {\n continue;\n }\n\n $user = $teamRepository->findActiveTeamMemberByEmail($this->team, $crmUser['Email']);\n\n if (! $user instanceof User) {\n continue;\n }\n\n $edition = $crmUser['UserPreferencesLightningExperiencePreferred']\n ? Profile::EDITION_LIGHTNING\n : Profile::EDITION_CLASSIC;\n\n $profileRepository = app(ProfileRepository::class);\n $profile = $profileRepository->updateOrCreateProfile(\n $user,\n [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmUser['Id'],\n ],\n [\n 'user_id' => $user->getId(),\n 'edition' => $edition,\n 'has_external_cti' => ! empty($crmUser['CallCenterId']),\n 'crm_profile_id' => $crmUser['ProfileId'],\n ]\n );\n\n if ($userToSearch instanceof User && $userToSearch->getId() === $user->getId()) {\n return $profile;\n }\n }\n\n // Clean up inactive profiles\n try {\n $this->archiveInactiveProfiles();\n } catch (\\Exception $e) {\n $this->logger->warning('[Salesforce] Profile archiving failed', [\n 'teamId' => $this->team->getUuid(),\n 'reason' => $e->getMessage(),\n ]);\n }\n\n return null;\n }\n\n public function generateProviderUrl(string $providerId, string $objectType): ?string\n {\n $url = null;\n\n // For Salesforce it's easy, we just point every object to the apex domain and they handle it.\n switch ($objectType) {\n case 'lead':\n case 'account':\n case 'contact':\n case 'opportunity':\n case 'task':\n case 'event':\n case 'activity':\n\n $url = $this->config->crm_base_url . '/' . $providerId;\n\n break;\n }\n\n return $url;\n }\n\n public function buildTaskSearchFields(): array\n {\n return ['Id', 'WhoId', 'WhatId', 'AccountId'];\n }\n\n public function getTaskByFilterConditions(\n array $fields,\n array $filters,\n bool $bulkSearch = false,\n bool $strictFilters = true\n ): ?array {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $query = $queryBuilder->buildSearchTaskQuery($fields, $filters, $bulkSearch, $strictFilters);\n\n try {\n if (! $bulkSearch) {\n $objects = $this->queryHandler->query($query, $filters);\n if ($objects->count() === 1) {\n return $objects->current();\n }\n }\n\n if ($bulkSearch) {\n $objects = $this->queryHandler->query($query);\n $records = [];\n foreach ($objects as $record) {\n $key = $record[end($fields)];\n $records[$key] = $record;\n }\n\n return $records;\n }\n } catch (\\Exception $e) {\n $this->logger->info('[Salesforce] Failed to execute query', [\n 'query' => $query,\n 'error' => $e->getMessage(),\n ]);\n }\n\n return null;\n }\n\n public function mapCrmObjects(array $task): array\n {\n $activityData = [];\n\n if (! empty($task['WhoId'])) {\n $type = $this->parseObjectType($task['WhoId']);\n $activityData[$type] = $task['WhoId'];\n }\n if (! empty($task['AccountId'])) {\n $activityData['account'] = $task['AccountId'];\n }\n if (! empty($task['WhatId'])) {\n $activityData['opportunity'] = $task['WhatId'];\n }\n\n return $activityData;\n }\n\n /**\n * Get SF task by Outreach call id.\n */\n public function getTaskByFilter(\n string $activityFieldType,\n array $filters,\n string $operator = '=',\n array $additionalFields = []\n ): ?array {\n $data = [];\n\n try {\n // Default (base) fields.\n $fields = ['Id', 'Subject', 'Description', 'ActivityDate', 'WhoId', 'WhatId', $activityFieldType];\n\n foreach ($additionalFields as $additionalField) {\n $fields[] = $additionalField->crm_provider_id;\n }\n\n $fields = array_unique($fields);\n\n // Find task with the same Outreach id as the call id.\n $query = 'SELECT ' . implode(',', $fields) . '\n FROM Task\n WHERE IsArchived = false AND IsDeleted = false';\n\n foreach ($filters as $key => $value) {\n $key = preg_quote($key, '/');\n $key = str_replace(['\\'', '\"'], '', $key);\n // Prepare the substitution.\n $strKey = \":$key\";\n\n $query .= \" AND $key $operator $strKey\";\n }\n\n $query .= ' ORDER BY LastModifiedDate DESC LIMIT 1';\n\n $objects = $this->queryHandler->query($query, $filters);\n\n // There should be only one task related to this call if any.\n if ($objects->count() === 1) {\n $object = $objects->current();\n\n $dueDate = $object['ActivityDate'] ? Carbon::parse($object['ActivityDate'])->toIso8601String() : null;\n\n $data = array_merge($object, [\n 'crmId' => $object['Id'],\n 'subject' => $object['Subject'],\n 'summary' => $object['Description'],\n 'due' => $dueDate,\n 'Type' => $object[$activityFieldType],\n ]);\n }\n } catch (NoResultsException $e) {\n // Filters don't match any records.\n } catch (ServiceUnavailableException $serviceUnavailableException) {\n // Service cannot be queried. We should probably log this.\n }\n\n return $data;\n }\n\n /**\n * Get Salesforce fields including datetime fields\n *\n * @param $objectType\n */\n private function getAllFieldsAsArray($objectType): array\n {\n $basicFields = [];\n // Not all users have access to all object fields.\n if ($this->profile->{$objectType . '_fields'}) {\n $basicFields = explode(',', $this->profile->{$objectType . '_fields'});\n }\n\n $extraFields = [\n 'CreatedDate',\n 'LastModifiedDate',\n 'IsDeleted',\n ];\n\n if ($objectType === self::OBJECT_OPPORTUNITY\n && $this->config->opportunity_value_field_id\n && ! in_array($this->config->opportunityValueField->crm_provider_id, $basicFields)\n ) {\n $extraFields[] = $this->config->opportunityValueField->crm_provider_id;\n }\n\n return array_unique(array_merge($basicFields, $extraFields));\n }\n\n /**\n * Generate transcription for activity description.\n */\n private function generateTranscription(Activity $activity): string\n {\n if (! ($this->config->store_transcript)) {\n // If sending transcription to activity toggle is disabled\n return '';\n }\n\n return $this->transcriptionService\n ->findTranscriptionByActivity($activity)\n ->map(static function (array $transcriptionSegment): string {\n return $transcriptionSegment['formattedStartsAt'] . ' | ' . $transcriptionSegment['transcript'];\n })\n ->implode(PHP_EOL);\n }\n\n /**\n * Find related Salesforce event based on activity data\n *\n * @return array<string>\n */\n public function fetchRelatedActivity(Activity $activity): array\n {\n $this->logger->info('[Salesforce] Searching for related activity', [\n 'activityId' => $activity->getUuid(),\n 'ownerId' => $this->profile?->crm_provider_id,\n ]);\n\n $sfEvent = $this->fetchRelatedEvent($activity);\n if (empty($sfEvent)) {\n $this->logger->info('[Salesforce] No related activity found', [\n 'activityId' => $activity->getUuid(),\n 'ownerId' => $this->profile?->crm_provider_id,\n 'account' => $activity->hasAccount()\n ? $activity->getAccount()->getCrmProviderId()\n : null,\n ]);\n\n return [];\n }\n\n return $sfEvent;\n }\n\n public function fetchAndAssociateRelatedActivity(Activity $activity): ?Activity\n {\n if ($activity->isTypeConference() === false) {\n return null;\n }\n\n if ($activity->hasActualStartTime() === false && $activity->hasScheduledStartTime() === false) {\n return null;\n }\n\n if (! $activity->hasProspect()) {\n $this->logger->info('[Salesforce] Skip look up, Activity not linked to Lead, Contact or Account', [\n 'activityId' => $activity->getUuid(),\n ]);\n\n return null;\n }\n\n $playbook = $this->getPlaybook($activity->getUser());\n if ($playbook !== null && $playbook->getActivityType() === Playbook::ACTIVITY_TYPE_TASK) {\n $this->logger->info('[Salesforce] Skip auto-sync for task-based playbook', [\n 'activityUuid' => $activity->getUuid(),\n 'playbookId' => $playbook->getId(),\n 'playbookType' => $playbook->getActivityType(),\n ]);\n\n return null;\n }\n\n try {\n $sfEvent = $this->fetchRelatedActivity($activity);\n if (empty($sfEvent)) {\n return null;\n }\n\n [$activityField, $activityType] = $this->resolveActivityTypeFromEvent($activity, $sfEvent);\n\n $this->logger->info('[Salesforce] Found related activity', [\n 'activityId' => $activity->getUuid(),\n 'sfEvent' => $sfEvent['Id'],\n 'activityFieldName' => $activityField,\n 'crmActivityType' => ($activityField !== null && isset($sfEvent[$activityField]))\n ? $sfEvent[$activityField]\n : null,\n 'activityType' => $activityType,\n ]);\n\n $userId = $this->findRelatedActivityUserId($activity, $sfEvent);\n\n if ($activity->getUserId() !== $userId) {\n $this->logger->info('[Salesforce] Updating meeting owner', [\n 'activityId' => $activity->getUuid(),\n 'oldUserId' => $activity->getUserId(),\n 'newUserId' => $userId,\n ]);\n }\n\n $this->updateSfEventDescription($activity, $sfEvent);\n\n $activity->update([\n 'user_id' => $userId,\n 'crm_provider_id' => $sfEvent['Id'],\n 'playbook_category_id' => $activityType->id ?? $activity->getCategory()?->getId(),\n ]);\n\n $this->logger->info('[Salesforce] Activity updated', [\n 'activityId' => $activity->getUuid(),\n ]);\n\n return $activity;\n } catch (\\Exception $exception) {\n \\Sentry::captureException($exception);\n\n throw $exception;\n }\n }\n\n /**\n * @param array<string, mixed> $sfEvent\n *\n * @return array{0: string|null, 1: mixed}\n */\n private function resolveActivityTypeFromEvent(Activity $activity, array $sfEvent): array\n {\n $activityField = $this->getActivityFieldName($activity);\n $activityType = null;\n\n if ($activityField !== null && ! empty($sfEvent[$activityField])) {\n $playbook = $this->getPlaybook($activity->getUser());\n $activityType = $this->getPlaybookCategory($playbook, strval($sfEvent[$activityField]));\n }\n\n return [$activityField, $activityType];\n }\n\n /**\n * @param array<string> $sfEvent\n */\n private function findRelatedActivityUserId(Activity $activity, array $sfEvent): int\n {\n $userId = $activity->getUserId();\n\n if (empty($sfEvent['OwnerId']) === false) {\n $profile = $this\n ->config\n ->profiles()\n ->where('crm_provider_id', $sfEvent['OwnerId'])\n ->get()\n ->filter(static function (Profile $profile) use ($activity): bool {\n if (! $activity->isTypeConference()) {\n return ! empty($profile->user) ? $profile->user->isStatusActive() : false;\n }\n\n $participants = $activity->getParticipants();\n\n return ! empty($profile->user)\n ? $profile->user->isStatusActive()\n && $profile->user->hasPermission(PermissionEnum::RECORD_MEETING)\n && $participants->contains('user_id', $profile->user_id)\n : false;\n })\n ->first();\n\n if ($profile) {\n $userId = $profile->user_id;\n }\n }\n\n return $userId;\n }\n\n /**\n * @param array<string, mixed> $sfEvent\n */\n private function updateSfEventDescription(Activity $activity, array $sfEvent): void\n {\n try {\n if (str_contains($sfEvent['Description'], $activity->id_string)) {\n return;\n }\n\n $payload = [\n 'Description' => $sfEvent['Description']\n . PHP_EOL\n . PHP_EOL\n . new DecorateActivity()->generateDescription($activity),\n ];\n\n $this->logger->info('[Salesforce] Update record', [\n 'activityId' => $activity->getUuid(),\n 'sfEvent' => $sfEvent['Id'],\n 'payload' => $payload,\n ]);\n\n $payload = array_merge(\n $payload,\n $this->payloadBuilder->fetchCustomFieldData($activity, Field::OBJECT_EVENT)\n );\n\n $this->updateRecord('Event', $sfEvent['Id'], $payload);\n } catch (\\Exception) {\n $this->logger->error('[Salesforce] Failed to update record', [\n 'activityUuid' => $activity->getUuid(),\n 'sfEvent' => $sfEvent['Id'],\n ]);\n }\n }\n\n /**\n * Returns the most recently modified Event within time range (if any).\n *\n * @return array|null An Event record from Salesforce.\n */\n private function fetchRelatedEvent(Activity $activity): ?array\n {\n $ownerId = $this->profile?->crm_provider_id;\n if ($ownerId === null) {\n return [];\n }\n\n /** @var ?Carbon $from */\n /** @var ?Carbon $to */\n [$from, $to] = $this->getFromToDates($activity);\n\n try {\n $whoId = null;\n $hasWho = $activity->lead_id || $activity->contact_id;\n if ($hasWho) {\n $whoId = $activity->hasLead()\n ? $activity->getLead()->crm_provider_id\n : $activity->getContact()->crm_provider_id;\n }\n\n if ($hasWho === false && $activity->account_id === null) {\n return null;\n }\n\n $query = $this->buildFetchRelatedEventQuery($activity);\n\n $objects = $this->queryHandler->query($query, [\n 'ownerId' => $ownerId,\n 'whoId' => $whoId,\n 'whatId' => $activity->hasOpportunity() ? $activity->getOpportunity()->crm_provider_id : null,\n 'accountId' => $activity->hasAccount() ? $activity->getAccount()->crm_provider_id : null,\n 'from' => $from?->format('Y-m-d\\TH:i:s\\Z'),\n 'to' => $to?->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($objects as $object) {\n return $object;\n }\n } catch (NoResultsException $e) {\n return [];\n }\n\n return [];\n }\n\n private function getFromToDates(Activity $activity): array\n {\n $from = null;\n $to = null;\n\n /** @var ?CalendarEvent $calendarEvent */\n $calendarEvent = $activity->calendarEvent()->first();\n if ($calendarEvent !== null) {\n $from = $calendarEvent->getStartTime();\n $to = $calendarEvent->getEndTime();\n }\n\n // For non-calendar imported activities\n // Also double check if calendar event dates could be null?\n // If null use what we've got so far\n if ($from === null || $to === null) {\n $from = $activity->hasScheduledStartTime()\n ? $activity->getScheduledStartTime()\n : $activity->getActualStartTime();\n $to = $activity->hasScheduledEndTime()\n ? $activity->getScheduledEndTime()->addMinutes(15)\n : $activity->getActualEndTime();\n }\n\n return [$from, $to];\n }\n\n /**\n * Determines the appropriate activity field name for querying Salesforce events.\n *\n * This method follows a hierarchy to determine the field name:\n * 1. Uses the playbook's activity field if it exists and is in the profile's accessible fields\n * 2. Falls back to the default activity field if the profile has no event fields configured\n * 3. Returns null if no suitable field is found\n *\n * @param Activity $activity The activity to determine the field for\n *\n * @return string|null The field name to use in queries, or null if none is available\n */\n private function getActivityFieldName(Activity $activity): ?string\n {\n if ($this->profile === null) {\n $this->logger->warning('[Salesforce] Cannot determine activity field - profile not found', [\n 'activityId' => $activity->getUuid(),\n ]);\n\n return null;\n }\n\n $profileEventFields = $this->profile->getFieldsAsArray('event');\n\n if (empty($profileEventFields)) {\n $defaultActivityField = $this->getDefaultActivityField(Field::OBJECT_EVENT);\n $defaultFieldName = $defaultActivityField?->getAttribute('crm_provider_id');\n // Profile not yet synced — fall back to the default activity field.\n // There is a small chance that the profile won't have Default Activity Type field access\n // in which case the query will fail.\n // This is however an edge case and should be reviewed for profile sync issues.\n Sentry::withScope(function (\\Sentry\\State\\Scope $scope) use ($defaultFieldName): void {\n $scope->setContext('details', [\n 'profileId' => $this->profile->id,\n 'defaultField' => $defaultFieldName,\n ]);\n Sentry::captureMessage(\n '[Salesforce] Profile event fields empty, falling back to default activity field.',\n \\Sentry\\Severity::warning()\n );\n });\n\n return $defaultFieldName;\n }\n\n $playbook = $this->getPlaybook($activity->getUser());\n\n if (! is_null($playbook) && ! is_null($playbook->getActivityField())) {\n $playbookFieldName = $playbook->getActivityField()->getAttribute('crm_provider_id');\n\n if (in_array($playbookFieldName, $profileEventFields, true)) {\n return $playbookFieldName;\n }\n\n $this->logger->warning('[Salesforce] Playbook activity field not found in profile fields', [\n 'activityId' => $activity->getUuid(),\n 'playbookField' => $playbookFieldName,\n 'profileId' => $this->profile->id,\n ]);\n }\n\n return null;\n }\n\n private function buildFetchRelatedEventQuery(Activity $activity): string\n {\n $hasWho = $activity->lead_id || $activity->contact_id;\n\n $activityFieldName = $this->getActivityFieldName($activity);\n $fields = array_filter(['Id', 'Description', 'OwnerId', $activityFieldName]);\n\n $ownerCondition = '(OwnerId = :ownerId OR CreatedById = :ownerId)';\n\n $query = '\n SELECT ' . implode(',', $fields) . '\n FROM Event\n WHERE ' . $ownerCondition . '\n AND IsArchived = false\n AND IsAllDayEvent = false\n AND StartDateTime >= :from\n AND EndDateTime <= :to\n AND (';\n\n $operator = '';\n if ($activity->account_id) {\n // This covers events tied to a related contact or opportunity too.\n $query .= 'AccountId = :accountId';\n\n $operator = ' OR ';\n }\n\n if ($hasWho) {\n $query .= $operator . 'WhoId = :whoId';\n\n // If we are also going to check on a specific opportunity, set that up.\n if ($activity->opportunity_id) {\n $query .= ' OR WhatId = :whatId';\n }\n }\n\n $query .= ') ORDER BY LastModifiedDate DESC';\n\n return $query;\n }\n\n public function fetchProspect(array $task): array\n {\n $lead = $account = $opportunity = $contact = $stage = $countryCode = null;\n $externalId = $task['WhoId'] ?? null;\n\n // Lead or Contact\n if ($externalId) {\n try {\n [$lead, $account, $opportunity, $contact, $stage, $countryCode] = $this->parseRecords($externalId);\n } catch (\\InvalidArgumentException $exception) {\n // Invalid object type.\n }\n }\n\n // If we happen to know the opportunity or account from the Task, figure that out.\n if (empty($task['WhatId']) === false) {\n // WhatId could be either Account ID or Opportunity ID.\n // If WhatId is Opportunity ID, get the opportunity and stage from the CRM.\n try {\n [, $account, $opportunity, , $stage, ] = $this->parseRecords($task['WhatId']);\n } catch (\\InvalidArgumentException $exception) {\n // Invalid object type.\n }\n }\n\n return [$lead, $account, $opportunity, $contact, $stage, $countryCode];\n }\n\n /**\n * Save activity transcription summary as note\n */\n public function saveTranscriptionSummaryAsNote(\n ActivityContract $activity,\n string $title,\n string $body,\n ?string $objectId,\n ?NoteObject $noteObject = null,\n ): ?string {\n return $this->saveNote($title, $body, (string) $objectId);\n }\n\n public function getObjectByFilterConditions(string $objectType, array $fields, array $filters): ?array\n {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $query = $queryBuilder->buildObjectSearchQuery($objectType, $fields, $filters);\n\n try {\n $objects = $this->queryHandler->query($query, $filters);\n if ($objects->count() === 1) {\n return $objects->current();\n }\n } catch (\\Exception $e) {\n $this->logger->info('[Salesforce] Failed to execute query', [\n 'query' => $query,\n 'error' => $e->getMessage(),\n ]);\n }\n\n return null;\n }\n\n private function getCustomProfileRules(TeamRepository $teamRepository): array\n {\n $teamSettings = $teamRepository->getTeamSetting($this->team, 'custom_profile_validation');\n\n if ($teamSettings instanceof TeamSettings && $teamSettings->getValueType() === 'array') {\n $customRules = json_decode($teamSettings->getValue(), true);\n if (is_array($customRules)) {\n return $customRules;\n }\n }\n\n return [];\n }\n\n private function customProfileValidation(array $crmUser, array $customRules): bool\n {\n foreach ($customRules as $customRule) {\n if ($crmUser[$customRule['field']] !== $customRule['value']) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * When syncing Contact / Lead / Account / Opportunity / Stage crm entities,\n * validate and restore locally trashed objects,\n * before updating them. Objects are identified by CrmProviderId\n */\n private function restoreAnyTrashedEntity(HasMany $targetEntity, string $crmProviderId): void\n {\n $recordExists = $targetEntity->withTrashed()->where(['crm_provider_id' => $crmProviderId])->first();\n if ($recordExists && $recordExists->trashed()) {\n $recordExists->restore();\n }\n }\n\n #[\\Override] public function supportsNotes(): bool\n {\n return true;\n }\n\n private function getOwnerProfile(?string $ownerId): ?Profile\n {\n if ($ownerId === null) {\n return null;\n }\n\n return $this->config->profiles()\n ->where('crm_provider_id', $ownerId)\n ->first();\n }\n}","depth":4,"on_screen":true,"value":"<?php\n\nnamespace Jiminny\\Services\\Crm\\Salesforce;\n\nuse Carbon\\Carbon;\nuse Exception;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany;\nuse Illuminate\\Events\\Dispatcher;\nuse Illuminate\\Support\\Facades\\Cache;\nuse Illuminate\\Support\\Facades\\Log;\nuse Illuminate\\Support\\Str;\nuse Jiminny\\Component\\Country\\CountriesMap;\nuse Jiminny\\Contracts\\Acl\\PermissionEnum;\nuse Jiminny\\Contracts\\Repositories\\TeamRepository;\nuse Jiminny\\Contracts\\Services\\Crm\\FetchRelatedActivityInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\ImportsBusinessProcessesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\LayoutManagementInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\MatchCrmEntitiesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\Provider\\SalesforceBatchSyncInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\Provider\\SalesforceInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\RemoteEntityLookupInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\RemoteEntityManipulationInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\RemoteNoteEntityManipulationInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SearchTaskInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SendSummaryToCrmInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SettingsInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SupportsObjectTypeParseInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SyncCrmEntitiesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\SyncCrmProfileRecordTypesInterface;\nuse Jiminny\\Contracts\\Services\\Crm\\VerifyTaskExistsInterface;\nuse Jiminny\\Enums\\CrmObject;\nuse Jiminny\\Events\\Activities\\Crm\\LeadConverted;\nuse Jiminny\\Exceptions\\CrmException;\nuse Jiminny\\Exceptions\\HttpBadRequestException;\nuse Jiminny\\Exceptions\\HttpNotFoundException;\nuse Jiminny\\Exceptions\\NoResultsException;\nuse Jiminny\\Exceptions\\ServiceUnavailableException;\nuse Jiminny\\Jobs\\Crm\\NoteObject;\nuse Jiminny\\Jobs\\Crm\\MatchActivitiesToNewOpportunity;\nuse Jiminny\\Models\\Account;\nuse Jiminny\\Models\\Activity;\nuse Jiminny\\Models\\Calendar\\CalendarEvent;\nuse Jiminny\\Models\\Contact;\nuse Jiminny\\Models\\Contracts\\ActivityContract;\nuse Jiminny\\Models\\Crm\\BusinessProcess;\nuse Jiminny\\Models\\Crm\\Configuration;\nuse Jiminny\\Models\\Crm\\ContactRole;\nuse Jiminny\\Models\\Crm\\Field;\nuse Jiminny\\Models\\Crm\\Profile;\nuse Jiminny\\Models\\Crm\\RecordType;\nuse Jiminny\\Models\\Lead;\nuse Jiminny\\Models\\Opportunity;\nuse Jiminny\\Models\\Playbook;\nuse Jiminny\\Models\\SocialAccount;\nuse Jiminny\\Models\\Stage;\nuse Jiminny\\Models\\TeamSettings;\nuse Jiminny\\Models\\User;\nuse Jiminny\\Repositories\\Crm\\ContactRoleRepository;\nuse Jiminny\\Repositories\\Crm\\FieldRepository;\nuse Jiminny\\Repositories\\Crm\\ProfileRepository;\nuse Jiminny\\Repositories\\Crm\\RecordTypeFieldValuesRepository;\nuse Jiminny\\Services\\Avatar\\ProspectPhotoPathService;\nuse Jiminny\\Services\\Crm\\BaseService;\nuse Jiminny\\Services\\Crm\\Helpers\\ArrayIterator;\nuse Jiminny\\Services\\Crm\\MatchDomainByEmailInterface;\nuse Jiminny\\Services\\Crm\\OpportunitySyncStrategyResolver;\nuse Jiminny\\Services\\Crm\\ResolveCompanyNameByEmailTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\Fields\\FieldHelper;\nuse Jiminny\\Services\\Crm\\Salesforce\\Fields\\FieldTypeConverter;\nuse Jiminny\\Services\\Crm\\Salesforce\\Fields\\ValueNormalizer;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\FollowupActivityTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\LogActivityTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\RecordManipulationsTrait;\nuse Jiminny\\Services\\Crm\\Salesforce\\ServiceTraits\\SyncFieldsTrait;\nuse Jiminny\\Utils\\CurrencyFormatter;\nuse Jiminny\\Utils\\StringUtil;\nuse Ramsey\\Uuid\\Uuid;\nuse Sentry\\Laravel\\Facade as Sentry;\n\nclass Service extends BaseService implements\n SalesforceInterface,\n SalesforceBatchSyncInterface,\n SyncCrmEntitiesInterface,\n SyncCrmProfileRecordTypesInterface,\n ImportsBusinessProcessesInterface,\n RemoteEntityManipulationInterface,\n FetchRelatedActivityInterface,\n SendSummaryToCrmInterface,\n MatchDomainByEmailInterface,\n SearchTaskInterface,\n LayoutManagementInterface,\n SettingsInterface,\n MatchCrmEntitiesInterface,\n RemoteEntityLookupInterface,\n SupportsObjectTypeParseInterface,\n RemoteNoteEntityManipulationInterface,\n VerifyTaskExistsInterface\n{\n use ResolveCompanyNameByEmailTrait;\n use SyncFieldsTrait;\n use DeleteObjectsTrait;\n use RecordManipulationsTrait;\n use ServiceTraits\\BatchSyncTrait;\n use FollowupActivityTrait;\n use LogActivityTrait;\n\n /**\n * Note Body Limit for the Old Note-Taking Tool\n *\n * @var int\n */\n private const int CLASSIC_NOTE_MAX_LENGTH = 32000;\n\n /**\n * Note Content Limit for the New Notes\n *\n * @var int\n */\n private const int ENHANCED_NOTE_MAX_LENGTH = 50000000;\n\n private const string INSTALLED_PACKAGE_ID = '033Tw0000007bKbIAI';\n\n private const int CACHE_TTL = 600;\n\n private const int TASK_VERIFICATION_CACHE_TTL = 86400; // 1 day - 86400\n\n /**\n * @var Client\n */\n protected $client;\n\n protected PayloadBuilder $payloadBuilder;\n protected QueryHandler $queryHandler;\n\n private OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;\n\n public function __construct(\n Client $client,\n PayloadBuilder $payloadBuilder,\n protected Dispatcher $eventDispatcher,\n private readonly CountriesMap $countriesMap,\n private readonly ProspectPhotoPathService $prospectPhotoPathService,\n ) {\n parent::__construct();\n\n $this->client = $client;\n $this->payloadBuilder = $payloadBuilder;\n $this->queryHandler = app(QueryHandler::class, [\n 'client' => $this->client,\n 'logger' => $this->logger,\n ]);\n $this->opportunitySyncStrategyResolver = app(OpportunitySyncStrategyResolver::class, [\n 'client' => $this->client,\n ]);\n }\n\n public function getDisplayName(): string\n {\n return 'Salesforce';\n }\n\n public function getJobDelay(): int\n {\n return 1;\n }\n\n protected function getOAuthAccount(User $user): ?SocialAccount\n {\n return $user->getSocialAccount(SocialAccount::PROVIDER_SALESFORCE);\n }\n\n public function verifyTaskExists(Activity $activity): bool\n {\n $crmProviderId = $activity->getCrmProviderId();\n $cacheKey = \"crm_task_exists:{$this->config->getId()}:$crmProviderId\";\n\n return Cache::remember($cacheKey, self::TASK_VERIFICATION_CACHE_TTL, function () use ($activity, $crmProviderId) {\n $playbook = $this->getPlaybookFromActivity($activity);\n\n if ($playbook === null) {\n $this->logger->warning('[Salesforce] Cannot verify task - no playbook found', [\n 'activity' => $activity->getId(),\n 'crm_provider_id' => $crmProviderId,\n ]);\n\n return false;\n }\n\n $objectType = $playbook->getActivityType() === Playbook::ACTIVITY_TYPE_EVENT ? 'Event' : 'Task';\n\n try {\n $record = $this->getRecord($objectType, $crmProviderId, ['Id', 'IsDeleted']);\n\n return ! empty($record) && ($record['IsDeleted'] ?? false) === false;\n } catch (HttpNotFoundException|HttpBadRequestException) {\n $this->logger->info('[Salesforce] Activity record not found during verification', [\n 'activity' => $activity->getId(),\n 'object_type' => $objectType,\n 'crm_provider_id' => $crmProviderId,\n 'config_id' => $this->config->getId(),\n ]);\n\n return false;\n }\n });\n }\n\n public function query(string $queryToRun, array $parameters = []): QueryIterator\n {\n // Due to poorly designed external calls, this method cannot be entirely removed\n return $this->queryHandler->query($queryToRun, $parameters);\n }\n\n /*=========== Organization Information ===============*/\n\n /**\n * Get a list of all the API Versions for the instance.\n *\n * @throws CrmException\n *\n * @return mixed\n *\n */\n public function getApiVersions()\n {\n $url = $this->config->crm_base_url . '/services/data';\n\n $response = $this->client->get($url);\n\n return json_decode($response->getBody(), true);\n }\n\n /**\n * Gets the valid recordTypes for a given Salesforce Object via the describe API.\n */\n private function getRecordTypes(string $crmObject): array\n {\n $url = $this->client->getObjectsUrl() . $crmObject . '/describe';\n\n $response = $this->client->get($url);\n $jsonResponse = json_decode($response->getBody(), true);\n\n $fields = [];\n foreach ($jsonResponse['recordTypeInfos'] as $row) {\n $fields[] = ['recordTypeId' => $row['recordTypeId'], 'default' => $row['defaultRecordTypeMapping']];\n }\n\n return $fields;\n }\n\n /**\n * Convert raw field data into a format compatible with CRM APIs.\n */\n public function normalizeValue(string $fieldType, string $fieldValue, bool $internal = false): string\n {\n return ValueNormalizer::normalize($fieldType, $fieldValue, $internal);\n }\n\n /**\n * @inheritdoc\n */\n public function getDefaultFields(string $activityType): array\n {\n $fields = [];\n\n $defaultFields = ($activityType === Playbook::ACTIVITY_TYPE_TASK)\n ? FieldDefinitions::defaultTaskFields()\n : FieldDefinitions::defaultEventFields();\n\n // This lazy creates these fields if not already setup.\n foreach ($defaultFields as $defaultField) {\n $fields[] = $this->config->fields()->firstOrCreate($defaultField);\n }\n\n return $fields;\n }\n\n /**\n * @inheritdoc\n */\n public function getDefaultActivityField(string $activityType): Field\n {\n // Setup the activity field as the default Type.\n /** @var Field $activityField */\n $activityField = $this->config->fields()->where([\n 'crm_provider_id' => 'Type',\n 'object_type' => $activityType,\n ])->first();\n\n return $activityField;\n }\n\n /**\n * @inheritdoc\n */\n public function getSupportedPlaybookTypes(): array\n {\n return [Playbook::ACTIVITY_TYPE_TASK, Playbook::ACTIVITY_TYPE_EVENT];\n }\n\n protected function getDefaultFollowupLayoutFields(string $activityType): array\n {\n $fields = [];\n $fieldRepo = app(FieldRepository::class);\n\n $fieldFilter = ($activityType === Playbook::ACTIVITY_TYPE_TASK)\n ? FieldDefinitions::taskFollowupFieldsFilter()\n : FieldDefinitions::eventFollowupFieldsFilter();\n\n foreach ($fieldFilter as $eachFilter) {\n $field = $fieldRepo->findOneConfigurationFieldByProperties($this->config, $eachFilter);\n\n // Only add the field if it is created, which it should be.\n if ($field) {\n $fields[] = $field;\n }\n }\n\n return $fields;\n }\n\n public function getDealInsightsFields(): array\n {\n return FieldDefinitions::dealInsightsFields();\n }\n\n /**\n * This one is now called only when ImportActivityTypes is triggered or SyncFieldMetadata executed manually\n * Regular sync now uses SharedSyncFieldsTrait -> syncSingleObjectType\n * Needs to be replaced later on\n */\n public function syncField(Field $field): void\n {\n try {\n if (FieldHelper::isCustomField($field)) {\n $query = '\n SELECT\n Id, Metadata, TableEnumOrId\n FROM\n CustomField\n WHERE\n DeveloperName = :fieldName\n AND\n TableEnumOrId = :fieldType\n AND\n NamespacePrefix = :namespacePrefix';\n\n // We need to constrain the field lookup to the object, in case it's used in multiple places.\n $objectType = \\in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true)\n ? 'activity'\n : $field->object_type;\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'fieldName' => substr($field->crm_provider_id, 0, -\\strlen('__c')),\n 'fieldType' => ucfirst($objectType),\n\n // This is used to ensure we only consider the field within the org, not installed packages.\n 'namespacePrefix' => 'null',\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n // Sync field metadata.\n $metadata = $sfField['Metadata'];\n\n $field->description = mb_strimwidth($metadata['description'] ?? '', 0, 191);\n $field->label = mb_strimwidth($metadata['label'] ?? '', 0, Field::LABEL_MAX_LENGTH);\n $field->type = $this->convertFieldType($metadata['type'], $field->getEntityName());\n $field->is_mandatory = ($metadata['required'] === true);\n $field->length = $metadata['length'];\n $field->default_value = mb_strimwidth(trim($metadata['defaultValue'] ?? '', '\"'), 0, 191);\n $field->save();\n } else {\n $query = '\n SELECT\n Id, DataType, DeveloperName, Label, Length, Description\n FROM\n FieldDefinition\n WHERE\n DurableId = :entityName';\n\n $entityName = $field->getEntityName();\n $sfFields = $this->queryHandler->metadata($query, [\n 'entityName' => $entityName,\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n $convertedType = $this->convertFieldType($sfField['DataType'], $entityName);\n $label = mb_strimwidth($sfField['Label'], 0, Field::LABEL_MAX_LENGTH);\n\n if ($field->isBusinessType()) {\n $label = 'Opportunity Type';\n }\n\n $field->description = mb_strimwidth($sfField['Description'], 0, Field::DESCRIPTION_MAX_LENGTH);\n $field->label = $label;\n $field->type = $convertedType;\n $field->length = $sfField['Length'];\n $field->save();\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n private function convertFieldType(string $from, ?string $entityName = null): string\n {\n $converter = new FieldTypeConverter();\n\n return $converter->convert($from, $entityName);\n }\n\n /**\n * @inheritdoc\n */\n public function importPicklistValues(Field $field): array\n {\n $values = [];\n $fieldValues = [];\n\n try {\n if (FieldHelper::isCustomField($field)) {\n $query = '\n SELECT\n Id, Metadata, TableEnumOrId\n FROM\n CustomField\n WHERE\n DeveloperName = :fieldName\n AND\n TableEnumOrId = :fieldType\n AND\n NamespacePrefix = :namespacePrefix';\n\n // We need to constrain the field lookup to the object, in case it's used in multiple places.\n $objectType = \\in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true) ?\n 'activity' : $field->object_type;\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'fieldName' => substr($field->crm_provider_id, 0, -\\strlen('__c')),\n 'fieldType' => ucfirst($objectType),\n // This is used to ensure we only consider the field within the org, not installed packages.\n 'namespacePrefix' => 'null',\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n $valueSet = $sfField['Metadata']['valueSet'];\n\n if ($valueSet['valueSetName'] === null) {\n // Local picklist values can be obtained easily.\n $picklistValues = $valueSet['valueSetDefinition']['value'];\n } else {\n // But for some fields, we just get the Global Value Picklist pointer so need to do more work.\n $picklistValues = $this->importGlobalValuePicklistValues($valueSet['valueSetName']);\n }\n\n // Import all active values.\n foreach ($picklistValues as $i => $sfFieldValue) {\n // Setup default value.\n if ($sfFieldValue['default']) {\n $field->update(['default_value' => $sfFieldValue['valueName']]);\n }\n\n // This comes through as null if active (lol).\n if ($sfFieldValue['isActive'] !== false) {\n $values[] = [\n 'value' => $sfFieldValue['valueName'],\n 'label' => $sfFieldValue['valueName'],\n 'sequence' => $i,\n 'is_default' => $sfFieldValue['default'],\n ];\n }\n }\n } else {\n $objectFields = $this->getObjectFields($field->object_type);\n $fieldId = $field->crm_provider_id;\n\n // Only work with our field of interest.\n $objectField = array_filter($objectFields, function ($item) use ($fieldId) {\n return $item['name'] === $fieldId;\n });\n\n $objectField = array_shift($objectField);\n if (empty($objectField['picklistValues']) === false) {\n foreach ($objectField['picklistValues'] as $i => $sfFieldValue) {\n // Skip inactive values.\n if ($sfFieldValue['active'] === false) {\n continue;\n }\n\n // Setup default value.\n if ($sfFieldValue['defaultValue']) {\n $field->update(['default_value' => $sfFieldValue['value']]);\n }\n\n $values[] = [\n 'value' => $sfFieldValue['value'],\n 'label' => $sfFieldValue['label'],\n 'sequence' => $i,\n 'is_default' => $sfFieldValue['defaultValue'],\n ];\n }\n }\n }\n\n $fieldsToPurge = $field->values()->get()->pluck('value')->toArray();\n\n foreach ($values as $value) {\n $value['value'] = substr($value['value'] ?? '', 0, 255);\n $fieldValues[] = $field->values()->updateOrCreate([\n 'value' => $value['value'],\n ], $value);\n\n // Remove this value from the ones we are going to purge.\n if (($key = array_search($value['value'], $fieldsToPurge, true)) !== false) {\n unset($fieldsToPurge[$key]);\n }\n }\n\n // Delete the old values that are no longer used.\n // Get IDs of the values to be deleted\n $valuesToDelete = $field->values()->whereIn('value', $fieldsToPurge);\n $valuesToDeleteIds = $valuesToDelete->pluck('id');\n if (! $valuesToDeleteIds->isEmpty()) {\n $recordTypeFieldValuesRepository = app(RecordTypeFieldValuesRepository::class);\n $recordTypeFieldValuesRepository->deleteForCrmFieldValueIds($valuesToDeleteIds->toArray());\n\n // Now safely delete from crm_field_values\n $valuesToDelete->delete();\n }\n\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n return $fieldValues;\n }\n\n /**\n * Gets values from Global Value Picklists.\n */\n private function importGlobalValuePicklistValues(string $picklistName): array\n {\n $query = '\n SELECT\n Metadata\n FROM\n GlobalValueSet\n WHERE\n DeveloperName = :picklistName\n LIMIT 1';\n\n try {\n $sfValues = $this->queryHandler->metadata($query, [\n 'picklistName' => $picklistName,\n ]);\n\n // There is always 1 result at this point.\n $sfValue = $sfValues->current();\n\n return $sfValue['Metadata']['customValue'];\n } catch (NoResultsException $noResultsException) {\n // Nothing returned.\n\n return [];\n }\n }\n\n /**\n * @inheritdoc\n */\n public function syncProfileRecordTypes(): void\n {\n $objectTypes = [\n 'lead',\n 'account',\n 'contact',\n 'opportunity',\n 'task',\n 'event',\n ];\n\n foreach ($objectTypes as $objectType) {\n try {\n $crmRecordTypes = $this->getRecordTypes(ucfirst($objectType));\n\n foreach ($crmRecordTypes as $crmRecordType) {\n // If the record type is default and not the Master type, set this.\n if ($crmRecordType['default'] && $crmRecordType['recordTypeId'] !== '012000000000000AAA') {\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $crmRecordType['recordTypeId'])\n ->first();\n\n if ($recordType) {\n $this->profile->{$objectType . '_record_type_id'} = $recordType->id;\n }\n }\n }\n } catch (HttpNotFoundException $exception) {\n Log::error('No access to ' . $objectType . ' object, skipping...');\n\n // XXX: should we log this fact somewhere?\n continue;\n }\n }\n\n if ($this->profile->isDirty()) {\n $this->profile->save();\n }\n }\n\n /**\n * Gets business processes.\n */\n public function importBusinessProcesses(): void\n {\n $query = '\n SELECT\n Id, IsActive, Name, TableEnumOrId\n FROM\n BusinessProcess\n WHERE\n TableEnumOrId IN (\\'Lead\\',\\'Opportunity\\')';\n\n try {\n $sfProcesses = $this->queryHandler->query($query);\n\n // Upsert all processes for the team.\n foreach ($sfProcesses as $sfProcess) {\n /** @var BusinessProcess $businessProcess */\n $businessProcess = $this->config->businessProcesses()->updateOrCreate([\n 'crm_provider_id' => $sfProcess['Id'],\n ], [\n 'team_id' => $this->team->id,\n 'name' => $sfProcess['Name'],\n 'type' => $sfProcess['TableEnumOrId'] === 'Lead' ? 'lead' : 'opportunity',\n 'is_selectable' => $sfProcess['IsActive'],\n ]);\n\n $this->importBusinessProcessStages($businessProcess);\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n /**\n * Gets business process stages.\n */\n private function importBusinessProcessStages(BusinessProcess $businessProcess): void\n {\n $query = '\n SELECT\n Metadata\n FROM\n BusinessProcess\n WHERE\n Id = :processId';\n\n try {\n $stages = [];\n $sfProcessStages = $this->queryHandler->metadata($query, [\n 'processId' => $businessProcess->crm_provider_id,\n ]);\n\n // There is always 1 result at this point.\n $sfProcessStage = $sfProcessStages->current();\n\n // Upsert all processes for the team.\n foreach ($sfProcessStage['Metadata']['values'] as $sfProcessStage) {\n $sanitizedName = urldecode($sfProcessStage['valueName']); // Must decode: \"%2C\" becomes \",\" etc.\n\n $stage = $businessProcess->crm->stages()\n // This MUST match on label because this API doesn't use API Name.\n ->where('label', $sanitizedName)\n ->where('type', $businessProcess->type)\n ->where('is_selectable', 1)\n ->first();\n\n if ($stage) {\n $stages[] = $stage->id;\n }\n }\n\n $businessProcess->stages()->sync($stages);\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n /**\n * Gets record types.\n */\n public function importRecordTypes(): void\n {\n $query = '\n SELECT\n Id, IsActive, Name, BusinessProcessId, SobjectType\n FROM\n RecordType';\n\n try {\n $sfRecordTypes = $this->queryHandler->query($query);\n\n // Upsert all record types for the process.\n foreach ($sfRecordTypes as $sfRecordType) {\n $businessProcess = null;\n if ($sfRecordType['BusinessProcessId']) {\n $businessProcess = $this->config->businessProcesses()\n ->where('crm_provider_id', $sfRecordType['BusinessProcessId'])\n ->first();\n }\n\n /** @var RecordType $recordType */\n $recordType = $this->config->recordTypes()->updateOrCreate([\n 'crm_provider_id' => $sfRecordType['Id'],\n ], [\n 'team_id' => $this->team->id,\n 'type' => mb_strtolower($sfRecordType['SobjectType']),\n 'name' => $sfRecordType['Name'],\n 'is_selectable' => $sfRecordType['IsActive'],\n 'business_process_id' => $businessProcess->id ?? null,\n ]);\n\n $this->importRecordTypeFieldValues($recordType);\n }\n } catch (NoResultsException $noResultsException) {\n // Do nothing.\n }\n }\n\n /**\n * Import record type - field value mappings. This only works for standard fields.\n */\n private function importRecordTypeFieldValues(RecordType $recordType): void\n {\n try {\n $query = '\n SELECT\n Metadata\n FROM\n RecordType\n WHERE\n Id = :recordTypeId';\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'recordTypeId' => $recordType->crm_provider_id,\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n // Sync field metadata.\n $picklists = $sfField['Metadata']['picklistValues'];\n\n foreach ($picklists as $picklist) {\n $field = $this->config->fields()->where([\n 'type' => Field::TYPE_PICKLIST,\n 'object_type' => $recordType->type,\n 'crm_provider_id' => $picklist['picklist'],\n ])->first();\n\n if ($field) {\n $fieldValues = [];\n\n foreach ($picklist['values'] as $value) {\n // Must decode: \"%2C\" becomes \",\" etc.\n $fieldValue = $field->values()\n ->where('value', urldecode($value['valueName']))\n ->first();\n\n if ($fieldValue) {\n $fieldValues[] = $fieldValue->id;\n }\n }\n\n $recordType->fieldValues()->sync($fieldValues);\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n }\n\n /**\n * @inheritdoc\n */\n public function importStages(?array $types = null, ?string $missingStageName = null): ?Stage\n {\n $params = [];\n $missingStage = null;\n if ($types === null) {\n $types = [Stage::TYPE_LEAD, Stage::TYPE_OPPORTUNITY];\n }\n\n foreach ($types as $type) {\n if ($type === Stage::TYPE_LEAD) {\n $query = '\n SELECT\n Id, ApiName, MasterLabel, SortOrder\n FROM\n LeadStatus';\n } else {\n $query = '\n SELECT\n Id, ApiName, MasterLabel, IsActive, SortOrder, DefaultProbability\n FROM\n OpportunityStage';\n }\n\n if ($missingStageName) {\n $escapedStageName = ValueNormalizer::replaceQueryWithStringLiterals($missingStageName);\n\n $query .= ' WHERE ApiName = :stageName';\n\n $params = [\n 'stageName' => $escapedStageName,\n ];\n }\n\n try {\n $sfStages = $this->queryHandler->query($query, $params);\n } catch (NoResultsException $exception) {\n $sfStages = [];\n }\n\n $missingStage = null;\n\n // Upsert all stages for the team.\n foreach ($sfStages as $sfStage) {\n $selectable = true;\n if (array_key_exists('IsActive', $sfStage)) {\n $selectable = $sfStage['IsActive'];\n }\n\n $this->restoreAnyTrashedEntity($this->config->stages(), $sfStage['Id']);\n\n $stage = $this->config->stages()->updateOrCreate([\n 'crm_provider_id' => $sfStage['Id'],\n ], [\n 'team_id' => $this->team->id,\n 'name' => mb_strimwidth($sfStage['ApiName'], 0, 50),\n 'label' => mb_strimwidth($sfStage['MasterLabel'], 0, 191),\n 'type' => $type,\n 'sequence' => $sfStage['SortOrder'] ?? 0,\n 'is_selectable' => $selectable,\n 'probability' => $sfStage['DefaultProbability'] ?? null,\n ]);\n\n if ($missingStageName && $missingStageName === $sfStage['ApiName']) {\n $missingStage = $stage;\n }\n }\n\n if ($missingStageName && $missingStage === null) {\n // If they requested a stage that still doesn't exist, it must be inactive so lazy create it.\n $missingStage = $this->config->stages()->create([\n 'crm_provider_id' => Uuid::uuid4(),\n 'team_id' => $this->team->id,\n 'name' => mb_strimwidth($missingStageName, 0, 50),\n 'label' => mb_strimwidth($missingStageName, 0, 191),\n 'type' => $type,\n 'sequence' => 0,\n 'is_selectable' => 0,\n ]);\n }\n }\n\n return $missingStage;\n }\n\n /**\n * @inheritdoc\n */\n public function syncLeads(Carbon $since, ?Carbon $to = null, ?string $crmProfileId = null): int\n {\n $syncCount = 0;\n $fields = $this->getAllFieldsAsArray('lead');\n if (\\in_array('Id', $fields, true) === false) {\n return $syncCount;\n }\n\n $query = '\n SELECT ' . rtrim(implode(',', $fields), ',') . '\n FROM Lead\n WHERE LastModifiedDate > :since\n ORDER BY LastModifiedDate ASC';\n\n try {\n $sfLeads = $this->queryHandler->query($query, [\n 'since' => $since->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($sfLeads as $sfLead) {\n // Only sync if previously imported.\n if ($this->hasLead($sfLead['Id'])) {\n $this->importLead($sfLead);\n $syncCount++;\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::LEAD);\n\n return $syncCount;\n }\n\n /**\n * @inheritdoc\n */\n public function syncLead(string $crmId): ?Lead\n {\n $fields = $this->getAllFieldsAsArray('lead');\n\n $sfLead = $this->getRecord('Lead', $crmId, $fields);\n\n return $this->importLead($sfLead);\n }\n\n private function importLead($crmData): ?Lead\n {\n /** @var ?Stage $stage */\n $stage = null;\n if (isset($crmData['Status'])) {\n // Get the current stage.\n $stage = $this->config\n ->stages()\n ->where('name', $crmData['Status'])\n ->where('type', Stage::TYPE_LEAD)\n ->first();\n\n if ($stage === null) {\n // Import it.\n $stage = $this->importStages([Stage::TYPE_LEAD], $crmData['Status']);\n }\n }\n\n // If we have no way of importing this, just return null :(\n if ($stage === null) {\n return null;\n }\n\n $countryCode = $crmData['CountryCode'] ?? null;\n\n // Salesforce allows custom \"countries\" to be created. Disregard these.\n if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {\n $countryCode = null;\n }\n\n // If we have no country code, try to parse it from the country name.\n if ($countryCode === null && empty($crmData['Country']) !== false) {\n $countryCode = $this->convertCountryNameToCode($crmData['Country']);\n }\n\n // Trim to our width and attempt to parse it.\n $number = mb_strimwidth($crmData['Phone'] ?? '', 0, 25);\n $parsedNumber = parsePhoneNumber($countryCode, $number);\n\n $mobilePhone = null;\n if (empty($crmData['MobilePhone']) === false) {\n // Trim to our width and attempt to parse it.\n $number = mb_strimwidth($crmData['MobilePhone'], 0, 25);\n $mobilePhone = phone_e164($countryCode, $number);\n }\n\n $convertedDate = null;\n $convertedAccount = null;\n $convertedOpportunity = null;\n $convertedContact = null;\n\n if ($crmData['IsConverted'] == 'true') {\n $convertedDate = $crmData['ConvertedDate'];\n\n if (empty($crmData['ConvertedAccountId']) === false) {\n $convertedAccount = $this->config\n ->accounts()\n ->where('crm_provider_id', $crmData['ConvertedAccountId'])\n ->first();\n\n if ($convertedAccount === null) {\n try {\n $convertedAccount = $this->syncAccount($crmData['ConvertedAccountId']);\n } catch (HttpNotFoundException $exception) {\n // Probably the user has no permissions to access the converted data.\n }\n }\n }\n\n if (empty($crmData['ConvertedOpportunityId']) === false) {\n $convertedOpportunity = $this->config\n ->opportunities()\n ->where('crm_provider_id', $crmData['ConvertedOpportunityId'])\n ->first();\n\n if ($convertedOpportunity === null) {\n try {\n $convertedOpportunity = $this->syncOpportunity($crmData['ConvertedOpportunityId']);\n } catch (HttpNotFoundException $exception) {\n // Probably the user has no permissions to access the converted data.\n }\n }\n }\n\n if (empty($crmData['ConvertedContactId']) === false) {\n $convertedContact = $this->team\n ->crm\n ->contacts()\n ->where('crm_provider_id', $crmData['ConvertedContactId'])\n ->first();\n\n if ($convertedContact === null) {\n try {\n $convertedContact = $this->syncContact($crmData['ConvertedContactId']);\n } catch (HttpNotFoundException $exception) {\n // Probably the user has no permissions to access the converted data.\n }\n }\n }\n }\n\n if (empty($crmData['Company'])) {\n $company = 'Unknown';\n } else {\n $company = mb_strimwidth($crmData['Company'], 0, 191);\n }\n\n $domain = null;\n if (empty($crmData['Website']) === false) {\n $domain = mb_strimwidth($crmData['Website'], 0, 191);\n $domain = StringUtil::resolveDomain($domain);\n }\n\n $createdDate = null;\n if (empty($crmData['CreatedDate']) === false) {\n $createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n }\n\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $data = [\n 'team_id' => $this->team->id,\n 'user_id' => $profile?->user_id,\n 'owner_id' => $crmData['OwnerId'] ?? '',\n 'company' => $company,\n 'domain' => $domain,\n 'name' => $crmData['Name'] ? mb_strimwidth($crmData['Name'], 0, 191) : '',\n 'title' => $crmData['Title'] ? mb_strimwidth($crmData['Title'], 0, 128) : null,\n 'email' => $crmData['Email'] ? mb_strimwidth($crmData['Email'], 0, 80) : null,\n 'phone' => $parsedNumber['phone'],\n 'ext' => $parsedNumber['ext'] ?? null,\n 'mobile_phone' => $mobilePhone,\n 'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(\n crmConfiguration: $this->config,\n crmProviderId: $crmData['Id'],\n modelType: Lead::class,\n fileName: $crmData['Id'],\n avatarText: $crmData['Name']\n ),\n 'stage_id' => $stage->id,\n 'record_type_id' => null,\n 'converted_at' => $convertedDate,\n 'converted_account_id' => $convertedAccount->id ?? null,\n 'converted_opportunity_id' => $convertedOpportunity->id ?? null,\n 'converted_contact_id' => $convertedContact->id ?? null,\n 'country_code' => $countryCode,\n 'remotely_created_at' => $createdDate,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->leads(), $crmData['Id']);\n\n /** @var Lead $lead */\n $lead = $this->config->leads()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n if ($lead->wasChanged('converted_at') && $lead->getConvertedAt() !== null) {\n $this->eventDispatcher->dispatch(new LeadConverted($lead));\n }\n\n $this->handleObjectDeletion($lead, $crmData);\n\n if ($lead->trashed()) {\n return null;\n }\n\n return $lead;\n }\n\n /**\n * @inheritdoc\n */\n public function syncAccounts(Carbon $since, ?Carbon $to = null): int\n {\n $syncCount = 0;\n $fields = $this->getAllFieldsAsArray('account');\n\n if (\\in_array('Id', $fields, true) === false) {\n return $syncCount;\n }\n\n $query = '\n SELECT ' . rtrim(implode(',', $fields), ',') . '\n FROM Account\n WHERE LastModifiedDate > :since\n ORDER BY LastModifiedDate ASC';\n\n try {\n $sfAccounts = $this->queryHandler->query($query, [\n 'since' => $since->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($sfAccounts as $sfAccount) {\n // Only sync if previously imported.\n if ($this->hasAccount($sfAccount['Id'])) {\n $this->importAccount($sfAccount);\n $syncCount++;\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::ACCOUNT);\n\n return $syncCount;\n }\n\n /**\n * @inheritdoc\n */\n public function syncAccount(string $crmId): ?Account\n {\n $fields = $this->getAllFieldsAsArray('account');\n if (! in_array('Id', $fields, true)) {\n $this->logger->info('[Salesforce] Sync account cancelled. Fields are not available.', [\n 'crmId' => $crmId,\n 'userId' => $this->profile->getUserId(),\n ]);\n\n return null;\n }\n\n $sfAccount = $this->getRecord('Account', $crmId, $fields);\n\n return $this->importAccount($sfAccount);\n }\n\n private function importAccount($crmData): ?Account\n {\n if (! empty($crmData['IsDeleted'])) {\n $this->handleEntityDeletionByProviderId($this->config->accounts(), $crmData);\n\n return null;\n }\n\n $countryCode = $crmData['BillingCountryCode'] ?? $crmData['ShippingCountryCode'] ?? null;\n\n // Salesforce allows custom \"countries\" to be created. Disregard these.\n if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {\n $countryCode = null;\n }\n\n // If we have no country code, try to parse it from the country names.\n if ($countryCode === null && empty($crmData['BillingCountry']) === false) {\n $countryCode = $this->convertCountryNameToCode($crmData['BillingCountry']);\n }\n\n if ($countryCode === null && empty($crmData['ShippingCountry']) === false) {\n $countryCode = $this->convertCountryNameToCode($crmData['ShippingCountry']);\n }\n\n if (empty($crmData['Phone']) === false) {\n // Trim to our width and attempt to parse it.\n $number = mb_strimwidth($crmData['Phone'], 0, 25);\n $parsedNumber = parsePhoneNumber($countryCode, $number);\n } else {\n $parsedNumber = [];\n }\n\n $industry = null;\n if (empty($crmData['Industry']) === false) {\n $industry = mb_strimwidth($crmData['Industry'], 0, 40);\n }\n\n $domain = null;\n if (empty($crmData['Website']) === false) {\n $domain = mb_strimwidth($crmData['Website'], 0, 191);\n $domain = StringUtil::resolveDomain($domain);\n }\n\n $createdDate = null;\n if (empty($crmData['CreatedDate']) === false) {\n $createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n }\n\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $data = [\n 'team_id' => $this->team->id,\n 'user_id' => $profile?->user_id,\n 'owner_id' => $crmData['OwnerId'],\n 'name' => mb_strimwidth($crmData['Name'], 0, 191),\n 'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(\n crmConfiguration: $this->config,\n crmProviderId: $crmData['Id'],\n modelType: Account::class,\n fileName: $crmData['Id'],\n avatarText: $crmData['Name']\n ),\n 'industry' => $industry,\n 'domain' => $domain,\n 'phone' => $parsedNumber['phone'] ?? null,\n 'ext' => $parsedNumber['ext'] ?? null,\n 'country_code' => $countryCode,\n 'remotely_created_at' => $createdDate,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->accounts(), $crmData['Id']);\n\n /** @var Account $account */\n $account = $this->config->accounts()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n $this->handleObjectDeletion($account, $crmData);\n\n return $account->trashed() ? null : $account;\n }\n\n /**\n * @inheritdoc\n */\n public function syncOpportunities(array $parameters, ?string $strategy = null): int\n {\n $strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);\n\n $syncCount = 0;\n $logParams = $parameters;\n $parameters['profile'] = $this->profile;\n $logParams['user'] = $this->profile->getUserId();\n\n if (count($strategies) > 1) {\n $this->logger->warning('[' . $this->getDisplayName() . '] Multiple sync strategies used', [\n 'teamId' => $this->team->getUuid(),\n 'params' => $logParams,\n 'strategies_count' => count($strategies),\n ]);\n }\n\n foreach ($strategies as $syncStrategy) {\n $name = $syncStrategy->getStrategyName();\n\n try {\n $sfOpportunities = $syncStrategy->fetchOpportunities($parameters);\n $totalRecords = $sfOpportunities->count();\n\n foreach ($sfOpportunities as $sfOpportunity) {\n $this->importOpportunity($sfOpportunity);\n $syncCount++;\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n $this->logger->warning('[' . $this->getDisplayName() . '] No opportunities found', [\n 'teamId' => $this->team->getUuid(),\n 'name' => $name,\n 'params' => $logParams,\n 'reason' => $noResultsException->getMessage(),\n ]);\n } catch (CrmException $crmException) {\n // Nothing to sync.\n $this->logger->warning('[' . $this->getDisplayName() . '] Opportunity sync failed', [\n 'teamId' => $this->team->getUuid(),\n 'name' => $name,\n 'params' => $logParams,\n 'reason' => $crmException->getMessage(),\n ]);\n }\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::OPPORTUNITY, ['params' => $logParams]);\n\n // debug to see how if count of opportunities reaches 1000\n if ($syncCount >= 1000) {\n $this->logger->info(\n '[' . $this->getDisplayName() . '] Sync Opportunities - count warning',\n [\n 'team_id' => $this->team->getId(),\n 'params' => $logParams,\n 'count' => $syncCount,\n 'strategies_count' => count($strategies),\n 'total_records' => $totalRecords ?? null,\n ]\n );\n }\n\n return $syncCount;\n }\n\n\n /**\n * @inheritdoc\n */\n public function syncOpportunity(string $crmId): ?Opportunity\n {\n $strategy = $this->opportunitySyncStrategyResolver->resolve(\n $this->config,\n OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY\n );\n\n $parameters = [\n 'profile' => $this->profile,\n 'crm_id' => $crmId,\n ];\n\n try {\n $sfOpportunity = $strategy->fetchOpportunities($parameters);\n } catch (HttpNotFoundException $e) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [\n 'teamId' => $this->team->id_string,\n 'crmId' => $crmId,\n ]);\n\n return null;\n } catch (CrmException $crmException) {\n $this->logger->info('[' . $this->getDisplayName() . '] Opportunity sync failed', [\n 'teamId' => $this->team->id_string,\n 'crmId' => $crmId,\n 'exception' => $crmException->getMessage(),\n ]);\n\n return null;\n }\n\n if ($sfOpportunity instanceof ArrayIterator) {\n return $this->importOpportunity($sfOpportunity->getItems());\n }\n\n return $this->importOpportunity($sfOpportunity);\n }\n\n /**\n * @throws HttpNotFoundException\n */\n private function importOpportunity($crmData): ?Opportunity\n {\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $account = null;\n if (empty($crmData['AccountId']) === false) {\n /** @var ?Account $account */\n $account = $this->config->accounts()\n ->where('crm_provider_id', (string) $crmData['AccountId'])\n ->first();\n\n if ($account === null) {\n $account = $this->syncAccount($crmData['AccountId']);\n }\n }\n\n $userId = $profile?->getUserId() ?? $account?->getUserId();\n if ($userId === null) {\n $this->logger->error('[Salesforce] | Skip import, no user_id found', [\n 'id' => $crmData['Id'],\n ]);\n\n return null;\n }\n\n /** @var ?Stage $stage */\n $stage = null;\n if (isset($crmData['StageName'])) {\n $stage = $this->config\n ->stages()\n ->where('name', $crmData['StageName'])\n ->where('type', Stage::TYPE_OPPORTUNITY)\n ->orderBy('is_selectable', 'DESC')\n ->orderBy('id')\n ->first();\n\n if ($stage === null) {\n // Import it.\n $stage = $this->importStages([Stage::TYPE_OPPORTUNITY], $crmData['StageName']);\n }\n }\n\n $recordType = null;\n if (empty($crmData['RecordTypeId']) === false) {\n /** @var ?RecordType $recordType */\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $crmData['RecordTypeId'])\n ->first();\n }\n\n $createdDate = null;\n if (empty($crmData['CreatedDate']) === false) {\n $createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n }\n\n $closeDate = null;\n if (empty($crmData['CloseDate']) === false) {\n $closeDate = Carbon::parse($crmData['CloseDate'])->format('Y-m-d');\n }\n\n $valueFieldName = 'Amount';\n if ($this->config->opportunity_value_field_id) {\n $valueFieldName = $this->config->opportunityValueField->crm_provider_id;\n }\n\n $data = [\n 'team_id' => $this->team->id,\n 'account_id' => $account->id ?? null,\n 'user_id' => $userId,\n 'owner_id' => $crmData['OwnerId'] ?? null,\n 'name' => mb_strimwidth($crmData['Name'] ?? '', 0, 128),\n 'value' => $crmData[$valueFieldName],\n 'currency_code' => CurrencyFormatter::formatCode($crmData['CurrencyIsoCode'] ?? null),\n 'close_date' => $closeDate,\n 'is_closed' => $crmData['IsClosed'],\n 'is_won' => $crmData['IsWon'],\n 'stage_id' => $stage?->id ?? null,\n 'record_type_id' => $recordType->id ?? null,\n 'remotely_created_at' => $createdDate,\n 'probability' => $crmData['Probability'] ?? null,\n 'forecast_category' => $crmData['ForecastCategoryName'] ?? null,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->opportunities(), $crmData['Id']);\n\n // Do not allow locked DB tables & other errors\n // to interrupt the process of reverting the trashed opportunities\n try {\n /** @var Opportunity $opportunity */\n $opportunity = $this->config->opportunities()\n ->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n // import external fields into crm_field_data if present\n $crmFields = $this->getOpportunitySyncableFields();\n\n $this->importOpportunityCrmFieldData($crmData, $crmFields, $opportunity->id);\n\n $this->handleObjectDeletion($opportunity, $crmData);\n\n if ($opportunity->trashed()) {\n return null;\n }\n\n if ($opportunity->wasRecentlyCreated) {\n MatchActivitiesToNewOpportunity::dispatch($opportunity->getId());\n }\n\n return $opportunity;\n } catch (Exception $exception) {\n Sentry::captureException($exception);\n\n $this->logger->error('[Salesforce] importOpportunity failure.', [\n 'crm_provider_id' => $crmData['Id'],\n 'team_id' => $this->team->id,\n 'exception' => $exception->getMessage(),\n ]);\n\n $this->handleEntityDeletionByProviderId($this->config->opportunities(), $crmData);\n }\n\n return null;\n }\n\n /**\n * @inheritdoc\n */\n public function syncContacts(Carbon $since, ?Carbon $to = null): int\n {\n $syncCount = 0;\n $fields = $this->getAllFieldsAsArray('contact');\n if (\\in_array('Id', $fields, true) === false) {\n return $syncCount;\n }\n\n $query = '\n SELECT ' . rtrim(implode(',', $fields), ',') . '\n FROM Contact\n WHERE LastModifiedDate > :since\n ORDER BY LastModifiedDate ASC';\n\n try {\n $sfContacts = $this->queryHandler->query($query, [\n 'since' => $since->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($sfContacts as $sfContact) {\n // Only sync if previously imported.\n if ($this->hasContact($sfContact['Id'])) {\n $this->importContact($sfContact);\n $syncCount++;\n }\n }\n } catch (NoResultsException $noResultsException) {\n // Nothing to sync.\n }\n\n $this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::CONTACT);\n\n return $syncCount;\n }\n\n /**\n * @inheritdoc\n */\n public function syncContact(string $crmId): ?Contact\n {\n $fields = $this->getAllFieldsAsArray('contact');\n if (! in_array('Id', $fields, true)) {\n $this->logger->info('[Salesforce] Sync contact cancelled. Fields are not available.', [\n 'crmId' => $crmId,\n 'userId' => $this->profile->getUserId(),\n ]);\n\n return null;\n }\n\n $sfContact = $this->getRecord('Contact', $crmId, $fields);\n\n return $this->importContact($sfContact);\n }\n\n private function importContact($crmData): ?Contact\n {\n if (! empty($crmData['IsDeleted'])) {\n $this->handleEntityDeletionByProviderId($this->config->contacts(), $crmData);\n\n return null;\n }\n\n $account = $this->resolveContactAccount($crmData);\n $countryCode = $this->resolveContactCountryCode($crmData, $account);\n [$parsedNumber, $ext] = $this->parseContactPhone($countryCode, $crmData);\n $mobileNumber = $this->parseContactMobile($countryCode, $crmData);\n $createdDate = empty($crmData['CreatedDate'])\n ? null\n : Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');\n $profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);\n\n $data = [\n 'team_id' => $this->team->id,\n 'account_id' => $account->id ?? null,\n 'user_id' => $profile?->user_id,\n 'owner_id' => $crmData['OwnerId'] ?? null,\n 'name' => ($crmData['Name'] ?? null) !== null ? mb_strimwidth($crmData['Name'], 0, 100) : '',\n 'title' => ($crmData['Title'] ?? null) !== null ? mb_strimwidth($crmData['Title'], 0, 128) : null,\n 'email' => ($crmData['Email'] ?? null) !== null ? mb_strimwidth($crmData['Email'], 0, 191) : null,\n 'country_code' => $countryCode,\n 'phone' => $parsedNumber['phone'] ?? null,\n 'ext' => $ext,\n 'mobile_phone' => $mobileNumber,\n 'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(\n crmConfiguration: $this->config,\n crmProviderId: $crmData['Id'],\n modelType: Contact::class,\n fileName: $crmData['Id'],\n avatarText: $crmData['Name']\n ),\n 'remotely_created_at' => $createdDate,\n ];\n\n $this->restoreAnyTrashedEntity($this->config->contacts(), $crmData['Id']);\n\n /** @var Contact $contact */\n $contact = $this->config->contacts()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);\n\n $this->handleObjectDeletion($contact, $crmData);\n\n return $contact->trashed() ? null : $contact;\n }\n\n private function resolveContactAccount(array $crmData): ?Account\n {\n if (! isset($crmData['AccountId'])) {\n return null;\n }\n\n return $this->config->accounts()\n ->where('crm_provider_id', (string) $crmData['AccountId'])\n ->first() ?? $this->syncAccount($crmData['AccountId']);\n }\n\n private function resolveContactCountryCode(array $crmData, ?Account $account): ?string\n {\n $countryCode = $crmData['MailingCountryCode'] ?? null;\n\n if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {\n $countryCode = null;\n }\n\n if ($countryCode === null && empty($crmData['MailingCountry']) === false) {\n $countryCode = $this->convertCountryNameToCode($crmData['MailingCountry'])\n ?? ($account?->country_code);\n }\n\n return $countryCode;\n }\n\n private function parseContactPhone(?string $countryCode, array $crmData): array\n {\n if (empty($crmData['Phone'])) {\n return [[], null];\n }\n\n $parsedNumber = parsePhoneNumber($countryCode, Str::limit($crmData['Phone'], 25, ''));\n $ext = empty($parsedNumber['ext']) ? null : Str::limit($parsedNumber['ext'], 10, '');\n\n return [$parsedNumber, $ext];\n }\n\n private function parseContactMobile(?string $countryCode, array $crmData): ?string\n {\n if (empty($crmData['MobilePhone'])) {\n return null;\n }\n\n return Str::limit(phone_e164($countryCode, $crmData['MobilePhone']), 25, '');\n }\n\n /**\n * @inheritdoc\n */\n public function syncOrganization(): void\n {\n $fields = [\n 'InstanceName',\n 'OrganizationType',\n 'IsSandbox',\n ];\n\n $orgValues = $this->getRecord('Organization', $this->config->crm_provider_id, $fields);\n\n $edition = null;\n switch ($orgValues['OrganizationType']) {\n case 'Developer Edition':\n $edition = Configuration::EDITION_DEVELOPER;\n\n break;\n\n case 'Professional Edition':\n $edition = Configuration::EDITION_PROFESSIONAL;\n\n break;\n\n case 'Enterprise Edition':\n $edition = Configuration::EDITION_ENTERPRISE;\n\n break;\n }\n\n $this->config->edition = $edition;\n $this->config->instance = $orgValues['InstanceName'];\n\n // XXX: How can this state be possible?\n if ($this->config->version === null) {\n $this->config->version = Client::MIN_API_VERSION;\n }\n\n $installedVersion = $this->getInstalledAppVersion();\n if ($installedVersion !== null) {\n $installedVersion = (string) $this->getInstalledAppVersion();\n }\n\n $this->config->installed_app_version = $installedVersion;\n\n $this->config->save();\n }\n\n public function getInstalledAppVersion(): ?string\n {\n try {\n $query = '\n SELECT\n SubscriberPackageVersion.MajorVersion,\n SubscriberPackageVersion.MinorVersion,\n SubscriberPackageVersion.PatchVersion,\n SubscriberPackageVersion.BuildNumber\n FROM\n InstalledSubscriberPackage\n WHERE\n SubscriberPackageId = :packageId\n ';\n\n $sfFields = $this->queryHandler->metadata($query, [\n 'packageId' => self::INSTALLED_PACKAGE_ID,\n ]);\n\n // There is always 1 result at this point.\n $sfField = $sfFields->current();\n\n // Grab version number.\n $version = $sfField['SubscriberPackageVersion']['MajorVersion'] .\n $sfField['SubscriberPackageVersion']['MinorVersion'] .\n $sfField['SubscriberPackageVersion']['PatchVersion'] .\n $sfField['SubscriberPackageVersion']['BuildNumber'];\n } catch (\\Exception) {\n $version = null;\n }\n\n return $version;\n }\n\n /**\n * Store transcripts as note.\n *\n * @throws \\Exception\n */\n public function createTranscriptNotes(Activity $activity): void\n {\n // For SF we also check if Log Notes is enabled.\n if ($this->profile->log_notes === Profile::LOG_NOTE_NONE) {\n return;\n }\n\n if ($activity->opportunity_id && $activity->prospect === null) {\n return;\n }\n\n try {\n $transcriptionData = $this->generateTranscription($activity);\n\n $noteMaxLength = $this->profile->log_notes === Profile::LOG_NOTE_ENHANCED\n ? self::ENHANCED_NOTE_MAX_LENGTH\n : self::CLASSIC_NOTE_MAX_LENGTH;\n\n $title = 'Transcript for ';\n $title .= $activity->title ?? $activity->activity_title;\n\n // Truncate Notes with max notes length because transcription text could be very long.\n $body = mb_strimwidth($transcriptionData, 0, $noteMaxLength);\n\n if ($activity->opportunity_id) {\n $objectId = $activity->opportunity->crm_provider_id;\n } else {\n $objectId = $activity->prospect->crm_provider_id;\n }\n\n $noteId = $this->saveNote($title, $body, $objectId);\n\n // Store crm logged id in transcription.\n $transcription = $activity->getTranscription();\n $transcription->crm_activity_id = $noteId;\n $transcription->save();\n } catch (\\Exception $e) {\n \\Sentry::captureException($e);\n }\n }\n\n public function saveNote(string $title, string $body, string $objectId, ?NoteObject $noteObject = null): ?string\n {\n $noteId = null;\n\n try {\n if ($this->profile->log_notes === Profile::LOG_NOTE_ENHANCED) {\n $noteId = $this->buildEnhancedNote($title, $body, $objectId);\n } else {\n $noteId = $this->buildClassicNote($title, $body, $objectId);\n }\n } catch (HttpNotFoundException $exception) {\n // The profile not having access to create Enhanced Notes. Set their preference to Classic.\n if ($this->profile->log_notes === Profile::LOG_NOTE_ENHANCED) {\n $this->profile->update([\n 'log_notes' => Profile::LOG_NOTE_CLASSIC,\n ]);\n }\n }\n\n return $noteId;\n }\n\n /**\n * This is using the \"Enhanced\" Notes feature, NOT the \"Notes & Attachments\" feature being deprecated.\n *\n * @url https://salesforce.stackexchange.com/questions/104408/how-can-i-create-an-account-note-or-contact-note-via-api-that-is-visible-in-sale\n */\n private function buildEnhancedNote(string $title, string $body, string $objectId): string\n {\n // Decode stored entities, escape HTML (without quoting), then convert line breaks for Salesforce formatting\n $decodedBody = html_entity_decode($body, ENT_QUOTES | ENT_HTML5);\n $sanitizedBody = htmlspecialchars($decodedBody, ENT_NOQUOTES, 'UTF-8', false);\n $content = nl2br($sanitizedBody, false);\n $note = [\n 'OwnerId' => $this->profile->crm_provider_id,\n 'Title' => $title,\n 'Content' => base64_encode($content),\n ];\n\n $noteId = $this->createRecord('ContentNote', $note);\n\n $link = [\n 'ContentDocumentId' => $noteId,\n 'LinkedEntityId' => $objectId,\n 'ShareType' => 'I',\n ];\n\n $this->createRecord('ContentDocumentLink', $link);\n\n return $noteId;\n }\n\n private function buildClassicNote(string $title, string $body, string $objectId): string\n {\n if (in_array($this->parseObjectType($objectId), [Field::OBJECT_TASK, Field::OBJECT_EVENT])) {\n $this->logger->info('[Salesforce] Summary not sent', [\n 'profile_id' => $this->profile->id,\n 'objectId' => $objectId,\n 'reason' => 'Classical Note does not support Task/Event relation',\n ]);\n\n return '';\n }\n\n $titleTrimmed = null;\n\n if (mb_strlen($title) > 80) {\n $titleTrimmed = substr($title, 0, 77) . '...';\n }\n $payload = [\n 'OwnerId' => $this->profile->crm_provider_id,\n 'IsPrivate' => false,\n 'Title' => $titleTrimmed ?? $title,\n 'Body' => $titleTrimmed ? $title . PHP_EOL . $body : $body,\n 'ParentId' => $objectId,\n ];\n\n return $this->createRecord('Note', $payload);\n }\n\n /**\n * @inheritdoc\n */\n public function find(string $name, array $scopes): array\n {\n if ($this->profile === null) {\n return [];\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $limitValues = ['limit' => $this->limit, 'offset' => $this->offset];\n $sosl = $queryBuilder->buildFindQuery($name, $scopes, $limitValues);\n\n $this->logger->info('[Salesforce] Find prospects', [\n 'profile_id' => $this->profile->id,\n 'sosl_query' => $sosl,\n 'search_string' => $name,\n 'scopes' => $scopes,\n ]);\n\n $data = Cache::remember($this->profile->id . $sosl, self::CACHE_TTL, function () use ($sosl) {\n $data = [];\n\n try {\n // Hit remote API.\n $objects = $this->queryHandler->search($sosl);\n\n // Build mapped list.\n foreach ($objects as $object) {\n $type = strtolower($object['attributes']['type']);\n\n $record = [\n 'crmId' => $object['Id'],\n 'name' => $object['Name'],\n 'prospectType' => $type,\n 'phoneNumbers' => [],\n 'crmUrl' => $this->generateProviderUrl($object['Id'], $type),\n ];\n\n switch ($type) {\n case 'lead':\n if (empty($object['Company']) === false) {\n $record['organization'] = $object['Company'];\n }\n\n if (empty($object['Title']) === false) {\n $record['title'] = $object['Title'];\n }\n\n $stage = $this->config->stages()\n ->where('type', Stage::TYPE_LEAD)\n ->where('name', $object['Status'])\n ->first();\n\n // Lazy create the stage.\n if ($stage === null) {\n $stage = $this->importStages([Stage::TYPE_LEAD], $object['Status']);\n }\n\n if ($stage) {\n $record += [\n 'stage' => [\n 'id' => $stage->id_string,\n 'name' => $stage->name,\n ],\n ];\n }\n\n if (empty($object['RecordTypeId']) === false) {\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $object['RecordTypeId'])\n ->first();\n\n if ($recordType) {\n $record += [\n 'recordType' => [\n 'id' => $recordType->id_string,\n 'name' => $recordType->name,\n ],\n ];\n }\n }\n\n break;\n\n case 'account':\n if (empty($object['Industry']) === false) {\n $record['industry'] = $object['Industry'];\n $record['detailsLine'] = $object['Industry'];\n }\n if (! empty($object['PersonEmail'])) {\n $record['detailsLine'] = $object['PersonEmail'];\n }\n\n break;\n\n case 'contact':\n // For contacts, we should try and fetch their account name too.\n if ($object['AccountId']) {\n // Cheaper to get this locally.\n $account = $this->config->accounts()\n ->where('crm_provider_id', $object['AccountId'])\n ->first(['name']);\n\n if ($account) {\n $record['organization'] = $account->name;\n }\n }\n\n if (! empty($object['IsPersonAccount']) && $object['Email']) {\n $record['detailsLine'] = $object['Email'];\n } else {\n if (empty($object['Title']) === false) {\n $record['title'] = $object['Title'];\n }\n }\n\n break;\n }\n\n // Add phone numbers to record.\n if (empty($object['Phone']) === false && $object['Phone']) {\n $record['phoneNumbers'][] = [\n 'number' => $object['Phone'],\n 'nationalFormat' => phone_national($this->profile->user->country_code, $object['Phone']),\n 'type' => 'phone',\n ];\n }\n\n if (empty($object['MobilePhone']) === false && $object['MobilePhone']) {\n $record['phoneNumbers'][] = [\n 'number' => $object['MobilePhone'],\n 'nationalFormat' => phone_national(\n $this->profile->user->country_code,\n $object['MobilePhone']\n ),\n 'type' => 'mobile',\n ];\n }\n\n $data[] = $record;\n }\n } catch (NoResultsException $e) {\n $data = [];\n }\n\n return $data;\n });\n\n return $data;\n }\n\n /**\n * @inheritdoc\n */\n public function findOpportunities(?string $crmAccountId, ?string $crmContactId, ?int $userId = null): array\n {\n $data = [];\n $ownerData = [];\n $ownerId = null;\n\n if ($crmAccountId === null) {\n return $data;\n }\n\n if ($userId) {\n $profileRepository = app(ProfileRepository::class);\n $profile = $profileRepository->findProfileByUserId($this->config, $userId);\n\n $ownerId = $profile instanceof Profile ? $profile->getCrmProviderId() : null;\n }\n\n try {\n // Perhaps their profile has no opportunity permissions.\n if ($this->profile === null || $this->profile->opportunity_fields === null) {\n return $data;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $query = $queryBuilder->buildFindOpportunitiesQuery();\n\n $objects = $this->queryHandler->query($query, ['accountId' => $crmAccountId]);\n\n foreach ($objects as $object) {\n $record = [\n 'crmId' => $object['Id'],\n 'name' => $object['Name'],\n 'won' => $object['IsWon'],\n 'closed' => $object['IsClosed'],\n ];\n\n $valueFieldName = 'Amount';\n if ($this->config->opportunity_value_field_id) {\n $valueFieldName = $this->config->opportunityValueField->crm_provider_id;\n }\n\n if (empty($object[$valueFieldName]) === false) {\n $currency = $object['CurrencyIsoCode'] ?? $this->config->default_currency;\n $value = formatCurrency($object[$valueFieldName], $currency);\n\n $record += [\n 'value' => $value,\n ];\n }\n\n $stage = $this->config->stages()\n ->where('type', Stage::TYPE_OPPORTUNITY)\n ->where('name', $object['StageName'])\n ->first();\n\n // Lazy create the stage.\n if ($stage === null) {\n $stage = $this->importStages([Stage::TYPE_OPPORTUNITY], $object['StageName']);\n }\n\n $record += [\n 'stage' => [\n 'id' => $stage->id_string,\n 'name' => $stage->name,\n ],\n ];\n\n if (empty($object['RecordTypeId']) === false) {\n $recordType = $this->config->recordTypes()\n ->where('crm_provider_id', $object['RecordTypeId'])\n ->first();\n\n if ($recordType) {\n $record += [\n 'recordType' => [\n 'id' => $recordType->id_string,\n 'name' => $recordType->name,\n ],\n ];\n }\n }\n\n if ($ownerId && isset($object['OwnerId']) && $object['OwnerId'] === $ownerId) {\n $ownerData[] = $record;\n }\n\n $data[] = $record;\n }\n } catch (NoResultsException $e) {\n return $data;\n }\n\n if (! empty($ownerData)) {\n return $ownerData;\n }\n\n return $data;\n }\n\n public function getContactRolesFromCrm(?Carbon $since = null): array\n {\n $roles = [];\n\n if ($this->profile === null) {\n return $roles;\n }\n\n $queryBuilder = app(QueryBuilder::class, ['profile' => $this->profile]);\n\n $query = $queryBuilder->buildGetContactRolesQuery($since);\n\n try {\n $objects = $this->queryHandler->query($query);\n\n foreach ($objects as $object) {\n $roles[] = [\n 'id' => $object['Id'],\n 'contactId' => $object['ContactId'],\n 'opportunityId' => $object['OpportunityId'],\n 'ownerId' => $object['Opportunity']['OwnerId'] ?? null,\n 'isPrimary' => $object['IsPrimary'],\n 'role' => $object['Role'],\n ];\n }\n } catch (NoResultsException) {\n // Just return an empty array.\n $this->logger->info('[Salesforce] No contact roles found', [\n 'since' => $since?->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n }\n\n return $roles;\n }\n\n public function syncContactRoles(Carbon $since): int\n {\n $contactRoleRepository = app(ContactRoleRepository::class);\n\n $crmContactRoles = $this->getContactRolesFromCrm(since: $since);\n $syncCount = 0;\n $contactRoles = [];\n\n foreach ($crmContactRoles as $crmContactRole) {\n $contactRoles[] = $this->importContactRole($crmContactRole);\n $syncCount++;\n }\n\n $contactRoleRepository->saveContactRoles($contactRoles);\n\n $this->syncRemotelyDeletedContactRoles();\n\n return $syncCount;\n }\n\n private function importContactRole(array $contactRole): array\n {\n $contact = $this->config->contacts()\n ->where('crm_provider_id', $contactRole['contactId'])\n ->first();\n\n if ($contact === null) {\n $contact = $this->syncContact($contactRole['contactId']);\n }\n\n $opportunity = $this->config->opportunities()\n ->where('crm_provider_id', $contactRole['opportunityId'])\n ->first();\n\n if ($opportunity === null) {\n $opportunity = $this->syncOpportunity($contactRole['opportunityId']);\n }\n\n $role = null;\n if (! empty($contactRole['role'])) {\n $role = mb_strimwidth($contactRole['role'], 0, 191);\n }\n\n return [\n 'crm_configuration_id' => $this->config->getId(),\n 'contact_id' => $contact->getId(),\n 'crm_provider_id' => $contactRole['id'],\n 'subject_type' => ContactRole::SUBJECT_TYPE_OPPORTUNITY,\n 'subject_id' => $opportunity->getId(),\n 'is_primary' => $contactRole['isPrimary'],\n 'role' => $role,\n ];\n }\n\n protected function syncRemotelyDeletedContactRoles(): bool\n {\n try {\n $deletedRemotely = $this->queryHandler->queryDeleted('OpportunityContactRole');\n } catch (NoResultsException $e) {\n return false;\n }\n\n $deletedOpportunities = $deletedRemotely->getResults();\n $deletedIds = array_column($deletedOpportunities, 'id');\n\n $contactRoleRepository = app(ContactRoleRepository::class);\n\n foreach (array_chunk($deletedIds, self::HARD_DELETE_CHUNK) as $chunk) {\n $contactRoleRepository->deleteContactRoles($chunk);\n\n $this->logger->info('[' . $this->getDisplayName() . '] Remotely deleted opportunities synced', [\n 'teamId' => $this->team->id_string,\n 'remotelyDeletedOpportunities' => $chunk,\n 'count' => count($chunk),\n ]);\n }\n\n return true;\n }\n\n /**\n * @inheritdoc\n */\n public function getTasks(string $objectType, string $objectId, ?string $opportunityId): array\n {\n $data = $objects = [];\n\n $hasWho = \\in_array($objectType, ['lead', 'contact']);\n $playbook = $this->getPlaybook($this->profile->user);\n $fields = array_merge(\n $this->profile->getFieldsAsArray(parent::OBJECT_TASK),\n $playbook && $playbook->activityField ? [$playbook->activityField->crm_provider_id] : []\n );\n\n // Query should default to any open call for that user.\n $query = '\n SELECT ' . implode(',', array_unique($fields)) . '\n FROM Task\n WHERE OwnerId = :ownerId\n AND IsArchived = false\n AND IsDeleted = false\n AND IsClosed = false\n AND (';\n\n if ($objectType === 'account') {\n // This covers tasks tied to a related contact or opportunity too.\n $query .= '\n AccountId = :accountId';\n }\n\n if ($hasWho) {\n $query .= '\n WhoId = :whoId';\n\n // If we are also going to check on a specific opportunity, set that up.\n if ($opportunityId) {\n $query .= ' OR WhatId = :whatId';\n }\n }\n\n $query .= ' ) ORDER BY LastModifiedDate DESC';\n\n try {\n $objects = $this->queryHandler->query($query, [\n 'ownerId' => $this->profile->crm_provider_id,\n 'whoId' => $objectId,\n 'whatId' => $opportunityId,\n 'accountId' => $objectId,\n ]);\n } catch (NoResultsException $e) {\n return $data;\n } finally {\n $this->logger->debug(sprintf('[Salesforce] Found %s tasks for query \"%s\"', count($objects), $query));\n }\n\n foreach ($objects as $object) {\n $dueDate = $object['ActivityDate'] ? Carbon::parse($object['ActivityDate'])->toIso8601String() : null;\n $data[] = [\n 'crmId' => $object['Id'],\n 'subject' => $object['Subject'],\n 'due' => $dueDate,\n 'type' => $object[$playbook->activityField->crm_provider_id],\n ];\n }\n\n return $data;\n }\n\n /**\n * @inheritdoc\n */\n public function getEvents(string $objectType, string $objectId, ?string $opportunityId): array\n {\n $data = $objects = [];\n $user = $this->profile?->user;\n if ($this->profile === null || $user === null) {\n return $data;\n }\n\n $hasWho = \\in_array($objectType, ['lead', 'contact']);\n $playbook = $this->getPlaybook($user);\n $fields = array_merge(\n $this->profile->getFieldsAsArray(parent::OBJECT_EVENT),\n $playbook && $playbook->activityField ? [$playbook->activityField->crm_provider_id] : []\n );\n\n // Query should default to any event starting in the last week and ending up until today owned by the user.\n $query = '\n SELECT ' . implode(',', array_unique($fields)) . '\n FROM Event\n WHERE OwnerId = :ownerId\n AND IsArchived = false\n AND IsAllDayEvent = false\n AND StartDateTime >= LAST_N_DAYS:7\n AND EndDateTime <= TODAY\n AND (';\n\n if ($objectType === 'account') {\n // This covers events tied to a related contact or opportunity too.\n $query .= '\n AccountId = :accountId';\n }\n\n if ($hasWho) {\n $query .= '\n WhoId = :whoId';\n\n // If we are also going to check on a specific opportunity, set that up.\n if ($opportunityId) {\n $query .= ' OR WhatId = :whatId';\n }\n }\n\n $query .= ' ) ORDER BY LastModifiedDate DESC';\n\n try {\n $objects = $this->queryHandler->query($query, [\n 'ownerId' => $this->profile->crm_provider_id,\n 'whoId' => $objectId,\n 'whatId' => $opportunityId,\n 'accountId' => $objectId,\n ]);\n } catch (NoResultsException $e) {\n return $data;\n } finally {\n $this->logger->debug(sprintf('[Salesforce] Found %s tasks for query \"%s\"', count($objects), $query));\n }\n\n foreach ($objects as $object) {\n $dueDate = $object['StartDateTime'] ? Carbon::parse($object['StartDateTime'])->toIso8601String() : null;\n\n $data[] = [\n 'crmId' => $object['Id'],\n 'subject' => $object['Subject'],\n 'due' => $dueDate,\n 'type' => $object[$playbook->activityField->crm_provider_id],\n ];\n }\n\n return $data;\n }\n\n /**\n * Try to find CRM Objects using email address\n *\n * @return null|array{\n * Lead|null,\n * Account|null,\n * Opportunity|null,\n * Contact|null,\n * Stage|null,\n * string|null\n * }\n */\n public function matchExactlyByEmail(string $email, ?int $userId = null): ?array\n {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $sosl = $queryBuilder->buildMatchByQuery($email, Field::TYPE_EMAIL);\n if ($sosl === null) {\n return null;\n }\n\n try {\n $objects = $this->queryHandler->search($sosl);\n $objects = $this->queryHandler->prioritiseResults(\n $objects,\n $email,\n QueryHandler::PRIORITISE_EMAIL\n );\n\n $data = $this->convertCrmData($objects, $userId);\n\n return ! empty(array_filter($data)) ? $data : null;\n } catch (NoResultsException $e) {\n // Try the account next.\n if ($this->profile->account_fields === null) {\n return null;\n }\n }\n\n return null;\n }\n\n public function getDomain(string $email): ?string\n {\n // SF improved search - strip the domain extension, min domain name length 4\n return $this->getCompanyNameFromEmail(email: $email, minNameLength: 4);\n }\n\n /**\n * Try to find CRM objects using domain name of the email address\n *\n * @return null|array{\n * Lead|null,\n * Account|null,\n * Opportunity|null,\n * Contact|null,\n * Stage|null,\n * string|null\n * }\n */\n public function matchByDomain(string $domain, ?int $userId = null): ?array\n {\n $companyName = $domain;\n\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $sosl = $queryBuilder->buildMatchByDomainQuery($companyName);\n\n try {\n $objects = $this->queryHandler->search($sosl);\n\n $data = $this->convertCrmData($objects, $userId);\n\n return ! empty(array_filter($data)) ? $data : null;\n } catch (NoResultsException) {\n return null;\n }\n }\n\n public function matchByPhone(string $phone, ?string $rawPhoneNumber = null, ?int $userId = null): ?array\n {\n // Don't bother looking up numbers that are masked.\n if (str_contains($phone, '**')) {\n return null;\n }\n\n if ($this->isPhoneNumberOfTeamMember($phone)) {\n return null;\n }\n\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $phoneNational = phone_national(null, $phone) ?? '';\n $possiblePhoneFormats = collect([\n preg_replace('/\\D/', '', ltrim($phone, '0+')),\n preg_replace('/\\D/', '', $phoneNational),\n formatDashPhoneNumber($phone),\n $phoneNational,\n ])\n ->filter() // Removes null and empty strings\n ->unique()\n ->values();\n\n foreach ($possiblePhoneFormats as $phone) {\n $sosl = $queryBuilder->buildMatchByQuery($phone, Field::TYPE_PHONE);\n if ($sosl === null) {\n continue;\n }\n\n try {\n $objects = $this->queryHandler->search($sosl);\n $objects = $this->queryHandler->prioritiseResults(\n $objects,\n $phone,\n QueryHandler::PRIORITISE_PHONE\n );\n\n return $this->convertCrmData($objects, $userId);\n } catch (NoResultsException) {\n continue;\n }\n }\n\n return null;\n }\n\n private function isPhoneNumberOfTeamMember(string $phone): bool\n {\n $teamRepository = app(TeamRepository::class);\n $user = $teamRepository->findTeamMemberByPhone($this->team, $phone);\n\n if ($user instanceof User) {\n return true;\n }\n\n return false;\n }\n\n protected function getCacheKey(string $object, ?int $userId = null): ?string\n {\n $key = $this->profile->id . $object;\n $keySuffix = $this->getOwnerKeySuffix($userId);\n\n return $key . $keySuffix;\n }\n\n private function getOwnerKeySuffix(?int $userId = null): string\n {\n return $userId === null ? '' : (string) $userId;\n }\n\n /** Determine the CRM Objects which represent the call activity. */\n public function matchByName(string $name, ?int $userId = null): ?array\n {\n // Don't waste time searching for single character strings.\n if (\\strlen($name) <= 1) {\n return null;\n }\n\n if ($this->profile === null) {\n return null;\n }\n\n $cacheKey = $this->getCacheKey($name, $userId);\n\n $result = Cache::remember($cacheKey, 60, function () use ($name, $userId) {\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $sosl = $queryBuilder->buildMatchByQuery($name, 'name');\n if ($sosl === null) {\n return false;\n }\n\n try {\n $objects = $this->queryHandler->search($sosl);\n } catch (NoResultsException $e) {\n return false;\n }\n\n $objects = $this->queryHandler->prioritiseResults(\n $objects,\n $name,\n QueryHandler::PRIORITISE_NAME\n );\n\n $data = $this->convertCrmData($objects, $userId);\n\n return (! empty(array_filter($data))) ? $data : false;\n });\n\n return is_array($result) ? $result : null;\n }\n\n /**\n * @return array{\n * Lead|null,\n * Account|null,\n * Opportunity|null,\n * Contact|null,\n * Stage|null,\n * string|null\n * }\n */\n protected function convertCrmData(QueryIterator $objects, ?int $userId = null): array\n {\n $lead = null;\n $contact = null;\n $opportunity = null;\n $account = null;\n $stage = null;\n $countryCode = null;\n\n if ($objects->count() > 0) {\n $object = $objects->current();\n\n if ($object['attributes']['type'] === 'Lead') {\n $lead = $this->importLead($object);\n\n // Lead might not be imported if the Stage is null for example.\n if ($lead) {\n $countryCode = $lead->country_code;\n $stage = $lead->stage;\n }\n } else {\n if ($object['attributes']['type'] === 'Contact') {\n $contact = $this->importContact($object);\n $account = $contact?->account;\n } else {\n $account = $this->importAccount($object);\n }\n\n if ($contact && $contact->country_code) {\n $countryCode = $contact->country_code;\n } elseif ($account) {\n $countryCode = $account->country_code;\n }\n\n try {\n $sfOpportunities = $this->findOpportunities(\n $account?->getCrmProviderId(),\n $contact?->getCrmProviderId(),\n $userId\n );\n\n // Take the first opportunity, which will be ordered as priority based on their settings.\n if (! empty($sfOpportunities)) {\n // Persist this remote object.\n $opportunity = $this->syncOpportunity($sfOpportunities[0]['crmId']);\n $stage = $opportunity?->stage;\n }\n } catch (Exception) {\n // Nothing to see here.\n }\n }\n }\n\n return [\n $lead,\n $account,\n $opportunity,\n $contact,\n $stage,\n $countryCode,\n ];\n }\n\n /**\n * @inheritdoc\n */\n public function updateStage($crmObject, Stage $stage): void\n {\n if ($stage->type === Stage::TYPE_LEAD) {\n $objectType = 'Lead';\n $objectId = $crmObject->crm_provider_id;\n $objectStageType = 'Status';\n } else {\n $objectType = 'Opportunity';\n $objectId = $crmObject->crm_provider_id;\n $objectStageType = 'StageName';\n }\n\n $headers = [];\n if ($this->config->trigger_assignment_rules === false) {\n // @see: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/headers_autoassign.htm\n $headers = [\n 'Sforce-Auto-Assign' => 'false',\n ];\n }\n\n $this->updateRecord($objectType, $objectId, [$objectStageType => $stage->name], $headers);\n }\n\n public function parseObjectType(string $objectId): string\n {\n if (Str::startsWith($objectId, '001')) {\n return 'account';\n }\n\n if (Str::startsWith($objectId, '003')) {\n return 'contact';\n }\n\n if (Str::startsWith($objectId, '00Q')) {\n return 'lead';\n }\n\n if (Str::startsWith($objectId, '006')) {\n return 'opportunity';\n }\n\n if (Str::startsWith($objectId, '00U')) {\n return 'event';\n }\n\n if (Str::startsWith($objectId, '00T')) {\n return 'task';\n }\n\n throw new \\InvalidArgumentException('Unsupported Object Type');\n }\n\n public function syncProfiles(?User $userToSearch = null): ?Profile\n {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, ['profile' => $this->profile]);\n $query = $queryBuilder->buildGetUsersQuery($userToSearch);\n\n try {\n $salesforceUsers = $this->queryHandler->query($query, [\n 'active' => true,\n ]);\n } catch (NoResultsException $e) {\n $this->logger->info('[Salesforce] Sync Profiles. No users found', [\n 'query' => $query,\n 'error' => $e->getMessage(),\n ]);\n\n return null;\n }\n\n $teamRepository = app(TeamRepository::class);\n $customRules = $this->getCustomProfileRules($teamRepository);\n\n foreach ($salesforceUsers as $crmUser) {\n if ($crmUser['Email'] === null) {\n continue;\n }\n\n if (! $this->customProfileValidation($crmUser, $customRules)) {\n continue;\n }\n\n $user = $teamRepository->findActiveTeamMemberByEmail($this->team, $crmUser['Email']);\n\n if (! $user instanceof User) {\n continue;\n }\n\n $edition = $crmUser['UserPreferencesLightningExperiencePreferred']\n ? Profile::EDITION_LIGHTNING\n : Profile::EDITION_CLASSIC;\n\n $profileRepository = app(ProfileRepository::class);\n $profile = $profileRepository->updateOrCreateProfile(\n $user,\n [\n 'crm_configuration_id' => $this->config->getId(),\n 'crm_provider_id' => $crmUser['Id'],\n ],\n [\n 'user_id' => $user->getId(),\n 'edition' => $edition,\n 'has_external_cti' => ! empty($crmUser['CallCenterId']),\n 'crm_profile_id' => $crmUser['ProfileId'],\n ]\n );\n\n if ($userToSearch instanceof User && $userToSearch->getId() === $user->getId()) {\n return $profile;\n }\n }\n\n // Clean up inactive profiles\n try {\n $this->archiveInactiveProfiles();\n } catch (\\Exception $e) {\n $this->logger->warning('[Salesforce] Profile archiving failed', [\n 'teamId' => $this->team->getUuid(),\n 'reason' => $e->getMessage(),\n ]);\n }\n\n return null;\n }\n\n public function generateProviderUrl(string $providerId, string $objectType): ?string\n {\n $url = null;\n\n // For Salesforce it's easy, we just point every object to the apex domain and they handle it.\n switch ($objectType) {\n case 'lead':\n case 'account':\n case 'contact':\n case 'opportunity':\n case 'task':\n case 'event':\n case 'activity':\n\n $url = $this->config->crm_base_url . '/' . $providerId;\n\n break;\n }\n\n return $url;\n }\n\n public function buildTaskSearchFields(): array\n {\n return ['Id', 'WhoId', 'WhatId', 'AccountId'];\n }\n\n public function getTaskByFilterConditions(\n array $fields,\n array $filters,\n bool $bulkSearch = false,\n bool $strictFilters = true\n ): ?array {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $query = $queryBuilder->buildSearchTaskQuery($fields, $filters, $bulkSearch, $strictFilters);\n\n try {\n if (! $bulkSearch) {\n $objects = $this->queryHandler->query($query, $filters);\n if ($objects->count() === 1) {\n return $objects->current();\n }\n }\n\n if ($bulkSearch) {\n $objects = $this->queryHandler->query($query);\n $records = [];\n foreach ($objects as $record) {\n $key = $record[end($fields)];\n $records[$key] = $record;\n }\n\n return $records;\n }\n } catch (\\Exception $e) {\n $this->logger->info('[Salesforce] Failed to execute query', [\n 'query' => $query,\n 'error' => $e->getMessage(),\n ]);\n }\n\n return null;\n }\n\n public function mapCrmObjects(array $task): array\n {\n $activityData = [];\n\n if (! empty($task['WhoId'])) {\n $type = $this->parseObjectType($task['WhoId']);\n $activityData[$type] = $task['WhoId'];\n }\n if (! empty($task['AccountId'])) {\n $activityData['account'] = $task['AccountId'];\n }\n if (! empty($task['WhatId'])) {\n $activityData['opportunity'] = $task['WhatId'];\n }\n\n return $activityData;\n }\n\n /**\n * Get SF task by Outreach call id.\n */\n public function getTaskByFilter(\n string $activityFieldType,\n array $filters,\n string $operator = '=',\n array $additionalFields = []\n ): ?array {\n $data = [];\n\n try {\n // Default (base) fields.\n $fields = ['Id', 'Subject', 'Description', 'ActivityDate', 'WhoId', 'WhatId', $activityFieldType];\n\n foreach ($additionalFields as $additionalField) {\n $fields[] = $additionalField->crm_provider_id;\n }\n\n $fields = array_unique($fields);\n\n // Find task with the same Outreach id as the call id.\n $query = 'SELECT ' . implode(',', $fields) . '\n FROM Task\n WHERE IsArchived = false AND IsDeleted = false';\n\n foreach ($filters as $key => $value) {\n $key = preg_quote($key, '/');\n $key = str_replace(['\\'', '\"'], '', $key);\n // Prepare the substitution.\n $strKey = \":$key\";\n\n $query .= \" AND $key $operator $strKey\";\n }\n\n $query .= ' ORDER BY LastModifiedDate DESC LIMIT 1';\n\n $objects = $this->queryHandler->query($query, $filters);\n\n // There should be only one task related to this call if any.\n if ($objects->count() === 1) {\n $object = $objects->current();\n\n $dueDate = $object['ActivityDate'] ? Carbon::parse($object['ActivityDate'])->toIso8601String() : null;\n\n $data = array_merge($object, [\n 'crmId' => $object['Id'],\n 'subject' => $object['Subject'],\n 'summary' => $object['Description'],\n 'due' => $dueDate,\n 'Type' => $object[$activityFieldType],\n ]);\n }\n } catch (NoResultsException $e) {\n // Filters don't match any records.\n } catch (ServiceUnavailableException $serviceUnavailableException) {\n // Service cannot be queried. We should probably log this.\n }\n\n return $data;\n }\n\n /**\n * Get Salesforce fields including datetime fields\n *\n * @param $objectType\n */\n private function getAllFieldsAsArray($objectType): array\n {\n $basicFields = [];\n // Not all users have access to all object fields.\n if ($this->profile->{$objectType . '_fields'}) {\n $basicFields = explode(',', $this->profile->{$objectType . '_fields'});\n }\n\n $extraFields = [\n 'CreatedDate',\n 'LastModifiedDate',\n 'IsDeleted',\n ];\n\n if ($objectType === self::OBJECT_OPPORTUNITY\n && $this->config->opportunity_value_field_id\n && ! in_array($this->config->opportunityValueField->crm_provider_id, $basicFields)\n ) {\n $extraFields[] = $this->config->opportunityValueField->crm_provider_id;\n }\n\n return array_unique(array_merge($basicFields, $extraFields));\n }\n\n /**\n * Generate transcription for activity description.\n */\n private function generateTranscription(Activity $activity): string\n {\n if (! ($this->config->store_transcript)) {\n // If sending transcription to activity toggle is disabled\n return '';\n }\n\n return $this->transcriptionService\n ->findTranscriptionByActivity($activity)\n ->map(static function (array $transcriptionSegment): string {\n return $transcriptionSegment['formattedStartsAt'] . ' | ' . $transcriptionSegment['transcript'];\n })\n ->implode(PHP_EOL);\n }\n\n /**\n * Find related Salesforce event based on activity data\n *\n * @return array<string>\n */\n public function fetchRelatedActivity(Activity $activity): array\n {\n $this->logger->info('[Salesforce] Searching for related activity', [\n 'activityId' => $activity->getUuid(),\n 'ownerId' => $this->profile?->crm_provider_id,\n ]);\n\n $sfEvent = $this->fetchRelatedEvent($activity);\n if (empty($sfEvent)) {\n $this->logger->info('[Salesforce] No related activity found', [\n 'activityId' => $activity->getUuid(),\n 'ownerId' => $this->profile?->crm_provider_id,\n 'account' => $activity->hasAccount()\n ? $activity->getAccount()->getCrmProviderId()\n : null,\n ]);\n\n return [];\n }\n\n return $sfEvent;\n }\n\n public function fetchAndAssociateRelatedActivity(Activity $activity): ?Activity\n {\n if ($activity->isTypeConference() === false) {\n return null;\n }\n\n if ($activity->hasActualStartTime() === false && $activity->hasScheduledStartTime() === false) {\n return null;\n }\n\n if (! $activity->hasProspect()) {\n $this->logger->info('[Salesforce] Skip look up, Activity not linked to Lead, Contact or Account', [\n 'activityId' => $activity->getUuid(),\n ]);\n\n return null;\n }\n\n $playbook = $this->getPlaybook($activity->getUser());\n if ($playbook !== null && $playbook->getActivityType() === Playbook::ACTIVITY_TYPE_TASK) {\n $this->logger->info('[Salesforce] Skip auto-sync for task-based playbook', [\n 'activityUuid' => $activity->getUuid(),\n 'playbookId' => $playbook->getId(),\n 'playbookType' => $playbook->getActivityType(),\n ]);\n\n return null;\n }\n\n try {\n $sfEvent = $this->fetchRelatedActivity($activity);\n if (empty($sfEvent)) {\n return null;\n }\n\n [$activityField, $activityType] = $this->resolveActivityTypeFromEvent($activity, $sfEvent);\n\n $this->logger->info('[Salesforce] Found related activity', [\n 'activityId' => $activity->getUuid(),\n 'sfEvent' => $sfEvent['Id'],\n 'activityFieldName' => $activityField,\n 'crmActivityType' => ($activityField !== null && isset($sfEvent[$activityField]))\n ? $sfEvent[$activityField]\n : null,\n 'activityType' => $activityType,\n ]);\n\n $userId = $this->findRelatedActivityUserId($activity, $sfEvent);\n\n if ($activity->getUserId() !== $userId) {\n $this->logger->info('[Salesforce] Updating meeting owner', [\n 'activityId' => $activity->getUuid(),\n 'oldUserId' => $activity->getUserId(),\n 'newUserId' => $userId,\n ]);\n }\n\n $this->updateSfEventDescription($activity, $sfEvent);\n\n $activity->update([\n 'user_id' => $userId,\n 'crm_provider_id' => $sfEvent['Id'],\n 'playbook_category_id' => $activityType->id ?? $activity->getCategory()?->getId(),\n ]);\n\n $this->logger->info('[Salesforce] Activity updated', [\n 'activityId' => $activity->getUuid(),\n ]);\n\n return $activity;\n } catch (\\Exception $exception) {\n \\Sentry::captureException($exception);\n\n throw $exception;\n }\n }\n\n /**\n * @param array<string, mixed> $sfEvent\n *\n * @return array{0: string|null, 1: mixed}\n */\n private function resolveActivityTypeFromEvent(Activity $activity, array $sfEvent): array\n {\n $activityField = $this->getActivityFieldName($activity);\n $activityType = null;\n\n if ($activityField !== null && ! empty($sfEvent[$activityField])) {\n $playbook = $this->getPlaybook($activity->getUser());\n $activityType = $this->getPlaybookCategory($playbook, strval($sfEvent[$activityField]));\n }\n\n return [$activityField, $activityType];\n }\n\n /**\n * @param array<string> $sfEvent\n */\n private function findRelatedActivityUserId(Activity $activity, array $sfEvent): int\n {\n $userId = $activity->getUserId();\n\n if (empty($sfEvent['OwnerId']) === false) {\n $profile = $this\n ->config\n ->profiles()\n ->where('crm_provider_id', $sfEvent['OwnerId'])\n ->get()\n ->filter(static function (Profile $profile) use ($activity): bool {\n if (! $activity->isTypeConference()) {\n return ! empty($profile->user) ? $profile->user->isStatusActive() : false;\n }\n\n $participants = $activity->getParticipants();\n\n return ! empty($profile->user)\n ? $profile->user->isStatusActive()\n && $profile->user->hasPermission(PermissionEnum::RECORD_MEETING)\n && $participants->contains('user_id', $profile->user_id)\n : false;\n })\n ->first();\n\n if ($profile) {\n $userId = $profile->user_id;\n }\n }\n\n return $userId;\n }\n\n /**\n * @param array<string, mixed> $sfEvent\n */\n private function updateSfEventDescription(Activity $activity, array $sfEvent): void\n {\n try {\n if (str_contains($sfEvent['Description'], $activity->id_string)) {\n return;\n }\n\n $payload = [\n 'Description' => $sfEvent['Description']\n . PHP_EOL\n . PHP_EOL\n . new DecorateActivity()->generateDescription($activity),\n ];\n\n $this->logger->info('[Salesforce] Update record', [\n 'activityId' => $activity->getUuid(),\n 'sfEvent' => $sfEvent['Id'],\n 'payload' => $payload,\n ]);\n\n $payload = array_merge(\n $payload,\n $this->payloadBuilder->fetchCustomFieldData($activity, Field::OBJECT_EVENT)\n );\n\n $this->updateRecord('Event', $sfEvent['Id'], $payload);\n } catch (\\Exception) {\n $this->logger->error('[Salesforce] Failed to update record', [\n 'activityUuid' => $activity->getUuid(),\n 'sfEvent' => $sfEvent['Id'],\n ]);\n }\n }\n\n /**\n * Returns the most recently modified Event within time range (if any).\n *\n * @return array|null An Event record from Salesforce.\n */\n private function fetchRelatedEvent(Activity $activity): ?array\n {\n $ownerId = $this->profile?->crm_provider_id;\n if ($ownerId === null) {\n return [];\n }\n\n /** @var ?Carbon $from */\n /** @var ?Carbon $to */\n [$from, $to] = $this->getFromToDates($activity);\n\n try {\n $whoId = null;\n $hasWho = $activity->lead_id || $activity->contact_id;\n if ($hasWho) {\n $whoId = $activity->hasLead()\n ? $activity->getLead()->crm_provider_id\n : $activity->getContact()->crm_provider_id;\n }\n\n if ($hasWho === false && $activity->account_id === null) {\n return null;\n }\n\n $query = $this->buildFetchRelatedEventQuery($activity);\n\n $objects = $this->queryHandler->query($query, [\n 'ownerId' => $ownerId,\n 'whoId' => $whoId,\n 'whatId' => $activity->hasOpportunity() ? $activity->getOpportunity()->crm_provider_id : null,\n 'accountId' => $activity->hasAccount() ? $activity->getAccount()->crm_provider_id : null,\n 'from' => $from?->format('Y-m-d\\TH:i:s\\Z'),\n 'to' => $to?->format('Y-m-d\\TH:i:s\\Z'),\n ]);\n\n foreach ($objects as $object) {\n return $object;\n }\n } catch (NoResultsException $e) {\n return [];\n }\n\n return [];\n }\n\n private function getFromToDates(Activity $activity): array\n {\n $from = null;\n $to = null;\n\n /** @var ?CalendarEvent $calendarEvent */\n $calendarEvent = $activity->calendarEvent()->first();\n if ($calendarEvent !== null) {\n $from = $calendarEvent->getStartTime();\n $to = $calendarEvent->getEndTime();\n }\n\n // For non-calendar imported activities\n // Also double check if calendar event dates could be null?\n // If null use what we've got so far\n if ($from === null || $to === null) {\n $from = $activity->hasScheduledStartTime()\n ? $activity->getScheduledStartTime()\n : $activity->getActualStartTime();\n $to = $activity->hasScheduledEndTime()\n ? $activity->getScheduledEndTime()->addMinutes(15)\n : $activity->getActualEndTime();\n }\n\n return [$from, $to];\n }\n\n /**\n * Determines the appropriate activity field name for querying Salesforce events.\n *\n * This method follows a hierarchy to determine the field name:\n * 1. Uses the playbook's activity field if it exists and is in the profile's accessible fields\n * 2. Falls back to the default activity field if the profile has no event fields configured\n * 3. Returns null if no suitable field is found\n *\n * @param Activity $activity The activity to determine the field for\n *\n * @return string|null The field name to use in queries, or null if none is available\n */\n private function getActivityFieldName(Activity $activity): ?string\n {\n if ($this->profile === null) {\n $this->logger->warning('[Salesforce] Cannot determine activity field - profile not found', [\n 'activityId' => $activity->getUuid(),\n ]);\n\n return null;\n }\n\n $profileEventFields = $this->profile->getFieldsAsArray('event');\n\n if (empty($profileEventFields)) {\n $defaultActivityField = $this->getDefaultActivityField(Field::OBJECT_EVENT);\n $defaultFieldName = $defaultActivityField?->getAttribute('crm_provider_id');\n // Profile not yet synced — fall back to the default activity field.\n // There is a small chance that the profile won't have Default Activity Type field access\n // in which case the query will fail.\n // This is however an edge case and should be reviewed for profile sync issues.\n Sentry::withScope(function (\\Sentry\\State\\Scope $scope) use ($defaultFieldName): void {\n $scope->setContext('details', [\n 'profileId' => $this->profile->id,\n 'defaultField' => $defaultFieldName,\n ]);\n Sentry::captureMessage(\n '[Salesforce] Profile event fields empty, falling back to default activity field.',\n \\Sentry\\Severity::warning()\n );\n });\n\n return $defaultFieldName;\n }\n\n $playbook = $this->getPlaybook($activity->getUser());\n\n if (! is_null($playbook) && ! is_null($playbook->getActivityField())) {\n $playbookFieldName = $playbook->getActivityField()->getAttribute('crm_provider_id');\n\n if (in_array($playbookFieldName, $profileEventFields, true)) {\n return $playbookFieldName;\n }\n\n $this->logger->warning('[Salesforce] Playbook activity field not found in profile fields', [\n 'activityId' => $activity->getUuid(),\n 'playbookField' => $playbookFieldName,\n 'profileId' => $this->profile->id,\n ]);\n }\n\n return null;\n }\n\n private function buildFetchRelatedEventQuery(Activity $activity): string\n {\n $hasWho = $activity->lead_id || $activity->contact_id;\n\n $activityFieldName = $this->getActivityFieldName($activity);\n $fields = array_filter(['Id', 'Description', 'OwnerId', $activityFieldName]);\n\n $ownerCondition = '(OwnerId = :ownerId OR CreatedById = :ownerId)';\n\n $query = '\n SELECT ' . implode(',', $fields) . '\n FROM Event\n WHERE ' . $ownerCondition . '\n AND IsArchived = false\n AND IsAllDayEvent = false\n AND StartDateTime >= :from\n AND EndDateTime <= :to\n AND (';\n\n $operator = '';\n if ($activity->account_id) {\n // This covers events tied to a related contact or opportunity too.\n $query .= 'AccountId = :accountId';\n\n $operator = ' OR ';\n }\n\n if ($hasWho) {\n $query .= $operator . 'WhoId = :whoId';\n\n // If we are also going to check on a specific opportunity, set that up.\n if ($activity->opportunity_id) {\n $query .= ' OR WhatId = :whatId';\n }\n }\n\n $query .= ') ORDER BY LastModifiedDate DESC';\n\n return $query;\n }\n\n public function fetchProspect(array $task): array\n {\n $lead = $account = $opportunity = $contact = $stage = $countryCode = null;\n $externalId = $task['WhoId'] ?? null;\n\n // Lead or Contact\n if ($externalId) {\n try {\n [$lead, $account, $opportunity, $contact, $stage, $countryCode] = $this->parseRecords($externalId);\n } catch (\\InvalidArgumentException $exception) {\n // Invalid object type.\n }\n }\n\n // If we happen to know the opportunity or account from the Task, figure that out.\n if (empty($task['WhatId']) === false) {\n // WhatId could be either Account ID or Opportunity ID.\n // If WhatId is Opportunity ID, get the opportunity and stage from the CRM.\n try {\n [, $account, $opportunity, , $stage, ] = $this->parseRecords($task['WhatId']);\n } catch (\\InvalidArgumentException $exception) {\n // Invalid object type.\n }\n }\n\n return [$lead, $account, $opportunity, $contact, $stage, $countryCode];\n }\n\n /**\n * Save activity transcription summary as note\n */\n public function saveTranscriptionSummaryAsNote(\n ActivityContract $activity,\n string $title,\n string $body,\n ?string $objectId,\n ?NoteObject $noteObject = null,\n ): ?string {\n return $this->saveNote($title, $body, (string) $objectId);\n }\n\n public function getObjectByFilterConditions(string $objectType, array $fields, array $filters): ?array\n {\n if ($this->profile === null) {\n return null;\n }\n\n $queryBuilder = app(QueryBuilder::class, [\n 'profile' => $this->profile,\n ]);\n\n $query = $queryBuilder->buildObjectSearchQuery($objectType, $fields, $filters);\n\n try {\n $objects = $this->queryHandler->query($query, $filters);\n if ($objects->count() === 1) {\n return $objects->current();\n }\n } catch (\\Exception $e) {\n $this->logger->info('[Salesforce] Failed to execute query', [\n 'query' => $query,\n 'error' => $e->getMessage(),\n ]);\n }\n\n return null;\n }\n\n private function getCustomProfileRules(TeamRepository $teamRepository): array\n {\n $teamSettings = $teamRepository->getTeamSetting($this->team, 'custom_profile_validation');\n\n if ($teamSettings instanceof TeamSettings && $teamSettings->getValueType() === 'array') {\n $customRules = json_decode($teamSettings->getValue(), true);\n if (is_array($customRules)) {\n return $customRules;\n }\n }\n\n return [];\n }\n\n private function customProfileValidation(array $crmUser, array $customRules): bool\n {\n foreach ($customRules as $customRule) {\n if ($crmUser[$customRule['field']] !== $customRule['value']) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * When syncing Contact / Lead / Account / Opportunity / Stage crm entities,\n * validate and restore locally trashed objects,\n * before updating them. Objects are identified by CrmProviderId\n */\n private function restoreAnyTrashedEntity(HasMany $targetEntity, string $crmProviderId): void\n {\n $recordExists = $targetEntity->withTrashed()->where(['crm_provider_id' => $crmProviderId])->first();\n if ($recordExists && $recordExists->trashed()) {\n $recordExists->restore();\n }\n }\n\n #[\\Override] public function supportsNotes(): bool\n {\n return true;\n }\n\n private function getOwnerProfile(?string $ownerId): ?Profile\n {\n if ($ownerId === null) {\n return null;\n }\n\n return $this->config->profiles()\n ->where('crm_provider_id', $ownerId)\n ->first();\n }\n}","role_description":"text entry area","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Execute","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Explain Plan","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Browse Query History","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"View Parameters","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open Query Execution Settings…","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"In-Editor Results","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Tx: Auto","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Cancel Running Statements","depth":4,"on_screen":true,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Playground","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"jiminny","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Sync Changes","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide This Notification","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":false,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Code changed:","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.088194445,"height":0.027777778},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"45","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"41","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"66","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXButton","text":"Previous Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Next Highlighted Error","depth":4,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextArea","text":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01';\nand id IN (32415, 32416);\n# and id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;\n\nSELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436\n\nSELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses\nFROM text_relays\nWHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')\nGROUP BY email_provider_id;\nSELECT id, status, telephony_provider_id, created_at\nFROM activities\nWHERE id IN (80028719, 80028846);\nSELECT id, status, code, email_sent_at, created_at, updated_at\nFROM text_relays\nWHERE id IN (32415, 32416);\nSELECT id, status, code, sender, recipient, created_at\nFROM text_relays\nWHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'\nORDER BY created_at DESC\nLIMIT 10;\n\nSELECT id, uuid, status, code, sender, recipient, created_at, updated_at\nFROM text_relays\nWHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');\n\n# ***************\nSELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count\nFROM users u\nINNER JOIN activities a ON u.id = .user_id\nWHERE a.type LIKE 'sms%'\nAND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.email, u.name, u.softphone_number\nORDER BY sms_count DESC;\n\nselect * from teams where id = 1;\n\nselect * from roles;\n\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1117 and sa.provider = 'hubspot';\nSELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES\nSELECT * FROM activities WHERE uuid_to_bin('25529043-8094-4781-927f-4f4da2a8185c') = uuid; # 80186192 NO\nSELECT * FROM crm_configurations WHERE id = 1053;\nSELECT * FROM teams WHERE id = 1117;\nselect * from users where id = 30249;\nselect * from playbooks where id = 5473;\nselect * from playbook_categories where id = 43783;\nselect * from playbook_categories where playbook_id = 5473;\nselect * from crm_fields where id = 659242;\nselect * from crm_field_values where crm_field_id = 659242;\n\nSELECT * FROM crm_field_data fd\n# JOIN crm_fields f ON fd.crm_field_id = f.id\n# JOIN activities a ON fd.activity_id = a.id\nWHERE activity_id = 79933459\n# AND f.crm_provider_id = 'hs_activity_type';\n\n\nSELECT * FROM activity_messages;\nselect * from text_relays where created_at > '2026-05-01';\nselect * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;\nselect * from users where team_id = 1 and id IN (18608, 13934, 7160);\nselect * from activities where user_id = 7160 order by id desc limit 10;\n\nselect * from accounts where team_id = 1 and name = 'Column5';\n\nselect * from users where name like '%Subra%'; # 31054, 1117\nselect * from teams where id = 1117;\nselect * from activity_searches where user_id = 31054;\nselect * from activity_search_filters where activity_search_id IN (88882, 88902);","depth":4,"on_screen":true,"value":"SELECT * FROM teams WHERE name LIKE '%litify%'; # 1069, 994, 24993\nSELECT * FROM users WHERE id = 25061;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 994;\nSELECT * FROM crm_profiles WHERE user_id = 25061;\n\nselect * from crm_configurations where id = 834;\nSELECT * FROM teams WHERE id = 882;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot' and crm_provider_id = 7270388;\n\nSELECT * FROM contacts where crm_configuration_id = 834;\nSELECT * FROM opportunities WHERE team_id = 933\n# AND crm_provider_id IN ('20131586060','46017317898','52543911090','53451356564','54101251892','54323768459');\nAND id IN (8482561,18352941,19042734,19232139,19445140,19472541);\nSELECT * FROM opportunity_contacts\nWHERE opportunity_id IN (8482561,18352941,19042734,19232139,19445140,19472541);\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 485; #\nSELECT * FROM opportunities WHERE team_id = 933 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\nselect crm.provider, l.* from leads l join crm_configurations crm on l.crm_configuration_id = crm.id\nwhere crm.provider NOT IN ('salesforce', 'integration-app', 'bullhorn', 'copper')\n# and l.converted_at IS NOT NULL\n;\n\n# ********************************************************************\nSELECT * FROM activities a WHERE type IN ('email-inbound', 'email-outbound')\nand opportunity_id IS NULL\norder by id desc;\n\nSELECT * FROM teams WHERE id = 604; # 598\nSELECT * FROM activities WHERE id = 74410828; # chelseaw@allvoices.co\nSELECT * FROM accounts WHERE id = 20068382;\nSELECT * FROM accounts WHERE id = 35186038;\n\nSELECT * FROM contacts WHERE team_id = 852 and updated_at > '2026-01-23 12:30:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 559 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('cb6342b6-a183-401c-b0af-ede92b2ae763') = uuid;\nselect * from sidekick_settings where team_id = 781;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 26651871; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 7562435;\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8420347; # opflit 2100\n\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 711;\nSELECT * FROM activities where crm_configuration_id = 711 and crm_provider_id IS NULL\nand is_internal = 0 and status = 'completed'\norder by id desc;\n\nSELECT * FROM crm_layout_entities\nWHERE crm_layout_id IN (2352, 2353);\n;\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and id = 530;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 556 and sa.provider = 'hubspot';\n\nSELECT * FROM activities WHERE uuid_to_bin('c6ca4b22-7738-4563-a95d-b8a9598924ae') = uuid;\nSELECT * FROM activities WHERE uuid_to_bin('442abb2b-28bd-4be8-9c25-19e9bf02766d') = uuid;\nselect * from contacts\nwhere crm_configuration_id = 530\nand crm_provider_id = 872252;\n\nselect * from activities where crm_configuration_id = 530\nand user_id = 14343 and type like '%softphone%'\nand created_at between '2026-01-28 15:00:00' and '2026-01-28 15:10:00';\n\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 25666868; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id = 8646335; # Teya\nSELECT * FROM crm_configurations where provider = 'hubspot' and crm_provider_id IN (5933397);\n\n\nSELECT t.name, t.id, t.owner_id, c.id, c.provider, c.crm_base_url FROM teams t\nJOIN crm_configurations c ON t.id = c.team_id\nWHERE t.status = 'active';\n\nSELECT * FROM teams where id = 1091;\nSELECT * FROM crm_configurations where team_id = 1091;\nSELECT * FROM activity_providers where team_id = 1091;\nSELECT * FROM activities where crm_configuration_id = 1024 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT * FROM teams WHERE name LIKE '%Leadventure%';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1091 and sa.provider = 'salesforce';\n\nSELECT * FROM teams WHERE name LIKE '%Wilson%'; # 862, 812\nSELECT * FROM teams where id = 862;\nSELECT * FROM crm_configurations where team_id = 862;\nSELECT * FROM activity_providers where team_id = 862;\nSELECT * FROM activities where crm_configuration_id = 812 and type IN ('softphone', 'softphone-outbound')\nand provider NOT IN ('hubspot', 'aircall')\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by id desc;\n\n\nSELECT t.id, crm.id, crm.provider, ap.* FROM teams t\njoin crm_configurations crm on t.id = crm.team_id\njoin activity_providers ap on t.id = ap.team_id\nwhere t.status = 'active' and ap.is_enabled = 1\nand crm.provider = 'hubspot'\nand ap.provider NOT IN ('hubspot', 'aircall', 'uploader', 'gong', 'twilio', 'zoom-bot', 'google-meet', 'ms-teams',\n 'outreach', 'close', 'ringcentral', 'dialpad', 'zoom-phone');\n\nSELECT * FROM teams where id = 1068;\nSELECT * FROM crm_configurations where team_id = 1068;\nSELECT * FROM activity_providers where team_id = 1068;\n\nSELECT * FROM activities a\nwhere crm_configuration_id = 993 and type IN ('softphone', 'softphone-outbound')\nand a.provider NOT IN ('hubspot', 'uploader', 'gong', 'twilio', 'google-meet', 'ms-teams','close'\n )\n# and telephony_provider_id = '019c1131-a22f-4792-b9ea-20adf6a02ed0'\norder by a.id desc;\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1068 and sa.provider = 'hubspot';\n\n# ********************************************************************\n# ********************************************************************\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 882; # 933 - GoGlobal , portalId: 6017093\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 933 and updated_at > '2026-02-06 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 933 and sa.provider = 'hubspot';\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 834; # 882 - AnyVan , portalId: 5468262\nSELECT * FROM contacts WHERE crm_configuration_id = 834 and updated_at > '2026-03-30 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and updated_at > '2026-03-04 08:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 882 and sa.provider = 'hubspot';\nselect * from crm_layouts where crm_configuration_id = 834;\nselect * from crm_layout_entities where crm_layout_id = 2780;\nselect * from crm_fields where id IN (321153,321192,321193,321194);\n\nSELECT * FROM opportunities WHERE crm_configuration_id = 834 and id = 10993426;\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 988; # 1057 - Teya (543ce4f4-168c-4571-91ea-5b35c253f06f) , portalId: 26651871\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1057 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1057 and sa.provider = 'hubspot';\n\nSELECT * FROM crm_configurations where id = 533; # 559 - Connectd , portalId: 6710988\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 559 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 801; # 852 - Rise Vision , portalId: 2700250\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 852 and updated_at > '2026-02-04 00:00:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 962; # 1034 - evergrowth.io , portalId: 143180990\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1034 and updated_at > '2026-02-04 00:00:00' order by updated_at desc;\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 1037; # 1102 - Jibble , portalId: 6649755\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1102 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 8\n\nSELECT * FROM crm_configurations where id = 1015; # 1049 - Travefy , portalId: 48904401\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1049 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 20\n\nSELECT * FROM crm_configurations where id = 64; # 70 - SalaryFinance , portalId: 3404115\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 70 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 6th last\n\nSELECT * FROM crm_configurations where id = 802; # 853 - Street Group , portalId: 7658438\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 853 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 10\n\nSELECT * FROM crm_configurations where id = 872; # 921 - In Professional Development , portalId: 9238273\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 921 and updated_at > '2026-02-04 12:30:00' order by updated_at desc; # 2\n\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 550; # 576 - SeedLegals , portalId: 3028661\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 576 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 989; # 1058 - rtaoutdoor.com , portalId: 22371204\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1058 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 896; # 946 - Mintago , portalId: 6621281\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 946 and updated_at > '2026-02-05 14:00:00' order by updated_at desc;\n\nSELECT * FROM crm_configurations where id = 617; # 641 - PCS , portalId: 5244937\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 641 and updated_at > '2026-02-05 14:00:00' order by updated_at desc; # 7th\n# ********************************************************************\nSELECT * FROM crm_configurations where id = 649; # 670 - Eventeny , portalId: 4492849\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-18 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 670 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; #\n\nSELECT * FROM crm_configurations where id = 48; # 51 - CleanCloud , portalId: 4373137\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-03-04 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 51 and updated_at > '2026-02-09 08:00:00' order by updated_at desc;\nselect * from users where team_id = 51; # 7783\nSELECT * FROM groups WHERE uuid_to_bin('8a8d2cb6-8b55-4fa3-8b5c-5f0e3d8de59a') = uuid; # 1130\nselect * from activity_searches where user_id = 7783;\nselect * from activity_search_filters where activity_search_id IN (32291, 32292);\n\nSELECT asf.activity_search_id, asf.id, asf.value\nFROM activity_search_filters asf\nWHERE asf.filter = 'group_id'\nAND asf.value IN (\n SELECT CONCAT(\n HEX(SUBSTR(uuid, 5, 4)), '-',\n HEX(SUBSTR(uuid, 3, 2)), '-',\n HEX(SUBSTR(uuid, 1, 2)), '-',\n HEX(SUBSTR(uuid, 9, 2)), '-',\n HEX(SUBSTR(uuid, 11))\n )\n FROM groups\n WHERE deleted_at IS NOT NULL\n);\n\nSELECT * FROM crm_configurations where id = 272; # 290 - Bonham & Brook , portalId: 5705856\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-05 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 290 and updated_at > '2026-02-09 08:00:00' order by updated_at desc; # 6th\n# ********************************************************************\nSELECT * FROM crm_configurations where provider = 'hubspot';\nSELECT * FROM crm_configurations where id = 1056; # 1119 - Chromatic , portalId: 45602133\nSELECT * FROM opportunities WHERE team_id = 1119 and remotely_created_at > '2026-02-01 00:00:00' order by updated_at desc;\nSELECT * FROM opportunities WHERE team_id = 1119 and updated_at > '2026-02-09 09:00:00' order by updated_at desc; # null\n# ********************************************************************\n\nselect * from contacts where crm_provider_id = '003Uu00000ojD4NIAU';\nselect\n cp.*\n# DISTINCT t.id\n# cp.id, cp.user_id, t.id, cp.crm_configuration_id, cp.contact_fields\nFROM crm_profiles cp\nJOIN crm_configurations crm on crm.id = cp.crm_configuration_id\nJOIN users u on u.id = cp.user_id\nJOIN teams t ON t.id = crm.team_id\nWHERE crm.provider = 'salesforce' and t.status = 'active'\n and cp.archived_at IS NULL and u.deleted_at IS NULL\n and t.id NOT IN (1093)\n and t.id = 2\n and cp.contact_fields IS NULL;\n# and c.crm_provider_id = '003Uu00000ojD4NIAU';\n\nSELECT * FROM users WHERE id = 26484;\nSELECT * FROM crm_profiles WHERE user_id = 26484;\nSELECT * FROM social_accounts WHERE sociable_id = 26484;\nSELECT * FROM crm_configurations where provider = 'salesforce';\nselect * from users where id IN (10022, 10403);\nselect * from users where team_id IN (526);\nselect * from teams where id IN (526, 532);\nselect * from crm_configurations where id IN (500, 516);\nselect * from crm_profiles where crm_configuration_id IN (500, 516) and user_id IN (10022, 10403);\nselect * from contacts where crm_configuration_id IN (500, 516) and crm_provider_id = '003Uu00000ojD4NIAU';\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 526 and sa.provider = 'salesforce';\nselect * from team_settings where team_id IN (526, 532);\n\nselect * from users where id IN (22824);\nselect * from crm_profiles where crm_configuration_id IN (1026);\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1093 and sa.provider = 'salesforce';\n\nselect * from teams where id = 1099;\nselect * from users where id = 29643\n\nselect * from activity_processing_states;\n\nSELECT * FROM teams where name LIKE '%Fare%'; # 233\nSELECT * FROM opportunities where crm_configuration_id = 215\n# and crm_provider_id = 'oppo_ogESZf2P50nDrd1nGPvKDXeA6sSaTN5v51Lp4ayVzKR'\n;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1088 and sa.provider = 'hubspot';\n\nSELECT * FROM teams order by updated_at DESC\nSELECT * FROM crm_configurations WHERE id = 1019; # SimpleConsign 1088 - no social account\n\nselect * from crm_configurations where provider = 'pipedrive';\n\nselect * from teams where id = 957;\nselect * from crm_configurations where id = 957;\n\nSELECT * FROM teams WHERE name LIKE '%Prolific%'; # 544, 518, 10743\nSELECT * FROM opportunities where crm_configuration_id = 518 order by id desc;\n\nselect * from users where team_id = 1; # 26726 - Gabriela Dureva\nSELECT * FROM opportunities where user_id = 26726; # 16834447 - Prolific\nselect * from activities where user_id = 26726 order by id desc;\nselect * from contacts where crm_configuration_id = 1\nand email IN ('charlotte.ward@prolific.com', 'frankie.bryant@prolific.com'); # 2094416, 2093620\nSELECT * FROM contacts WHERE id = 6284931;\n\nSELECT p.* FROM activities a JOIN participants p ON a.id = p.activity_id\nWHERE a.user_id = 26726 and p.lead_id IN (2094416, 2093620) and a.created_at > '2026-01-01 00:00:00' order by p.email;\n\nselect * from activities where id IN (75509259,75509261,75509261,75511034,75026464,75517602,75517605);\nselect * from crm_configurations where id = 1;\n\n43801692-1aeb-32ce-acba-5b80a479701a\n44c3c9cf-6f5e-75f3-8179-bc9f75dd2b1b\n405975c0-b3d0-7aaa-821f-09d59cae6dd1\n4caf848d-4bed-2299-b248-7788d41f9fca\n49bedc3f-f196-eef3-89c3-dea6a3b4aa63\n43420989-a09d-b8f8-9806-c8bbf7a02aac\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nSELECT * FROM activities WHERE id = 75461988;\n\nSELECT * FROM activities WHERE uuid_to_bin('d6c5052e-e972-49e9-8912-26f2f7d6c5f6') = uuid;\n\nselect * from contacts where id = 17900517;\n\nselect * from contact_roles cr join crm_configurations crm on cr.crm_configuration_id = crm.id\nwhere crm.provider != 'salesforce';\n\nselect * from users where id = 21047;\nSELECT * FROM crm_configurations WHERE id = 892;\nSELECT * FROM teams WHERE id = 942;\nselect * from opportunities where team_id = 942 order by updated_at desc;\nselect * from contacts where team_id = 942 order by updated_at desc;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 942 and sa.provider = 'hubspot';\n\nSELECT * FROM opportunities where team_id = 1 and crm_provider_id IN ('006Pq00000NeH6XIAV', '006Pq000007z8kdIAA'); # 10697889, 6621430\nSELECT * FROM crm_configurations WHERE id = 1;\nSELECT * FROM teams WHERE crm_id = 1;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1 and sa.provider = 'salesforce';\n\nselect id, user_id, opportunity_fields from crm_profiles where crm_configuration_id = 1\nSELECT * FROM opportunities where team_id = 1 order by updated_at desc; # 10697889, 6621430\n\nselect * from teams where id = 852;\nselect * from groups where id = 2286;\nselect * from sidekick_settings where team_id = 852;\nselect * from default_activity_types where team_id = 852;\n\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id AND p.id IS NULL -- no profile\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active' -- team is active\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1 AND u.deleted_at IS NULL\nAND u.crm_required = 1\nAND u.team_id = 1\nORDER BY u.team_id;\n\nSELECT * FROM crm_profiles cp where cp.crm_configuration_id = 1 and cp.user_id IN (\n18481\n );\n\nSELECT cc.provider, cc.id, p.id, u.*\nFROM users u\nLEFT JOIN crm_profiles p ON u.id = p.user_id\nINNER JOIN teams t ON u.team_id = t.id AND t.status = 'active'\nINNER JOIN crm_configurations cc ON t.crm_id = cc.id\nWHERE u.status = 1\n AND u.deleted_at IS NULL\n AND u.crm_required = 1\n# AND u.team_id = 1\n AND p.id IS NULL -- Move this condition to WHERE clause\nORDER BY u.team_id;\n\nSELECT * FROM opportunities WHERE id = 20002609;\nselect * from teams where id = 1122; # Velatir, 29953 - christian@velatir.com\nselect * from crm_configurations where id = 1060;\nselect * from crm_layouts where crm_configuration_id = 1060;\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3596;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1122 and sa.provider = 'hubspot';\nselect * from opportunities where team_id = 1122 order by updated_at desc;\n\nselect * from crm_field_data where object_type = 'contact';\n\nSELECT * FROM activities WHERE uuid_to_bin('374fc8ed-3315-4c9f-9b25-318b7fd2928f') = uuid; # 76584262\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 248 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles where user_id = 24115; # 005QF000002CswMYAS\nSELECT * FROM users where id = 24115;\nSELECT * FROM accounts where id = 4002896;\nSELECT * FROM teams WHERE name LIKE '%adswerve%';\nSELECT * FROM opportunities where crm_configuration_id = 230 AND crm_provider_id IN (\"0069N000003GIQ9QAO\",\"0061r000019yGP9AAM\",\"0066900001S2KWlAAN\",\"0066900001TDpj2AAD\",\"0066900001b8uEwAAI\",\"0069N000001rQi0QAE\",\"006QF00000KD40mYAD\",\"006QF00000LzpRJYAZ\",\"0069N000002uomtQAA\",\"0069N000002xlMLQAY\",\"0066900001NV6ubAAD\",\"0061r00001HJp45AAD\",\"006QF00000uTlUoYAK\",\"006QF00000v0bZqYAI\");\nSELECT * FROM opportunities WHERE crm_configuration_id = 230 AND crm_provider_id = '0069N000003GIQ9QAO'; # 6272203\n\nSELECT u.id, u.email, ac.name, a.* FROM activities a\nJOIN users u ON a.user_id = u.id\nJOIN accounts ac ON a.account_id = ac.id\nWHERE\nuuid_to_bin('e3269598-b562-44fb-b5e9-9d2694dc63e0') = a.uuid or\nuuid_to_bin('66ddc3ab-4e15-45aa-af0c-248c1eece593') = a.uuid or\nuuid_to_bin('826bd328-e1cc-4213-b8d8-572454cacc07') = a.uuid;\n\nselect * from users where id = 5825;\nSELECT * FROM activities WHERE uuid_to_bin('e56aa2e8-231a-421b-ab1f-cb38ed2bf573') = uuid;\n\nselect * from activities where uuid_to_bin('91e13b2f-2d1b-45f8-b1fd-1141b6563782') = uuid;\n19594, 862\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 862 and sa.provider = 'salesforce';\n\nselect * from automated_reports where id = 36;\nselect ar.frequency, r.*, ar.* from automated_report_results r\njoin automated_reports ar on r.report_id = ar.id\nwhere ar.frequency != 'one_off';\n\nselect s.* from activity_searches s join users u ON s.user_id = u.id where u.team_id = 882;\nselect * from nudges n where n.activity_search_id\n\nselect * from teams where created_at > '2026-03-09';\nSELECT * FROM crm_layouts WHERE crm_configuration_id = 1065; # 1065\nSELECT * FROM crm_layout_entities WHERE crm_layout_id = 3617;\n\nselect * from users where team_id = 1 and name like '%Lukas%'; # 7160\n\nSELECT * FROM teams WHERE id = 575;\nselect * from opportunities where team_id = 575;\nSELECT * FROM teams WHERE name LIKE '%Integrum ESG%'; # 1126, 1065,\nselect * from opportunities where team_id = 1126;\nSELECT * FROM teams WHERE name LIKE '%Base%'; # 1125, 1063,\nselect * from opportunities where team_id = 1125;\nselect * from contacts c\nwhere c.team_id = 882;\n\nSELECT * FROM activities WHERE id = 76822967;\nSELECT * FROM crm_profiles WHERE user_id = 15440;\nSELECT * FROM crm_profiles WHERE crm_configuration_id = 555;\nSELECT * FROM crm_configurations WHERE id = 555;\nSELECT * FROM users WHERE id = 15440; # team. 581, gr. 15440, pl. 3911, act. field 162182\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 581 and sa.provider = 'salesforce';\n\nSELECT * FROM automated_report_results order by id desc;\n\nselect * from features;\nselect * from team_features where feature_id = 40;\n\nselect * from teams where id = 556;\n\nselect * from automated_reports;\nwhere id = 54; # 4fdd41f6-dcf0-30d0-b339-7345381b6044 , [\"pdf\",\"podcast\"]\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\nselect * from automated_report_results order by id desc;\nSELECT * FROM automated_report_results WHERE id = 1919;\n\nselect * from automated_report_results WHERE report_id = 54;\n\nselect * from opportunities where id = 7594349;\n\nSELECT * FROM teams WHERE name LIKE '%Les%'; # 711, 692, 16067 - jiminnyintegration@lesmills.com\nselect * from playbooks where team_id = 711; # event 226147\nSELECT * FROM playbook_categories WHERE playbook_id = 5515;\nSELECT * FROM crm_fields WHERE crm_configuration_id = 692 and object_type = 'event';\nSELECT * FROM crm_fields WHERE id = 226147;\nSELECT * FROM crm_field_values WHERE crm_field_id = 226147;\n\nSELECT * FROM crm_configurations WHERE id = 692;\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 711 and sa.provider = 'salesforce';\n\nSELECT * FROM crm_profiles cp JOIN users u on u.id = cp.user_id WHERE u.team_id = 711;\n\nselect * from leads;\n\nselect * from calendars;\n\nSELECT\n t.id AS team_id,\n t.name,\n LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1)) AS calendar_domain\nFROM teams t\nJOIN users u ON u.team_id = t.id\nJOIN calendars c ON c.user_id = u.id AND c.status = 'active' AND c.calendar_provider_id LIKE '%@%'\nLEFT JOIN team_domains td\n ON td.team_id = t.id\n AND td.deleted_at IS NULL\n AND td.domain = LOWER(SUBSTRING_INDEX(c.calendar_provider_id, '@', -1))\nGROUP BY t.id, t.name, calendar_domain\nORDER BY t.name, calendar_domain;\n\nselect * from users u join calendars c on c.user_id = u.id\nwhere u.team_id = 882;\n\n\nselect * from activities where id = 74049485; # team 563 crm 537\nselect * from activities where id = 73272382; # team 563 crm 537\nselect * from activities where id = 64400389; # team 563 crm 537\nselect * from activities where id = 58081273; # team 563 crm 537\nselect * from activities where id = 54520297; # team 563 crm 537\nselect * from participants where activity_id = 58081273;\n\nselect * from activities where crm_configuration_id = 537 and provider = 'aircall'\nand account_id = 19003658 order by updated_at desc;\n\nselect * from contacts where crm_configuration_id = 537 and id = 35957759;\nselect * from accounts where crm_configuration_id = 537 and id = 19003658;\n\nselect * from automated_report_results where id = 1976;\nselect * from automated_reports where id = 583;\nselect * from activity_searches where id = 87714;\nselect * from activity_search_filters where activity_search_id = 87714;\n\nSELECT * FROM activities WHERE uuid_to_bin('8827f672-202d-4162-9d04-73ff5f0566a9') = uuid\nor uuid_to_bin('47842446-af51-4bcb-854f-cc6560290101') = uuid;\n\nSELECT * FROM crm_configurations WHERE provider = 'hubspot';\nselect * from rate_limits;\n\nselect * from automated_report_results where media_type = 'pdf' and status = 2\nand id IN (18, 1872);\nselect * from automated_reports where id = 54;\nSELECT * FROM users WHERE id IN (24623,29443,29613);\n\nSELECT * FROM automated_report_results WHERE uuid_to_bin('822fa41b-afd3-43a9-a248-86b0e36f3131') = uuid;\n\nselect * from text_relays where created_at > '2026-05-01';\nand id IN (32415, 32416);\n# and id = 32412;\n\nselect * from users where team_id = 2 and email like '%scott%' and id = 29510;\n\nSELECT * FROM activities WHERE uuid_to_bin('67cebfc2-ed56-44a2-8c68-7a0286ed8618') = uuid; # 79763436\n\nSELECT email_provider_id, COUNT(*) as count, GROUP_CONCAT(id) as ids, GROUP_CONCAT(status) as statuses\nFROM text_relays\nWHERE email_provider_id IN ('19e2027868a64b42', '19e2033ed8ea6b10')\nGROUP BY email_provider_id;\nSELECT id, status, telephony_provider_id, created_at\nFROM activities\nWHERE id IN (80028719, 80028846);\nSELECT id, status, code, email_sent_at, created_at, updated_at\nFROM text_relays\nWHERE id IN (32415, 32416);\nSELECT id, status, code, sender, recipient, created_at\nFROM text_relays\nWHERE sender LIKE '%mario.georgiev%' OR sender LIKE '%stoyan.tomov%'\nORDER BY created_at DESC\nLIMIT 10;\n\nSELECT id, uuid, status, code, sender, recipient, created_at, updated_at\nFROM text_relays\nWHERE uuid = uuid_to_bin('0626141c-27a6-4d8c-aff8-7c8020a2c656');\n\n# ***************\nSELECT DISTINCT u.id, u.email, u.name, u.softphone_number, COUNT(a.id) as sms_count\nFROM users u\nINNER JOIN activities a ON u.id = .user_id\nWHERE a.type LIKE 'sms%'\nAND a.created_at > DATE_SUB(NOW(), INTERVAL 30 DAY)\nGROUP BY u.id, u.email, u.name, u.softphone_number\nORDER BY sms_count DESC;\n\nselect * from teams where id = 1;\n\nselect * from roles;\n\n\nSELECT\n CONCAT(u.id, CASE WHEN u.id = t.owner_id THEN ' (owner)' ELSE '' END) AS user_id,\n u.email,\n sa.*,\n t.owner_id FROM social_accounts sa\nJOIN users u on u.id = sa.sociable_id\nJOIN teams t on t.id = u.team_id\nWHERE u.team_id = 1117 and sa.provider = 'hubspot';\nSELECT * FROM activities WHERE uuid_to_bin('8024fffb-2df7-4017-91f4-d9f896050248') = uuid; # 79933459 YES\nSELECT * FROM activities WHERE uuid_to_bin('25529043-8094-4781-927f-4f4da2a8185c') = uuid; # 80186192 NO\nSELECT * FROM crm_configurations WHERE id = 1053;\nSELECT * FROM teams WHERE id = 1117;\nselect * from users where id = 30249;\nselect * from playbooks where id = 5473;\nselect * from playbook_categories where id = 43783;\nselect * from playbook_categories where playbook_id = 5473;\nselect * from crm_fields where id = 659242;\nselect * from crm_field_values where crm_field_id = 659242;\n\nSELECT * FROM crm_field_data fd\n# JOIN crm_fields f ON fd.crm_field_id = f.id\n# JOIN activities a ON fd.activity_id = a.id\nWHERE activity_id = 79933459\n# AND f.crm_provider_id = 'hs_activity_type';\n\n\nSELECT * FROM activity_messages;\nselect * from text_relays where created_at > '2026-05-01';\nselect * from activities where user_id IN (7160, 18608) and created_at > '2026-05-22' order by id desc;\nselect * from users where team_id = 1 and id IN (18608, 13934, 7160);\nselect * from activities where user_id = 7160 order by id desc limit 10;\n\nselect * from accounts where team_id = 1 and name = 'Column5';\n\nselect * from users where name like '%Subra%'; # 31054, 1117\nselect * from teams where id = 1117;\nselect * from activity_searches where user_id = 31054;\nselect * from activity_search_filters where activity_search_id IN (88882, 88902);","role_description":"text entry area","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Project","depth":3,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Project","depth":3,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"New File or Directory…","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Expand Selected","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Collapse All","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Options","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Hide","depth":4,"bounds":{"left":0.0,"top":0.0,"width":0.018055556,"height":0.026666667},"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-1556586073691613239
|
-7851921920897086523
|
idle
|
accessibility
|
NULL
|
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
Sync Changes
Hide This Notification
Code changed:
Hide
12
246
3
21
Previous Highlighted Error
Next Highlighted Error
<?php
namespace Jiminny\Services\Crm\Salesforce;
use Carbon\Carbon;
use Exception;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Events\Dispatcher;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Jiminny\Component\Country\CountriesMap;
use Jiminny\Contracts\Acl\PermissionEnum;
use Jiminny\Contracts\Repositories\TeamRepository;
use Jiminny\Contracts\Services\Crm\FetchRelatedActivityInterface;
use Jiminny\Contracts\Services\Crm\ImportsBusinessProcessesInterface;
use Jiminny\Contracts\Services\Crm\LayoutManagementInterface;
use Jiminny\Contracts\Services\Crm\MatchCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\Provider\SalesforceBatchSyncInterface;
use Jiminny\Contracts\Services\Crm\Provider\SalesforceInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityLookupInterface;
use Jiminny\Contracts\Services\Crm\RemoteEntityManipulationInterface;
use Jiminny\Contracts\Services\Crm\RemoteNoteEntityManipulationInterface;
use Jiminny\Contracts\Services\Crm\SearchTaskInterface;
use Jiminny\Contracts\Services\Crm\SendSummaryToCrmInterface;
use Jiminny\Contracts\Services\Crm\SettingsInterface;
use Jiminny\Contracts\Services\Crm\SupportsObjectTypeParseInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmEntitiesInterface;
use Jiminny\Contracts\Services\Crm\SyncCrmProfileRecordTypesInterface;
use Jiminny\Contracts\Services\Crm\VerifyTaskExistsInterface;
use Jiminny\Enums\CrmObject;
use Jiminny\Events\Activities\Crm\LeadConverted;
use Jiminny\Exceptions\CrmException;
use Jiminny\Exceptions\HttpBadRequestException;
use Jiminny\Exceptions\HttpNotFoundException;
use Jiminny\Exceptions\NoResultsException;
use Jiminny\Exceptions\ServiceUnavailableException;
use Jiminny\Jobs\Crm\NoteObject;
use Jiminny\Jobs\Crm\MatchActivitiesToNewOpportunity;
use Jiminny\Models\Account;
use Jiminny\Models\Activity;
use Jiminny\Models\Calendar\CalendarEvent;
use Jiminny\Models\Contact;
use Jiminny\Models\Contracts\ActivityContract;
use Jiminny\Models\Crm\BusinessProcess;
use Jiminny\Models\Crm\Configuration;
use Jiminny\Models\Crm\ContactRole;
use Jiminny\Models\Crm\Field;
use Jiminny\Models\Crm\Profile;
use Jiminny\Models\Crm\RecordType;
use Jiminny\Models\Lead;
use Jiminny\Models\Opportunity;
use Jiminny\Models\Playbook;
use Jiminny\Models\SocialAccount;
use Jiminny\Models\Stage;
use Jiminny\Models\TeamSettings;
use Jiminny\Models\User;
use Jiminny\Repositories\Crm\ContactRoleRepository;
use Jiminny\Repositories\Crm\FieldRepository;
use Jiminny\Repositories\Crm\ProfileRepository;
use Jiminny\Repositories\Crm\RecordTypeFieldValuesRepository;
use Jiminny\Services\Avatar\ProspectPhotoPathService;
use Jiminny\Services\Crm\BaseService;
use Jiminny\Services\Crm\Helpers\ArrayIterator;
use Jiminny\Services\Crm\MatchDomainByEmailInterface;
use Jiminny\Services\Crm\OpportunitySyncStrategyResolver;
use Jiminny\Services\Crm\ResolveCompanyNameByEmailTrait;
use Jiminny\Services\Crm\Salesforce\Fields\FieldHelper;
use Jiminny\Services\Crm\Salesforce\Fields\FieldTypeConverter;
use Jiminny\Services\Crm\Salesforce\Fields\ValueNormalizer;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\FollowupActivityTrait;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\LogActivityTrait;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\RecordManipulationsTrait;
use Jiminny\Services\Crm\Salesforce\ServiceTraits\SyncFieldsTrait;
use Jiminny\Utils\CurrencyFormatter;
use Jiminny\Utils\StringUtil;
use Ramsey\Uuid\Uuid;
use Sentry\Laravel\Facade as Sentry;
class Service extends BaseService implements
SalesforceInterface,
SalesforceBatchSyncInterface,
SyncCrmEntitiesInterface,
SyncCrmProfileRecordTypesInterface,
ImportsBusinessProcessesInterface,
RemoteEntityManipulationInterface,
FetchRelatedActivityInterface,
SendSummaryToCrmInterface,
MatchDomainByEmailInterface,
SearchTaskInterface,
LayoutManagementInterface,
SettingsInterface,
MatchCrmEntitiesInterface,
RemoteEntityLookupInterface,
SupportsObjectTypeParseInterface,
RemoteNoteEntityManipulationInterface,
VerifyTaskExistsInterface
{
use ResolveCompanyNameByEmailTrait;
use SyncFieldsTrait;
use DeleteObjectsTrait;
use RecordManipulationsTrait;
use ServiceTraits\BatchSyncTrait;
use FollowupActivityTrait;
use LogActivityTrait;
/**
* Note Body Limit for the Old Note-Taking Tool
*
* @var int
*/
private const int CLASSIC_NOTE_MAX_LENGTH = 32000;
/**
* Note Content Limit for the New Notes
*
* @var int
*/
private const int ENHANCED_NOTE_MAX_LENGTH = 50000000;
private const string INSTALLED_PACKAGE_ID = '033Tw0000007bKbIAI';
private const int CACHE_TTL = 600;
private const int TASK_VERIFICATION_CACHE_TTL = 86400; // 1 day - 86400
/**
* @var Client
*/
protected $client;
protected PayloadBuilder $payloadBuilder;
protected QueryHandler $queryHandler;
private OpportunitySyncStrategyResolver $opportunitySyncStrategyResolver;
public function __construct(
Client $client,
PayloadBuilder $payloadBuilder,
protected Dispatcher $eventDispatcher,
private readonly CountriesMap $countriesMap,
private readonly ProspectPhotoPathService $prospectPhotoPathService,
) {
parent::__construct();
$this->client = $client;
$this->payloadBuilder = $payloadBuilder;
$this->queryHandler = app(QueryHandler::class, [
'client' => $this->client,
'logger' => $this->logger,
]);
$this->opportunitySyncStrategyResolver = app(OpportunitySyncStrategyResolver::class, [
'client' => $this->client,
]);
}
public function getDisplayName(): string
{
return 'Salesforce';
}
public function getJobDelay(): int
{
return 1;
}
protected function getOAuthAccount(User $user): ?SocialAccount
{
return $user->getSocialAccount(SocialAccount::PROVIDER_SALESFORCE);
}
public function verifyTaskExists(Activity $activity): bool
{
$crmProviderId = $activity->getCrmProviderId();
$cacheKey = "crm_task_exists:{$this->config->getId()}:$crmProviderId";
return Cache::remember($cacheKey, self::TASK_VERIFICATION_CACHE_TTL, function () use ($activity, $crmProviderId) {
$playbook = $this->getPlaybookFromActivity($activity);
if ($playbook === null) {
$this->logger->warning('[Salesforce] Cannot verify task - no playbook found', [
'activity' => $activity->getId(),
'crm_provider_id' => $crmProviderId,
]);
return false;
}
$objectType = $playbook->getActivityType() === Playbook::ACTIVITY_TYPE_EVENT ? 'Event' : 'Task';
try {
$record = $this->getRecord($objectType, $crmProviderId, ['Id', 'IsDeleted']);
return ! empty($record) && ($record['IsDeleted'] ?? false) === false;
} catch (HttpNotFoundException|HttpBadRequestException) {
$this->logger->info('[Salesforce] Activity record not found during verification', [
'activity' => $activity->getId(),
'object_type' => $objectType,
'crm_provider_id' => $crmProviderId,
'config_id' => $this->config->getId(),
]);
return false;
}
});
}
public function query(string $queryToRun, array $parameters = []): QueryIterator
{
// Due to poorly designed external calls, this method cannot be entirely removed
return $this->queryHandler->query($queryToRun, $parameters);
}
/*=========== Organization Information ===============*/
/**
* Get a list of all the API Versions for the instance.
*
* @throws CrmException
*
* @return mixed
*
*/
public function getApiVersions()
{
$url = $this->config->crm_base_url . '/services/data';
$response = $this->client->get($url);
return json_decode($response->getBody(), true);
}
/**
* Gets the valid recordTypes for a given Salesforce Object via the describe API.
*/
private function getRecordTypes(string $crmObject): array
{
$url = $this->client->getObjectsUrl() . $crmObject . '/describe';
$response = $this->client->get($url);
$jsonResponse = json_decode($response->getBody(), true);
$fields = [];
foreach ($jsonResponse['recordTypeInfos'] as $row) {
$fields[] = ['recordTypeId' => $row['recordTypeId'], 'default' => $row['defaultRecordTypeMapping']];
}
return $fields;
}
/**
* Convert raw field data into a format compatible with CRM APIs.
*/
public function normalizeValue(string $fieldType, string $fieldValue, bool $internal = false): string
{
return ValueNormalizer::normalize($fieldType, $fieldValue, $internal);
}
/**
* @inheritdoc
*/
public function getDefaultFields(string $activityType): array
{
$fields = [];
$defaultFields = ($activityType === Playbook::ACTIVITY_TYPE_TASK)
? FieldDefinitions::defaultTaskFields()
: FieldDefinitions::defaultEventFields();
// 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
{
// Setup the activity field as the default Type.
/** @var Field $activityField */
$activityField = $this->config->fields()->where([
'crm_provider_id' => 'Type',
'object_type' => $activityType,
])->first();
return $activityField;
}
/**
* @inheritdoc
*/
public function getSupportedPlaybookTypes(): array
{
return [Playbook::ACTIVITY_TYPE_TASK, Playbook::ACTIVITY_TYPE_EVENT];
}
protected function getDefaultFollowupLayoutFields(string $activityType): array
{
$fields = [];
$fieldRepo = app(FieldRepository::class);
$fieldFilter = ($activityType === Playbook::ACTIVITY_TYPE_TASK)
? FieldDefinitions::taskFollowupFieldsFilter()
: FieldDefinitions::eventFollowupFieldsFilter();
foreach ($fieldFilter as $eachFilter) {
$field = $fieldRepo->findOneConfigurationFieldByProperties($this->config, $eachFilter);
// 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();
}
/**
* This one is now called only when ImportActivityTypes is triggered or SyncFieldMetadata executed manually
* Regular sync now uses SharedSyncFieldsTrait -> syncSingleObjectType
* Needs to be replaced later on
*/
public function syncField(Field $field): void
{
try {
if (FieldHelper::isCustomField($field)) {
$query = '
SELECT
Id, Metadata, TableEnumOrId
FROM
CustomField
WHERE
DeveloperName = :fieldName
AND
TableEnumOrId = :fieldType
AND
NamespacePrefix = :namespacePrefix';
// We need to constrain the field lookup to the object, in case it's used in multiple places.
$objectType = \in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true)
? 'activity'
: $field->object_type;
$sfFields = $this->queryHandler->metadata($query, [
'fieldName' => substr($field->crm_provider_id, 0, -\strlen('__c')),
'fieldType' => ucfirst($objectType),
// This is used to ensure we only consider the field within the org, not installed packages.
'namespacePrefix' => 'null',
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
// Sync field metadata.
$metadata = $sfField['Metadata'];
$field->description = mb_strimwidth($metadata['description'] ?? '', 0, 191);
$field->label = mb_strimwidth($metadata['label'] ?? '', 0, Field::LABEL_MAX_LENGTH);
$field->type = $this->convertFieldType($metadata['type'], $field->getEntityName());
$field->is_mandatory = ($metadata['required'] === true);
$field->length = $metadata['length'];
$field->default_value = mb_strimwidth(trim($metadata['defaultValue'] ?? '', '"'), 0, 191);
$field->save();
} else {
$query = '
SELECT
Id, DataType, DeveloperName, Label, Length, Description
FROM
FieldDefinition
WHERE
DurableId = :entityName';
$entityName = $field->getEntityName();
$sfFields = $this->queryHandler->metadata($query, [
'entityName' => $entityName,
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
$convertedType = $this->convertFieldType($sfField['DataType'], $entityName);
$label = mb_strimwidth($sfField['Label'], 0, Field::LABEL_MAX_LENGTH);
if ($field->isBusinessType()) {
$label = 'Opportunity Type';
}
$field->description = mb_strimwidth($sfField['Description'], 0, Field::DESCRIPTION_MAX_LENGTH);
$field->label = $label;
$field->type = $convertedType;
$field->length = $sfField['Length'];
$field->save();
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
private function convertFieldType(string $from, ?string $entityName = null): string
{
$converter = new FieldTypeConverter();
return $converter->convert($from, $entityName);
}
/**
* @inheritdoc
*/
public function importPicklistValues(Field $field): array
{
$values = [];
$fieldValues = [];
try {
if (FieldHelper::isCustomField($field)) {
$query = '
SELECT
Id, Metadata, TableEnumOrId
FROM
CustomField
WHERE
DeveloperName = :fieldName
AND
TableEnumOrId = :fieldType
AND
NamespacePrefix = :namespacePrefix';
// We need to constrain the field lookup to the object, in case it's used in multiple places.
$objectType = \in_array($field->object_type, [Field::OBJECT_TASK, Field::OBJECT_EVENT], true) ?
'activity' : $field->object_type;
$sfFields = $this->queryHandler->metadata($query, [
'fieldName' => substr($field->crm_provider_id, 0, -\strlen('__c')),
'fieldType' => ucfirst($objectType),
// This is used to ensure we only consider the field within the org, not installed packages.
'namespacePrefix' => 'null',
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
$valueSet = $sfField['Metadata']['valueSet'];
if ($valueSet['valueSetName'] === null) {
// Local picklist values can be obtained easily.
$picklistValues = $valueSet['valueSetDefinition']['value'];
} else {
// But for some fields, we just get the Global Value Picklist pointer so need to do more work.
$picklistValues = $this->importGlobalValuePicklistValues($valueSet['valueSetName']);
}
// Import all active values.
foreach ($picklistValues as $i => $sfFieldValue) {
// Setup default value.
if ($sfFieldValue['default']) {
$field->update(['default_value' => $sfFieldValue['valueName']]);
}
// This comes through as null if active (lol).
if ($sfFieldValue['isActive'] !== false) {
$values[] = [
'value' => $sfFieldValue['valueName'],
'label' => $sfFieldValue['valueName'],
'sequence' => $i,
'is_default' => $sfFieldValue['default'],
];
}
}
} else {
$objectFields = $this->getObjectFields($field->object_type);
$fieldId = $field->crm_provider_id;
// Only work with our field of interest.
$objectField = array_filter($objectFields, function ($item) use ($fieldId) {
return $item['name'] === $fieldId;
});
$objectField = array_shift($objectField);
if (empty($objectField['picklistValues']) === false) {
foreach ($objectField['picklistValues'] as $i => $sfFieldValue) {
// Skip inactive values.
if ($sfFieldValue['active'] === false) {
continue;
}
// Setup default value.
if ($sfFieldValue['defaultValue']) {
$field->update(['default_value' => $sfFieldValue['value']]);
}
$values[] = [
'value' => $sfFieldValue['value'],
'label' => $sfFieldValue['label'],
'sequence' => $i,
'is_default' => $sfFieldValue['defaultValue'],
];
}
}
}
$fieldsToPurge = $field->values()->get()->pluck('value')->toArray();
foreach ($values as $value) {
$value['value'] = substr($value['value'] ?? '', 0, 255);
$fieldValues[] = $field->values()->updateOrCreate([
'value' => $value['value'],
], $value);
// Remove this value from the ones we are going to purge.
if (($key = array_search($value['value'], $fieldsToPurge, true)) !== false) {
unset($fieldsToPurge[$key]);
}
}
// Delete the old values that are no longer used.
// Get IDs of the values to be deleted
$valuesToDelete = $field->values()->whereIn('value', $fieldsToPurge);
$valuesToDeleteIds = $valuesToDelete->pluck('id');
if (! $valuesToDeleteIds->isEmpty()) {
$recordTypeFieldValuesRepository = app(RecordTypeFieldValuesRepository::class);
$recordTypeFieldValuesRepository->deleteForCrmFieldValueIds($valuesToDeleteIds->toArray());
// Now safely delete from crm_field_values
$valuesToDelete->delete();
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
return $fieldValues;
}
/**
* Gets values from Global Value Picklists.
*/
private function importGlobalValuePicklistValues(string $picklistName): array
{
$query = '
SELECT
Metadata
FROM
GlobalValueSet
WHERE
DeveloperName = :picklistName
LIMIT 1';
try {
$sfValues = $this->queryHandler->metadata($query, [
'picklistName' => $picklistName,
]);
// There is always 1 result at this point.
$sfValue = $sfValues->current();
return $sfValue['Metadata']['customValue'];
} catch (NoResultsException $noResultsException) {
// Nothing returned.
return [];
}
}
/**
* @inheritdoc
*/
public function syncProfileRecordTypes(): void
{
$objectTypes = [
'lead',
'account',
'contact',
'opportunity',
'task',
'event',
];
foreach ($objectTypes as $objectType) {
try {
$crmRecordTypes = $this->getRecordTypes(ucfirst($objectType));
foreach ($crmRecordTypes as $crmRecordType) {
// If the record type is default and not the Master type, set this.
if ($crmRecordType['default'] && $crmRecordType['recordTypeId'] !== '012000000000000AAA') {
$recordType = $this->config->recordTypes()
->where('crm_provider_id', $crmRecordType['recordTypeId'])
->first();
if ($recordType) {
$this->profile->{$objectType . '_record_type_id'} = $recordType->id;
}
}
}
} catch (HttpNotFoundException $exception) {
Log::error('No access to ' . $objectType . ' object, skipping...');
// XXX: should we log this fact somewhere?
continue;
}
}
if ($this->profile->isDirty()) {
$this->profile->save();
}
}
/**
* Gets business processes.
*/
public function importBusinessProcesses(): void
{
$query = '
SELECT
Id, IsActive, Name, TableEnumOrId
FROM
BusinessProcess
WHERE
TableEnumOrId IN (\'Lead\',\'Opportunity\')';
try {
$sfProcesses = $this->queryHandler->query($query);
// Upsert all processes for the team.
foreach ($sfProcesses as $sfProcess) {
/** @var BusinessProcess $businessProcess */
$businessProcess = $this->config->businessProcesses()->updateOrCreate([
'crm_provider_id' => $sfProcess['Id'],
], [
'team_id' => $this->team->id,
'name' => $sfProcess['Name'],
'type' => $sfProcess['TableEnumOrId'] === 'Lead' ? 'lead' : 'opportunity',
'is_selectable' => $sfProcess['IsActive'],
]);
$this->importBusinessProcessStages($businessProcess);
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
/**
* Gets business process stages.
*/
private function importBusinessProcessStages(BusinessProcess $businessProcess): void
{
$query = '
SELECT
Metadata
FROM
BusinessProcess
WHERE
Id = :processId';
try {
$stages = [];
$sfProcessStages = $this->queryHandler->metadata($query, [
'processId' => $businessProcess->crm_provider_id,
]);
// There is always 1 result at this point.
$sfProcessStage = $sfProcessStages->current();
// Upsert all processes for the team.
foreach ($sfProcessStage['Metadata']['values'] as $sfProcessStage) {
$sanitizedName = urldecode($sfProcessStage['valueName']); // Must decode: "%2C" becomes "," etc.
$stage = $businessProcess->crm->stages()
// This MUST match on label because this API doesn't use API Name.
->where('label', $sanitizedName)
->where('type', $businessProcess->type)
->where('is_selectable', 1)
->first();
if ($stage) {
$stages[] = $stage->id;
}
}
$businessProcess->stages()->sync($stages);
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
/**
* Gets record types.
*/
public function importRecordTypes(): void
{
$query = '
SELECT
Id, IsActive, Name, BusinessProcessId, SobjectType
FROM
RecordType';
try {
$sfRecordTypes = $this->queryHandler->query($query);
// Upsert all record types for the process.
foreach ($sfRecordTypes as $sfRecordType) {
$businessProcess = null;
if ($sfRecordType['BusinessProcessId']) {
$businessProcess = $this->config->businessProcesses()
->where('crm_provider_id', $sfRecordType['BusinessProcessId'])
->first();
}
/** @var RecordType $recordType */
$recordType = $this->config->recordTypes()->updateOrCreate([
'crm_provider_id' => $sfRecordType['Id'],
], [
'team_id' => $this->team->id,
'type' => mb_strtolower($sfRecordType['SobjectType']),
'name' => $sfRecordType['Name'],
'is_selectable' => $sfRecordType['IsActive'],
'business_process_id' => $businessProcess->id ?? null,
]);
$this->importRecordTypeFieldValues($recordType);
}
} catch (NoResultsException $noResultsException) {
// Do nothing.
}
}
/**
* Import record type - field value mappings. This only works for standard fields.
*/
private function importRecordTypeFieldValues(RecordType $recordType): void
{
try {
$query = '
SELECT
Metadata
FROM
RecordType
WHERE
Id = :recordTypeId';
$sfFields = $this->queryHandler->metadata($query, [
'recordTypeId' => $recordType->crm_provider_id,
]);
// There is always 1 result at this point.
$sfField = $sfFields->current();
// Sync field metadata.
$picklists = $sfField['Metadata']['picklistValues'];
foreach ($picklists as $picklist) {
$field = $this->config->fields()->where([
'type' => Field::TYPE_PICKLIST,
'object_type' => $recordType->type,
'crm_provider_id' => $picklist['picklist'],
])->first();
if ($field) {
$fieldValues = [];
foreach ($picklist['values'] as $value) {
// Must decode: "%2C" becomes "," etc.
$fieldValue = $field->values()
->where('value', urldecode($value['valueName']))
->first();
if ($fieldValue) {
$fieldValues[] = $fieldValue->id;
}
}
$recordType->fieldValues()->sync($fieldValues);
}
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
}
/**
* @inheritdoc
*/
public function importStages(?array $types = null, ?string $missingStageName = null): ?Stage
{
$params = [];
$missingStage = null;
if ($types === null) {
$types = [Stage::TYPE_LEAD, Stage::TYPE_OPPORTUNITY];
}
foreach ($types as $type) {
if ($type === Stage::TYPE_LEAD) {
$query = '
SELECT
Id, ApiName, MasterLabel, SortOrder
FROM
LeadStatus';
} else {
$query = '
SELECT
Id, ApiName, MasterLabel, IsActive, SortOrder, DefaultProbability
FROM
OpportunityStage';
}
if ($missingStageName) {
$escapedStageName = ValueNormalizer::replaceQueryWithStringLiterals($missingStageName);
$query .= ' WHERE ApiName = :stageName';
$params = [
'stageName' => $escapedStageName,
];
}
try {
$sfStages = $this->queryHandler->query($query, $params);
} catch (NoResultsException $exception) {
$sfStages = [];
}
$missingStage = null;
// Upsert all stages for the team.
foreach ($sfStages as $sfStage) {
$selectable = true;
if (array_key_exists('IsActive', $sfStage)) {
$selectable = $sfStage['IsActive'];
}
$this->restoreAnyTrashedEntity($this->config->stages(), $sfStage['Id']);
$stage = $this->config->stages()->updateOrCreate([
'crm_provider_id' => $sfStage['Id'],
], [
'team_id' => $this->team->id,
'name' => mb_strimwidth($sfStage['ApiName'], 0, 50),
'label' => mb_strimwidth($sfStage['MasterLabel'], 0, 191),
'type' => $type,
'sequence' => $sfStage['SortOrder'] ?? 0,
'is_selectable' => $selectable,
'probability' => $sfStage['DefaultProbability'] ?? null,
]);
if ($missingStageName && $missingStageName === $sfStage['ApiName']) {
$missingStage = $stage;
}
}
if ($missingStageName && $missingStage === null) {
// If they requested a stage that still doesn't exist, it must be inactive so lazy create it.
$missingStage = $this->config->stages()->create([
'crm_provider_id' => Uuid::uuid4(),
'team_id' => $this->team->id,
'name' => mb_strimwidth($missingStageName, 0, 50),
'label' => mb_strimwidth($missingStageName, 0, 191),
'type' => $type,
'sequence' => 0,
'is_selectable' => 0,
]);
}
}
return $missingStage;
}
/**
* @inheritdoc
*/
public function syncLeads(Carbon $since, ?Carbon $to = null, ?string $crmProfileId = null): int
{
$syncCount = 0;
$fields = $this->getAllFieldsAsArray('lead');
if (\in_array('Id', $fields, true) === false) {
return $syncCount;
}
$query = '
SELECT ' . rtrim(implode(',', $fields), ',') . '
FROM Lead
WHERE LastModifiedDate > :since
ORDER BY LastModifiedDate ASC';
try {
$sfLeads = $this->queryHandler->query($query, [
'since' => $since->format('Y-m-d\TH:i:s\Z'),
]);
foreach ($sfLeads as $sfLead) {
// Only sync if previously imported.
if ($this->hasLead($sfLead['Id'])) {
$this->importLead($sfLead);
$syncCount++;
}
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
$this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::LEAD);
return $syncCount;
}
/**
* @inheritdoc
*/
public function syncLead(string $crmId): ?Lead
{
$fields = $this->getAllFieldsAsArray('lead');
$sfLead = $this->getRecord('Lead', $crmId, $fields);
return $this->importLead($sfLead);
}
private function importLead($crmData): ?Lead
{
/** @var ?Stage $stage */
$stage = null;
if (isset($crmData['Status'])) {
// Get the current stage.
$stage = $this->config
->stages()
->where('name', $crmData['Status'])
->where('type', Stage::TYPE_LEAD)
->first();
if ($stage === null) {
// Import it.
$stage = $this->importStages([Stage::TYPE_LEAD], $crmData['Status']);
}
}
// If we have no way of importing this, just return null :(
if ($stage === null) {
return null;
}
$countryCode = $crmData['CountryCode'] ?? null;
// Salesforce allows custom "countries" to be created. Disregard these.
if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {
$countryCode = null;
}
// If we have no country code, try to parse it from the country name.
if ($countryCode === null && empty($crmData['Country']) !== false) {
$countryCode = $this->convertCountryNameToCode($crmData['Country']);
}
// Trim to our width and attempt to parse it.
$number = mb_strimwidth($crmData['Phone'] ?? '', 0, 25);
$parsedNumber = parsePhoneNumber($countryCode, $number);
$mobilePhone = null;
if (empty($crmData['MobilePhone']) === false) {
// Trim to our width and attempt to parse it.
$number = mb_strimwidth($crmData['MobilePhone'], 0, 25);
$mobilePhone = phone_e164($countryCode, $number);
}
$convertedDate = null;
$convertedAccount = null;
$convertedOpportunity = null;
$convertedContact = null;
if ($crmData['IsConverted'] == 'true') {
$convertedDate = $crmData['ConvertedDate'];
if (empty($crmData['ConvertedAccountId']) === false) {
$convertedAccount = $this->config
->accounts()
->where('crm_provider_id', $crmData['ConvertedAccountId'])
->first();
if ($convertedAccount === null) {
try {
$convertedAccount = $this->syncAccount($crmData['ConvertedAccountId']);
} catch (HttpNotFoundException $exception) {
// Probably the user has no permissions to access the converted data.
}
}
}
if (empty($crmData['ConvertedOpportunityId']) === false) {
$convertedOpportunity = $this->config
->opportunities()
->where('crm_provider_id', $crmData['ConvertedOpportunityId'])
->first();
if ($convertedOpportunity === null) {
try {
$convertedOpportunity = $this->syncOpportunity($crmData['ConvertedOpportunityId']);
} catch (HttpNotFoundException $exception) {
// Probably the user has no permissions to access the converted data.
}
}
}
if (empty($crmData['ConvertedContactId']) === false) {
$convertedContact = $this->team
->crm
->contacts()
->where('crm_provider_id', $crmData['ConvertedContactId'])
->first();
if ($convertedContact === null) {
try {
$convertedContact = $this->syncContact($crmData['ConvertedContactId']);
} catch (HttpNotFoundException $exception) {
// Probably the user has no permissions to access the converted data.
}
}
}
}
if (empty($crmData['Company'])) {
$company = 'Unknown';
} else {
$company = mb_strimwidth($crmData['Company'], 0, 191);
}
$domain = null;
if (empty($crmData['Website']) === false) {
$domain = mb_strimwidth($crmData['Website'], 0, 191);
$domain = StringUtil::resolveDomain($domain);
}
$createdDate = null;
if (empty($crmData['CreatedDate']) === false) {
$createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');
}
$profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);
$data = [
'team_id' => $this->team->id,
'user_id' => $profile?->user_id,
'owner_id' => $crmData['OwnerId'] ?? '',
'company' => $company,
'domain' => $domain,
'name' => $crmData['Name'] ? mb_strimwidth($crmData['Name'], 0, 191) : '',
'title' => $crmData['Title'] ? mb_strimwidth($crmData['Title'], 0, 128) : null,
'email' => $crmData['Email'] ? mb_strimwidth($crmData['Email'], 0, 80) : null,
'phone' => $parsedNumber['phone'],
'ext' => $parsedNumber['ext'] ?? null,
'mobile_phone' => $mobilePhone,
'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(
crmConfiguration: $this->config,
crmProviderId: $crmData['Id'],
modelType: Lead::class,
fileName: $crmData['Id'],
avatarText: $crmData['Name']
),
'stage_id' => $stage->id,
'record_type_id' => null,
'converted_at' => $convertedDate,
'converted_account_id' => $convertedAccount->id ?? null,
'converted_opportunity_id' => $convertedOpportunity->id ?? null,
'converted_contact_id' => $convertedContact->id ?? null,
'country_code' => $countryCode,
'remotely_created_at' => $createdDate,
];
$this->restoreAnyTrashedEntity($this->config->leads(), $crmData['Id']);
/** @var Lead $lead */
$lead = $this->config->leads()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);
if ($lead->wasChanged('converted_at') && $lead->getConvertedAt() !== null) {
$this->eventDispatcher->dispatch(new LeadConverted($lead));
}
$this->handleObjectDeletion($lead, $crmData);
if ($lead->trashed()) {
return null;
}
return $lead;
}
/**
* @inheritdoc
*/
public function syncAccounts(Carbon $since, ?Carbon $to = null): int
{
$syncCount = 0;
$fields = $this->getAllFieldsAsArray('account');
if (\in_array('Id', $fields, true) === false) {
return $syncCount;
}
$query = '
SELECT ' . rtrim(implode(',', $fields), ',') . '
FROM Account
WHERE LastModifiedDate > :since
ORDER BY LastModifiedDate ASC';
try {
$sfAccounts = $this->queryHandler->query($query, [
'since' => $since->format('Y-m-d\TH:i:s\Z'),
]);
foreach ($sfAccounts as $sfAccount) {
// Only sync if previously imported.
if ($this->hasAccount($sfAccount['Id'])) {
$this->importAccount($sfAccount);
$syncCount++;
}
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
}
$this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::ACCOUNT);
return $syncCount;
}
/**
* @inheritdoc
*/
public function syncAccount(string $crmId): ?Account
{
$fields = $this->getAllFieldsAsArray('account');
if (! in_array('Id', $fields, true)) {
$this->logger->info('[Salesforce] Sync account cancelled. Fields are not available.', [
'crmId' => $crmId,
'userId' => $this->profile->getUserId(),
]);
return null;
}
$sfAccount = $this->getRecord('Account', $crmId, $fields);
return $this->importAccount($sfAccount);
}
private function importAccount($crmData): ?Account
{
if (! empty($crmData['IsDeleted'])) {
$this->handleEntityDeletionByProviderId($this->config->accounts(), $crmData);
return null;
}
$countryCode = $crmData['BillingCountryCode'] ?? $crmData['ShippingCountryCode'] ?? null;
// Salesforce allows custom "countries" to be created. Disregard these.
if ($countryCode && $this->countriesMap->countryExists($countryCode) === false) {
$countryCode = null;
}
// If we have no country code, try to parse it from the country names.
if ($countryCode === null && empty($crmData['BillingCountry']) === false) {
$countryCode = $this->convertCountryNameToCode($crmData['BillingCountry']);
}
if ($countryCode === null && empty($crmData['ShippingCountry']) === false) {
$countryCode = $this->convertCountryNameToCode($crmData['ShippingCountry']);
}
if (empty($crmData['Phone']) === false) {
// Trim to our width and attempt to parse it.
$number = mb_strimwidth($crmData['Phone'], 0, 25);
$parsedNumber = parsePhoneNumber($countryCode, $number);
} else {
$parsedNumber = [];
}
$industry = null;
if (empty($crmData['Industry']) === false) {
$industry = mb_strimwidth($crmData['Industry'], 0, 40);
}
$domain = null;
if (empty($crmData['Website']) === false) {
$domain = mb_strimwidth($crmData['Website'], 0, 191);
$domain = StringUtil::resolveDomain($domain);
}
$createdDate = null;
if (empty($crmData['CreatedDate']) === false) {
$createdDate = Carbon::parse($crmData['CreatedDate'])->setTimezone('UTC');
}
$profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);
$data = [
'team_id' => $this->team->id,
'user_id' => $profile?->user_id,
'owner_id' => $crmData['OwnerId'],
'name' => mb_strimwidth($crmData['Name'], 0, 191),
'photo_path' => $this->prospectPhotoPathService->getOrGeneratePhotoPath(
crmConfiguration: $this->config,
crmProviderId: $crmData['Id'],
modelType: Account::class,
fileName: $crmData['Id'],
avatarText: $crmData['Name']
),
'industry' => $industry,
'domain' => $domain,
'phone' => $parsedNumber['phone'] ?? null,
'ext' => $parsedNumber['ext'] ?? null,
'country_code' => $countryCode,
'remotely_created_at' => $createdDate,
];
$this->restoreAnyTrashedEntity($this->config->accounts(), $crmData['Id']);
/** @var Account $account */
$account = $this->config->accounts()->updateOrCreate(['crm_provider_id' => $crmData['Id']], $data);
$this->handleObjectDeletion($account, $crmData);
return $account->trashed() ? null : $account;
}
/**
* @inheritdoc
*/
public function syncOpportunities(array $parameters, ?string $strategy = null): int
{
$strategies = $this->opportunitySyncStrategyResolver->getStrategies($this->config, $strategy);
$syncCount = 0;
$logParams = $parameters;
$parameters['profile'] = $this->profile;
$logParams['user'] = $this->profile->getUserId();
if (count($strategies) > 1) {
$this->logger->warning('[' . $this->getDisplayName() . '] Multiple sync strategies used', [
'teamId' => $this->team->getUuid(),
'params' => $logParams,
'strategies_count' => count($strategies),
]);
}
foreach ($strategies as $syncStrategy) {
$name = $syncStrategy->getStrategyName();
try {
$sfOpportunities = $syncStrategy->fetchOpportunities($parameters);
$totalRecords = $sfOpportunities->count();
foreach ($sfOpportunities as $sfOpportunity) {
$this->importOpportunity($sfOpportunity);
$syncCount++;
}
} catch (NoResultsException $noResultsException) {
// Nothing to sync.
$this->logger->warning('[' . $this->getDisplayName() . '] No opportunities found', [
'teamId' => $this->team->getUuid(),
'name' => $name,
'params' => $logParams,
'reason' => $noResultsException->getMessage(),
]);
} catch (CrmException $crmException) {
// Nothing to sync.
$this->logger->warning('[' . $this->getDisplayName() . '] Opportunity sync failed', [
'teamId' => $this->team->getUuid(),
'name' => $name,
'params' => $logParams,
'reason' => $crmException->getMessage(),
]);
}
}
$this->syncRemotelyDeletedObjectsWithErrorHandling(CrmObject::OPPORTUNITY, ['params' => $logParams]);
// debug to see how if count of opportunities reaches 1000
if ($syncCount >= 1000) {
$this->logger->info(
'[' . $this->getDisplayName() . '] Sync Opportunities - count warning',
[
'team_id' => $this->team->getId(),
'params' => $logParams,
'count' => $syncCount,
'strategies_count' => count($strategies),
'total_records' => $totalRecords ?? null,
]
);
}
return $syncCount;
}
/**
* @inheritdoc
*/
public function syncOpportunity(string $crmId): ?Opportunity
{
$strategy = $this->opportunitySyncStrategyResolver->resolve(
$this->config,
OpportunitySyncStrategyResolver::SINGLE_SYNC_OPPORTUNITY_STRATEGY
);
$parameters = [
'profile' => $this->profile,
'crm_id' => $crmId,
];
try {
$sfOpportunity = $strategy->fetchOpportunities($parameters);
} catch (HttpNotFoundException $e) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity not found', [
'teamId' => $this->team->id_string,
'crmId' => $crmId,
]);
return null;
} catch (CrmException $crmException) {
$this->logger->info('[' . $this->getDisplayName() . '] Opportunity sync failed', [
'teamId' => $this->team->id_string,
'crmId' => $crmId,
'exception' => $crmException->getMessage(),
]);
return null;
}
if ($sfOpportunity instanceof ArrayIterator) {
return $this->importOpportunity($sfOpportunity->getItems());
}
return $this->importOpportunity($sfOpportunity);
}
/**
* @throws HttpNotFoundException
*/
private function importOpportunity($crmData): ?Opportunity
{
$profile = $this->getOwnerProfile($crmData['OwnerId'] ?? null);
$account = null;
if (empty($crmData['AccountId']) === false) {
/** @var ?Account $account */
$account = $this->config->accounts()
->where('crm_provider_id', (string) $crmData['AccountId'])
->first();
if ($account === null) {
$account = $this->syncAccount($crmData['AccountId']);
}
}
$userId = $profile?->getUserId() ?? $account?->getUserId();
if ($userId === null) {
$this->logger->error('[Salesforce] | Skip import, no user_id found', [
'id' => $crmData['Id'],
]);
return null;
}
/** @var ?Stage $stage */
$stage = null;
if (isset($crmData['StageName'])...
|
85913
|
NULL
|
NULL
|
NULL
|
|
85915
|
2949
|
5
|
2026-05-28T13:28:22.977605+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974902977_m2.jpg...
|
PhpStorm
|
faVsco.js – Service.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
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...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project: faVsco.js, menu","depth":5,"bounds":{"left":0.025930852,"top":0.019952115,"width":0.03856383,"height":0.025538707},"on_screen":true,"help_text":"~/jiminny/app","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"#12121 on JY-20963-fix-import-on-deleted-entity, menu","depth":5,"bounds":{"left":0.064494684,"top":0.019952115,"width":0.11569149,"height":0.025538707},"on_screen":true,"help_text":"Pull request #12121 exists for current branch JY-20963-fix-import-on-deleted-entity, but pull request details loading failed","role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Start Listening for PHP Debug Connections","depth":5,"bounds":{"left":0.85638297,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"ServiceTest","depth":6,"bounds":{"left":0.87167555,"top":0.019952115,"width":0.043882977,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Run 'ServiceTest'","depth":6,"bounds":{"left":0.9155585,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Debug 'ServiceTest'","depth":6,"bounds":{"left":0.9268617,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"More Actions","depth":6,"bounds":{"left":0.9381649,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"JetBrains AI","depth":5,"bounds":{"left":0.96609044,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Search Everywhere","depth":5,"bounds":{"left":0.9773936,"top":0.019952115,"width":0.011303191,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"IDE and Project Settings","depth":5,"bounds":{"left":0.9886968,"top":0.019952115,"width":0.011303186,"height":0.025538707},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
5582423643801155883
|
-8994321436789994556
|
visual_change
|
hybrid
|
NULL
|
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
& console (PROD) X# console fiaum8458185Y0=NCATCu,id. CASE WHEN unid = thouner id THEN • (oaner)* ELSE ** END) AS user_idena1aormen fo FRil soctal accnuntssasers u on u.1d = sa.soclable_1cParGTnCoontd n.teandu.tean_1d = 1117 and sa.provider = "hubspot":*EROM actMtes WHEOF Wund to binl18a2tetth-2147-1817.0144-40480695926801= Musd: " 70033459 VES+EROM eCtlWifleS.- Nh ĐNNo +o.- 01-92eLe0919501-Tisde# 89186100 M0*EROM eon confaurazons MHEPF 3d = 1953%* FROM teans WHERE id = 1117:+Eoon licene whene a= 30240.TO0% L7o Inu co moy to.zoittServiceTesteeendhles orchwerwicee+0.• testParsccontactPhoncw1thVal LaNurber = E.104 number parses corrcctly, ext is nul•testParseContactPhoncWithExtension - Number with ext. 42 correctly extracts the extensionoesVarsctonlac noneex Sirincalcolo ohirserttiiionkten chats derstunceolrraninit(..*, 10, "*))•testrarcontac rnonemthcountint oor = Loch on numocrtcovoo to tutr Usine counthy cootanrsccontactloble•testParseContactMobileWithValidNumber - E.164 number returned [EMAIL]@chars=mowtchowhnocharsowstunc.eolstoine"estarsccontac tootewhcountrwcode =cukmoiowo t usina county cooOal -Necant alll+ < Code$ AdaptiveditterencePurtent version• >rapstomvewNeweNNCCoocKetucioHunTOOI-WindowFV faVsco.|s ~#12121 on JY-20963-fx-imAdtwycontroller.png© ServiceTest.phgpeleteobiectstrai.php=custom.logaraveuosA SF fiminny@localhost)> DV2UeerRokObserver.ohpo Tesmuonso nemeuonie(© Client.phpA console (STAGING)aedonitemscondocr.on© ActivityController.phpTXS AUTO NIcreated at > DATE SUB(NOWO,INTERVAL 38 DAYXeacimnoucontoon412 B246 Y3221 AУobastcontoonuser.781bY 0.20u.caszlBY sns count DESCu.name u.sotcphone nunbenoeenoxeionoron© CrmController.phoclass Service extends BaseService nolesentsSalesfonceintenface.* fron ceans where 20 =1eeall eveirononePalkxeontoueSalesforceBatchsyncinterface,suncioent es intentace.c)Lanquacecontroller cho$ %SynccrmProf1LeRecordtypesinterfacesonortcrus ness?racessesiintensaceC)LavoutVanagementcontrLiveFeedController.choRemoteEntityHanipulationinterface— 72-783C) Meet nascontro er ohoForchrel aredaciav.LyintertaceC) Messagecontroler ohoSendSummaryToCrmInterfaceC) Metadatacontro er ohoMatchio g inby-nazuintertoce,c) MooilesettinascontroerCaerchitiknrcrrdceC) Momentcontro er.ond) NudgeControllec.ohdLayoutManagementInterfaceSettingsIntenface.MatchfoeFntftfacTntanfacsMeNimodtweatorehoto« Oraaninationl icaneseContaletohr hiostamoatteletanehondathatdenkeaorccne ylookue ncertaceSupports0briectTypeParseInterface.RemoteNoteEntityManipulationInterface.c OrganizationRolesControlVeryekexsentertachTlaa annar a01a TaleLosal chandesChanges 4 filesE.env.local apc© JiminnyDebugCommand.php app/Console/CommandsTIO +→0Side-by-side viewer"@ ebbaab95 app/Services/PlaybackService.phpDo not ignore"Highlight words -x15€pe loagina.ono contiac) Playbickservice.ono apo serviceeUnversioned Files 9 file:Stean & Stracko>oe Activityo->oetUser Oe>aetteam Oiinw.nikiochooE.enw.other aodnumonsto andl doloto sill connonteforeach (Splaylist "mediaSegnents') as Ssegment) ?Ka eanhccosea Reoorglestono escluni PolicosSsegment ""uri' = client cdn(Ssegnent ("uri'), Stean):© GreateMockAskJliminnvReoortRocu*tCommand.ohn.ano/Console/Commandavicon.ico ouroEids.tyt aodSplayList ("EXT-X-PLAYLIST-TYPE' = 'VOD':Praw sol quem coaodSplayList (*EXT-X-ENDLIST' = true:@[EMAIL]/Console/Commands/Crm/HubsootM. WERHOOK FILTFRING IMDIFMENTATION md anoSteam = Strack->aetActvitylor>aerlser Oo>oeteaniobSnumonsto and dolloto consontellforeach (Splaylist "mediaSegments' as Ssegment)Ssegnent ("uri') = client con(Ssegment("uri', Stean):SplayList("EXT-X-PLAYLIST-TYPE') = *VOD*:SplayList("EXT-X-ENDLIST') = true:Nu Wodtur Teams 1108-50 UTE-R Ai/A enano...
|
85914
|
NULL
|
NULL
|
NULL
|
|
85914
|
2949
|
4
|
2026-05-28T13:28:19.508293+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974899508_m2.jpg...
|
PhpStorm
|
faVsco.js – Service.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rapstomViewNeweNNCCoocFV faVsco.|s ~#12121 on JY-2 rapstomViewNeweNNCCoocFV faVsco.|s ~#12121 on JY-20963-fx-l>E HubspolE InicaradonAde>E Listener:v saestorch› E FieldsOpoorunitvMatcheba OpportunitvSvncStrate› ProspectsearchStrategService t raits© elientrest.php© DecorateActivityTest.ppolated, aositn ties© FieldDetinitionsTest.phCCercwmset ame#i PavtoadRuilderTest.ohe"Quer Rt dertest nhnQuervHandierTast ood© QueryiteratorTest.php© QueryResultsTests.phpC Semcetescono© SyncBatchRedisServickRacASanicatast oboa CachadComSanicsPaooeChanges 4 filesE.env.local apc© JiminnyDebugCommand.php app/Console/Commandspe loagina.ono contiac) Playbickservice.ono apo serviceeUnversioned Files 9 file:inw.nikiochooE.enw.other aod@ GanAccoscA ReporteTest.oho teste/Unit/Policios© GreateMockAskJliminnvReoortRocu*tCommand.ohn.ano/Console/Commanavicon.ico ouroEids.tyt aodPraw sol quem coaod@[EMAIL]/Console/Commands/Crm/HubsootM. WERHOOK FILTFRING IMPL FMENTATION molanoWindowpeleteobiectstrait.phpo Tesmuonso Nemeuoni(© Client.phpfinal class ActivityController extends Controller implements CommentContextInterfaceoreakcase "contact':Sthis->logger->info('processing contact'):Scontact = Stean->cra-›contacts)-›where( column: 'crm_provider_id', SobjectId)->firze.// Contact does not exist locally, import it.if (! Scontact instanceof Contact)Sthis->Logger->info("contact does not exist locally'):Scontact = ScraService-›syncContact (SobiectId):if ( Scontact instanceof Contact)=714=729sthises occeresntol resol wing accounteSaccount = Sthis->resolveAccount (Stean, Scontact, ScrnService, Sprospects)719T+0 +→ Side-by-side viewer -@ ebbaab95 app/Services/PlaybackService.phpDo not ignore"71 • ?Stean & Stracko>oe Activitye ->oetUser Or>aetteam orEnumonsto and doloto l connonteforeach (Splaylist "mediaSegnents') as Ssegment) ?Ssegment ""uri' = client cdn(Ssegnent ("uri'), Stean):SplayList ("EXT-X-PLAYLIST-TYPE' = 'VOD'ASplayList (*EXT-X-ENDLIST' = true:custom.ioaraveuosA SF fiminny@localhost)A console [STAGINGTXS AUTO NIcreated at > DATE SUB(NOWO,INTERVAL 38 DAY.by 0.20, u.caazlBY sns count DESCu.name u.sotcphone nunben* fron ceans where 20 =1& console (PROD) XNCATCu,id. CASE WHEN u.id = thouner_id THEN • (oaner)* ELSE ** END) AS user_idena1aormen o Fril soctalaccountssasers u on u.1d = sa.soclable_1cpargtuncosontd n.teandu.tean_1d = 1117 and sa.provider = "hubspot":*EROM actMtes WHEOF Wund to binl18a2tetth-2147-1817.0144-40480695926801= Musd: " 70033459 VES*EPOM Activitieg WHEDE mnsd to bio(105529043-9994-4781-9226-464d2228185a/) - uuSde # 80186190 N0*EROM eon confaucatzons WHERE 3d = 1953%* FROM teans WHERE id = 1117:+Eoon ucene whene 3d= 30240.1O0% LXoo Inu comoy 1o:zo.1ServiceTest# console fiaumeeendhles orchwerwicee+0.8458185Y00• testParsccontactPhoncw1thVal LaNurber = E.104 number parses corrcctly, ext is nul•testParseContactPhoncWithExtension - Number with ext. 42 correctly extracts the extension=oesVarsctonlac noneex Sirincalcolo ohirserttiiionkten chats derstunceolrraninit(..*, 10, "*))•testrarcontac rnonemthcountint oor = Loch on numocrtcovoo to tutr Usine counthy cootanrsccontactloble•testParseContactMobileWithValidNumber - E.164 number returned as-istswarsecon.acwoo@struncalcoloschars=umottohohnochrsowtstuno.eostrie"estarsccontac tootewhcountrwcode =cukmoiowo t usina county cooOal -Necant alll+ < Code$ AdaptiveditterencePurtent vereionSteam = Strack->aetActvitylor>aerlser Oo>oeteaniobnumonstoand dolloto conmonteforeach (Splaylist "mediaSegments' as Ssegment)Ssegnent ("uri') = client con(Ssegment("uri', Stean):SplayList("EXT-X-PLAYLIST-TYPE') = *VOD*:SplayList("EXT-X-ENDLIST') = true:N Wodeud Teams 25554 UTE-R Ai/A enano...
|
NULL
|
-199933608666415325
|
NULL
|
visual_change
|
ocr
|
NULL
|
rapstomViewNeweNNCCoocFV faVsco.|s ~#12121 on JY-2 rapstomViewNeweNNCCoocFV faVsco.|s ~#12121 on JY-20963-fx-l>E HubspolE InicaradonAde>E Listener:v saestorch› E FieldsOpoorunitvMatcheba OpportunitvSvncStrate› ProspectsearchStrategService t raits© elientrest.php© DecorateActivityTest.ppolated, aositn ties© FieldDetinitionsTest.phCCercwmset ame#i PavtoadRuilderTest.ohe"Quer Rt dertest nhnQuervHandierTast ood© QueryiteratorTest.php© QueryResultsTests.phpC Semcetescono© SyncBatchRedisServickRacASanicatast oboa CachadComSanicsPaooeChanges 4 filesE.env.local apc© JiminnyDebugCommand.php app/Console/Commandspe loagina.ono contiac) Playbickservice.ono apo serviceeUnversioned Files 9 file:inw.nikiochooE.enw.other aod@ GanAccoscA ReporteTest.oho teste/Unit/Policios© GreateMockAskJliminnvReoortRocu*tCommand.ohn.ano/Console/Commanavicon.ico ouroEids.tyt aodPraw sol quem coaod@[EMAIL]/Console/Commands/Crm/HubsootM. WERHOOK FILTFRING IMPL FMENTATION molanoWindowpeleteobiectstrait.phpo Tesmuonso Nemeuoni(© Client.phpfinal class ActivityController extends Controller implements CommentContextInterfaceoreakcase "contact':Sthis->logger->info('processing contact'):Scontact = Stean->cra-›contacts)-›where( column: 'crm_provider_id', SobjectId)->firze.// Contact does not exist locally, import it.if (! Scontact instanceof Contact)Sthis->Logger->info("contact does not exist locally'):Scontact = ScraService-›syncContact (SobiectId):if ( Scontact instanceof Contact)=714=729sthises occeresntol resol wing accounteSaccount = Sthis->resolveAccount (Stean, Scontact, ScrnService, Sprospects)719T+0 +→ Side-by-side viewer -@ ebbaab95 app/Services/PlaybackService.phpDo not ignore"71 • ?Stean & Stracko>oe Activitye ->oetUser Or>aetteam orEnumonsto and doloto l connonteforeach (Splaylist "mediaSegnents') as Ssegment) ?Ssegment ""uri' = client cdn(Ssegnent ("uri'), Stean):SplayList ("EXT-X-PLAYLIST-TYPE' = 'VOD'ASplayList (*EXT-X-ENDLIST' = true:custom.ioaraveuosA SF fiminny@localhost)A console [STAGINGTXS AUTO NIcreated at > DATE SUB(NOWO,INTERVAL 38 DAY.by 0.20, u.caazlBY sns count DESCu.name u.sotcphone nunben* fron ceans where 20 =1& console (PROD) XNCATCu,id. CASE WHEN u.id = thouner_id THEN • (oaner)* ELSE ** END) AS user_idena1aormen o Fril soctalaccountssasers u on u.1d = sa.soclable_1cpargtuncosontd n.teandu.tean_1d = 1117 and sa.provider = "hubspot":*EROM actMtes WHEOF Wund to binl18a2tetth-2147-1817.0144-40480695926801= Musd: " 70033459 VES*EPOM Activitieg WHEDE mnsd to bio(105529043-9994-4781-9226-464d2228185a/) - uuSde # 80186190 N0*EROM eon confaucatzons WHERE 3d = 1953%* FROM teans WHERE id = 1117:+Eoon ucene whene 3d= 30240.1O0% LXoo Inu comoy 1o:zo.1ServiceTest# console fiaumeeendhles orchwerwicee+0.8458185Y00• testParsccontactPhoncw1thVal LaNurber = E.104 number parses corrcctly, ext is nul•testParseContactPhoncWithExtension - Number with ext. 42 correctly extracts the extension=oesVarsctonlac noneex Sirincalcolo ohirserttiiionkten chats derstunceolrraninit(..*, 10, "*))•testrarcontac rnonemthcountint oor = Loch on numocrtcovoo to tutr Usine counthy cootanrsccontactloble•testParseContactMobileWithValidNumber - E.164 number returned as-istswarsecon.acwoo@struncalcoloschars=umottohohnochrsowtstuno.eostrie"estarsccontac tootewhcountrwcode =cukmoiowo t usina county cooOal -Necant alll+ < Code$ AdaptiveditterencePurtent vereionSteam = Strack->aetActvitylor>aerlser Oo>oeteaniobnumonstoand dolloto conmonteforeach (Splaylist "mediaSegments' as Ssegment)Ssegnent ("uri') = client con(Ssegment("uri', Stean):SplayList("EXT-X-PLAYLIST-TYPE') = *VOD*:SplayList("EXT-X-ENDLIST') = true:N Wodeud Teams 25554 UTE-R Ai/A enano...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85913
|
2948
|
4
|
2026-05-28T13:28:19.309611+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974899309_m1.jpg...
|
PhpStorm
|
faVsco.js – Service.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowHel iTerm2ShellEditViewSessionScriptsProfilesWindowHelplah]-zshDOCKER881DEV (docker)₴82-zshscreenpipe"84-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash-c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8I 100%85ec2-user@ip-10-30-129-...100% <478• Thu 28 May 16:28:19181ec2-user@ip-10-30-140-…₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
NULL
|
-7938528177350361320
|
NULL
|
click
|
ocr
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowHel iTerm2ShellEditViewSessionScriptsProfilesWindowHelplah]-zshDOCKER881DEV (docker)₴82-zshscreenpipe"84-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash-c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8I 100%85ec2-user@ip-10-30-129-...100% <478• Thu 28 May 16:28:19181ec2-user@ip-10-30-140-…₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85911
|
2948
|
3
|
2026-05-28T13:28:16.205065+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974896205_m1.jpg...
|
PhpStorm
|
faVsco.js – ActivityController.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowHel iTerm2ShellEditViewSessionScriptsProfilesWindowHelplah]-zshDOCKER881DEV (docker)₴82-zshscreenpipe"O ₴4-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash-c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8I 100%85ec2-user@ip-10-30-129-...100% <478 • Thu 28 May 16:28:16181ec2-user@ip-10-30-140-…₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
NULL
|
4855874610199585258
|
NULL
|
click
|
ocr
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowHel iTerm2ShellEditViewSessionScriptsProfilesWindowHelplah]-zshDOCKER881DEV (docker)₴82-zshscreenpipe"O ₴4-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash-c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8I 100%85ec2-user@ip-10-30-129-...100% <478 • Thu 28 May 16:28:16181ec2-user@ip-10-30-140-…₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
85909
|
NULL
|
NULL
|
NULL
|
|
85912
|
2949
|
3
|
2026-05-28T13:28:16.108722+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974896108_m2.jpg...
|
PhpStorm
|
faVsco.js – ActivityController.php
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
wune 8sin bosse sepрeмa-anJa = ISITON3-X-1X3025T2A wune 8sin bosse sepрeмa-anJa = ISITON3-X-1X3025T2Ae1dS•.сол. = Зам-1SINAV7d-X-1X3,025T2Ae105•measton,nuambass tuim, paambarayuoavos te osoloy fuc oecwosnluswon wobtewgdepy $ap00 0) +ooawwwou auoot dow→sosrl boreneoowo woostN 60198608 8 -Pут - (7998188690997-9260-[CREDIT_CARD]-3949 04 991 38388 3095999908 H083 7weolaouocou suedis szunoose eroos as e douuoRieuoPYJoSISVCONSIS573(SOUNO NSHI PISOUMO PEMEHM SSSO PEEON-anJa = LSITON3-X-LX3.35T2Ae10S• .сол. = 3аАL-ISInAY1a-X-LX3.a572Ae10s•meansnon, nuaubassupo auatiamo 1o mbasequambass se,squaubaserpau astiлelds) цреазо)oerodooce trostrooccone toonoco¿ @ 91 X А ярюмзбонA OXoUoroUoedud aswasypeakeialsasues/dde ssaceaaooA JOMOн OPI-4A-OOS E +→ 0TJ6T2wstowartwoown.oc.ookooucor.oot001g00itostomsypo z10 LLeXosenwoseceucl,auoyo,sagunnpasseospsersssceett.os PooxoousNosoceuNoounNoROTORDOyWONSPHAPNWWOSSPROSsoqunnposseos?-L2ectSSSZBZt+. <=joosqnh/wrorspoewooo/e.osbogfooe oyerpoewwogsyjooueo/oenuseooe oswono os weSue PaSPiEcno os uos nerseuwogle, osuoofode ayorpueumog,nsedtoooooe, sappiepononeoo e03 0d0103. 00703 0001700UC0Kooe sotionoo eoooosuwsu 6 soly pouorssonunaрисшшоо/моsuоо/соe очо росшкодоларолuцur oooe KoopnusADSOOUEUAAO0D nOS nHOONGTOWTWTONEDDWNTONTNNOUDONROWSRATOM(с.. 'от ****)3титsoot-umsrosiw.turcotonr=so1opouniscouourbrluo.s0.tnooNousook=•9ADU LU STOnseosuosmrCAVO BE TVA&BININSOUICDOROKUURUD ES P• C+O7-O1OMO7noBonBAeTBL =sorwoisno =dudusra odudJegonuoskannoy odud sisoysunsey/ueno adud ase Jo1eseaeno aJudase ueipueHtieno aHossetroperdpeopied tesows.w0.00.0de1dudasa zuare 6BarensupJeastoadson e<PEASSUSAU10000 5ewwiui3ooodetS7Sz2752asponsall souanxa asalastAuas sspraOoonHEkTOSUISMATHSAPROASONISROlud suadiou dur x dudrasuuas o)-xJ-C960Z-AF UO LZIZL O• SгOOSAel AS• •MOOUIANIМОIСаTИ...
|
NULL
|
1210516918737852876
|
NULL
|
click
|
ocr
|
NULL
|
wune 8sin bosse sepрeмa-anJa = ISITON3-X-1X3025T2A wune 8sin bosse sepрeмa-anJa = ISITON3-X-1X3025T2Ae1dS•.сол. = Зам-1SINAV7d-X-1X3,025T2Ae105•measton,nuambass tuim, paambarayuoavos te osoloy fuc oecwosnluswon wobtewgdepy $ap00 0) +ooawwwou auoot dow→sosrl boreneoowo woostN 60198608 8 -Pут - (7998188690997-9260-[CREDIT_CARD]-3949 04 991 38388 3095999908 H083 7weolaouocou suedis szunoose eroos as e douuoRieuoPYJoSISVCONSIS573(SOUNO NSHI PISOUMO PEMEHM SSSO PEEON-anJa = LSITON3-X-LX3.35T2Ae10S• .сол. = 3аАL-ISInAY1a-X-LX3.a572Ae10s•meansnon, nuaubassupo auatiamo 1o mbasequambass se,squaubaserpau astiлelds) цреазо)oerodooce trostrooccone toonoco¿ @ 91 X А ярюмзбонA OXoUoroUoedud aswasypeakeialsasues/dde ssaceaaooA JOMOн OPI-4A-OOS E +→ 0TJ6T2wstowartwoown.oc.ookooucor.oot001g00itostomsypo z10 LLeXosenwoseceucl,auoyo,sagunnpasseospsersssceett.os PooxoousNosoceuNoounNoROTORDOyWONSPHAPNWWOSSPROSsoqunnposseos?-L2ectSSSZBZt+. <=joosqnh/wrorspoewooo/e.osbogfooe oyerpoewwogsyjooueo/oenuseooe oswono os weSue PaSPiEcno os uos nerseuwogle, osuoofode ayorpueumog,nsedtoooooe, sappiepononeoo e03 0d0103. 00703 0001700UC0Kooe sotionoo eoooosuwsu 6 soly pouorssonunaрисшшоо/моsuоо/соe очо росшкодоларолuцur oooe KoopnusADSOOUEUAAO0D nOS nHOONGTOWTWTONEDDWNTONTNNOUDONROWSRATOM(с.. 'от ****)3титsoot-umsrosiw.turcotonr=so1opouniscouourbrluo.s0.tnooNousook=•9ADU LU STOnseosuosmrCAVO BE TVA&BININSOUICDOROKUURUD ES P• C+O7-O1OMO7noBonBAeTBL =sorwoisno =dudusra odudJegonuoskannoy odud sisoysunsey/ueno adud ase Jo1eseaeno aJudase ueipueHtieno aHossetroperdpeopied tesows.w0.00.0de1dudasa zuare 6BarensupJeastoadson e<PEASSUSAU10000 5ewwiui3ooodetS7Sz2752asponsall souanxa asalastAuas sspraOoonHEkTOSUISMATHSAPROASONISROlud suadiou dur x dudrasuuas o)-xJ-C960Z-AF UO LZIZL O• SгOOSAel AS• •MOOUIANIМОIСаTИ...
|
85910
|
NULL
|
NULL
|
NULL
|
|
85910
|
2949
|
2
|
2026-05-28T13:28:13.124994+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974893124_m2.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rapstomViewCoocWindow#12121 on JY-20963-foc-© Acti rapstomViewCoocWindow#12121 on JY-20963-foc-© ActivityController.php xcustonlosaraveuesA SF fiminny@localhost)Usciko cooscrytriono TesmuonsuCicheenoA console [STAGING>E HubspolE InicaradonAdeTXS AUTO NI>E Listener:final class ActivityController extends Controller implements CommentContextInterfactoAnalyine.AvINTERVAL 38 DAYXby 0.20, u.caazlBY sns count DESCu.name u.sotcphone nunbenv saestorch› E FieldsOpoorunitvMatcheba OpportunitvSvncStrateoreskcase "contact':=7as— 784Sthis->logger->info('processing contact'):Scontact = Stean->cra-›contacts-›where( column: 'crm_provider_id', SobjectId)->fjpze.* fron ceans where 20 =1› ProspectsearchStrategServicetraits©elientrest.php© DecorateActivityTest.ppolated, aositn ties// Contact does not exist locally, import it.if (! Scontact instanceof Contact)Sthis->Logger->info("contact does not exist Locally'):© FieldDetinitionsTest.phScontact = ScraService-›syncContact (SobiectId):CCercwtset ame#i PavtoadRuilderTest.ohe"Quer Rt dertest nhnQuervHandierTast oodif ( Scontact instanceof Contact)E714=715© QueryiteratorTest.php© QueryResultsTests.phpC Semcetescono© SyncBatchRedisServickRacASanicatast oboa CachadComSanicsPaooesthises occeresntol resol vind accounteSaccount = Sthis->resolveAccount (Stean, Scontact, ScrnService, Sprospects)Changes 4 filesE.env.local apc© JiminnyDebugCommand.php app/Console/CommandsT+ 0 +→0 Side-by-side viewer -@ ebbaab95 app/Services/PlaybackService.phpDo not ignore"71 • ?pe loagina.ono contiac) Playbickservice.ono apo serviceeUnversioned Files 9 file:Stean & Stracko>oe Activitye ->oetUser Or>aetteam orinw.nikiochooE.enw.other aodnumonsto andl doloto sill connonteforeach (Splaylist "mediaSegnents') as Ssegment) ?Ka eanhccosea Reoorglestono escluni PolicosSsegment ""uri' = client cdn(Ssegnent ("uri'), Stean):© GreateMockAskJliminnvReoortRocu*tCommand.ohn.ano/Console/Commanavicon.ico ouroEids.tyt aodSplayList ("EXT-X-PLAYLIST-TYPE' = 'VOD'APraw sol quem coaodSplayList (*EXT-X-ENDLIST' = true:@[EMAIL]/Console/Commands/Crm/HubsootM. WERHOOK FILTFRING IMPL FMENTATION molano& console (PROD) X# console fiaum045 A1 A41 У 66 4=NCATCu,id. CASE WHEN u.id = thouner_id THEN • (oaner)* ELSE ** END) AS user_idena1aormen fo FRil soctal accnuntssasers u on u.1d = sa.soclable_1cParGTnCoontd n.teandu.tean_1d = 1117 and sa.provider = "hubspot":*EROM actMtes WHEOF Wund to binl18a2tetth-2147-1817.0144-40480695926801= Musd: " 70033459 VES*EPOM Activitieg WHEDE mnsd to bio(105529043-9994-4781-9226-464d2228185a/) - uuSde # 80186190 N0*EROM eon confaucatzons WHERE 3d = 1953%* FROM teans WHERE id = 1117:+Eoon licene whene a= 30240.inu co woy to.co.eeendhles orchwerwicee+0.• testParsccontactPhoncw1thVal LaNurber = E.104 number parses corrcctly, ext is nul•testParseContactPhoncWithExtension - Number with ext. 42 correctly extracts the extensionoesVarsctonlac noneex Sirincalcolo ohirserttiiionkten chats derstunceolrraninit(..*, 10, "*))•testrarcontac rnonemthcountint oor = Loch on numocrtcovoo to tutr Usine counthy cootanrsccontactloble•testParseContactMobileWithValidNumber - E.164 number returned as-istswarsecon.acwoo@struncalcoloschars=umottohohnochrsowtstuno.eostrie"estarsccontac tootewhcountrwcode =cukmoiowo t usina county cooOal -Necant alll+ < Code$ AdaptiveditterencePurtent vereionSteam = Strack->aetActvitylor>aerlser Oo>oeteaniobSnumonsto and dolloto consontellforeach (Splaylist "mediaSegments' as Ssegment)Ssegnent ("uri') = client con(Ssegment("uri', Stean):SplayList("EXT-X-PLAYLIST-TYPE') = *VOD*:SplayList("EXT-X-ENDLIST') = true:Tiesehensar...
|
NULL
|
3426300873445266929
|
NULL
|
visual_change
|
ocr
|
NULL
|
rapstomViewCoocWindow#12121 on JY-20963-foc-© Acti rapstomViewCoocWindow#12121 on JY-20963-foc-© ActivityController.php xcustonlosaraveuesA SF fiminny@localhost)Usciko cooscrytriono TesmuonsuCicheenoA console [STAGING>E HubspolE InicaradonAdeTXS AUTO NI>E Listener:final class ActivityController extends Controller implements CommentContextInterfactoAnalyine.AvINTERVAL 38 DAYXby 0.20, u.caazlBY sns count DESCu.name u.sotcphone nunbenv saestorch› E FieldsOpoorunitvMatcheba OpportunitvSvncStrateoreskcase "contact':=7as— 784Sthis->logger->info('processing contact'):Scontact = Stean->cra-›contacts-›where( column: 'crm_provider_id', SobjectId)->fjpze.* fron ceans where 20 =1› ProspectsearchStrategServicetraits©elientrest.php© DecorateActivityTest.ppolated, aositn ties// Contact does not exist locally, import it.if (! Scontact instanceof Contact)Sthis->Logger->info("contact does not exist Locally'):© FieldDetinitionsTest.phScontact = ScraService-›syncContact (SobiectId):CCercwtset ame#i PavtoadRuilderTest.ohe"Quer Rt dertest nhnQuervHandierTast oodif ( Scontact instanceof Contact)E714=715© QueryiteratorTest.php© QueryResultsTests.phpC Semcetescono© SyncBatchRedisServickRacASanicatast oboa CachadComSanicsPaooesthises occeresntol resol vind accounteSaccount = Sthis->resolveAccount (Stean, Scontact, ScrnService, Sprospects)Changes 4 filesE.env.local apc© JiminnyDebugCommand.php app/Console/CommandsT+ 0 +→0 Side-by-side viewer -@ ebbaab95 app/Services/PlaybackService.phpDo not ignore"71 • ?pe loagina.ono contiac) Playbickservice.ono apo serviceeUnversioned Files 9 file:Stean & Stracko>oe Activitye ->oetUser Or>aetteam orinw.nikiochooE.enw.other aodnumonsto andl doloto sill connonteforeach (Splaylist "mediaSegnents') as Ssegment) ?Ka eanhccosea Reoorglestono escluni PolicosSsegment ""uri' = client cdn(Ssegnent ("uri'), Stean):© GreateMockAskJliminnvReoortRocu*tCommand.ohn.ano/Console/Commanavicon.ico ouroEids.tyt aodSplayList ("EXT-X-PLAYLIST-TYPE' = 'VOD'APraw sol quem coaodSplayList (*EXT-X-ENDLIST' = true:@[EMAIL]/Console/Commands/Crm/HubsootM. WERHOOK FILTFRING IMPL FMENTATION molano& console (PROD) X# console fiaum045 A1 A41 У 66 4=NCATCu,id. CASE WHEN u.id = thouner_id THEN • (oaner)* ELSE ** END) AS user_idena1aormen fo FRil soctal accnuntssasers u on u.1d = sa.soclable_1cParGTnCoontd n.teandu.tean_1d = 1117 and sa.provider = "hubspot":*EROM actMtes WHEOF Wund to binl18a2tetth-2147-1817.0144-40480695926801= Musd: " 70033459 VES*EPOM Activitieg WHEDE mnsd to bio(105529043-9994-4781-9226-464d2228185a/) - uuSde # 80186190 N0*EROM eon confaucatzons WHERE 3d = 1953%* FROM teans WHERE id = 1117:+Eoon licene whene a= 30240.inu co woy to.co.eeendhles orchwerwicee+0.• testParsccontactPhoncw1thVal LaNurber = E.104 number parses corrcctly, ext is nul•testParseContactPhoncWithExtension - Number with ext. 42 correctly extracts the extensionoesVarsctonlac noneex Sirincalcolo ohirserttiiionkten chats derstunceolrraninit(..*, 10, "*))•testrarcontac rnonemthcountint oor = Loch on numocrtcovoo to tutr Usine counthy cootanrsccontactloble•testParseContactMobileWithValidNumber - E.164 number returned as-istswarsecon.acwoo@struncalcoloschars=umottohohnochrsowtstuno.eostrie"estarsccontac tootewhcountrwcode =cukmoiowo t usina county cooOal -Necant alll+ < Code$ AdaptiveditterencePurtent vereionSteam = Strack->aetActvitylor>aerlser Oo>oeteaniobSnumonsto and dolloto consontellforeach (Splaylist "mediaSegments' as Ssegment)Ssegnent ("uri') = client con(Ssegment("uri', Stean):SplayList("EXT-X-PLAYLIST-TYPE') = *VOD*:SplayList("EXT-X-ENDLIST') = true:Tiesehensar...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85909
|
2948
|
2
|
2026-05-28T13:28:11.403987+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974891403_m1.jpg...
|
PhpStorm
|
faVsco.js – ActivityController.php
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowHel iTerm2ShellEditViewSessionScriptsProfilesWindowHelplah]-zshDOCKER- ₴81DEV (docker)₴82-zshscreenpipe"•84-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash-c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8I 100%85ec2-user@ip-10-30-129-...100% <478• Thu 28 May 16:28:11181ec2-user@ip-10-30-140-…₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
NULL
|
-4019550801436933115
|
NULL
|
click
|
ocr
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowHel iTerm2ShellEditViewSessionScriptsProfilesWindowHelplah]-zshDOCKER- ₴81DEV (docker)₴82-zshscreenpipe"•84-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash-c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8I 100%85ec2-user@ip-10-30-129-...100% <478• Thu 28 May 16:28:11181ec2-user@ip-10-30-140-…₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85908
|
2949
|
1
|
2026-05-28T13:28:09.151837+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974889151_m2.jpg...
|
iTerm2
|
NULL
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormViewNeweNNCCoocWindowFV faVsco.|s ~#12121 PhpStormViewNeweNNCCoocWindowFV faVsco.|s ~#12121 on JY-20963-fx-imnhe heloers.onp©ActivityControlier.php=custom.loglaravel.logA SF fiminny@localhost)HS Jocal (jiminny(blocalhost)console (PROD) x C Service.php# console fiaumUsciko cooscrytriono Tesmuons© Client.phpconsolA ISTAGING>E HubspolE InicaradonAde>E Listener:class ServiceTest extends TestCasepublic function testParseContactPhoneWithCountryCodeO: void045 A1 A41 У 66 Av saestorch>D Fielde2595090OpportunitvMatcheba OpportunitvSvncStratesorassenAnnayhaskey ney.ohoneoononoehSthis->assentStringStartsWith@prefic *+44*. SparsedNunberf'phone'])uD SDaSSeNULLOPAOY700=791E7e2_705-705created at > DATE SUB(NOWO.INTERVAL 38 DAY.BY u.id, u.email, u.name, u.softphone numbenBY sns count DESC* fron teans where id = 1› ProspectsearchStrategServicetraits©elientrest.php© DecorateActivityTest.ppolated, aositn ties" fron rolesusaod=797-783public static function parseContactMobileProvider(): arrayNCATU.Nd. CASE WHEN U.N© FieldbefinitionsTest.ph 2693CCercwme amenreturn2694DPayloadBullderTesupny 2695 DQueryBuilder Test.php© QueryHandler Test.php© QueryiteratorTest.phpQueryResunsiestspip 2690C Semcetesconoemory hoo il ephone returns nutt=>wobtlephone s> "' nutur nuuuno MobiilePhone key returns null' => [ll null. nulll.Onen o FRil soctallaceSeNg M On NiG sArsOepargtncesE715— 712—714U.tean_1d = 1117 and sa.+EROM actM tes WHEDE*FROM activities. WHFDE7A18I© SyncBatchRedisserviat2s1лlRacASanicatast obo2412Va CachadCrm SanicsPhooewkoataenav.honnancerootcerlohmepcoutem* FROM eon conf qucataapublio function testParseContactiobiten thenptyrnone Carray Sersibata, Pstring ScountryCode, Pstring S ,2+ EROM tRAnC WHERE SO* Eron uicene whene 3aChanges 4 filesE.env.local apc© JiminnyDebugCommand.php app/Console/Commands1L P +→ Side-by-side viewer -Do not lgnoreHighlght words +X15 € ?@ ebbaab95 app/Services/PlaybackService.phppe loagina.ono contiac) Playbickservice.ono apo serviceeUnversioned Files 9 file:Stean & Stracko>oe Activitye ->oetUser Or>aetteam orEinw.nikiochhogE.enw.other aodnumonsto andl doloto sill connonteforeach (Splaylist('mediaSegnents'] as Ssegment) ‹Ka eanhccosea Reoorglestono escluni PolicosSsegment ""uri' = client cdn(Ssegnent ("uri'), Stean):© GreateMockAskJliminnvReoortRocu*tCommand.ohn.ano/Console/Commanavicon.ico ouroEids.tyt aodSplayList ("EXT-X-PLAYLIST-TYPE' = 'VOD'APraw sol quem coaodSplayList (*EXT-X-ENDLIST' = true:@[EMAIL]/Console/Commands/Crm/HubsootM. WERHOOK FILTFRING IMPIFWENTATION mol anol7o0sLXo Inu comoy 1o.zo.usServiceTesteeendhles orchwerwicee+0.• testParsccontactPhoncw1thVal LaNurber = E.104 number parses corrcctly, ext is nul•testParseContactPhoncWithExtension - Number with ext. 42 correctly extracts the extensionoesParsctonlack noneex Strinca coloohirertiiion cn chas oestunceolsrras{nit(..•, 10, "*))oestrarctontact tnonenthcountincoor = Loch on numot tco voo to tut Usine counhy cootanrsccontacthobeehcenevetaeInclude non-project items•testParseContactMobileWithValidNumber - E.164 number returned as-iseswarsecon.ac.tooeStruncalcoloschars=umottchowhnochharsowstunc.eostr.ntesQ- app/Http/Controllers/APl/[EMAIL]./apo/Htto/Controllers/APl/ActivityController.phr<> ActivityController.oho.html build/coverace/Http/Controllers/AF© ActivityStatsController.oho./apo/Htto/Controllers/AP1/Teaminsiahts/ActivityStatsController.ohgoestarsccontac tootewhcountrwcode =cukmoiwo t usina county cooOal -<> ActivityStatscontroller.php.html buiid/coverage/Http/controllers/APl/[EMAIL]/ano/Htto/Controllers/APIM?/ActivitvV2Controller.ohrinnvlHtollconttollors?lcweontroller=haset..annRttn/conttollerautc oadcacsmao.chokrM4liminnvl|Httol|Gontrollers|IAP1|Activitv@ontroller.es_DIP//Yaoo/Htto/Controllerautoload.static.oho.455771R6 480Necant alllAsk ammnina+ « Code$ Adaptiveditterenceegment)unstCtosnM Woderd Teams 280847 UTE-R AiA enano...
|
NULL
|
2623055657401608146
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormViewNeweNNCCoocWindowFV faVsco.|s ~#12121 PhpStormViewNeweNNCCoocWindowFV faVsco.|s ~#12121 on JY-20963-fx-imnhe heloers.onp©ActivityControlier.php=custom.loglaravel.logA SF fiminny@localhost)HS Jocal (jiminny(blocalhost)console (PROD) x C Service.php# console fiaumUsciko cooscrytriono Tesmuons© Client.phpconsolA ISTAGING>E HubspolE InicaradonAde>E Listener:class ServiceTest extends TestCasepublic function testParseContactPhoneWithCountryCodeO: void045 A1 A41 У 66 Av saestorch>D Fielde2595090OpportunitvMatcheba OpportunitvSvncStratesorassenAnnayhaskey ney.ohoneoononoehSthis->assentStringStartsWith@prefic *+44*. SparsedNunberf'phone'])uD SDaSSeNULLOPAOY700=791E7e2_705-705created at > DATE SUB(NOWO.INTERVAL 38 DAY.BY u.id, u.email, u.name, u.softphone numbenBY sns count DESC* fron teans where id = 1› ProspectsearchStrategServicetraits©elientrest.php© DecorateActivityTest.ppolated, aositn ties" fron rolesusaod=797-783public static function parseContactMobileProvider(): arrayNCATU.Nd. CASE WHEN U.N© FieldbefinitionsTest.ph 2693CCercwme amenreturn2694DPayloadBullderTesupny 2695 DQueryBuilder Test.php© QueryHandler Test.php© QueryiteratorTest.phpQueryResunsiestspip 2690C Semcetesconoemory hoo il ephone returns nutt=>wobtlephone s> "' nutur nuuuno MobiilePhone key returns null' => [ll null. nulll.Onen o FRil soctallaceSeNg M On NiG sArsOepargtncesE715— 712—714U.tean_1d = 1117 and sa.+EROM actM tes WHEDE*FROM activities. WHFDE7A18I© SyncBatchRedisserviat2s1лlRacASanicatast obo2412Va CachadCrm SanicsPhooewkoataenav.honnancerootcerlohmepcoutem* FROM eon conf qucataapublio function testParseContactiobiten thenptyrnone Carray Sersibata, Pstring ScountryCode, Pstring S ,2+ EROM tRAnC WHERE SO* Eron uicene whene 3aChanges 4 filesE.env.local apc© JiminnyDebugCommand.php app/Console/Commands1L P +→ Side-by-side viewer -Do not lgnoreHighlght words +X15 € ?@ ebbaab95 app/Services/PlaybackService.phppe loagina.ono contiac) Playbickservice.ono apo serviceeUnversioned Files 9 file:Stean & Stracko>oe Activitye ->oetUser Or>aetteam orEinw.nikiochhogE.enw.other aodnumonsto andl doloto sill connonteforeach (Splaylist('mediaSegnents'] as Ssegment) ‹Ka eanhccosea Reoorglestono escluni PolicosSsegment ""uri' = client cdn(Ssegnent ("uri'), Stean):© GreateMockAskJliminnvReoortRocu*tCommand.ohn.ano/Console/Commanavicon.ico ouroEids.tyt aodSplayList ("EXT-X-PLAYLIST-TYPE' = 'VOD'APraw sol quem coaodSplayList (*EXT-X-ENDLIST' = true:@[EMAIL]/Console/Commands/Crm/HubsootM. WERHOOK FILTFRING IMPIFWENTATION mol anol7o0sLXo Inu comoy 1o.zo.usServiceTesteeendhles orchwerwicee+0.• testParsccontactPhoncw1thVal LaNurber = E.104 number parses corrcctly, ext is nul•testParseContactPhoncWithExtension - Number with ext. 42 correctly extracts the extensionoesParsctonlack noneex Strinca coloohirertiiion cn chas oestunceolsrras{nit(..•, 10, "*))oestrarctontact tnonenthcountincoor = Loch on numot tco voo to tut Usine counhy cootanrsccontacthobeehcenevetaeInclude non-project items•testParseContactMobileWithValidNumber - E.164 number returned as-iseswarsecon.ac.tooeStruncalcoloschars=umottchowhnochharsowstunc.eostr.ntesQ- app/Http/Controllers/APl/[EMAIL]./apo/Htto/Controllers/APl/ActivityController.phr<> ActivityController.oho.html build/coverace/Http/Controllers/AF© ActivityStatsController.oho./apo/Htto/Controllers/AP1/Teaminsiahts/ActivityStatsController.ohgoestarsccontac tootewhcountrwcode =cukmoiwo t usina county cooOal -<> ActivityStatscontroller.php.html buiid/coverage/Http/controllers/APl/[EMAIL]/ano/Htto/Controllers/APIM?/ActivitvV2Controller.ohrinnvlHtollconttollors?lcweontroller=haset..annRttn/conttollerautc oadcacsmao.chokrM4liminnvl|Httol|Gontrollers|IAP1|Activitv@ontroller.es_DIP//Yaoo/Htto/Controllerautoload.static.oho.455771R6 480Necant alllAsk ammnina+ « Code$ Adaptiveditterenceegment)unstCtosnM Woderd Teams 280847 UTE-R AiA enano...
|
85905
|
NULL
|
NULL
|
NULL
|
|
85907
|
2948
|
1
|
2026-05-28T13:28:09.051546+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974889051_m1.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Include non-project items
Preview
Filter
Open in F Include non-project items
Preview
Filter
Open in Find Tool Window
app/Http/Controllers/API/ActivityController.php
ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class
ActivityController.php.html build/coverage/Http/Controllers/API...
|
[{"role":"AXCheckBox","text [{"role":"AXCheckBox","text":"Include non-project items","depth":2,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Preview","depth":2,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter","depth":2,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Find Tool Window","depth":2,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"app/Http/Controllers/API/ActivityController.php","depth":1,"on_screen":true,"value":"app/Http/Controllers/API/ActivityController.php","role_description":"text field","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityController.php.html build/coverage/Http/Controllers/API","depth":2,"on_screen":true,"role_description":"text"}]...
|
-4850061339535374778
|
-7025256415354728599
|
click
|
accessibility
|
NULL
|
Include non-project items
Preview
Filter
Open in F Include non-project items
Preview
Filter
Open in Find Tool Window
app/Http/Controllers/API/ActivityController.php
ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class
ActivityController.php.html build/coverage/Http/Controllers/API...
|
85906
|
NULL
|
NULL
|
NULL
|
|
85906
|
2948
|
0
|
2026-05-28T13:27:49.833773+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974869833_m1.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Include non-project items
Preview
Filter
Open in F Include non-project items
Preview
Filter
Open in Find Tool Window
app/Http/Controllers/API/ActivityController.php
ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class
ActivityController.php.html build/coverage/Http/Controllers/API
ActivityStatsController.php .../app/Http/Controllers/API/TeamInsights/ActivityStatsController.php, class
ActivityStatsController.php.html build/coverage/Http/Controllers/API/TeamInsights
ActivityV2Controller.php .../app/Http/Controllers/API/V2/ActivityV2Controller.php, class
ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class
ActivityController.php.html build/coverage/Http/Controllers/API
ActivityStatsController.php .../app/Http/Controllers/API/TeamInsights/ActivityStatsController.php, class
ActivityStatsController.php.html build/coverage/Http/Controllers/API/TeamInsights
ActivityV2Controller.php .../app/Http/Controllers/API/V2/ActivityV2Controller.php, class
Http/Controllers/API/ActivityController.php
Open In Right Split...
|
[{"role":"AXCheckBox","text [{"role":"AXCheckBox","text":"Include non-project items","depth":2,"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Preview","depth":2,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter","depth":2,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Find Tool Window","depth":2,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"app/Http/Controllers/API/ActivityController.php","depth":1,"on_screen":true,"value":"app/Http/Controllers/API/ActivityController.php","role_description":"text field","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityController.php.html build/coverage/Http/Controllers/API","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityStatsController.php .../app/Http/Controllers/API/TeamInsights/ActivityStatsController.php, class","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityStatsController.php.html build/coverage/Http/Controllers/API/TeamInsights","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityV2Controller.php .../app/Http/Controllers/API/V2/ActivityV2Controller.php, class","depth":2,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityController.php.html build/coverage/Http/Controllers/API","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityStatsController.php .../app/Http/Controllers/API/TeamInsights/ActivityStatsController.php, class","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityStatsController.php.html build/coverage/Http/Controllers/API/TeamInsights","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityV2Controller.php .../app/Http/Controllers/API/V2/ActivityV2Controller.php, class","depth":4,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Http/Controllers/API/ActivityController.php","depth":1,"on_screen":true,"help_text":"Http/Controllers/API/ActivityController.php","role_description":"text"},{"role":"AXLink","text":"Open In Right Split","depth":1,"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6429638851078712736
|
1022394378506160504
|
idle
|
accessibility
|
NULL
|
Include non-project items
Preview
Filter
Open in F Include non-project items
Preview
Filter
Open in Find Tool Window
app/Http/Controllers/API/ActivityController.php
ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class
ActivityController.php.html build/coverage/Http/Controllers/API
ActivityStatsController.php .../app/Http/Controllers/API/TeamInsights/ActivityStatsController.php, class
ActivityStatsController.php.html build/coverage/Http/Controllers/API/TeamInsights
ActivityV2Controller.php .../app/Http/Controllers/API/V2/ActivityV2Controller.php, class
ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class
ActivityController.php.html build/coverage/Http/Controllers/API
ActivityStatsController.php .../app/Http/Controllers/API/TeamInsights/ActivityStatsController.php, class
ActivityStatsController.php.html build/coverage/Http/Controllers/API/TeamInsights
ActivityV2Controller.php .../app/Http/Controllers/API/V2/ActivityV2Controller.php, class
Http/Controllers/API/ActivityController.php
Open In Right Split...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85905
|
2949
|
0
|
2026-05-28T13:27:48.830137+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974868830_m2.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Include non-project items
Preview
Filter
Open in F Include non-project items
Preview
Filter
Open in Find Tool Window
app/Http/Controllers/API/ActivityController.php
ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class
ActivityController.php.html build/coverage/Http/Controllers/API
ActivityStatsController.php .../app/Http/Controllers/API/TeamInsights/ActivityStatsController.php, class
ActivityStatsController.php.html build/coverage/Http/Controllers/API/TeamInsights
ActivityV2Controller.php .../app/Http/Controllers/API/V2/ActivityV2Controller.php, class
ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class
ActivityController.php.html build/coverage/Http/Controllers/API
ActivityStatsController.php .../app/Http/Controllers/API/TeamInsights/ActivityStatsController.php, class
ActivityStatsController.php.html build/coverage/Http/Controllers/API/TeamInsights
ActivityV2Controller.php .../app/Http/Controllers/API/V2/ActivityV2Controller.php, class
Http/Controllers/API/ActivityController.php
Open In Right Split...
|
[{"role":"AXCheckBox","text [{"role":"AXCheckBox","text":"Include non-project items","depth":2,"bounds":{"left":0.66788566,"top":0.24181964,"width":0.064494684,"height":0.01915403},"on_screen":true,"role_description":"checkbox","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Preview","depth":2,"bounds":{"left":0.73238033,"top":0.24181964,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter","depth":2,"bounds":{"left":0.74102396,"top":0.24181964,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Find Tool Window","depth":2,"bounds":{"left":0.7496675,"top":0.24181964,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"app/Http/Controllers/API/ActivityController.php","depth":1,"bounds":{"left":0.50232714,"top":0.27214685,"width":0.25598404,"height":0.023144454},"on_screen":true,"value":"app/Http/Controllers/API/ActivityController.php","role_description":"text field","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class","depth":2,"bounds":{"left":0.4993351,"top":0.30407023,"width":0.26196808,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityController.php.html build/coverage/Http/Controllers/API","depth":2,"bounds":{"left":0.4993351,"top":0.3216281,"width":0.26196808,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityStatsController.php .../app/Http/Controllers/API/TeamInsights/ActivityStatsController.php, class","depth":2,"bounds":{"left":0.4993351,"top":0.33918595,"width":0.26196808,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityStatsController.php.html build/coverage/Http/Controllers/API/TeamInsights","depth":2,"bounds":{"left":0.4993351,"top":0.3567438,"width":0.26196808,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityV2Controller.php .../app/Http/Controllers/API/V2/ActivityV2Controller.php, class","depth":2,"bounds":{"left":0.4993351,"top":0.37430167,"width":0.26196808,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class","depth":4,"bounds":{"left":0.4993351,"top":0.30407023,"width":0.26196808,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityController.php.html build/coverage/Http/Controllers/API","depth":4,"bounds":{"left":0.4993351,"top":0.3216281,"width":0.26196808,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityStatsController.php .../app/Http/Controllers/API/TeamInsights/ActivityStatsController.php, class","depth":4,"bounds":{"left":0.4993351,"top":0.33918595,"width":0.26196808,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityStatsController.php.html build/coverage/Http/Controllers/API/TeamInsights","depth":4,"bounds":{"left":0.4993351,"top":0.3567438,"width":0.26196808,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ActivityV2Controller.php .../app/Http/Controllers/API/V2/ActivityV2Controller.php, class","depth":4,"bounds":{"left":0.4993351,"top":0.37430167,"width":0.26196808,"height":0.017557861},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Http/Controllers/API/ActivityController.php","depth":1,"bounds":{"left":0.50598407,"top":0.75259376,"width":0.080119684,"height":0.013567438},"on_screen":true,"help_text":"Http/Controllers/API/ActivityController.php","role_description":"text"},{"role":"AXLink","text":"Open In Right Split","depth":1,"bounds":{"left":0.71476066,"top":0.75259376,"width":0.03856383,"height":0.013567438},"on_screen":true,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
6429638851078712736
|
1022394378506160504
|
idle
|
accessibility
|
NULL
|
Include non-project items
Preview
Filter
Open in F Include non-project items
Preview
Filter
Open in Find Tool Window
app/Http/Controllers/API/ActivityController.php
ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class
ActivityController.php.html build/coverage/Http/Controllers/API
ActivityStatsController.php .../app/Http/Controllers/API/TeamInsights/ActivityStatsController.php, class
ActivityStatsController.php.html build/coverage/Http/Controllers/API/TeamInsights
ActivityV2Controller.php .../app/Http/Controllers/API/V2/ActivityV2Controller.php, class
ActivityController.php .../app/Http/Controllers/API/ActivityController.php, final class
ActivityController.php.html build/coverage/Http/Controllers/API
ActivityStatsController.php .../app/Http/Controllers/API/TeamInsights/ActivityStatsController.php, class
ActivityStatsController.php.html build/coverage/Http/Controllers/API/TeamInsights
ActivityV2Controller.php .../app/Http/Controllers/API/V2/ActivityV2Controller.php, class
Http/Controllers/API/ActivityController.php
Open In Right Split...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85904
|
NULL
|
0
|
2026-05-28T13:27:16.176836+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974836176_m1.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Project Files
Preview
Filter
Open in Find Tool Win Project Files
Preview
Filter
Open in Find Tool Window
app/Http/Controllers/API/ActivityController.php...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project Files","depth":2,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Preview","depth":2,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter","depth":2,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Find Tool Window","depth":2,"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"app/Http/Controllers/API/ActivityController.php","depth":1,"on_screen":true,"value":"app/Http/Controllers/API/ActivityController.php","role_description":"text field","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false}]...
|
7142920278886782853
|
577118956892520976
|
click
|
hybrid
|
NULL
|
Project Files
Preview
Filter
Open in Find Tool Win Project Files
Preview
Filter
Open in Find Tool Window
app/Http/Controllers/API/ActivityController.php
iTerm2ShellEditViewSessionScriptsProfilesWindowHelp-zshDOCKER881DEV (docker)₴82-zshscreenpipe"•84-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash-c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8I 100%85ec2-user@ip-10-30-129-...100% <78 • Thu 28 May 16:27:15181ec2-user@ip-10-30-140-…₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
85901
|
NULL
|
NULL
|
NULL
|
|
85903
|
NULL
|
0
|
2026-05-28T13:27:16.033591+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974836033_m2.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
PhpStormViewNeweNNCCoocWindowFV faVsco.|s ~#12121 PhpStormViewNeweNNCCoocWindowFV faVsco.|s ~#12121 on JY-20963-fx-imnhe heloers.onp©ActivityControlier.phpUscrko.cooscrvtrcono Tesmuonsc) eienupnp>E HubspolE InicaradonAde>E Listener:class ServiceTest extends TestCasepublic function testParseContactPhoneWithCountryCodeO: voidv saestorch>D Field.25955990OpportunitvMatcheba OpportunitvSvncStrateusorassenAnhayhaskey ney.ononeoononoehSthis->assentStringStartsWith@prefic '+44*. SparsedNunberf'phone'))uD SDaSSeNULLOPAOY› ProspectsearchStrategService t raits© elientrest.php© DecorateActivityTest.ppolated, aositn tiesusaodpublic static function parseContactMobileProvider(): array© FieldbefinitionsTest.ph 2693CCeTcwmaet amereturn2694DPayloadBullderTesupny 2695 DQueryBuilder Test.php© QueryHandler Test.php© QueryiteratorTest.phpQueryResunsiestspip 2690C Semcetesconoemory hoo i ephone returns nutt=>wobtlephone s> "' nutur nuuuno MobsilePhone key returns null' a> [ll. null. nulll.7A18I© SyncBatchRedisserviat2s1лlRacASanicatast obo2412Va CachadCrm SanicsPhooewkoataenav.honnancerootcerlohmepcoutempublio function testParseContactiobiten thenptyrnone Carray Sersibata, Pstring ScountryCode, Pstring S ,2Changes 4 filesE.env.local apc© JiminnyDebugCommand.php app/Console/Commands1L P +→ Side-by-side viewer -Do not ignore"Highlight words"710?@ ebbaab95 app/Services/PlaybackService.phppp loaging,ono contiac) Playbickservice.ono apo sernceeUnversioned Files 9 file:Stean & Stracko>oe ActivityO->oetUser Ole>aetTeam Orinw.nikiochooE.enw.other aod/ Enumerate and delete all segnents.foreach (Splaylist "mediaSegnents') as Ssegment) "la eanaccosea Reoorgles ono esclunt PoicesSsegment ""uri' = client cdn(Ssegnent ("uri'), Steam):© GreateMockAskJliminnvReoortRocu*tCommand.ohn.ano/Console/Commanavicon.ico ouroEids.tyt aodSplayList ("EXT-X-PLAYLIST-TYPE' = 'VOD'APraw sol quem coaodSplayList (*EXT-X-ENDLIST' = true:@[EMAIL]/Console/Commands/Crm/HubsootM. WERHOOK FILTFRING IMPIFWENTATION mol anolcustonlosaraveuosA SF fiminny@localhost)A console [STAGING=7017e57847es=797708709TXS AUTO NIcreated at > DATE SUB(NOWO,INTERVAL 38 DAYXbY 0.20u.caazlBY sns count DESCu.name u.sotcphone nunben* fron ceans where 20 =1NCATU.Nd, CASE WHEN U.Tonmen 1o FRil soctalacesers u on u.1d = sa.soc1pargtuncosU.tean_1d = 1117 and sa.+EROM actM tes WHEDE+EROM actM tes. WHEDE*EROM eon confauratad* FROM teans WHERE id =+Eoon lisens whene fdsClassesSymbolsActionsQ- app/Http/Controllers/APl/ActivityController.php& console (PROD) X# console fiaum045 A1 A41 У 66 ATexProject Filesvoo nu comoy toic/eleServiceTesteeendhlesorceserwicee+0.• testParsccontactPhoncw1thVal LaNumber = E.104 number parses corrcctly, ext is nul•testParseContactPhoncWithExtension - Number with ext. 42 correctly extracts the extensionoesvarsctontac noneex Sirinca colothirerxiiiion crno chascetunceolri:init(..*, 10, "*))oestrarsctontac rnonemthcountin ooc = Loch on nomot tconooto tut Usine counry cooanrsccontactlobletestParseContactMobileWithVal1dNumber -E.164 number returned as-isswarseconkac.nooestrunca.coloachars=[EMAIL]=cllkmoowotusins couniry cooOal -1R6 480Necant alllAsk ammnina4@code§ Adaptiveditterenceegment)unstCtosnM Woderd Teams 280847 UTE-R AiA enano...
|
NULL
|
7508432122332628947
|
NULL
|
click
|
ocr
|
NULL
|
PhpStormViewNeweNNCCoocWindowFV faVsco.|s ~#12121 PhpStormViewNeweNNCCoocWindowFV faVsco.|s ~#12121 on JY-20963-fx-imnhe heloers.onp©ActivityControlier.phpUscrko.cooscrvtrcono Tesmuonsc) eienupnp>E HubspolE InicaradonAde>E Listener:class ServiceTest extends TestCasepublic function testParseContactPhoneWithCountryCodeO: voidv saestorch>D Field.25955990OpportunitvMatcheba OpportunitvSvncStrateusorassenAnhayhaskey ney.ononeoononoehSthis->assentStringStartsWith@prefic '+44*. SparsedNunberf'phone'))uD SDaSSeNULLOPAOY› ProspectsearchStrategService t raits© elientrest.php© DecorateActivityTest.ppolated, aositn tiesusaodpublic static function parseContactMobileProvider(): array© FieldbefinitionsTest.ph 2693CCeTcwmaet amereturn2694DPayloadBullderTesupny 2695 DQueryBuilder Test.php© QueryHandler Test.php© QueryiteratorTest.phpQueryResunsiestspip 2690C Semcetesconoemory hoo i ephone returns nutt=>wobtlephone s> "' nutur nuuuno MobsilePhone key returns null' a> [ll. null. nulll.7A18I© SyncBatchRedisserviat2s1лlRacASanicatast obo2412Va CachadCrm SanicsPhooewkoataenav.honnancerootcerlohmepcoutempublio function testParseContactiobiten thenptyrnone Carray Sersibata, Pstring ScountryCode, Pstring S ,2Changes 4 filesE.env.local apc© JiminnyDebugCommand.php app/Console/Commands1L P +→ Side-by-side viewer -Do not ignore"Highlight words"710?@ ebbaab95 app/Services/PlaybackService.phppp loaging,ono contiac) Playbickservice.ono apo sernceeUnversioned Files 9 file:Stean & Stracko>oe ActivityO->oetUser Ole>aetTeam Orinw.nikiochooE.enw.other aod/ Enumerate and delete all segnents.foreach (Splaylist "mediaSegnents') as Ssegment) "la eanaccosea Reoorgles ono esclunt PoicesSsegment ""uri' = client cdn(Ssegnent ("uri'), Steam):© GreateMockAskJliminnvReoortRocu*tCommand.ohn.ano/Console/Commanavicon.ico ouroEids.tyt aodSplayList ("EXT-X-PLAYLIST-TYPE' = 'VOD'APraw sol quem coaodSplayList (*EXT-X-ENDLIST' = true:@[EMAIL]/Console/Commands/Crm/HubsootM. WERHOOK FILTFRING IMPIFWENTATION mol anolcustonlosaraveuosA SF fiminny@localhost)A console [STAGING=7017e57847es=797708709TXS AUTO NIcreated at > DATE SUB(NOWO,INTERVAL 38 DAYXbY 0.20u.caazlBY sns count DESCu.name u.sotcphone nunben* fron ceans where 20 =1NCATU.Nd, CASE WHEN U.Tonmen 1o FRil soctalacesers u on u.1d = sa.soc1pargtuncosU.tean_1d = 1117 and sa.+EROM actM tes WHEDE+EROM actM tes. WHEDE*EROM eon confauratad* FROM teans WHERE id =+Eoon lisens whene fdsClassesSymbolsActionsQ- app/Http/Controllers/APl/ActivityController.php& console (PROD) X# console fiaum045 A1 A41 У 66 ATexProject Filesvoo nu comoy toic/eleServiceTesteeendhlesorceserwicee+0.• testParsccontactPhoncw1thVal LaNumber = E.104 number parses corrcctly, ext is nul•testParseContactPhoncWithExtension - Number with ext. 42 correctly extracts the extensionoesvarsctontac noneex Sirinca colothirerxiiiion crno chascetunceolri:init(..*, 10, "*))oestrarsctontac rnonemthcountin ooc = Loch on nomot tconooto tut Usine counry cooanrsccontactlobletestParseContactMobileWithVal1dNumber -E.164 number returned as-isswarseconkac.nooestrunca.coloachars=[EMAIL]=cllkmoowotusins couniry cooOal -1R6 480Necant alllAsk ammnina4@code§ Adaptiveditterenceegment)unstCtosnM Woderd Teams 280847 UTE-R AiA enano...
|
85902
|
NULL
|
NULL
|
NULL
|
|
85902
|
2947
|
24
|
2026-05-28T13:27:12.297092+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974832297_m2.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Project Files
Preview
Filter
Open in Find Tool Win Project Files
Preview
Filter
Open in Find Tool Window
app/Http/Controllers/API/ActivityController.php...
|
[{"role":"AXButton","text" [{"role":"AXButton","text":"Project Files","depth":2,"bounds":{"left":0.6968085,"top":0.24181964,"width":0.03557181,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Preview","depth":2,"bounds":{"left":0.73238033,"top":0.24181964,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Filter","depth":2,"bounds":{"left":0.74102396,"top":0.24181964,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Open in Find Tool Window","depth":2,"bounds":{"left":0.7496675,"top":0.24181964,"width":0.008643617,"height":0.01915403},"on_screen":true,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXTextField","text":"app/Http/Controllers/API/ActivityController.php","depth":1,"bounds":{"left":0.50232714,"top":0.27214685,"width":0.25598404,"height":0.023144454},"on_screen":true,"value":"app/Http/Controllers/API/ActivityController.php","role_description":"text field","is_enabled":true,"is_focused":true,"is_selected":false,"is_expanded":false}]...
|
7142920278886782853
|
577118956892520976
|
typing_pause
|
hybrid
|
NULL
|
Project Files
Preview
Filter
Open in Find Tool Win Project Files
Preview
Filter
Open in Find Tool Window
app/Http/Controllers/API/ActivityController.php
PhpStormViewNeWENNCCoocWindowFV faVsco.|s ~#12121 on JY-20963-fx-imwnapers.ohe©ActivityControlier.phpUscrko.cooscrvtrcono Tesmuonsc) eienupnpE HubspolE InicaradonAde>E Listener:class ServiceTest extends TestCasepublic function testParseContactPhoneWithCountryCodeO: voidv saestorch>D Field.25955990OpportunitvMatcheba OpportunitvSvncStratesorassenAnhayhaskey ney.ononeoononoehSthis->assentStringStartsWith@prefic '+44*. SparsedNunberf'phone')ED SDaSSeNULLOPAOY› ProspectsearchStrategService t raits© elientrest.php© DecorateActivityTest.ppolated, aositn tiesusaodpublic static function parseContactMobileProvider(): array© FieldbefinitionsTest.ph 2693CCeTcwmaet amereturn2634DPayloadBullderTesupny 2695 DQueryBuilder Test.php© QueryHandler Test.php© QueryiteratorTest.phpQueryResunsiestspip 2690c Semcetesconoemory hoo i ephone returns nutt=>wobtlephone s> "' nutur nutuno MobsilePhone key returns null' a> [ll. null. nulll.7A18I© SyncBatchRedisserviat2s1lRacASanicatast obo2412Va CachadCrm SanicsPhooewkoataenav.honnancerootcerlohmepcoutempublio function testParseContactiobiten thenptyrnone Carray Sorsibata, Pstring ScountryCode, Pstring S ,2Changes 4 filesE.env.local apc© JiminnyDebugCommand.php app/Console/Commands1L P +→ Side-by-side viewer -Do not ignore"Highlight words"710?@ ebbaab95 app/Services/PlaybackService.phppe loaaina.ono contiac) Playbickservice.ono apo sernceeUnversioned Files 9 file:Stean & Stracko>oe ActivityO->oetUser Ole>aetTeam OrEinw.nikiochhogE.enw.other aod/ Enumerate and delete all segnents.foreach (Splaylist "mediaSegnents') as Ssegment) "la anaccosea Reoorgles ono esclunt PoicesSsegment ""uri' = client cdn(Ssegnent ("uri'), Steam):© GreateMockAskJliminnvReoortRocu*tCommand.ohnano/Console/Commanav con.ico ourdEids.tyt aodSplayList ("EXT-X-PLAYLIST-TYPE' = 'VOD'APraw sol quem coaodSplayList (*EXT-X-ENDLIST' = true:@[EMAIL]/Console/Commands/Crm/HubsootM. WERHOOK FILTFRING IMPIFWENTATION mol anolcustonlosaraveuosA SF fiminny@localhost)A console [STAGING=7037e517847es=797708709TXS AUTO NIcreated at > DATE SUB(NOWO,INTERVAL 38 DAY.bY 0.20u.caazlBY sns count DESCu.name u.sotcphone nunben* fron ceans where 20 =1NCATU.Nd, CASE WHEN U.onmen 1o FRil soctalacesers u on u.1d = sa.soc1pangtuncosU.tean_1d = 1117 and sa.+EROM actM tes WHEDE+EROM actM tes. WHEDE*EROM eon confauratad* FROM teans WHERE id =+Eoon lisens whene fdsClassesSymbolsActionsQ- app/Http/Controllers/APl/ActivityController.php& console (PROD) X# console fiaum8458185Y00TexProject FilesvJO0%L7Aoo inu comoy toicelServiceTesteeendhlesorceserwicee+0.• testParsccontactPhoncw1thVa LaNumber = E.104 number parses corrcctly, ext is nul•testParseContactPhoncWithExtension - Number with ext. 42 correctly extracts the extensionoesvarsccontac noneex Sirinca colothirerxiiiion crhno chascetunceolri:{nit(..•, 10, "*))oestrarsctontac rnonemthcountin ooc = Loch on nomottconooto tut Usine counry cooanrsccontactlobletestParseContactMobileWithVal1dNumber -E.164 number returned [EMAIL]=[EMAIL]=clkmoowotusins couniry cooOal -1RA A80Necant alllAsk ammnina4 @ code§ AdaptiveditterencepunstCtosnM Woderd Teams 280847 UTE-R AiA enano...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85901
|
2946
|
20
|
2026-05-28T13:27:09.142877+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974829142_m1.jpg...
|
PhpStorm
|
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowH iTerm2ShellEditViewSessionScriptsProfilesWindowHelp(ah]-zshDOCKER÷ ₴81DEV (docker)₴82-zshscreenpipe"84-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash-c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8I 100%X5ec2-user@ip-10-30-129-...100% <78 • Thu 28 May 16:27:08181ec2-user@ip-10-30-140-...₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
NULL
|
3545671891130730163
|
NULL
|
visual_change
|
ocr
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowH iTerm2ShellEditViewSessionScriptsProfilesWindowHelp(ah]-zshDOCKER÷ ₴81DEV (docker)₴82-zshscreenpipe"84-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash-c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8I 100%X5ec2-user@ip-10-30-129-...100% <78 • Thu 28 May 16:27:08181ec2-user@ip-10-30-140-...₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85900
|
2947
|
23
|
2026-05-28T13:27:07.661352+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974827661_m2.jpg...
|
iTerm2
|
NULL
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rapstomViewNeweNNCCoocWindowFV faVsco.|s ~#12121 o rapstomViewNeweNNCCoocWindowFV faVsco.|s ~#12121 on JY-20963-fx-imnhe heloers.onp©ActivityControlier.php=custom.logaraveuesA SF fiminny@localhost)Usciko cooscrytriono Tesmuonsc) eienupnpA console [STAGING>E HubspolE InicaradonAdeTX Autow>E Listener:INTERVAL 38 DAY.class ServiceTest extends TestCasepublic function testParseContactPhoneWithCountryCodeO: voidv saestorch>D Fielde25959990=701bY 0.20u.caszlBY sns count DESCu.sorcphonenuabenOpoorunitvMatcheaOpportunitvSvncStratesorassenAnnayhaskey ney.ohoneoononoehSthis->assentStringStartsWith@prefic '+44*. SparsedNunberf'phone')uD SoaSSeNThULCOPA-7057847es* fron ceans where 20 =1› ProspectsearchStrategService t raits©elientrest.php© DecorateActivity Test.P 2691polated, aositn tiesusaodpublic static function parseContactMobileProvider(): array3 %© FieldDefinitionsTest.phCCeTcwmaet amereturn24S4D© PayloadBuilderTest.phe 2495QueryBuilder Test.php© QueryHandler Test.php© QueryiteratorTest.phpQueryResultsiests.prp 2699C Semcetesconoemory hoo i ephone returns nutt=>wobtlephone s> "' nutur nuuu'no MobiilePhone key returns null' a> [ll null, nulll.7A18I© SyncBatchReosservict 26sRacASanicatast obo2412Va CachadCrm SanicsPhooewkoatabrav.hon nancerootcertohmepcou.em2718public function testParseContactMobilenstnenptyrhoneCorray ScnaData, Bstring ScountryCode, Pstring Sa7Changes 4 files, updatingE.env.local apc© JiminnyDebugCommand.php app/Console/CommandsT+ 0 +→0 Side-by-side viewer -@ ebbaab95 app/Services/PlaybackService.phpDo not ignore"pe loagina.ono contiaStean & Stracko>oe Activitye ->oetUser Or>aetteam OrUnversioned Files 9 file:inw.nikiochooE.enw.other aodnumonsto andl doloto sill connonteforeach (Splaylist "mediaSegnents') as Ssegment) ?Ka eanhccosea Reoorglestono escluni PolicosSsegment ""uri' = client cdn(Ssegnent ("uri'), Stean):© GreateMockAskJliminnvReoortRocu*tCommand.ohn.ano/Console/Commandsavicon.ico ouroEids.tyt aodSplayList ("EXT-X-PLAYLIST-TYPE' = 'VOD'APraw sol quem coaodSplayList (*EXT-X-ENDLIST' = true:@[EMAIL]/Console/Commands/Crm/HubsootM. WERHOOK FILTFRING IMPIFWENTATION mol anol& console (PROD) X# console fiaum8458185Y00=NCATCu,id. CASE WHEN unid = thouner id THEN • (oaner)* ELSE ** END) AS user_idena1aormen fo FRil soctal accnuntssasers u on u.1d = sa.soclable_1cParGTnCoontd n.teandu.tean_1d = 1117 and sa.provider = "hubspot":*EROM actMtes WHEOF Wund to binl18a2tetth-2147-1817.0144-40480695926801= Musd: " 70033459 VES+EROM eCtlWifleS.- Nh ĐNNo +o.- 01-92eLe0919501-Tisde# 89186100 M0*EROM eon confauratzons WHERE 3d = 1953%* FROM teans WHERE id = 1117:+Eoon ucene whene 3d= 30240.TO0У L7oe ind co moy toicy.uServiceTesteeendhles orchwerwicee+0.• testParsccontactPhoncw1thVal LaNurber = E.104 number parses corrcctly, ext is nul•testParseContactPhoncWithExtension - Number with ext. 42 correctly extracts the extensionoesVarsctonlac noneex Sirincalcolo ohirserttiiionkten chats derstunceolrran{nit(..•, 10, "*))•testrarcontac rnonemthcountint oor = Loch on numocrtcovoo to tutr Usine counthy cootanrsccontactloble•testParseContactMobileWithValidNumber - E.164 number returned [EMAIL]@chars=mowtchowhnocharsowstunc.eolstoine"estarsccontac tootewhcountrwcode =cukmoiowo t usina county cooOal -Necantalll+ < Code$ AdaptiveditterencePurtent vereionSteam = Strack->aetActvitylor>aerlser Oo>oeteaniobnumonstoand dolloto conmonteforeach (Splaylist 'mediaSegments' as Ssegment)Ssegnent ("uri') = client con(Ssegment("uri', Stean):SplayList("EXT-X-PLAYLIST-TYPE') = *VOD*:SplayList("EXT-X-ENDLIST') = true:N Wodtur Teams DRAR•R UTE-R AIA enano...
|
NULL
|
3964702547689064288
|
NULL
|
visual_change
|
ocr
|
NULL
|
rapstomViewNeweNNCCoocWindowFV faVsco.|s ~#12121 o rapstomViewNeweNNCCoocWindowFV faVsco.|s ~#12121 on JY-20963-fx-imnhe heloers.onp©ActivityControlier.php=custom.logaraveuesA SF fiminny@localhost)Usciko cooscrytriono Tesmuonsc) eienupnpA console [STAGING>E HubspolE InicaradonAdeTX Autow>E Listener:INTERVAL 38 DAY.class ServiceTest extends TestCasepublic function testParseContactPhoneWithCountryCodeO: voidv saestorch>D Fielde25959990=701bY 0.20u.caszlBY sns count DESCu.sorcphonenuabenOpoorunitvMatcheaOpportunitvSvncStratesorassenAnnayhaskey ney.ohoneoononoehSthis->assentStringStartsWith@prefic '+44*. SparsedNunberf'phone')uD SoaSSeNThULCOPA-7057847es* fron ceans where 20 =1› ProspectsearchStrategService t raits©elientrest.php© DecorateActivity Test.P 2691polated, aositn tiesusaodpublic static function parseContactMobileProvider(): array3 %© FieldDefinitionsTest.phCCeTcwmaet amereturn24S4D© PayloadBuilderTest.phe 2495QueryBuilder Test.php© QueryHandler Test.php© QueryiteratorTest.phpQueryResultsiests.prp 2699C Semcetesconoemory hoo i ephone returns nutt=>wobtlephone s> "' nutur nuuu'no MobiilePhone key returns null' a> [ll null, nulll.7A18I© SyncBatchReosservict 26sRacASanicatast obo2412Va CachadCrm SanicsPhooewkoatabrav.hon nancerootcertohmepcou.em2718public function testParseContactMobilenstnenptyrhoneCorray ScnaData, Bstring ScountryCode, Pstring Sa7Changes 4 files, updatingE.env.local apc© JiminnyDebugCommand.php app/Console/CommandsT+ 0 +→0 Side-by-side viewer -@ ebbaab95 app/Services/PlaybackService.phpDo not ignore"pe loagina.ono contiaStean & Stracko>oe Activitye ->oetUser Or>aetteam OrUnversioned Files 9 file:inw.nikiochooE.enw.other aodnumonsto andl doloto sill connonteforeach (Splaylist "mediaSegnents') as Ssegment) ?Ka eanhccosea Reoorglestono escluni PolicosSsegment ""uri' = client cdn(Ssegnent ("uri'), Stean):© GreateMockAskJliminnvReoortRocu*tCommand.ohn.ano/Console/Commandsavicon.ico ouroEids.tyt aodSplayList ("EXT-X-PLAYLIST-TYPE' = 'VOD'APraw sol quem coaodSplayList (*EXT-X-ENDLIST' = true:@[EMAIL]/Console/Commands/Crm/HubsootM. WERHOOK FILTFRING IMPIFWENTATION mol anol& console (PROD) X# console fiaum8458185Y00=NCATCu,id. CASE WHEN unid = thouner id THEN • (oaner)* ELSE ** END) AS user_idena1aormen fo FRil soctal accnuntssasers u on u.1d = sa.soclable_1cParGTnCoontd n.teandu.tean_1d = 1117 and sa.provider = "hubspot":*EROM actMtes WHEOF Wund to binl18a2tetth-2147-1817.0144-40480695926801= Musd: " 70033459 VES+EROM eCtlWifleS.- Nh ĐNNo +o.- 01-92eLe0919501-Tisde# 89186100 M0*EROM eon confauratzons WHERE 3d = 1953%* FROM teans WHERE id = 1117:+Eoon ucene whene 3d= 30240.TO0У L7oe ind co moy toicy.uServiceTesteeendhles orchwerwicee+0.• testParsccontactPhoncw1thVal LaNurber = E.104 number parses corrcctly, ext is nul•testParseContactPhoncWithExtension - Number with ext. 42 correctly extracts the extensionoesVarsctonlac noneex Sirincalcolo ohirserttiiionkten chats derstunceolrran{nit(..•, 10, "*))•testrarcontac rnonemthcountint oor = Loch on numocrtcovoo to tutr Usine counthy cootanrsccontactloble•testParseContactMobileWithValidNumber - E.164 number returned [EMAIL]@chars=mowtchowhnocharsowstunc.eolstoine"estarsccontac tootewhcountrwcode =cukmoiowo t usina county cooOal -Necantalll+ < Code$ AdaptiveditterencePurtent vereionSteam = Strack->aetActvitylor>aerlser Oo>oeteaniobnumonstoand dolloto conmonteforeach (Splaylist 'mediaSegments' as Ssegment)Ssegnent ("uri') = client con(Ssegment("uri', Stean):SplayList("EXT-X-PLAYLIST-TYPE') = *VOD*:SplayList("EXT-X-ENDLIST') = true:N Wodtur Teams DRAR•R UTE-R AIA enano...
|
85897
|
NULL
|
NULL
|
NULL
|
|
85899
|
2946
|
19
|
2026-05-28T13:27:05.815959+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974825815_m1.jpg...
|
iTerm2
|
NULL
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowHel iTerm2ShellEditViewSessionScriptsProfilesWindowHelp‹ $0 lhl-zshDOCKER881DEV (docker)₴82-zshscreenpipe"•84-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_1amp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8I 100%X5ec2-user@ip-10-30-129-...100% <78 • Thu 28 May 16:27:05181ec2-user@ip-10-30-140-…₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration"is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
NULL
|
-3801106396402634586
|
NULL
|
visual_change
|
ocr
|
NULL
|
iTerm2ShellEditViewSessionScriptsProfilesWindowHel iTerm2ShellEditViewSessionScriptsProfilesWindowHelp‹ $0 lhl-zshDOCKER881DEV (docker)₴82-zshscreenpipe"•84-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_1amp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8I 100%X5ec2-user@ip-10-30-129-...100% <78 • Thu 28 May 16:27:05181ec2-user@ip-10-30-140-…₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration"is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
85898
|
NULL
|
NULL
|
NULL
|
|
85898
|
2946
|
18
|
2026-05-28T13:27:03.723430+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974823723_m1.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121/changes
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Skip to content","depth":0,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Skip to content","depth":1,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Open menu","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Homepage (g then d)","depth":3,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-8142286967028504160
|
-2241707257167551257
|
click
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85897
|
2947
|
22
|
2026-05-28T13:27:03.620782+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974823620_m2.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121/changes
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.27055067,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.28172386,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.09757314,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.47206703,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.49561054,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5067837,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.62649643,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.63766956,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.66081405,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-3350944840147375387
|
-1953617618504190747
|
click
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85896
|
2947
|
21
|
2026-05-28T13:26:55.206161+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974815206_m2.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121/changes
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.27055067,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.28172386,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.09757314,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-5786192580378617073
|
-3429531797196771113
|
visual_change
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira...
|
85895
|
NULL
|
NULL
|
NULL
|
|
85895
|
2947
|
20
|
2026-05-28T13:26:52.907754+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974812907_m2.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121/changes
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.27055067,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.28172386,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.09757314,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-1863909645441244766
|
-9132355562878738233
|
click
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85894
|
2946
|
17
|
2026-05-28T13:26:52.765033+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974812765_m1.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
4987803367386134521
|
-1953617755943148315
|
click
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)...
|
85892
|
NULL
|
NULL
|
NULL
|
|
85893
|
2947
|
19
|
2026-05-28T13:26:52.082954+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974812082_m2.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.27055067,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.28172386,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.09757314,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.47206703,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.49561054,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
7081192352157737272
|
-1123829525675220745
|
visual_change
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny...
|
85891
|
NULL
|
NULL
|
NULL
|
|
85891
|
2947
|
18
|
2026-05-28T13:26:48.962028+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974808962_m2.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny
app
app
Search or jump to…
Type
/
to search
Chat with Copilot
Open Copilot…
Create new...
All issues(g then i)
All pull requests
All repositories
You have unread notifications(g then n)
Open user navigation menu
Repository navigation
Repository navigation
Code
Code
Pull requests (34)
Pull requests
(
34
)
Agents
Agents
Actions
Actions
Wiki
Wiki
Security and quality (12)
Security and quality
(
12
)
Insights
Insights
Settings
Settings
JY-20963 fix deleted object import #12121 Edit title
JY-20963 fix deleted object import
#
12121
Edit title
Checks pending
Checks pending
Code
Code
Open
LakyLak
LakyLak
wants to merge 7 commits into
master
master
from
JY-20963-fix-import-on-deleted-entity
JY-20963-fix-import-on-deleted-entity
Copy head branch name to clipboard
Lines changed: 483 additions & 52 deletions
Conversation (4)
Conversation
(
4
)
Commits (7)
Commits
(
7
)
Checks (2)
Checks
(
2
)
Files changed (3)
Files changed
(
3
)
Open
JY-20963 fix deleted object import #12121 LakyLak wants to merge 7 commits into master from JY-20963-fix-import-on-deleted-entity Copy head branch name to clipboard
JY-20963 fix deleted object import
JY-20963 fix deleted object import
#
12121
LakyLak
LakyLak
wants to merge 7 commits into
master
master
from
JY-20963-fix-import-on-deleted-entity
JY-20963-fix-import-on-deleted-entity
Copy head branch name to clipboard
Conversation
Conversation
@LakyLak
Show options
LakyLak commented last week •
LakyLak
LakyLak
commented
last week
last week
•
edited by nikolay-yankov
edited by nikolay-yankov
JIRA:
JIRA:
Changes:
Changes:
Fix import object if deleted
Add or remove reactions...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.27055067,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.28172386,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.09757314,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.47206703,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.49561054,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5067837,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.62649643,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.63766956,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.66081405,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Skip to content","depth":0,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Skip to content","depth":1,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Open menu","depth":4,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Homepage (g then d)","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"jiminny","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"jiminny","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"app","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"app","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search or jump to…","depth":3,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Type","depth":6,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"/","depth":6,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to search","depth":6,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Chat with Copilot","depth":4,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXMenuButton","text":"Open Copilot…","depth":3,"on_screen":false,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXMenuButton","text":"Create new...","depth":3,"on_screen":false,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"All issues(g then i)","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"All pull requests","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"All repositories","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"You have unread notifications(g then n)","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open user navigation menu","depth":3,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Repository navigation","depth":3,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Repository navigation","depth":4,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Code","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Code","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Pull requests (34)","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pull requests","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"34","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Agents","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Agents","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Actions","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Actions","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Wiki","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Wiki","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Security and quality (12)","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Security and quality","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"12","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Insights","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Insights","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Settings","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Settings","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"JY-20963 fix deleted object import #12121 Edit title","depth":7,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"JY-20963 fix deleted object import","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"#","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"12121","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Edit title","depth":8,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Checks pending","depth":7,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Checks pending","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXMenuButton","text":"Code","depth":7,"on_screen":false,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Code","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Open","depth":7,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"LakyLak","depth":9,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"LakyLak","depth":10,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"wants to merge 7 commits into","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"master","depth":9,"on_screen":false,"role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"master","depth":10,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"from","depth":10,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"JY-20963-fix-import-on-deleted-entity","depth":10,"on_screen":false,"role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963-fix-import-on-deleted-entity","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Copy head branch name to clipboard","depth":10,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Lines changed: 483 additions & 52 deletions","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Conversation (4)","depth":10,"on_screen":false,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Conversation","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"4","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Commits (7)","depth":10,"on_screen":false,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Commits","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"7","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Checks (2)","depth":10,"on_screen":false,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Checks","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"2","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Files changed (3)","depth":10,"on_screen":false,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Files changed","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Open","depth":8,"bounds":{"left":0.34840426,"top":0.0726257,"width":0.011968086,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"JY-20963 fix deleted object import #12121 LakyLak wants to merge 7 commits into master from JY-20963-fix-import-on-deleted-entity Copy head branch name to clipboard","depth":8,"bounds":{"left":0.36702126,"top":0.058260176,"width":0.20977394,"height":0.042298485},"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXLink","text":"JY-20963 fix deleted object import","depth":10,"bounds":{"left":0.36702126,"top":0.05865922,"width":0.07912234,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import","depth":11,"bounds":{"left":0.36702126,"top":0.06304868,"width":0.07912234,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"#","depth":10,"bounds":{"left":0.4488032,"top":0.06304868,"width":0.0028257978,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"12121","depth":10,"bounds":{"left":0.45162898,"top":0.06304868,"width":0.011801862,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"LakyLak","depth":12,"bounds":{"left":0.36702126,"top":0.08339984,"width":0.016123671,"height":0.011971269},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"LakyLak","depth":13,"bounds":{"left":0.36702126,"top":0.08339984,"width":0.016123671,"height":0.011971269},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"wants to merge 7 commits into","depth":12,"bounds":{"left":0.38447472,"top":0.08339984,"width":0.057845745,"height":0.011971269},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"master","depth":12,"bounds":{"left":0.44365028,"top":0.08180367,"width":0.018284574,"height":0.015163607},"on_screen":true,"role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"master","depth":13,"bounds":{"left":0.44564494,"top":0.083798885,"width":0.014295213,"height":0.011572227},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"from","depth":13,"bounds":{"left":0.4632646,"top":0.08339984,"width":0.00880984,"height":0.011971269},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"JY-20963-fix-import-on-deleted-entity","depth":13,"bounds":{"left":0.47340426,"top":0.08180367,"width":0.09275266,"height":0.015163607},"on_screen":true,"role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963-fix-import-on-deleted-entity","depth":14,"bounds":{"left":0.47539893,"top":0.083798885,"width":0.0887633,"height":0.011572227},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Copy head branch name to clipboard","depth":13,"bounds":{"left":0.5674867,"top":0.07821229,"width":0.00930851,"height":0.022346368},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation","depth":6,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation","depth":7,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"@LakyLak","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Show options","depth":9,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXHeading","text":"LakyLak commented last week •","depth":8,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXLink","text":"LakyLak","depth":10,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"LakyLak","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"commented","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"last week","depth":9,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"last week","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"•","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"edited by nikolay-yankov","depth":11,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"edited by nikolay-yankov","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"JIRA:","depth":10,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"JIRA:","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Changes:","depth":10,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Changes:","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Fix import object if deleted","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Add or remove reactions","depth":10,"on_screen":false,"help_text":"","role_description":"summary","subrole":"AXSummary","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-7219285235203896184
|
353391083335803984
|
visual_change
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny
app
app
Search or jump to…
Type
/
to search
Chat with Copilot
Open Copilot…
Create new...
All issues(g then i)
All pull requests
All repositories
You have unread notifications(g then n)
Open user navigation menu
Repository navigation
Repository navigation
Code
Code
Pull requests (34)
Pull requests
(
34
)
Agents
Agents
Actions
Actions
Wiki
Wiki
Security and quality (12)
Security and quality
(
12
)
Insights
Insights
Settings
Settings
JY-20963 fix deleted object import #12121 Edit title
JY-20963 fix deleted object import
#
12121
Edit title
Checks pending
Checks pending
Code
Code
Open
LakyLak
LakyLak
wants to merge 7 commits into
master
master
from
JY-20963-fix-import-on-deleted-entity
JY-20963-fix-import-on-deleted-entity
Copy head branch name to clipboard
Lines changed: 483 additions & 52 deletions
Conversation (4)
Conversation
(
4
)
Commits (7)
Commits
(
7
)
Checks (2)
Checks
(
2
)
Files changed (3)
Files changed
(
3
)
Open
JY-20963 fix deleted object import #12121 LakyLak wants to merge 7 commits into master from JY-20963-fix-import-on-deleted-entity Copy head branch name to clipboard
JY-20963 fix deleted object import
JY-20963 fix deleted object import
#
12121
LakyLak
LakyLak
wants to merge 7 commits into
master
master
from
JY-20963-fix-import-on-deleted-entity
JY-20963-fix-import-on-deleted-entity
Copy head branch name to clipboard
Conversation
Conversation
@LakyLak
Show options
LakyLak commented last week •
LakyLak
LakyLak
commented
last week
last week
•
edited by nikolay-yankov
edited by nikolay-yankov
JIRA:
JIRA:
Changes:
Changes:
Fix import object if deleted
Add or remove reactions...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85892
|
2946
|
16
|
2026-05-28T13:26:47.572775+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974807572_m1.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-3693216725545869923
|
4739222772041917682
|
click
|
hybrid
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
iTerm2ShellEditViewSessionScriptsProfilesWindowHelplah]-zshDOCKER• ₴1DEV (docker)₴82-zshscreenpipe"O &4-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash-c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8• 100%85ec2-user@ip-10-30-129-...100% <478 • Thu 28 May 16:26:47181ec2-user@ip-10-30-140-…₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85890
|
2947
|
17
|
2026-05-28T13:26:46.988545+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974806988_m2.jpg...
|
Slack
|
backend (Channel) - Jiminny Inc - 2 new items - Sl backend (Channel) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
engineering
general
happy_birthday
infosec_internal_all
infra-changes
infrastructure_dev
jbu-team-info
jiminny-bg
platform-team
platform-tickets
product_launches
random
releases
support
thank-yous
the_people_of_jiminny...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"bounds":{"left":0.5369016,"top":0.10055866,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5369016,"top":0.10055866,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.5405585,"top":0.10055866,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"bounds":{"left":0.5369016,"top":0.12290503,"width":0.01761968,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5369016,"top":0.12290503,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.5398936,"top":0.12290503,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"bounds":{"left":0.5369016,"top":0.1452514,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5369016,"top":0.1452514,"width":0.0039893617,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54089093,"top":0.1452514,"width":0.014295213,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"bounds":{"left":0.5369016,"top":0.16759777,"width":0.02925532,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5369016,"top":0.16759777,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.5405585,"top":0.16759777,"width":0.025265958,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"bounds":{"left":0.5884308,"top":0.16839585,"width":0.0026595744,"height":0.012769354},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"bounds":{"left":0.5369016,"top":0.18994413,"width":0.024268618,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5369016,"top":0.18994413,"width":0.0039893617,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54089093,"top":0.18994413,"width":0.020279255,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"bounds":{"left":0.5422208,"top":0.28411812,"width":0.044215426,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.28411812,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":25,"bounds":{"left":0.54521275,"top":0.28411812,"width":0.058843084,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"bounds":{"left":0.5422208,"top":0.3064645,"width":0.04454787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.3064645,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":18,"bounds":{"left":0.54521275,"top":0.3064645,"width":0.04155585,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"bounds":{"left":0.5422208,"top":0.35913807,"width":0.022273935,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.35913807,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54488033,"top":0.35913807,"width":0.019614361,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"bounds":{"left":0.5422208,"top":0.38148445,"width":0.012300532,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.38148445,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54488033,"top":0.38148445,"width":0.00930851,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":16,"bounds":{"left":0.5422208,"top":0.4038308,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4038308,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54521275,"top":0.4038308,"width":0.015292553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"bounds":{"left":0.5422208,"top":0.42617717,"width":0.010638298,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.42617717,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":3,"bounds":{"left":0.54521275,"top":0.42617717,"width":0.00731383,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"bounds":{"left":0.5422208,"top":0.44852355,"width":0.034574468,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.44852355,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54454786,"top":0.44852355,"width":0.032247342,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"bounds":{"left":0.5422208,"top":0.4708699,"width":0.025265958,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.4708699,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54521275,"top":0.4708699,"width":0.022273935,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"bounds":{"left":0.5422208,"top":0.49321628,"width":0.025930852,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.49321628,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":10,"bounds":{"left":0.54488033,"top":0.49321628,"width":0.022938829,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"bounds":{"left":0.5422208,"top":0.51556265,"width":0.016289894,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.51556265,"width":0.0026595744,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54488033,"top":0.51556265,"width":0.013297873,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"bounds":{"left":0.5422208,"top":0.53790903,"width":0.033909574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.53790903,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":13,"bounds":{"left":0.54521275,"top":0.53790903,"width":0.030917553,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"bounds":{"left":0.5422208,"top":0.5602554,"width":0.041888297,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5602554,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":19,"bounds":{"left":0.54355055,"top":0.5602554,"width":0.040226065,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"bounds":{"left":0.5422208,"top":0.5826017,"width":0.029587766,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.5826017,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.5826017,"width":0.02825798,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"bounds":{"left":0.5422208,"top":0.6049481,"width":0.040226065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6049481,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":17,"bounds":{"left":0.54355055,"top":0.6049481,"width":0.038896278,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"bounds":{"left":0.5422208,"top":0.6272945,"width":0.029920213,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6272945,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54355055,"top":0.6272945,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"bounds":{"left":0.5422208,"top":0.64964086,"width":0.023271276,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.64964086,"width":0.0013297872,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54355055,"top":0.64964086,"width":0.021609042,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"bounds":{"left":0.5422208,"top":0.67198724,"width":0.03158245,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.67198724,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":12,"bounds":{"left":0.54521275,"top":0.67198724,"width":0.028590426,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"bounds":{"left":0.5422208,"top":0.6943336,"width":0.034906916,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.6943336,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.6943336,"width":0.031914894,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"bounds":{"left":0.5422208,"top":0.71668,"width":0.03856383,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.71668,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":15,"bounds":{"left":0.54521275,"top":0.71668,"width":0.03557181,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"bounds":{"left":0.5422208,"top":0.7390263,"width":0.016954787,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7390263,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":5,"bounds":{"left":0.54421544,"top":0.7390263,"width":0.014960106,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"bounds":{"left":0.5422208,"top":0.7613727,"width":0.01761968,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.7613727,"width":0.0016622341,"height":0.014365523}},{"char_start":1,"char_count":7,"bounds":{"left":0.54388297,"top":0.7613727,"width":0.015957447,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"bounds":{"left":0.5422208,"top":0.78371906,"width":0.017287234,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.78371906,"width":0.0023271276,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.54454786,"top":0.78371906,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"bounds":{"left":0.5422208,"top":0.80606544,"width":0.024601065,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.80606544,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":9,"bounds":{"left":0.54421544,"top":0.80606544,"width":0.022606382,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"bounds":{"left":0.5422208,"top":0.8284118,"width":0.045212764,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5422208,"top":0.8284118,"width":0.0019946808,"height":0.014365523}},{"char_start":1,"char_count":20,"bounds":{"left":0.54421544,"top":0.8284118,"width":0.04720745,"height":0.014365523}}],"role_description":"text"}]...
|
-2514829430078690937
|
-5801313908410827038
|
idle
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
engineering
general
happy_birthday
infosec_internal_all
infra-changes
infrastructure_dev
jbu-team-info
jiminny-bg
platform-team
platform-tickets
product_launches
random
releases
support
thank-yous
the_people_of_jiminny
SlackEditViewGoHistoryWindowHelp= github.com/jiminny/app/pull/12121Pipelines - jiminny/appBE upgrade libraries(JY-20613) Allow owner's role to bText relayDeleted object errorJY-20963 fix deleted object i x• Login | SalesforceJiminalExceotionslEmailActivityrMlinbox 11224) - Iias kowstikSlimilZ (JY-20979) Resoive PHP 8.5.5 depSimionOatiwm Sorat 502-Ointarm Ttranscript ss issue8 Jiminny$ (SRD-6881) (On demand) Transe8 Sona Subramanian at 27/05/202€Ithrans Netceva at 27/05/2026, 168 Jmicay4 Now Thb(17 OpenJY-20963 fix deleted object import #12121LakyLak wants to meroe i comms mo bastertromT=40%03& LakyLak and others added 3 commits 2 days ago® Merge branch 'naster' into JY-20963-1ix-import-on-® JY-28963 code saellJY-20963 add code coveragesonarqubecloud Bot commented 2 days agcx Quality Gate failedFailed conditionsX 67.4% Coverace on New Code (recuired ≥ 70%See analysis details on SonarQube Cloud@ JY-20963 add tests coverageThis branch has not been deployedNo declovments.Review requiredAt least 1 approving review is required by reviewers with vSome checks haven't completed yet1 pending, 1 in progress, 1 expected, 8 successful checkscilcircleci: test Waitina for status to be reported = CircleCl i• & SonarCloud Code Analysis Expected - Waiting for status !• O build_accept _deploy Started 11 minutes ago — Workflow: b0) cilcircleci: build-backend e Yourtecte nassad on Cireled0 ci/circleci: build-frontend — Your tests passed on CirckActivityFilesLaterMoneiJiminnY ….( Unreads@ Threads6 HuddiesDrafts & sent© Directories01Ah External connections# Starred olatform-backend.8 platform-inner-team® Channels# ai-chapter# alerts# backend# bugs# confusion-dlinid# donut_time# engineering# general# happy_birthdayA infosec intemal all# infra-changest infrastructure del# ibu-team-info# jiminny-bg# olatform-team# platform-tickets# product launches# random# releases# support# thank-yous# the _people_of jimi.…^ Direct messagesllivana Netceve8. Vasil Vasilev Ef8. Stefka Stoyanova O88. Stoyan Tomov® Petko KashinskiTO0У L7Thu 28 May 16:26:46Q Describe what you are looking fort:.mhlckento32llechuin.erew.whrktheareas.wouhnremooranito.covar0nn09500.lestng.om8 1720$© Files& BookmarkeeDDor MeTiesKeearnins& PinsFriday, April 17th -llian Kyuchukov 10:17 AMI won't be able to join the Backend Meeting, as there is a prod issueThursday. Apnil 3othSaved for later • Due 21 days agoNikolay Ivanov 10:58 AMFor those using make cs-fix and getting annoved by how long it takes (since it scans the entire project), you can now use make cs-fix-branch. It will fix only the fles thatdiffer from master, and it runs in just a couple of secondsA43 21 GIlian Kyuchukov 9:32 AMtnsothih.com/iminav/ann//multxos0Since we started using/evaluating Claude Code, adding the dev rules for it.Reformated .windsurfrules to MD format and made a symlink to CLAUDE.md (so we can use one file for both, until we need to separate them)#W40sU naKe.enuoestreso2aiJIRA: JY-XXXXChanges:• Reformat .windsurfrules to MD format, copied the rules to CLAUDE.md as welljiminry/app May 7th Added by GitHubFriday, May 15th~llian Kyuchukov 910AMFor today's chapter we will take a look at tech days ideas and Claude Code usage/tips2reolice last moly 13 davs andToday~Vasil Vasilev # 3:44 PM@here guys, please do not deploy until further notice, I am scheduling logs of activities for reindexing, for the MCP, and a deploy will break the processVasil Vasilev # 3:52 PMAll activities are scheduled, releases are okay nowMessage #backend+ Aa...
|
85888
|
NULL
|
NULL
|
NULL
|
|
85889
|
2946
|
15
|
2026-05-28T13:26:45.822034+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974805822_m1.jpg...
|
Slack
|
backend (Channel) - Jiminny Inc - 2 new items - Sl backend (Channel) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
engineering
general
happy_birthday
infosec_internal_all
infra-changes
infrastructure_dev
jbu-team-info
jiminny-bg
platform-team
platform-tickets
product_launches
random
releases
support
thank-yous
the_people_of_jiminny
Iliyana Netseva
Vasil Vasilev
Stefka Stoyanova
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Messages
Messages
Untitled
Untitled
Files
Files
Bookmarks
Bookmarks
DEV ENV SETUP
DEV ENV SETUP
DataDog Metrics
DataDog Metrics
Learning
Learning
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Ilian Kyuchukov
Apr 7th at 9:51:07 AM
9:51 AM
https://www.facebook.com/watch/?v=933473732429611
https://www.facebook.com/watch/?v=933473732429611
facebook.com
10K views · 2.5K reactions | The 90’s were just different. | Laravel News
10K views · 2.5K reactions | The 90’s were just different. | Laravel News
The 90’s were just different.
1 reaction, react with smiling face with tear emoji
1
Add reaction…
Jump to date...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"product_launches","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"random","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"releases","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"support","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"thank-yous","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"the_people_of_jiminny","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Iliyana Netseva","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Vasil Vasilev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stefka Stoyanova","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Stoyan Tomov","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.06458333,"height":0.02},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Petko Kashinski","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.072222225,"height":0.02},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Galya Dimitrova","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.07361111,"height":0.0044444446},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Todor Stamatov","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.072222225,"height":0.0011111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Steliyan Georgiev","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.07986111,"height":0.0011111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Ves","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.016666668,"height":0.0011111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Mira","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.021527778,"height":0.0011111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Nikolay Yankov","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.06875,"height":0.0011111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"James Graham","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.06666667,"height":0.0011111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Lukas Kovalik","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.061805554,"height":0.0011111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"you","depth":15,"bounds":{"left":0.6354167,"top":0.0,"width":0.013194445,"height":0.0011111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Jira Cloud","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.045833334,"height":0.0011111111},"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Toast","depth":15,"bounds":{"left":0.56805557,"top":0.0,"width":0.024305556,"height":0.0011111111},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Messages","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Messages","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Untitled","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Untitled","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Bookmarks","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Bookmarks","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DEV ENV SETUP","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DEV ENV SETUP","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DataDog Metrics","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DataDog Metrics","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Learning","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Learning","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Pins","depth":9,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Pins","depth":11,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Add and Edit Channel Tabs","depth":9,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Canvas","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"List","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Folder","depth":9,"on_screen":true,"role_description":"text"},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"on_screen":false,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Ilian Kyuchukov","depth":15,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"","depth":15,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"Apr 7th at 9:51:07 AM","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"9:51 AM","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"https://www.facebook.com/watch/?v=933473732429611","depth":15,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"https://www.facebook.com/watch/?v=933473732429611","depth":16,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"facebook.com","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXLink","text":"10K views · 2.5K reactions | The 90’s were just different. | Laravel News","depth":17,"on_screen":false,"role_description":"link","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"10K views · 2.5K reactions | The 90’s were just different. | Laravel News","depth":18,"on_screen":false,"role_description":"text"},{"role":"AXStaticText","text":"The 90’s were just different.","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXCheckBox","text":"1 reaction, react with smiling face with tear emoji","depth":16,"on_screen":false,"role_description":"toggle button","subrole":"AXToggleButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"1","depth":17,"on_screen":false,"role_description":"text"},{"role":"AXButton","text":"Add reaction…","depth":16,"on_screen":false,"role_description":"button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXPopUpButton","text":"Jump to date","depth":14,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-152958194860719342
|
-4883974095888181526
|
idle
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
engineering
general
happy_birthday
infosec_internal_all
infra-changes
infrastructure_dev
jbu-team-info
jiminny-bg
platform-team
platform-tickets
product_launches
random
releases
support
thank-yous
the_people_of_jiminny
Iliyana Netseva
Vasil Vasilev
Stefka Stoyanova
Stoyan Tomov
Petko Kashinski
Galya Dimitrova
Todor Stamatov
Steliyan Georgiev
Ves
Mira
Nikolay Yankov
James Graham
Lukas Kovalik
you
Jira Cloud
Toast
Messages
Messages
Untitled
Untitled
Files
Files
Bookmarks
Bookmarks
DEV ENV SETUP
DEV ENV SETUP
DataDog Metrics
DataDog Metrics
Learning
Learning
Pins
Pins
Add and Edit Channel Tabs
Canvas
List
Folder
Jump to date
Ilian Kyuchukov
Apr 7th at 9:51:07 AM
9:51 AM
https://www.facebook.com/watch/?v=933473732429611
https://www.facebook.com/watch/?v=933473732429611
facebook.com
10K views · 2.5K reactions | The 90’s were just different. | Laravel News
10K views · 2.5K reactions | The 90’s were just different. | Laravel News
The 90’s were just different.
1 reaction, react with smiling face with tear emoji
1
Add reaction…
Jump to date
iTerm2ShellEditViewSessionScriptsProfilesWindowHelp-zshDOCKER© *1DEV (docker)₴82-zshscreenpipe"O ₴4-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash-c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8I 100%85ec2-user@ip-10-30-129-...100% <78 • Thu 28 May 16:26:45181ec2-user@ip-10-30-140-…₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
85887
|
NULL
|
NULL
|
NULL
|
|
85888
|
2947
|
16
|
2026-05-28T13:26:14.726180+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974774726_m2.jpg...
|
Slack
|
backend (Channel) - Jiminny Inc - 2 new items - Sl backend (Channel) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"bounds":{"left":0.5056516,"top":0.058260176,"width":0.011968086,"height":0.028731046},"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"bounds":{"left":0.50299203,"top":0.10055866,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"bounds":{"left":0.50664896,"top":0.13806863,"width":0.009973404,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"bounds":{"left":0.50299203,"top":0.15482841,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"bounds":{"left":0.50764626,"top":0.19233839,"width":0.007978723,"height":0.0103751},"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"bounds":{"left":0.50299203,"top":0.20909816,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.012965426,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5053192,"top":0.24660814,"width":0.0026595744,"height":0.011173184}},{"char_start":1,"char_count":7,"bounds":{"left":0.50764626,"top":0.24660814,"width":0.010638298,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"bounds":{"left":0.50299203,"top":0.26336792,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0076462766,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50797874,"top":0.3008779,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5099734,"top":0.3008779,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"bounds":{"left":0.50299203,"top":0.31763768,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.008643617,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.35514766,"width":0.0019946808,"height":0.011173184}},{"char_start":1,"char_count":4,"bounds":{"left":0.5093085,"top":0.35514766,"width":0.0066489363,"height":0.011173184}}],"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"bounds":{"left":0.50299203,"top":0.3719074,"width":0.017287234,"height":0.054269753},"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.008976064,"height":0.0103751},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.50731385,"top":0.4094174,"width":0.0033244682,"height":0.011173184}},{"char_start":1,"char_count":3,"bounds":{"left":0.5106383,"top":0.4094174,"width":0.0056515955,"height":0.011173184}}],"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"bounds":{"left":0.5369016,"top":0.10055866,"width":0.018284574,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5369016,"top":0.10055866,"width":0.003656915,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.5405585,"top":0.10055866,"width":0.01462766,"height":0.014365523}}],"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"bounds":{"left":0.5369016,"top":0.12290503,"width":0.01761968,"height":0.014365523},"on_screen":true,"lines":[{"char_start":0,"char_count":1,"bounds":{"left":0.5369016,"top":0.12290503,"width":0.0029920214,"height":0.014365523}},{"char_start":1,"char_count":6,"bounds":{"left":0.5398936,"top":0.12290503,"width":0.01462766,"height":0.014365523}}],"role_description":"text"}]...
|
8802802765596083200
|
-8129993884726510929
|
visual_change
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
SlackEditViewGoHistoryWindowHelp= github.com/jiminny/app/pull/12121Pipelines - jiminny/appBE upgrade libraries(JY-20613) Allow owner's role to bText relay]Deleted object errorJY-20963 fix deleted object i x• Login | SalesforceJiminalExceotionslEmailActivityrMlinbox 11224) - Iias kowstikSlimilZ (JY-20979) Resoive PHP 8.5.5 depSimionOatiwm Sorat 502-Ointarm Ttranscript ss issue8 Jiminny$ (SRD-6881) (On demand) Transe8 Sona Subramanian at 27/05/202€Ithrans Netceva at 27/05/2026, 168 Jmicay4 Now Thb(17 OpenJY-20963 fix deleted object import #12121LakyLak wants to meroe i comms mo bastertromT=40%03& LakyLak and others added 3 commits 2 days ago® Merge branch 'naster' into JY-20963-1ix-import-on-® JY-28963 code saellJY-20963 add code coveragesonarqubecloud Bot commented 2 days agcx Quality Gate failedFailed conditionsX 67.4% Coverace on New Code (recuired ≥ 70%See analysis details on SonarQube Cloud@ JY-20963 add tests coverageThis branch has not been deployedNo declovments.Review requiredAt least 1 approving review is required by reviewers with vSome checks haven't completed yet1 pending, 1 in progress, 1 expected, 8 successful checkscilcircleci: test Waitina for status to be reported = CircleCl i• & SonarCloud Code Analysis Expected - Waiting for status !• O build_accept _deploy Started 11 minutes ago — Workflow: b→o cilcircleci: build-backend e Yourtecte nassad on Cireled0 ci/circleci: build-frontend — Your tests passed on CirckHoeActivityFilesLaterMoreiJiminnY ….( Unreads@ Threads6 HuddlesDrafts & sent© Directories01Ah External connections# Starred8 platform-backend-….8 platform-inner-team© Channels# ai-chapter# alerts# backend# bugs# confusion-dlinid# donut_time# engineering# general# happy_birthdayA infosec intemal all# infra-changest infrastructure del# ibu-team-info# jiminny-bg# olatform-team# platform-tickets# product launches# random# releases# support# thank-yous# the _people_of jimi.…^ Direct messagesllivana Netceve8. Vasil Vasilev Ef8. Stefka Stoyanova O88. Stoyan Tomov® Petko KashinskiTO0У L7Inu cowoy 1o.2o.1-Q Describe what you are looking fort:.mhlckento32llechuin.erew.whrktheareas.wouhnremooranito.covar0nn09500.lestng.om8 1720$© Files& BookmarkeDDor MeTiesKeearnins& PinsFriday, April 17th -llian Kyuchukov 10:17 AMIwon't be able to join the Backend Meeting, as there is a prod issueThursday. Apnil 3othSaved for later • Due 21 days agoNikolay Ivanoy 10:58 AMFor those using make cs-fix and getting annoved by how long it takes (since it scans the entire project), you can now use make cs-fix-branch. It will fix only the fles thatdiffer from master, and it runs in just a couple of secondsA43 21 GIlian Kyuchukov 9:32 AMtnsothih.com/iminav/ann//multxos0Since we started using/evaluating Claude Code, adding the dev rules for it.Reformated .windsurfrules to MD format and made a symlink to CLAUDE.md (so we can use one file for both, until we need to separate them)#450 nhKe.dnudescrec 2alJIRA: JY-XXXXChanges:• Reformat .windsurfrules to MD format, copied the rules to CLAUDE.md as welljiminry/app May 7th Added by GitHubFriday, May 15th~llian Kyuchukov 910AMFor today's chapter we will take a look at tech days ideas and Claude Code usage/tips2reolice Last moly 13 davs andToday~Vasil Vasilev # 3:44 PM@here guys, please do not deploy until further notice, I am scheduling logs of activities for reindexing, for the MCP, and a deploy will break the processVasil Vasilev # 3:52 PMAll activities are scheduled, releases are okay nowMessage #backend- Aa...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85887
|
2946
|
14
|
2026-05-28T13:26:13.085282+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974773085_m1.jpg...
|
Slack
|
backend (Channel) - Jiminny Inc - 2 new items - Sl backend (Channel) - Jiminny Inc - 2 new items - Slack...
|
1
|
NULL
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
engineering
general
happy_birthday
infosec_internal_all
infra-changes
infrastructure_dev
jbu-team-info
jiminny-bg
platform-team
platform-tickets...
|
[{"role":"AXPopUpButton","text [{"role":"AXPopUpButton","text":"Switch workspaces… (Jiminny Inc) Has new messages","depth":6,"on_screen":true,"role_description":"pop-up button","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"Home","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true,"is_expanded":false},{"role":"AXStaticText","text":"Home","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"DMs","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"DMs","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Activity","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Activity","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Files","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Files","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"Later","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Later","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXRadioButton","text":"More…","depth":6,"on_screen":true,"role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"More","depth":8,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Unreads","depth":13,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Threads","depth":13,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Huddles","depth":13,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Drafts & sent","depth":13,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"1","depth":13,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"Directories","depth":13,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-backend-engineers","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-inner-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"ai-chapter","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"alerts","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"backend","depth":16,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"bugs","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"confusion-clinic","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"donut_time","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"engineering","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"general","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"happy_birthday","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infosec_internal_all","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infra-changes","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"infrastructure_dev","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jbu-team-info","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"jiminny-bg","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-team","depth":15,"on_screen":true,"role_description":"text"},{"role":"AXStaticText","text":"platform-tickets","depth":15,"on_screen":true,"role_description":"text"}]...
|
2053464608967851550
|
-5812854107580186889
|
visual_change
|
hybrid
|
NULL
|
Switch workspaces… (Jiminny Inc) Has new messages
Switch workspaces… (Jiminny Inc) Has new messages
Home
Home
DMs
DMs
Activity
Activity
Files
Files
Later
Later
More…
More
Unreads
Threads
Huddles
Drafts & sent
1
Directories
platform-backend-engineers
platform-inner-team
ai-chapter
alerts
backend
bugs
confusion-clinic
donut_time
engineering
general
happy_birthday
infosec_internal_all
infra-changes
infrastructure_dev
jbu-team-info
jiminny-bg
platform-team
platform-tickets
iTerm2ShellEditViewSessionScriptsProfilesWindowHelplah]-zshDOCKER₴81DEV (docker)₴82-zshscreenpipe"84-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash-c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8I 100%85ec2-user@ip-10-30-129-...100% <478• Thu 28 May 16:26:12181ec2-user@ip-10-30-140-…₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85886
|
2946
|
13
|
2026-05-28T13:26:09.985345+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974769985_m1.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny
app
app
Search or jump to…
Type
/
to search
Chat with Copilot
Open Copilot…
Create new...
All issues(g then i)
All pull requests
All repositories
You have unread notifications(g then n)
Open user navigation menu
Repository navigation
Repository navigation
Code
Code
Pull requests (34)
Pull requests
(
34
)
Agents
Agents
Actions
Actions
Wiki
Wiki
Security and quality (12)
Security and quality
(
12
)
Insights
Insights
Settings
Settings
JY-20963 fix deleted object import #12121 Edit title
JY-20963 fix deleted object import
#
12121
Edit title
Checks pending
Checks pending
Code
Code
Open
LakyLak
LakyLak
wants to merge 7 commits into
master
master
from
JY-20963-fix-import-on-deleted-entity
JY-20963-fix-import-on-deleted-entity
Copy head branch name to clipboard
Lines changed: 483 additions & 52 deletions
Conversation (4)
Conversation
(
4
)
Commits (7)
Commits
(
7
)
Checks (2)
Checks
(
2
)
Files changed (3)
Files changed
(
3
)
Open
JY-20963 fix deleted object import #12121 LakyLak wants to merge 7 commits into master from JY-20963-fix-import-on-deleted-entity Copy head branch name to clipboard
JY-20963 fix deleted object import
JY-20963 fix deleted object import
#
12121
LakyLak
LakyLak
wants to merge 7 commits into
master
master
from
JY-20963-fix-import-on-deleted-entity
JY-20963-fix-import-on-deleted-entity
Copy head branch name to clipboard
Conversation
Conversation
@LakyLak
Show options
LakyLak commented last week •
LakyLak
LakyLak
commented
last week
last week
•
edited by nikolay-yankov
edited by nikolay-yankov
JIRA:
JIRA:
Changes:
Changes:
Fix import object if deleted
Add or remove reactions
LakyLak
LakyLak
and others
added
2
commits
last week
last week
@LakyLak
JY-20963
JY-20963
fix deleted object import
fix deleted object import
11 / 12 checks OK
0c151a1
0c151a1
@nikolay-yankov
Merge branch 'master' into
Merge branch 'master' into
JY-20963
JY-20963
-fix-import-on-deleted-entity
-fix-import-on-deleted-entity
Verified
Verified
11 / 12 checks OK...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Skip to content","depth":0,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Skip to content","depth":1,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Open menu","depth":4,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Homepage (g then d)","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"jiminny","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"jiminny","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"app","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"app","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search or jump to…","depth":3,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Type","depth":6,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"/","depth":6,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to search","depth":6,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Chat with Copilot","depth":4,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXMenuButton","text":"Open Copilot…","depth":3,"on_screen":false,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXMenuButton","text":"Create new...","depth":3,"on_screen":false,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"All issues(g then i)","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"All pull requests","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"All repositories","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"You have unread notifications(g then n)","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open user navigation menu","depth":3,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Repository navigation","depth":3,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Repository navigation","depth":4,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Code","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Code","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Pull requests (34)","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pull requests","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"34","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Agents","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Agents","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Actions","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Actions","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Wiki","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Wiki","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Security and quality (12)","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Security and quality","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"12","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Insights","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Insights","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Settings","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Settings","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"JY-20963 fix deleted object import #12121 Edit title","depth":7,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"JY-20963 fix deleted object import","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"#","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"12121","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Edit title","depth":8,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Checks pending","depth":7,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Checks pending","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXMenuButton","text":"Code","depth":7,"on_screen":false,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Code","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Open","depth":7,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"LakyLak","depth":9,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"LakyLak","depth":10,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"wants to merge 7 commits into","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"master","depth":9,"on_screen":false,"role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"master","depth":10,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"from","depth":10,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"JY-20963-fix-import-on-deleted-entity","depth":10,"on_screen":false,"role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963-fix-import-on-deleted-entity","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Copy head branch name to clipboard","depth":10,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Lines changed: 483 additions & 52 deletions","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Conversation (4)","depth":10,"on_screen":false,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Conversation","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"4","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Commits (7)","depth":10,"on_screen":false,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Commits","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"7","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Checks (2)","depth":10,"on_screen":false,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Checks","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"2","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Files changed (3)","depth":10,"on_screen":false,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Files changed","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"3","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Open","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"JY-20963 fix deleted object import #12121 LakyLak wants to merge 7 commits into master from JY-20963-fix-import-on-deleted-entity Copy head branch name to clipboard","depth":8,"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXLink","text":"JY-20963 fix deleted object import","depth":10,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963 fix deleted object import","depth":11,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"#","depth":10,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"12121","depth":10,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"LakyLak","depth":12,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"LakyLak","depth":13,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"wants to merge 7 commits into","depth":12,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"master","depth":12,"on_screen":true,"role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"master","depth":13,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"from","depth":13,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"JY-20963-fix-import-on-deleted-entity","depth":13,"on_screen":true,"role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963-fix-import-on-deleted-entity","depth":14,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Copy head branch name to clipboard","depth":13,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Conversation","depth":6,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Conversation","depth":7,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"@LakyLak","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Show options","depth":9,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXHeading","text":"LakyLak commented last week •","depth":8,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXLink","text":"LakyLak","depth":10,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"LakyLak","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"commented","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"last week","depth":9,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"last week","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"•","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"edited by nikolay-yankov","depth":11,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"edited by nikolay-yankov","depth":13,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"JIRA:","depth":10,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"JIRA:","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"Changes:","depth":10,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Changes:","depth":11,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Fix import object if deleted","depth":12,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Add or remove reactions","depth":10,"on_screen":false,"help_text":"","role_description":"summary","subrole":"AXSummary","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"LakyLak","depth":8,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"LakyLak","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"and others","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"added","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"2","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"commits","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"last week","depth":8,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"last week","depth":10,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"@LakyLak","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"JY-20963","depth":8,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"fix deleted object import","depth":8,"on_screen":false,"help_text":"JY-20963 fix deleted object import","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"fix deleted object import","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"11 / 12 checks OK","depth":8,"on_screen":false,"help_text":"","role_description":"summary","subrole":"AXSummary","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"0c151a1","depth":8,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"0c151a1","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"@nikolay-yankov","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Merge branch 'master' into","depth":8,"on_screen":false,"help_text":"Merge branch 'master' into JY-20963-fix-import-on-deleted-entity","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Merge branch 'master' into","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"JY-20963","depth":8,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"-fix-import-on-deleted-entity","depth":8,"on_screen":false,"help_text":"Merge branch 'master' into JY-20963-fix-import-on-deleted-entity","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"-fix-import-on-deleted-entity","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Verified","depth":7,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Verified","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"11 / 12 checks OK","depth":8,"on_screen":false,"help_text":"","role_description":"summary","subrole":"AXSummary","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false}]...
|
-998728886961377367
|
-8869983143952260016
|
visual_change
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny
app
app
Search or jump to…
Type
/
to search
Chat with Copilot
Open Copilot…
Create new...
All issues(g then i)
All pull requests
All repositories
You have unread notifications(g then n)
Open user navigation menu
Repository navigation
Repository navigation
Code
Code
Pull requests (34)
Pull requests
(
34
)
Agents
Agents
Actions
Actions
Wiki
Wiki
Security and quality (12)
Security and quality
(
12
)
Insights
Insights
Settings
Settings
JY-20963 fix deleted object import #12121 Edit title
JY-20963 fix deleted object import
#
12121
Edit title
Checks pending
Checks pending
Code
Code
Open
LakyLak
LakyLak
wants to merge 7 commits into
master
master
from
JY-20963-fix-import-on-deleted-entity
JY-20963-fix-import-on-deleted-entity
Copy head branch name to clipboard
Lines changed: 483 additions & 52 deletions
Conversation (4)
Conversation
(
4
)
Commits (7)
Commits
(
7
)
Checks (2)
Checks
(
2
)
Files changed (3)
Files changed
(
3
)
Open
JY-20963 fix deleted object import #12121 LakyLak wants to merge 7 commits into master from JY-20963-fix-import-on-deleted-entity Copy head branch name to clipboard
JY-20963 fix deleted object import
JY-20963 fix deleted object import
#
12121
LakyLak
LakyLak
wants to merge 7 commits into
master
master
from
JY-20963-fix-import-on-deleted-entity
JY-20963-fix-import-on-deleted-entity
Copy head branch name to clipboard
Conversation
Conversation
@LakyLak
Show options
LakyLak commented last week •
LakyLak
LakyLak
commented
last week
last week
•
edited by nikolay-yankov
edited by nikolay-yankov
JIRA:
JIRA:
Changes:
Changes:
Fix import object if deleted
Add or remove reactions
LakyLak
LakyLak
and others
added
2
commits
last week
last week
@LakyLak
JY-20963
JY-20963
fix deleted object import
fix deleted object import
11 / 12 checks OK
0c151a1
0c151a1
@nikolay-yankov
Merge branch 'master' into
Merge branch 'master' into
JY-20963
JY-20963
-fix-import-on-deleted-entity
-fix-import-on-deleted-entity
Verified
Verified
11 / 12 checks OK...
|
85882
|
NULL
|
NULL
|
NULL
|
|
85885
|
2947
|
15
|
2026-05-28T13:25:56.380900+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974756380_m2.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny
app
app
Search or jump to…
Type
/
to search
Chat with Copilot
Open Copilot…
Create new...
All issues(g then i)
All pull requests
All repositories
You have unread notifications(g then n)
Open user navigation menu
Repository navigation
Repository navigation
Code
Code
Pull requests (34)
Pull requests
(
34
)
Agents
Agents
Actions
Actions
Wiki
Wiki
Security and quality (12)
Security and quality
(
12
)
Insights
Insights
Settings
Settings
JY-20963 fix deleted object import #12121 Edit title
JY-20963 fix deleted object import
#
12121
Edit title
Checks pending
Checks pending
Code
Code
Open...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.27055067,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.28172386,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.09757314,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.47206703,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.49561054,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5067837,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.62649643,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.63766956,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.66081405,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Skip to content","depth":0,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Skip to content","depth":1,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Open menu","depth":4,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Homepage (g then d)","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"jiminny","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"jiminny","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"app","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"app","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search or jump to…","depth":3,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Type","depth":6,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"/","depth":6,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to search","depth":6,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Chat with Copilot","depth":4,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXMenuButton","text":"Open Copilot…","depth":3,"on_screen":false,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXMenuButton","text":"Create new...","depth":3,"on_screen":false,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"All issues(g then i)","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"All pull requests","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"All repositories","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"You have unread notifications(g then n)","depth":3,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open user navigation menu","depth":3,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Repository navigation","depth":3,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Repository navigation","depth":4,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Code","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Code","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Pull requests (34)","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pull requests","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"34","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Agents","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Agents","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Actions","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Actions","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Wiki","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Wiki","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Security and quality (12)","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Security and quality","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"12","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Insights","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Insights","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Settings","depth":6,"on_screen":false,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Settings","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"JY-20963 fix deleted object import #12121 Edit title","depth":7,"on_screen":false,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"JY-20963 fix deleted object import","depth":8,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"#","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"12121","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Edit title","depth":8,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Checks pending","depth":7,"on_screen":false,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Checks pending","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXMenuButton","text":"Code","depth":7,"on_screen":false,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Code","depth":9,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Open","depth":7,"on_screen":false,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-4562551706377760675
|
-6852408250732841369
|
visual_change
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny
app
app
Search or jump to…
Type
/
to search
Chat with Copilot
Open Copilot…
Create new...
All issues(g then i)
All pull requests
All repositories
You have unread notifications(g then n)
Open user navigation menu
Repository navigation
Repository navigation
Code
Code
Pull requests (34)
Pull requests
(
34
)
Agents
Agents
Actions
Actions
Wiki
Wiki
Security and quality (12)
Security and quality
(
12
)
Insights
Insights
Settings
Settings
JY-20963 fix deleted object import #12121 Edit title
JY-20963 fix deleted object import
#
12121
Edit title
Checks pending
Checks pending
Code
Code
Open...
|
85884
|
NULL
|
NULL
|
NULL
|
|
85884
|
2947
|
14
|
2026-05-28T13:25:53.200855+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974753200_m2.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.27055067,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.28172386,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.09757314,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.47206703,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.49561054,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5067837,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.62649643,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.63766956,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.66081405,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
7341521229306248742
|
-1953617618504190747
|
visual_change
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85883
|
2947
|
13
|
2026-05-28T13:25:49.184035+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974749184_m2.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.27055067,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.28172386,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.09757314,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.47206703,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.49561054,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5067837,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.62649643,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.63766956,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.66081405,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Skip to content","depth":0,"bounds":{"left":0.07962101,"top":0.0518755,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Skip to content","depth":1,"bounds":{"left":0.07962101,"top":0.05347167,"width":0.0029920214,"height":0.21468475},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Open menu","depth":4,"bounds":{"left":0.08494016,"top":0.06464485,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Homepage (g then d)","depth":3,"bounds":{"left":0.099567816,"top":0.06464485,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"jiminny","depth":6,"bounds":{"left":0.112865694,"top":0.06464485,"width":0.018949468,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"jiminny","depth":8,"bounds":{"left":0.11486037,"top":0.07063048,"width":0.014960106,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-1021949118404325854
|
-2241707257167551257
|
idle
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny...
|
85881
|
NULL
|
NULL
|
NULL
|
|
85882
|
2946
|
12
|
2026-05-28T13:25:49.018900+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974749018_m1.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Skip to content","depth":0,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Skip to content","depth":1,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-1523903900926938682
|
-2241847994655906585
|
idle
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85881
|
2947
|
12
|
2026-05-28T13:25:18.668587+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974718668_m2.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.27055067,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.28172386,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.09757314,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.47206703,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.49561054,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
7081192352157737272
|
-1123829525675220745
|
idle
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85880
|
2946
|
11
|
2026-05-28T13:25:18.413303+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974718413_m1.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny
app
app
Search or jump to…
Type
/
to search
Chat with Copilot
Open Copilot…
Create new...
All issues(g then i)
All pull requests
All repositories
You have unread notifications(g then n)
Open user navigation menu
Repository navigation
Repository navigation
Code
Code
Pull requests (34)
Pull requests
(
34
)...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Skip to content","depth":0,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Skip to content","depth":1,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Open menu","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Homepage (g then d)","depth":3,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"jiminny","depth":6,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"jiminny","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"app","depth":6,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"app","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search or jump to…","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Type","depth":6,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"/","depth":6,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to search","depth":6,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Chat with Copilot","depth":4,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXMenuButton","text":"Open Copilot…","depth":3,"on_screen":true,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXMenuButton","text":"Create new...","depth":3,"on_screen":true,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"All issues(g then i)","depth":3,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"All pull requests","depth":3,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"All repositories","depth":3,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"You have unread notifications(g then n)","depth":3,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open user navigation menu","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Repository navigation","depth":3,"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Repository navigation","depth":4,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Code","depth":6,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Code","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Pull requests (34)","depth":6,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pull requests","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"34","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-7157395746843511394
|
-6852267375801207069
|
idle
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny
app
app
Search or jump to…
Type
/
to search
Chat with Copilot
Open Copilot…
Create new...
All issues(g then i)
All pull requests
All repositories
You have unread notifications(g then n)
Open user navigation menu
Repository navigation
Repository navigation
Code
Code
Pull requests (34)
Pull requests
(
34
)...
|
85878
|
NULL
|
NULL
|
NULL
|
|
85879
|
2947
|
11
|
2026-05-28T13:24:48.062571+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974688062_m2.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny
app
app
Search or jump to…
Type
/
to search
Chat with Copilot
Open Copilot…
Create new...
All issues(g then i)
All pull requests
All repositories
You have no unread notifications(g then n)
Open user navigation menu
Repository navigation
Repository navigation
Code
Code
Pull requests (34)
Pull requests
(
34
)
Agents
Agents
Actions
Actions
Wiki
Wiki
Security and quality (12)
Security and quality
(
12
)
Insights
Insights
Settings
Settings
JY-20963 fix deleted object import #12121 Edit title
JY-20963 fix deleted object import
#
12121
Edit title
View statusView status
Loading
Loading merge status
Code
Code
Open
LakyLak
LakyLak
wants to merge 7 commits into
master
master
from
JY-20963-fix-import-on-deleted-entity
JY-20963-fix-import-on-deleted-entity
Copy head branch name to clipboard
Lines changed: 483 additions & 52 deletions
Conversation (4)
Conversation
(
4
)
Commits (7)
Commits
(
7
)
Checks (2)
Checks...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.27055067,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.28172386,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.09757314,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.47206703,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.49561054,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5067837,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.62649643,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.63766956,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.66081405,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Skip to content","depth":0,"bounds":{"left":0.07962101,"top":0.0518755,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Skip to content","depth":1,"bounds":{"left":0.07962101,"top":0.05347167,"width":0.0029920214,"height":0.21468475},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Open menu","depth":4,"bounds":{"left":0.08494016,"top":0.06464485,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Homepage (g then d)","depth":3,"bounds":{"left":0.099567816,"top":0.06464485,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"jiminny","depth":6,"bounds":{"left":0.112865694,"top":0.06464485,"width":0.018949468,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"jiminny","depth":8,"bounds":{"left":0.11486037,"top":0.07063048,"width":0.014960106,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"app","depth":6,"bounds":{"left":0.13680187,"top":0.06464485,"width":0.017785905,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"app","depth":8,"bounds":{"left":0.13879654,"top":0.07063048,"width":0.008477394,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search or jump to…","depth":3,"bounds":{"left":0.81698805,"top":0.06464485,"width":0.06565824,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Type","depth":6,"bounds":{"left":0.82928854,"top":0.07063048,"width":0.011801862,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"/","depth":6,"bounds":{"left":0.8424202,"top":0.07222666,"width":0.002493351,"height":0.011572227},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to search","depth":6,"bounds":{"left":0.84640956,"top":0.07063048,"width":0.021276595,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Chat with Copilot","depth":4,"bounds":{"left":0.88464093,"top":0.06464485,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXMenuButton","text":"Open Copilot…","depth":3,"bounds":{"left":0.8949468,"top":0.06464485,"width":0.008643617,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXMenuButton","text":"Create new...","depth":3,"bounds":{"left":0.9115692,"top":0.06464485,"width":0.01662234,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"All issues(g then i)","depth":3,"bounds":{"left":0.93085104,"top":0.06464485,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"All pull requests","depth":3,"bounds":{"left":0.94414896,"top":0.06464485,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"All repositories","depth":3,"bounds":{"left":0.9574468,"top":0.06464485,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"You have no unread notifications(g then n)","depth":3,"bounds":{"left":0.97074467,"top":0.06464485,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open user navigation menu","depth":3,"bounds":{"left":0.9840425,"top":0.06464485,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Repository navigation","depth":3,"bounds":{"left":0.079288565,"top":0.051077414,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Repository navigation","depth":4,"bounds":{"left":0.079288565,"top":0.05387071,"width":0.0787899,"height":0.023144454},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Code","depth":6,"bounds":{"left":0.08494016,"top":0.09936153,"width":0.025099734,"height":0.026336791},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Code","depth":8,"bounds":{"left":0.095744684,"top":0.10574621,"width":0.011469414,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Pull requests (34)","depth":6,"bounds":{"left":0.11269947,"top":0.09936153,"width":0.05518617,"height":0.026336791},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pull requests","depth":8,"bounds":{"left":0.12333777,"top":0.10574621,"width":0.02925532,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":8,"bounds":{"left":0.15525267,"top":0.113727055,"width":0.0029920214,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"34","depth":8,"bounds":{"left":0.15824468,"top":0.113727055,"width":0.005817819,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":8,"bounds":{"left":0.1640625,"top":0.113727055,"width":0.0016622341,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Agents","depth":6,"bounds":{"left":0.1705452,"top":0.09936153,"width":0.029089095,"height":0.026336791},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Agents","depth":8,"bounds":{"left":0.18151596,"top":0.10574621,"width":0.01512633,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Actions","depth":6,"bounds":{"left":0.20229389,"top":0.09936153,"width":0.03025266,"height":0.026336791},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Actions","depth":8,"bounds":{"left":0.21343085,"top":0.10574621,"width":0.015957447,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Wiki","depth":6,"bounds":{"left":0.23520611,"top":0.09936153,"width":0.022938829,"height":0.026336791},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Wiki","depth":8,"bounds":{"left":0.24617687,"top":0.10574621,"width":0.009142287,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Security and quality (12)","depth":6,"bounds":{"left":0.26080453,"top":0.09936153,"width":0.069980055,"height":0.026336791},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Security and quality","depth":8,"bounds":{"left":0.27260637,"top":0.10574621,"width":0.04255319,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":8,"bounds":{"left":0.31898272,"top":0.113727055,"width":0.0029920214,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"12","depth":8,"bounds":{"left":0.32197472,"top":0.113727055,"width":0.0048204786,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":8,"bounds":{"left":0.32679522,"top":0.113727055,"width":0.0018284575,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Insights","depth":6,"bounds":{"left":0.33344415,"top":0.09936153,"width":0.03125,"height":0.026336791},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Insights","depth":8,"bounds":{"left":0.34458113,"top":0.10574621,"width":0.016788565,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Settings","depth":6,"bounds":{"left":0.36735374,"top":0.09936153,"width":0.032081116,"height":0.026336791},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Settings","depth":8,"bounds":{"left":0.3784907,"top":0.10574621,"width":0.017785905,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"JY-20963 fix deleted object import #12121 Edit title","depth":7,"bounds":{"left":0.33776596,"top":0.15123703,"width":0.20777926,"height":0.031923383},"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"JY-20963 fix deleted object import","depth":8,"bounds":{"left":0.33776596,"top":0.15203512,"width":0.16057181,"height":0.030327214},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"#","depth":9,"bounds":{"left":0.50099736,"top":0.15203512,"width":0.006482713,"height":0.030327214},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"12121","depth":9,"bounds":{"left":0.50748,"top":0.15203512,"width":0.026097074,"height":0.030327214},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Edit title","depth":8,"bounds":{"left":0.5349069,"top":0.15442938,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"View statusView status","depth":7,"bounds":{"left":0.6761968,"top":0.15762171,"width":0.034906916,"height":0.025538707},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":false,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Loading","depth":9,"bounds":{"left":0.6909907,"top":0.1660016,"width":0.017453458,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Loading merge status","depth":9,"bounds":{"left":0.6761968,"top":0.18635276,"width":0.06632314,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXMenuButton","text":"Code","depth":7,"bounds":{"left":0.7137633,"top":0.15762171,"width":0.02825798,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Code","depth":9,"bounds":{"left":0.7180851,"top":0.16360734,"width":0.011635638,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Open","depth":7,"bounds":{"left":0.34840426,"top":0.19553073,"width":0.011968086,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"LakyLak","depth":9,"bounds":{"left":0.36702126,"top":0.19233839,"width":0.018450798,"height":0.016759777},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"LakyLak","depth":10,"bounds":{"left":0.36702126,"top":0.19393456,"width":0.018450798,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"wants to merge 7 commits into","depth":9,"bounds":{"left":0.38680187,"top":0.19393456,"width":0.06632314,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"master","depth":9,"bounds":{"left":0.45445478,"top":0.19193934,"width":0.018284574,"height":0.017557861},"on_screen":true,"role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"master","depth":10,"bounds":{"left":0.45644948,"top":0.19513169,"width":0.014295213,"height":0.011572227},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"from","depth":10,"bounds":{"left":0.47406915,"top":0.19393456,"width":0.009973404,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"JY-20963-fix-import-on-deleted-entity","depth":10,"bounds":{"left":0.48537233,"top":0.19193934,"width":0.09275266,"height":0.017557861},"on_screen":true,"role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963-fix-import-on-deleted-entity","depth":11,"bounds":{"left":0.48736703,"top":0.19513169,"width":0.0887633,"height":0.011572227},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Copy head branch name to clipboard","depth":10,"bounds":{"left":0.5794548,"top":0.1895451,"width":0.00930851,"height":0.022346368},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Lines changed: 483 additions & 52 deletions","depth":8,"bounds":{"left":0.7066157,"top":0.24581006,"width":0.020113032,"height":0.11412609},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Conversation (4)","depth":10,"bounds":{"left":0.33776596,"top":0.22785315,"width":0.054853722,"height":0.031923383},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Conversation","depth":11,"bounds":{"left":0.35006648,"top":0.23743017,"width":0.028091755,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":12,"bounds":{"left":0.3882979,"top":0.23743017,"width":0.0028257978,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"4","depth":12,"bounds":{"left":0.39112368,"top":0.23743017,"width":0.0029920214,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":12,"bounds":{"left":0.3941157,"top":0.23743017,"width":0.0018284575,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Commits (7)","depth":10,"bounds":{"left":0.39261967,"top":0.22785315,"width":0.045212764,"height":0.031923383},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Commits","depth":11,"bounds":{"left":0.40492022,"top":0.23743017,"width":0.018949468,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":12,"bounds":{"left":0.43351063,"top":0.23743017,"width":0.0029920214,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"7","depth":12,"bounds":{"left":0.43650267,"top":0.23743017,"width":0.0026595744,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":12,"bounds":{"left":0.43916222,"top":0.23743017,"width":0.0016622341,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Checks (2)","depth":10,"bounds":{"left":0.43783244,"top":0.22785315,"width":0.042386968,"height":0.031923383},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Checks","depth":11,"bounds":{"left":0.45013297,"top":0.23743017,"width":0.015957447,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
-223743641123781569
|
-6852373066360757167
|
click
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny
app
app
Search or jump to…
Type
/
to search
Chat with Copilot
Open Copilot…
Create new...
All issues(g then i)
All pull requests
All repositories
You have no unread notifications(g then n)
Open user navigation menu
Repository navigation
Repository navigation
Code
Code
Pull requests (34)
Pull requests
(
34
)
Agents
Agents
Actions
Actions
Wiki
Wiki
Security and quality (12)
Security and quality
(
12
)
Insights
Insights
Settings
Settings
JY-20963 fix deleted object import #12121 Edit title
JY-20963 fix deleted object import
#
12121
Edit title
View statusView status
Loading
Loading merge status
Code
Code
Open
LakyLak
LakyLak
wants to merge 7 commits into
master
master
from
JY-20963-fix-import-on-deleted-entity
JY-20963-fix-import-on-deleted-entity
Copy head branch name to clipboard
Lines changed: 483 additions & 52 deletions
Conversation (4)
Conversation
(
4
)
Commits (7)
Commits
(
7
)
Checks (2)
Checks...
|
85876
|
NULL
|
NULL
|
NULL
|
|
85878
|
2946
|
10
|
2026-05-28T13:24:47.957441+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974687957_m1.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny
app
app
Search or jump to…
Type
/
to search
Chat with Copilot
Open Copilot…
Create new...
All issues(g then i)
All pull requests
All repositories
You have no unread notifications(g then n)
Open user navigation menu
Repository navigation
Repository navigation
Code
Code
Pull requests (34)
Pull requests
(
34
)
Agents
Agents
Actions
Actions
Wiki
Wiki
Security and quality (12)
Security and quality
(
12
)
Insights
Insights
Settings
Settings
JY-20963 fix deleted object import #12121 Edit title
JY-20963 fix deleted object import
#
12121
Edit title
View statusView status
Loading
Loading merge status
Code
Code
Open
LakyLak
LakyLak
wants to merge 7 commits into
master
master
from
JY-20963-fix-import-on-deleted-entity
JY-20963-fix-import-on-deleted-entity
Copy head branch name to clipboard
Lines changed: 483 additions & 52 deletions
Conversation (4)
Conversation
(
4
)
Commits (7)
Commits
(
7
)
Checks (2)...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Skip to content","depth":0,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Skip to content","depth":1,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Open menu","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Homepage (g then d)","depth":3,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"jiminny","depth":6,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"jiminny","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"app","depth":6,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"app","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search or jump to…","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Type","depth":6,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"/","depth":6,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"to search","depth":6,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Chat with Copilot","depth":4,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXMenuButton","text":"Open Copilot…","depth":3,"on_screen":true,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXMenuButton","text":"Create new...","depth":3,"on_screen":true,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXLink","text":"All issues(g then i)","depth":3,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"All pull requests","depth":3,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"All repositories","depth":3,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"You have no unread notifications(g then n)","depth":3,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"Open user navigation menu","depth":3,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXHeading","text":"Repository navigation","depth":3,"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Repository navigation","depth":4,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Code","depth":6,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Code","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Pull requests (34)","depth":6,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pull requests","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"34","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Agents","depth":6,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Agents","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Actions","depth":6,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Actions","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Wiki","depth":6,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Wiki","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Security and quality (12)","depth":6,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Security and quality","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"12","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Insights","depth":6,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Insights","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"Settings","depth":6,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Settings","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXHeading","text":"JY-20963 fix deleted object import #12121 Edit title","depth":7,"on_screen":true,"help_text":"","role_description":"heading","subrole":"AXUnknown"},{"role":"AXStaticText","text":"JY-20963 fix deleted object import","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"#","depth":9,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"12121","depth":9,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Edit title","depth":8,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXButton","text":"View statusView status","depth":7,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":false,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Loading","depth":9,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Loading merge status","depth":9,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXMenuButton","text":"Code","depth":7,"on_screen":true,"help_text":"","role_description":"menu button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXStaticText","text":"Code","depth":9,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"Open","depth":7,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"LakyLak","depth":9,"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"LakyLak","depth":10,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"wants to merge 7 commits into","depth":9,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"master","depth":9,"on_screen":true,"role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"master","depth":10,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"from","depth":10,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"JY-20963-fix-import-on-deleted-entity","depth":10,"on_screen":true,"role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"JY-20963-fix-import-on-deleted-entity","depth":11,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Copy head branch name to clipboard","depth":10,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Lines changed: 483 additions & 52 deletions","depth":8,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Conversation (4)","depth":10,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Conversation","depth":11,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":12,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"4","depth":12,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":12,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Commits (7)","depth":10,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Commits","depth":11,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"(","depth":12,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"7","depth":12,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":")","depth":12,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Checks (2)","depth":10,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-8889115632658854521
|
-6564142621489568687
|
click
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny
app
app
Search or jump to…
Type
/
to search
Chat with Copilot
Open Copilot…
Create new...
All issues(g then i)
All pull requests
All repositories
You have no unread notifications(g then n)
Open user navigation menu
Repository navigation
Repository navigation
Code
Code
Pull requests (34)
Pull requests
(
34
)
Agents
Agents
Actions
Actions
Wiki
Wiki
Security and quality (12)
Security and quality
(
12
)
Insights
Insights
Settings
Settings
JY-20963 fix deleted object import #12121 Edit title
JY-20963 fix deleted object import
#
12121
Edit title
View statusView status
Loading
Loading merge status
Code
Code
Open
LakyLak
LakyLak
wants to merge 7 commits into
master
master
from
JY-20963-fix-import-on-deleted-entity
JY-20963-fix-import-on-deleted-entity
Copy head branch name to clipboard
Lines changed: 483 additions & 52 deletions
Conversation (4)
Conversation
(
4
)
Commits (7)
Commits
(
7
)
Checks (2)...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85877
|
2946
|
9
|
2026-05-28T13:24:46.810556+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974686810_m1.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
4038346338935103875
|
-1880434261998308105
|
click
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket...
|
85875
|
NULL
|
NULL
|
NULL
|
|
85876
|
2947
|
10
|
2026-05-28T13:24:46.698253+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974686698_m2.jpg...
|
Firefox
|
JY-20963 fix deleted object import by LakyLak · Pu JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app — Work...
|
1
|
github.com/jiminny/app/pull/12121
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.14245346,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.27055067,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.28172386,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.09757314,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.47206703,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.49561054,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5067837,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
3935047927001615761
|
-4474368010461776649
|
click
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
JY-20963 fix deleted object import by LakyLak · Pull Request #12121 · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85875
|
2946
|
8
|
2026-05-28T13:24:43.098770+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974683098_m1.jpg...
|
Firefox
|
Pull requests · jiminny/app — Work
|
1
|
github.com/jiminny/app/pulls/LakyLak
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Pull requests · jiminny/app
Pull requests · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Pull requests · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Pull requests · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
2479216471615309514
|
-1953496672359373596
|
click
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Pull requests · jiminny/app
Pull requests · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85874
|
2947
|
9
|
2026-05-28T13:24:42.760698+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974682760_m2.jpg...
|
Firefox
|
Pull requests · jiminny/app — Work
|
1
|
github.com/jiminny/app/pulls/LakyLak
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Pull requests · jiminny/app
Pull requests · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Pull requests · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Pull requests · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.045545213,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.27055067,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.28172386,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.09757314,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.47206703,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.49561054,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5067837,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-8453251936693158983
|
-1916340876861463305
|
visual_change
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Pull requests · jiminny/app
Pull requests · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket...
|
85873
|
NULL
|
NULL
|
NULL
|
|
85873
|
2947
|
8
|
2026-05-28T13:24:40.288587+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974680288_m2.jpg...
|
Firefox
|
Pull requests · jiminny/app — Work
|
1
|
github.com/jiminny/app/pulls
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Pull requests · jiminny/app
Pull requests · jiminny/app
Close tab...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Pull requests · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Pull requests · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.045545213,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
9040091211076879040
|
-8916748890974657327
|
click
|
hybrid
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Pull requests · jiminny/app
Pull requests · jiminny/app
Close tab
Firefox•.• •EditViewmistonooountrnroitesToolsWindow= github.com/jiminny/app/pullsHelpjiminny / app &<> Code17 Pull requests 34G. AgentsOESOMОДQ Type to search100% K/2 8 • Thu 28 May 16:24:40®SOEE+ONG0ePipelines - jiminny/appBE upgrade libraries(JY-20613) Allow owner's role to bText relayDeleted object errorPul requests - jiminylsop *• Login | SalesforceJiminalExceotionslEmailActivityrMlinbox 11224) - Iias kowstikSlimilZ (JY-20979) Resoive PHP 8.5.5 depOatiwm Sorat 502-Ointarm Ttranscript ss issue8 Jiminmy+* (SRD-6881) (On demand) Transo8 Sona Subramanian at 27/05/2024Ithrans Netceva at 27/05/2026, 168 Jmicay& Now Tal• Actions |W Wiki© Security and quality12w InsightsE SettingsFilters -Qis:pr is:open• 11 34 Open v 11,047 Closed• 1 Jy-20977: Fix ore-meeting reminde.rihter oy autnotO 1 Jy 20771 call scoring filter for exec r#1213? ooened 2 hours 200 du n colmo aivanoylLakyLak Lukas Kovalikan. adeuinaPe rov.• 17 Jy-20905 | Search members v00 alexbogomilov77 Sasholali-fin• 17 Jy 20910 schedule parallel update tieaneliva-liminny Aneliva Angeloval• 11 Add disallowed tools configuration t‹) asharma-roszatanasdimitrovilminny• 11 Jy-20963 fix deleted object importbobisum== dariantcous Tonis ay Atamasol• I7 fix(security): npm dependency upda#12118 opened last week by github-actions Bor dependabot Botdes-d Desislay Damvanou• 17 JY-20828: Manage app permissions#12116 onened laet weol hu dee.?• 11 Jy-20664: expose Exec Reports via customer REST API (read-only vt) x#12111 coened last week bu iamesoraham - Review recuired F) 9 tasksO 17 JY 20741 user can log in access the desktop app~#12110 ocened Iaxt weok bu das-d . Aol• 17 Jy 20835 mcp enable users to get a list of deals and their details•• 1: pipedrive offical SDK v2 POC x#12090 opened last week by LakyLak - Draft• il introduce-new-kiosk-login-features#12084 coencd 2 weeies aoo bu tane minny • Review required• 12 JY-20853 |JY-20833 updated tool search_calls •ew . Oosima tonirorO?B1.207A9IMCD . GAith a nCp X#12063 gocned 2 wecie aoo bu valoionony • Dratt• Labels 67$ Milestones 1dew pull requestAutnor"LabelProiecisMilestonesReviews - Assignee - Sort -d invalid timezone X1@18....
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85872
|
2946
|
7
|
2026-05-28T13:24:39.122248+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974679122_m1.jpg...
|
Firefox
|
Pull requests · jiminny/app — Work
|
1
|
github.com/jiminny/app/pulls
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Pull requests · jiminny/app
Pull requests · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Pull requests · jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Pull requests · jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-8870576352460371759
|
-4511665436798159662
|
click
|
hybrid
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Pull requests · jiminny/app
Pull requests · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
iTerm2ShellEditViewSessionScriptsProfilesWindowHelplda]-zshDOCKER-₴81DEV (docker)₴82-zshscreenpipe"O ₴4-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash-c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8I 100%85ec2-user@ip-10-30-129-...100% <478• Thu 28 May 16:24:38181ec2-user@ip-10-30-140-…₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
85870
|
NULL
|
NULL
|
NULL
|
|
85871
|
2947
|
7
|
2026-05-28T13:24:38.304715+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974678304_m2.jpg...
|
Firefox
|
Pull requests · jiminny/app — Work
|
1
|
github.com/jiminny/app/pulls
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Pull requests · jiminny/app
Pull requests · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny
app
app
Search or jump to…
Type
/...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Pull requests · jiminny/app","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"Pull requests · jiminny/app","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.045545213,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.27055067,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.28172386,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.09757314,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.44533122,"width":0.10106383,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"transcript ss issue","depth":4,"bounds":{"left":0.0028257978,"top":0.47206703,"width":0.036070477,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0028257978,"top":0.49561054,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.015957447,"top":0.5067837,"width":0.013297873,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.0028257978,"top":0.528332,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":5,"bounds":{"left":0.015957447,"top":0.5395052,"width":0.1271609,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.56105345,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.57222664,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":4,"bounds":{"left":0.0028257978,"top":0.5937749,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket","depth":5,"bounds":{"left":0.015957447,"top":0.6049481,"width":0.12134308,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.62649643,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.63766956,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"New Tab","depth":4,"bounds":{"left":0.0028257978,"top":0.66081405,"width":0.07413564,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Customize sidebar","depth":6,"bounds":{"left":0.0028257978,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open Google Gemini (⌃X)","depth":6,"bounds":{"left":0.013796543,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Tabs from other devices","depth":6,"bounds":{"left":0.024933511,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open history (⇧⌘H)","depth":6,"bounds":{"left":0.036070477,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXCheckBox","text":"Open bookmarks (⌘B)","depth":6,"bounds":{"left":0.04720745,"top":0.97007185,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"toggle button","subrole":"AXToggle","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Skip to content","depth":0,"bounds":{"left":0.07962101,"top":0.0518755,"width":0.0003324468,"height":0.0007980846},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Skip to content","depth":1,"bounds":{"left":0.07962101,"top":0.05347167,"width":0.0029920214,"height":0.21468475},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Open menu","depth":4,"bounds":{"left":0.08494016,"top":0.06464485,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"Homepage (g then d)","depth":3,"bounds":{"left":0.099567816,"top":0.06464485,"width":0.010638298,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXLink","text":"jiminny","depth":6,"bounds":{"left":0.112865694,"top":0.06464485,"width":0.018949468,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"jiminny","depth":8,"bounds":{"left":0.11486037,"top":0.07063048,"width":0.014960106,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXLink","text":"app","depth":6,"bounds":{"left":0.13680187,"top":0.06464485,"width":0.017785905,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"link","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"app","depth":8,"bounds":{"left":0.13879654,"top":0.07063048,"width":0.008477394,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Search or jump to…","depth":3,"bounds":{"left":0.81698805,"top":0.06464485,"width":0.06565824,"height":0.025538707},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Type","depth":6,"bounds":{"left":0.82928854,"top":0.07063048,"width":0.011801862,"height":0.013567438},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXStaticText","text":"/","depth":6,"bounds":{"left":0.8424202,"top":0.07222666,"width":0.002493351,"height":0.011572227},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"}]...
|
7732944677590405536
|
-2240583556418181915
|
visual_change
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
Pull requests · jiminny/app
Pull requests · jiminny/app
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
transcript ss issue
Jiminny
Jiminny
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Sona Subramanian at 27/05/2026, 17:46:08 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Iliyana Netseva at 27/05/2026, 18:48:18 - Session Replay - LogRocket
Jiminny
Jiminny
New Tab
Customize sidebar
Open Google Gemini (⌃X)
Tabs from other devices
Open history (⇧⌘H)
Open bookmarks (⌘B)
Skip to content
Skip to content
Open menu
Homepage (g then d)
jiminny
jiminny
app
app
Search or jump to…
Type
/...
|
85869
|
NULL
|
NULL
|
NULL
|
|
85869
|
2947
|
6
|
2026-05-28T13:24:35.245800+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974675245_m2.jpg...
|
Firefox
|
jiminny/app: Jiminny Web Application — Work
|
1
|
github.com/jiminny/app
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
jiminny/app: Jiminny Web Application
jiminny/app: Jiminny Web Application
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0018284575,"top":0.0518755,"width":0.038065158,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"bounds":{"left":0.039893616,"top":0.0518755,"width":0.037898935,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"bounds":{"left":0.0,"top":0.09497207,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"bounds":{"left":0.013297873,"top":0.10614525,"width":0.039228722,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"bounds":{"left":0.0028257978,"top":0.13288109,"width":0.03939495,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"bounds":{"left":0.0,"top":0.15203512,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.1632083,"width":0.12799202,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"bounds":{"left":0.0028257978,"top":0.18994413,"width":0.020279255,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"bounds":{"left":0.0028257978,"top":0.21428572,"width":0.039228722,"height":0.01915403},"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"jiminny/app: Jiminny Web Application","depth":4,"bounds":{"left":0.0028257978,"top":0.23782921,"width":0.07679521,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"jiminny/app: Jiminny Web Application","depth":5,"bounds":{"left":0.015957447,"top":0.2490024,"width":0.064494684,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"bounds":{"left":0.06732048,"top":0.24501197,"width":0.007978723,"height":0.01915403},"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"bounds":{"left":0.0,"top":0.27055067,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Login | Salesforce","depth":5,"bounds":{"left":0.013297873,"top":0.28172386,"width":0.030917553,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":4,"bounds":{"left":0.0,"top":0.30327216,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny\\Exceptions\\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app","depth":5,"bounds":{"left":0.013297873,"top":0.31444532,"width":0.24301861,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":4,"bounds":{"left":0.0,"top":0.33599362,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Inbox (1,734) - lukas.kovalik@jiminny.com - Jiminny Mail","depth":5,"bounds":{"left":0.013297873,"top":0.3471668,"width":0.09757314,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":4,"bounds":{"left":0.0,"top":0.36871508,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20979] Resolve PHP 8.5.5 deprications - Jira","depth":5,"bounds":{"left":0.013297873,"top":0.37988827,"width":0.08543883,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Jiminny","depth":4,"bounds":{"left":0.0,"top":0.40143654,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Jiminny","depth":5,"bounds":{"left":0.013297873,"top":0.41260973,"width":0.013131649,"height":0.010774142},"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"bounds":{"left":0.0,"top":0.43415803,"width":0.07962101,"height":0.032721467},"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-3947767348559576139
|
-1123706376076648205
|
visual_change
|
accessibility
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
jiminny/app: Jiminny Web Application
jiminny/app: Jiminny Web Application
Close tab
Login | Salesforce
Login | Salesforce
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Jiminny\Exceptions\EmailActivityImportException: [Email Import] Failed for InboxEmail ID: 125695762: Error: Request failed — jiminny — app
Inbox (1,734) - [EMAIL] - Jiminny Mail
Inbox (1,734) - [EMAIL] - Jiminny Mail
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
[JY-20979] Resolve PHP 8.5.5 deprications - Jira
Jiminny
Jiminny
Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85870
|
2946
|
6
|
2026-05-28T13:24:35.013997+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974675013_m1.jpg...
|
Firefox
|
jiminny/app: Jiminny Web Application — Work
|
1
|
github.com/jiminny/app
|
monitor_1
|
NULL
|
NULL
|
NULL
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
jiminny/app: Jiminny Web Application
jiminny/app: Jiminny Web Application
Close tab
Login | Salesforce...
|
[{"role":"AXRadioButton","text [{"role":"AXRadioButton","text":"Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"[SRD-6881] [On demand] Transcription in saved search disappears - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Pipelines - jiminny/app","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"Pipelines - jiminny/app","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"BE upgrade libraries","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXRadioButton","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXStaticText","text":"[JY-20613] Allow owner's role to be selected when setting up a trial - Jira","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Text relay","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":false},{"role":"AXButton","text":"Deleted object error","depth":4,"on_screen":true,"role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false,"is_expanded":true},{"role":"AXRadioButton","text":"jiminny/app: Jiminny Web Application","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":true},{"role":"AXStaticText","text":"jiminny/app: Jiminny Web Application","depth":5,"on_screen":true,"help_text":"","role_description":"text","subrole":"AXUnknown"},{"role":"AXButton","text":"Close tab","depth":5,"on_screen":true,"help_text":"","role_description":"button","subrole":"AXUnknown","is_enabled":true,"is_focused":false,"is_selected":false},{"role":"AXRadioButton","text":"Login | Salesforce","depth":4,"on_screen":true,"help_text":"","role_description":"tab","subrole":"AXTabButton","is_enabled":true,"is_focused":false,"is_selected":false}]...
|
-7060131813144740106
|
-3899171559090674478
|
click
|
hybrid
|
NULL
|
Platform Sprint 5 Q2 - Platform Team - Scrum Board Platform Sprint 5 Q2 - Platform Team - Scrum Board - Jira
[SRD-6881] [On demand] Transcription in saved search disappears - Jira
Pipelines - jiminny/app
Pipelines - jiminny/app
BE upgrade libraries
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
[JY-20613] Allow owner's role to be selected when setting up a trial - Jira
Text relay
Deleted object error
jiminny/app: Jiminny Web Application
jiminny/app: Jiminny Web Application
Close tab
Login | Salesforce
iTerm2ShellEditViewSessionScriptsProfilesWindowHelp-zshDOCKER₴81DEV (docker)₴82-zshffmpegO ₴4-zshcreate mode 100644 tests/Unit/Component/TranscriptionSummary/Services/TranscriptionSummaryIndexingServiceTest.phplukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (master) $ ;xddocker exec -it docker_lamp_1 bash -c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"What's next:Try Docker Debug forseamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ ;xddocker exec -itdocker_lamp_1 bash-c "mv /usr/local/etc/php/conf.d/xdebug.ini ~/xdebug.ini"mv: cannot stat '/usr/local/etc/php/conf.d/xdebug.ini': No such file or directoryWhat's next:Try Docker Debug for seamless, persistent debugging tools in any container or image + docker debug docker_lamp_1Learn more at [URL_WITH_CREDENTIALS] ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $ csfixdocker exec -it docker_lamp_1•/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php -v --using-cache=no --diffPHP CS Fixer 3.95.1 Adalbertus by Fabien Potencier, Dariusz Ruminski and contributors.PHP runtime: 8.5.5Loaded config default from ".php-cs-fixer.dist.php".Running analysis on 7 cores with 10 files per process.5697/5697 C8• 100%85ec2-user@ip-10-30-129-...100% <478• Thu 28 May 16:24:34181ec2-user@ip-10-30-140-…₴7Fixed 0 of 5697 files in 67.976 seconds, 799.06 MBmemory usedDetected deprecations in use (they will stop working in next major release):- Rule set"@PHP74Migration" is deprecated. Use "@PHP7x4Migration" instead.- Rule set "@PHP80Migration" is deprecated. Use "@PHP8x®Migration" instead.- Rule set "@PHP81Migration" is deprecated. Use "@PHP8x1Migration" instead.- Rule set "@PHP82Migration" is deprecated. Use "@PHP8x2Migration" instead.- Ruleset "@PHP83Migration" is deprecated. Use "@PHP8x3Migration" instead.- Rule set "@PHP84Migration" is deprecated. Use "@PHP8x4Migration" instead.What's next:Try Docker Debug for seamless, persistent debugging tools in any container or image → docker debug docker_lamp_1Learn more at https://docs.docker.com/go/debug-cli/lukas@Lukas-Kovaliks-MacBook-Pro-Jiminny ~/jiminny/app (JY-20963-fix-import-on-deleted-entity) $I...
|
NULL
|
NULL
|
NULL
|
NULL
|
|
85868
|
2947
|
5
|
2026-05-28T13:24:30.625395+00:00
|
/Users/lukas/.screenpipe/data/data/2026-05-28/1779 /Users/lukas/.screenpipe/data/data/2026-05-28/1779974670625_m2.jpg...
|
Firefox
|
jiminny/app: Jiminny Web Application — Work
|
1
|
github.com/jiminny/app
|
monitor_2
|
NULL
|
NULL
|
NULL
|
NULL
|
rircroxViewhsttonHelp© Pipelines - |Iminnylapp* (J rircroxViewhsttonHelp© Pipelines - |Iminnylapp* (JY-20613) Allow owner's role to tText relayDeleted object errjiminnylapp: Jiminny Web Apx XMlinbox (1294) - Mias kowlikSlimlZ (JY-20979) Resoive PHP 8.5.5 depPiatform Sprint 5 Q2 - Platform TeJiminmy(SRD-6881) (On demand) Transc8 Sona Subramanian at 27/05/2021Ihaos Netcoya at 27/05/2026.188 Jiminay& Now TalooountrnPotLe.= github.com/fiWindow~ Google GeminiGemini 3.1 Pro ~That is a very common misconception, but it is not true anymore!While it is true that many years ago (around 2014-2016) (phpredis had some bugsregardling tne order in wnich ex and nx arguments were passeo, lnas tuly suppontedcombining them into a single atomic command for a very long time.To do this atomically using the phpredis driver, you simply pass an associative array ofoptions as the third argument.Here is exactly how you would write it in your code:PHPSlockKey = sprintf(self::LOCK_KEY, $this->updateTarget);// This executes a single, atomic SET conmmand with both NX and EXSacquired = Redis::set(lockkey, true, L'NX, "EX => seLT::LOCK-TIL.SECONDS))Eif (! Sacquired) &// Another process already holds the lockreturn;I... report your metrics ...By relvina on senarate det, setand expire commands, vou are leavino amicrosecond gap open. In your new multi-process Supervisor architecture, two parallelworkers can check the get , both see (null), and both proceed to write the lock andpush duplicate metrics. Using the array syntax above closes that gap completely.A Cleaner Laravel AlternativeSince you are inside a Laravel app, you don't even need to fight with driver-specific Redissyntax. Laravel provides a dedicated, atomic lock manager that handles the phpredis /Ask cemintSummarize pagejiminny / app &<> Code1 Pull requests 34(. Agents®+eO&OASOMОД100% 142-• Thu 28 May 16:24:30Q Type to search8 -• Actions.Q Wiki|© Security and qualitylw Insights83 Settingsa appo Unwatchsrofk* Star 1PP master - P 94 Branches • 26 TagsQ Go to fileAdd file-< CodeTodorStamatovJiminny Merge pull request #12133 from jiminny/JY-20802... •c225959 - 1 hour aco 0) 74,550 Commit.circieci .cursor/rulesCKnutsonarlintln vscodeappIn bootstrap# configdatabasedocstront-endim lang/en_USim node_modulesphpstan/stubFiles/Illuminatepudlioresources/viewghroutad?a scriptsstoragetestseditorconfinJY-18091 | Composer changesZweeks ao0Add responsive breakpoints guidance to frontend conventi…..Enhance sanitization function to escape both '' and 'S' c.last monthWire up outlook authenticationlast week11 months agoJy-8427 Add launch.json for debug settingsMerge branch 'master' into JY-20802-salesforce-zoom-in..3 years ago1 hour agoRun php-cs-fixer fixJY-18091 | Resolve conflictsJY-20960: Update Swagger and tests4 years ago2 weeks agolast weerJY-20771 | Add ai_call_scores columnupoate expioreyesterday2 weeks ago|J-20960: Uodate tests)last wee.JY-14450 shorten linesJY-16379 Updated postmark templates with new coachin..2 years agolast yearphp artisan ide-helper:modelsAdd automated reports promotion components and updat...JY-20699 | Restore import3 years agolast monthlast monthJY-20960: Update AJA GET to POSTlast weekFix stage profile for remote commands run5 hours agoUodate audio fille, volume and timeout.last voalMerge branch 'master' into JY-20802-salesforce-zoom-in...1 hour ago|JY-16889 Uodate trontendilast veatAboutJiminny Web Application@ app.jiminny.comC Readme1 ActivityE Custom properties# 1 star• 3 watching|O forksDeployments 500+@ Staging inactive|+ more deploymentsPackagesNo packages publishedPublish your first packageContributors 22ОeФeС.+ 8 contributors)Languages• PHP 72.8% • JavaScript 12.5%• Vue 6.5% • HTML 6.5%• Less 0.9%• Mustache 0.3%Other 0.5%...
|
NULL
|
-550891304601264866
|
NULL
|
click
|
ocr
|
NULL
|
rircroxViewhsttonHelp© Pipelines - |Iminnylapp* (J rircroxViewhsttonHelp© Pipelines - |Iminnylapp* (JY-20613) Allow owner's role to tText relayDeleted object errjiminnylapp: Jiminny Web Apx XMlinbox (1294) - Mias kowlikSlimlZ (JY-20979) Resoive PHP 8.5.5 depPiatform Sprint 5 Q2 - Platform TeJiminmy(SRD-6881) (On demand) Transc8 Sona Subramanian at 27/05/2021Ihaos Netcoya at 27/05/2026.188 Jiminay& Now TalooountrnPotLe.= github.com/fiWindow~ Google GeminiGemini 3.1 Pro ~That is a very common misconception, but it is not true anymore!While it is true that many years ago (around 2014-2016) (phpredis had some bugsregardling tne order in wnich ex and nx arguments were passeo, lnas tuly suppontedcombining them into a single atomic command for a very long time.To do this atomically using the phpredis driver, you simply pass an associative array ofoptions as the third argument.Here is exactly how you would write it in your code:PHPSlockKey = sprintf(self::LOCK_KEY, $this->updateTarget);// This executes a single, atomic SET conmmand with both NX and EXSacquired = Redis::set(lockkey, true, L'NX, "EX => seLT::LOCK-TIL.SECONDS))Eif (! Sacquired) &// Another process already holds the lockreturn;I... report your metrics ...By relvina on senarate det, setand expire commands, vou are leavino amicrosecond gap open. In your new multi-process Supervisor architecture, two parallelworkers can check the get , both see (null), and both proceed to write the lock andpush duplicate metrics. Using the array syntax above closes that gap completely.A Cleaner Laravel AlternativeSince you are inside a Laravel app, you don't even need to fight with driver-specific Redissyntax. Laravel provides a dedicated, atomic lock manager that handles the phpredis /Ask cemintSummarize pagejiminny / app &<> Code1 Pull requests 34(. Agents®+eO&OASOMОД100% 142-• Thu 28 May 16:24:30Q Type to search8 -• Actions.Q Wiki|© Security and qualitylw Insights83 Settingsa appo Unwatchsrofk* Star 1PP master - P 94 Branches • 26 TagsQ Go to fileAdd file-< CodeTodorStamatovJiminny Merge pull request #12133 from jiminny/JY-20802... •c225959 - 1 hour aco 0) 74,550 Commit.circieci .cursor/rulesCKnutsonarlintln vscodeappIn bootstrap# configdatabasedocstront-endim lang/en_USim node_modulesphpstan/stubFiles/Illuminatepudlioresources/viewghroutad?a scriptsstoragetestseditorconfinJY-18091 | Composer changesZweeks ao0Add responsive breakpoints guidance to frontend conventi…..Enhance sanitization function to escape both '' and 'S' c.last monthWire up outlook authenticationlast week11 months agoJy-8427 Add launch.json for debug settingsMerge branch 'master' into JY-20802-salesforce-zoom-in..3 years ago1 hour agoRun php-cs-fixer fixJY-18091 | Resolve conflictsJY-20960: Update Swagger and tests4 years ago2 weeks agolast weerJY-20771 | Add ai_call_scores columnupoate expioreyesterday2 weeks ago|J-20960: Uodate tests)last wee.JY-14450 shorten linesJY-16379 Updated postmark templates with new coachin..2 years agolast yearphp artisan ide-helper:modelsAdd automated reports promotion components and updat...JY-20699 | Restore import3 years agolast monthlast monthJY-20960: Update AJA GET to POSTlast weekFix stage profile for remote commands run5 hours agoUodate audio fille, volume and timeout.last voalMerge branch 'master' into JY-20802-salesforce-zoom-in...1 hour ago|JY-16889 Uodate trontendilast veatAboutJiminny Web Application@ app.jiminny.comC Readme1 ActivityE Custom properties# 1 star• 3 watching|O forksDeployments 500+@ Staging inactive|+ more deploymentsPackagesNo packages publishedPublish your first packageContributors 22ОeФeС.+ 8 contributors)Languages• PHP 72.8% • JavaScript 12.5%• Vue 6.5% • HTML 6.5%• Less 0.9%• Mustache 0.3%Other 0.5%...
|
85866
|
NULL
|
NULL
|
NULL
|