public function export(ServiceBase $api, $args = array())
 {
     ob_start();
     // Load up a seed bean
     $seed = BeanFactory::getBean('ForecastWorksheets');
     if (!$seed->ACLAccess('list')) {
         throw new SugarApiExceptionNotAuthorized('No access to view records for module: ' . $seed->object_name);
     }
     $args['timeperiod_id'] = isset($args['timeperiod_id']) ? $args['timeperiod_id'] : TimePeriod::getCurrentId();
     $args['user_id'] = isset($args['user_id']) ? $args['user_id'] : $api->user->id;
     if (!isset($args['filters'])) {
         $args['filters'] = array();
     } elseif (!is_array($args['filters'])) {
         $args['filters'] = array($args['filters']);
     }
     // don't allow encoding to html for data used in export
     $args['encode_to_html'] = false;
     // base file and class name
     $file = 'include/SugarForecasting/Export/Individual.php';
     $klass = 'SugarForecasting_Export_Individual';
     // check for a custom file exists
     SugarAutoLoader::requireWithCustom($file);
     $klass = SugarAutoLoader::customClass($klass);
     // create the class
     /* @var $obj SugarForecasting_Export_AbstractExport */
     $obj = new $klass($args);
     $content = $obj->process($api);
     ob_end_clean();
     return $this->doExport($api, $obj->getFilename(), $content);
 }
 /**
  * Utility Method to create the filter for the filer API to use
  *
  * @param ServiceBase $api                  Service Api Class
  * @param mixed $user_id                    Passed in User ID, if false, it will use the current use from $api->user
  * @param mixed $timeperiod_id              TimePeriod Id, if false, the current time period will be found an used
  * @param string $forecast_type             Type of forecast to return, direct or rollup
  * @return array                            The Filer array to be passed back into the filerList Api
  * @throws SugarApiExceptionNotAuthorized
  * @throws SugarApiExceptionInvalidParameter
  */
 protected function createFilter(ServiceBase $api, $user_id, $timeperiod_id, $forecast_type)
 {
     $filter = array();
     // if we did not find a user in the filters array, set it to the current user's id
     if ($user_id == false) {
         // use the current user, since on one was passed in
         $user_id = $api->user->id;
     } else {
         // make sure that the passed in user is a valid user
         /* @var $user User */
         // we use retrieveBean so it will return NULL and not an empty bean if the $args['user_id'] is invalid
         $user = BeanFactory::retrieveBean('Users', $user_id);
         if (is_null($user) || is_null($user->id)) {
             throw new SugarApiExceptionInvalidParameter('Provided User is not valid');
         }
         # if they are not a manager, don't show them committed number for others
         global $mod_strings, $current_language;
         $mod_strings = return_module_language($current_language, 'Forecasts');
         if ($user_id != $api->user->id && !User::isManager($api->user->id)) {
             throw new SugarApiExceptionNotAuthorized(string_format($mod_strings['LBL_ERROR_NOT_MANAGER'], array($api->user->id, $user_id)));
         }
     }
     // set the assigned_user_id
     array_push($filter, array('user_id' => $user_id));
     if ($forecast_type !== false) {
         // make sure $forecast_type is valid (e.g. Direct or Rollup)
         switch (strtolower($forecast_type)) {
             case 'direct':
             case 'rollup':
                 break;
             default:
                 throw new SugarApiExceptionInvalidParameter('Forecast Type of ' . $forecast_type . ' is not valid. Valid options Direct or Rollup.');
         }
         // set the forecast type, make sure it's always capitalized
         array_push($filter, array('forecast_type' => ucfirst($forecast_type)));
     }
     // if we didn't find a time period, set the time period to be the current time period
     if ($timeperiod_id == false) {
         $timeperiod_id = TimePeriod::getCurrentId();
     }
     // fix up the timeperiod filter
     /* @var $tp TimePeriod */
     // we use retrieveBean so it will return NULL and not an empty bean if the $args['timeperiod_id'] is invalid
     $tp = BeanFactory::retrieveBean('TimePeriods', $timeperiod_id);
     if (is_null($tp) || is_null($tp->id)) {
         throw new SugarApiExceptionInvalidParameter('Provided TimePeriod is not valid');
     }
     array_push($filter, array('timeperiod_id' => $tp->id));
     return $filter;
 }
