Пример #1
0
 /**
  * Creates a receipt without receipt-items using the generic tokens
  * @param $tokens             tokens coming from SnapshotReceipt->getAllTokens
  * @return Receipt object if successfull, FALSE otherwise.
  */
 public static function _createReceiptFromTokens($tokens)
 {
     // initialize custom field map
     self::getCustomFields();
     $fields = self::$_custom_fields;
     $custom_group_id = self::$_custom_group_id;
     $table = "civicrm_value_donation_receipt_{$custom_group_id}";
     // build SET-SQL
     $sql_set = "`entity_id`={$tokens['contact_id']}";
     foreach ($fields as $key => $field) {
         $value = null;
         if (0 === strpos($key, 'shipping')) {
             $token_key = substr($key, strlen('shipping_'));
             $value = $tokens['addressee'][$token_key];
         } elseif ($tokens[$key]) {
             $value = $tokens[$key];
         } elseif ($tokens['contributor'][$key]) {
             $value = $tokens['contributor'][$key];
         }
         if (!is_null($value)) {
             $value = CRM_Utils_DonrecHelper::escapeString($value);
             $sql_set .= ", `{$field}`='{$value}'";
         }
     }
     // build query
     $query = "INSERT INTO `{$table}` SET {$sql_set}";
     // run the query
     return CRM_Core_DAO::executeQuery($query);
 }
Пример #2
0
 /** 
  * 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']);
 }
Пример #3
0
 /**
  * Creates a new receipt item
  * @param array of parameters
  * @return TRUE or FALSE if there was an error //TODO
  */
 public static function create($params)
 {
     self::getCustomFields();
     $fields = self::$_custom_fields;
     $group_id = self::$_custom_group_id;
     $table = "civicrm_value_donation_receipt_item_{$group_id}";
     $params['contribution_hash'] = self::calculateChecksum($params);
     // build set-string
     $set_str = "`entity_id`={$params['contribution_id']}";
     foreach ($fields as $key => $field) {
         if (!is_null($params[$key])) {
             $value = CRM_Utils_DonrecHelper::escapeString($params[$key]);
             $set_str .= ", `{$field}`='{$value}'";
         }
     }
     // build query
     $query = "INSERT INTO `{$table}` SET {$set_str}";
     // run query
     $result = CRM_Core_DAO::executeQuery($query);
     return $result;
 }
Пример #4
0
 /**
  * This is a workaround for the problem that using the translated title right away makes the
  * table names change.
  *
  * FIXME: we should not be working with static table names
  */
 public static function translateCustomGroups()
 {
     try {
         // TRANSLATE zwb_donation_receipt title
         $custom_group_receipt = civicrm_api3('CustomGroup', 'getsingle', array('name' => 'zwb_donation_receipt'));
         // since the API is not reliable here, we do this via SQL
         $new_title = CRM_Utils_DonrecHelper::escapeString(ts('Donation Receipt', array('domain' => 'de.systopia.donrec')));
         $custom_group_receipt_id = (int) $custom_group_receipt['id'];
         CRM_Core_DAO::executeQuery("UPDATE `civicrm_custom_group` SET title='{$new_title}' WHERE id={$custom_group_receipt_id};");
         // TRANSLATE zwb_donation_receipt_item title
         $custom_group_receipt_item = civicrm_api3('CustomGroup', 'getsingle', array('name' => 'zwb_donation_receipt_item'));
         // since the API is not reliable here, we do this via SQL
         $new_title = CRM_Utils_DonrecHelper::escapeString(ts('Donation Receipt Item', array('domain' => 'de.systopia.donrec')));
         $custom_group_receipt_item_id = (int) $custom_group_receipt_item['id'];
         CRM_Core_DAO::executeQuery("UPDATE `civicrm_custom_group` SET title='{$new_title}' WHERE id={$custom_group_receipt_item_id};");
     } catch (Exception $e) {
         CRM_Core_Error::debug_log_message('de.systopia.donrec - Error translating custom groups: ' . $e->getMessage());
     }
 }
