Compare commits

..

29 Commits

Author SHA1 Message Date
Yuri Kuznetsov d8f58dcc1d upgrade cleanup 2020-10-09 14:58:34 +03:00
Yuri Kuznetsov 32aaaa350e v 2020-10-09 14:37:50 +03:00
Yuri Kuznetsov 0f6d1c6817 fix diff: ignore upgrades 2020-10-09 13:56:41 +03:00
Yuri Kuznetsov 8c5a342a5a fix diff 2020-10-09 13:53:07 +03:00
Yuri Kuznetsov 257401898b upgrade cleanup files and fix msg 2020-10-09 12:24:24 +03:00
Yuri Kuznetsov e7ff3f903a fix email modal 2020-10-08 14:05:28 +03:00
Taras Machyshyn 6f82638b5d Upgrade script 2020-10-07 17:46:08 +03:00
Taras Machyshyn 0625ce51c4 Upgrade script 2020-10-07 17:26:11 +03:00
Taras Machyshyn f5670436d0 Merge branch 'master' of https://github.com/espocrm/espocrm 2020-10-07 17:19:05 +03:00
Taras Machyshyn 5d20a56ac8 Upgrade script 2020-10-07 17:18:34 +03:00
Yuri Kuznetsov 020cf9713a Merge branch 'master' of https://github.com/espocrm/espocrm 2020-10-07 16:49:33 +03:00
Yuri Kuznetsov fe1361fc9c portal action list restriction 2020-10-07 16:49:01 +03:00
Taras Machyshyn 36621be496 Merge branch 'master' of https://github.com/espocrm/espocrm 2020-10-07 15:51:31 +03:00
Taras Machyshyn 25690030d1 Installation fixes 2020-10-07 15:50:57 +03:00
Yuri Kuznetsov fcd6be3a0c fix password recovery 2020-10-07 15:39:03 +03:00
Yuri Kuznetsov ad8dfa487c fix convert lead 2020-10-07 15:13:39 +03:00
Yuri Kuznetsov 7f6f54628d cs fix 2020-10-07 15:04:42 +03:00
Taras Machyshyn 8ea0b072c6 Installation fixes 2020-10-07 14:22:21 +03:00
Yuri Kuznetsov 0df6248226 getPhpSafeContents for unix 2020-10-07 13:12:55 +03:00
Yuri Kuznetsov 26a132658e date after before validation autocomplete 2020-10-07 12:42:51 +03:00
Yuri Kuznetsov d02529ee86 Merge branch 'hotfix/5.9.5' 2020-10-07 11:02:01 +03:00
Yuri Kuznetsov 0cec0fef51 fix image orientation 2020-10-07 11:01:32 +03:00
Yuri Kuznetsov e56f6ab75d fix image orientation 2020-10-07 10:55:39 +03:00
Yuri Kuznetsov a4980aa8f2 cs fix 2020-10-07 10:53:21 +03:00
Yuri Kuznetsov fd219b49be calendar modal fix 2020-10-06 13:44:35 +03:00
Yuri Kuznetsov b90579aadc cs fix 2020-10-06 13:44:18 +03:00
Yuri Kuznetsov 0b39d7f6b6 cs fix 2020-10-06 12:13:17 +03:00
Yuri Kuznetsov a44ce06162 Merge branch 'master' of https://github.com/espocrm/espocrm 2020-10-06 12:02:35 +03:00
Yuri Kuznetsov f1eb2ab5d5 cs fix 2020-10-06 12:00:48 +03:00
26 changed files with 620 additions and 199 deletions
+1 -1
View File
@@ -274,7 +274,7 @@ class Recovery
'isSystem' => true,
]);
if (!$this->emailAddress->hasSystemSmtp()) {
if (!$this->emailSender->hasSystemSmtp()) {
$sender->withSmtpParams([
'server' => $config->get('internalSmtpServer'),
'port' => $config->get('internalSmtpPort'),
+1 -5
View File
@@ -203,7 +203,7 @@ class Manager
/**
* Get array or StdClass data from PHP file.
* For Windows: If a file is not yet written, it will wait until it's ready.
* If a file is not yet written, it will wait until it's ready.
*
* @return array|StdClass
*/
@@ -226,10 +226,6 @@ class Manager
return $data;
}
if (stripos(\PHP_OS, 'WIN') !== 0) {
break;
}
usleep(self::GET_SAFE_CONTENTS_RETRY_INTERVAL * 1000000);
$counter ++;
@@ -4,6 +4,7 @@
"tab": false,
"acl": "recordAllTeamNo",
"aclPortal": "recordAllNo",
"aclPortalActionList": ["read"],
"module": "Crm",
"customizable": true,
"importable": false,
@@ -4,6 +4,7 @@
"tab": true,
"acl": "recordAllTeamNo",
"aclPortal": "recordAllNo",
"aclPortalActionList": ["read"],
"module": "Crm",
"customizable": true,
"importable": true,
@@ -4,6 +4,7 @@
"tab": false,
"acl": "recordAllTeamNo",
"aclPortal": "recordAllNo",
"aclPortalActionList": ["read"],
"module": "Crm",
"customizable": true,
"importable": false,
+157 -81
View File
@@ -31,14 +31,17 @@ namespace Espo\Modules\Crm\Services;
use Espo\Core\Exceptions\Error;
use Espo\Core\Exceptions\Forbidden;
use Espo\Core\Exceptions\ConflictSilent;
use Espo\ORM\Entity;
use Espo\Modules\Crm\Entities\Lead as LeadEntity;
use Espo\Core\Templates\Services\Person as PersonService;
use Espo\Core\Di;
class Lead extends \Espo\Core\Templates\Services\Person implements
class Lead extends PersonService implements
Di\FieldUtilAware
{
@@ -52,31 +55,36 @@ class Lead extends \Espo\Core\Templates\Services\Person implements
{
if (!empty($data->emailId)) {
$email = $this->getEntityManager()->getEntity('Email', $data->emailId);
if ($email && !$email->get('parentId') && $this->getAcl()->check($email)) {
$email->set(array(
$email->set([
'parentType' => 'Lead',
'parentId' => $entity->id
));
]);
$this->getEntityManager()->saveEntity($email);
}
}
if ($entity->get('campaignId')) {
$campaign = $this->getEntityManager()->getEntity('Campaign', $entity->get('campaignId'));
if ($campaign) {
$log = $this->getEntityManager()->getEntity('CampaignLogRecord');
$log->set(array(
'action' => 'Lead Created',
'actionDate' => date('Y-m-d H:i:s'),
'parentType' => 'Lead',
'parentId' => $entity->id,
'campaignId' => $campaign->id
));
$this->getEntityManager()->saveEntity($log);
}
$campaign = $this->getEntityManager()->getEntity('Campaign', $entity->get('campaignId'));
if ($campaign) {
$log = $this->getEntityManager()->getEntity('CampaignLogRecord');
$log->set([
'action' => 'Lead Created',
'actionDate' => date('Y-m-d H:i:s'),
'parentType' => 'Lead',
'parentId' => $entity->id,
'campaignId' => $campaign->id,
]);
$this->getEntityManager()->saveEntity($log);
}
}
}
public function getConvertAttributes($id)
public function getConvertAttributes(string $id)
{
$lead = $this->getEntity($id);
@@ -84,7 +92,7 @@ class Lead extends \Espo\Core\Templates\Services\Person implements
throw new Forbidden();
}
$data = array();
$data = [];
$entityList = $this->getMetadata()->get('entityDefs.Lead.convertEntityList', []);
@@ -93,22 +101,30 @@ class Lead extends \Espo\Core\Templates\Services\Person implements
$convertFieldsDefs = $this->getMetadata()->get('entityDefs.Lead.convertFields', array());
foreach ($entityList as $entityType) {
if (!$this->getAcl()->checkScope($entityType, 'edit')) continue;
if (!$this->getAcl()->checkScope($entityType, 'edit')) {
continue;
}
$attributes = array();
$attributes = [];
$target = $this->getEntityManager()->getEntity($entityType);
$fieldMap = array();
$fieldMap = [];
$fieldList = array_keys($this->getMetadata()->get('entityDefs.Lead.fields', []));
$fieldList = array_keys($this->getMetadata()->get('entityDefs.Lead.fields', array()));
foreach ($fieldList as $field) {
if (!$this->getMetadata()->get('entityDefs.'.$entityType.'.fields.' . $field)) continue;
if (!$this->getMetadata()->get('entityDefs.'.$entityType.'.fields.' . $field)) {
continue;
}
if (
$this->getMetadata()->get(['entityDefs', $entityType, 'fields', $field, 'type'])
!==
$this->getMetadata()->get(['entityDefs', 'Lead', 'fields', $field, 'type'])
) continue;
) {
continue;
}
$fieldMap[$field] = $field;
}
@@ -121,55 +137,69 @@ class Lead extends \Espo\Core\Templates\Services\Person implements
foreach ($fieldMap as $field => $leadField) {
$type = $this->getMetadata()->get(['entityDefs', 'Lead', 'fields', $field, 'type']);
if (in_array($type, ['file', 'image'])) {
$attachment = $lead->get($field);
if ($attachment) {
$attachment = $this->getEntityManager()->getRepository('Attachment')->getCopiedAttachment($attachment);
$idAttribute = $field . 'Id';
$nameAttribute = $field . 'Name';
if ($attachment) {
$attributes[$idAttribute] = $attachment->id;
$attributes[$nameAttribute] = $attachment->get('name');
}
}
continue;
} else if (in_array($type, ['attachmentMultiple'])) {
}
else if (in_array($type, ['attachmentMultiple'])) {
$attachmentList = $lead->get($field);
if (count($attachmentList)) {
$idList = [];
$nameHash = (object) [];
$typeHash = (object) [];
foreach ($attachmentList as $attachment) {
$attachment = $this->getEntityManager()->getRepository('Attachment')->getCopiedAttachment($attachment);
if ($attachment) {
$idList[] = $attachment->id;
$nameHash->{$attachment->id} = $attachment->get('name');
$typeHash->{$attachment->id} = $attachment->get('type');
}
}
$attributes[$field . 'Ids'] = $idList;
$attributes[$field . 'Names'] = $nameHash;
$attributes[$field . 'Types'] = $typeHash;
}
continue;
}
$leadAttributeList = $this->fieldUtil->getAttributeList('Lead', $leadField);
$attributeList = $this->fieldUtil->getAttributeList($entityType, $field);
foreach ($attributeList as $i => $attribute) {
if (in_array($attribute, $ignoreAttributeList)) continue;
if (in_array($attribute, $ignoreAttributeList)) {
continue;
}
$leadAttribute = $leadAttributeList[$i];
if (!$lead->has($leadAttribute)) continue;
if (!$lead->has($leadAttribute)) {
continue;
}
$attributes[$attribute] = $lead->get($leadAttribute);
}
}
$data[$entityType] = $attributes;
}
return $data;
@@ -197,7 +227,10 @@ class Lead extends \Espo\Core\Templates\Services\Person implements
$account->set(get_object_vars($recordsData->Account));
if ($duplicateCheck) {
$rDuplicateList = $this->getServiceFactory()->create('Account')->findDuplicates($account, $recordsData->Account);
$rDuplicateList = $this->getServiceFactory()
->create('Account')
->findDuplicates($account, $recordsData->Account);
if ($rDuplicateList) {
foreach ($rDuplicateList as $e) {
$item = $e->getValueMap();
@@ -210,6 +243,7 @@ class Lead extends \Espo\Core\Templates\Services\Person implements
if (!$skipSave) {
$entityManager->saveEntity($account);
$lead->set('createdAccountId', $account->id);
}
}
@@ -217,12 +251,16 @@ class Lead extends \Espo\Core\Templates\Services\Person implements
if (!empty($recordsData->Contact)) {
$contact = $entityManager->getEntity('Contact');
$contact->set(get_object_vars($recordsData->Contact));
if (isset($account)) {
$contact->set('accountId', $account->id);
}
if ($duplicateCheck) {
$rDuplicateList = $this->getServiceFactory()->create('Contact')->findDuplicates($contact, $recordsData->Contact);
$rDuplicateList = $this->getServiceFactory()
->create('Contact')
->findDuplicates($contact, $recordsData->Contact);
if ($rDuplicateList) {
foreach ($rDuplicateList as $e) {
$item = $e->getValueMap();
@@ -235,6 +273,7 @@ class Lead extends \Espo\Core\Templates\Services\Person implements
if (!$skipSave) {
$entityManager->saveEntity($contact);
$lead->set('createdContactId', $contact->id);
}
}
@@ -242,15 +281,18 @@ class Lead extends \Espo\Core\Templates\Services\Person implements
if (!empty($recordsData->Opportunity)) {
$opportunity = $entityManager->getEntity('Opportunity');
$opportunity->set(get_object_vars($recordsData->Opportunity));
if (isset($account)) {
$opportunity->set('accountId', $account->id);
}
if (isset($contact)) {
$opportunity->set('contactId', $contact->id);
}
if ($duplicateCheck) {
$rDuplicateList = $this->getServiceFactory()->create('Opportunity')
$rDuplicateList = $this->getServiceFactory()
->create('Opportunity')
->findDuplicates($opportunity, $recordsData->Opportunity);
if ($rDuplicateList) {
@@ -265,9 +307,11 @@ class Lead extends \Espo\Core\Templates\Services\Person implements
if (!$skipSave) {
$entityManager->saveEntity($opportunity);
if (isset($contact)) {
$entityManager->getRepository('Contact')->relate($contact, 'opportunities', $opportunity);
}
$lead->set('createdOpportunityId', $opportunity->id);
}
}
@@ -277,78 +321,110 @@ class Lead extends \Espo\Core\Templates\Services\Person implements
'reason' => 'duplicate',
'duplicates' => $duplicateList,
];
throw new \Espo\Core\Exceptions\ConflictSilent(json_encode($reason));
throw new ConflictSilent(json_encode($reason));
}
$lead->set('status', 'Converted');
$entityManager->saveEntity($lead);
if ($meetings = $lead->get('meetings')) {
foreach ($meetings as $meeting) {
if (!empty($contact)) {
$entityManager->getRepository('Meeting')->relate($meeting, 'contacts', $contact);
}
$leadRepisotory = $entityManager->getRepository('Lead');
if (!empty($opportunity)) {
$meeting->set('parentId', $opportunity->id);
$meeting->set('parentType', 'Opportunity');
$entityManager->saveEntity($meeting);
} else if (!empty($account)) {
$meeting->set('parentId', $account->id);
$meeting->set('parentType', 'Account');
$entityManager->saveEntity($meeting);
}
$meetings = $leadRepisotory
->getRelation($lead, 'meetings')
->select(['id', 'parentId', 'parentType'])
->find();
foreach ($meetings as $meeting) {
if (!empty($contact)) {
$entityManager->getRepository('Meeting')->relate($meeting, 'contacts', $contact);
}
}
if ($calls = $lead->get('calls')) {
foreach ($calls as $call) {
if (!empty($contact)) {
$entityManager->getRepository('Call')->relate($call, 'contacts', $contact);
}
if (!empty($opportunity)) {
$call->set('parentId', $opportunity->id);
$call->set('parentType', 'Opportunity');
$entityManager->saveEntity($call);
} else if (!empty($account)) {
$call->set('parentId', $account->id);
$call->set('parentType', 'Account');
$entityManager->saveEntity($call);
}
if (!empty($opportunity)) {
$meeting->set('parentId', $opportunity->id);
$meeting->set('parentType', 'Opportunity');
$entityManager->saveEntity($meeting);
}
}
if ($emails = $lead->get('emails')) {
foreach ($emails as $email) {
if (!empty($opportunity)) {
$email->set('parentId', $opportunity->id);
$email->set('parentType', 'Opportunity');
$entityManager->saveEntity($email);
} else if (!empty($account)) {
$email->set('parentId', $account->id);
$email->set('parentType', 'Account');
$entityManager->saveEntity($email);
}
else if (!empty($account)) {
$meeting->set('parentId', $account->id);
$meeting->set('parentType', 'Account');
$entityManager->saveEntity($meeting);
}
}
if ($documents = $lead->get('documents')) {
foreach ($documents as $document) {
if (!empty($account)) {
$entityManager->getRepository('Document')->relate($document, 'accounts', $account);
}
if (!empty($opportunity)) {
$entityManager->getRepository('Document')->relate($document, 'opportunities', $opportunity);
}
$calls = $leadRepisotory
->getRelation($lead, 'calls')
->select(['id', 'parentId', 'parentType'])
->find();
foreach ($calls as $call) {
if (!empty($contact)) {
$entityManager->getRepository('Call')->relate($call, 'contacts', $contact);
}
if (!empty($opportunity)) {
$call->set('parentId', $opportunity->id);
$call->set('parentType', 'Opportunity');
$entityManager->saveEntity($call);
}
else if (!empty($account)) {
$call->set('parentId', $account->id);
$call->set('parentType', 'Account');
$entityManager->saveEntity($call);
}
}
$emails = $leadRepisotory
->getRelation($lead, 'emails')
->select(['id', 'parentId', 'parentType'])
->find();
foreach ($emails as $email) {
if (!empty($opportunity)) {
$email->set('parentId', $opportunity->id);
$email->set('parentType', 'Opportunity');
$entityManager->saveEntity($email);
}
else if (!empty($account)) {
$email->set('parentId', $account->id);
$email->set('parentType', 'Account');
$entityManager->saveEntity($email);
}
}
$documents = $leadRepisotory
->getRelation($lead, 'documents')
->select(['id'])
->find();
foreach ($documents as $document) {
if (!empty($account)) {
$entityManager->getRepository('Document')->relate($document, 'accounts', $account);
}
if (!empty($opportunity)) {
$entityManager->getRepository('Document')->relate($document, 'opportunities', $opportunity);
}
}
$streamService = $this->getStreamService();
if ($streamService->checkIsFollowed($lead, $this->getUser()->id)) {
if (!empty($opportunity)) {
$streamService->followEntity($opportunity, $this->getUser()->id);
}
if (!empty($account)) {
$streamService->followEntity($account, $this->getUser()->id);
}
if (!empty($contact)) {
$streamService->followEntity($contact, $this->getUser()->id);
}
@@ -42,11 +42,13 @@
},
{
"name":"after",
"type":"varchar"
"type":"varchar",
"view": "views/admin/field-manager/fields/date/after-before"
},
{
"name":"before",
"type":"varchar"
"type":"varchar",
"view": "views/admin/field-manager/fields/date/after-before"
},
{
"type": "bool",
@@ -39,11 +39,13 @@
},
{
"name":"after",
"type":"varchar"
"type":"varchar",
"view": "views/admin/field-manager/fields/date/after-before"
},
{
"name":"before",
"type":"varchar"
"type":"varchar",
"view": "views/admin/field-manager/fields/date/after-before"
},
{
"type": "bool",
@@ -39,11 +39,13 @@
},
{
"name":"after",
"type":"varchar"
"type":"varchar",
"view": "views/admin/field-manager/fields/date/after-before"
},
{
"name":"before",
"type":"varchar"
"type":"varchar",
"view": "views/admin/field-manager/fields/date/after-before"
},
{
"type": "bool",
@@ -5,6 +5,7 @@
"acl": "recordAllTeamNo",
"aclPortal": true,
"aclPortalLevelList": ["all", "no"],
"aclPortalActionList": ["read"],
"customizable": true,
"importable": true,
"disabled": false
+177 -68
View File
@@ -43,10 +43,16 @@ use Espo\Core\{
Mail\Parsers\MailMimeParser,
};
use Espo\Services\{
Email as EmailService,
Record as RecordService,
};
use Espo\Entities\{
Team,
InboundEmail as InboundEmailEntity,
User,
Email as EmailEntity,
};
use Espo\Core\Di;
@@ -57,7 +63,7 @@ use Throwable;
use DateTime;
use DateTimeZone;
class InboundEmail extends \Espo\Services\Record implements
class InboundEmail extends RecordService implements
Di\CryptAware,
Di\EmailSenderAware,
@@ -83,9 +89,11 @@ class InboundEmail extends \Espo\Services\Record implements
protected function handleInput($data)
{
parent::handleInput($data);
if (property_exists($data, 'password')) {
$data->password = $this->getCrypt()->encrypt($data->password);
}
if (property_exists($data, 'smtpPassword')) {
$data->smtpPassword = $this->getCrypt()->encrypt($data->smtpPassword);
}
@@ -106,6 +114,7 @@ class InboundEmail extends \Espo\Services\Record implements
{
if (!empty($params['id'])) {
$account = $this->getEntityManager()->getEntity('InboundEmail', $params['id']);
if ($account) {
$params['password'] = $this->getCrypt()->decrypt($account->get('password'));
$params['imapHandler'] = $account->get('imapHandler');
@@ -117,9 +126,11 @@ class InboundEmail extends \Espo\Services\Record implements
$storage = $this->createStorage($params);
$folders = new RecursiveIteratorIterator($storage->getFolders(), RecursiveIteratorIterator::SELF_FIRST);
foreach ($folders as $name => $folder) {
$foldersArr[] = mb_convert_encoding($folder->getGlobalName(), 'UTF-8', 'UTF7-IMAP');
}
return $foldersArr;
}
@@ -127,6 +138,7 @@ class InboundEmail extends \Espo\Services\Record implements
{
if (!empty($params['id'])) {
$account = $this->getEntityManager()->getEntity('InboundEmail', $params['id']);
if ($account) {
$params['imapHandler'] = $account->get('imapHandler');
}
@@ -137,6 +149,7 @@ class InboundEmail extends \Espo\Services\Record implements
if ($storage->getFolders()) {
return true;
}
throw new Error();
}
@@ -153,25 +166,30 @@ class InboundEmail extends \Espo\Services\Record implements
$maxSize = $this->getConfig()->get('emailMessageMaxSize');
$teamId = $emailAccount->get('teamId');
$userId = null;
if ($emailAccount->get('assignToUserId')) {
$userId = $emailAccount->get('assignToUserId');
}
$userIdList = [];
$teamIdList = $emailAccount->getLinkMultipleIdList('teams');
if (!empty($teamIdList)) {
if ($emailAccount->get('addAllTeamUsers')) {
$userList = $this->getEntityManager()->getRepository('User')->find([
'select' => ['id'],
'whereClause' => [
$userList = $this->getEntityManager()
->getRepository('User')
->select(['id'])
->distinct()
->join('teams')
->where([
'isActive' => true,
'teamsMiddle.teamId' => $teamIdList
],
'distinct' => true,
'joins' => ['teams'],
]);
'teamsMiddle.teamId' => $teamIdList,
])
->find();
foreach ($userList as $user) {
$userIdList[] = $user->id;
}
@@ -182,18 +200,21 @@ class InboundEmail extends \Espo\Services\Record implements
$teamIdList[] = $teamId;
}
$filterCollection = $this->getEntityManager()->getRepository('EmailFilter')->where([
'action' => 'Skip',
'OR' => [
[
'parentType' => $emailAccount->getEntityType(),
'parentId' => $emailAccount->id
$filterCollection = $this->getEntityManager()
->getRepository('EmailFilter')
->where([
'action' => 'Skip',
'OR' => [
[
'parentType' => $emailAccount->getEntityType(),
'parentId' => $emailAccount->id,
],
[
'parentId' => null
],
],
[
'parentId' => null
]
]
])->find();
])
->find();
$fetchData = $emailAccount->get('fetchData');
@@ -239,6 +260,7 @@ class InboundEmail extends \Espo\Services\Record implements
$GLOBALS['log']->error(
'InboundEmail '.$emailAccount->id.' (Select Folder) [' . $e->getCode() . '] ' .$e->getMessage()
);
continue;
}
@@ -266,6 +288,7 @@ class InboundEmail extends \Espo\Services\Record implements
$idList = $storage->getIdsFromUID($lastUID);
} else {
$fetchSince = $emailAccount->get('fetchSince');
if ($lastDate) {
$fetchSince = $lastDate;
}
@@ -296,8 +319,10 @@ class InboundEmail extends \Espo\Services\Record implements
if ($forceByDate && $previousLastUID) {
$uid = $storage->getUniqueId($id);
if ($uid <= $previousLastUID) {
$k++;
continue;
}
}
@@ -379,6 +404,7 @@ class InboundEmail extends \Espo\Services\Record implements
} else {
if ($emailAccount->get('reply')) {
$user = $this->getEntityManager()->getEntity('User', $userId);
$this->autoReply($emailAccount, $email, $user);
}
}
@@ -394,15 +420,18 @@ class InboundEmail extends \Espo\Services\Record implements
if ($email && $email->get('dateSent')) {
$dt = null;
try {
$dt = new DateTime($email->get('dateSent'));
} catch (Exception $e) {}
if ($dt) {
$nowDt = new DateTime();
if ($dt->getTimestamp() >= $nowDt->getTimestamp()) {
$dt = $nowDt;
}
$dateSent = $dt->setTimezone(new DateTimeZone('UTC'))->format('Y-m-d H:i:s');
$lastDate = $dateSent;
}
@@ -416,6 +445,7 @@ class InboundEmail extends \Espo\Services\Record implements
if ($forceByDate) {
$nowDt = new DateTime();
$lastDate = $nowDt->format('Y-m-d H:i:s');
}
@@ -425,8 +455,10 @@ class InboundEmail extends \Espo\Services\Record implements
if ($forceByDate) {
if ($previousLastUID) {
$idList = $storage->getIdsFromUID($previousLastUID);
if (count($idList)) {
$uid1 = $storage->getUniqueId($idList[0]);
if ($uid1 && $uid1 > $previousLastUID) {
unset($fetchData->byDate->$folder);
}
@@ -453,6 +485,7 @@ class InboundEmail extends \Espo\Services\Record implements
$filterCollection, $fetchOnlyHeader, $folderData = null
) {
$email = null;
try {
$email = $importer->importMessage(
$message, $userId, $teamIdList, $userIdList, $filterCollection, $fetchOnlyHeader, $folderData
@@ -475,8 +508,10 @@ class InboundEmail extends \Espo\Services\Record implements
{
if ($email->get('parentType') && $email->get('parentId')) {
$parent = $this->getEntityManager()->getEntity($email->get('parentType'), $email->get('parentId'));
if ($parent) {
$this->getServiceFactory()->create('Stream')->noteEmailReceived($parent, $email);
return;
}
}
@@ -490,6 +525,7 @@ class InboundEmail extends \Espo\Services\Record implements
$userIdList = $case->getLinkMultipleIdList('assignedUsers');
} else {
$assignedUserId = $case->get('assignedUserId');
if ($assignedUserId) {
$userIdList[] = $assignedUserId;
}
@@ -515,48 +551,58 @@ class InboundEmail extends \Espo\Services\Record implements
{
if ($email->get('parentType') == 'Case' && $email->get('parentId')) {
$case = $this->getEntityManager()->getEntity('Case', $email->get('parentId'));
if ($case) {
$this->processCaseToEmailFields($case, $email);
if (!$email->isFetched()) {
$this->getServiceFactory()->create('Stream')->noteEmailReceived($case, $email);
}
}
return;
}
if (preg_match('/\[#([0-9]+)[^0-9]*\]/', $email->get('name'), $m)) {
$caseNumber = $m[1];
$case = $this->getEntityManager()->getRepository('Case')->where([
'number' => $caseNumber
])->findOne();
$case = $this->getEntityManager()
->getRepository('Case')
->where([
'number' => $caseNumber,
])
->findOne();
if ($case) {
$email->set('parentType', 'Case');
$email->set('parentId', $case->id);
$this->processCaseToEmailFields($case, $email);
if (!$email->isFetched()) {
$this->getServiceFactory()->create('Stream')->noteEmailReceived($case, $email);
}
}
} else {
$params = [
'caseDistribution' => $inboundEmail->get('caseDistribution'),
'teamId' => $inboundEmail->get('teamId'),
'userId' => $inboundEmail->get('assignToUserId'),
'targetUserPosition' => $inboundEmail->get('targetUserPosition'),
'inboundEmailId' => $inboundEmail->id
];
$case = $this->emailToCase($email, $params);
return;
}
$user = $this->getEntityManager()->getEntity('User', $case->get('assignedUserId'));
$params = [
'caseDistribution' => $inboundEmail->get('caseDistribution'),
'teamId' => $inboundEmail->get('teamId'),
'userId' => $inboundEmail->get('assignToUserId'),
'targetUserPosition' => $inboundEmail->get('targetUserPosition'),
'inboundEmailId' => $inboundEmail->id,
];
$this->getServiceFactory()->create('Stream')->noteEmailReceived($case, $email, true);
$case = $this->emailToCase($email, $params);
if ($inboundEmail->get('reply')) {
$this->autoReply($inboundEmail, $email, $case, $user);
}
$user = $this->getEntityManager()->getEntity('User', $case->get('assignedUserId'));
$this->getServiceFactory()->create('Stream')->noteEmailReceived($case, $email, true);
if ($inboundEmail->get('reply')) {
$this->autoReply($inboundEmail, $email, $case, $user);
}
}
@@ -581,6 +627,7 @@ class InboundEmail extends \Espo\Services\Record implements
protected function assignLeastBusy(Entity $case, Team $team, $targetUserPosition)
{
$className = 'Espo\\Custom\\Business\\Distribution\\CaseObj\\LeastBusy';
if (!class_exists($className)) {
$className = 'Espo\\Modules\\Crm\\Business\\Distribution\\CaseObj\\LeastBusy';
}
@@ -595,10 +642,12 @@ class InboundEmail extends \Espo\Services\Record implements
}
}
protected function emailToCase(\Espo\Entities\Email $email, array $params = [])
protected function emailToCase(EmailEntity $email, array $params = [])
{
$case = $this->getEntityManager()->getEntity('Case');
$case->populateDefaults();
$case->set('name', $email->get('name'));
$bodyPlain = $email->getBodyPlain();
@@ -616,8 +665,13 @@ class InboundEmail extends \Espo\Services\Record implements
foreach ($attachmentIdList as $attachmentId) {
$attachment = $this->getEntityManager()->getRepository('Attachment')->get($attachmentId);
if (!$attachment) continue;
if (!$attachment) {
continue;
}
$copiedAttachment = $this->getEntityManager()->getRepository('Attachment')->getCopiedAttachment($attachment);
$copiedAttachmentIdList[] = $copiedAttachment->id;
}
@@ -626,6 +680,7 @@ class InboundEmail extends \Espo\Services\Record implements
}
$userId = null;
if (!empty($params['userId'])) {
$userId = $params['userId'];
}
@@ -635,19 +690,23 @@ class InboundEmail extends \Espo\Services\Record implements
}
$teamId = false;
if (!empty($params['teamId'])) {
$teamId = $params['teamId'];
}
if ($teamId) {
$case->set('teamsIds', [$teamId]);
}
$caseDistribution = '';
if (!empty($params['caseDistribution'])) {
$caseDistribution = $params['caseDistribution'];
}
$targetUserPosition = null;
if (!empty($params['targetUserPosition'])) {
$targetUserPosition = $params['targetUserPosition'];
}
@@ -660,21 +719,26 @@ class InboundEmail extends \Espo\Services\Record implements
$case->set('status', 'Assigned');
}
break;
case 'Round-Robin':
if ($teamId) {
$team = $this->getEntityManager()->getEntity('Team', $teamId);
if ($team) {
$this->assignRoundRobin($case, $team, $targetUserPosition);
}
}
break;
case 'Least-Busy':
if ($teamId) {
$team = $this->getEntityManager()->getEntity('Team', $teamId);
if ($team) {
$this->assignLeastBusy($case, $team, $targetUserPosition);
}
}
break;
}
@@ -686,18 +750,26 @@ class InboundEmail extends \Espo\Services\Record implements
$case->set('accountId', $email->get('accountId'));
}
$contact = $this->getEntityManager()->getRepository('Contact')->join('emailAddresses', 'emailAddressesMultiple')->where([
'emailAddressesMultiple.id' => $email->get('fromEmailAddressId')
])->findOne();
$contact = $this->getEntityManager()
->getRepository('Contact')
->join('emailAddresses', 'emailAddressesMultiple')
->where([
'emailAddressesMultiple.id' => $email->get('fromEmailAddressId')
])
->findOne();
if ($contact) {
$case->set('contactId', $contact->id);
} else {
if (!$case->get('accountId')) {
$lead = $this->getEntityManager()->getRepository('Lead')
->join('emailAddresses', 'emailAddressesMultiple')->where([
'emailAddressesMultiple.id' => $email->get('fromEmailAddressId')
])->findOne();
$lead = $this->getEntityManager()
->getRepository('Lead')
->join('emailAddresses', 'emailAddressesMultiple')
->where([
'emailAddressesMultiple.id' => $email->get('fromEmailAddressId')
])
->findOne();
if ($lead) {
$case->set('leadId', $lead->id);
}
@@ -731,11 +803,15 @@ class InboundEmail extends \Espo\Services\Record implements
$emailAddress = $this->getEntityManager()->getRepository('EmailAddress')->getByAddress($email->get('from'));
$sent = $this->getEntityManager()->getRepository('Email')->where([
'toEmailAddresses.id' => $emailAddress->id,
'dateSent>' => $threshold,
'status' => 'Sent'
])->join('toEmailAddresses')->findOne();
$sent = $this->getEntityManager()
->getRepository('Email')
->where([
'toEmailAddresses.id' => $emailAddress->id,
'dateSent>' => $threshold,
'status' => 'Sent',
])
->join('toEmailAddresses')
->findOne();
if ($sent) {
return false;
@@ -745,15 +821,20 @@ class InboundEmail extends \Espo\Services\Record implements
$replyEmailTemplateId = $inboundEmail->get('replyEmailTemplateId');
if ($replyEmailTemplateId) {
$entityHash = [];
if ($case) {
$entityHash['Case'] = $case;
if ($case->get('contactId')) {
$contact = $this->getEntityManager()->getEntity('Contact', $case->get('contactId'));
}
}
if (empty($contact)) {
$contact = $this->getEntityManager()->getEntity('Contact');
$fromName = \Espo\Services\Email::parseFromName($email->get('fromString'));
$fromName = EmailService::parseFromName($email->get('fromString'));
if (!empty($fromName)) {
$contact->set('name', $fromName);
}
@@ -771,11 +852,13 @@ class InboundEmail extends \Espo\Services\Record implements
$replyData = $emailTemplateService->parse($replyEmailTemplateId, ['entityHash' => $entityHash], true);
$subject = $replyData['subject'];
if ($case) {
$subject = '[#' . $case->get('number'). '] ' . $subject;
}
$reply = $this->getEntityManager()->getEntity('Email');
$reply->set('to', $email->get('from'));
$reply->set('subject', $subject);
$reply->set('body', $replyData['body']);
@@ -829,7 +912,6 @@ class InboundEmail extends \Espo\Services\Record implements
return true;
}
} catch (Exception $e) {}
}
@@ -844,9 +926,11 @@ class InboundEmail extends \Espo\Services\Record implements
$smtpParams['security'] = $emailAccount->get('smtpSecurity');
$smtpParams['username'] = $emailAccount->get('smtpUsername');
$smtpParams['password'] = $emailAccount->get('smtpPassword');
if (array_key_exists('password', $smtpParams)) {
$smtpParams['password'] = $this->getCrypt()->decrypt($smtpParams['password']);
}
return $smtpParams;
}
@@ -858,6 +942,7 @@ class InboundEmail extends \Espo\Services\Record implements
$content = $message->getRawContent();
$isHard = false;
if (preg_match('/permanent[ ]*[error|failure]/', $content)) {
$isHard = true;
}
@@ -876,15 +961,21 @@ class InboundEmail extends \Espo\Services\Record implements
}
}
if (!$queueItemId) return false;
if (!$queueItemId) {
return false;
}
$queueItem = $this->getEntityManager()->getEntity('EmailQueueItem', $queueItemId);
if (!$queueItem) return false;
if (!$queueItem) {
return false;
}
$massEmailId = $queueItem->get('massEmailId');
$massEmail = $this->getEntityManager()->getEntity('MassEmail', $massEmailId);
$campaignId = null;
if ($massEmail) {
$campaignId = $massEmail->get('campaignId');
}
@@ -898,12 +989,15 @@ class InboundEmail extends \Espo\Services\Record implements
if ($isHard && $emailAddress) {
$emailAddressEntity = $this->getEntityManager()->getRepository('EmailAddress')->getByAddress($emailAddress);
$emailAddressEntity->set('invalid', true);
$this->getEntityManager()->saveEntity($emailAddressEntity);
}
if ($campaignId && $target && $target->id) {
$this->getCampaignService()
->logBounced($campaignId, $queueItemId, $target, $emailAddress, $isHard, null, $queueItem->get('isTest'));
->logBounced(
$campaignId, $queueItemId, $target, $emailAddress, $isHard, null, $queueItem->get('isTest')
);
}
return true;
@@ -918,14 +1012,17 @@ class InboundEmail extends \Espo\Services\Record implements
return $this->campaignService;
}
public function findAccountForSending(string $emailAddress) : ?\Espo\Entities\InboundEmail
public function findAccountForSending(string $emailAddress) : ?InboundEmailEntity
{
$inboundEmail = $this->getEntityManager()->getRepository('InboundEmail')->where([
'status' => 'Active',
'useSmtp' => true,
'smtpHost!=' => null,
'emailAddress' => $emailAddress,
])->findOne();
$inboundEmail = $this->getEntityManager()
->getRepository('InboundEmail')
->where([
'status' => 'Active',
'useSmtp' => true,
'smtpHost!=' => null,
'emailAddress' => $emailAddress,
])
->findOne();
return $inboundEmail;
}
@@ -933,6 +1030,7 @@ class InboundEmail extends \Espo\Services\Record implements
public function findSharedAccountForUser(User $user, $emailAddress)
{
$groupEmailAccountPermission = $this->getAclManager()->get($user, 'groupEmailAccountPermission');
$teamIdList = $user->getLinkMultipleIdList('teams');
$inboundEmail = null;
@@ -941,17 +1039,20 @@ class InboundEmail extends \Espo\Services\Record implements
if ($groupEmailAccountPermission && $groupEmailAccountPermission !== 'no') {
if ($groupEmailAccountPermission === 'team') {
if (!count($teamIdList)) return;
if (!count($teamIdList)) {
return;
}
$selectParams = [
'whereClause' => [
'status' => 'Active',
'useSmtp' => true,
'smtpIsShared' => true,
'teamsMiddle.teamId' => $teamIdList,
'emailAddress' => $emailAddress
'emailAddress' => $emailAddress,
],
'joins' => ['teams'],
'distinct' => true
'distinct' => true,
];
} else if ($groupEmailAccountPermission === 'all') {
$selectParams = [
@@ -959,7 +1060,7 @@ class InboundEmail extends \Espo\Services\Record implements
'status' => 'Active',
'useSmtp' => true,
'smtpIsShared' => true,
'emailAddress' => $emailAddress
'emailAddress' => $emailAddress,
]
];
}
@@ -967,6 +1068,7 @@ class InboundEmail extends \Espo\Services\Record implements
$inboundEmail = $this->getEntityManager()->getRepository('InboundEmail')->findOne($selectParams);
}
return $inboundEmail;
}
@@ -1034,9 +1136,11 @@ class InboundEmail extends \Espo\Services\Record implements
$storage = $this->getStorage($emailAccount);
$folder = $emailAccount->get('sentFolder');
if (empty($folder)) {
throw new Error("No sent folder for Email Account: " . $emailAccount->id . ".");
}
$storage->appendMessage($message->toString(), $folder);
}
@@ -1044,6 +1148,7 @@ class InboundEmail extends \Espo\Services\Record implements
{
$smtpParams = [];
$smtpParams['server'] = $emailAccount->get('smtpHost');
if ($smtpParams['server']) {
$smtpParams['port'] = $emailAccount->get('smtpPort');
$smtpParams['auth'] = $emailAccount->get('smtpAuth');
@@ -1058,9 +1163,11 @@ class InboundEmail extends \Espo\Services\Record implements
if ($emailAccount->get('fromName')) {
$smtpParams['fromName'] = $emailAccount->get('fromName');
}
if ($emailAccount->get('emailAddress')) {
$smtpParams['fromAddress'] = $emailAccount->get('emailAddress');
}
if (array_key_exists('password', $smtpParams) && is_string($smtpParams['password'])) {
$smtpParams['password'] = $this->getCrypt()->decrypt($smtpParams['password']);
}
@@ -1077,7 +1184,9 @@ class InboundEmail extends \Espo\Services\Record implements
{
$handlerClassName = $emailAccount->get('smtpHandler');
if (!$handlerClassName) return;
if (!$handlerClassName) {
return;
}
try {
$handler = $this->injectableFactory->create($handlerClassName);
@@ -9,4 +9,4 @@
</div>
{{/if}}
<div class="edit-container">{{{edit}}}</div>
<div class="edit-container record">{{{edit}}}</div>
@@ -26,7 +26,7 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
Espo.define('crm:views/calendar/modals/edit', 'views/modals/edit', function (Dep) {
define('crm:views/calendar/modals/edit', 'views/modals/edit', function (Dep) {
return Dep.extend({
@@ -42,25 +42,32 @@ Espo.define('crm:views/calendar/modals/edit', 'views/modals/edit', function (Dep
return {
scopeList: this.scopeList,
scope: this.scope,
isNew: !(this.id)
isNew: !(this.id),
};
},
events: {
'change .scope-switcher input[name="scope"]': function () {
this.notify('Loading...');
var scope = $('.scope-switcher input[name="scope"]:checked').val();
this.scope = scope;
this.getModelFactory().create(this.scope, function (model) {
model.populateDefaults();
var attributes = this.getView('edit').fetch();
attributes = _.extend(attributes, this.getView('edit').model.toJSON());
model.set(attributes);
this.model = model;
this.createRecordView(model, function (view) {
view.render();
view.notify(false);
});
this.handleAccess(model);
}.bind(this));
},
@@ -75,11 +82,13 @@ Espo.define('crm:views/calendar/modals/edit', 'views/modals/edit', function (Dep
if (this.options.allDay) {
var allDayScopeList = this.getMetadata().get('clientDefs.Calendar.allDayScopeList') || [];
if (~allDayScopeList.indexOf(this.scope)) {
this.model.set('dateStart', null);
this.model.set('dateEnd', null);
this.model.set('dateStartDate', null);
this.model.set('dateEndDate', this.options.dateEndDate);
if (this.options.dateEndDate !== this.options.dateStartDate) {
this.model.set('dateStartDate', this.options.dateStartDate)
}
@@ -102,7 +111,9 @@ Espo.define('crm:views/calendar/modals/edit', 'views/modals/edit', function (Dep
this.dateIsChanged = true;
}
}, this);
this.listenTo(this.model, 'change:dateEnd', function (m, value, o) {
this.listenTo(
this.model, 'change:dateEnd', function (m, value, o) {
if (o.ui || o.updatedByDuration) {
this.dateIsChanged = true;
}
@@ -115,6 +126,7 @@ Espo.define('crm:views/calendar/modals/edit', 'views/modals/edit', function (Dep
if (this.id && !this.getAcl().checkModel(model, 'edit') || !this.id && !this.getAcl().checkModel(model, 'create')) {
this.hideButton('save');
this.hideButton('fullForm');
this.$el.find('button[data-name="save"]').addClass('hidden');
this.$el.find('button[data-name="fullForm"]').addClass('hidden');
} else {
@@ -131,8 +143,10 @@ Espo.define('crm:views/calendar/modals/edit', 'views/modals/edit', function (Dep
afterRender: function () {
Dep.prototype.afterRender.call(this);
if (this.hasView('edit')) {
var model = this.getView('edit').model;
if (model) {
this.handleAccess(model);
}
@@ -145,6 +159,7 @@ Espo.define('crm:views/calendar/modals/edit', 'views/modals/edit', function (Dep
if (!this.options.id && !this.options.scope) {
var scopeList = [];
this.scopeList.forEach(function (scope) {
if (this.getAcl().check(scope, 'create')) {
if (~this.enabledScopeList.indexOf(scope)) {
@@ -152,6 +167,7 @@ Espo.define('crm:views/calendar/modals/edit', 'views/modals/edit', function (Dep
}
}
}, this);
this.scopeList = scopeList;
var calendarDefaultEntity = scopeList[0];
@@ -187,6 +203,7 @@ Espo.define('crm:views/calendar/modals/edit', 'views/modals/edit', function (Dep
this.confirm(this.translate('removeRecordConfirmation', 'messages'), function () {
var $buttons = this.dialog.$el.find('.modal-footer button');
$buttons.addClass('disabled');
model.destroy({
success: function () {
this.trigger('after:destroy', model);
@@ -194,10 +211,9 @@ Espo.define('crm:views/calendar/modals/edit', 'views/modals/edit', function (Dep
}.bind(this),
error: function () {
$buttons.removeClass('disabled');
}
},
});
}, this);
}
},
});
});
+17 -1
View File
@@ -142,7 +142,10 @@ define('ui', [], function () {
if (this.removeOnClose) {
this.$el.on('hidden.bs.modal', function (e) {
if (this.$el.get(0) == e.target) {
if (this.skipRemove) return;
if (this.skipRemove) {
return;
}
this.remove();
}
}.bind(this));
@@ -324,11 +327,22 @@ define('ui', [], function () {
$('body > .popover').addClass('hidden');
};
Dialog.prototype.hide = function () {
this.$el.find('.modal-content').addClass('hidden');
};
Dialog.prototype.hideWithBackdrop = function () {
var $modalBackdrop = $('.modal-backdrop');
$modalBackdrop.last().addClass('hidden');
$($modalBackdrop.get($modalBackdrop.length - 2)).removeClass('hidden');
var $modalConainer = $('.modal-container');
$($modalConainer.get($modalConainer.length - 2)).removeClass('overlaid');
this.skipRemove = true;
setTimeout(function () {
this.skipRemove = false;
}.bind(this), 50);
@@ -337,6 +351,7 @@ define('ui', [], function () {
this.$el.find('.modal-content').addClass('hidden');
};
Dialog.prototype.close = function () {
var $modalBackdrop = $('.modal-backdrop');
$modalBackdrop.last().removeClass('hidden');
@@ -347,6 +362,7 @@ define('ui', [], function () {
this.$el.modal('hide');
$(this).trigger('dialog:close');
};
Dialog.prototype.remove = function () {
this.onRemove();
this.$el.remove();
@@ -88,6 +88,7 @@ define('views/admin/field-manager/edit', ['view', 'model'], function (Dep, Model
this.model.set('tooltipText', this.getLanguage().translate(this.field, 'tooltips', this.scope));
}
} else {
this.model.scope = this.scope;
this.model.set('type', this.type);
}
@@ -0,0 +1,57 @@
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EspoCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/admin/field-manager/fields/date/after-before', 'views/fields/varchar', function (Dep) {
return Dep.extend({
setupOptions: function () {
Dep.prototype.setupOptions.call(this);
if (!this.model.scope) {
return;
}
var list = this.getFieldManager().getEntityTypeFieldList(
this.model.scope,
{
typeList: ['date', 'datetime', 'datetimeOptional'],
}
);
if (this.model.get('name')) {
list = list.filter(function (item) {
return item !== this.model.get('name');
}, this);
}
this.params.options = list;
},
});
});
+20 -1
View File
@@ -624,6 +624,10 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
var self = options.espoView;
var lang = options.langInfo;
if (!self) {
return;
}
context.memo('button.espoImage', function () {
var button = ui.button({
contents: options.espoImage.icon,
@@ -673,6 +677,10 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
var self = options.espoView;
var lang = options.langInfo;
if (!self) {
return;
}
this.show = function () {
var linkInfo = context.invoke('editor.getLinkInfo');
@@ -705,6 +713,10 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
var self = options.espoView;
var lang = options.langInfo;
if (!self) {
return;
}
var isMacLike = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);
context.memo('button.espoLink', function () {
@@ -721,7 +733,10 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
this.initialize = function () {};
this.destroy = function () {
if (!self) return;
if (!self) {
return;
}
self.clearView('dialogInsertLink');
}
@@ -757,6 +772,10 @@ define('views/fields/wysiwyg', ['views/fields/text', 'lib!Summernote'], function
var self = options.espoView;
var lang = options.langInfo;
if (!self) {
return;
}
this.$window = $(window);
this.$scrollbar = $('html, body');
+41 -2
View File
@@ -70,8 +70,13 @@ define('views/modals/compose-email', 'views/modals/edit', function (Dep) {
this.once('after:render', function () {
this.actionClose();
}, this);
return;
}
this.once('remove', function () {
this.dialogIsHidden = false;
}, this);
},
createRecordView: function (model, callback) {
@@ -99,18 +104,34 @@ define('views/modals/compose-email', 'views/modals/edit', function (Dep) {
var model = editView.model;
var afterSend = function () {
this.dialogIsHidden = false;
this.trigger('after:save', model);
this.trigger('after:send', model);
dialog.close();
this.stopListening(editView, 'before:save', beforeSave);
this.stopListening(editView, 'error:save', errorSave);
this.remove();
}.bind(this);
var beforeSave = function () {
dialog.hide();
this.dialogIsHidden = true;
dialog.hideWithBackdrop();
editView.setConfirmLeaveOut(false);
};
if (!this.forceRemoveIsInitiated) {
this.initiateForceRemove();
}
}.bind(this);
var errorSave = function () {
this.dialogIsHidden = false;
if (this.isRendered()) {
dialog.show();
}
@@ -169,5 +190,23 @@ define('views/modals/compose-email', 'views/modals/edit', function (Dep) {
editView.saveDraft();
},
initiateForceRemove: function () {
this.forceRemoveIsInitiated = true;
var parentView = this.getParentView();
if (!parentView) {
return true;
}
parentView.once('remove', function () {
if (!this.dialogIsHidden) {
return;
}
this.remove();
}, this);
},
});
});
+17 -3
View File
@@ -26,7 +26,7 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
Espo.define('views/modals/image-preview', ['views/modal', 'lib!exif'], function (Dep) {
define('views/modals/image-preview', ['views/modal', 'lib!exif'], function (Dep) {
return Dep.extend({
@@ -72,25 +72,29 @@ Espo.define('views/modals/image-preview', ['views/modal', 'lib!exif'], function
getImageUrl: function () {
var url = this.getBasePath() + '?entryPoint=image&id=' + this.options.id;
if (this.size) {
url += '&size=' + this.size;
}
if (this.getUser().get('portalId')) {
url += '&portalId=' + this.getUser().get('portalId');
}
return url;
},
getOriginalImageUrl: function () {
var url = this.getBasePath() + '?entryPoint=image&id=' + this.options.id;
if (this.getUser().get('portalId')) {
url += '&portalId=' + this.getUser().get('portalId');
}
return url;
},
onImageLoad: function () {
console.log(1);
},
afterRender: function () {
@@ -102,7 +106,12 @@ Espo.define('views/modals/image-preview', ['views/modal', 'lib!exif'], function
var imgEl = $img.get(0);
EXIF.getData(imgEl, function () {
if ($img.css('image-orientation') === 'from-image') {
return;
}
var orientation = EXIF.getTag(this, 'Orientation');
switch (orientation) {
case 2:
$img.addClass('transform-flip');
@@ -138,6 +147,7 @@ Espo.define('views/modals/image-preview', ['views/modal', 'lib!exif'], function
if (this.navigationEnabled) {
$img.css('cursor', 'pointer');
$img.click(function () {
this.switchToNext();
}.bind(this));
@@ -145,10 +155,12 @@ Espo.define('views/modals/image-preview', ['views/modal', 'lib!exif'], function
var manageSize = function () {
var width = $container.width();
$img.css('maxWidth', width);
}.bind(this);
$(window).off('resize.image-review');
$(window).on('resize.image-review', function () {
manageSize();
});
@@ -159,12 +171,12 @@ Espo.define('views/modals/image-preview', ['views/modal', 'lib!exif'], function
},
switchToNext: function () {
this.transformClassList.forEach(function (item) {
this.$img.removeClass(item);
}, this);
var index = -1;
this.imageList.forEach(function (d, i) {
if (d.id === this.options.id) {
index = i;
@@ -172,12 +184,14 @@ Espo.define('views/modals/image-preview', ['views/modal', 'lib!exif'], function
}, this);
index++;
if (index > this.imageList.length - 1) {
index = 0;
}
this.options.id = this.imageList[index].id
this.options.name = this.imageList[index].name;
this.reRender();
},
+23 -13
View File
@@ -410,32 +410,42 @@ class Installer
{
$this->auth();
$user = array(
$result = $this->createRecord('User', [
'id' => '1',
'userName' => $userName,
'password' => $this->getPasswordHash()->hash($password),
'lastName' => 'Admin',
'type' => 'admin',
);
]);
$result = $this->createRecord('User', $user);
return $result;
}
protected function saveAdminPreferences($preferences)
{
$data = [
$this->saveAdminPreferences([
'dateFormat' => '',
'timeFormat' => '',
'timeZone' => '',
'weekStart' => -1,
'defaultCurrency' => '',
'language' => '',
'thousandSeparator' => $preferences['thousandSeparator'] ?? ',',
'decimalMark' => $preferences['decimalMark'] ?? '.',
];
'thousandSeparator' => $this->getConfig()->get('thousandSeparator', ','),
'decimalMark' => $this->getConfig()->get('decimalMark', '.'),
]);
return $result;
}
protected function saveAdminPreferences($preferences)
{
$permittedSettingList = array(
'dateFormat',
'timeFormat',
'timeZone',
'weekStart',
'defaultCurrency',
'thousandSeparator',
'decimalMark',
'language',
);
$data = array_intersect_key($preferences, array_flip($permittedSettingList));
if (empty($data)) {
return true;
}
+3 -3
View File
@@ -100,7 +100,7 @@
{$langs['fields']['Thousand Separator']}
</label>
<div class="field field-thousandSeparator">
<input type="text" class="main-element form-control" name="thousandSeparator" value="{$fields['thousandSeparator'].value}">
<input type="text" class="main-element form-control" name="thousandSeparator" value="{$fields['thousandSeparator'].value}" maxlength="1">
</div>
</div>
@@ -108,8 +108,8 @@
<label class="field-label-decimalMark control-label">
{$langs['fields']['Decimal Mark']} *</label>
<div class="field field-decimalMark">
<input type="text" class="main-element form-control" name="decimalMark" value="{$fields['decimalMark'].value}">
</div>
<input type="text" class="main-element form-control" name="decimalMark" value="{$fields['decimalMark'].value}" maxlength="1">
</div>
</div>
</div>
+16 -4
View File
@@ -45,15 +45,21 @@ class Diff
}
getTagList () {
var dirInitial = process.cwd();
process.chdir(this.espoPath);
var tagsString = cp.execSync('git tag -l --sort=-v:refname').toString();
var tagList = tagsString.trim().split("\n");
process.chdir(dirInitial);
return tagList;
}
getPreviousVersionList () {
var dirInitial = process.cwd();
var version = (require(this.espoPath + '/package.json') || {}).version;
process.chdir(this.espoPath);
@@ -92,6 +98,8 @@ class Diff
}
}
process.chdir(dirInitial);
return versionFromList;
}
@@ -225,6 +233,9 @@ class Diff
}
}
var deletedFileList = this.getDeletedFileList(versionFrom);
var tagList = this.getTagList();
process.chdir(buildPath);
var fileList = [];
@@ -251,8 +262,6 @@ class Diff
fs.writeFileSync(diffBeforeUpgradeFolderPath, beforeUpgradeFileList.join('\n'));
}
var deletedFileList = this.getDeletedFileList(versionFrom);
if (beforeUpgradeFileList.length) {
cp.execSync(
'xargs -a ' + diffBeforeUpgradeFolderPath + ' cp -p --parents -t ' + upgradePath + '/beforeUpgradeFiles'
@@ -265,8 +274,6 @@ class Diff
}
}
var tagList = this.getTagList();
execute('xargs -a ' + diffFilePath + ' cp -p --parents -t ' + upgradePath + '/files' , function (stdout) {
var d = new Date();
@@ -442,6 +449,8 @@ class Diff
}
getDeletedFileList (versionFrom) {
var dirInitial = process.cwd();
process.chdir(this.espoPath);
var deletedFileList = this.getRepositoryDeletedFileList(versionFrom);
@@ -460,6 +469,7 @@ class Diff
deletedFileList = deletedFileList.filter(function (item) {
if (
item.indexOf('tests/') === 0 ||
item.indexOf('upgrades/') === 0 ||
item.indexOf('frontend/less') === 0
) {
return false;
@@ -468,6 +478,8 @@ class Diff
return true;
});
process.chdir(dirInitial);
return deletedFileList;
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "espocrm",
"version": "6.0.0-beta3",
"version": "6.0.0-beta4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "espocrm",
"version": "6.0.0-beta3",
"version": "6.0.0-beta4",
"description": "",
"main": "index.php",
"repository": {
+27
View File
@@ -34,6 +34,8 @@ class AfterUpgrade
$this->container = $container;
$this->processEmailAccountsUpdate();
$this->cleanupFiles();
}
protected function processEmailAccountsUpdate()
@@ -46,4 +48,29 @@ class AfterUpgrade
$pdo->exec($q1);
$pdo->exec($q2);
}
protected function cleanupFiles()
{
$fileManager = $this->container->get('fileManager');
$fileList = [
'application/Espo/Core/Loaders/ClientManager.php',
'client/res/templates/record/panels/default-side.tpl',
'application/Espo/Resources/templates/noteEmailRecieved',
];
foreach ($fileList as $file) {
if (is_dir($file)) {
$fileManager->removeInDir($file, true);
continue;
}
if (!file_exists($file)) {
continue;
}
unlink($file);
}
}
}
+21 -2
View File
@@ -94,6 +94,25 @@ class BeforeUpgrade
throw new Error($message);
}
}
$extension = $em->getRepository('Extension')
->where([
'name' => 'VoIP Integration',
'isInstalled' => true,
])
->findOne();
if ($extension) {
$version = $extension->get('version');
if (version_compare($version, '1.15.0', '<')) {
$message =
"EspoCRM 6.0.0 is not compatible with VoIP Integration extension of a version lower than 1.15.0. " .
"Please upgrade the extension or uninstall it. Then run the upgrade command again.";
throw new Error($message);
}
}
}
protected function processMyIsamCheck()
@@ -116,8 +135,8 @@ class BeforeUpgrade
$message =
"In v6.0 we have dropped a support of MyISAM engine for DB tables. " .
"You have the following tables that use MyISAM: {$tableListString}.{$lineBreak}" .
"Please change the engine to InnoDB for these tables then run upgrade again.{$lineBreak}" .
"You have the following tables that use MyISAM: {$tableListString}.{$lineBreak}{$lineBreak}" .
"Please change the engine to InnoDB for these tables then run upgrade again.{$lineBreak}{$lineBreak}" .
"See: {$linkString}.";
throw new Error($message);