function adjustAmount($mandate_id)
 {
     // check if we are allowed to...
     if (CRM_Sepa_Logic_Settings::getSetting('allow_mandate_modification')) {
         $adjusted_amount = (double) $_REQUEST['adjust_amount'];
         if ($adjusted_amount > 0) {
             if (CRM_Sepa_BAO_SEPAMandate::adjustAmount($mandate_id, $adjusted_amount)) {
                 CRM_Core_Session::setStatus(sprintf(ts("The amount of this mandate was modified. You should send out a new prenotification to the debtor.")), ts('Advice'), 'info');
             }
         } else {
             CRM_Core_Session::setStatus(sprintf(ts("Invalid amount. Mandate not modified.")), ts('Error'), 'error');
         }
     } else {
         CRM_Core_Session::setStatus(sprintf(ts("Modifying an existing mandate is currently not allowed. You can change this on the SEPA settings page.")), ts('Error'), 'error');
     }
 }
 /**
  * gracefully terminates RCUR mandates
  * 
  * @return success as boolean
  * @author endres -at- systopia.de 
  */
 static function terminateMandate($mandate_id, $new_end_date_str, $cancel_reason = NULL)
 {
     $contribution_id_pending = CRM_Core_OptionGroup::getValue('contribution_status', 'Pending', 'name');
     // use a lock, in case somebody is batching just now
     $lock = CRM_Sepa_Logic_Settings::getLock();
     if (empty($lock)) {
         CRM_Core_Session::setStatus(sprintf(ts("Cannot terminate mandate [%s], batching in progress!"), $mandate_id), ts('Error'), 'error');
         return FALSE;
     }
     // first, load the mandate
     $mandate = civicrm_api("SepaMandate", "getsingle", array('id' => $mandate_id, 'version' => 3));
     if (isset($mandate['is_error'])) {
         CRM_Core_Session::setStatus(sprintf(ts("Cannot read mandate [%s]. Error was: '%s'"), $mandate_id, $mandate['error_message']), ts('Error'), 'error');
         $lock->release();
         return FALSE;
     }
     // check the mandate type
     if ($mandate['type'] == "OOFF") {
         return CRM_Sepa_BAO_SEPAMandate::terminateOOFFMandate($mandate_id, $new_end_date_str, $cancel_reason, $mandate);
     } elseif ($mandate['type'] != "RCUR") {
         CRM_Core_Session::setStatus(ts("You can only modify the end date of recurring contribution mandates."), ts('Error'), 'error');
         $lock->release();
         return FALSE;
     }
     // load the contribution
     $contribution_id = $mandate['entity_id'];
     $contribution = civicrm_api('ContributionRecur', "getsingle", array('id' => $contribution_id, 'version' => 3));
     if (isset($contribution['is_error']) && $contribution['is_error']) {
         CRM_Core_Session::setStatus(sprintf(ts("Cannot read contribution [%s]. Error was: '%s'"), $contribution_id, $contribution['error_message']), ts('Error'), 'error');
         $lock->release();
         return FALSE;
     }
     // check the date
     $today = strtotime("today");
     $new_end_date = strtotime($new_end_date_str);
     if ($new_end_date < $today) {
         CRM_Core_Session::setStatus(sprintf(ts("You cannot set an end date in the past."), $contribution_id, $contribution['error_message']), ts('Error'), 'error');
         $lock->release();
         return FALSE;
     }
     // actually set the date
     $query = array('version' => 3, 'id' => $contribution_id, 'currency' => 'EUR', 'end_date' => date('YmdHis', $new_end_date));
     if ($cancel_reason) {
         // FIXME: cancel_reason does not exist in contribution_recur!!
         //$query['cancel_reason'] = $cancel_reason;
         $query['cancel_date'] = $query['end_date'];
     }
     $result = civicrm_api("ContributionRecur", "create", $query);
     if (isset($result['is_error']) && $result['is_error']) {
         CRM_Core_Session::setStatus(sprintf(ts("Cannot modify recurring contribution [%s]. Error was: '%s'"), $contribution_id, $result['error_message']), ts('Error'), 'error');
         $lock->release();
         return FALSE;
     }
     // set the cancel reason
     if ($cancel_reason) {
         // ..and create a note, since the contribution_recur does not have cancel_reason
         $note_result = civicrm_api("Note", "create", array('version' => 3, 'entity_table' => 'civicrm_contribution_recur', 'entity_id' => $contribution_id, 'modified_date' => date('YmdHis'), 'subject' => 'cancel_reason', 'note' => $cancel_reason, 'privacy' => 0));
         if (isset($note_result['is_error']) && $note_result['is_error']) {
             CRM_Core_Session::setStatus(sprintf(ts("Cannot set cancel reason for mandate [%s]. Error was: '%s'"), $mandate_id, $note_result['error_message']), ts('Error'), 'warn');
         }
     }
     // find already created contributions that are now obsolete...
     $obsolete_ids = array();
     $deleted_ids = array();
     $obsolete_query = "\n    SELECT id\n    FROM civicrm_contribution\n    WHERE receive_date > '{$new_end_date_str}'\n      AND contribution_recur_id = {$contribution_id}\n      AND contribution_status_id = {$contribution_id_pending};";
     $obsolete_ids_query = CRM_Core_DAO::executeQuery($obsolete_query);
     while ($obsolete_ids_query->fetch()) {
         array_push($obsolete_ids, $obsolete_ids_query->id);
     }
     // ...and delete them:
     foreach ($obsolete_ids as $obsolete_id) {
         $delete_result = civicrm_api("Contribution", "delete", array('id' => $obsolete_id, 'version' => 3));
         if (isset($delete_result['is_error']) && $delete_result['is_error']) {
             CRM_Core_Session::setStatus(sprintf(ts("Cannot delete scheduled contribution [%s]. Error was: '%s'"), $obsolete_id, $delete_result['error_message']), ts('Error'), 'warn');
         } else {
             array_push($deleted_ids, $obsolete_id);
         }
     }
     if (count($deleted_ids)) {
         // also, remove them from the groups
         $deleted_ids_string = implode(',', $deleted_ids);
         CRM_Core_DAO::executeQuery("DELETE FROM civicrm_sdd_contribution_txgroup WHERE contribution_id IN ({$deleted_ids_string});");
     }
     // finally, let the API close the mandate if end_date is now
     if ($new_end_date <= $today) {
         $close_result = civicrm_api("SepaAlternativeBatching", "closeended", array('version' => 3));
         if (isset($close_result['is_error']) && $close_result['is_error']) {
             CRM_Core_Session::setStatus(sprintf(ts("Closing Mandate failed. Error was: '%s'"), $close_result['error_message']), ts('Error'), 'warn');
         }
     }
     CRM_Core_Session::setStatus(ts("New end date set."), ts('Mandate updated.'), 'info');
     CRM_Core_Session::setStatus(ts("Please note, that any <i>closed</i> batches that include this mandate cannot be changed any more - all pending contributions will still be executed."), ts('Mandate updated.'), 'warn');
     if (count($deleted_ids)) {
         CRM_Core_Session::setStatus(sprintf(ts("Successfully deleted %d now obsolete contributions."), count($deleted_ids)), ts('Mandate updated.'), 'info');
     }
     $lock->release();
     return TRUE;
 }
 /**
  * Creates a SEPA mandate for the given type
  */
 function createMandate($type)
 {
     // first create a contribution
     $payment_instrument_id = CRM_Core_OptionGroup::getValue('payment_instrument', $type, 'name');
     $contribution_status_id = CRM_Core_OptionGroup::getValue('contribution_status', 'Pending', 'name');
     $contribution_data = array('version' => 3, 'contact_id' => $_REQUEST['contact_id'], 'campaign_id' => $_REQUEST['campaign_id'], 'financial_type_id' => $_REQUEST['financial_type_id'], 'payment_instrument_id' => $payment_instrument_id, 'contribution_status_id' => $contribution_status_id, 'currency' => 'EUR');
     if ($type == 'OOFF') {
         $initial_status = 'OOFF';
         $entity_table = 'civicrm_contribution';
         $contribution_data['total_amount'] = number_format($_REQUEST['total_amount'], 2, '.', '');
         $contribution_data['receive_date'] = $_REQUEST['date'];
         $contribution_data['source'] = $_REQUEST['source'];
         $contribution = civicrm_api('Contribution', 'create', $contribution_data);
     } else {
         if ($type == 'RCUR') {
             $initial_status = 'FRST';
             $entity_table = 'civicrm_contribution_recur';
             $contribution_data['amount'] = number_format($_REQUEST['total_amount'], 2, '.', '');
             $contribution_data['start_date'] = $_REQUEST['start_date'];
             $contribution_data['end_date'] = $_REQUEST['end_date'];
             $contribution_data['create_date'] = date('YmdHis');
             $contribution_data['modified_date'] = date('YmdHis');
             $contribution_data['frequency_unit'] = 'month';
             $contribution_data['frequency_interval'] = $_REQUEST['interval'];
             $contribution_data['cycle_day'] = $_REQUEST['cycle_day'];
             $contribution_data['is_email_receipt'] = 0;
             $contribution = civicrm_api('ContributionRecur', 'create', $contribution_data);
         }
     }
     if (isset($contribution['is_error']) && $contribution['is_error']) {
         $this->processError(sprintf(ts("Couldn't create contribution for contact #%s"), $_REQUEST['contact_id']), ts("Couldn't create contribution"), $contribution['error_message'], $_REQUEST['contact_id']);
         return;
     }
     // create a note, if requested
     if ($_REQUEST['note']) {
         // add note
         $create_note = array('version' => 3, 'entity_table' => $entity_table, 'entity_id' => $contribution['id'], 'note' => $_REQUEST['note'], 'privacy' => 0);
         $create_note_result = civicrm_api('Note', 'create', $create_note);
         if (isset($create_note_result['is_error']) && $create_note_result['is_error']) {
             // don't consider this a fatal error...
             CRM_Core_Session::setStatus(sprintf(ts("Couldn't create note for contribution #%s"), $contribution['id']), ts('Error'), 'alert');
             error_log("org.project60.sepa_dd: error creating note - " . $create_note_result['error_message']);
         }
     }
     // next, create mandate
     $mandate_data = array('version' => 3, 'debug' => 1, 'contact_id' => $_REQUEST['contact_id'], 'source' => $_REQUEST['source'], 'entity_table' => $entity_table, 'entity_id' => $contribution['id'], 'creation_date' => date('YmdHis'), 'validation_date' => date('YmdHis'), 'date' => date('YmdHis'), 'iban' => $_REQUEST['iban'], 'bic' => $_REQUEST['bic'], 'reference' => $_REQUEST['reference'], 'status' => $initial_status, 'type' => $type, 'creditor_id' => $_REQUEST['creditor_id'], 'is_enabled' => 1);
     // call the hook for mandate generation
     $mandate = civicrm_api('SepaMandate', 'create', $mandate_data);
     if (isset($mandate['is_error']) && $mandate['is_error']) {
         $this->processError(sprintf(ts("Couldn't create %s mandate for contact #%s"), $type, $_REQUEST['contact_id']), ts("Couldn't create mandate"), $mandate['error_message'], $_REQUEST['contact_id']);
         return;
     }
     // if we want to replace an old mandate:
     if (isset($_REQUEST['replace'])) {
         CRM_Sepa_BAO_SEPAMandate::terminateMandate($_REQUEST['replace'], $_REQUEST['replace_date'], $_REQUEST['replace_reason']);
     }
     // if we get here, everything went o.k.
     $reference = $mandate['values'][$mandate['id']]['reference'];
     $mandate_url = CRM_Utils_System::url('civicrm/sepa/xmandate', "mid={$mandate['id']}");
     CRM_Core_Session::setStatus(ts("'%3' SEPA Mandate <a href=\"%2\">%1</a> created.", array(1 => $reference, 2 => $mandate_url, 3 => $type)), ts("Success"), 'info');
     if (!$this->isPopup()) {
         $contact_url = CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$contribution_data['contact_id']}&selectedChild=contribute");
         CRM_Utils_System::redirect($contact_url);
     }
 }
 /**
  * Test CRM_Sepa_BAO_SEPAMandate::add()
  *
  * @author niko bochan
  */
 public function testCreateUsingBAO()
 {
     // create a new contact
     $contactId = $this->individualCreate();
     // create a recurring contribution
     $txmd5 = md5(date("YmdHis" . rand(1, 100)));
     $txref = "SDD-TEST-RCUR-" . $txmd5;
     $cparams = array('contact_id' => $contactId, 'frequency_interval' => '1', 'frequency_unit' => 'month', 'amount' => 123.42, 'contribution_status_id' => 1, 'start_date' => date("Ymd") . "000000", 'currency' => "EUR", 'trxn_id' => $txref);
     $contrib = $this->callAPISuccess("contribution_recur", "create", $cparams);
     $contrib = $contrib["values"][$contrib["id"]];
     // mandate parameters array
     $params = array();
     $params['status'] = "FRST";
     $params['is_enabled'] = 1;
     $params['version'] = 3;
     $params['debug'] = 1;
     $params['contact_id'] = $contactId;
     $params['source'] = "TestSource";
     $params['entity_table'] = "civicrm_contribution_recur";
     $params['entity_id'] = $contrib;
     $params['creation_date'] = "20140722092142";
     $params['validation_date'] = "20140722092142";
     $params['date'] = "20140722092142";
     $params['iban'] = "BE68844010370034";
     $params['bic'] = "TESTTEST";
     $params['type'] = "RCUR";
     $params['creditor_id'] = $this->getCreditor();
     $dao = CRM_Sepa_BAO_SEPAMandate::add($params);
     // close the mandate
     CRM_Sepa_BAO_SEPAMandate::terminateMandate($dao->id, date("Y-m-d"), "Test");
     // get the mandate via API and test it against the parameters array
     $mdtest = $this->callAPISuccess("SepaMandate", "get", array("entity_id" => $dao->id));
     $mdtest = $mdtest["values"][$mdtest["id"]];
     foreach ($params as $key => $value) {
         $this->assertEquals($params[$key], $value);
     }
 }