Esempio n. 3
0
 /**
  * Retrieve a user's quota using the rollup value, if available.  This method is useful for
  * fetching user quota data when you're unsure about whether or not the given user is a manager.
  * If you would like to force a direct quota, pass a false value to $should_rollup.
  *
  * @param $timeperiod_id String id of the TimePeriod to retrieve quota for
  * @param $user_id String value of the user id to retrieve.  If NULL, the $current_user is used
  * @param $should_rollup boolean value indicating whether or not the quota should be a rollup calculation; false by default
  *
  * @return array [currency_id => int, amount => number, formatted_amount => String]
  */
 public function getRollupQuota($timeperiod_id, $user_id = null, $should_rollup = false)
 {
     if (is_null($user_id)) {
         global $current_user;
         $user_id = $current_user->id;
     }
     // figure out the timeperiod
     // if we didn't find a time period, set the time period to be the current time period
     if (!is_guid($timeperiod_id) && is_numeric($timeperiod_id) && $timeperiod_id != 0) {
         // we have a timestamp, find timeperiod it belongs in
         $timeperiod_id = TimePeriod::getIdFromTimestamp($timeperiod_id);
     }
     if (!is_guid($timeperiod_id)) {
         $timeperiod_id = TimePeriod::getCurrentId();
     }
     $sq = new SugarQuery();
     $sq->select(array('quotas.currency_id', 'quotas.amount'));
     $sq->from(BeanFactory::getBean('Quotas'));
     $sq->where()->equals('user_id', $user_id)->equals('quota_type', $should_rollup ? 'Rollup' : 'Direct')->equals('timeperiod_id', $timeperiod_id);
     $sq->orderBy('date_modified', 'DESC');
     $sq->limit(1);
     // since there is only ever one row, just shift the value off the results
     $row = array_shift($sq->execute());
     if (empty($row)) {
         // This is to prevent return value of false when a given timeperiod has no quota.
         $row = array('currency_id' => -99, 'amount' => 0);
     }
     $row['formatted_amount'] = SugarCurrency::formatAmountUserLocale($row['amount'], $row['currency_id']);
     return $row;
 }
Esempio n. 4
0
 /**
  * @param String|Number $tp_id
  * @return TimePeriod
  * @throws SugarApiExceptionInvalidParameter
  */
 protected function getTimeperiod($tp_id = '')
 {
     $forecast_settings = $this->getForecastSettings();
     if ($forecast_settings['is_setup'] == 1) {
         // we have no timeperiod defined, so lets just pull the current one
         if (empty($tp_id)) {
             $tp_id = TimePeriod::getCurrentId();
         }
         /* @var $tp TimePeriod */
         // we use retrieveBean so it will return NULL and not an empty bean if the $args['timeperiod_id'] is invalid
         $tp = BeanFactory::retrieveBean('TimePeriods', $tp_id);
     } else {
         /* @var $tp TimePeriod */
         $tp = BeanFactory::retrieveBean('TimePeriods');
         // generate the generic timeperiod based off the integer that was passed in.
         $data = $tp->getGenericStartEndByDuration($tp_id);
         // set the values
         $tp->id = 'fake_timeperiod';
         foreach ($data as $key => $value) {
             $tp->{$key} = $value;
         }
     }
     // if $tp is null or the id is empty, throw an exception
     if (is_null($tp) || empty($tp->id)) {
         throw new SugarApiExceptionInvalidParameter('Provided TimePeriod is invalid');
     }
     return $tp;
 }
