/**
  * get special field value
  *
  * @param Tinebase_Record_Interface $_record
  * @param array $_param
  * @param string $_key
  * @param string $_cellType
  * @param array $_resolvedRecords
  * @return string
  */
 public static function getSpecialFieldValue(Tinebase_Record_Interface $_record, $_param, $_key = NULL, &$_cellType = NULL, $_resolvedRecords = NULL)
 {
     if (is_null($_key)) {
         throw new Tinebase_Exception_InvalidArgument('Missing required parameter $key');
     }
     $configKeysAndProps = array('status' => array('config' => Crm_Config::LEAD_STATES, 'property' => 'leadstate_id'), 'source' => array('config' => Crm_Config::LEAD_SOURCES, 'property' => 'leadsource_id'), 'type' => array('config' => Crm_Config::LEAD_TYPES, 'property' => 'leadtype_id'));
     switch ($_param['type']) {
         case 'status':
         case 'source':
         case 'type':
             $value = Crm_Config::getInstance()->get($configKeysAndProps[$_param['type']]['config'])->getTranslatedValue($_record->{$configKeysAndProps[$_param['type']]['property']});
             break;
         case 'open_tasks':
             $value = 0;
             foreach ($_record->relations as $relation) {
                 // check if is task and open
                 if ($relation->type == 'TASK') {
                     $idx = $_resolvedRecords['tasksStatus']->getIndexById($relation->related_record->status);
                     if ($idx) {
                         $status = $_resolvedRecords['tasksStatus'][$idx];
                         if ($status->is_open) {
                             $value++;
                         }
                     }
                 }
             }
             break;
         default:
             $value = '';
     }
     return $value;
 }
 /**
  * Returns instance of Tinebase_Config
  *
  * @return Tinebase_Config
  */
 public static function getInstance()
 {
     if (self::$_instance === NULL) {
         self::$_instance = new self();
     }
     return self::$_instance;
 }
 /**
  * init favorites
  */
 protected function _initializeFavorites()
 {
     $pfe = Tinebase_PersistentFilter::getInstance();
     $commonValues = array('account_id' => NULL, 'application_id' => Tinebase_Application::getInstance()->getApplicationByName('Crm')->getId(), 'model' => 'Crm_Model_LeadFilter');
     $closedStatus = Crm_Config::getInstance()->get(Crm_Config::LEAD_STATES)->records->filter('endslead', true)->id;
     $pfe->createDuringSetup(new Tinebase_Model_PersistentFilter(array_merge($commonValues, array('name' => Crm_Preference::DEFAULTPERSISTENTFILTER_NAME, 'description' => "All leads I have read grants for", 'filters' => array(array('field' => 'leadstate_id', 'operator' => 'notin', 'value' => $closedStatus))))));
     $pfe->createDuringSetup(new Tinebase_Model_PersistentFilter(array_merge($commonValues, array('name' => "Last modified by me", 'description' => "All leads that I have last modified", 'filters' => array(array('field' => 'last_modified_by', 'operator' => 'equals', 'value' => Tinebase_Model_User::CURRENTACCOUNT))))));
     $pfe->createDuringSetup(new Tinebase_Model_PersistentFilter(array_merge($commonValues, array('name' => "My leads", 'description' => "All leads that I am responsible for", 'filters' => array(array('field' => 'contact', 'operator' => 'AND', 'value' => array(array('field' => 'id', 'operator' => 'equals', 'value' => Addressbook_Model_Contact::CURRENTCONTACT))))))));
     $pfe->createDuringSetup(new Tinebase_Model_PersistentFilter(array_merge($commonValues, array('name' => "Leads with overdue tasks", 'description' => "Leads with overdue tasks", 'filters' => array(array('field' => 'task', 'operator' => 'AND', 'value' => array(array('field' => 'due', 'operator' => 'before', 'value' => 'dayThis'))))))));
 }
 /**
  * the constructor
  *
  * don't use the constructor. use the singleton 
  */
 private function __construct()
 {
     $this->_applicationName = 'Crm';
     $this->_modelName = 'Crm_Model_Lead';
     $this->_relatedObjectsToDelete = array('Tasks_Model_Task');
     $this->_sendNotifications = TRUE;
     $this->_purgeRecords = FALSE;
     $this->_doRightChecks = TRUE;
     $this->_resolveCustomFields = TRUE;
     $this->_duplicateCheckFields = Crm_Config::getInstance()->get(Crm_Config::LEAD_DUP_FIELDS, array(array('relations', 'lead_name')));
     $this->_duplicateCheckConfig = array('relations' => array('type' => 'CUSTOMER', 'filterField' => 'contact'));
     $this->_backend = new Crm_Backend_Lead();
 }
 /**
  * update from 2.1 -> 2.2
  * - move leadstates/types/sources to config and remove tables
  * 
  * @return void
  */
 public function update_1()
 {
     $toUpdate = array('leadtype' => array('table' => 'metacrm_leadtype', 'cfgId' => Crm_Model_Config::LEADTYPES, 'fkName' => 'metacrm_lead::leadtype_id--metacrm_leadtype::id'), 'leadstate' => array('table' => 'metacrm_leadstate', 'cfgId' => Crm_Model_Config::LEADSTATES, 'fkName' => 'metacrm_lead::leadstate_id--metacrm_leadstate::id'), 'leadsource' => array('table' => 'metacrm_leadsource', 'cfgId' => Crm_Model_Config::LEADSOURCES, 'fkName' => 'metacrm_lead::leadsource_id--metacrm_leadsource::id'));
     foreach ($toUpdate as $config) {
         // get from db
         $select = $this->_db->select()->from(SQL_TABLE_PREFIX . $config['table']);
         $stmt = $this->_db->query($select);
         $queryResult = $stmt->fetchAll();
         // save to config
         Crm_Config::getInstance()->set($config['cfgId'], Zend_Json::encode($queryResult));
         // remove tables and constraints
         try {
             $this->_backend->dropForeignKey('metacrm_lead', $config['fkName']);
         } catch (Zend_Db_Statement_Exception $zdse) {
             Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' error dropping fk for ' . $config['table'] . ': ' . $zdse->__toString());
         }
         $this->_backend->dropTable($config['table']);
     }
     $this->setTableVersion('metacrm_lead', '5');
     $this->setApplicationVersion('Crm', '2.2');
 }
 /**
  * @see 0011234: automatically add task for responsible person on lead import
  */
 public function testAutoTaskImport()
 {
     Crm_Config::getInstance()->set(Crm_Config::LEAD_IMPORT_AUTOTASK, true);
     $personalContainerOfSClever = $this->_getPersonalContainer('Tasks', $this->_personas['sclever']);
     $this->_setPersonaGrantsForTestContainer($personalContainerOfSClever->getId(), 'sclever', true, false);
     $result = $this->testImport(false);
     foreach ($result['results'] as $lead) {
         foreach ($lead->relations as $relation) {
             if ($relation->type === 'TASK') {
                 $this->_tasksToDelete[] = $relation->related_id;
             }
         }
     }
     $translate = Tinebase_Translation::getTranslation('Crm');
     $tasksFilter = new Tasks_Model_TaskFilter(array(array('field' => 'container_id', 'operator' => 'equals', 'value' => $personalContainerOfSClever->getId()), array('field' => 'summary', 'operator' => 'equals', 'value' => $translate->_('Edit new lead'))));
     $tasks = Tasks_Controller_Task::getInstance()->search($tasksFilter);
     $this->_tasksToDelete = array_merge($this->_tasksToDelete, $tasks->getArrayOfIds());
     $this->assertEquals(1, count($tasks), 'could not find task in sclevers container: ' . print_r($personalContainerOfSClever->toArray(), true));
     $task = $tasks->getFirstRecord();
     $this->assertEquals($this->_personas['sclever']['accountId'], $task->organizer);
     $this->assertEquals('IN-PROCESS', $task->status);
 }
 /**
  * special field value function
  * 
  * @param Tinebase_Record_Abstract $_record
  * @param string $_fieldName
  * @return string
  */
 protected function _addSpecialValue(Tinebase_Record_Abstract $_record, $_fieldName)
 {
     $keyFieldName = preg_replace('/_id/', 's', $_fieldName);
     return Crm_Config::getInstance()->get($keyFieldName)->getTranslatedValue($_record->{$_fieldName});
 }
 /**
  * @see 0011376: send mail on lead import to responsibles
  */
 public function testEmailNotification()
 {
     $smtpConfig = Tinebase_Config::getInstance()->get(Tinebase_Config::SMTP, new Tinebase_Config_Struct())->toArray();
     if (empty($smtpConfig)) {
         $this->markTestSkipped('No SMTP config found: this is needed to send notifications.');
     }
     Crm_Config::getInstance()->set(Crm_Config::LEAD_IMPORT_NOTIFICATION, true);
     $this->testImport(false);
     // mark tasks for deletion
     $this->_searchTestTasks(Tinebase_Container::getInstance()->getDefaultContainer('Tasks_Model_Task')->getId(), 'task');
     // assert emails for responsibles
     $messages = self::getMessages();
     $this->assertGreaterThan(1, count($messages));
     $translate = Tinebase_Translation::getTranslation('Crm');
     $importNotifications = array();
     $subjectToMatch = sprintf($translate->_('%s new leads have been imported'), 1);
     foreach ($messages as $message) {
         if ($message->getSubject() == $subjectToMatch) {
             $importNotifications[] = $message;
         }
     }
     $this->assertGreaterThan(1, count($importNotifications), 'expecting 2 or more mails (at least for unittest + sclever) / messages:' . print_r($messages, true));
     $firstMessage = $importNotifications[0];
     $this->assertContains('neuer lead 2', $firstMessage->getBodyText()->getContent(), 'lead name missing');
     $this->assertContains('PHPUnit', $firstMessage->getBodyText()->getContent(), 'container name missing');
 }
 /**
  * do something after the import
  */
 protected function _afterImport()
 {
     if (Crm_Config::getInstance()->get(Crm_Config::LEAD_IMPORT_NOTIFICATION) && !$this->_options['dryrun']) {
         $this->_sendNotificationToResponsibles();
     }
 }
 /**
  * get record array
  *
  * @param   Crm_Model_Lead $_lead lead data
  * @param   Zend_Locale $_locale the locale
  * @param   Zend_Translate $_translate
  * @return  array  the record
  *
  */
 protected function getRecord(Crm_Model_Lead $_lead, Zend_Locale $_locale, Zend_Translate $_translate)
 {
     $leadFields = array(array('label' => "", 'type' => 'separator'), array('label' => $_translate->_('Leadstate'), 'value' => array('leadstate_id')), array('label' => $_translate->_('Leadtype'), 'value' => array('leadtype_id')), array('label' => $_translate->_('Leadsource'), 'value' => array('leadsource_id')), array('label' => $_translate->_('Turnover'), 'value' => array('turnover')), array('label' => $_translate->_('Probability'), 'value' => array('probability')), array('label' => $_translate->_('Start'), 'value' => array('start')), array('label' => $_translate->_('End'), 'value' => array('end')), array('label' => $_translate->_('End Scheduled'), 'value' => array('end_scheduled')));
     // add data to array
     $record = array();
     foreach ($leadFields as $fieldArray) {
         if (!isset($fieldArray['type']) || $fieldArray['type'] !== 'separator') {
             $values = array();
             foreach ($fieldArray['value'] as $valueFields) {
                 $content = array();
                 if (is_array($valueFields)) {
                     $keys = $valueFields;
                 } else {
                     $keys = array($valueFields);
                 }
                 foreach ($keys as $key) {
                     if ($_lead->{$key} instanceof DateTime) {
                         $content[] = Tinebase_Translation::dateToStringInTzAndLocaleFormat($_lead->{$key}, NULL, NULL, 'date');
                     } elseif (!empty($_lead->{$key})) {
                         if ($key === 'turnover') {
                             try {
                                 $content[] = Zend_Locale_Format::toNumber($_lead->{$key}, array('locale' => $_locale)) . " €";
                             } catch (Zend_Locale_Exception $zle) {
                                 Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Could not convert turnover: ' . $zle->getMessage());
                                 $content[] = 'NaN';
                             }
                         } elseif ($key === 'probability') {
                             $content[] = $_lead->{$key} . " %";
                         } elseif ($key === 'leadstate_id') {
                             $content[] = Crm_Config::getInstance()->get(Crm_Config::LEAD_STATES)->getTranslatedValue($_lead->leadstate_id);
                         } elseif ($key === 'leadtype_id') {
                             $content[] = Crm_Config::getInstance()->get(Crm_Config::LEAD_TYPES)->getTranslatedValue($_lead->leadtype_id);
                         } elseif ($key === 'leadsource_id') {
                             $content[] = Crm_Config::getInstance()->get(Crm_Config::LEAD_SOURCES)->getTranslatedValue($_lead->leadsource_id);
                         } else {
                             $content[] = $_lead->{$key};
                         }
                     }
                 }
                 if (!empty($content)) {
                     $glue = isset($fieldArray['glue']) ? $fieldArray['glue'] : " ";
                     $values[] = implode($glue, $content);
                 }
             }
             if (!empty($values)) {
                 $record[] = array('label' => $fieldArray['label'], 'type' => isset($fieldArray['type']) ? $fieldArray['type'] : 'singleRow', 'value' => sizeof($values) === 1 ? $values[0] : $values);
             }
         } elseif (isset($fieldArray['type']) && $fieldArray['type'] === 'separator') {
             $record[] = $fieldArray;
         }
     }
     $record = $this->_addActivities($record, $_lead->notes);
     return $record;
 }
 /**
  * save crm settings
  * 
  * @param Crm_Model_Config $_settings
  * @return Crm_Model_Config
  * 
  * @todo generalize this
  */
 public function saveConfigSettings($_settings)
 {
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Updating Crm Settings: ' . print_r($_settings->toArray(), TRUE));
     }
     foreach ($_settings->toArray() as $field => $value) {
         if ($field == 'id') {
             continue;
         } else {
             if ($field == 'defaults') {
                 parent::saveConfigSettings($value);
             } else {
                 Crm_Config::getInstance()->set($field, $value);
             }
         }
     }
     // invalidate cache
     Tinebase_Core::getCache()->remove('getCrmSettings');
     Crm_Config::getInstance()->clearCache();
     return $this->getConfigSettings();
 }
 /**
  * creates notification text and sends out notifications
  *
  * @todo:
  *  - add changes to mail body
  *  - find updater in addressbook to notify him
  *  - add products?
  *  - add notification levels
  *  
  * @param Tinebase_Record_Interface $_lead
  * @param Tinebase_Model_FullUser   $_updater
  * @param string                    $_action   {created|changed}
  * @param Tinebase_Record_Interface $_oldLead
  * @param Array                     $_additionalData
  * @return void
  */
 public function doSendNotifications(Tinebase_Record_Interface $_lead, Tinebase_Model_FullUser $_updater, $_action, Tinebase_Record_Interface $_oldLead = NULL, array $_additionalData = array())
 {
     $sendOnOwnActions = Tinebase_Core::getPreference('Crm')->getValue(Crm_Preference::SEND_NOTIFICATION_OF_OWN_ACTIONS);
     if (!$sendOnOwnActions) {
         Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Sending of Lead notifications disabled by user.');
         return;
     }
     $view = new Zend_View();
     $view->setScriptPath(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'views');
     $translate = Tinebase_Translation::getTranslation('Crm');
     $view->updater = $_updater;
     $view->lead = $_lead;
     $view->leadState = Crm_Config::getInstance()->get(Crm_Config::LEAD_STATES)->getTranslatedValue($_lead->leadstate_id);
     $view->leadType = Crm_Config::getInstance()->get(Crm_Config::LEAD_TYPES)->getTranslatedValue($_lead->leadtype_id);
     $view->leadSource = Crm_Config::getInstance()->get(Crm_Config::LEAD_SOURCES)->getTranslatedValue($_lead->leadsource_id);
     $view->container = Tinebase_Container::getInstance()->getContainerById($_lead->container_id);
     $view->tags = Tinebase_Tags::getInstance()->getTagsOfRecord($_lead);
     $view->updates = $this->_getNotificationUpdates($_lead, $_oldLead);
     if (isset($_lead->relations)) {
         $customer = $_lead->relations->filter('type', 'CUSTOMER')->getFirstRecord();
         if ($customer) {
             $view->customer = $customer->related_record->n_fn;
             if (isset($customer->related_record->org_name)) {
                 $view->customer .= ' (' . $customer->related_record->org_name . ')';
             }
         }
     }
     if ($_lead->start instanceof DateTime) {
         $view->start = Tinebase_Translation::dateToStringInTzAndLocaleFormat($_lead->start, NULL, NULL, 'date');
     } else {
         $view->start = '-';
     }
     if ($_lead->end instanceof DateTime) {
         $view->leadEnd = Tinebase_Translation::dateToStringInTzAndLocaleFormat($_lead->end, NULL, NULL, 'date');
     } else {
         $view->leadEnd = '-';
     }
     if ($_lead->end_scheduled instanceof DateTime) {
         $view->ScheduledEnd = Tinebase_Translation::dateToStringInTzAndLocaleFormat($_lead->end_scheduled, NULL, NULL, 'date');
     } else {
         $view->ScheduledEnd = '-';
     }
     $view->lang_customer = $translate->_('Customer');
     $view->lang_state = $translate->_('State');
     $view->lang_type = $translate->_('Role');
     $view->lang_source = $translate->_('Source');
     $view->lang_start = $translate->_('Start');
     $view->lang_scheduledEnd = $translate->_('Scheduled end');
     $view->lang_end = $translate->_('End');
     $view->lang_turnover = $translate->_('Turnover');
     $view->lang_probability = $translate->_('Probability');
     $view->lang_folder = $translate->_('Folder');
     $view->lang_updatedBy = $translate->_('Updated by');
     $view->lang_updatedFields = $translate->_('Updated Fields:');
     $view->lang_updatedFieldMsg = $translate->_("'%s' changed from '%s' to '%s'.");
     $view->lang_tags = $translate->_('Tags');
     $plain = $view->render('newLeadPlain.php');
     $html = $view->render('newLeadHtml.php');
     if ($_action == 'changed') {
         $subject = sprintf($translate->_('Lead %s has been changed'), $_lead->lead_name);
     } else {
         if ($_action == 'deleted') {
             $subject = sprintf($translate->_('Lead %s has been deleted'), $_lead->lead_name);
         } else {
             $subject = sprintf($translate->_('Lead %s has been created'), $_lead->lead_name);
         }
     }
     // create pdf
     try {
         $pdfGenerator = new Crm_Export_Pdf();
         $pdfGenerator->generate($_lead);
         $attachment = array('rawdata' => $pdfGenerator->render(), 'filename' => $_lead->lead_name . '.pdf');
     } catch (Zend_Pdf_Exception $e) {
         Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' error creating pdf: ' . $e->__toString());
         $attachment = NULL;
     }
     $recipients = $this->_getNotificationRecipients($_lead);
     // send notification to updater in any case!
     if (!in_array($_updater->contact_id, $recipients->getArrayOfIds())) {
         $updaterContact = Addressbook_Controller_Contact::getInstance()->get($_updater->contact_id);
         $recipients->addRecord($updaterContact);
     }
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . $plain);
     }
     try {
         Tinebase_Notification::getInstance()->send(Tinebase_Core::getUser(), $recipients, $subject, $plain, $html, array($attachment));
     } catch (Exception $e) {
         Tinebase_Core::getLogger()->warn(__CLASS__ . '::' . __METHOD__ . '::' . __LINE__ . ' ' . $e->getMessage());
         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
             Tinebase_Core::getLogger()->trace(__CLASS__ . '::' . __METHOD__ . '::' . __LINE__ . ' ' . $e->getTraceAsString());
         }
     }
 }
 /**
  * (non-PHPdoc)
  * @see Tinebase_Backend_Sql_Abstract::_appendForeignSort()
  * 
  * @todo generalize this: find a place (in model config?) for foreign record sorting information
  * @todo maybe we can use a temp table with joins here
  * @todo allow to to use it with keyfields, too (and/or switch those settings to keyfield configs)
  */
 protected function _appendForeignSort(Tinebase_Model_Pagination $pagination, Zend_Db_Select $select)
 {
     $virtualSortColumns = array('leadstate_id' => Crm_Config::LEAD_STATES, 'leadsource_id' => Crm_Config::LEAD_SOURCES, 'leadtype_id' => Crm_Config::LEAD_TYPES);
     $col = $pagination->sort;
     if (isset($virtualSortColumns[$col])) {
         $config = Crm_Config::getInstance()->get($virtualSortColumns[$col]);
         // create cases (when => then) for sql switch (CASE) command
         $cases = array();
         foreach ($config['records'] as $settingRecord) {
             $cases[$settingRecord['id']] = $settingRecord['value'];
         }
         $foreignSortCase = $this->_dbCommand->getSwitch($col, $cases);
         $select->columns(array('foreignSortCol' => $foreignSortCase));
         $pagination->sort = 'foreignSortCol';
     }
 }