/** * Build and run the query to select all contributions * matching the criteria, and try to create a snapshot * * @return snapshot creation result/error */ public static function createSnapshot($values) { // prepare timestamps $raw_from_ts = $values['donrec_contribution_horizon_from']; $raw_to_ts = $values['donrec_contribution_horizon_to']; $date_from = CRM_Utils_DonrecHelper::convertDate($raw_from_ts, -1); $date_to = CRM_Utils_DonrecHelper::convertDate($raw_to_ts, 1); $formatted_date_from = date('Y-m-d H:i:s', $date_from); $formatted_date_to = date('Y-m-d H:i:s', $date_to); $query_date_limit = ""; if ($date_from) { $query_date_limit .= "AND `receive_date` >= '{$formatted_date_from}'"; } if ($date_to) { $query_date_limit .= " AND `receive_date` <= '{$formatted_date_to}'"; } // get table- and column name $table_query = "SELECT `cg`.`table_name`,\n `cf`.`column_name`\n FROM `civicrm_custom_group` AS cg,\n `civicrm_custom_field` AS cf\n WHERE `cg`.`name` = 'zwb_donation_receipt_item'\n AND `cf`.`custom_group_id` = `cg`.`id`\n AND `cf`.`name` = 'status'"; $results = CRM_Core_DAO::executeQuery($table_query); $custom_group_table = NULL; $status_column = NULL; while ($results->fetch()) { $custom_group_table = $results->table_name; $status_column = $results->column_name; } if ($custom_group_table == NULL || $status_column == NULL) { // something went wrong here CRM_Core_Error::debug_log_message("de.systopia.donrec: error: custom_group_table or status_column is empty!"); return array(); } // calculate main selector clause if (!empty($values['contact_id'])) { $contact_id = (int) $values['contact_id']; $main_selector = "`contact_id` = {$contact_id}"; } elseif (!empty($values['contact_ids'])) { $contact_ids = implode(',', $values['contact_ids']); $main_selector = "`contact_id` IN ({$contact_ids})"; } elseif (!empty($values['contribution_ids'])) { $contribution_ids = implode(',', $values['contribution_ids']); $main_selector = "`civicrm_contribution`.`id` IN ({$contribution_ids})"; } else { CRM_Core_Error::debug_log_message("de.systopia.donrec: error: no selector data found in params!"); $main_selector = "FALSE"; } // get financial type selector clause $profile = new CRM_Donrec_Logic_Profile($values['profile']); $financialTypeClause = $profile->getContributionTypesClause(); // run the main query $query = "SELECT `civicrm_contribution`.`id`\n FROM (`civicrm_contribution`)\n LEFT JOIN `{$custom_group_table}` AS existing_receipt\n ON `civicrm_contribution`.`id` = existing_receipt.`entity_id`\n AND existing_receipt.`{$status_column}` = 'ORIGINAL'\n WHERE\n ({$main_selector})\n {$query_date_limit}\n AND {$financialTypeClause}\n AND (`non_deductible_amount` = 0 OR `non_deductible_amount` IS NULL)\n AND `contribution_status_id` = 1\n AND `is_test` = 0\n AND `currency` = 'EUR'\n AND existing_receipt.`entity_id` IS NULL;"; // execute the query $result = CRM_Core_DAO::executeQuery($query); // build array $contributionIds = array(); while ($result->fetch()) { $contributionIds[] = $result->id; } // finally, build the snapshot with it return CRM_Donrec_Logic_Snapshot::create($contributionIds, CRM_Donrec_Logic_Settings::getLoggedInContactID(), $formatted_date_from, $formatted_date_to, $values['profile']); }
function postProcess() { // process all form values and save valid settings $values = $this->exportValues(); // save generic settings CRM_Donrec_Logic_Settings::set('donrec_packet_size', $values['packet_size']); if ($values['pdfinfo_path']) { CRM_Donrec_Logic_Settings::set('donrec_pdfinfo_path', $values['pdfinfo_path']); } // first, update current values into slected profile if (!empty($values['selected_profile'])) { $profile = $values['selected_profile']; $profile_data = json_decode($values['profile_data'], 1); $profile_defaults = CRM_Donrec_Logic_Profile::defaultProfileData(); foreach (array_keys($profile_defaults) as $field_name) { $value = CRM_Utils_Array::value($field_name, $values, NULL); if ($value != NULL) { $profile_data[$profile][$field_name] = $value; } } // verify some stuff foreach ($profile_data as $profile_name => $profile) { // test the ID pattern try { $generator = new CRM_Donrec_Logic_IDGenerator($profile['id_pattern'], false); } catch (Exception $e) { $session = CRM_Core_Session::singleton(); $session->setStatus(ts("One of the Receipt ID patterns are invalid! Changes NOT saved!", array('domain' => 'de.systopia.donrec')), ts('Error', array('domain' => 'de.systopia.donrec')), 'error'); return; } } // then store the profiles CRM_Donrec_Logic_Profile::setAllData($profile_data); } $session = CRM_Core_Session::singleton(); $session->setStatus(ts("Settings successfully saved", array('domain' => 'de.systopia.donrec')), ts('Settings', array('domain' => 'de.systopia.donrec')), 'success'); $session->replaceUserContext(CRM_Utils_System::url('civicrm/admin/setting/donrec')); }
function postProcess() { // CAUTION: changes to this function should also be done in CRM_Donrec_Form_Task_Create:postProcess() // process remaining snapshots if exsisting $rsid = empty($_REQUEST['rsid']) ? NULL : $_REQUEST['rsid']; if (!empty($rsid)) { //work on with a remaining snapshot... $use_remaining_snapshot = CRM_Utils_Array::value('use_remaining_snapshot', $_REQUEST, NULL); if (!empty($use_remaining_snapshot)) { CRM_Core_Session::singleton()->pushUserContext(CRM_Utils_System::url('civicrm/donrec/task', 'sid=' . $rsid)); return; // or delete all remaining snapshots of this user } else { $uid = CRM_Donrec_Logic_Settings::getLoggedInContactID(); CRM_Donrec_Logic_Snapshot::deleteUserSnapshots($uid); } } // process form values and try to build a snapshot with all contributions // that match the specified criteria (i.e. contributions which have been // created between two specific dates) $values = $this->exportValues(); $values['contact_ids'] = $this->_contactIds; //set url_back as session-variable $session = CRM_Core_Session::singleton(); $session->set('url_back', CRM_Utils_System::url('civicrm/contact/search', "reset=1")); // generate the snapshot $result = CRM_Donrec_Logic_Selector::createSnapshot($values); $sid = empty($result['snapshot']) ? NULL : $result['snapshot']->getId(); if (!empty($result['intersection_error'])) { CRM_Core_Session::singleton()->pushUserContext(CRM_Utils_System::url('civicrm/donrec/task', 'conflict=1' . '&sid=' . $result['snapshot']->getId() . '&ccount=' . count($this->_contactIds))); } elseif (empty($result['snapshot'])) { CRM_Core_Session::setStatus(ts('There are no selectable contributions for these contacts in the selected time period.', array('domain' => 'de.systopia.donrec')), ts('Warning', array('domain' => 'de.systopia.donrec')), 'warning'); $qfKey = $values['qfKey']; CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/search', "_qf_DonrecTask_display=true&qfKey={$qfKey}")); } else { CRM_Core_Session::singleton()->pushUserContext(CRM_Utils_System::url('civicrm/donrec/task', 'sid=' . $result['snapshot']->getId() . '&ccount=' . count($this->_contactIds))); } }
/** * will select a previously unprocessed set of snapshot items * * @return array: <id> => array with values */ public function getNextChunk($is_bulk, $is_test) { $chunk_size = CRM_Donrec_Logic_Settings::getChunkSize(); $snapshot_id = $this->getId(); $chunk = array(); if ($is_test) { $status_clause = "`status` IS NULL"; } else { $status_clause = "(`status` IS NULL OR `status`='TEST')"; } // here, we need a different algorithm for bulk than for single: if (empty($is_bulk)) { // SINGLE case: just grab $chunk_size items $query = "SELECT * FROM `donrec_snapshot` WHERE `snapshot_id` = {$snapshot_id} AND {$status_clause} LIMIT {$chunk_size};"; $result = CRM_Core_DAO::executeQuery($query); while ($result->fetch()) { $chunk_line = array(); foreach (self::$CHUNK_FIELDS as $field) { $chunk_line[$field] = $result->{$field}; } $chunk[$chunk_line['id']] = $chunk_line; } } else { // BULK case: get items grouped by contact ID until it exceeds $chunk_size // get all lines $query = "SELECT\n snapshot.*,\n a.contrib_count\n FROM\n `donrec_snapshot` AS snapshot,\n (SELECT `contact_id`, COUNT(*) AS contrib_count\n FROM `donrec_snapshot`\n GROUP BY `contact_id`) AS a\n WHERE a.`contact_id` = snapshot.`contact_id`\n AND snapshot.`snapshot_id` = {$snapshot_id}\n AND {$status_clause}\n ORDER BY snapshot.`contact_id` ASC;"; $query = CRM_Core_DAO::executeQuery($query); $last_added_contact_id = NULL; $contribution_count = 0; while ($query->fetch()) { if ($last_added_contact_id != $query->contact_id) { // this is a new contact ID if (count($chunk) >= $chunk_size || $contribution_count > 5 * $chunk_size) { // we already have $chunk_size contacts, or 5x $chunk_size contributions // => that's enough for this chunk! break; } // ok, we're still under the limit => create a section for the contact $chunk[$query->contact_id] = array(); $last_added_contact_id = $query->contact_id; } // add contribution $contribution = array(); foreach (self::$CHUNK_FIELDS as $field) { $contribution[$field] = $query->{$field}; } $chunk[$query->contact_id][] = $contribution; $contribution_count += 1; } } // reset the process information for the given chunk $this->resetChunk($chunk, $is_bulk); if (count($chunk) == 0) { return NULL; } else { return $chunk; } }
/** * Creates a copy of this receipt. The receipt status will be 'COPY' * * @param $parameters an assoc. array of creation parameters TODO: to be defined * * @return TRUE if successfull, FALSE otherwise. In that case, the $parameters['error'] contains an error message */ public function createCopy(&$parameters) { $receipt_id = $this->Id; $receipt_group_id = self::$_custom_group_id; $receipt_fields = self::$_custom_fields; $uid = CRM_Donrec_Logic_Settings::getLoggedInContactID(); $exclude = array('status', 'issued_on', 'issued_by', 'original_file'); $field_query = '`entity_id`'; foreach ($receipt_fields as $key => $field) { if (!in_array($key, $exclude)) { $field_query .= ", `{$field}`"; } } $query = "\n INSERT INTO `civicrm_value_donation_receipt_{$receipt_group_id}` (\n `{$receipt_fields['status']}`,\n `{$receipt_fields['issued_on']}`,\n `{$receipt_fields['issued_by']}`,\n {$field_query}\n )\n SELECT\n 'COPY' AS `{$receipt_fields['status']}`,\n NOW() AS `{$receipt_fields['issued_on']}`,\n {$uid} AS `{$receipt_fields['issued_by']}`,\n {$field_query}\n FROM `civicrm_value_donation_receipt_{$receipt_group_id}`\n WHERE `id` = {$receipt_id}\n AND `{$receipt_fields['status']}` = 'ORIGINAL'\n "; $result = CRM_Core_DAO::executeQuery($query); $lastId = CRM_Core_DAO::singleValueQuery('SELECT LAST_INSERT_ID();'); CRM_Donrec_Logic_ReceiptItem::createCopyAll($this->Id, $lastId); return TRUE; }
/** * get page count for a pdf file * * @return int page count (-1 if there is an error) */ private function getPDFPageCount($document) { $pdfinfo_path = CRM_Donrec_Logic_Settings::get('donrec_pdfinfo_path'); $cmd = escapeshellarg($pdfinfo_path); $document = escapeshellarg($document); $cmd = escapeshellcmd("{$cmd} {$document}") . " 2>&1"; exec($cmd, $output); $count = 0; foreach ($output as $line) { // Extract the number if (preg_match("/Pages:\\s*(\\d+)/i", $line, $matches) === 1) { return intval($matches[1]); } } return -1; }
/** * Get a batching lock * * the lock is needed so that only one relevant process can access the * payment/statment data structures at a time * * @return lock object. check if it ->isAcquired() before use */ public static function getLock($type, $id) { if ($type == '') { // for the 'next' lock, we calculate the lock timeout as follows $max_lock_timeout = ini_get('max_execution_time'); if (empty($max_lock_timeout)) { $max_lock_timeout = 30 * 60; // 30 minutes } // calculate based on chunk size (max 1min/item) $calculation_time = CRM_Donrec_Logic_Settings::getChunkSize() * 60; $timeout = min($calculation_time, $max_lock_timeout); } else { // default timeout for other locks $timeout = 600.0; // 10mins, TODO: do we need a setting here? } //CRM_Core_Error::debug_log_message("de.systopia.donrec.$type".'-'.$id." timeout $timeout created."); return CRM_Utils_DonrecSafeLock::acquireLock("de.systopia.donrec.{$type}" . '-' . $id, $timeout); }