From 95627f36171ba13ec59ba8e81855dfd18801f714 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Wed, 28 Apr 2021 12:49:54 +0300 Subject: [PATCH] reminder saver --- .../Core/FieldProcessing/Reminder/Saver.php | 230 ++++++++++++++++++ application/Espo/Core/Repositories/Event.php | 204 +++------------- .../Templates/Metadata/Event/recordDefs.json | 3 + .../Espo/Modules/Crm/Repositories/Task.php | 2 - .../Resources/metadata/entityDefs/Task.json | 3 +- .../Resources/metadata/recordDefs/Call.json | 3 + .../metadata/recordDefs/Meeting.json | 3 + .../Resources/metadata/recordDefs/Task.json | 3 + 8 files changed, 272 insertions(+), 179 deletions(-) create mode 100644 application/Espo/Core/FieldProcessing/Reminder/Saver.php diff --git a/application/Espo/Core/FieldProcessing/Reminder/Saver.php b/application/Espo/Core/FieldProcessing/Reminder/Saver.php new file mode 100644 index 0000000000..511dd2dae8 --- /dev/null +++ b/application/Espo/Core/FieldProcessing/Reminder/Saver.php @@ -0,0 +1,230 @@ +entityManager = $entityManager; + } + + public function process(Entity $entity, SaverParams $params): void + { + $entityType = $entity->getEntityType(); + + $hasReminder = $this->entityManager + ->getDefs() + ->getEntity($entityType) + ->hasField('reminders'); + + if (!$hasReminder) { + return; + } + + $dateAttribute = $this->entityManager + ->getDefs() + ->getEntity($entityType) + ->getField('reminders') + ->getParam('dateField') ?? + $this->dateAttribute; + + $toProcess = + $entity->isNew() || + $entity->isAttributeChanged('assignedUserId') || + ($entity->hasLinkMultipleField('assignedUsers') && $entity->isAttributeChanged('assignedUsersIds')) || + ($entity->hasLinkMultipleField('users') && $entity->isAttributeChanged('usersIds')) || + $entity->isAttributeChanged($dateAttribute) || + $entity->has('reminders'); + + if (!$toProcess) { + return; + } + + $reminderTypeList = $this->entityManager + ->getDefs() + ->getEntity('Reminder') + ->getField('type') + ->getParam('options') ?? []; + + $reminderList = $entity->has('reminders') ? + $entity->get('reminders') : + $this->getEntityReminderDataList($entity); + + if (!$entity->isNew()) { + $query = $this->entityManager + ->getQueryBuilder() + ->delete() + ->from('Reminder') + ->where([ + 'entityId' => $entity->getId(), + 'entityType' => $entityType, + 'deleted' => false, + ]) + ->build(); + + $this->entityManager->getQueryExecutor()->execute($query); + } + + if (empty($reminderList) || !is_array($reminderList)) { + return; + } + + $dateValue = $entity->get($dateAttribute); + + if (!$entity->has($dateAttribute)) { + $reloadedEntity = $this->entityManager->getEntity($entityType, $entity->getId()); + + if ($reloadedEntity) { + $dateValue = $reloadedEntity->get($dateAttribute); + } + } + + if (!$dateValue) { + return; + } + + + if ($entity->hasLinkMultipleField('users')) { + $userIdList = $entity->getLinkMultipleIdList('users'); + } + else if ($entity->hasLinkMultipleField('assignedUsers')) { + $userIdList = $entity->getLinkMultipleIdList('assignedUsers'); + } + else { + $userIdList = []; + + if ($entity->get('assignedUserId')) { + $userIdList[] = $entity->get('assignedUserId'); + } + } + + if (empty($userIdList)) { + return; + } + + $dateValueObj = new DateTime($dateValue); + + if (!$dateValueObj) { + return; + } + + foreach ($reminderList as $item) { + $remindAt = clone $dateValueObj; + $seconds = intval($item->seconds); + $type = $item->type; + + if (!in_array($type , $reminderTypeList)) { + continue; + } + + $remindAt->sub(new DateInterval('PT' . $seconds . 'S')); + + foreach ($userIdList as $userId) { + $reminderId = Util::generateId(); + + $query = $this->entityManager + ->getQueryBuilder() + ->insert() + ->into('Reminder') + ->columns([ + 'id', + 'entityId', + 'entityType', + 'type', + 'userId', + 'remindAt', + 'startAt', + 'seconds' + ]) + ->values([ + 'id' => $reminderId, + 'entityId' => $entity->getId(), + 'entityType' => $entityType, + 'type' => $type, + 'userId' => $userId, + 'remindAt' => $remindAt->format('Y-m-d H:i:s'), + 'startAt' => $dateValue, + 'seconds' => $seconds, + ]) + ->build(); + + $this->entityManager->getQueryExecutor()->execute($query); + } + } + } + + /** + * @return StdClass[] + */ + private function getEntityReminderDataList(Entity $entity): array + { + $reminderDataList = []; + + $reminderCollection = $this->entityManager + ->getRDBRepository('Reminder') + ->select(['seconds', 'type']) + ->where([ + 'entityType' => $entity->getEntityType(), + 'entityId' => $entity->getId(), + ]) + ->distinct() + ->order('seconds') + ->find(); + + foreach ($reminderCollection as $reminder) { + $reminderDataList[] = (object) [ + 'seconds' => $reminder->get('seconds'), + 'type' => $reminder->get('type'), + ]; + } + + return $reminderDataList; + } +} diff --git a/application/Espo/Core/Repositories/Event.php b/application/Espo/Core/Repositories/Event.php index 795ae95cfe..94c50b3e59 100644 --- a/application/Espo/Core/Repositories/Event.php +++ b/application/Espo/Core/Repositories/Event.php @@ -30,13 +30,11 @@ namespace Espo\Core\Repositories; use Espo\ORM\Entity; -use Espo\Core\Utils\Util; use Espo\Core\Di; use DateTime; use DateTimeZone; -use DateInterval; use Exception; class Event extends Database implements @@ -47,8 +45,6 @@ class Event extends Database implements use Di\DateTimeSetter; use Di\ConfigSetter; - protected $reminderDateAttribute = 'dateStart'; - protected $reminderSkippingStatusList = ['Held', 'Not Held']; protected $preserveDuration = true; @@ -98,6 +94,7 @@ class Event extends Database implements try { $dt = new DateTime($dateEnd); $dt->modify('+1 day'); + $dateEnd = $dt->format('Y-m-d H:i:s'); } catch (Exception $e) {} @@ -109,31 +106,29 @@ class Event extends Database implements } } - if (!$entity->isNew()) { - if ( - $this->preserveDuration - && - $entity->isAttributeChanged('dateStart') && $entity->get('dateStart') - && - $entity->isAttributeChanged('dateStart') && !$entity->isAttributeChanged('dateEnd') - ) { - $dateEndPrevious = $entity->getFetched('dateEnd'); - $dateStartPrevious = $entity->getFetched('dateStart'); + if ( + !$entity->isNew() && + $this->preserveDuration && + $entity->isAttributeChanged('dateStart') && + $entity->get('dateStart') && + $entity->isAttributeChanged('dateStart') && + !$entity->isAttributeChanged('dateEnd') + ) { + $dateEndPrevious = $entity->getFetched('dateEnd'); + $dateStartPrevious = $entity->getFetched('dateStart'); - if ($dateStartPrevious && $dateEndPrevious) { - $dtStart = new DateTime($dateStartPrevious); - $dtEnd = new DateTime($dateEndPrevious); - $dt = new DateTime($entity->get('dateStart')); + if ($dateStartPrevious && $dateEndPrevious) { + $dtStart = new DateTime($dateStartPrevious); + $dtEnd = new DateTime($dateEndPrevious); + $dt = new DateTime($entity->get('dateStart')); - if ($dtStart && $dtEnd && $dt) { - $duration = ($dtEnd->getTimestamp() - $dtStart->getTimestamp()); + $duration = ($dtEnd->getTimestamp() - $dtStart->getTimestamp()); - $dt->modify('+' . $duration . ' seconds'); + $dt->modify('+' . $duration . ' seconds'); - $dateEnd = $dt->format('Y-m-d H:i:s'); - $entity->set('dateEnd', $dateEnd); - } - } + $dateEnd = $dt->format('Y-m-d H:i:s'); + + $entity->set('dateEnd', $dateEnd); } } @@ -156,155 +151,6 @@ class Event extends Database implements $this->getEntityManager()->getQueryExecutor()->execute($delete); } - protected function afterSave(Entity $entity, array $options = []) - { - $this->processReminderAfterSave($entity, $options); - - parent::afterSave($entity, $options); - } - - protected function processReminderAfterSave(Entity $entity, array $options = []) - { - if ( - $entity->isNew() || - $entity->isAttributeChanged('assignedUserId') || - $entity->isAttributeChanged('usersIds') || - $entity->isAttributeChanged($this->reminderDateAttribute) || - $entity->has('reminders') - ) { - $reminderTypeList = $this->getMetadata()->get('entityDefs.Reminder.fields.type.options'); - - if (!$entity->has('reminders')) { - $reminderList = $this->getEntityReminderList($entity); - } - else { - $reminderList = $entity->get('reminders'); - } - - if (!$entity->isNew()) { - $query = $this->getEntityManager()->getQueryBuilder() - ->delete() - ->from('Reminder') - ->where([ - 'entityId' => $entity->id, - 'entityType' => $entity->getEntityType(), - 'deleted' => false, - ]) - ->build(); - - $this->getEntityManager()->getQueryExecutor()->execute($query); - } - - if (empty($reminderList) || !is_array($reminderList)) { - return; - } - - $entityType = $entity->getEntityType(); - - $dateValue = $entity->get($this->reminderDateAttribute); - - if (!$dateValue) { - $e = $this->get($entity->id); - - if ($e) { - $dateValue = $e->get($this->reminderDateAttribute); - } - } - - if ($entity->hasLinkMultipleField('users')) { - $userIdList = $entity->getLinkMultipleIdList('users'); - } - else { - $userIdList = []; - - if ($entity->get('assignedUserId')) { - $userIdList[] = $entity->get('assignedUserId'); - } - } - - if (!$dateValue) { - return; - } - - if (empty($userIdList)) { - return; - } - - $dateValueObj = new DateTime($dateValue); - - if (!$dateValueObj) { - return; - } - - foreach ($reminderList as $item) { - $remindAt = clone $dateValueObj; - $seconds = intval($item->seconds); - $type = $item->type; - - if (!in_array($type , $reminderTypeList)) { - continue; - } - - $remindAt->sub(new DateInterval('PT' . $seconds . 'S')); - - foreach ($userIdList as $userId) { - $id = Util::generateId(); - - $query = $this->getEntityManager()->getQueryBuilder() - ->insert() - ->into('Reminder') - ->columns([ - 'id', - 'entityId', - 'entityType', - 'type', - 'userId', - 'remindAt', - 'startAt', - 'seconds' - ]) - ->values([ - 'id' => $id, - 'entityId' => $entity->id, - 'entityType' => $entityType, - 'type' => $type, - 'userId' => $userId, - 'remindAt' => $remindAt->format('Y-m-d H:i:s'), - 'startAt' => $dateValue, - 'seconds' => $seconds, - ]) - ->build(); - - $this->getEntityManager()->getQueryExecutor()->execute($query); - } - } - } - } - - public function getEntityReminderList(Entity $entity): array - { - $reminderDataList = []; - - $reminderCollection = $this->getEntityManager()->getRepository('Reminder') - ->select(['seconds', 'type']) - ->where([ - 'entityType' => $entity->getEntityType(), - 'entityId' => $entity->id, - ]) - ->distinct() - ->order('seconds') - ->find(); - - foreach ($reminderCollection as $reminder) { - $reminderDataList[] = (object) [ - 'seconds' => $reminder->get('seconds'), - 'type' => $reminder->get('type'), - ]; - } - - return $reminderDataList; - } - protected function convertDateTimeToDefaultTimezone($string) { $timeZone = $this->getConfig()->get('timeZone') ?? 'UTC'; @@ -312,14 +158,20 @@ class Event extends Database implements $tz = new DateTimeZone($timeZone); try { - $dt = DateTime::createFromFormat($this->getDateTime()->getInternalDateTimeFormat(), $string, $tz); + $dt = DateTime::createFromFormat( + $this->getDateTime()->getInternalDateTimeFormat(), + $string, + $tz + ); } catch (Exception $e) {} if ($dt) { $utcTz = new DateTimeZone('UTC'); - return $dt->setTimezone($utcTz)->format($this->getDateTime()->getInternalDateTimeFormat()); + return $dt + ->setTimezone($utcTz) + ->format($this->getDateTime()->getInternalDateTimeFormat()); } return null; diff --git a/application/Espo/Core/Templates/Metadata/Event/recordDefs.json b/application/Espo/Core/Templates/Metadata/Event/recordDefs.json index 5ac5dbf19f..ec2621635e 100644 --- a/application/Espo/Core/Templates/Metadata/Event/recordDefs.json +++ b/application/Espo/Core/Templates/Metadata/Event/recordDefs.json @@ -1,5 +1,8 @@ { "readLoaderClassNameList": [ "Espo\\Core\\FieldProcessing\\Reminder\\Loader" + ], + "saverClassNameList": [ + "Espo\\Core\\FieldProcessing\\Reminder\\Saver" ] } diff --git a/application/Espo/Modules/Crm/Repositories/Task.php b/application/Espo/Modules/Crm/Repositories/Task.php index 0b7790abe9..4e380be06d 100644 --- a/application/Espo/Modules/Crm/Repositories/Task.php +++ b/application/Espo/Modules/Crm/Repositories/Task.php @@ -33,8 +33,6 @@ use Espo\ORM\Entity; class Task extends \Espo\Core\Repositories\Event { - protected $reminderDateAttribute = 'dateEnd'; - protected $reminderSkippingStatusList = ['Completed', 'Canceled']; protected $preserveDuration = false; diff --git a/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Task.json b/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Task.json index a0fcaffd94..e65a8f71ab 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Task.json +++ b/application/Espo/Modules/Crm/Resources/metadata/entityDefs/Task.json @@ -64,7 +64,8 @@ "reminders": { "type": "jsonArray", "notStorable": true, - "view": "crm:views/meeting/fields/reminders" + "view": "crm:views/meeting/fields/reminders", + "dateField": "dateEnd" }, "description": { "type": "text" diff --git a/application/Espo/Modules/Crm/Resources/metadata/recordDefs/Call.json b/application/Espo/Modules/Crm/Resources/metadata/recordDefs/Call.json index 3737cbfdfd..d7311ed9e3 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/recordDefs/Call.json +++ b/application/Espo/Modules/Crm/Resources/metadata/recordDefs/Call.json @@ -2,5 +2,8 @@ "readLoaderClassNameList": [ "Espo\\Core\\FieldProcessing\\Reminder\\Loader", "Espo\\Modules\\Crm\\Classes\\FieldProcessing\\Call\\PhoneNumberMapLoader" + ], + "saverClassNameList": [ + "Espo\\Core\\FieldProcessing\\Reminder\\Saver" ] } diff --git a/application/Espo/Modules/Crm/Resources/metadata/recordDefs/Meeting.json b/application/Espo/Modules/Crm/Resources/metadata/recordDefs/Meeting.json index 5ac5dbf19f..ec2621635e 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/recordDefs/Meeting.json +++ b/application/Espo/Modules/Crm/Resources/metadata/recordDefs/Meeting.json @@ -1,5 +1,8 @@ { "readLoaderClassNameList": [ "Espo\\Core\\FieldProcessing\\Reminder\\Loader" + ], + "saverClassNameList": [ + "Espo\\Core\\FieldProcessing\\Reminder\\Saver" ] } diff --git a/application/Espo/Modules/Crm/Resources/metadata/recordDefs/Task.json b/application/Espo/Modules/Crm/Resources/metadata/recordDefs/Task.json index 5ac5dbf19f..ec2621635e 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/recordDefs/Task.json +++ b/application/Espo/Modules/Crm/Resources/metadata/recordDefs/Task.json @@ -1,5 +1,8 @@ { "readLoaderClassNameList": [ "Espo\\Core\\FieldProcessing\\Reminder\\Loader" + ], + "saverClassNameList": [ + "Espo\\Core\\FieldProcessing\\Reminder\\Saver" ] }