Esempio n. 5
0
 /**
  * Returns the current TimePeriod name if a TimePeriod entry is found
  *
  * @param $type String CONSTANT for the TimePeriod type; if none supplied it will use the leaf type as defined in config settings
  * @return String name of the current TimePeriod for given type; null if none found
  */
 public static function getCurrentName($type = '')
 {
     if (empty($type)) {
         $admin = BeanFactory::getBean('Administration');
         $config = $admin->getConfigForModule('Forecasts', 'base');
         $type = $config['timeperiod_leaf_interval'];
     }
     $id = TimePeriod::getCurrentId($type);
     $tp = TimePeriod::getByType($type, $id);
     return !empty($tp) ? $tp->name : null;
 }
 /**
  * Roll up the data from the rep-worksheets to the manager worksheets
  *
  * @param User $reportee
  * @param $data
  * @return boolean
  */
 public function reporteeForecastRollUp(User $reportee, $data)
 {
     /* @var $quotaSeed Quota */
     $quotaSeed = BeanFactory::getBean('Quotas');
     if (!isset($data['timeperiod_id']) || !is_guid($data['timeperiod_id'])) {
         $data['timeperiod_id'] = TimePeriod::getCurrentId();
     }
     // handle top level managers
     $reports_to = $reportee->reports_to_id;
     if (empty($reports_to)) {
         $reports_to = $reportee->id;
     }
     if (isset($data['forecast_type'])) {
         // check forecast type to see if the assigned_user_id should be equal to the $reportee as it's their own
         // rep worksheet
         if ($data['forecast_type'] == "Direct" && User::isManager($reportee->id)) {
             // this is the manager committing their own data, the $reports_to should be them
             // and not their actual manager
             $reports_to = $reportee->id;
         } else {
             if ($data['forecast_type'] == "Rollup" && $reports_to == $reportee->id) {
                 // if type is rollup and reports_to is equal to the $reportee->id (aka no top level manager),
                 // we don't want to update their draft record so just ignore this,
                 return false;
             }
         }
     }
     if (isset($data['draft']) && $data['draft'] == '1' && $GLOBALS['current_user']->id == $reportee->id) {
         // this data is for the current user, but is not a commit so we need to update their own draft record
         $reports_to = $reportee->id;
     }
     $this->retrieve_by_string_fields(array('user_id' => $reportee->id, 'assigned_user_id' => $reports_to, 'timeperiod_id' => $data['timeperiod_id'], 'draft' => 1, 'deleted' => 0));
     $copyMap = array('currency_id', 'base_rate', 'timeperiod_id', 'opp_count', 'pipeline_opp_count', 'pipeline_amount', 'closed_amount');
     if ($data["forecast_type"] == "Direct") {
         $copyMap[] = "likely_case";
         $copyMap[] = "best_case";
         $copyMap[] = "worst_case";
     } else {
         if ($data["forecast_type"] == "Rollup") {
             $copyMap[] = array("likely_case" => "likely_adjusted");
             $copyMap[] = array("best_case" => "best_adjusted");
             $copyMap[] = array("worst_case" => "worst_adjusted");
         }
     }
     if (empty($this->id) || $this->manager_saved == false) {
         if ($data["forecast_type"] == "Rollup") {
             $copyMap[] = array('likely_case_adjusted' => 'likely_adjusted');
             $copyMap[] = array('best_case_adjusted' => 'best_adjusted');
             $copyMap[] = array('worst_case_adjusted' => 'worst_adjusted');
         } elseif ($data["forecast_type"] == "Direct") {
             $copyMap[] = array('likely_case_adjusted' => 'likely_case');
             $copyMap[] = array('best_case_adjusted' => 'best_case');
             $copyMap[] = array('worst_case_adjusted' => 'worst_case');
         }
     }
     if (empty($this->id)) {
         if (!isset($data['quota']) || empty($data['quota'])) {
             // we need to get a fresh bean to store the quota if one exists
             $quotaSeed = BeanFactory::getBean('Quotas');
             // check if we need to get the roll up amount
             $getRollupQuota = User::isManager($reportee->id) && isset($data['forecast_type']) && $data['forecast_type'] == 'Rollup';
             $quota = $quotaSeed->getRollupQuota($data['timeperiod_id'], $reportee->id, $getRollupQuota);
             $data['quota'] = $quota['amount'];
         }
         $copyMap[] = "quota";
     }
     $this->copyValues($copyMap, $data);
     // set the team to the default ones from the passed in user
     $this->team_set_id = $reportee->team_set_id;
     $this->team_id = $reportee->team_id;
     $this->name = $reportee->full_name;
     $this->user_id = $reportee->id;
     $this->assigned_user_id = $reports_to;
     $this->draft = 1;
     $this->save();
     // roll up the draft value for best/likely/worst case values to the committed record if one exists
     $this->rollupDraftToCommittedWorksheet($this);
     return true;
 }
