mirror of
https://github.com/espocrm/espocrm.git
synced 2026-03-06 14:57:01 +00:00
Compare commits
152 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d4ada7ec2 | ||
|
|
1c31a6689f | ||
|
|
a839144796 | ||
|
|
87cbe603d2 | ||
|
|
ec96916013 | ||
|
|
2c811a4faa | ||
|
|
6e089c1e25 | ||
|
|
2e203341b7 | ||
|
|
5bea143bf0 | ||
|
|
732494e251 | ||
|
|
39e1303cbe | ||
|
|
62c3549004 | ||
|
|
9bcc942f0f | ||
|
|
e34ee34d7b | ||
|
|
dedef4b36f | ||
|
|
e6f6e0fcf1 | ||
|
|
11a9e2ab9c | ||
|
|
9077542f61 | ||
|
|
cb6faaa769 | ||
|
|
a209d5aaaf | ||
|
|
767cdc75ee | ||
|
|
3eef0e088a | ||
|
|
1e5ef6a070 | ||
|
|
a2edc3cf4e | ||
|
|
9a5dc7b4d1 | ||
|
|
7b0fd40d3e | ||
|
|
169df31cab | ||
|
|
44b0ba2f33 | ||
|
|
8d70956607 | ||
|
|
5ad20c8666 | ||
|
|
790d4a88b5 | ||
|
|
b72ac42068 | ||
|
|
0a379be049 | ||
|
|
e0e08a1c17 | ||
|
|
0d825120bb | ||
|
|
7b81b66b76 | ||
|
|
d39f4e2533 | ||
|
|
598a2f9f05 | ||
|
|
ce9089b838 | ||
|
|
45b06fc154 | ||
|
|
f44177a994 | ||
|
|
d91b13a7c1 | ||
|
|
bd1894322c | ||
|
|
90874535ea | ||
|
|
8c919dbca4 | ||
|
|
05223c5272 | ||
|
|
afee6d564b | ||
|
|
b4e879a369 | ||
|
|
de4d96e260 | ||
|
|
89056f61c2 | ||
|
|
afac29151c | ||
|
|
e54430fb1b | ||
|
|
7d8736b98c | ||
|
|
216e9419d4 | ||
|
|
359fdd4dab | ||
|
|
2044a87630 | ||
|
|
171feed28e | ||
|
|
92dbbbd390 | ||
|
|
3166cb862e | ||
|
|
b606cb2e04 | ||
|
|
724ef00d52 | ||
|
|
0b7857b495 | ||
|
|
a150eb7f0e | ||
|
|
4cb21a4fdb | ||
|
|
46e13b0269 | ||
|
|
d4d5138991 | ||
|
|
9fd00d9f0a | ||
|
|
9361938285 | ||
|
|
cb054b2f2b | ||
|
|
f8ff6e6cf5 | ||
|
|
918c1b2114 | ||
|
|
2026bcb021 | ||
|
|
ce5393155a | ||
|
|
6f4b752b10 | ||
|
|
2a5a453517 | ||
|
|
191bba7afc | ||
|
|
f50d2ef9e3 | ||
|
|
1ad744d151 | ||
|
|
ba0f86c8d4 | ||
|
|
372c84bfa3 | ||
|
|
6ec18950e4 | ||
|
|
6c3168a356 | ||
|
|
109ee17a47 | ||
|
|
21702b3c34 | ||
|
|
159a2ee99d | ||
|
|
d6151d33b4 | ||
|
|
2217e03fa8 | ||
|
|
794c7eb523 | ||
|
|
98f61c0c4b | ||
|
|
5f5a450d95 | ||
|
|
0ba9679a75 | ||
|
|
85e60d4e32 | ||
|
|
a074b8a214 | ||
|
|
ac593c1d3d | ||
|
|
170e62bc8b | ||
|
|
5d19ae42dc | ||
|
|
9f3fdd01bf | ||
|
|
65e94e237d | ||
|
|
7935bc59fe | ||
|
|
f49677b5c0 | ||
|
|
b69f829a3e | ||
|
|
13dfc90a1b | ||
|
|
6d49d39480 | ||
|
|
f473ea9cea | ||
|
|
db8536ac55 | ||
|
|
e402745a86 | ||
|
|
abcaaddc2f | ||
|
|
3ac375c95c | ||
|
|
56f65e0fc0 | ||
|
|
471df0034e | ||
|
|
a1b3be9ef3 | ||
|
|
c4f70482ac | ||
|
|
31a8fa387d | ||
|
|
a0d6cb9be4 | ||
|
|
4586d26bd6 | ||
|
|
1609adc766 | ||
|
|
aa0a9cf708 | ||
|
|
d7dfe5fea4 | ||
|
|
340ed5acec | ||
|
|
7ec3e38e6d | ||
|
|
879bf13809 | ||
|
|
4edf4ef9ea | ||
|
|
b44bbaffa2 | ||
|
|
4b24491fe4 | ||
|
|
96458ab26a | ||
|
|
4c562cb603 | ||
|
|
494227324a | ||
|
|
8eb2be46ca | ||
|
|
6d4b3f24cb | ||
|
|
a26436d3de | ||
|
|
cd7571387c | ||
|
|
741f7f65c2 | ||
|
|
1b3496edd9 | ||
|
|
356da4e70d | ||
|
|
cd6da3ba87 | ||
|
|
ba0a79cc9b | ||
|
|
f3deffb3f6 | ||
|
|
c76823f9ee | ||
|
|
8398cc4364 | ||
|
|
6ddda814c0 | ||
|
|
5b777d3f1e | ||
|
|
4f19109ba1 | ||
|
|
76ffa2def9 | ||
|
|
2fdc0a3a93 | ||
|
|
7f3b874061 | ||
|
|
d9315763a6 | ||
|
|
c732f30e40 | ||
|
|
793cb4b878 | ||
|
|
85c476c548 | ||
|
|
0dcc8d08d1 | ||
|
|
da7635f68f | ||
|
|
2fc66f14f3 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -15,6 +15,7 @@
|
||||
/client/css/violet.css
|
||||
/client/css/violet-vertical.css
|
||||
/client/css/espo-rtl.css
|
||||
/client/css/hazyblue.css
|
||||
/client/css/hazyblue-vertical.css
|
||||
|
||||
/tests/unit/testData/cache/*
|
||||
|
||||
@@ -92,6 +92,14 @@ module.exports = function (grunt) {
|
||||
'client/css/hazyblue-vertical.css': 'frontend/less/hazyblue-vertical/main.less',
|
||||
}
|
||||
},
|
||||
hazyblue: {
|
||||
options: {
|
||||
yuicompress: true,
|
||||
},
|
||||
files: {
|
||||
'client/css/hazyblue.css': 'frontend/less/hazyblue/main.less',
|
||||
}
|
||||
},
|
||||
sakura: {
|
||||
options: {
|
||||
yuicompress: true,
|
||||
|
||||
@@ -54,7 +54,7 @@ class Attachment extends \Espo\Core\Controllers\Record
|
||||
|
||||
$attachment = $this->getEntityManager()->getEntity('Attachment');
|
||||
$this->getEntityManager()->saveEntity($attachment);
|
||||
$this->getContainer()->get('fileManager')->putContents('data/upload/' . $attachment->id, $contents);
|
||||
$this->getContainer()->get('fileStorageManager')->putContents($attachment, $contents);
|
||||
|
||||
return array(
|
||||
'attachmentId' => $attachment->id
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
namespace Espo\Controllers;
|
||||
|
||||
use \Espo\Core\Exceptions\Error,
|
||||
\Espo\Core\Exceptions\Forbidden,
|
||||
\Espo\Core\Exceptions\NotFound,
|
||||
\Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
|
||||
class FieldManager extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
@@ -49,7 +49,7 @@ class FieldManager extends \Espo\Core\Controllers\Base
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$data = $this->getContainer()->get('fieldManager')->read($params['name'], $params['scope']);
|
||||
$data = $this->getContainer()->get('fieldManager')->read($params['scope'], $params['name']);
|
||||
|
||||
if (!isset($data)) {
|
||||
throw new BadRequest();
|
||||
@@ -65,16 +65,16 @@ class FieldManager extends \Espo\Core\Controllers\Base
|
||||
}
|
||||
|
||||
$fieldManager = $this->getContainer()->get('fieldManager');
|
||||
$fieldManager->create($data['name'], $data, $params['scope']);
|
||||
$fieldManager->create($params['scope'], $data['name'], $data);
|
||||
|
||||
try {
|
||||
$this->getContainer()->get('dataManager')->rebuild($params['scope']);
|
||||
} catch (Error $e) {
|
||||
$fieldManager->delete($data['name'], $params['scope']);
|
||||
$fieldManager->delete($params['scope'], $data['name']);
|
||||
throw new Error($e->getMessage());
|
||||
}
|
||||
|
||||
return $fieldManager->read($data['name'], $params['scope']);
|
||||
return $fieldManager->read($params['scope'], $data['name']);
|
||||
}
|
||||
|
||||
public function putActionUpdate($params, $data)
|
||||
@@ -84,7 +84,7 @@ class FieldManager extends \Espo\Core\Controllers\Base
|
||||
}
|
||||
|
||||
$fieldManager = $this->getContainer()->get('fieldManager');
|
||||
$fieldManager->update($params['name'], $data, $params['scope']);
|
||||
$fieldManager->update($params['scope'], $params['name'], $data);
|
||||
|
||||
if ($fieldManager->isChanged()) {
|
||||
$this->getContainer()->get('dataManager')->rebuild($params['scope']);
|
||||
@@ -92,7 +92,7 @@ class FieldManager extends \Espo\Core\Controllers\Base
|
||||
$this->getContainer()->get('dataManager')->clearCache();
|
||||
}
|
||||
|
||||
return $fieldManager->read($params['name'], $params['scope']);
|
||||
return $fieldManager->read($params['scope'], $params['name']);
|
||||
}
|
||||
|
||||
public function deleteActionDelete($params, $data)
|
||||
@@ -101,11 +101,11 @@ class FieldManager extends \Espo\Core\Controllers\Base
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$res = $this->getContainer()->get('fieldManager')->delete($params['name'], $params['scope']);
|
||||
$result = $this->getContainer()->get('fieldManager')->delete($params['scope'], $params['name']);
|
||||
|
||||
$this->getContainer()->get('dataManager')->rebuildMetadata();
|
||||
|
||||
return $res;
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function postActionResetToDefault($params, $data)
|
||||
@@ -114,7 +114,7 @@ class FieldManager extends \Espo\Core\Controllers\Base
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$this->getContainer()->get('fieldManager')->resetToDefault($data['name'], $data['scope']);
|
||||
$this->getContainer()->get('fieldManager')->resetToDefault($data['scope'], $data['name']);
|
||||
|
||||
$this->getContainer()->get('dataManager')->rebuildMetadata();
|
||||
|
||||
|
||||
@@ -68,9 +68,9 @@ class Import extends \Espo\Core\Controllers\Record
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
protected function getFileManager()
|
||||
protected function getFileStorageManager()
|
||||
{
|
||||
return $this->getContainer()->get('fileManager');
|
||||
return $this->getContainer()->get('fileStorageManager');
|
||||
}
|
||||
|
||||
protected function getEntityManager()
|
||||
@@ -92,7 +92,7 @@ class Import extends \Espo\Core\Controllers\Record
|
||||
$attachment->set('name', 'import-file.csv');
|
||||
$this->getEntityManager()->saveEntity($attachment);
|
||||
|
||||
$this->getFileManager()->putContents('data/upload/' . $attachment->id, $contents);
|
||||
$this->getFileStorageManager()->putContents($attachment, $contents);
|
||||
|
||||
return array(
|
||||
'attachmentId' => $attachment->id
|
||||
@@ -167,12 +167,18 @@ class Import extends \Espo\Core\Controllers\Record
|
||||
throw new BadRequest();
|
||||
}
|
||||
|
||||
$timezone = 'UTC';
|
||||
if (isset($data['timezone'])) {
|
||||
$timezone = $data['timezone'];
|
||||
}
|
||||
|
||||
$importParams = array(
|
||||
'headerRow' => !empty($data['headerRow']),
|
||||
'fieldDelimiter' => $data['fieldDelimiter'],
|
||||
'textQualifier' => $data['textQualifier'],
|
||||
'dateFormat' => $data['dateFormat'],
|
||||
'timeFormat' => $data['timeFormat'],
|
||||
'timezone' => $timezone,
|
||||
'personNameFormat' => $data['personNameFormat'],
|
||||
'decimalMark' => $data['decimalMark'],
|
||||
'currency' => $data['currency'],
|
||||
|
||||
@@ -33,11 +33,10 @@ use \Espo\Core\Exceptions\Forbidden;
|
||||
|
||||
class Metadata extends \Espo\Core\Controllers\Base
|
||||
{
|
||||
|
||||
public function actionRead($params, $data)
|
||||
{
|
||||
$data = $this->getMetadata()->getAll();
|
||||
unset($data['formula']);
|
||||
return $data;
|
||||
return $this->getMetadata()->getAllForFrontend();
|
||||
}
|
||||
|
||||
public function getActionGet($params, $data, $request)
|
||||
|
||||
@@ -128,6 +128,14 @@ class Container
|
||||
return new \Espo\Core\Utils\Api\Slim();
|
||||
}
|
||||
|
||||
protected function loadFileStorageManager()
|
||||
{
|
||||
return new \Espo\Core\FileStorage\Manager(
|
||||
$this->get('metadata')->get(['app', 'fileStorage', 'implementationClassNameMap']),
|
||||
$this
|
||||
);
|
||||
}
|
||||
|
||||
protected function loadFileManager()
|
||||
{
|
||||
return new \Espo\Core\Utils\File\Manager(
|
||||
@@ -343,6 +351,13 @@ class Container
|
||||
);
|
||||
}
|
||||
|
||||
protected function loadInjectableFactory()
|
||||
{
|
||||
return new \Espo\Core\InjectableFactory(
|
||||
$this
|
||||
);
|
||||
}
|
||||
|
||||
public function setUser(\Espo\Entities\User $user)
|
||||
{
|
||||
$this->set('user', $user);
|
||||
|
||||
115
application/Espo/Core/FileStorage/Manager.php
Normal file
115
application/Espo/Core/FileStorage/Manager.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://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.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FileStorage;
|
||||
|
||||
use \Espo\Entities\Attachment;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class Manager
|
||||
{
|
||||
private $implementations = array();
|
||||
|
||||
private $implementationClassNameMap = array();
|
||||
|
||||
private $container;
|
||||
|
||||
public function __construct(array $implementationClassNameMap, $container)
|
||||
{
|
||||
$this->implementationClassNameMap = $implementationClassNameMap;
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
private function getImplementation($storage = null)
|
||||
{
|
||||
if (!$storage) {
|
||||
$storage = 'EspoUploadDir';
|
||||
}
|
||||
|
||||
if (array_key_exists($storage, $this->implementations)) {
|
||||
return $this->implementations[$storage];
|
||||
}
|
||||
|
||||
if (!array_key_exists($storage, $this->implementationClassNameMap)) {
|
||||
throw new Error("FileStorageManager: Unknown storage '{$storage}'");
|
||||
}
|
||||
$className = $this->implementationClassNameMap[$storage];
|
||||
|
||||
$implementation = new $className();
|
||||
foreach ($implementation->getDependencyList() as $dependencyName) {
|
||||
$implementation->inject($dependencyName, $this->container->get($dependencyName));
|
||||
}
|
||||
$this->implementations[$storage] = $implementation;
|
||||
|
||||
return $implementation;
|
||||
}
|
||||
|
||||
public function isFile(Attachment $attachment)
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment->get('storage'));
|
||||
return $implementation->isFile($attachment);
|
||||
}
|
||||
|
||||
public function getContents(Attachment $attachment)
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment->get('storage'));
|
||||
return $implementation->getContents($attachment);
|
||||
}
|
||||
|
||||
public function putContents(Attachment $attachment, $contents)
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment->get('storage'));
|
||||
return $implementation->putContents($attachment, $contents);
|
||||
}
|
||||
|
||||
public function unlink(Attachment $attachment)
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment->get('storage'));
|
||||
return $implementation->unlink($attachment);
|
||||
}
|
||||
|
||||
public function getLocalFilePath(Attachment $attachment)
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment->get('storage'));
|
||||
return $implementation->getLocalFilePath($attachment);
|
||||
}
|
||||
|
||||
public function hasDownloadUrl(Attachment $attachment)
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment->get('storage'));
|
||||
return $implementation->hasDownloadUrl($attachment);
|
||||
}
|
||||
|
||||
public function getDownloadUrl(Attachment $attachment)
|
||||
{
|
||||
$implementation = $this->getImplementation($attachment->get('storage'));
|
||||
return $implementation->getDownloadUrl($attachment);
|
||||
}
|
||||
}
|
||||
89
application/Espo/Core/FileStorage/Storages/Base.php
Normal file
89
application/Espo/Core/FileStorage/Storages/Base.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://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.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FileStorage\Storages;
|
||||
|
||||
use \Espo\Core\Interfaces\Injectable;
|
||||
|
||||
abstract class Base implements Injectable
|
||||
{
|
||||
protected $dependencyList = [];
|
||||
|
||||
protected $injections = array();
|
||||
|
||||
public function inject($name, $object)
|
||||
{
|
||||
$this->injections[$name] = $object;
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->init();
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
}
|
||||
|
||||
protected function getInjection($name)
|
||||
{
|
||||
return $this->injections[$name];
|
||||
}
|
||||
|
||||
protected function addDependency($name)
|
||||
{
|
||||
$this->dependencyList[] = $name;
|
||||
}
|
||||
|
||||
protected function addDependencyList(array $list)
|
||||
{
|
||||
foreach ($list as $item) {
|
||||
$this->addDependency($item);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDependencyList()
|
||||
{
|
||||
return $this->dependencyList;
|
||||
}
|
||||
|
||||
abstract public function hasDownloadUrl(\Espo\Entities\Attachment $attachment);
|
||||
|
||||
abstract public function getDownloadUrl(\Espo\Entities\Attachment $attachment);
|
||||
|
||||
abstract public function unlink(\Espo\Entities\Attachment $attachment);
|
||||
|
||||
abstract public function getContents(\Espo\Entities\Attachment $attachment);
|
||||
|
||||
abstract public function isFile(\Espo\Entities\Attachment $attachment);
|
||||
|
||||
abstract public function putContents(\Espo\Entities\Attachment $attachment, $contents);
|
||||
|
||||
abstract public function getLocalFilePath(\Espo\Entities\Attachment $attachment);
|
||||
}
|
||||
85
application/Espo/Core/FileStorage/Storages/EspoUploadDir.php
Normal file
85
application/Espo/Core/FileStorage/Storages/EspoUploadDir.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://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.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\FileStorage\Storages;
|
||||
|
||||
use \Espo\Entities\Attachment;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class EspoUploadDir extends Base
|
||||
{
|
||||
protected $dependencyList = ['fileManager'];
|
||||
|
||||
protected function getFileManager()
|
||||
{
|
||||
return $this->getInjection('fileManager');
|
||||
}
|
||||
|
||||
public function unlink(Attachment $attachment)
|
||||
{
|
||||
return $this->getFileManager()->unlink($this->getFilePath($attachment));
|
||||
}
|
||||
|
||||
public function isFile(Attachment $attachment)
|
||||
{
|
||||
return $this->getFileManager()->isFile($this->getFilePath($attachment));
|
||||
}
|
||||
|
||||
public function getContents(Attachment $attachment)
|
||||
{
|
||||
return $this->getFileManager()->getContents($this->getFilePath($attachment));
|
||||
}
|
||||
|
||||
public function putContents(Attachment $attachment, $contents)
|
||||
{
|
||||
return $this->getFileManager()->putContents($this->getFilePath($attachment), $contents);
|
||||
}
|
||||
|
||||
public function getLocalFilePath(Attachment $attachment)
|
||||
{
|
||||
return $this->getFilePath($attachment);
|
||||
}
|
||||
|
||||
protected function getFilePath(Attachment $attachment)
|
||||
{
|
||||
$sourceId = $attachment->getSourceId();
|
||||
return 'data/upload/' . $sourceId;
|
||||
}
|
||||
|
||||
public function getDownloadUrl(Attachment $attachment)
|
||||
{
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
public function hasDownloadUrl(Attachment $attachment)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
@@ -65,6 +65,13 @@ class AttributeFetcher
|
||||
$methodName = 'getFetched';
|
||||
}
|
||||
|
||||
if ($entity->getAttributeParam($attribute, 'isParentName') && $methodName == 'get') {
|
||||
$relationName = $entity->getAttributeParam($attribute, 'relation');
|
||||
if ($parent = $entity->get($relationName)) {
|
||||
return $parent->get('name');
|
||||
}
|
||||
}
|
||||
|
||||
return $entity->$methodName($attribute);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://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.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Formula\Functions\DatetimeGroup;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class DiffType extends \Espo\Core\Formula\Functions\Base
|
||||
{
|
||||
protected function init()
|
||||
{
|
||||
$this->addDependency('dateTime');
|
||||
}
|
||||
|
||||
protected $intevalTypePropertyMap = array(
|
||||
'years' => 'y', 'months' => 'm', 'days' => 'd', 'hours' => 'h', 'minutes' => 'i', 'seconds' => 's'
|
||||
);
|
||||
|
||||
public function process(\StdClass $item)
|
||||
{
|
||||
if (!property_exists($item, 'value')) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (!is_array($item->value)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (count($item->value) < 2) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$dateTime1String = $this->evaluate($item->value[0]);
|
||||
$dateTime2String = $this->evaluate($item->value[1]);
|
||||
|
||||
if (!$dateTime1String) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$dateTime2String) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!is_string($dateTime1String)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (!is_string($dateTime2String)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$intervalType = 'days';
|
||||
if (count($item->value) > 2) {
|
||||
$intervalType = $this->evaluate($item->value[2]);
|
||||
}
|
||||
|
||||
if (!is_string($intervalType)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (!array_key_exists($intervalType, $this->intevalTypePropertyMap)) {
|
||||
throw new Error('Not supported interval type' . $intervalType);
|
||||
}
|
||||
|
||||
$property = $this->intevalTypePropertyMap[$intervalType];
|
||||
|
||||
$isTime = false;
|
||||
if (strlen($dateTime1String) > 10) {
|
||||
$isTime = true;
|
||||
}
|
||||
|
||||
try {
|
||||
$dateTime1 = new \DateTime($dateTime1String);
|
||||
$dateTime2 = new \DateTime($dateTime2String);
|
||||
} catch (\Exception $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$interval = $dateTime2->diff($dateTime1);
|
||||
|
||||
$number = $interval->$property;
|
||||
|
||||
if ($interval->invert) {
|
||||
$number *= -1;
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
@@ -58,10 +58,15 @@ class FormatType extends \Espo\Core\Formula\Functions\Base
|
||||
}
|
||||
$value = $this->evaluate($item->value[0]);
|
||||
|
||||
$format = null;
|
||||
if (count($item->value) > 2) {
|
||||
$format = $this->evaluate($item->value[2]);
|
||||
}
|
||||
|
||||
if (strlen($value) > 11) {
|
||||
return $this->getInjection('dateTime')->convertSystemDateTime($value, $timezone);
|
||||
return $this->getInjection('dateTime')->convertSystemDateTime($value, $timezone, $format);
|
||||
} else {
|
||||
return $this->getInjection('dateTime')->convertSystemDate($value);
|
||||
return $this->getInjection('dateTime')->convertSystemDate($value, $format);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
@@ -32,7 +32,7 @@ namespace Espo\Core\Formula\Functions\EntityGroup;
|
||||
use \Espo\ORM\Entity;
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class AttributeFetchedType extends \Espo\Core\Formula\Functions\AttributeType
|
||||
class AttributeFetchedType extends AttributeType
|
||||
{
|
||||
protected function getAttributeValue($attribute)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
@@ -34,4 +34,22 @@ use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class AttributeType extends \Espo\Core\Formula\Functions\AttributeType
|
||||
{
|
||||
public function process(\StdClass $item)
|
||||
{
|
||||
if (!property_exists($item, 'value')) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (!is_array($item->value)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (count($item->value) < 1) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$attribute = $this->evaluate($item->value[0]);
|
||||
|
||||
return $this->getAttributeValue($attribute);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
@@ -40,30 +40,21 @@ class IsAttributeChangedType extends \Espo\Core\Formula\Functions\Base
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$attributeList = [];
|
||||
if (is_array($item->value)) {
|
||||
$attributeList = $attribute;
|
||||
foreach ($item->value as $value) {
|
||||
$attribute = $this->evaluate($item->value);
|
||||
$attributeList[] = $attribute;
|
||||
}
|
||||
} else {
|
||||
$attribute = $this->evaluate($item->value);
|
||||
$attributeList[] = $attribute;
|
||||
if (!is_array($item->value)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
return $this->check($attributeList);
|
||||
if (count($item->value) < 1) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$attribute = $this->evaluate($item->value[0]);
|
||||
|
||||
return $this->check($attribute);
|
||||
}
|
||||
|
||||
protected function check(array $attributeList)
|
||||
protected function check($attribute)
|
||||
{
|
||||
$result = true;
|
||||
foreach ($attributeList as $i => $attribute) {
|
||||
if (!$this->getEntity()->isAttributeChanged($attribute)) {
|
||||
$result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
return $this->getEntity()->isAttributeChanged($attribute);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
@@ -33,8 +33,8 @@ use \Espo\ORM\Entity;
|
||||
|
||||
class IsAttributeNotChangedType extends IsAttributeChangedType
|
||||
{
|
||||
protected function check(array $attributeList)
|
||||
protected function check($attribute)
|
||||
{
|
||||
return !parent::check($attributeList);
|
||||
return !parent::check($attribute);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://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.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Formula\Functions\NumberGroup;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class AbsType extends \Espo\Core\Formula\Functions\Base
|
||||
{
|
||||
|
||||
public function process(\StdClass $item)
|
||||
{
|
||||
if (!property_exists($item, 'value')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!is_array($item->value)) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
if (count($item->value) < 1) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
$value = $this->evaluate($item->value[0]);
|
||||
|
||||
if (!is_numeric($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return abs($value);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
@@ -229,7 +229,11 @@ class Parser
|
||||
$possibleRightOperator = trim($operator . $expression[$index + 1]);
|
||||
}
|
||||
}
|
||||
if ($possibleRightOperator && $possibleRightOperator != $operator && $this->operatorMap[$possibleRightOperator]) continue;
|
||||
if (
|
||||
$possibleRightOperator &&
|
||||
$possibleRightOperator != $operator &&
|
||||
!empty($this->operatorMap[$possibleRightOperator])
|
||||
) continue;
|
||||
|
||||
$firstPart = substr($expression, 0, $index);
|
||||
$secondPart = substr($expression, $index + strlen($operator));
|
||||
|
||||
@@ -48,12 +48,15 @@ class Htmlizer
|
||||
|
||||
protected $acl;
|
||||
|
||||
public function __construct(FileManager $fileManager, DateTime $dateTime, NumberUtil $number, $acl = null)
|
||||
protected $entityManager;
|
||||
|
||||
public function __construct(FileManager $fileManager, DateTime $dateTime, NumberUtil $number, $acl = null, $entityManager = null)
|
||||
{
|
||||
$this->fileManager = $fileManager;
|
||||
$this->dateTime = $dateTime;
|
||||
$this->number = $number;
|
||||
$this->acl = $acl;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
protected function getAcl()
|
||||
@@ -61,6 +64,11 @@ class Htmlizer
|
||||
return $this->acl;
|
||||
}
|
||||
|
||||
protected function getEntityManager()
|
||||
{
|
||||
return $this->entityManager;
|
||||
}
|
||||
|
||||
protected function format($value)
|
||||
{
|
||||
if (is_float($value)) {
|
||||
@@ -163,7 +171,8 @@ class Htmlizer
|
||||
'helpers' => [
|
||||
'file' => function ($context, $options) {
|
||||
if (count($context) && $context[0]) {
|
||||
return 'data/upload/'.$context[0];
|
||||
$id = $context[0];
|
||||
return "?entryPoint=attachment&id=" . $id;
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -192,8 +201,20 @@ class Htmlizer
|
||||
|
||||
$html = $renderer($data);
|
||||
|
||||
|
||||
$html = str_replace('?entryPoint=attachment&', '?entryPoint=attachment&', $html);
|
||||
$html = preg_replace('/\?entryPoint=attachment\&id=(.*)/', 'data/upload/$1', $html);
|
||||
|
||||
if ($this->getEntityManager()) {
|
||||
$html = preg_replace_callback('/\?entryPoint=attachment\&id=([A-Za-z0-9]*)/', function ($matches) {
|
||||
$id = $matches[1];
|
||||
$attachment = $this->getEntityManager()->getEntity('Attachment', $id);
|
||||
|
||||
if ($attachment) {
|
||||
$filePath = $this->getEntityManager()->getRepository('Attachment')->getFilePath($attachment);
|
||||
return $filePath;
|
||||
}
|
||||
}, $html);
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
74
application/Espo/Core/Injectable.php
Normal file
74
application/Espo/Core/Injectable.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://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.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core;
|
||||
|
||||
abstract class Injectable implements \Espo\Core\Interfaces\Injectable
|
||||
{
|
||||
protected $dependencyList = array();
|
||||
|
||||
protected $injections = array();
|
||||
|
||||
public function inject($name, $object)
|
||||
{
|
||||
$this->injections[$name] = $object;
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->init();
|
||||
}
|
||||
|
||||
protected function init()
|
||||
{
|
||||
}
|
||||
|
||||
protected function getInjection($name)
|
||||
{
|
||||
return $this->injections[$name];
|
||||
}
|
||||
|
||||
protected function addDependency($name)
|
||||
{
|
||||
if (in_array($name, $this->dependencyList)) return;
|
||||
$this->dependencyList[] = $name;
|
||||
}
|
||||
|
||||
protected function addDependencyList(array $list)
|
||||
{
|
||||
foreach ($list as $item) {
|
||||
$this->addDependency($item);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDependencyList()
|
||||
{
|
||||
return $this->dependencyList;
|
||||
}
|
||||
}
|
||||
58
application/Espo/Core/InjectableFactory.php
Normal file
58
application/Espo/Core/InjectableFactory.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://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.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core;
|
||||
|
||||
use \Espo\Core\Exceptions\Error;
|
||||
|
||||
class InjectableFactory
|
||||
{
|
||||
private $container;
|
||||
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function createByClassName($className)
|
||||
{
|
||||
if (class_exists($className)) {
|
||||
$service = new $className();
|
||||
if (!($service instanceof \Espo\Core\Interfaces\Injectable)) {
|
||||
throw new Error("Class '$className' is not instance of Injectable interface");
|
||||
}
|
||||
$dependencyList = $service->getDependencyList();
|
||||
foreach ($dependencyList as $name) {
|
||||
$service->inject($name, $this->container->get($name));
|
||||
}
|
||||
return $service;
|
||||
}
|
||||
throw new Error("Class '$className' does not exist");
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,8 @@ class Base
|
||||
|
||||
protected $additionalFilterTypeList = ['linkedWith', 'inCategory', 'isUserFromTeams'];
|
||||
|
||||
protected $textFilterUseContainsAttributeList = [];
|
||||
|
||||
const MIN_LENGTH_FOR_CONTENT_SEARCH = 4;
|
||||
|
||||
public function __construct($entityManager, \Espo\Entities\User $user, Acl $acl, AclManager $aclManager, Metadata $metadata, Config $config)
|
||||
@@ -144,7 +146,7 @@ class Base
|
||||
$list = $this->getMetadata()->get(['entityDefs', $this->getEntityType(), 'fields', $sortBy, 'options']);
|
||||
if ($list && is_array($list) && count($list)) {
|
||||
if ($this->getMetadata()->get(['entityDefs', $this->getEntityType(), 'fields', $sortBy, 'isSorted'])) {
|
||||
$list = asort($list);
|
||||
asort($list);
|
||||
}
|
||||
if ($desc) {
|
||||
$list = array_reverse($list);
|
||||
@@ -1107,7 +1109,7 @@ class Base
|
||||
$quarter--;
|
||||
if ($quarter == 0) {
|
||||
$quarter = 4;
|
||||
$dt->sub('P1Y');
|
||||
$dt->modify('-1 year');
|
||||
}
|
||||
$part['AND'] = array(
|
||||
$attribute . '>=' => $dt->add(new \DateInterval('P'.(($quarter - 1) * 3).'M'))->format('Y-m-d'),
|
||||
@@ -1322,6 +1324,9 @@ class Base
|
||||
(
|
||||
!empty($fieldDefs[$field]['type']) && $fieldDefs[$field]['type'] == 'text'
|
||||
||
|
||||
!empty($this->textFilterUseContainsAttributeList[$field])
|
||||
||
|
||||
!empty($fieldDefs[$field]['type']) && $fieldDefs[$field]['type'] == 'varchar' &&
|
||||
$this->getConfig()->get('textFilterUseContainsForVarchar')
|
||||
)
|
||||
) {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
{
|
||||
"controller": "controllers/record",
|
||||
"boolFilterList": ["onlyMy"],
|
||||
"recordViews": {
|
||||
"detail": "views/templates/event/record/detail"
|
||||
},
|
||||
"activityDefs": {
|
||||
"activitiesCreate": true,
|
||||
"historyCreate": true
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
"end": "dateEnd",
|
||||
"options": [300, 600, 900, 1800, 2700, 3600, 7200],
|
||||
"default": 300,
|
||||
"notStorable": true
|
||||
"notStorable": true,
|
||||
"select": "TIMESTAMPDIFF(SECOND, {tableName}.date_start, {tableName}.date_end)",
|
||||
"orderBy": "duration {direction}"
|
||||
},
|
||||
"parent": {
|
||||
"type": "linkParent",
|
||||
@@ -44,7 +46,8 @@
|
||||
"reminders": {
|
||||
"type": "jsonArray",
|
||||
"notStorable": true,
|
||||
"view": "crm:views/meeting/fields/reminders"
|
||||
"view": "crm:views/meeting/fields/reminders",
|
||||
"layoutListDisabled": true
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "datetime",
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"dateStart": "Startdatum",
|
||||
"dateEnd": "Enddatum",
|
||||
"duration": "Dauer",
|
||||
"status": "Status"
|
||||
"status": "Status",
|
||||
"reminders": "Erinnerungen"
|
||||
},
|
||||
"links": {
|
||||
"parent": "Bezieht sich auf"
|
||||
|
||||
@@ -31,6 +31,89 @@ namespace Espo\Core\Utils\Api;
|
||||
|
||||
class Slim extends \Slim\Slim
|
||||
{
|
||||
public function __construct(array $userSettings = array())
|
||||
{
|
||||
// Setup IoC container
|
||||
$this->container = new \Slim\Helper\Set();
|
||||
$this->container['settings'] = array_merge(static::getDefaultSettings(), $userSettings);
|
||||
|
||||
// Default environment
|
||||
$this->container->singleton('environment', function ($c) {
|
||||
/* ESPOCRM: change Environment class */
|
||||
//return \Slim\Environment::getInstance();
|
||||
return \Espo\Core\Utils\Api\Slim\Environment::getInstance();
|
||||
/* ESPOCRM: end */
|
||||
});
|
||||
|
||||
// Default request
|
||||
$this->container->singleton('request', function ($c) {
|
||||
return new \Slim\Http\Request($c['environment']);
|
||||
});
|
||||
|
||||
// Default response
|
||||
$this->container->singleton('response', function ($c) {
|
||||
return new \Slim\Http\Response();
|
||||
});
|
||||
|
||||
// Default router
|
||||
$this->container->singleton('router', function ($c) {
|
||||
return new \Slim\Router();
|
||||
});
|
||||
|
||||
// Default view
|
||||
$this->container->singleton('view', function ($c) {
|
||||
$viewClass = $c['settings']['view'];
|
||||
$templatesPath = $c['settings']['templates.path'];
|
||||
|
||||
$view = ($viewClass instanceOf \Slim\View) ? $viewClass : new $viewClass;
|
||||
$view->setTemplatesDirectory($templatesPath);
|
||||
return $view;
|
||||
});
|
||||
|
||||
// Default log writer
|
||||
$this->container->singleton('logWriter', function ($c) {
|
||||
$logWriter = $c['settings']['log.writer'];
|
||||
|
||||
return is_object($logWriter) ? $logWriter : new \Slim\LogWriter($c['environment']['slim.errors']);
|
||||
});
|
||||
|
||||
// Default log
|
||||
$this->container->singleton('log', function ($c) {
|
||||
$log = new \Slim\Log($c['logWriter']);
|
||||
$log->setEnabled($c['settings']['log.enabled']);
|
||||
$log->setLevel($c['settings']['log.level']);
|
||||
$env = $c['environment'];
|
||||
$env['slim.log'] = $log;
|
||||
|
||||
return $log;
|
||||
});
|
||||
|
||||
// Default mode
|
||||
$this->container['mode'] = function ($c) {
|
||||
$mode = $c['settings']['mode'];
|
||||
|
||||
if (isset($_ENV['SLIM_MODE'])) {
|
||||
$mode = $_ENV['SLIM_MODE'];
|
||||
} else {
|
||||
$envMode = getenv('SLIM_MODE');
|
||||
if ($envMode !== false) {
|
||||
$mode = $envMode;
|
||||
}
|
||||
}
|
||||
|
||||
return $mode;
|
||||
};
|
||||
|
||||
// Define default middleware stack
|
||||
$this->middleware = array($this);
|
||||
$this->add(new \Slim\Middleware\Flash());
|
||||
$this->add(new \Slim\Middleware\MethodOverride());
|
||||
|
||||
// Make default if first instance
|
||||
if (is_null(static::getInstance())) {
|
||||
$this->setName('default');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redefine the run method
|
||||
|
||||
60
application/Espo/Core/Utils/Api/Slim/Environment.php
Normal file
60
application/Espo/Core/Utils/Api/Slim/Environment.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://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.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Utils\Api\Slim;
|
||||
|
||||
class Environment extends \Slim\Environment
|
||||
{
|
||||
/**
|
||||
* Define undefined $_SERVER variables
|
||||
*/
|
||||
private static function setUndefinedVariables()
|
||||
{
|
||||
$list = array(
|
||||
'REQUEST_METHOD',
|
||||
'REMOTE_ADDR',
|
||||
'SERVER_NAME',
|
||||
'SERVER_PORT',
|
||||
'REQUEST_URI',
|
||||
);
|
||||
|
||||
foreach ($list as $name) {
|
||||
if (!array_key_exists($name, $_SERVER)) {
|
||||
$_SERVER[$name] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getInstance($refresh = false)
|
||||
{
|
||||
static::setUndefinedVariables();
|
||||
|
||||
return parent::getInstance($refresh);
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,8 @@ class LinkParent extends Base
|
||||
$fieldName.'Name' => array(
|
||||
'type' => 'varchar',
|
||||
'notStorable' => true,
|
||||
'relation' => $fieldName,
|
||||
'isParentName' => true
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -36,11 +36,18 @@ use Espo\Core\Utils\Util,
|
||||
class Converter
|
||||
{
|
||||
private $dbalSchema;
|
||||
|
||||
private $fileManager;
|
||||
|
||||
private $metadata;
|
||||
|
||||
private $ormMeta = null;
|
||||
|
||||
private $customTablePath = 'application/Espo/Core/Utils/Database/Schema/tables';
|
||||
protected $tablePaths = array(
|
||||
'corePath' => 'application/Espo/Core/Utils/Database/Schema/tables',
|
||||
'modulePath' => 'application/Espo/Modules/{*}/Core/Utils/Database/Schema/tables',
|
||||
'customPath' => 'custom/Espo/Custom/Core/Utils/Database/Schema/tables',
|
||||
);
|
||||
|
||||
protected $typeList;
|
||||
|
||||
@@ -69,13 +76,19 @@ class Converter
|
||||
'foreign'
|
||||
);
|
||||
|
||||
public function __construct(\Espo\Core\Utils\File\Manager $fileManager)
|
||||
public function __construct(\Espo\Core\Utils\Metadata $metadata, \Espo\Core\Utils\File\Manager $fileManager)
|
||||
{
|
||||
$this->metadata = $metadata;
|
||||
$this->fileManager = $fileManager;
|
||||
|
||||
$this->typeList = array_keys(\Doctrine\DBAL\Types\Type::getTypesMap());
|
||||
}
|
||||
|
||||
protected function getMetadata()
|
||||
{
|
||||
return $this->metadata;
|
||||
}
|
||||
|
||||
protected function getFileManager()
|
||||
{
|
||||
return $this->fileManager;
|
||||
@@ -369,17 +382,22 @@ class Converter
|
||||
*/
|
||||
protected function getCustomTables(array $ormMeta)
|
||||
{
|
||||
$customTables = array();
|
||||
$customTables = $this->loadData($this->tablePaths['corePath']);
|
||||
|
||||
$fileList = $this->getFileManager()->getFileList($this->customTablePath, false, '\.php$', true);
|
||||
if (!empty($this->tablePaths['modulePath'])) {
|
||||
$moduleDir = strstr($this->tablePaths['modulePath'], '{*}', true);
|
||||
$moduleList = isset($this->metadata) ? $this->getMetadata()->getModuleList() : $this->getFileManager()->getFileList($moduleDir, false, '', false);
|
||||
|
||||
foreach($fileList as $fileName) {
|
||||
$fileData = $this->getFileManager()->getPhpContents( array($this->customTablePath, $fileName) );
|
||||
if (is_array($fileData)) {
|
||||
$customTables = Util::merge($customTables, $fileData);
|
||||
foreach ($moduleList as $moduleName) {
|
||||
$modulePath = str_replace('{*}', $moduleName, $this->tablePaths['modulePath']);
|
||||
$customTables = Util::merge($customTables, $this->loadData($modulePath));
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->tablePaths['customPath'])) {
|
||||
$customTables = Util::merge($customTables, $this->loadData($this->tablePaths['customPath']));
|
||||
}
|
||||
|
||||
//get custom tables from metdata 'additionalTables'
|
||||
foreach ($ormMeta as $entityName => $entityParams) {
|
||||
if (isset($entityParams['additionalTables']) && is_array($entityParams['additionalTables'])) {
|
||||
@@ -437,4 +455,23 @@ class Converter
|
||||
return implode('_', $names);
|
||||
}
|
||||
|
||||
protected function loadData($path)
|
||||
{
|
||||
$tables = array();
|
||||
|
||||
if (!file_exists($path)) {
|
||||
return $tables;
|
||||
}
|
||||
|
||||
$fileList = $this->getFileManager()->getFileList($path, false, '\.php$', true);
|
||||
|
||||
foreach($fileList as $fileName) {
|
||||
$fileData = $this->getFileManager()->getPhpContents( array($path, $fileName) );
|
||||
if (is_array($fileData)) {
|
||||
$tables = Util::merge($tables, $fileData);
|
||||
}
|
||||
}
|
||||
|
||||
return $tables;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ class Schema
|
||||
|
||||
$this->converter = new \Espo\Core\Utils\Database\Converter($this->metadata, $this->fileManager);
|
||||
|
||||
$this->schemaConverter = new Converter($this->fileManager);
|
||||
$this->schemaConverter = new Converter($this->metadata, $this->fileManager);
|
||||
|
||||
$this->ormMetadata = $ormMetadata;
|
||||
}
|
||||
|
||||
@@ -25,12 +25,13 @@
|
||||
*
|
||||
* 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.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
return array(
|
||||
return array(
|
||||
|
||||
'unset' => array(
|
||||
'Preferences',
|
||||
'__APPEND__',
|
||||
'Preferences',
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
@@ -25,12 +25,13 @@
|
||||
*
|
||||
* 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.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
return array(
|
||||
return array(
|
||||
|
||||
'unset' => array(
|
||||
'Settings',
|
||||
'__APPEND__',
|
||||
'Settings',
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
@@ -55,6 +55,36 @@ class DateTime
|
||||
'hh:mmA' => 'h:iA',
|
||||
);
|
||||
|
||||
|
||||
protected $formattingMap = array(
|
||||
'MMMM' => 'F',
|
||||
'MMM' => 'M',
|
||||
'MM' => 'm',
|
||||
'M' => 'n',
|
||||
'DDDD' => 'z',
|
||||
'DD' => 'd',
|
||||
'D' => 'j',
|
||||
'dddd' => 'l',
|
||||
'ddd' => 'D',
|
||||
'ww' => 'W',
|
||||
'w' => 'W',
|
||||
'e' => 'w',
|
||||
'YYYY' => 'Y',
|
||||
'YY' => 'y',
|
||||
'HH' => 'H',
|
||||
'H' => 'G',
|
||||
'hh' => 'h',
|
||||
'h' => 'g',
|
||||
'mm' => 'i',
|
||||
'm' => 'i',
|
||||
'A' => 'A',
|
||||
'a' => 'a',
|
||||
'ss' => 's',
|
||||
's' => 's',
|
||||
'Z' => 'O',
|
||||
'z' => 'O'
|
||||
);
|
||||
|
||||
public function __construct($dateFormat = 'YYYY-MM-DD', $timeFormat = 'HH:mm', $timeZone = 'UTC')
|
||||
{
|
||||
$this->dateFormat = $dateFormat;
|
||||
@@ -83,6 +113,11 @@ class DateTime
|
||||
return $this->dateFormats[$this->dateFormat] . ' ' . $this->timeFormats[$this->timeFormat];
|
||||
}
|
||||
|
||||
protected function convertFormatToPhp($format)
|
||||
{
|
||||
return strtr($format, $this->formattingMap);
|
||||
}
|
||||
|
||||
public function convertSystemDateToGlobal($string)
|
||||
{
|
||||
return $this->convertSystemDate($string);
|
||||
@@ -93,25 +128,39 @@ class DateTime
|
||||
return $this->convertSystemDateTime($string);
|
||||
}
|
||||
|
||||
public function convertSystemDate($string)
|
||||
public function convertSystemDate($string, $format = null)
|
||||
{
|
||||
$dateTime = \DateTime::createFromFormat('Y-m-d', $string);
|
||||
if ($dateTime) {
|
||||
return $dateTime->format($this->getPhpDateFormat());
|
||||
if ($format) {
|
||||
$phpFormat = $this->convertFormatToPhp($format);
|
||||
} else {
|
||||
$phpFormat = $this->getPhpDateFormat();
|
||||
}
|
||||
return $dateTime->format($phpFormat);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function convertSystemDateTime($string, $timezone = null)
|
||||
public function convertSystemDateTime($string, $timezone = null, $format = null)
|
||||
{
|
||||
if (is_string($string) && strlen($string) === 16) {
|
||||
$string .= ':00';
|
||||
}
|
||||
$dateTime = \DateTime::createFromFormat('Y-m-d H:i:s', $string);
|
||||
if (empty($timezone)) {
|
||||
$timezone = $this->timezone;
|
||||
} else {
|
||||
$timezone = new \DateTimeZone($timezone);
|
||||
}
|
||||
|
||||
if ($dateTime) {
|
||||
return $dateTime->setTimezone($timezone)->format($this->getPhpDateTimeFormat());
|
||||
if ($format) {
|
||||
$phpFormat = $this->convertFormatToPhp($format);
|
||||
} else {
|
||||
$phpFormat = $this->getPhpDateTimeFormat();
|
||||
}
|
||||
return $dateTime->setTimezone($timezone)->format($phpFormat);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,13 @@ class EntityManager
|
||||
return $this->metadata;
|
||||
}
|
||||
|
||||
protected function getEntityManager()
|
||||
{
|
||||
if (!$this->container) return;
|
||||
|
||||
return $this->container->get('entityManager');
|
||||
}
|
||||
|
||||
protected function getLanguage()
|
||||
{
|
||||
return $this->language;
|
||||
@@ -210,6 +217,7 @@ class EntityManager
|
||||
$filePath = "application/Espo/Core/Templates/Metadata/{$type}/entityDefs.json";
|
||||
$entityDefsDataContents = $this->getFileManager()->getContents($filePath);
|
||||
$entityDefsDataContents = str_replace('{entityType}', $name, $entityDefsDataContents);
|
||||
$entityDefsDataContents = str_replace('{tableName}', $this->getEntityManager()->getQuery()->toDb($name), $entityDefsDataContents);
|
||||
$entityDefsData = Json::decode($entityDefsDataContents, true);
|
||||
$this->getMetadata()->set('entityDefs', $name, $entityDefsData);
|
||||
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Utils;
|
||||
use \Espo\Core\Exceptions\Error,
|
||||
\Espo\Core\Exceptions\Conflict;
|
||||
|
||||
use \Espo\Core\Container;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Conflict;
|
||||
use Espo\Core\Container;
|
||||
|
||||
class FieldManager
|
||||
{
|
||||
@@ -78,9 +78,9 @@ class FieldManager
|
||||
return $this->container->get('defaultLanguage');
|
||||
}
|
||||
|
||||
public function read($name, $scope)
|
||||
public function read($scope, $name)
|
||||
{
|
||||
$fieldDefs = $this->getFieldDefs($name, $scope);
|
||||
$fieldDefs = $this->getFieldDefs($scope, $name);
|
||||
|
||||
$fieldDefs['label'] = $this->getLanguage()->translate($name, 'fields', $scope);
|
||||
|
||||
@@ -91,30 +91,33 @@ class FieldManager
|
||||
return $fieldDefs;
|
||||
}
|
||||
|
||||
public function create($name, $fieldDefs, $scope)
|
||||
public function create($scope, $name, $fieldDefs)
|
||||
{
|
||||
$existingField = $this->getFieldDefs($name, $scope);
|
||||
$existingField = $this->getFieldDefs($scope, $name);
|
||||
if (isset($existingField)) {
|
||||
throw new Conflict('Field ['.$name.'] exists in '.$scope);
|
||||
}
|
||||
|
||||
return $this->update($name, $fieldDefs, $scope, true);
|
||||
return $this->update($scope, $name, $fieldDefs, true);
|
||||
}
|
||||
|
||||
public function update($name, $fieldDefs, $scope, $isNew = false)
|
||||
public function update($scope, $name, $fieldDefs, $isNew = false)
|
||||
{
|
||||
$name = trim($name);
|
||||
$this->isChanged = false;
|
||||
|
||||
/*Add option to metadata to identify the custom field*/
|
||||
if (!$this->isCore($name, $scope)) {
|
||||
if (!$this->isCore($scope, $name)) {
|
||||
$fieldDefs[$this->customOptionName] = true;
|
||||
}
|
||||
|
||||
$res = true;
|
||||
$result = true;
|
||||
$isLabelChanged = false;
|
||||
if (isset($fieldDefs['label'])) {
|
||||
$this->setLabel($name, $fieldDefs['label'], $scope);
|
||||
$isLabelChanged |= $this->setLabel($scope, $name, $fieldDefs['label']);
|
||||
}
|
||||
if (isset($fieldDefs['tooltipText'])) {
|
||||
$this->setTooltipText($name, $fieldDefs['tooltipText'], $scope);
|
||||
$isLabelChanged |= $this->setTooltipText($scope, $name, $fieldDefs['tooltipText']);
|
||||
}
|
||||
|
||||
$type = isset($fieldDefs['type']) ? $fieldDefs['type'] : $type = $this->getMetadata()->get(['entityDefs', $scope, 'fields', $name, 'type']);
|
||||
@@ -127,16 +130,15 @@ class FieldManager
|
||||
$translatedOptions = json_decode(json_encode($fieldDefs['translatedOptions']), true);
|
||||
if (isset($translatedOptions['_empty_'])) {
|
||||
$translatedOptions[''] = $translatedOptions['_empty_'];
|
||||
unset($translatedOptions['_empty_']);
|
||||
}
|
||||
|
||||
$this->setTranslatedOptions($name, $translatedOptions, $scope);
|
||||
$isLabelChanged |= $this->setTranslatedOptions($scope, $name, $translatedOptions);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
isset($fieldDefs['label']) || isset($fieldDefs['translatedOptions']) || isset($fieldDefs['tooltipText'])
|
||||
) {
|
||||
$res &= $this->getLanguage()->save();
|
||||
if ($isLabelChanged) {
|
||||
$result &= $this->getLanguage()->save();
|
||||
|
||||
if (isset($fieldDefs['tooltipText'])) {
|
||||
$this->getDefaultLanguage()->save();
|
||||
@@ -223,19 +225,20 @@ class FieldManager
|
||||
$this->getMetadata()->set('clientDefs', $scope, $clientDefs);
|
||||
}
|
||||
|
||||
if ($this->isDefsChanged($name, $fieldDefs, $scope)) {
|
||||
$entityDefs = $this->normalizeDefs($name, $fieldDefs, $scope);
|
||||
$entityDefs = $this->normalizeDefs($scope, $name, $fieldDefs);
|
||||
if (!empty($entityDefs)) {
|
||||
$this->getMetadata()->set('entityDefs', $scope, $entityDefs);
|
||||
$metadataToBeSaved = true;
|
||||
$this->isChanged = true;
|
||||
}
|
||||
|
||||
if ($metadataToBeSaved) {
|
||||
$res &= $this->getMetadata()->save();
|
||||
$result &= $this->getMetadata()->save();
|
||||
|
||||
$this->processHook('afterSave', $type, $scope, $name, $fieldDefs, array('isNew' => $isNew));
|
||||
}
|
||||
|
||||
return (bool) $res;
|
||||
return (bool) $result;
|
||||
}
|
||||
|
||||
protected function prepareClientDefsFieldsDynamicLogic(&$clientDefs, $name)
|
||||
@@ -264,9 +267,9 @@ class FieldManager
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($name, $scope)
|
||||
public function delete($scope, $name)
|
||||
{
|
||||
if ($this->isCore($name, $scope)) {
|
||||
if ($this->isCore($scope, $name)) {
|
||||
throw new Error('Cannot delete core field ['.$name.'] in '.$scope);
|
||||
}
|
||||
|
||||
@@ -288,16 +291,16 @@ class FieldManager
|
||||
|
||||
|
||||
$res = $this->getMetadata()->save();
|
||||
$res &= $this->deleteLabel($name, $scope);
|
||||
$res &= $this->deleteLabel($scope, $name);
|
||||
|
||||
$this->processHook('afterRemove', $type, $scope, $name);
|
||||
|
||||
return (bool) $res;
|
||||
}
|
||||
|
||||
public function resetToDefault($name, $scope)
|
||||
public function resetToDefault($scope, $name)
|
||||
{
|
||||
if (!$this->isCore($name, $scope)) {
|
||||
if (!$this->isCore($scope, $name)) {
|
||||
throw new Error('Cannot reset to default custom field ['.$name.'] in '.$scope);
|
||||
}
|
||||
|
||||
@@ -321,28 +324,32 @@ class FieldManager
|
||||
$this->getDefaultLanguage()->save();
|
||||
}
|
||||
|
||||
protected function setEntityDefs($name, $fieldDefs, $scope)
|
||||
protected function setTranslatedOptions($scope, $name, $value)
|
||||
{
|
||||
$fieldDefs = $this->normalizeDefs($name, $fieldDefs, $scope);
|
||||
if (!$this->isLabelChanged($scope, 'options', $name, $value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->getMetadata()->set('entityDefs', $scope, $fieldDefs);
|
||||
$res = $this->getMetadata()->save();
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
protected function setTranslatedOptions($name, $value, $scope)
|
||||
{
|
||||
$this->getLanguage()->set($scope, 'options', $name, $value);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function setLabel($name, $value, $scope)
|
||||
protected function setLabel($scope, $name, $value)
|
||||
{
|
||||
return $this->getLanguage()->set($scope, 'fields', $name, $value);
|
||||
if (!$this->isLabelChanged($scope, 'fields', $name, $value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->getLanguage()->set($scope, 'fields', $name, $value);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function setTooltipText($name, $value, $scope)
|
||||
protected function setTooltipText($scope, $name, $value)
|
||||
{
|
||||
if (!$this->isLabelChanged($scope, 'tooltips', $name, $value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($value && $value !== '') {
|
||||
$this->getLanguage()->set($scope, 'tooltips', $name, $value);
|
||||
$this->getDefaultLanguage()->set($scope, 'tooltips', $name, $value);
|
||||
@@ -350,9 +357,11 @@ class FieldManager
|
||||
$this->getLanguage()->delete($scope, 'tooltips', $name);
|
||||
$this->getDefaultLanguage()->delete($scope, 'tooltips', $name);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function deleteLabel($name, $scope)
|
||||
protected function deleteLabel($scope, $name)
|
||||
{
|
||||
$this->getLanguage()->delete($scope, 'fields', $name);
|
||||
$this->getLanguage()->delete($scope, 'tooltips', $name);
|
||||
@@ -363,12 +372,12 @@ class FieldManager
|
||||
$this->getDefaultLanguage()->save();
|
||||
}
|
||||
|
||||
protected function getFieldDefs($name, $scope)
|
||||
protected function getFieldDefs($scope, $name)
|
||||
{
|
||||
return $this->getMetadata()->get('entityDefs'.'.'.$scope.'.fields.'.$name);
|
||||
}
|
||||
|
||||
protected function getLinkDefs($name, $scope)
|
||||
protected function getLinkDefs($scope, $name)
|
||||
{
|
||||
return $this->getMetadata()->get('entityDefs'.'.'.$scope.'.links.'.$name);
|
||||
}
|
||||
@@ -381,12 +390,16 @@ class FieldManager
|
||||
* @param string $scope
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareFieldDefs($name, $fieldDefs, $scope)
|
||||
protected function prepareFieldDefs($scope, $name, $fieldDefs)
|
||||
{
|
||||
$unnecessaryFields = array(
|
||||
'name',
|
||||
'label',
|
||||
'translatedOptions',
|
||||
'dynamicLogicVisible',
|
||||
'dynamicLogicReadOnly',
|
||||
'dynamicLogicRequired',
|
||||
'dynamicLogicOptions',
|
||||
);
|
||||
|
||||
foreach ($unnecessaryFields as $fieldName) {
|
||||
@@ -395,7 +408,7 @@ class FieldManager
|
||||
}
|
||||
}
|
||||
|
||||
$currentOptionList = array_keys((array) $this->getFieldDefs($name, $scope));
|
||||
$currentOptionList = array_keys((array) $this->getFieldDefs($scope, $name));
|
||||
foreach ($fieldDefs as $defName => $defValue) {
|
||||
if ( (!isset($defValue) || $defValue === '') && !in_array($defName, $currentOptionList) ) {
|
||||
unset($fieldDefs[$defName]);
|
||||
@@ -408,14 +421,14 @@ class FieldManager
|
||||
/**
|
||||
* Add all needed block for a field defenition
|
||||
*
|
||||
* @param string $scope
|
||||
* @param string $fieldName
|
||||
* @param array $fieldDefs
|
||||
* @param string $scope
|
||||
* @return array
|
||||
*/
|
||||
protected function normalizeDefs($fieldName, array $fieldDefs, $scope)
|
||||
protected function normalizeDefs($scope, $fieldName, array $fieldDefs)
|
||||
{
|
||||
$fieldDefs = $this->prepareFieldDefs($fieldName, $fieldDefs, $scope);
|
||||
$fieldDefs = $this->prepareFieldDefs($scope, $fieldName, $fieldDefs);
|
||||
|
||||
$metaFieldDefs = $this->getMetadataHelper()->getFieldDefsInFieldMeta($fieldDefs);
|
||||
if (isset($metaFieldDefs)) {
|
||||
@@ -427,19 +440,29 @@ class FieldManager
|
||||
unset($fieldDefs['linkDefs']);
|
||||
}
|
||||
|
||||
$defs = array(
|
||||
'fields' => array(
|
||||
$fieldName => $fieldDefs,
|
||||
),
|
||||
);
|
||||
$defs = array();
|
||||
|
||||
$currentFieldDefs = (array) $this->getFieldDefs($scope, $fieldName);
|
||||
$normalizedFieldDefs = Util::arrayDiff($currentFieldDefs, $fieldDefs);
|
||||
if (!empty($normalizedFieldDefs)) {
|
||||
$defs['fields'] = array(
|
||||
$fieldName => $normalizedFieldDefs,
|
||||
);
|
||||
}
|
||||
|
||||
/** Save links for a field. */
|
||||
$metaLinkDefs = $this->getMetadataHelper()->getLinkDefsInFieldMeta($scope, $fieldDefs);
|
||||
if (isset($linkDefs) || isset($metaLinkDefs)) {
|
||||
$linkDefs = Util::merge((array) $metaLinkDefs, (array) $linkDefs);
|
||||
$defs['links'] = array(
|
||||
$fieldName => $linkDefs,
|
||||
);
|
||||
|
||||
$metaLinkDefs = isset($metaLinkDefs) ? $metaLinkDefs : array();
|
||||
$linkDefs = isset($linkDefs) ? $linkDefs : array();
|
||||
|
||||
$normalizedLinkdDefs = Util::merge($metaLinkDefs, $linkDefs);
|
||||
if (!empty($normalizedLinkdDefs)) {
|
||||
$defs['links'] = array(
|
||||
$fieldName => $normalizedLinkdDefs,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $defs;
|
||||
@@ -448,18 +471,45 @@ class FieldManager
|
||||
/**
|
||||
* Check if changed metadata defenition for a field except 'label'
|
||||
*
|
||||
* @param string $scope
|
||||
* @param string $name
|
||||
* @param array $fieldDefs
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function isDefsChanged($name, $fieldDefs, $scope)
|
||||
protected function isDefsChanged($scope, $name, $fieldDefs)
|
||||
{
|
||||
$fieldDefs = $this->prepareFieldDefs($name, $fieldDefs, $scope);
|
||||
$currentFieldDefs = $this->getFieldDefs($name, $scope);
|
||||
$fieldDefs = $this->prepareFieldDefs($scope, $name, $fieldDefs);
|
||||
$currentFieldDefs = $this->getFieldDefs($scope, $name);
|
||||
|
||||
$this->isChanged = Util::isEquals($fieldDefs, $currentFieldDefs) ? false : true;
|
||||
$diffDefs = Util::arrayDiff($currentFieldDefs, $fieldDefs);
|
||||
|
||||
$this->isChanged = empty($diffDefs) ? false : true;
|
||||
|
||||
return $this->isChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if label is changed
|
||||
*
|
||||
* @param string $scope
|
||||
* @param string $category
|
||||
* @param string $name
|
||||
* @param mixed $newLabel
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function isLabelChanged($scope, $category, $name, $newLabel)
|
||||
{
|
||||
$currentLabel = $this->getLanguage()->get([$scope, $category, $name]);
|
||||
|
||||
if ($newLabel != $currentLabel) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only for update method
|
||||
*
|
||||
@@ -477,9 +527,9 @@ class FieldManager
|
||||
* @param string $scope
|
||||
* @return boolean
|
||||
*/
|
||||
protected function isCore($name, $scope)
|
||||
protected function isCore($scope, $name)
|
||||
{
|
||||
$existingField = $this->getFieldDefs($name, $scope);
|
||||
$existingField = $this->getFieldDefs($scope, $name);
|
||||
if (isset($existingField) && (!isset($existingField[$this->customOptionName]) || !$existingField[$this->customOptionName])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -61,6 +61,12 @@ class Metadata
|
||||
|
||||
private $moduleList = null;
|
||||
|
||||
protected $frontendHiddenPathList = [
|
||||
['app', 'formula', 'functionClassNameMap'],
|
||||
['app', 'fileStorage', 'implementationClassNameMap'],
|
||||
['app', 'emailNotifications', 'handlerClassNameMap']
|
||||
];
|
||||
|
||||
/**
|
||||
* Default module order
|
||||
* @var integer
|
||||
@@ -198,6 +204,36 @@ class Metadata
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function getAllForFrontend()
|
||||
{
|
||||
$data = $this->getAll();
|
||||
|
||||
foreach ($this->frontendHiddenPathList as $row) {
|
||||
$p =& $data;
|
||||
$path = [&$p];
|
||||
foreach ($row as $i => $item) {
|
||||
if (!array_key_exists($item, $p)) break;
|
||||
if ($i == count($row) - 1) {
|
||||
unset($p[$item]);
|
||||
$o =& $p;
|
||||
for ($j = $i - 1; $j > 0; $j--) {
|
||||
if (is_array($o) && empty($o)) {
|
||||
$o =& $path[$j];
|
||||
$k = $row[$j];
|
||||
unset($o[$k]);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$p =& $p[$item];
|
||||
$path[] = &$p;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* todo: move to a separate file
|
||||
* Add additional fields defined from metadata -> fields
|
||||
|
||||
@@ -146,9 +146,9 @@ class Util
|
||||
{
|
||||
$mergeIdentifier = '__APPEND__';
|
||||
|
||||
if (is_array($currentArray) && (!is_array($newArray) || empty($newArray))) {
|
||||
if (is_array($currentArray) && !is_array($newArray)) {
|
||||
return $currentArray;
|
||||
} else if ((!is_array($currentArray) || empty($currentArray)) && is_array($newArray)) {
|
||||
} else if (!is_array($currentArray) && is_array($newArray)) {
|
||||
return $newArray;
|
||||
} else if ((!is_array($currentArray) || empty($currentArray)) && (!is_array($newArray) || empty($newArray))) {
|
||||
return array();
|
||||
@@ -156,10 +156,6 @@ class Util
|
||||
|
||||
foreach ($newArray as $newName => $newValue) {
|
||||
|
||||
if (is_array($newValue) && empty($newValue)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_array($newValue) && array_key_exists($newName, $currentArray) && is_array($currentArray[$newName])) {
|
||||
|
||||
// check __APPEND__ identifier
|
||||
@@ -557,5 +553,32 @@ class Util
|
||||
return preg_replace("/([^\w\s\d\-_~,;:\[\]\(\).])/u", '_', $fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Improved computing the difference of arrays
|
||||
*
|
||||
* @param array $array1
|
||||
* @param array $array2
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function arrayDiff(array $array1, array $array2)
|
||||
{
|
||||
$diff = array();
|
||||
|
||||
foreach ($array1 as $key1 => $value1) {
|
||||
if (array_key_exists($key1, $array2)) {
|
||||
if ($value1 !== $array2[$key1]) {
|
||||
$diff[$key1] = $array2[$key1];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$diff[$key1] = $value1;
|
||||
}
|
||||
|
||||
$diff = array_merge($diff, array_diff_key($array2, $array1));
|
||||
|
||||
return $diff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,6 +67,12 @@ class Download extends \Espo\Core\EntryPoints\Base
|
||||
|
||||
$sourceId = $attachment->getSourceId();
|
||||
|
||||
if ($this->getEntityManager()->getRepository('Attachment')->hasDownloadUrl($attachment)) {
|
||||
$downloadUrl = $this->getEntityManager()->getRepository('Attachment')->getDownloadUrl($attachment);
|
||||
header('Location: ' . $downloadUrl);
|
||||
exit;
|
||||
}
|
||||
|
||||
$fileName = $this->getEntityManager()->getRepository('Attachment')->getFilePath($attachment);
|
||||
|
||||
if (!file_exists($fileName)) {
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2017 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://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.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Business\EmailNotificationHandlers;
|
||||
|
||||
class CaseObj extends \Espo\Core\Injectable
|
||||
{
|
||||
protected $dependencyList = [
|
||||
'entityManager'
|
||||
];
|
||||
|
||||
protected $inboundEmailEntityHash = array();
|
||||
|
||||
public function getSmtpParams($type, $case, $user = null)
|
||||
{
|
||||
$inboundEmailId = $case->get('inboundEmailId');
|
||||
|
||||
if (!$inboundEmailId) return;
|
||||
|
||||
if (!array_key_exists($inboundEmailId, $this->inboundEmailEntityHash)) {
|
||||
$this->inboundEmailEntityHash[$inboundEmailId] = $this->getInjection('entityManager')->getEntity('InboundEmail', $inboundEmailId);
|
||||
}
|
||||
|
||||
$inboundEmail = $this->inboundEmailEntityHash[$inboundEmailId];
|
||||
|
||||
if (!$inboundEmail) return;
|
||||
|
||||
$emailAddress = $inboundEmail->get('emailAddress');
|
||||
|
||||
if (!$emailAddress) return;
|
||||
|
||||
return array(
|
||||
'replyToAddress' => $emailAddress
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -39,36 +39,55 @@
|
||||
"Reseller": "Wiederverkäufer"
|
||||
},
|
||||
"industry": {
|
||||
"Aerospace": "Luft- und Raumfahrt",
|
||||
"Agriculture": "Landwirtschaft",
|
||||
"Advertising": "Werbewirtschaft",
|
||||
"Apparel & Accessories": "Bekleidungsindustrie",
|
||||
"Architecture": "Architekten",
|
||||
"Automotive": "Automobilindustrie",
|
||||
"Banking": "Bankwesen",
|
||||
"Biotechnology": "Biotechnologie",
|
||||
"Building Materials & Equipment": "Baumaterial & -ausstattung",
|
||||
"Chemical": "Chemieindustrie",
|
||||
"Construction": "Konstruktion",
|
||||
"Computer": "Informationstechnologie",
|
||||
"Defense": "Verteidigung",
|
||||
"Creative": "Kreative",
|
||||
"Culture": "Kultur",
|
||||
"Education": "Bildungswesen",
|
||||
"Electronics": "Elektronik",
|
||||
"Electric Power": "Elektroenergie",
|
||||
"Energy": "Energieerzeuger",
|
||||
"Entertainment & Leisure": "Freizeit- und Unterhaltungsindustrie",
|
||||
"Finance": "Finanzsektor",
|
||||
"Food & Beverage": "Speisen und Getränke",
|
||||
"Grocery": "Einzelhandel",
|
||||
"Hospitality": "Gastronomie",
|
||||
"Healthcare": "Gesundheitswesen",
|
||||
"Insurance": "Versicherung",
|
||||
"Legal": "Rechtswesen",
|
||||
"Manufacturing": "Produktion",
|
||||
"Mass Media": "Massenmedien",
|
||||
"Mining": "Bergbau",
|
||||
"Music": "Musik",
|
||||
"Marketing": "Marketing",
|
||||
"Publishing": "Medien",
|
||||
"Petroleum": "Öl Industrie",
|
||||
"Real Estate": "Immobilien",
|
||||
"Retail": "Verkauf",
|
||||
"Shipping": "Versand und Transport",
|
||||
"Service": "Service",
|
||||
"Support": "Service",
|
||||
"Sports": "Sport",
|
||||
"Software": "Software",
|
||||
"Technology": "Technologie",
|
||||
"Telecommunications": "Telekommunikation",
|
||||
"Television": "Fernsehen",
|
||||
"Testing, Inspection & Certification": "Test, Inspektion & Zertifizierung",
|
||||
"Transportation": "Transportwesen",
|
||||
"Venture Capital": "Risikokapital"
|
||||
"Venture Capital": "Risikokapital",
|
||||
"Wholesale": "Großhandel",
|
||||
"Water": "Wasserwesen"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
"contacts": "Kontakte",
|
||||
"leads": "Interessenten",
|
||||
"reminders": "Erinnerungen",
|
||||
"account": "Firma"
|
||||
"account": "Firma",
|
||||
"acceptanceStatus": "Akzeptanzstatus"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
"accounts": "Firmen",
|
||||
"casesPrimary": "Fälle (Primär)",
|
||||
"portalUser": "Portal Benutzer",
|
||||
"originalLead": "Ursprünglicher Interessent"
|
||||
"originalLead": "Ursprünglicher Interessent",
|
||||
"documents": "Dokumente"
|
||||
},
|
||||
"labels": {
|
||||
"Create Contact": "Kontakt erstellen"
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
"status": "Status",
|
||||
"file": "Datei",
|
||||
"type": "Typ",
|
||||
"source": "Quelle",
|
||||
"publishDate": "Veröffentlichungsdatum",
|
||||
"expirationDate": "Ablaufdatum",
|
||||
"description": "Beschreibung",
|
||||
@@ -19,7 +18,8 @@
|
||||
"accounts": "Firmen",
|
||||
"opportunities": "Verkaufschancen",
|
||||
"folder": "Ordner",
|
||||
"leads": "Interessenten"
|
||||
"leads": "Interessenten",
|
||||
"contacts": "Kontakte"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
"Any": "Beliebig",
|
||||
"Send in Email": "In E-Mail senden",
|
||||
"Move Up": "Aufwärts",
|
||||
"Move Down": "Abwärts"
|
||||
"Move Down": "Abwärts",
|
||||
"Move to Top": "zu Anfang",
|
||||
"Move to Bottom": "zum Ende"
|
||||
},
|
||||
"fields": {
|
||||
"name": "Name",
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
"createdOpportunity": "Verkaufschance",
|
||||
"campaign": "Kampagne",
|
||||
"targetLists": "Kontaktlisten",
|
||||
"targetList": "Kontaktliste"
|
||||
"targetList": "Kontaktliste",
|
||||
"industry": "Industrie"
|
||||
},
|
||||
"links": {
|
||||
"targetLists": "Kontaktlisten",
|
||||
|
||||
@@ -45,5 +45,9 @@
|
||||
"optOutEntirely": "Für E-Mail Adressen von Empfängern, die sich abgemeldet haben, wird ein Opt-out gesetzt. Diese werden keine Massenaussendungen mehr erhalten.",
|
||||
"targetLists": "Zielkontakte die Nachrichten empfangen sollen",
|
||||
"excludingTargetLists": "Zielkontakte die keine Nachrichten empfangen sollen"
|
||||
},
|
||||
"presetFilters": {
|
||||
"actual": "Aktuell",
|
||||
"complete": "Fertig"
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,8 @@
|
||||
"contacts": "Kontakte",
|
||||
"leads": "Interessenten",
|
||||
"reminders": "Erinnerungen",
|
||||
"account": "Firma"
|
||||
"account": "Firma",
|
||||
"acceptanceStatus": "Akzeptanzstatus"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
@@ -42,5 +43,8 @@
|
||||
"planned": "Geplant",
|
||||
"held": "Abgehalten",
|
||||
"todays": "Heutige"
|
||||
},
|
||||
"messages": {
|
||||
"nothingHasBeenSent": "Es wurde nicht gesendet"
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,8 @@
|
||||
"isOverdue": "Ist überfällig",
|
||||
"account": "Firma",
|
||||
"dateCompleted": "Datum erledigt",
|
||||
"attachments": "Anhänge"
|
||||
"attachments": "Anhänge",
|
||||
"reminders": "Erinnerungen"
|
||||
},
|
||||
"links": {
|
||||
"attachments": "Anhänge"
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
"Defense": "Defense",
|
||||
"Creative": "Creative",
|
||||
"Culture": "Culture",
|
||||
"Consulting": "Consulting",
|
||||
"Education": "Education",
|
||||
"Electronics": "Electronics",
|
||||
"Electric Power": "Electric Power",
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
"targetLists": "Target Lists",
|
||||
"targetList": "Target List",
|
||||
"portalUser": "Portal User",
|
||||
"originalLead": "Original Lead"
|
||||
"originalLead": "Original Lead",
|
||||
"acceptanceStatus": "Acceptance Status"
|
||||
},
|
||||
"links": {
|
||||
"opportunities": "Opportunities",
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
"status": "Status",
|
||||
"file": "File",
|
||||
"type": "Type",
|
||||
"source": "Source",
|
||||
"publishDate": "Publish Date",
|
||||
"expirationDate": "Expiration Date",
|
||||
"description": "Description",
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
"status": {
|
||||
"Pending": "Pending",
|
||||
"Sent": "Sent",
|
||||
"Failed": "Failed"
|
||||
"Failed": "Failed",
|
||||
"Sending": "Sending"
|
||||
}
|
||||
},
|
||||
"presetFilters": {
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
"campaign": "Campaign",
|
||||
"targetLists": "Target Lists",
|
||||
"targetList": "Target List",
|
||||
"industry": "Industry"
|
||||
"industry": "Industry",
|
||||
"acceptanceStatus": "Acceptance Status"
|
||||
},
|
||||
"links": {
|
||||
"targetLists": "Target Lists",
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
{
|
||||
"fields": {
|
||||
"acceptanceStatus": "Acceptance Status"
|
||||
},
|
||||
"links": {
|
||||
"targetLists": "Target Lists"
|
||||
}
|
||||
|
||||
@@ -1,68 +1,80 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"emailAddress": "Email",
|
||||
"website": "Site internet",
|
||||
"phoneNumber": "Téléphone",
|
||||
"billingAddress": "Adresse de facturation",
|
||||
"shippingAddress": "Adresse de livraison",
|
||||
"description": "Description",
|
||||
"sicCode": "Sic Code",
|
||||
"industry": "Industrie",
|
||||
"type": "Type",
|
||||
"contactRole": "Titre",
|
||||
"campaign": "Campagne"
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"emailAddress": "Email",
|
||||
"website": "Site internet",
|
||||
"phoneNumber": "Téléphone",
|
||||
"billingAddress": "Adresse de facturation",
|
||||
"shippingAddress": "Adresse de livraison",
|
||||
"description": "Description",
|
||||
"sicCode": "Sic Code",
|
||||
"industry": "Industrie",
|
||||
"type": "Type",
|
||||
"contactRole": "Titre",
|
||||
"campaign": "Campagne",
|
||||
"targetLists": "Listes de cibles",
|
||||
"targetList": "Liste de cibles"
|
||||
},
|
||||
"links": {
|
||||
"contacts": "Contacts",
|
||||
"opportunities": "Opportunités",
|
||||
"cases": "Tickets",
|
||||
"documents": "Documents",
|
||||
"meetingsPrimary": "Rendez-vous (étendus)",
|
||||
"callsPrimary": "Appels (étendus)",
|
||||
"tasksPrimary": "Tâches (étendues)",
|
||||
"emailsPrimary": "Emails (étendus)",
|
||||
"targetLists": "Listes de cible",
|
||||
"campaignLogRecords": "Log de campagne",
|
||||
"campaign": "Campagne",
|
||||
"portalUsers": "Utilisateurs Portail"
|
||||
},
|
||||
"options": {
|
||||
"type": {
|
||||
"Customer": "Client",
|
||||
"Investor": "Investisseur",
|
||||
"Partner": "Partenaire",
|
||||
"Reseller": "Revendeur"
|
||||
},
|
||||
"links": {
|
||||
"contacts": "Contacts",
|
||||
"opportunities": "Opportunités",
|
||||
"cases": "Tickets",
|
||||
"documents": "Documents",
|
||||
"meetingsPrimary": "Rendez-vous (étendus)",
|
||||
"callsPrimary": "Appels (étendus)",
|
||||
"tasksPrimary": "Tâches (étendues)",
|
||||
"emailsPrimary": "Emails (étendus)",
|
||||
"targetLists": "Listes de cible",
|
||||
"campaignLogRecords": "Log de Campagne"
|
||||
},
|
||||
"options": {
|
||||
"type": {
|
||||
"Customer": "Client",
|
||||
"Investor": "Investisseur",
|
||||
"Partner": "Partenaire",
|
||||
"Reseller": "Commercialisateur"
|
||||
},
|
||||
"industry": {
|
||||
"Agriculture": "Agriculture",
|
||||
"Advertising": "Publicité",
|
||||
"Apparel & Accessories": "Mode et accessoires",
|
||||
"Automotive": "Auto",
|
||||
"Banking": "Banque",
|
||||
"Biotechnology": "Biotechnologie",
|
||||
"Chemical": "Chimie",
|
||||
"Computer": "Informatique",
|
||||
"Education": "Education",
|
||||
"Electronics": "Electronique",
|
||||
"Entertainment & Leisure": "Divertissement et loisir",
|
||||
"Finance": "Finance",
|
||||
"Food & Beverage": "Alimentation",
|
||||
"Grocery": "Epicerie",
|
||||
"Insurance": "Assurance",
|
||||
"Legal": "Droit",
|
||||
"Publishing": "Publication",
|
||||
"Real Estate": "Immobilier",
|
||||
"Service": "Service",
|
||||
"Sports": "Sports",
|
||||
"Software": "Logiciel",
|
||||
"Technology": "Technologie",
|
||||
"Telecommunications": "Télécommunications",
|
||||
"Television": "Télévision",
|
||||
"Transportation": "Transport",
|
||||
"Venture Capital": "Investissement"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create Account": "Créer un compte",
|
||||
"Copy Billing": "Copie de facturation"
|
||||
"industry": {
|
||||
"Agriculture": "Agriculture",
|
||||
"Advertising": "Publicité",
|
||||
"Apparel & Accessories": "Mode et accessoires",
|
||||
"Automotive": "Auto",
|
||||
"Banking": "Banque",
|
||||
"Biotechnology": "Biotechnologie",
|
||||
"Building Materials & Equipment": "Matériaux de construction & équipements",
|
||||
"Chemical": "Chimie",
|
||||
"Computer": "Informatique",
|
||||
"Education": "Education",
|
||||
"Electronics": "Électronique",
|
||||
"Energy": "Énergie",
|
||||
"Entertainment & Leisure": "Divertissement et loisirs",
|
||||
"Finance": "Finance",
|
||||
"Food & Beverage": "Alimentation",
|
||||
"Grocery": "Épicerie",
|
||||
"Healthcare": "Santé",
|
||||
"Insurance": "Assurance",
|
||||
"Legal": "Droit",
|
||||
"Manufacturing": "Industrie",
|
||||
"Publishing": "Publication",
|
||||
"Real Estate": "Immobilier",
|
||||
"Service": "Service",
|
||||
"Sports": "Sports",
|
||||
"Software": "Logiciel",
|
||||
"Technology": "Technologie",
|
||||
"Telecommunications": "Télécommunications",
|
||||
"Television": "Télévision",
|
||||
"Transportation": "Transport",
|
||||
"Venture Capital": "Investissement"
|
||||
}
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create Account": "Créer un compte",
|
||||
"Copy Billing": "Copie de facturation"
|
||||
},
|
||||
"presetFilters": {
|
||||
"customers": "Clients",
|
||||
"partners": "Partenaires"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"layouts": {
|
||||
"detailConvert": "Convertir le prospect"
|
||||
}
|
||||
}
|
||||
"layouts": {
|
||||
"detailConvert": "Convertir le prospect",
|
||||
"listForAccount": "Liste (compte)"
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,20 @@
|
||||
{
|
||||
"modes": {
|
||||
"month": "Mois",
|
||||
"week": "Semaine",
|
||||
"day": "Jour",
|
||||
"agendaWeek": "Semaine",
|
||||
"agendaDay": "Jour"
|
||||
},
|
||||
"labels": {
|
||||
"Today": "Aujourd'hui",
|
||||
"Create": "Créer"
|
||||
}
|
||||
}
|
||||
"modes": {
|
||||
"month": "Mois",
|
||||
"week": "Semaine",
|
||||
"agendaWeek": "Semaine",
|
||||
"day": "Jour",
|
||||
"agendaDay": "Jour",
|
||||
"timeline": "Plage de temps"
|
||||
},
|
||||
"labels": {
|
||||
"Today": "Aujourd'hui",
|
||||
"Create": "Créer",
|
||||
"Shared": "Partagé",
|
||||
"Add User": "Ajouter un utilisateur",
|
||||
"current": "actuel",
|
||||
"time": "heure",
|
||||
"User List": "Liste utilisateurs",
|
||||
"Manage Users": "Gérer les utilisateurs"
|
||||
}
|
||||
}
|
||||
@@ -1,47 +1,49 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"parent": "Parent",
|
||||
"status": "Statut",
|
||||
"dateStart": "Date de début",
|
||||
"dateEnd": "Date de fin",
|
||||
"direction": "Direction",
|
||||
"duration": "Durée",
|
||||
"description": "Description",
|
||||
"users": "Utilisateurs",
|
||||
"contacts": "Contacts",
|
||||
"leads": "Prospects",
|
||||
"reminders": "Rappels",
|
||||
"account": "Compte"
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"parent": "Parent",
|
||||
"status": "Statut",
|
||||
"dateStart": "Date de début",
|
||||
"dateEnd": "Date de fin",
|
||||
"direction": "Direction",
|
||||
"duration": "Durée",
|
||||
"description": "Description",
|
||||
"users": "Utilisateurs",
|
||||
"contacts": "Contacts",
|
||||
"leads": "Prospects",
|
||||
"reminders": "Notifications",
|
||||
"account": "Compte"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Planned": "Prévu",
|
||||
"Held": "Effectué",
|
||||
"Not Held": "Non effectué"
|
||||
},
|
||||
"links": {
|
||||
"direction": {
|
||||
"Outbound": "Sortant",
|
||||
"Inbound": "Entrant"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Planned": "Prévu",
|
||||
"Held": "Tenu",
|
||||
"Not Held": "Non tenu"
|
||||
},
|
||||
"direction": {
|
||||
"Outbound": "Sortant",
|
||||
"Inbound": "Entrant"
|
||||
},
|
||||
"acceptanceStatus": {
|
||||
"None": "Aucun",
|
||||
"Accepted": "Accepté",
|
||||
"Declined": "Décliné",
|
||||
"Tentative": "Tentative"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create Call": "Créer un Appel",
|
||||
"Set Held": "Qualifier en Tenu",
|
||||
"Set Not Held": "Qualifier en Non tenu",
|
||||
"Send Invitations": "Envoyer les invitations"
|
||||
},
|
||||
"presetFilters": {
|
||||
"planned": "Prévu",
|
||||
"held": "Tenu",
|
||||
"todays": "Aujourd'hui"
|
||||
"acceptanceStatus": {
|
||||
"None": "Aucun",
|
||||
"Accepted": "Accepté",
|
||||
"Declined": "Décliné",
|
||||
"Tentative": "Tentative"
|
||||
}
|
||||
}
|
||||
},
|
||||
"massActions": {
|
||||
"setHeld": "Définir comme effectué",
|
||||
"setNotHeld": "Définir comme non effectué"
|
||||
},
|
||||
"labels": {
|
||||
"Create Call": "Créer un appel",
|
||||
"Set Held": "Définir comme effectué",
|
||||
"Set Not Held": "Définir comme non effectué",
|
||||
"Send Invitations": "Envoyer les invitations"
|
||||
},
|
||||
"presetFilters": {
|
||||
"planned": "Prévu",
|
||||
"held": "Effectué",
|
||||
"todays": "Aujourd'hui"
|
||||
}
|
||||
}
|
||||
@@ -1,54 +1,71 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"description": "Description",
|
||||
"status": "Statut",
|
||||
"type": "Type",
|
||||
"startDate": "Date de début",
|
||||
"endDate": "Date de fin",
|
||||
"targetLists": "Listes de cibles",
|
||||
"sentCount": "Envoyé",
|
||||
"openedCount": "Ouvert",
|
||||
"clickedCount": "Cliqué",
|
||||
"optedOutCount": "Désinscrit",
|
||||
"bouncedCount": "Renvoyé",
|
||||
"hardBouncedCount": "Rejeté fortement",
|
||||
"softBouncedCount": "Rejeté",
|
||||
"leadCreatedCount": "Prospects créés",
|
||||
"revenue": "Revenu"
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"description": "Description",
|
||||
"status": "Statut",
|
||||
"type": "Type",
|
||||
"startDate": "Date de début",
|
||||
"endDate": "Date de fin",
|
||||
"targetLists": "Listes de cibles",
|
||||
"excludingTargetLists": "Exclure les listes de cibles",
|
||||
"sentCount": "Envoyé",
|
||||
"openedCount": "Ouvert",
|
||||
"clickedCount": "Cliqué",
|
||||
"optedOutCount": "Désinscrit",
|
||||
"bouncedCount": "Renvoyé",
|
||||
"hardBouncedCount": "Rejeté fortement",
|
||||
"softBouncedCount": "Rejeté",
|
||||
"leadCreatedCount": "Prospects créés",
|
||||
"revenue": "Revenu",
|
||||
"revenueConverted": "Revenu (converti)",
|
||||
"budget": "Budget",
|
||||
"budgetConverted": "Budget (converti)"
|
||||
},
|
||||
"links": {
|
||||
"targetLists": "Listes de cibles",
|
||||
"excludingTargetLists": "Excluant les listes de cibles",
|
||||
"accounts": "Comptes",
|
||||
"contacts": "Contacts",
|
||||
"leads": "Prospects",
|
||||
"opportunities": "Opportunités",
|
||||
"campaignLogRecords": "Enregistrer",
|
||||
"massEmails": "Emails groupés",
|
||||
"trackingUrls": "Tracking URLs"
|
||||
},
|
||||
"options": {
|
||||
"type": {
|
||||
"Email": "Email",
|
||||
"Web": "Web",
|
||||
"Television": "Télévision",
|
||||
"Radio": "Radio",
|
||||
"Newsletter": "Newsletter",
|
||||
"Mail": "Mail"
|
||||
},
|
||||
"links": {
|
||||
"targetLists": "Listes de cibles",
|
||||
"accounts": "Comptes",
|
||||
"contacts": "Contacts",
|
||||
"leads": "Prospects",
|
||||
"opportunities": "Opportunités",
|
||||
"campaignLogRecords": "Enregistrer"
|
||||
},
|
||||
"options": {
|
||||
"type": {
|
||||
"Email": "Email",
|
||||
"Web": "Web",
|
||||
"Television": "Télévision",
|
||||
"Radio": "Radio",
|
||||
"Newsletter": "Newsletter",
|
||||
"Mail": "Mail"
|
||||
},
|
||||
"status": {
|
||||
"Planning": "Planning",
|
||||
"Active": "Actif",
|
||||
"Inactive": "Inactif",
|
||||
"Complete": "Terminer"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create Campaign": "Créer une Campagne",
|
||||
"Target Lists": "Listes de cibles",
|
||||
"Statistics": "Statistiques",
|
||||
"hard": "fort",
|
||||
"soft": "faible"
|
||||
},
|
||||
"presetFilters": {
|
||||
"active": "Actif"
|
||||
"status": {
|
||||
"Planning": "Planning",
|
||||
"Active": "Actif",
|
||||
"Inactive": "Inactif",
|
||||
"Complete": "Terminer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create Campaign": "Créer une campagne",
|
||||
"Target Lists": "Listes de cibles",
|
||||
"Statistics": "Statistiques",
|
||||
"hard": "fort",
|
||||
"soft": "faible",
|
||||
"Unsubscribe": "Se désinscrire",
|
||||
"Mass Emails": "Emails groupés",
|
||||
"Email Templates": "Modèles d'email"
|
||||
},
|
||||
"presetFilters": {
|
||||
"active": "Actif"
|
||||
},
|
||||
"messages": {
|
||||
"unsubscribed": "Vous avez été désinscrit de notre liste d'envoi"
|
||||
},
|
||||
"tooltips": {
|
||||
"targetLists": "Cibles devant recevoir les messages",
|
||||
"excludingTargetLists": "Cibles ne devant pas recevoir les messages"
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,40 @@
|
||||
{
|
||||
"fields": {
|
||||
"action": "Action",
|
||||
"actionDate": "Date",
|
||||
"data": "Donnée",
|
||||
"campaign": "Campagne",
|
||||
"parent": "Cible",
|
||||
"object": "Objet",
|
||||
"application": "Application"
|
||||
},
|
||||
"options": {
|
||||
"action": {
|
||||
"Sent": "Envoyé",
|
||||
"Opened": "Ouvert",
|
||||
"Opted Out": "Désinscrit",
|
||||
"Bounced": "Renvoyé",
|
||||
"Clicked": "Cliqué",
|
||||
"Lead Created": "Prospect créé"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"All": "Tous"
|
||||
"fields": {
|
||||
"action": "Action",
|
||||
"actionDate": "Date",
|
||||
"data": "Donnée",
|
||||
"campaign": "Campagne",
|
||||
"parent": "Cible",
|
||||
"object": "Objet",
|
||||
"application": "Application",
|
||||
"queueItem": "Mettre en file d'attente",
|
||||
"stringData": "Chaîne de texte",
|
||||
"stringAdditionalData": "String Additional Data"
|
||||
},
|
||||
"links": {
|
||||
"queueItem": "Mettre en file d'attente",
|
||||
"parent": "Parent",
|
||||
"object": "Objet"
|
||||
},
|
||||
"options": {
|
||||
"action": {
|
||||
"Sent": "Envoyé",
|
||||
"Opened": "Ouvert",
|
||||
"Opted Out": "Désinscrit",
|
||||
"Bounced": "Renvoyé",
|
||||
"Clicked": "Cliqué",
|
||||
"Lead Created": "Prospect créé"
|
||||
}
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"All": "Tous"
|
||||
},
|
||||
"presetFilters": {
|
||||
"sent": "Envoyé",
|
||||
"opened": "Ouvert",
|
||||
"optedOut": "Opted Out",
|
||||
"bounced": "Bounced",
|
||||
"clicked": "Cliqué",
|
||||
"leadCreated": "Prospect créé"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"fields": {
|
||||
"url": "URL",
|
||||
"urlToUse": "Code à insérer au lieu de l'URL",
|
||||
"campaign": "Campagne"
|
||||
},
|
||||
"links": {
|
||||
"campaign": "Campagne"
|
||||
},
|
||||
"labels": {
|
||||
"Create CampaignTrackingUrl": "Create Tracking URL"
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,59 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"number": "Nombre",
|
||||
"status": "Statut",
|
||||
"account": "Compte",
|
||||
"contact": "Contact",
|
||||
"priority": "Priorité",
|
||||
"type": "Type",
|
||||
"description": "Description"
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"number": "Nombre",
|
||||
"status": "Statut",
|
||||
"account": "Compte",
|
||||
"contact": "Contact",
|
||||
"contacts": "Contacts",
|
||||
"priority": "Priorité",
|
||||
"type": "Type",
|
||||
"description": "Description",
|
||||
"inboundEmail": "Email entrant",
|
||||
"lead": "Prospect"
|
||||
},
|
||||
"links": {
|
||||
"inboundEmail": "Emails entrants",
|
||||
"account": "Compte",
|
||||
"contact": "Contact (principal)",
|
||||
"Contacts": "Contacts",
|
||||
"meetings": "Rendez-vous",
|
||||
"calls": "Appels",
|
||||
"tasks": "Tâches",
|
||||
"emails": "Emails",
|
||||
"articles": "Articles base de connaissance",
|
||||
"lead": "Prospect"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"New": "Nouveau",
|
||||
"Assigned": "Assigné",
|
||||
"Pending": "En cours",
|
||||
"Closed": "Fermé",
|
||||
"Rejected": "Rejeté",
|
||||
"Duplicate": "Dupliquer"
|
||||
},
|
||||
"links": {
|
||||
"priority": {
|
||||
"Low": "Basse",
|
||||
"Normal": "Normale",
|
||||
"High": "Haute",
|
||||
"Urgent": "Urgente"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"New": "Nouveau",
|
||||
"Assigned": "Assigné",
|
||||
"Pending": "En cours",
|
||||
"Closed": "Fermé",
|
||||
"Rejected": "Rejeté",
|
||||
"Duplicate": "Dupliquer"
|
||||
},
|
||||
"priority" : {
|
||||
"Low": "Basse",
|
||||
"Normal": "Normale",
|
||||
"High": "Haute",
|
||||
"Urgent": "Urgente"
|
||||
},
|
||||
"type": {
|
||||
"Question": "Question",
|
||||
"Incident": "Incident",
|
||||
"Problem": "Problème"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create Case": "Créer un ticket"
|
||||
},
|
||||
"presetFilters": {
|
||||
"open": "Ouvert",
|
||||
"closed": "Fermé"
|
||||
"type": {
|
||||
"Question": "Question",
|
||||
"Incident": "Incident",
|
||||
"Problem": "Problème"
|
||||
}
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create Case": "Créer un ticket",
|
||||
"Close": "Fermer",
|
||||
"Reject": "Rejeter",
|
||||
"Closed": "Fermé",
|
||||
"Rejected": "Rejeté"
|
||||
},
|
||||
"presetFilters": {
|
||||
"open": "Ouvert",
|
||||
"closed": "Fermé"
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,46 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"emailAddress": "Email",
|
||||
"title": "Titre",
|
||||
"account": "Compte",
|
||||
"accounts": "Comptes",
|
||||
"phoneNumber": "Téléphone",
|
||||
"accountType": "Type de compte",
|
||||
"doNotCall": "Ne pas appeler",
|
||||
"address": "Adresse",
|
||||
"opportunityRole": "Rôle d'opportunité",
|
||||
"accountRole": "Titre",
|
||||
"description": "Description",
|
||||
"campaign": "Campagne",
|
||||
"targetLists": "Listes de cibles",
|
||||
"targetList": "Liste de cibles"
|
||||
},
|
||||
"links": {
|
||||
"opportunities": "Opportunités",
|
||||
"cases": "Tickets",
|
||||
"targetLists": "Listes de cibles",
|
||||
"campaignLogRecords": "Rapporter une campagne"
|
||||
},
|
||||
"labels": {
|
||||
"Create Contact": "Créer un Contact"
|
||||
},
|
||||
"options": {
|
||||
"opportunityRole": {
|
||||
"": "--Aucun--",
|
||||
"Decision Maker": "Décisionnaire",
|
||||
"Evaluator": "Évaluateur",
|
||||
"Influencer": "Influenceur"
|
||||
}
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"emailAddress": "Email",
|
||||
"title": "Titre",
|
||||
"accountRole": "Titre",
|
||||
"account": "Compte",
|
||||
"accounts": "Comptes",
|
||||
"phoneNumber": "Téléphone",
|
||||
"accountType": "Type de compte",
|
||||
"doNotCall": "Ne pas appeler",
|
||||
"address": "Adresse",
|
||||
"opportunityRole": "Rôle d'opportunité",
|
||||
"description": "Description",
|
||||
"campaign": "Campagne",
|
||||
"targetLists": "Listes de cibles",
|
||||
"targetList": "Liste de cibles",
|
||||
"portalUser": "Utilisateur Portail"
|
||||
},
|
||||
"links": {
|
||||
"opportunities": "Opportunités",
|
||||
"cases": "Tickets",
|
||||
"targetLists": "Listes de cibles",
|
||||
"campaignLogRecords": "Rapporter une campagne",
|
||||
"campaign": "Campagne",
|
||||
"account": "Compte (principal)",
|
||||
"accounts": "Comptes",
|
||||
"casesPrimary": "Tickets (principal)",
|
||||
"portalUser": "Utilisateur Portail"
|
||||
},
|
||||
"labels": {
|
||||
"Create Contact": "Créer un Contact"
|
||||
},
|
||||
"options": {
|
||||
"opportunityRole": {
|
||||
"": "--Aucun--",
|
||||
"Decision Maker": "Décisionnaire",
|
||||
"Evaluator": "Évaluateur",
|
||||
"Influencer": "Influenceur"
|
||||
}
|
||||
}
|
||||
},
|
||||
"presetFilters": {
|
||||
"portalUsers": "Utilisateurs Portail",
|
||||
"notPortalUsers": "N'est pas un utilisateur Portail"
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,42 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create Document": "Créer un Document",
|
||||
"Details": "Détails"
|
||||
"labels": {
|
||||
"Create Document": "Créer un Document",
|
||||
"Details": "Détails"
|
||||
},
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"status": "Statut",
|
||||
"file": "Fichier",
|
||||
"type": "Type",
|
||||
"publishDate": "Date de publication",
|
||||
"expirationDate": "Date d'expiration",
|
||||
"description": "Description",
|
||||
"accounts": "Comptes",
|
||||
"folder": "Dossier"
|
||||
},
|
||||
"links": {
|
||||
"accounts": "Comptes",
|
||||
"opportunities": "Opportunités",
|
||||
"folder": "Dossier",
|
||||
"leads": "Prospects"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Active": "Actif",
|
||||
"Draft": "Brouillon",
|
||||
"Expired": "Expiré",
|
||||
"Canceled": "Annulé"
|
||||
},
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"status": "Statut",
|
||||
"file": "Fichier",
|
||||
"type": "Type",
|
||||
"source": "Source",
|
||||
"publishDate": "Date de publication",
|
||||
"expirationDate": "Date d'expiration",
|
||||
"description": "Description"
|
||||
},
|
||||
"links": {
|
||||
"accounts": "Comptes",
|
||||
"opportunities": "Opportunités"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Active": "Actif",
|
||||
"Draft": "Brouillon",
|
||||
"Expired": "Expiré",
|
||||
"Canceled": "Annulé"
|
||||
}
|
||||
},
|
||||
"presetFilters": {
|
||||
"active": "Actif",
|
||||
"draft": "Brouillon"
|
||||
"type": {
|
||||
"": "Aucun",
|
||||
"Contract": "Contrat",
|
||||
"NDA": "NDA",
|
||||
"EULA": "EULA",
|
||||
"License Agreement": "Accord de licence"
|
||||
}
|
||||
}
|
||||
},
|
||||
"presetFilters": {
|
||||
"active": "Actif",
|
||||
"draft": "Brouillon"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create DocumentFolder": "Créer un dossier",
|
||||
"Manage Categories": "Gérer les dossiers",
|
||||
"Documents": "Documents"
|
||||
},
|
||||
"links": {
|
||||
"documents": "Documents"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create Lead": "Créer un Prospect",
|
||||
"Create Contact": "Créer un Contact",
|
||||
"Create Task": "Créer une tâche",
|
||||
"Create Case": "Créer un Ticket"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"status": "Statut",
|
||||
"target": "Cible",
|
||||
"sentAt": "Date d'envoi",
|
||||
"attemptCount": "Tentatives",
|
||||
"emailAddress": "Adresse email",
|
||||
"massEmail": "Emails groupé",
|
||||
"isTest": "Test"
|
||||
},
|
||||
"links": {
|
||||
"target": "Cible",
|
||||
"massEmail": "Emails groupé"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Pending": "En cours",
|
||||
"Sent": "Envoyé",
|
||||
"Failed": "Echec"
|
||||
}
|
||||
},
|
||||
"presetFilters": {
|
||||
"pending": "En cours",
|
||||
"sent": "Envoyé",
|
||||
"failed": "Échec"
|
||||
}
|
||||
}
|
||||
@@ -1,100 +1,116 @@
|
||||
{
|
||||
"scopeNames": {
|
||||
"Account": "Compte",
|
||||
"Contact": "Contact",
|
||||
"Lead": "Prospect",
|
||||
"Target": "Cible",
|
||||
"Opportunity": "Opportunité",
|
||||
"Meeting": "Rendez-vous",
|
||||
"Calendar": "Calendrier",
|
||||
"Call": "Appel",
|
||||
"Task": "Tâche",
|
||||
"Case": "Ticket",
|
||||
"InboundEmail": "Email entrant",
|
||||
"Document": "Document",
|
||||
"Campaign": "Campagne",
|
||||
"TargetList": "Liste de cibles"
|
||||
},
|
||||
"scopeNamesPlural": {
|
||||
"Account": "Comptes",
|
||||
"Contact": "Contacts",
|
||||
"Lead": "Prospects",
|
||||
"Target": "Cibles",
|
||||
"Opportunity": "Opportunités",
|
||||
"Meeting": "Rendez-vous",
|
||||
"Calendar": "Calendrier",
|
||||
"Call": "Appels",
|
||||
"Task": "Tâches",
|
||||
"Case": "Tickets",
|
||||
"InboundEmail": "Emails entrants",
|
||||
"Document": "Documents",
|
||||
"Campaign": "Campagnes",
|
||||
"TargetList": "Listes de cibles"
|
||||
},
|
||||
"dashlets": {
|
||||
"Leads": "Mes prospects",
|
||||
"Opportunities": "Mes opportunités",
|
||||
"Tasks": "Mes tâches",
|
||||
"Cases": "Mes tickets",
|
||||
"Calendar": "Calendrier",
|
||||
"Calls": "Mes appels",
|
||||
"Meetings": "Mes rendez-vous",
|
||||
"OpportunitiesByStage": "Opportunités par étape",
|
||||
"OpportunitiesByLeadSource": "Opportunités par source de prospects",
|
||||
"SalesByMonth": "Ventes par mois",
|
||||
"SalesPipeline": "Canaux de vente"
|
||||
},
|
||||
"labels": {
|
||||
"Create InboundEmail": "Créer un email entrant",
|
||||
"Activities": "Activités",
|
||||
"History": "Historique",
|
||||
"Attendees": "Participants",
|
||||
"Schedule Meeting": "Planifier un rendez-vous",
|
||||
"Schedule Call": "Programmer un appel",
|
||||
"Compose Email": "Composer un Email",
|
||||
"Log Meeting": "Rapporter un rendez-vous",
|
||||
"Log Call": "Rapporter un appel",
|
||||
"Archive Email": "Archiver l'Email",
|
||||
"Create Task": "Créer une Tâche",
|
||||
"Tasks": "Tâches"
|
||||
},
|
||||
"fields": {
|
||||
"billingAddressCity": "Ville",
|
||||
"billingAddressCountry": "Pays",
|
||||
"billingAddressPostalCode": "Code Postal",
|
||||
"billingAddressState": "Région",
|
||||
"billingAddressStreet": "Rue",
|
||||
"addressCity": "Ville",
|
||||
"addressStreet": "Rue",
|
||||
"addressCountry": "Pays",
|
||||
"addressState": "Régions",
|
||||
"addressPostalCode": "Code Postal",
|
||||
"shippingAddressCity": "Ville (livraison)",
|
||||
"shippingAddressStreet": "Rue (livraison)",
|
||||
"shippingAddressCountry": "Pays (livraison)",
|
||||
"shippingAddressState": "Région (livraison)",
|
||||
"shippingAddressPostalCode": "Code Postal (livraison)"
|
||||
},
|
||||
"links": {
|
||||
"contacts": "Contacts",
|
||||
"opportunities": "Opportunités",
|
||||
"leads": "Prospects",
|
||||
"meetings": "Rendez-vous",
|
||||
"calls": "Appels",
|
||||
"tasks": "Tâches",
|
||||
"emails": "Emails",
|
||||
"accounts": "Comptes",
|
||||
"cases": "Tickets",
|
||||
"documents": "Documents",
|
||||
"account": "Compte",
|
||||
"opportunity": "Opportunité",
|
||||
"contact": "Contact",
|
||||
"parent": "Parent"
|
||||
},
|
||||
"options": {
|
||||
"reminderTypes": {
|
||||
"Popup": "Popup",
|
||||
"Email": "Email"
|
||||
}
|
||||
"links": {
|
||||
"parent": "Parent",
|
||||
"contacts": "Contacts",
|
||||
"opportunities": "Opportunités",
|
||||
"leads": "Prospects",
|
||||
"meetings": "Rendez-vous",
|
||||
"calls": "Appels",
|
||||
"tasks": "Tâches",
|
||||
"emails": "Emails",
|
||||
"accounts": "Comptes",
|
||||
"cases": "Tickets",
|
||||
"documents": "Documents",
|
||||
"account": "Compte",
|
||||
"opportunity": "Opportunité",
|
||||
"contact": "Contact"
|
||||
},
|
||||
"scopeNames": {
|
||||
"Account": "Compte",
|
||||
"Contact": "Contact",
|
||||
"Lead": "Prospect",
|
||||
"Target": "Cible",
|
||||
"Opportunity": "Opportunité",
|
||||
"Meeting": "Rendez-vous",
|
||||
"Calendar": "Calendrier",
|
||||
"Call": "Appel",
|
||||
"Task": "Tâche",
|
||||
"Case": "Ticket",
|
||||
"Document": "Document",
|
||||
"DocumentFolder": "Dossier",
|
||||
"Campaign": "Campagne",
|
||||
"TargetList": "Liste de cibles",
|
||||
"MassEmail": "Emails groupé",
|
||||
"EmailQueueItem": "Email Queue Item",
|
||||
"CampaignTrackingUrl": "Tracking URL",
|
||||
"Activities": "Activités",
|
||||
"KnowledgeBaseArticle": "Article de la base de connaissance",
|
||||
"KnowledgeBaseCategory": "Catégorie de la base de connaissance"
|
||||
},
|
||||
"scopeNamesPlural": {
|
||||
"Account": "Comptes",
|
||||
"Contact": "Contacts",
|
||||
"Lead": "Prospects",
|
||||
"Target": "Cibles",
|
||||
"Opportunity": "Opportunités",
|
||||
"Meeting": "Rendez-vous",
|
||||
"Calendar": "Calendrier",
|
||||
"Call": "Appels",
|
||||
"Task": "Tâches",
|
||||
"Case": "Tickets",
|
||||
"Document": "Documents",
|
||||
"DocumentFolder": "Dossiers",
|
||||
"Campaign": "Campagnes",
|
||||
"TargetList": "Listes de cibles",
|
||||
"MassEmail": "Emails groupés",
|
||||
"EmailQueueItem": "Email Queue Items",
|
||||
"CampaignTrackingUrl": "Tracking URLs",
|
||||
"Activities": "Activités",
|
||||
"KnowledgeBaseArticle": "Base de connaissance",
|
||||
"KnowledgeBaseCategory": "Catégories de la base de connaissance"
|
||||
},
|
||||
"dashlets": {
|
||||
"Leads": "Mes prospects",
|
||||
"Opportunities": "Mes opportunités",
|
||||
"Tasks": "Mes tâches",
|
||||
"Cases": "Mes tickets",
|
||||
"Calendar": "Calendrier",
|
||||
"Calls": "Mes appels",
|
||||
"Meetings": "Mes rendez-vous",
|
||||
"OpportunitiesByStage": "Opportunités par étape",
|
||||
"OpportunitiesByLeadSource": "Opportunités par source de prospects",
|
||||
"SalesByMonth": "Ventes par mois",
|
||||
"SalesPipeline": "Canaux de vente",
|
||||
"Activities": "Mes activités"
|
||||
},
|
||||
"labels": {
|
||||
"Create InboundEmail": "Créer un email entrant",
|
||||
"Activities": "Activités",
|
||||
"History": "Historique",
|
||||
"Attendees": "Participants",
|
||||
"Schedule Meeting": "Planifier un rendez-vous",
|
||||
"Schedule Call": "Programmer un appel",
|
||||
"Compose Email": "Composer un Email",
|
||||
"Log Meeting": "Rapporter un rendez-vous",
|
||||
"Log Call": "Rapporter un appel",
|
||||
"Archive Email": "Archiver l'Email",
|
||||
"Create Task": "Créer une tâche",
|
||||
"Tasks": "Tâches"
|
||||
},
|
||||
"fields": {
|
||||
"billingAddressCity": "Ville",
|
||||
"addressCity": "Ville",
|
||||
"billingAddressCountry": "Pays",
|
||||
"addressCountry": "Pays",
|
||||
"billingAddressPostalCode": "Code postal",
|
||||
"addressPostalCode": "Code postal",
|
||||
"billingAddressState": "Régions",
|
||||
"addressState": "Régions",
|
||||
"billingAddressStreet": "Rue",
|
||||
"addressStreet": "Rue",
|
||||
"billingAddressMap": "Carte",
|
||||
"addressMap": "Carte",
|
||||
"shippingAddressCity": "Ville (livraison)",
|
||||
"shippingAddressStreet": "Rue (livraison)",
|
||||
"shippingAddressCountry": "Pays (livraison)",
|
||||
"shippingAddressState": "Région (livraison)",
|
||||
"shippingAddressPostalCode": "Code Postal (livraison)",
|
||||
"shippingAddressMap": "Carte (Transport)"
|
||||
},
|
||||
"options": {
|
||||
"reminderTypes": {
|
||||
"Popup": "Popup",
|
||||
"Email": "Email"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create KnowledgeBaseArticle": "Créer un article",
|
||||
"Any": "Any",
|
||||
"Send in Email": "Send in Email"
|
||||
},
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"status": "Statut",
|
||||
"type": "Type",
|
||||
"attachments": "Pièces jointes",
|
||||
"publishDate": "Date de publication",
|
||||
"expirationDate": "Date d'expiration",
|
||||
"description": "Description",
|
||||
"body": "Corps de texte",
|
||||
"categories": "Catégories",
|
||||
"language": "Langue",
|
||||
"portals": "Portails"
|
||||
},
|
||||
"links": {
|
||||
"cases": "Tickets",
|
||||
"opportunities": "Opportunités",
|
||||
"categories": "Catégories",
|
||||
"portals": "Portails"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"In Review": "In Review",
|
||||
"Draft": "Brouillon",
|
||||
"Archived": "Archivé",
|
||||
"Published": "Publié"
|
||||
},
|
||||
"type": {
|
||||
"Article": "Article"
|
||||
}
|
||||
},
|
||||
"tooltips": {
|
||||
"portals": "If not empty then this article will be available only in specified portals. If empty then it will available in all portals."
|
||||
},
|
||||
"presetFilters": {
|
||||
"published": "Publié"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"labels": {
|
||||
"Create KnowledgeBaseCategory": "Créer une catégorie",
|
||||
"Manage Categories": "Gérer les catégories",
|
||||
"Articles": "Articles"
|
||||
},
|
||||
"links": {
|
||||
"articles": "Articles"
|
||||
}
|
||||
}
|
||||
@@ -1,56 +1,64 @@
|
||||
{
|
||||
"labels": {
|
||||
"Converted To": "Converti en",
|
||||
"Create Lead": "Créer un prospect",
|
||||
"Convert": "Convertir"
|
||||
"labels": {
|
||||
"Converted To": "Converti en",
|
||||
"Create Lead": "Créer un prospect",
|
||||
"Convert": "Convertir"
|
||||
},
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"emailAddress": "Email",
|
||||
"title": "Titre",
|
||||
"website": "Site internet",
|
||||
"phoneNumber": "Téléphone",
|
||||
"accountName": "Nom du compte",
|
||||
"doNotCall": "Ne pas appeler",
|
||||
"address": "Adresse",
|
||||
"status": "Statut",
|
||||
"source": "Source",
|
||||
"opportunityAmount": "Montant en jeu de l'opportunité",
|
||||
"opportunityAmountConverted": "Montant en jeu de l'opportunité (converti)",
|
||||
"description": "Description",
|
||||
"createdAccount": "Compte",
|
||||
"createdContact": "Contact",
|
||||
"createdOpportunity": "Opportunité",
|
||||
"campaign": "Campagne",
|
||||
"targetLists": "Listes de cibles",
|
||||
"targetList": "Liste de cibles"
|
||||
},
|
||||
"links": {
|
||||
"targetLists": "Listes de cibles",
|
||||
"campaignLogRecords": "Journaux de campagne",
|
||||
"campaign": "Campagne",
|
||||
"createdAccount": "Compte",
|
||||
"createdContact": "Contact",
|
||||
"createdOpportunity": "Opportunité",
|
||||
"cases": "Tickets",
|
||||
"documents": "Documents"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"New": "Nouveau",
|
||||
"Assigned": "Assigné",
|
||||
"In Process": "En cours",
|
||||
"Converted": "Converti",
|
||||
"Recycled": "Recyclé",
|
||||
"Dead": "Dead"
|
||||
},
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"emailAddress": "Email",
|
||||
"title": "Titre",
|
||||
"website": "Site internet",
|
||||
"phoneNumber": "Téléphone",
|
||||
"accountName": "Nom du compte",
|
||||
"doNotCall": "Ne pas appeler",
|
||||
"address": "Adresse",
|
||||
"status": "Statut",
|
||||
"source": "Source",
|
||||
"opportunityAmount": "Montant en jeu de l'opportunité",
|
||||
"opportunityAmountConverted": "Montant en jeu de l'opportunité (converti)",
|
||||
"description": "Description",
|
||||
"createdAccount": "Compte",
|
||||
"createdContact": "Contact",
|
||||
"createdOpportunity": "Opportunité",
|
||||
"campaign": "Campagne",
|
||||
"targetLists": "Listes de cibles",
|
||||
"targetList": "Liste de cibles"
|
||||
},
|
||||
"links": {
|
||||
"targetLists": "Listes de cibles",
|
||||
"campaignLogRecords": "Log de campagne"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"New": "Nouveau",
|
||||
"Assigned": "Assigné",
|
||||
"In Process": "En cours",
|
||||
"Converted": "Converti",
|
||||
"Recycled": "Recyclé",
|
||||
"Dead": "Dead"
|
||||
},
|
||||
"source": {
|
||||
"Call": "Appel",
|
||||
"Email": "Email",
|
||||
"Existing Customer": "Client existant",
|
||||
"Partner": "Partenaire",
|
||||
"Public Relations": "Relations publiques",
|
||||
"Web Site": "Site internet",
|
||||
"Campaign": "Campagne",
|
||||
"Other": "Autre"
|
||||
}
|
||||
},
|
||||
"presetFilters": {
|
||||
"active": "Actif",
|
||||
"actual": "En cours"
|
||||
"source": {
|
||||
"": "Aucun",
|
||||
"Call": "Appel",
|
||||
"Email": "Email",
|
||||
"Existing Customer": "Client existant",
|
||||
"Partner": "Partenaire",
|
||||
"Public Relations": "Relations publiques",
|
||||
"Web Site": "Site internet",
|
||||
"Campaign": "Campagne",
|
||||
"Other": "Autre"
|
||||
}
|
||||
}
|
||||
},
|
||||
"presetFilters": {
|
||||
"active": "Actif",
|
||||
"actual": "En cours",
|
||||
"converted": "Converti"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"status": "Statut",
|
||||
"storeSentEmails": "Store Sent Emails",
|
||||
"startAt": "Date Start",
|
||||
"fromAddress": "From Address",
|
||||
"fromName": "From Name",
|
||||
"replyToAddress": "Reply-to Address",
|
||||
"replyToName": "Reply-to Name",
|
||||
"campaign": "Campagne",
|
||||
"emailTemplate": "modèle d'email",
|
||||
"inboundEmail": "Compte email",
|
||||
"targetLists": "listes de cibles",
|
||||
"excludingTargetLists": "Excluding Target Lists",
|
||||
"optOutEntirely": "Opt-Out Entirely"
|
||||
},
|
||||
"links": {
|
||||
"targetLists": "listes de cibles",
|
||||
"excludingTargetLists": "Excluding Target Lists",
|
||||
"queueItems": "Queue Items",
|
||||
"campaign": "Campagne",
|
||||
"emailTemplate": "modèle d'email",
|
||||
"inboundEmail": "Compte email"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Draft": "Brouillon",
|
||||
"Pending": "En attente",
|
||||
"In Process": "En cours",
|
||||
"Complete": "Terminé",
|
||||
"Canceled": "Annulé",
|
||||
"Failed": "Échec"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create MassEmail": "Créer un email groupé",
|
||||
"Send Test": "Envoyer un message de test"
|
||||
},
|
||||
"messages": {
|
||||
"selectAtLeastOneTarget": "Sélectionner au moins une cible",
|
||||
"testSent": "Test email(s) supposed to be sent"
|
||||
},
|
||||
"tooltips": {
|
||||
"optOutEntirely": "Email addresses of recipients that unsubscribed will be marked as opted out and they will not receive any mass emails anymore.",
|
||||
"targetLists": "Targets that should receive messages.",
|
||||
"excludingTargetLists": "Targets that should not receive messages."
|
||||
}
|
||||
}
|
||||
@@ -1,44 +1,46 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"parent": "Parent",
|
||||
"status": "Statut",
|
||||
"dateStart": "Date de début",
|
||||
"dateEnd": "Date de fin",
|
||||
"duration": "Durée",
|
||||
"description": "Description",
|
||||
"users": "Utilisateurs",
|
||||
"contacts": "Contacts",
|
||||
"leads": "Prospects",
|
||||
"reminders": "Rappels",
|
||||
"account": "Compte"
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"parent": "Parent",
|
||||
"status": "Statut",
|
||||
"dateStart": "Date de début",
|
||||
"dateEnd": "Date de fin",
|
||||
"duration": "Durée",
|
||||
"description": "Description",
|
||||
"users": "Utilisateurs",
|
||||
"contacts": "Contacts",
|
||||
"leads": "Prospects",
|
||||
"reminders": "Notifications",
|
||||
"account": "Compte"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Planned": "Prévu",
|
||||
"Held": "Effectué",
|
||||
"Not Held": "Non effectué"
|
||||
},
|
||||
"links": {
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Planned": "Prévu",
|
||||
"Held": "Tenu",
|
||||
"Not Held": "Non tenu"
|
||||
},
|
||||
"acceptanceStatus": {
|
||||
"None": "Aucun",
|
||||
"Accepted": "Accepté",
|
||||
"Declined": "Décliné",
|
||||
"Tentative": "Tentative"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create Meeting": "Créer un Rendez-vous",
|
||||
"Set Held": "Qualifier en tenu",
|
||||
"Set Not Held": "Qualifier en non tenu",
|
||||
"Send Invitations": "Envoyer des Invitations",
|
||||
"on time": "à l'heure",
|
||||
"before": "en avance"
|
||||
},
|
||||
"presetFilters": {
|
||||
"planned": "Prévu",
|
||||
"held": "Tenu",
|
||||
"todays": "Aujourd'hui"
|
||||
"acceptanceStatus": {
|
||||
"None": "Aucun",
|
||||
"Accepted": "Accepté",
|
||||
"Declined": "Décliné",
|
||||
"Tentative": "Tentative"
|
||||
}
|
||||
}
|
||||
},
|
||||
"massActions": {
|
||||
"setHeld": "Définir comme effectué",
|
||||
"setNotHeld": "Définir comme non effectué"
|
||||
},
|
||||
"labels": {
|
||||
"Create Meeting": "Créer un Rendez-vous",
|
||||
"Set Held": "Définir comme effectué",
|
||||
"Set Not Held": "Définir comme non effectué",
|
||||
"Send Invitations": "Envoyer des Invitations",
|
||||
"on time": "à l'heure",
|
||||
"before": "en avance"
|
||||
},
|
||||
"presetFilters": {
|
||||
"planned": "Prévu",
|
||||
"held": "Effectué",
|
||||
"todays": "Aujourd'hui"
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,44 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"account": "Compte",
|
||||
"stage": "Etape",
|
||||
"amount": "Montant",
|
||||
"probability": "Probabilité, %",
|
||||
"leadSource": "Source du prospect",
|
||||
"doNotCall": "Ne pas appeler",
|
||||
"closeDate": "Date de fermeture",
|
||||
"contacts": "Contacts",
|
||||
"description": "Description",
|
||||
"amountConverted": "Montant (converti)",
|
||||
"amountWeightedConverted": "Montant pondéré",
|
||||
"campaign": "Campagne"
|
||||
},
|
||||
"links": {
|
||||
"contacts": "Contacts",
|
||||
"documents": "Documents"
|
||||
},
|
||||
"options": {
|
||||
"stage": {
|
||||
"Prospecting": "Prospection",
|
||||
"Qualification": "Qualification",
|
||||
"Needs Analysis": "Analyse des besoins",
|
||||
"Value Proposition": "Valeur de la proposition",
|
||||
"Id. Decision Makers": "Id. Decisionnaire",
|
||||
"Perception Analysis": "Analyse de la perception",
|
||||
"Proposal/Price Quote": "Proposition/devis",
|
||||
"Negotiation/Review": "Négociation/évaluation",
|
||||
"Closed Won": "Conclusion gagnante",
|
||||
"Closed Lost": "Conclusion perdante"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create Opportunity": "Créer une opportunité"
|
||||
},
|
||||
"presetFilters": {
|
||||
"open": "Ouvrir",
|
||||
"won": "Gagné"
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"account": "Compte",
|
||||
"stage": "Etape",
|
||||
"amount": "Montant",
|
||||
"probability": "Probabilité, %",
|
||||
"leadSource": "Source du prospect",
|
||||
"doNotCall": "Ne pas appeler",
|
||||
"closeDate": "Date de fermeture",
|
||||
"contacts": "Contacts",
|
||||
"description": "Description",
|
||||
"amountConverted": "Montant (converti)",
|
||||
"amountWeightedConverted": "Montant pondéré",
|
||||
"campaign": "Campagne"
|
||||
},
|
||||
"links": {
|
||||
"contacts": "Contacts",
|
||||
"documents": "Documents",
|
||||
"campaign": "Campagne"
|
||||
},
|
||||
"options": {
|
||||
"stage": {
|
||||
"Prospecting": "Prospection",
|
||||
"Qualification": "Qualification",
|
||||
"Needs Analysis": "Analyse des besoins",
|
||||
"Value Proposition": "Valeur de la proposition",
|
||||
"Id. Decision Makers": "Id. Decisionnaire",
|
||||
"Perception Analysis": "Analyse de la perception",
|
||||
"Proposal/Price Quote": "Proposition/devis",
|
||||
"Negotiation/Review": "Négociation/évaluation",
|
||||
"Closed Won": "Conclusion gagnante",
|
||||
"Closed Lost": "Conclusion perdante"
|
||||
}
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create Opportunity": "Créer une opportunité"
|
||||
},
|
||||
"presetFilters": {
|
||||
"open": "Ouvert",
|
||||
"won": "Gagné",
|
||||
"lost": "Perdu"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"links": {
|
||||
"articles": "Articles de la base de connaissance"
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
{
|
||||
|
||||
"options": {
|
||||
"job": {
|
||||
"CheckInboundEmails": "Vérifier les emails entrants",
|
||||
"CheckEmailAccounts": "Vérifier ses comptes emails personnels",
|
||||
"SendEmailReminders": "Envoyer des emails de rappel"
|
||||
}
|
||||
"options": {
|
||||
"job": {
|
||||
"ProcessMassEmail": "Envoyer emails groupés",
|
||||
"ControlKnowledgeBaseArticleStatus": "Control Knowledge Base Article Status"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,17 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"emailAddress": "Email",
|
||||
"title": "Titre",
|
||||
"website": "Site internet",
|
||||
"accountName": "Nom du compte",
|
||||
"phoneNumber": "Téléphone",
|
||||
"doNotCall": "Ne pas appeler",
|
||||
"address": "Adresse",
|
||||
"description": "Description"
|
||||
},
|
||||
"links": {
|
||||
},
|
||||
"labels": {
|
||||
"Create Target": "Créer une cible",
|
||||
"Convert to Lead": "Convertir en prospect"
|
||||
}
|
||||
}
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"emailAddress": "Email",
|
||||
"title": "Titre",
|
||||
"website": "Site internet",
|
||||
"accountName": "Nom du compte",
|
||||
"phoneNumber": "Téléphone",
|
||||
"doNotCall": "Ne pas appeler",
|
||||
"address": "Adresse",
|
||||
"description": "Description"
|
||||
},
|
||||
"labels": {
|
||||
"Create Target": "Créer une cible",
|
||||
"Convert to Lead": "Convertir en prospect"
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,32 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"description": "Description",
|
||||
"entryCount": "Compteur d'entrées",
|
||||
"campaigns": "Campagnes",
|
||||
"endDate": "Date de fin",
|
||||
"targetLists": "Listes de cibles"
|
||||
},
|
||||
"links": {
|
||||
"accounts": "Comptes",
|
||||
"contacts": "Contacts",
|
||||
"leads": "Prospects",
|
||||
"campaigns": "Campagnes"
|
||||
},
|
||||
"options": {
|
||||
"type": {
|
||||
"Email": "Email",
|
||||
"Web": "Web",
|
||||
"Television": "Télévision",
|
||||
"Radio": "Radio",
|
||||
"Newsletter": "Newsletter"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create TargetList": "Créer une liste de cibles"
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"description": "Description",
|
||||
"entryCount": "Compteur d'entrées",
|
||||
"campaigns": "Campagnes",
|
||||
"endDate": "Date de fin",
|
||||
"targetLists": "Listes de cibles"
|
||||
},
|
||||
"links": {
|
||||
"accounts": "Comptes",
|
||||
"contacts": "Contacts",
|
||||
"leads": "Prospects",
|
||||
"campaigns": "Campagnes",
|
||||
"massEmails": "Emails groupés"
|
||||
},
|
||||
"options": {
|
||||
"type": {
|
||||
"Email": "Email",
|
||||
"Web": "Web",
|
||||
"Television": "Télévision",
|
||||
"Radio": "Radio",
|
||||
"Newsletter": "Newsletter"
|
||||
}
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create TargetList": "Créer une liste de cibles",
|
||||
"Opted Out": "Opted Out",
|
||||
"Cancel Opt-Out": "Cancel Opt-Out",
|
||||
"Opt-Out": "Opt-Out"
|
||||
}
|
||||
}
|
||||
@@ -1,43 +1,45 @@
|
||||
{
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"parent": "Parent",
|
||||
"status": "Statut",
|
||||
"dateStart": "Date de début",
|
||||
"dateEnd": "Date d'échéance",
|
||||
"dateStartDate": "Date de début (toute la journée)",
|
||||
"dateEndDate": "Date de fin (toute la journée)",
|
||||
"priority": "Priorité",
|
||||
"description": "Description",
|
||||
"isOverdue": "En retard",
|
||||
"account": "Compte"
|
||||
"fields": {
|
||||
"name": "Nom",
|
||||
"parent": "Parent",
|
||||
"status": "Statut",
|
||||
"dateStart": "Date de début",
|
||||
"dateEnd": "Date d'échéance",
|
||||
"dateStartDate": "Date de début (toute la journée)",
|
||||
"dateEndDate": "Date de fin (toute la journée)",
|
||||
"priority": "Priorité",
|
||||
"description": "Description",
|
||||
"isOverdue": "En retard",
|
||||
"account": "Compte",
|
||||
"dateCompleted": "Date de Clôture",
|
||||
"attachments": "Pièces jointes"
|
||||
},
|
||||
"links": {
|
||||
"attachments": "Pièces jointes"
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Not Started": "N'a pas démarré",
|
||||
"Started": "Démarré",
|
||||
"Completed": "Terminé",
|
||||
"Canceled": "Annulé",
|
||||
"Deferred": "Reporté"
|
||||
},
|
||||
"links": {
|
||||
},
|
||||
"options": {
|
||||
"status": {
|
||||
"Not Started": "N'a pas démarré",
|
||||
"Started": "Démarré",
|
||||
"Completed": "Terminé",
|
||||
"Canceled": "Annulé",
|
||||
"Deferred": "Reporté"
|
||||
},
|
||||
"priority" : {
|
||||
"Low": "Basse",
|
||||
"Normal": "Normale",
|
||||
"High": "Haute",
|
||||
"Urgent": "Urgente"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create Task": "Créer une Tâche",
|
||||
"Complete": "Terminer"
|
||||
},
|
||||
"presetFilters": {
|
||||
"actual": "En cours",
|
||||
"completed": "Terminés",
|
||||
"todays": "Aujourd'hui",
|
||||
"deferred": "Reporté",
|
||||
"overdue": "En retard"
|
||||
"priority": {
|
||||
"Low": "Basse",
|
||||
"Normal": "Normale",
|
||||
"High": "Haute",
|
||||
"Urgent": "Urgente"
|
||||
}
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"Create Task": "Créer une tâche",
|
||||
"Complete": "Clôturer"
|
||||
},
|
||||
"presetFilters": {
|
||||
"actual": "En cours",
|
||||
"completed": "Terminés",
|
||||
"todays": "Aujourd'hui",
|
||||
"overdue": "En retard"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"links": {
|
||||
"targetLists": "Listes de cibles"
|
||||
}
|
||||
}
|
||||
"links": {
|
||||
"targetLists": "Listes de cibles"
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,10 @@
|
||||
"label":"",
|
||||
"rows":[
|
||||
[{"name":"name", "fullWidth": true}],
|
||||
[{"name":"website"}, {"name": "billingAddressCountry"}],
|
||||
[{"name":"website", "fullWidth": true}],
|
||||
[{"name":"emailAddress", "fullWidth": true}],
|
||||
[{"name":"phoneNumber", "fullWidth": true}],
|
||||
[{"name":"billingAddressCity"}, {"name": "billingAddressCountry"}],
|
||||
[{"name":"type"}, {"name":"industry"}]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -9,5 +9,6 @@
|
||||
"targetLists",
|
||||
"type",
|
||||
"teams",
|
||||
"shippingAddress"
|
||||
"shippingAddress",
|
||||
"website"
|
||||
]
|
||||
@@ -6,6 +6,7 @@
|
||||
[{"name":"status"}, {"name":"priority"}],
|
||||
[{"name":"type"}, {"name":"number"}],
|
||||
[{"name":"account", "fullWidth": true}],
|
||||
[{"name":"contacts", "fullWidth": true}],
|
||||
[{"name":"description", "fullWidth": true}]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
[{"name":"name", "fullWidth": true}],
|
||||
[{"name":"accounts", "fullWidth": true}],
|
||||
[{"name":"emailAddress", "fullWidth": true}],
|
||||
[{"name":"phoneNumber", "fullWidth": true}]
|
||||
[{"name":"phoneNumber", "fullWidth": true}],
|
||||
[{"name":"addressCity"}, {"name":"addressCountry"}]
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"label": "",
|
||||
"rows":[
|
||||
[{"name":"file"}, {"name":"source"}],
|
||||
[{"name":"file"}, false],
|
||||
[{"name":"name"}, {"name":"folder"}]
|
||||
]
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"label": "",
|
||||
"rows": [
|
||||
[{"name":"file"}, {"name":"source"}],
|
||||
[{"name":"file", "fullWidth": true}],
|
||||
[{"name":"name", "fullWidth": true}],
|
||||
[{"name":"status"}, {"name":"folder"}]
|
||||
]
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
[
|
||||
{"name":"name", "fullWidth": true}
|
||||
],
|
||||
[
|
||||
{"name":"accountName", "fullWidth": true}
|
||||
],
|
||||
[
|
||||
{"name":"emailAddress", "fullWidth": true}
|
||||
],
|
||||
@@ -12,10 +15,10 @@
|
||||
{"name":"phoneNumber", "fullWidth": true}
|
||||
],
|
||||
[
|
||||
{"name":"accountName"}, {"name":"addressCountry"}
|
||||
{"name":"title"}, {"name":"website"}
|
||||
],
|
||||
[
|
||||
{"name":"title"}, {"name":"website"}
|
||||
{"name":"addressCity"}, {"name":"addressCountry"}
|
||||
],
|
||||
[
|
||||
{"name":"status"}, {"name":"source"}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
[{"name":"account", "fullWidth": true}],
|
||||
[{"name":"stage"}, {"name":"closeDate"}],
|
||||
[{"name":"amount", "fullWidth": true}],
|
||||
[{"name":"contacts", "fullWidth": true}],
|
||||
[{"name":"description", "fullWidth": true}]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"detail": "crm:views/contact/record/detail",
|
||||
"detailQuick": "crm:views/contact/record/detail-small"
|
||||
},
|
||||
"defaultSidePanelFieldList": {
|
||||
"defaultSidePanelFieldLists": {
|
||||
"detail": [
|
||||
{
|
||||
"name": "assignedUser"
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
"Building Materials & Equipment",
|
||||
"Chemical",
|
||||
"Construction",
|
||||
"Consulting",
|
||||
"Computer",
|
||||
"Culture",
|
||||
"Creative",
|
||||
|
||||
@@ -32,12 +32,15 @@
|
||||
"end": "dateEnd",
|
||||
"options": [300, 600, 900, 1800, 2700, 3600, 7200],
|
||||
"default": 300,
|
||||
"notStorable": true
|
||||
"notStorable": true,
|
||||
"select": "TIMESTAMPDIFF(SECOND, call.date_start, call.date_end)",
|
||||
"orderBy": "duration {direction}"
|
||||
},
|
||||
"reminders": {
|
||||
"type": "jsonArray",
|
||||
"notStorable": true,
|
||||
"view": "crm:views/meeting/fields/reminders"
|
||||
"view": "crm:views/meeting/fields/reminders",
|
||||
"layoutListDisabled": true
|
||||
},
|
||||
"direction": {
|
||||
"type": "enum",
|
||||
|
||||
@@ -20,11 +20,6 @@
|
||||
"Expired": "danger"
|
||||
}
|
||||
},
|
||||
"source": {
|
||||
"type": "enum",
|
||||
"options": ["Espo"],
|
||||
"default": "Espo"
|
||||
},
|
||||
"type": {
|
||||
"type": "enum",
|
||||
"options": ["", "Contract", "NDA", "EULA", "License Agreement"]
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
},
|
||||
"status": {
|
||||
"type": "enum",
|
||||
"options": ["Pending", "Sent", "Failed"],
|
||||
"options": ["Pending", "Sent", "Failed", "Sending"],
|
||||
"readOnly": true
|
||||
},
|
||||
"attemptCount": {
|
||||
|
||||
@@ -32,12 +32,15 @@
|
||||
"end": "dateEnd",
|
||||
"options": [900, 1800, 3600, 7200, 10800, 86400],
|
||||
"default": 3600,
|
||||
"notStorable": true
|
||||
"notStorable": true,
|
||||
"select": "TIMESTAMPDIFF(SECOND, meeting.date_start, meeting.date_end)",
|
||||
"orderBy": "duration {direction}"
|
||||
},
|
||||
"reminders": {
|
||||
"type": "jsonArray",
|
||||
"notStorable": true,
|
||||
"view": "crm:views/meeting/fields/reminders"
|
||||
"view": "crm:views/meeting/fields/reminders",
|
||||
"layoutListDisabled": true
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@@ -39,6 +39,19 @@ class KnowledgeBaseArticle extends \Espo\Services\Record
|
||||
{
|
||||
protected $readOnlyAttributeList = ['order'];
|
||||
|
||||
protected function init()
|
||||
{
|
||||
parent::init();
|
||||
$this->addDependencyList([
|
||||
'fileStorageManager'
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getFileStorageManager()
|
||||
{
|
||||
return $this->getInjection('fileStorageManager');
|
||||
}
|
||||
|
||||
public function getCopiedAttachments($id, $parentType = null, $parentId = null)
|
||||
{
|
||||
$ids = array();
|
||||
@@ -67,16 +80,17 @@ class KnowledgeBaseArticle extends \Espo\Services\Record
|
||||
$attachment->set('global', $source->get('global'));
|
||||
$attachment->set('name', $source->get('name'));
|
||||
$attachment->set('sourceId', $source->getSourceId());
|
||||
$attachment->set('storage', $source->get('storage'));
|
||||
|
||||
if (!empty($parentType) && !empty($parentId)) {
|
||||
$attachment->set('parentType', $parentType);
|
||||
$attachment->set('parentId', $parentId);
|
||||
}
|
||||
|
||||
if ($this->getFileManager()->isFile('data/upload/' . $source->getSourceId())) {
|
||||
if ($this->getFileStorageManager()->isFile($source)) {
|
||||
$this->getEntityManager()->saveEntity($attachment);
|
||||
|
||||
$this->getFileManager()->putContents('data/upload/' . $attachment->id, $contents);
|
||||
$contents = $this->getFileStorageManager()->getContents($source);
|
||||
$this->getFileStorageManager()->putContents($attachment, $contents);
|
||||
$ids[] = $attachment->id;
|
||||
$names->{$attachment->id} = $attachment->get('name');
|
||||
}
|
||||
|
||||
@@ -70,9 +70,9 @@ class MassEmail extends \Espo\Services\Record
|
||||
}
|
||||
}
|
||||
|
||||
protected function afterRemove(Entity $entity, array $data = array())
|
||||
protected function afterRemove(Entity $massEmail, array $data = array())
|
||||
{
|
||||
parent::afterRemove($entity, $data);
|
||||
parent::afterRemove($massEmail, $data);
|
||||
$existingQueueItemList = $this->getEntityManager()->getRepository('EmailQueueItem')->where(array(
|
||||
'status' => ['Pending', 'Failed'],
|
||||
'massEmailId' => $massEmail->id
|
||||
@@ -394,6 +394,14 @@ class MassEmail extends \Espo\Services\Record
|
||||
|
||||
protected function sendQueueItem(Entity $queueItem, Entity $massEmail, Entity $emailTemplate, $attachmentList = [], $campaign = null, $isTest = false)
|
||||
{
|
||||
$queueItemFetched = $this->getEntityManager()->getEntity($queueItem->getEntityType(), $queueItem->id);
|
||||
if ($queueItemFetched->get('status') !== 'Pending') {
|
||||
return;
|
||||
}
|
||||
|
||||
$queueItem->set('status', 'Sending');
|
||||
$this->getEntityManager()->saveEntity($queueItem);
|
||||
|
||||
$target = $this->getEntityManager()->getEntity($queueItem->get('targetType'), $queueItem->get('targetId'));
|
||||
if (!$target || !$target->id || !$target->get('emailAddress')) {
|
||||
$queueItem->set('status', 'Failed');
|
||||
@@ -432,6 +440,8 @@ class MassEmail extends \Espo\Services\Record
|
||||
$params['replyToName'] = $massEmail->get('replyToName');
|
||||
}
|
||||
|
||||
$isSent = false;
|
||||
|
||||
try {
|
||||
$attemptCount = $queueItem->get('attemptCount');
|
||||
$attemptCount++;
|
||||
@@ -445,6 +455,19 @@ class MassEmail extends \Espo\Services\Record
|
||||
|
||||
$this->getMailSender()->useGlobal()->send($email, $params, $message, $attachmentList);
|
||||
|
||||
$isSent = true;
|
||||
} catch (\Exception $e) {
|
||||
if ($queueItem->get('attemptCount') >= self::MAX_ATTEMPT_COUNT) {
|
||||
$queueItem->set('status', 'Failed');
|
||||
} else {
|
||||
$queueItem->set('status', 'Pending');
|
||||
}
|
||||
$this->getEntityManager()->saveEntity($queueItem);
|
||||
$GLOBALS['log']->error('MassEmail#sendQueueItem: [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($isSent) {
|
||||
$emailObject = $emailTemplate;
|
||||
if ($massEmail->get('storeSentEmails') && !$isTest) {
|
||||
$this->getEntityManager()->saveEntity($email);
|
||||
@@ -460,14 +483,6 @@ class MassEmail extends \Espo\Services\Record
|
||||
if ($campaign) {
|
||||
$this->getCampaignService()->logSent($campaign->id, $queueItem->id, $target, $emailObject, $target->get('emailAddress'), null, $queueItem->get('isTest'));
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
if ($queueItem->get('attemptCount') >= self::MAX_ATTEMPT_COUNT) {
|
||||
$queueItem->set('status', 'Failed');
|
||||
}
|
||||
$this->getEntityManager()->saveEntity($queueItem);
|
||||
$GLOBALS['log']->error('MassEmail#sendQueueItem: [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -112,7 +112,7 @@ class TargetList extends \Espo\Services\Record
|
||||
$selectParams['whereClause'][] = array(
|
||||
'action=' => $includingActionList
|
||||
);
|
||||
$selectParams['groupBy'] = ['parentId', 'parentType'];
|
||||
$selectParams['groupBy'] = ['parentId', 'parentType', 'id'];
|
||||
|
||||
$notSelectParams['whereClause'][] = array(
|
||||
'action=' => $excludingActionList
|
||||
@@ -231,6 +231,8 @@ class TargetList extends \Espo\Services\Record
|
||||
ORDER BY createdAt DESC
|
||||
";
|
||||
|
||||
$sqlCount = "SELECT COUNT(*) AS 'count' FROM ({$sql}) AS c";
|
||||
|
||||
$sql = $query->limit($sql, $params['offset'], $params['maxSize']);
|
||||
|
||||
$sth = $pdo->prepare($sql);
|
||||
@@ -240,7 +242,6 @@ class TargetList extends \Espo\Services\Record
|
||||
$arr[] = $row;
|
||||
}
|
||||
|
||||
$sqlCount = "SELECT COUNT(*) AS 'count' FROM ({$sql}) AS c";
|
||||
$sth = $pdo->prepare($sqlCount);
|
||||
$sth->execute();
|
||||
|
||||
|
||||
@@ -383,6 +383,11 @@ abstract class Entity implements IEntity
|
||||
return null;
|
||||
}
|
||||
|
||||
public function hasFetched($attributeName)
|
||||
{
|
||||
return array_key_exists($attributeName, $this->fetchedValuesContainer);
|
||||
}
|
||||
|
||||
public function resetFetchedValues()
|
||||
{
|
||||
$this->fetchedValuesContainer = array();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user