Пример #5
0
/**
 * Prune the "find contributions" and "advanced contact search" forms
 * by removing the fields that don't make sense or don't work
 */
function donrec_civicrm_buildForm($formName, &$form)
{
    if ($formName == 'CRM_Contribute_Form_Search') {
        $item_fields = CRM_Donrec_Logic_ReceiptItem::getCustomFields();
        // remove unwanted fields
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'financial_type_id');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'total_amount');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'non_deductible_amount');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'currency');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'contribution_hash');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'issued_on');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'receive_date');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'issued_in');
        $form->assign('field_ids_to_remove', implode(',', $field_ids_to_remove));
        CRM_Core_Region::instance('page-body')->add(array('template' => 'CRM/Donrec/Form/Search/RemoveFields.snippet.tpl'));
        // DISABLED: date field search doesn't work
        // CRM_Utils_DonrecHelper::relabelDateField($form, $item_fields, 'issued_on', ts("Issed On - From", array('domain' => 'de.systopia.donrec')), ts("Issed On - To", array('domain' => 'de.systopia.donrec')));
        // CRM_Utils_DonrecHelper::relabelDateField($form, $item_fields, 'receive_date', ts("Received - From", array('domain' => 'de.systopia.donrec')), ts("Received - To", array('domain' => 'de.systopia.donrec')));
        // override the standard fields
        $status_id = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'status');
        if ($status_id) {
            $form->add('select', "custom_{$status_id}", ts('Status', array('domain' => 'de.systopia.donrec')), array('' => ts('- any -', array('domain' => 'de.systopia.donrec')), 'original' => ts('original', array('domain' => 'de.systopia.donrec')), 'copy' => ts('copy', array('domain' => 'de.systopia.donrec')), 'withdrawn' => ts('withdrawn', array('domain' => 'de.systopia.donrec')), 'withdrawn_copy' => ts('withdrawn_copy', array('domain' => 'de.systopia.donrec'))));
        }
        $status_id = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'type');
        if ($status_id) {
            $form->add('select', "custom_{$status_id}", ts('Type', array('domain' => 'de.systopia.donrec')), array('' => ts('- any -', array('domain' => 'de.systopia.donrec')), 'single' => ts('single receipt', array('domain' => 'de.systopia.donrec')), 'bulk' => ts('bulk receipt', array('domain' => 'de.systopia.donrec'))));
        }
        $status_id = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'issued_in');
        if ($status_id) {
            $form->add('text', "custom_{$status_id}", ts('Receipt ID', array('domain' => 'de.systopia.donrec')));
        }
        $status_id = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'issued_by');
        if ($status_id) {
            $form->add('text', "custom_{$status_id}", ts('Issued by contact', array('domain' => 'de.systopia.donrec')));
        }
    } elseif ($formName == 'CRM_Contact_Form_Search_Advanced') {
        // remove unwanted fields
        $item_fields = CRM_Donrec_Logic_Receipt::getCustomFields();
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'issued_on');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'original_file');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'contact_type');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'gender');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'prefix');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'display_name');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'postal_greeting_display');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'email_greeting_display');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'addressee_display');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'street_address');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'supplemental_address_1');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'supplemental_address_2');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'supplemental_address_3');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'postal_code');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'city');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'country');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'shipping_addressee_display');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'shipping_street_address');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'shipping_supplemental_address_1');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'shipping_supplemental_address_2');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'shipping_supplemental_address_3');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'shipping_postal_code');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'shipping_city');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'shipping_country');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'date_from');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'date_to');
        // remove unwanted fields from receipt items (in contribution tab)
        $item_fields_receipt = CRM_Donrec_Logic_ReceiptItem::getCustomFields();
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields_receipt, 'financial_type_id');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields_receipt, 'total_amount');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields_receipt, 'non_deductible_amount');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields_receipt, 'currency');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields_receipt, 'contribution_hash');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields_receipt, 'issued_on');
        $field_ids_to_remove[] = CRM_Utils_DonrecHelper::getFieldID($item_fields_receipt, 'receive_date');
        $form->assign('field_ids_to_remove', implode(',', $field_ids_to_remove));
        CRM_Core_Region::instance('page-body')->add(array('template' => 'CRM/Donrec/Form/Search/RemoveFields.snippet.tpl'));
        // DISABLED: date field search doesn't work
        //CRM_Utils_DonrecHelper::relabelDateField($form, $item_fields, 'issued_on', ts("Issed On - From", array('domain' => 'de.systopia.donrec')), ts("Issed On - To", array('domain' => 'de.systopia.donrec')));
        // override the standard fields
        $status_id = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'status');
        if ($status_id) {
            $form->add('select', "custom_{$status_id}", ts('Status', array('domain' => 'de.systopia.donrec')), array('' => ts('- any -', array('domain' => 'de.systopia.donrec')), 'original' => ts('original', array('domain' => 'de.systopia.donrec')), 'copy' => ts('copy', array('domain' => 'de.systopia.donrec')), 'withdrawn' => ts('withdrawn', array('domain' => 'de.systopia.donrec')), 'withdrawn_copy' => ts('withdrawn_copy', array('domain' => 'de.systopia.donrec'))));
        }
        $status_id = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'type');
        if ($status_id) {
            $form->add('select', "custom_{$status_id}", ts('Type', array('domain' => 'de.systopia.donrec')), array('' => ts('- any -', array('domain' => 'de.systopia.donrec')), 'single' => ts('single receipt', array('domain' => 'de.systopia.donrec')), 'bulk' => ts('bulk receipt', array('domain' => 'de.systopia.donrec'))));
        }
        $status_id = CRM_Utils_DonrecHelper::getFieldID($item_fields, 'issued_by');
        if ($status_id) {
            $form->add('text', "custom_{$status_id}", ts('Issued by contact', array('domain' => 'de.systopia.donrec')));
        }
        // override the receipt_item standard fields
        $status_id = CRM_Utils_DonrecHelper::getFieldID($item_fields_receipt, 'status');
        if ($status_id) {
            $form->add('select', "custom_{$status_id}", ts('Status', array('domain' => 'de.systopia.donrec')), array('' => ts('- any -', array('domain' => 'de.systopia.donrec')), 'original' => ts('original', array('domain' => 'de.systopia.donrec')), 'copy' => ts('copy', array('domain' => 'de.systopia.donrec')), 'withdrawn' => ts('withdrawn', array('domain' => 'de.systopia.donrec')), 'withdrawn_copy' => ts('withdrawn_copy', array('domain' => 'de.systopia.donrec'))));
        }
        $status_id = CRM_Utils_DonrecHelper::getFieldID($item_fields_receipt, 'type');
        if ($status_id) {
            $form->add('select', "custom_{$status_id}", ts('Type', array('domain' => 'de.systopia.donrec')), array('' => ts('- any -', array('domain' => 'de.systopia.donrec')), 'single' => ts('single receipt', array('domain' => 'de.systopia.donrec')), 'bulk' => ts('bulk receipt', array('domain' => 'de.systopia.donrec'))));
        }
        $status_id = CRM_Utils_DonrecHelper::getFieldID($item_fields_receipt, 'issued_in');
        if ($status_id) {
            $form->add('text', "custom_{$status_id}", ts('Receipt ID', array('domain' => 'de.systopia.donrec')));
        }
        $status_id = CRM_Utils_DonrecHelper::getFieldID($item_fields_receipt, 'issued_by');
        if ($status_id) {
            $form->add('text', "custom_{$status_id}", ts('Issued by contact', array('domain' => 'de.systopia.donrec')));
        }
    }
}
Пример #6
0
 public static function addDynamicTokens(&$values)
 {
     if (!empty($values['issued_by'])) {
         // add created_by_display_name
         try {
             $creator = civicrm_api3('Contact', 'getsingle', array('id' => $values['issued_by']));
             $values['issued_by_display_name'] = $creator['display_name'];
         } catch (Exception $e) {
             CRM_Core_Error::debug_log_message('de.systopia.donrec - ' . print_r($e, 1));
         }
     }
     // add the legacy 'today' token
     if (!empty($values['issued_on'])) {
         $values['today'] = $values['issued_on'];
     }
     // add the monetary tokens: 'total', 'totaltext', 'totalmoney'
     if (isset($values['total_amount'])) {
         // format total_amount
         $values['total_amount'] = number_format((double) $values['total_amount'], 2, '.', '');
         $values['total'] = $values['total_amount'];
         $values['totaltext'] = CRM_Utils_DonrecHelper::convert_number_to_words($values['total_amount']);
         $values['totalmoney'] = CRM_Utils_Money::format($values['total_amount'], '');
     }
     // add financial type name
     $financialTypes = CRM_Contribute_PseudoConstant::financialType();
     if (is_array($values['lines'])) {
         foreach ($values['lines'] as $key => $line) {
             if (!empty($line['financial_type_id'])) {
                 $values['lines'][$key]['financial_type'] = $financialTypes[$line['financial_type_id']];
             }
         }
     }
     // sort contribution lines by receive date (#1497)
     $receive_dates = array();
     $sorted_lines = $values['lines'];
     foreach ($sorted_lines as $key => $line) {
         $sorted_lines[$key]['id'] = $key;
         $receive_dates[$key] = $line['receive_date'];
     }
     array_multisort($receive_dates, SORT_ASC, $sorted_lines);
     $values['lines'] = array();
     foreach ($sorted_lines as $key => $line) {
         $values['lines'][$line['id']] = $line;
     }
     // add legacy 'items'
     if (count($values['lines']) > 1) {
         $values['items'] = $values['lines'];
     }
     // add organisation address
     if (empty($values['organisation'])) {
         $domain = CRM_Core_BAO_Domain::getDomain();
         $values['organisation'] = self::lookupAddressTokens($domain->contact_id, 0, 0);
     }
     // ADD watermarks
     $profile = CRM_Donrec_Logic_Profile::getProfile($values['profile']);
     if ($values['status'] == 'ORIGINAL') {
         // nothing to to in this case..
     } elseif ($values['status'] == 'COPY') {
         $values['watermark'] = $profile->get('copy_text');
     } else {
         // in all other cases, it's INVALID/DRAFT:
         $values['watermark'] = $profile->get('draft_text');
     }
     // copy contributor values to addressee, if not set separately
     if (!isset($values['addressee']['display_name'])) {
         $values['addressee']['display_name'] = $values['contributor']['display_name'];
     }
     if (!isset($values['addressee']['addressee_display'])) {
         $values['addressee']['addressee_display'] = $values['contributor']['addressee_display'];
     }
     // add URL to view original file, if it exists
     if (!empty($values['original_file'])) {
         $values['view_url'] = CRM_Donrec_Logic_File::getPermanentURL($values['original_file'], $values['contributor']['id']);
     }
     // TODO: call Token hooks? Currently done by PDF generator
 }