Esempio n. 7
0
 /**
  * Retrieve forecast data for user given a timeperiod.  By default uses the currently logged-in
  * user and the current timeperiod.
  *
  * @param String $user_id
  * @param String $timeperiod_id
  * @param bool   $should_rollup     False to use direct numbers, true to use rollup.
  */
 function getForecastForUser($user_id = NULL, $timeperiod_id, $should_rollup = FALSE)
 {
     global $current_user;
     if (is_null($user_id)) {
         $user_id = $current_user->id;
     }
     $where = "user_id='{$user_id}'";
     if ($should_rollup) {
         $where .= " AND forecast_type='Rollup'";
     } else {
         $where .= " AND forecast_type='Direct'";
     }
     if (!is_null($timeperiod_id)) {
         $where .= " AND timeperiod_id='{$timeperiod_id}'";
     } else {
         $where .= " AND timeperiod_id='" . TimePeriod::getCurrentId() . "'";
     }
     $query = $this->create_new_list_query(NULL, $where);
     $result = $this->db->query($query, true, 'Error retrieving user forecast information: ');
     return $this->db->fetchByAssoc($result);
 }
 /**
  * Utility Method to create the filter for the filer API to use
  *
  * @param ServiceBase $api                  Service Api Class
  * @param mixed $user_id                    Passed in User ID, if false, it will use the current use from $api->user
  * @param mixed $timeperiod_id              TimePeriod Id, if false, the current time period will be found an used
  * @return array                            The Filer array to be passed back into the filerList Api
  * @throws SugarApiExceptionNotAuthorized
  * @throws SugarApiExceptionInvalidParameter
  */
 protected function createFilter(ServiceBase $api, $user_id, $timeperiod_id)
 {
     // we need to check if the $api->user is a manager
     // if they are not a manager, throw back a 403 (Not Authorized) error
     if (!User::isManager($api->user->id)) {
         throw new SugarApiExceptionNotAuthorized();
     }
     $filter = array();
     // default draft to be 1
     $draft = 1;
     // if we did not find a user in the filters array, set it to the current user's id
     if ($user_id == false) {
         // use the current user, since on one was passed in
         $user_id = $api->user->id;
     } else {
         // make sure that the passed in user is a valid user
         /* @var $user User */
         // we use retrieveBean so it will return NULL and not an empty bean if the $args['user_id'] is invalid
         $user = BeanFactory::retrieveBean('Users', $user_id);
         if (is_null($user)) {
             throw new SugarApiExceptionInvalidParameter('Provided User is not valid');
         }
         // we found a user, so check to make sure that if it's not the current user, they only see committed data
         $draft = $user_id == $api->user->id ? 1 : 0;
     }
     // todo-sfa: Make sure that the passed in user can be viewed by the $api->user, need to check reportee tree
     // set the assigned_user_id
     array_push($filter, array('assigned_user_id' => $user_id));
     // set the draft flag depending on the assigned_user_id that is set from above
     array_push($filter, array('draft' => $draft));
     // if we didn't find a time period, set the time period to be the current time period
     if (!is_guid($timeperiod_id) && is_numeric($timeperiod_id) && $timeperiod_id != 0) {
         // we have a timestamp, find timeperiod it belongs in
         $timeperiod_id = TimePeriod::getIdFromTimestamp($timeperiod_id);
     }
     if (!is_guid($timeperiod_id)) {
         $timeperiod_id = TimePeriod::getCurrentId();
     }
     // fix up the timeperiod filter
     /* @var $tp TimePeriod */
     // we use retrieveBean so it will return NULL and not an empty bean if the $args['timeperiod_id'] is invalid
     $tp = BeanFactory::retrieveBean('TimePeriods', $timeperiod_id);
     if (is_null($tp)) {
         throw new SugarApiExceptionInvalidParameter('Provided TimePeriod is not valid');
     }
     array_push($filter, array('timeperiod_id' => $tp->id));
     return $filter;
 }
 /**
  * Utility Method to create the filter for the filer API to use
  *
  * @param ServiceBase $api                  Service Api Class
  * @param mixed $user_id                    Passed in User ID, if false, it will use the current use from $api->user
  * @param mixed $timeperiod_id              TimePeriod Id, if false, the current time period will be found an used
  * @param string $parent_type               Type of worksheet to return, defaults to 'opportunities', but can be 'products'
  * @return array                            The Filer array to be passed back into the filerList Api
  * @throws SugarApiExceptionNotAuthorized
  * @throws SugarApiExceptionInvalidParameter
  */
 protected function createFilter(ServiceBase $api, $user_id, $timeperiod_id, $parent_type = 'Opportunities')
 {
     $filter = array();
     // default draft to be 1
     $draft = 1;
     // if we did not find a user in the filters array, set it to the current user's id
     if ($user_id == false) {
         // use the current user, since on one was passed in
         $user_id = $api->user->id;
     } else {
         // make sure that the passed in user is a valid user
         /* @var $user User */
         // we use retrieveBean so it will return NULL and not an empty bean if the $args['user_id'] is invalid
         $user = BeanFactory::retrieveBean('Users', $user_id);
         if (is_null($user)) {
             throw new SugarApiExceptionInvalidParameter('Provided User is not valid');
         }
         // we found a user, so check to make sure that if it's not the current user, they only see committed data
         $draft = $user_id == $api->user->id ? 1 : 0;
     }
     // so we have a valid user, and it's not the $api->user, we need to check if the $api->user is a manager
     // if they are not a manager, throw back a 403 (Not Authorized) error
     if ($draft == 0 && !User::isManager($api->user->id)) {
         throw new SugarApiExceptionNotAuthorized();
     }
     // todo-sfa: Make sure that the passed in user can be viewed by the $api->user, need to check reportee tree
     // set the assigned_user_id
     array_push($filter, array('assigned_user_id' => $user_id));
     // set the draft flag depending on the assigned_user_id that is set from above
     array_push($filter, array('draft' => $draft));
     // if we didn't find a time period, set the time period to be the current time period
     if (!is_guid($timeperiod_id) && is_numeric($timeperiod_id) && $timeperiod_id != 0) {
         // we have a timestamp, find timeperiod it belongs in
         $timeperiod_id = TimePeriod::getIdFromTimestamp($timeperiod_id);
     }
     if (!is_guid($timeperiod_id)) {
         $timeperiod_id = TimePeriod::getCurrentId();
     }
     // fix up the timeperiod filter
     /* @var $tp TimePeriod */
     // we use retrieveBean so it will return NULL and not an empty bean if the $args['timeperiod_id'] is invalid
     $tp = BeanFactory::retrieveBean('TimePeriods', $timeperiod_id);
     if (is_null($tp)) {
         throw new SugarApiExceptionInvalidParameter('Provided TimePeriod is not valid');
     }
     array_push($filter, array('$and' => array(array('date_closed_timestamp' => array('$gte' => $tp->start_date_timestamp)), array('date_closed_timestamp' => array('$lte' => $tp->end_date_timestamp)))));
     if (empty($parent_type)) {
         // get the forecast_by setting
         /* @var $admin Administration */
         $admin = BeanFactory::getBean('Administration');
         $settings = $admin->getConfigForModule('Forecasts', $api->platform);
         $parent_type = $settings['forecast_by'];
     }
     // we only want to view parent_types of 'Opportunities' here
     array_push($filter, array('parent_type' => $parent_type));
     return $filter;
 }
