inbound email 3

This commit is contained in:
Yuri Kuznetsov
2014-01-31 17:45:38 +02:00
parent c7ab079c65
commit efe5cb23ed
9 changed files with 255 additions and 37 deletions
@@ -0,0 +1,55 @@
<?php
namespace Espo\Modules\Crm\Business\CaseDistribution;
class LeastBusy
{
protected $entityManager;
public function __construct($entityManager)
{
$this->entityManager = $entityManager;
}
protected function getEntityManager()
{
return $this->entityManager;
}
public function getUser($team)
{
$userList = $team->get('users');
if (count($userList) == 0) {
return false;
}
$countHash = array();
foreach ($userList as $user) {
$count = $this->getEntityManager()->getRepository('Case')->where(array(
'assignedUserId' => $user->id,
'status<>' => array('Closed', 'Rejected', 'Duplicated')
))->count();
$countHash[$user->id] = $count;
}
$foundUserId = false;
$min = false;
foreach ($countHash as $userId => $count) {
if ($min === false) {
$min = $count;
$foundUserId = $userId;
} else {
if ($count < $min) {
$min = $clunt;
$foundUserId = $userId;
}
}
}
if ($foundUserId !== false) {
return $this->getEntityManager()->getEntity('User', $foundUserId);
}
}
}
@@ -0,0 +1,51 @@
<?php
namespace Espo\Modules\Crm\Business\CaseDistribution;
class RoundRobin
{
protected $entityManager;
public function __construct($entityManager)
{
$this->entityManager = $entityManager;
}
protected function getEntityManager()
{
return $this->entityManager;
}
public function getUser($team)
{
$userList = $team->get('users');
if (count($userList) == 0) {
return false;
}
$userIdList = array();
foreach ($userList as $user) {
$userIdList[] = $user->id;
}
$case = $this->getEntityManager()->getRepository('Case')->where(array(
'assignedUserId' => $userIdList,
))->order('createdAt', 'DESC')->findOne();
if (empty($case)) {
$num = 0;
} else {
$num = array_search($case->get('assignedUserId'), $userIdList);
if ($num === false || $num == count($userIdList) - 1) {
$num = 0;
} else {
$num++;
}
}
return $this->getEntityManager()->getEntity('User', $userIdList[$num]);
}
}
@@ -5,6 +5,13 @@
[
{"name":"name"},
{"name":"status"}
],
[
{"name":"team"}
],
[
{"name":"assignToUser"}
]
]
},
@@ -1 +1,19 @@
[{"label":"","rows":[[{"name":"name"}],[{"name":"emailAddress"}],[{"name":"phone"}]]}]
[
{
"label":"",
"rows":[
[
{"name":"name"}
],
[
{"name":"emailAddress"}
],
[
{"name":"phone"}
],
[
{"name":"status"}
]
]
}
]
@@ -30,17 +30,23 @@
"default": "INBOX"
},
"trashFolder": {
"type": "varchar"
"type": "varchar",
"required": true,
"default": "INBOX.Trash"
},
"teams": {
"type": "linkMultiple"
"assignToUser": {
"type": "link"
},
"team": {
"type": "link"
},
"createCase": {
"type": "bool"
},
"caseDistribution": {
"type": "enum",
"options": ["Round-Robin", "Least-Busy"]
"options": ["Direct-Assignment", "Round-Robin", "Least-Busy"],
"default": "Direct-Assignment"
},
"reply": {
"type": "bool"
@@ -80,10 +86,13 @@
"type": "belongsTo",
"entity": "User"
},
"teams": {
"type": "hasMany",
"entity": "Team",
"relationName": "EntityTeam"
"assignToUser": {
"type": "belongsTo",
"entity": "User"
},
"team": {
"type": "belongsTo",
"entity": "Team"
},
"replyEmailTemplate": {
"type": "belongsTo",
@@ -1 +1,6 @@
{}
{
"recordViews":{
"detail":"Crm:InboundEmail.Record.Detail",
"edit":"Crm:InboundEmail.Record.Edit"
}
}
@@ -28,7 +28,7 @@ class InboundEmail extends \Espo\Services\Record
protected function findFolder($storage, $path)
{
$arr = explode('/', $path);
$arr = explode('.', $path);
$pointer = $storage->getFolders();
foreach ($arr as $folderName) {
$pointer = $pointer->$folderName;
@@ -40,7 +40,6 @@ class InboundEmail extends \Espo\Services\Record
public function fetchFromMailServer($id)
{
$inboundEmail = $this->getEntity($id);
$inboundEmail->loadLinkMultipleField('teams');
if ($inboundEmail->get('status') != 'Active') {
throw new Error();
@@ -58,11 +57,16 @@ class InboundEmail extends \Espo\Services\Record
}
$trash = null;
$trashFolder = $inboundEmail->get('trashFolder');
if ($trashFolder) {
$trash = $this->findFolder($storage, $trashFolder);
$trashFolder = $inboundEmail->get('trashFolder');
if (empty($trashFolder)) {
$trashFolder = 'INBOX.Trash';
}
try {
$trash = $this->findFolder($storage, $trashFolder);
} catch (\Exception $e) {
throw new Error("No trash folder '{$trashFolder}' found for Inbound Email {$id}");
}
$monitoredFolders = $inboundEmail->get('monitoredFolders');
if (empty($monitoredFolders)) {
$monitoredFolders = 'INBOX';
@@ -82,9 +86,7 @@ class InboundEmail extends \Espo\Services\Record
while ($storage->countMessages()) {
if ($trash) {
$folder->moveMessage(1, $trash);
} else {
$storage->removeMessage(1);
$storage->moveMessage(1, $trash);
}
}
}
@@ -109,12 +111,19 @@ class InboundEmail extends \Espo\Services\Record
try {
$email = $this->getEntityManager()->getEntity('Email');
$email->set('teamsIds', $inboundEmail->get('teamsIds'));
if ($inboundEmail->get('teamId')) {
$email->set('teamsIds', array($inboundEmail->get('teamId')));
}
$email->set('isHtml', false);
$email->set('name', $message->subject);
$email->set('attachmentsIds', array());
$email->set('assignedUserId', $this->getUser()->id);
$userId = $this->getUser()->id;
if ($inboundEmail->get('assignToUserId')) {
$userId = $inboundEmail->get('assignToUserId');
}
$email->set('assignedUserId', $userId);
$fromArr = $this->getAddressListFromMessage($message, 'from');
@@ -146,8 +155,6 @@ class InboundEmail extends \Espo\Services\Record
$this->getEntityManager()->saveEntity($email);
if ($inboundEmail->get('createCase')) {
// TODO check case exists
if (preg_match('/\[#([0-9]+)[^0-9]*\]/', $email->get('name'), $m)) {
$caseNumber = $m[1];
$case = $this->getEntityManager()->getRepository('Case')->where(array(
@@ -160,37 +167,96 @@ class InboundEmail extends \Espo\Services\Record
$this->getServiceFactory()->create('Stream')->noteEmail($case, $email);
}
} else {
$case = $this->emailToCase($email, $inboundEmail->get('caseDistribution'));
$params = array(
'caseDistribution' => $inboundEmail->get('caseDistribution'),
'teamId' => $inboundEmail->get('teamId'),
'userId' => $inboundEmail->get('assignToUserId'),
);
$case = $this->emailToCase($email, $params);
$user = $this->getEntityManager()->getEntity('User', $case->get('assignedUserId'));
if ($inboundEmail->get('reply')) {
$this->autoReply($inboundEmail, $email, $case);
$this->autoReply($inboundEmail, $email, $case, $user);
}
}
} else {
if ($inboundEmail->get('reply')) {
$this->autoReply($inboundEmail, $email);
$user = $this->getEntityManager()->getEntity('User', $userId);
$this->autoReply($inboundEmail, $email, $user);
}
}
$result = true;
} catch (\Exception $e){
// TODO log
// TODO log
}
return $result;
}
protected function emailToCase(\Espo\Entities\Email $email, $caseDistribution = 'Round-Robin')
protected function assignRoundRobin($case, $team)
{
$roundRobin = new \Espo\Modules\Crm\Business\CaseDistribution\RoundRobin($this->getEntityManager());
$user = $roundRobin->getUser($team);
if ($user) {
$case->set('assignedUserId', $user->id);
}
}
protected function assignLeastBusy($case, $team)
{
$leastBusy = new \Espo\Modules\Crm\Business\CaseDistribution\LeastBusy($this->getEntityManager());
$user = $leastBusy->getUser($team);
if ($user) {
$case->set('assignedUserId', $user->id);
}
}
protected function emailToCase(\Espo\Entities\Email $email, array $params = array())
{
$case = $this->getEntityManager()->getEntity('Case');
$case->populateDefaults();
$case->set('name', $email->get('name'));
$case->set('description', $email->get('bodyPlain'));
$case->set('teamsIds', $email->get('teamsIds'));
$case->set('description', $email->get('bodyPlain'));
// TODO distribution
$case->set('assignedUserId', $this->getUser()->id);
$userId = $this->getUser()->id;
if (!empty($params['userId'])) {
$userId = $params['userId'];
}
$case->set('assignedUserId', $userId);
$teamId = false;
if (!empty($params['teamId'])) {
$teamId = $params['teamId'];
}
if ($teamId) {
$case->set('teamsIds', array($teamId));
}
$caseDistribution = 'Direct-Assignment';
if (!empty($params['caseDistribution'])) {
$caseDistribution = $params['caseDistribution'];
}
switch ($caseDistribution) {
case 'Round-Robin':
if ($teamId) {
$team = $this->getEntityManager()->getEntity('Team', $teamId);
if ($team) {
$this->assignRoundRobin($case, $team);
}
}
break;
case 'Least-Busy':
if ($teamId) {
$team = $this->getEntityManager()->getEntity('Team', $teamId);
if ($team) {
$this->assignLeastBusy($case, $team);
}
}
break;
}
$contact = $this->getEntityManager()->getRepository('Contact')->where(array(
'EmailAddress.id' => $email->get('fromEmailAddressId')
@@ -251,7 +317,7 @@ class InboundEmail extends \Espo\Services\Record
}
}
protected function autoReply($inboundEmail, $email, $case = null)
protected function autoReply($inboundEmail, $email, $case = null, $user = null)
{
try {
$replyEmailTemplateId = $inboundEmail->get('replyEmailTemplateId');
@@ -270,7 +336,11 @@ class InboundEmail extends \Espo\Services\Record
$entityHash['Person'] = $contact;
$entityHash['Contact'] = $contact;
$entityHash['Contact'] = $contact;
if ($user) {
$entityHash['User'] = $user;
}
$emailTemplateService = $this->getServiceFactory()->create('EmailTemplate');
+1 -1
View File
@@ -152,7 +152,7 @@ class RDB extends \Espo\ORM\Repository
public function findOne(array $params = array())
{
$collection = $this->find($params);
$collection = $this->limit(0, 1)->find($params);
if (count($collection)) {
return $collection[0];
}
+3
View File
@@ -92,6 +92,9 @@ class Stream extends \Espo\Core\Services\Base
public function followEntity(Entity $entity, $userId)
{
if ($userId == 'system') {
return;
}
if (!$this->getMetadata()->get('scopes.' . $entity->getEntityName() . '.stream')) {
throw new Error();
}