Пример #7
0
 /**
  * execute the next step of a donation receipt run
  *
  * @return array of stats:
  */
 public function nextStep()
 {
     // some containers
     $exporter_results = array();
     $files = array();
     $profile = $this->snapshot->getProfile();
     // Synchronize this step
     $lock = CRM_Utils_DonrecHelper::getLock('CRM_Donrec_Logic_Engine', 'nextStep');
     if (!$lock->isAcquired()) {
         // lock timed out
         CRM_Core_Error::debug_log_message("de.systopia.donrec - couldn't acquire lock. Timeout is " . $lock->_timeout);
         // compile and return "state of affairs" report
         $stats = $this->createStats();
         $stats['log'] = array();
         $stats['files'] = $files;
         $stats['chunk_size'] = 0;
         CRM_Donrec_Logic_Exporter::addLogEntry($stats, "Couldn't acquire lock. Parallel processing denied. Lock timeout is {$lock->_timeout}s.");
         return $stats;
     }
     // check status
     $is_bulk = !empty($this->parameters['bulk']);
     $is_test = !empty($this->parameters['test']);
     // initialize stuff
     $chunk = $this->snapshot->getNextChunk($is_bulk, $is_test);
     $exporters = $this->getExporters();
     // loop over receipts
     foreach ($chunk as $chunk_id => $chunk_items) {
         // Setup some parameters
         //**********************************
         // Prepare chunk_items:
         // #FIXME: It is more convenient to have a simalar array-structure for bulk-
         // and single-processing. In future the getNextChunk-method might be
         // refactored and build up the arrays correspondingly.
         $chunk_items = $is_bulk ? $chunk_items : array($chunk_items);
         $contact_id = $chunk_items[0]['contact_id'];
         $line_ids = array();
         foreach ($chunk_items as $chunk_item) {
             $line_ids[] = $chunk_item['id'];
         }
         // create a SnapshotReceipt
         $snapshot_receipt = $this->snapshot->getSnapshotReceipt($line_ids, $is_test);
         // call exporters
         //**********************************
         foreach ($exporters as $exporter) {
             $exporter_id = $exporter->getID();
             if ($is_bulk) {
                 $result = $exporter->exportBulk($snapshot_receipt, $is_test);
             } else {
                 $result = $exporter->exportSingle($snapshot_receipt, $is_test);
             }
             if (!isset($exporter_results[$exporter_id])) {
                 $exporter_results[$exporter_id] = array();
                 $exporter_results[$exporter_id]['success'] = 0;
                 $exporter_results[$exporter_id]['failure'] = 0;
             }
             if ($result) {
                 $exporter_results[$exporter_id]['success']++;
             } else {
                 $exporter_results[$exporter_id]['failure']++;
             }
         }
         // save original pdfs and create receipt for non-test-runs
         //**********************************
         if (!$is_test) {
             $receipt_params = array();
             $receipt_params['type'] = $is_bulk ? 'BULK' : 'SINGLE';
             if ($profile->saveOriginalPDF()) {
                 $pdf_file = $this->getPDF($line_ids);
                 $file = CRM_Donrec_Logic_File::createPermanentFile($pdf_file, basename($pdf_file), $contact_id);
                 if (!empty($file)) {
                     $receipt_params['original_file'] = $file['id'];
                 }
             }
             CRM_Donrec_Logic_Receipt::createFromSnapshotReceipt($snapshot_receipt, $receipt_params);
         }
     }
     // The last chunk is empty.
     // If it is the last do some wrap-up.
     // Otherwise mark the chunk as processed.
     //**********************************
     if (!$chunk) {
         foreach ($exporters as $exporter) {
             $result = $exporter->wrapUp($this->snapshot->getId(), $is_test, $is_bulk);
             if (!empty($result['download_name']) && !empty($result['download_url'])) {
                 $files[$exporter->getID()] = array($result['download_name'], $result['download_url']);
             }
         }
     } else {
         $this->snapshot->markChunkProcessed($chunk, $is_test, $is_bulk);
     }
     // compile stats
     //**********************************
     $stats = $this->createStats();
     // create log-messages
     foreach ($exporter_results as $exporter_id => $result) {
         $msg = sprintf('%s processed %d items - %d succeeded, %d failed', $exporter_id, count($chunk), $result['success'], $result['failure']);
         $type = $result['failure'] ? 'ERROR' : 'INFO';
         CRM_Donrec_Logic_Exporter::addLogEntry($stats, $msg, $type);
     }
     $stats['files'] = $files;
     if ($chunk == NULL) {
         $stats['progress'] = 100.0;
     } else {
         $stats['chunk_size'] = count($chunk);
     }
     // release our lock
     $lock->release();
     return $stats;
 }