Esempio n. 10
0
 /**
  * Save any committed values
  *
  * @return array|mixed
  */
 public function save()
 {
     global $current_user;
     $args = $this->getArgs();
     $db = DBManagerFactory::getInstance();
     if (!isset($args['timeperiod_id']) || empty($args['timeperiod_id'])) {
         $args['timeperiod_id'] = TimePeriod::getCurrentId();
     }
     $commit_type = strtolower($this->getArg('commit_type'));
     /* @var $mgr_worksheet ForecastManagerWorksheet */
     $mgr_worksheet = BeanFactory::getBean('ForecastManagerWorksheets');
     /* @var $worksheet ForecastWorksheet */
     $worksheet = BeanFactory::getBean('ForecastWorksheets');
     $field_ext = '_case';
     if ($commit_type == "manager") {
         $worksheet_totals = $mgr_worksheet->worksheetTotals($current_user->id, $args['timeperiod_id']);
         // we don't need the *_case values so lets make them the same as the *_adjusted values
         $field_ext = '_adjusted';
     } else {
         $worksheet_totals = $worksheet->worksheetTotals($args['timeperiod_id'], $current_user->id);
         // set likely
         $worksheet_totals['likely_case'] = SugarMath::init($worksheet_totals['amount'], 6)->add($worksheet_totals['includedClosedAmount'])->result();
         $worksheet_totals['best_case'] = SugarMath::init($worksheet_totals['best_case'], 6)->add($worksheet_totals['includedClosedBest'])->result();
         $worksheet_totals['worst_case'] = SugarMath::init($worksheet_totals['worst_case'], 6)->add($worksheet_totals['includedClosedWorst'])->result();
     }
     /* @var $forecast Forecast */
     $forecast = BeanFactory::getBean('Forecasts');
     $forecast->user_id = $current_user->id;
     $forecast->timeperiod_id = $args['timeperiod_id'];
     $forecast->best_case = $worksheet_totals['best' . $field_ext];
     $forecast->likely_case = $worksheet_totals['likely' . $field_ext];
     $forecast->worst_case = $worksheet_totals['worst' . $field_ext];
     $forecast->forecast_type = $args['forecast_type'];
     $forecast->opp_count = $worksheet_totals['included_opp_count'];
     $forecast->currency_id = '-99';
     $forecast->base_rate = '1';
     //If we are committing a rep forecast, calculate things.  Otherwise, for a manager, just use what is passed in.
     if ($args['commit_type'] == 'sales_rep') {
         $forecast->calculatePipelineData($worksheet_totals['includedClosedAmount'], $worksheet_totals['includedClosedCount']);
         //push the pipeline numbers back into the args
         $args['pipeline_opp_count'] = $forecast->pipeline_opp_count;
         $args['pipeline_amount'] = $forecast->pipeline_amount;
         $worksheet_totals['closed_amount'] = $forecast->closed_amount;
     } else {
         $forecast->pipeline_opp_count = $worksheet_totals['pipeline_opp_count'];
         $forecast->pipeline_amount = $worksheet_totals['pipeline_amount'];
         $forecast->closed_amount = $worksheet_totals['closed_amount'];
     }
     if ($worksheet_totals['likely_case'] != 0 && $worksheet_totals['included_opp_count'] != 0) {
         $forecast->opp_weigh_value = $worksheet_totals['likely_case'] / $worksheet_totals['included_opp_count'];
     }
     $forecast->save();
     // roll up the committed forecast to that person manager view
     // copy the object so we can set some needed values
     $mgr_rollup_data = $worksheet_totals;
     $mgr_rollup_data['forecast_type'] = $args['forecast_type'];
     // pass same timeperiod as the other data to the manager's rollup
     $mgr_rollup_data['timeperiod_id'] = $args['timeperiod_id'];
     $mgr_worksheet->reporteeForecastRollUp($current_user, $mgr_rollup_data);
     if ($this->getArg('commit_type') == "sales_rep") {
         $worksheet->commitWorksheet($current_user->id, $args['timeperiod_id']);
     } elseif ($this->getArg('commit_type') == "manager") {
         $mgr_worksheet->commitManagerForecast($current_user, $args['timeperiod_id']);
     }
     //TODO-sfa remove this once the ability to map buckets when they get changed is implemented (SFA-215).
     $admin = BeanFactory::getBean('Administration');
     $settings = $admin->getConfigForModule('Forecasts');
     if (!isset($settings['has_commits']) || !$settings['has_commits']) {
         $admin->saveSetting('Forecasts', 'has_commits', true, 'base');
         MetaDataManager::refreshModulesCache(array('Forecasts'));
     }
     $forecast->date_entered = $this->convertDateTimeToISO($db->fromConvert($forecast->date_entered, 'datetime'));
     $forecast->date_modified = $this->convertDateTimeToISO($db->fromConvert($forecast->date_modified, 'datetime'));
     return $worksheet_totals;
 }