/**
  * Handle the different actions, should probably be handles at base class level ...
  * 
  * @param type $match
  * @param type $btx
  */
 public function execute($suggestion, $btx)
 {
     if ($suggestion->getId() === "manual") {
         $cids = $suggestion->getParameter('contribution_ids');
         $contribution_count = 0;
         if ($cids) {
             $completed_status = banking_helper_optionvalue_by_groupname_and_name('contribution_status', 'Completed');
             $cancelled_status = banking_helper_optionvalue_by_groupname_and_name('contribution_status', 'Cancelled');
             foreach ($cids as $cid) {
                 if ($cid) {
                     $contribution = civicrm_api('Contribution', 'getsingle', array('version' => 3, 'id' => $cid));
                     if (!empty($contribution['is_error'])) {
                         CRM_Core_Session::setStatus(sprintf(ts("Couldn't find contribution #%s"), $cid), ts('Error'), 'error');
                         continue;
                     }
                     // save the account
                     if (!empty($contribution['contact_id'])) {
                         $this->storeAccountWithContact($btx, $contribution['contact_id']);
                     }
                     $query = array('version' => 3, 'id' => $cid);
                     $query['is_test'] = 0;
                     $query = array_merge($query, $this->getPropagationSet($btx, $suggestion, 'contribution'));
                     // add propagated values
                     // set status to completed, unless it's a negative amount...
                     if ($btx->amount < 0) {
                         // ...in this case, we want to cancel this
                         $query['contribution_status_id'] = $cancelled_status;
                         $query['cancel_date'] = date('YmdHis', strtotime($btx->booking_date));
                     } else {
                         // ...otherwise, we close it
                         $query['contribution_status_id'] = $completed_status;
                         $query['receive_date'] = date('YmdHis', strtotime($btx->booking_date));
                     }
                     $result = civicrm_api('Contribution', 'create', $query);
                     if (isset($result['is_error']) && $result['is_error']) {
                         CRM_Core_Session::setStatus(sprintf(ts("Couldn't modify contribution #%s"), $cid), ts('Error'), 'error');
                     } else {
                         $contribution_count += 1;
                     }
                 }
             }
             if ($contribution_count > 0) {
                 $newStatus = banking_helper_optionvalueid_by_groupname_and_name('civicrm_banking.bank_tx_status', 'Processed');
                 $btx->setStatus($newStatus);
                 parent::execute($suggestion, $btx);
             } else {
                 CRM_Core_Session::setStatus(ts("The contribution is not valid. The transaction is NOT completed."), ts('Transaction NOT completed.'), 'alert');
             }
         } else {
             CRM_Core_Session::setStatus(ts("No contribution given. The transaction is NOT completed."), ts('Transaction NOT completed.'), 'alert');
         }
     } else {
         // this is the IGNORE action. Simply set the status to ignored
         $newStatus = banking_helper_optionvalueid_by_groupname_and_name('civicrm_banking.bank_tx_status', 'Ignored');
         $btx->setStatus($newStatus);
         parent::execute($suggestion, $btx);
     }
 }
 /**
  * Handle the different actions, should probably be handles at base class level ...
  * 
  * @param type $match
  * @param type $btx
  */
 public function execute($suggestion, $btx)
 {
     // this is the IGNORE action. Simply set the status to ignored
     $newStatus = banking_helper_optionvalueid_by_groupname_and_name('civicrm_banking.bank_tx_status', 'Ignored');
     $btx->setStatus($newStatus);
     parent::execute($suggestion, $btx);
     return true;
 }
 /**
  * Handle the different actions, should probably be handles at base class level ...
  * 
  * @param type $match
  * @param type $btx
  */
 public function execute($suggestion, $btx)
 {
     $config = $this->_plugin_config;
     $smarty_vars = array();
     // load the recurring contribution
     $rcontribution_id = $suggestion->getParameter('recurring_contribution_id');
     $rcontribution = civicrm_api3('ContributionRecur', 'getsingle', array('id' => $rcontribution_id));
     $last_contribution = NULL;
     $due_date = self::getExpectedDate($rcontribution, $btx, $config->recurring_mode, $last_contribution);
     if ($due_date) {
         $current_due_date = date('Y-m-d', $due_date);
     } else {
         $current_due_date = ts('None');
     }
     $recorded_due_date = $suggestion->getParameter('expected_date');
     if ($recorded_due_date != $current_due_date) {
         // something changed...
         CRM_Core_Session::setStatus(ts('The situation for the recurring contribution seems to have changed. Please analyse transaction again.'), ts('Recurring contributtion changed'), 'alert');
         return false;
     }
     // go ahead and create the contribution
     $contribution = array();
     $contribution['contact_id'] = $suggestion->getParameter('contact_id');
     $contribution['total_amount'] = $btx->amount;
     $contribution['receive_date'] = $btx->booking_date;
     $contribution['currency'] = $btx->currency;
     $contribution['financial_type_id'] = CRM_Utils_Array::value('financial_type_id', $rcontribution);
     $contribution['payment_instrument_id'] = CRM_Utils_Array::value('payment_instrument_id', $rcontribution);
     $contribution['campaign_id'] = CRM_Utils_Array::value('campaign_id', $rcontribution);
     $contribution['contribution_recur_id'] = $rcontribution_id;
     $contribution['contribution_status_id'] = banking_helper_optionvalue_by_groupname_and_name('contribution_status', $config->created_contribution_status);
     $contribution = array_merge($contribution, $this->getPropagationSet($btx, $suggestion, 'contribution'));
     $contribution['version'] = 3;
     $result = civicrm_api('Contribution', 'create', $contribution);
     if (isset($result['is_error']) && $result['is_error']) {
         CRM_Core_Session::setStatus(ts("Couldn't create contribution.") . "<br/>" . ts("Error was: ") . $result['error_message'], ts('Error'), 'error');
         return false;
     }
     // success!
     $suggestion->setParameter('contribution_id', $result['id']);
     // save the account
     $this->storeAccountWithContact($btx, $suggestion->getParameter('contact_id'));
     $newStatus = banking_helper_optionvalueid_by_groupname_and_name('civicrm_banking.bank_tx_status', 'Processed');
     $btx->setStatus($newStatus);
     parent::execute($suggestion, $btx);
     return true;
 }
 /**
  * Handle the different actions, should probably be handles at base class level ...
  * 
  * @param type $match
  * @param type $btx
  */
 public function execute($suggestion, $btx)
 {
     // create contribution
     $query = $this->get_contribution_data($btx, $suggestion, $suggestion->getParameter('contact_id'));
     $query['version'] = 3;
     $result = civicrm_api('Contribution', 'create', $query);
     if (isset($result['is_error']) && $result['is_error']) {
         CRM_Core_Session::setStatus(ts("Couldn't create contribution.") . "<br/>" . ts("Error was: ") . $result['error_message'], ts('Error'), 'error');
         return true;
     }
     $suggestion->setParameter('contribution_id', $result['id']);
     // save the account
     $this->storeAccountWithContact($btx, $suggestion->getParameter('contact_id'));
     // wrap it up
     $newStatus = banking_helper_optionvalueid_by_groupname_and_name('civicrm_banking.bank_tx_status', 'Processed');
     $btx->setStatus($newStatus);
     parent::execute($suggestion, $btx);
     return true;
 }
 /**
  * Handle the different actions, should probably be handles at base class level ...
  * 
  * @param type $match
  * @param type $btx
  */
 public function execute($suggestion, $btx)
 {
     $membership_id = $suggestion->getParameter('membership_id');
     $membership = civicrm_api3('Membership', 'getsingle', array('id' => $membership_id));
     $membership_type = civicrm_api3('MembershipType', 'getsingle', array('id' => $membership['membership_type_id']));
     // TODO: verify validity of suggestion (is outdated?)
     // 1. create contribution
     $contribution_parameters = array('contact_id' => $membership['contact_id'], 'total_amount' => $btx->amount, 'currency' => $btx->currency, 'receive_date' => $btx->value_date, 'financial_type_id' => $this->getMembershipOption($membership_type['id'], 'financial_type_id', $membership_type['financial_type_id']), 'version' => 3);
     $contribution_parameters = array_merge($contribution_parameters, $this->getPropagationSet($btx, $suggestion, 'contribution'));
     $contribution = civicrm_api('Contribution', 'create', $contribution_parameters);
     if (!empty($contribution['is_error'])) {
         CRM_Core_Session::setStatus(ts("Couldn't create contribution.") . "<br/>" . ts("Error was: ") . $contribution['error_message'], ts('Error'), 'error');
         return true;
     }
     // 2. connect to membership
     civicrm_api3('MembershipPayment', 'create', array('membership_id' => $membership_id, 'contribution_id' => $contribution['id']));
     // wrap it up
     $suggestion->setParameter('contact_id', $membership['contact_id']);
     $suggestion->setParameter('contribution_id', $contribution['id']);
     $this->storeAccountWithContact($btx, $membership['contact_id']);
     $newStatus = banking_helper_optionvalueid_by_groupname_and_name('civicrm_banking.bank_tx_status', 'Processed');
     $btx->setStatus($newStatus);
     parent::execute($suggestion, $btx);
     return true;
 }
 /**
  * class constructor
  */
 function __construct($config_name)
 {
     parent::__construct($config_name);
 }
 /**
  * Handle the different actions, should probably be handles at base class level ...
  * 
  * @param type $match
  * @param type $btx
  */
 public function execute($suggestion, $btx)
 {
     $config = $this->_plugin_config;
     $contribution_id = $suggestion->getParameter('contribution_id');
     $query = array('version' => 3, 'id' => $contribution_id);
     $query = array_merge($query, $this->getPropagationSet($btx, $suggestion, 'contribution'));
     // add propagated values
     // double check contribution (see https://github.com/Project60/CiviBanking/issues/61)
     $contribution = civicrm_api('Contribution', 'getsingle', array('id' => $contribution_id, 'version' => 3));
     if (!empty($contribution['is_error'])) {
         CRM_Core_Session::setStatus(ts('Contribution has disappeared.') . ' ' . ts('Error was:') . ' ' . $contribution['error_message'], ts('Execution Failure'), 'alert');
         return false;
     }
     $accepted_status_ids = $this->getAcceptedContributionStatusIDs();
     if (!in_array($contribution['contribution_status_id'], $accepted_status_ids)) {
         CRM_Core_Session::setStatus(ts('Contribution status has been modified.'), ts('Execution Failure'), 'alert');
         return false;
     }
     // depending on mode...
     if ($this->_plugin_config->mode != "cancellation") {
         $query['contribution_status_id'] = banking_helper_optionvalue_by_groupname_and_name('contribution_status', 'Completed');
         $query['receive_date'] = date('YmdHis', strtotime($btx->booking_date));
     } else {
         $query['contribution_status_id'] = banking_helper_optionvalue_by_groupname_and_name('contribution_status', 'Cancelled');
         $query['cancel_date'] = date('YmdHis', strtotime($btx->booking_date));
         if ($config->cancellation_cancel_reason) {
             $query['cancel_reason'] = $suggestion->getParameter('cancel_reason');
         }
     }
     $result = civicrm_api('Contribution', 'create', $query);
     if (isset($result['is_error']) && $result['is_error']) {
         CRM_Core_Session::setStatus(ts("Couldn't modify contribution.") . "<br/>" . $result['error_message'], ts('Error'), 'error');
         return false;
     } else {
         // everything seems fine, save the account
         if (!empty($result['values'][$contribution_id]['contact_id'])) {
             $this->storeAccountWithContact($btx, $result['values'][$contribution_id]['contact_id']);
         } elseif (!empty($result['values'][0]['contact_id'])) {
             $this->storeAccountWithContact($btx, $result['values'][0]['contact_id']);
         }
     }
     $newStatus = banking_helper_optionvalueid_by_groupname_and_name('civicrm_banking.bank_tx_status', 'Processed');
     $btx->setStatus($newStatus);
     parent::execute($suggestion, $btx);
     return true;
 }
 /**
  * Run a single plugin to check for a match
  * 
  * @param type $plugin
  * @param type $btx
  * @param type $context
  */
 protected function matchPlugin(CRM_Banking_PluginModel_Matcher $plugin, CRM_Banking_Matcher_Context $context)
 {
     $btx = $context->btx;
     // match() returns an instance of CRM_Banking_Matcher_Suggestion
     $suggestions = $plugin->match($btx, $context);
     if ($suggestions !== null) {
         // handle the possibility to get multiple matches in return
         if (!is_array($suggestions)) {
             $suggestions = array($suggestions->probability => $suggestions);
         }
     }
     return true;
 }
 /**
  * Handle the different actions, should probably be handles at base class level ...
  * 
  * @param type $match
  * @param type $btx
  */
 public function executeCancellation($match, $btx)
 {
     $config = $this->_plugin_config;
     $contribution_id = $match->getParameter('contribution_id');
     $mandate_id = $match->getParameter('mandate_id');
     $status_cancelled = banking_helper_optionvalue_by_groupname_and_name('contribution_status', 'Cancelled');
     // set the status to 'Cancelled'
     $query = array('version' => 3, 'id' => $contribution_id);
     $query['contribution_status_id'] = $status_cancelled;
     $query['cancel_date'] = date('Ymdhis', strtotime($btx->value_date));
     $query = array_merge($query, $this->getPropagationSet($btx, $match, 'contribution', $config->cancellation_value_propagation));
     // add propagated values
     if (empty($query['cancel_reason'])) {
         // add default values
         $query['cancel_reason'] = $config->cancellation_default_reason;
     }
     if ($config->cancellation_cancel_reason) {
         $query['cancel_reason'] = $match->getParameter('cancel_reason');
     }
     $result = civicrm_api('Contribution', 'create', $query);
     if (isset($result['is_error']) && $result['is_error']) {
         error_log("org.project60.sepa: matcher_sepa: Couldn't modify contribution, error was: " . $result['error_message']);
         CRM_Core_Session::setStatus(ts("Couldn't modify contribution."), ts('Error'), 'error');
     } else {
         // now for the mandate...
         $contribution = civicrm_api('Contribution', 'getsingle', array('version' => 3, 'id' => $contribution_id));
         if (!empty($contribution['is_error'])) {
             error_log("org.project60.sepa: matcher_sepa: Couldn't load contribution, error was: " . $result['error_message']);
             CRM_Core_Session::setStatus(ts("Couldn't modify contribution."), ts('Error'), 'error');
         } else {
             if ('OOFF' == $contribution['contribution_payment_instrument'] && !empty($config->cancellation_update_mandate_status_OOFF)) {
                 // everything seems fine, adjust the mandate's status
                 $query = array('version' => 3, 'id' => $mandate_id);
                 $query['status'] = $config->cancellation_update_mandate_status_OOFF;
                 $query = array_merge($query, $this->getPropagationSet($btx, $match, 'mandate'));
                 // add propagated values
                 $result = civicrm_api('SepaMandate', 'create', $query);
                 if (!empty($result['is_error'])) {
                     error_log("org.project60.sepa: matcher_sepa: Couldn't modify mandate, error was: " . $result['error_message']);
                     CRM_Core_Session::setStatus(ts("Couldn't modify mandate."), ts('Error'), 'error');
                 }
             } elseif ('RCUR' == $contribution['contribution_payment_instrument'] && !empty($config->cancellation_update_mandate_status_RCUR)) {
                 // everything seems fine, adjust the mandate's status
                 $query = array('version' => 3, 'id' => $mandate_id);
                 $query['status'] = $config->cancellation_update_mandate_status_RCUR;
                 $query = array_merge($query, $this->getPropagationSet($btx, $match, 'mandate'));
                 // add propagated values
                 $result = civicrm_api('SepaMandate', 'create', $query);
                 if (!empty($result['is_error'])) {
                     error_log("org.project60.sepa: matcher_sepa: Couldn't modify mandate, error was: " . $result['error_message']);
                     CRM_Core_Session::setStatus(ts("Couldn't modify mandate."), ts('Error'), 'error');
                 }
             }
         }
     }
     // create activity if wanted
     if ($config->cancellation_create_activity) {
         // gather some information to put in the text
         $smarty_vars = array();
         $smarty_vars['contribution'] = $contribution;
         $smarty_vars['cancel_fee'] = $match->getParameter('cancel_fee');
         $smarty_vars['cancel_reason'] = $match->getParameter('cancel_reason');
         // load the mandate
         $mandate = civicrm_api('SepaMandate', 'getsingle', array('id' => $mandate_id, 'version' => 3));
         $smarty_vars['mandate'] = $mandate;
         // load the contact
         $contact = civicrm_api('Contact', 'getsingle', array('id' => $contribution['contact_id'], 'version' => 3));
         $smarty_vars['contact'] = $contact;
         // count the cancelled contributions connected to this mandate
         $cancelled_contribution_count = 0;
         $current_contribution_date = date('Ymdhis', strtotime($contribution['receive_date']));
         if ($mandate['type'] == 'RCUR') {
             $query = "SELECT contribution_status_id\n                  FROM civicrm_contribution\n                  WHERE contribution_recur_id = {$mandate['entity_id']}\n                    AND receive_date <= '{$current_contribution_date}'\n                  ORDER BY receive_date DESC;";
             $status_list = CRM_Core_DAO::executeQuery($query);
             while ($status_list->fetch()) {
                 if ($status_list->contribution_status_id == $status_cancelled) {
                     $cancelled_contribution_count += 1;
                 } else {
                     break;
                 }
             }
         }
         $smarty_vars['cancelled_contribution_count'] = $cancelled_contribution_count;
         // look up contact if not set
         $user_id = CRM_Core_Session::singleton()->get('userID');
         if (empty($config->cancellation_create_activity_assignee_id)) {
             $assignedTo = $user_id;
         } else {
             $assignedTo = (int) $config->cancellation_create_activity_assignee_id;
         }
         // compile the text
         $smarty = CRM_Banking_Helpers_Smarty::singleton();
         $smarty->pushScope($smarty_vars);
         if (empty($config->cancellation_create_activity_text)) {
             $details = $smarty->fetch('CRM/Banking/PluginImpl/Matcher/SepaMandate.activity.tpl');
         } else {
             $details = $smarty->fetch("string:" . $config->cancellation_create_activity_text);
         }
         $smarty->popScope();
         $activity_parameters = array('version' => 3, 'activity_type_id' => $config->cancellation_create_activity_type_id, 'subject' => $config->cancellation_create_activity_subject, 'status_id' => 1, 'activity_date_time' => date('YmdHis'), 'source_contact_id' => $user_id, 'target_contact_id' => $contact['id'], 'details' => $details);
         $activity = CRM_Activity_BAO_Activity::create($activity_parameters);
         $assignment_parameters = array('activity_id' => $activity->id, 'contact_id' => $assignedTo, 'record_type_id' => 1);
         $assignment = CRM_Activity_BAO_ActivityContact::create($assignment_parameters);
     }
     $newStatus = banking_helper_optionvalueid_by_groupname_and_name('civicrm_banking.bank_tx_status', 'Processed');
     $btx->setStatus($newStatus);
     parent::execute($match, $btx);
     return true;
 }
 /**
  * class constructor
  */
 function __construct($config_name)
 {
     parent::__construct($config_name);
     $this->parseConditions();
 }
 /**
  * Handle the different actions, should probably be handles at base class level ...
  * 
  * @param type $match
  * @param type $btx
  */
 public function execute($suggestion, $btx)
 {
     // load the batch
     $batch_id = $suggestion->getParameter('batch_id');
     $result = civicrm_api('Batch', 'getsingle', array('version' => 3, 'id' => $batch_id));
     if ($result['is_error']) {
         CRM_Core_Session::setStatus(sprintf(ts("Internal error! Cannot find batch %s"), $match->getParameter('batch_id')), ts('Error'), 'error');
     }
     if ($suggestion->getParameter('override_status') || !count($this->getNonPendingContributionIDs($batch_id))) {
         // all seems fine, lets set all these contributions to 'completed'
         $contribution_status_completed = banking_helper_optionvalue_by_groupname_and_name('contribution_status', 'Completed');
         // first, get all contributions:
         $contributionIDs = array();
         $query = "SELECT contribution.id as contribution_id FROM civicrm_entity_batch AS batch " . "INNER JOIN civicrm_entity_financial_trxn  AS trxn2c       ON batch.entity_id=trxn2c.financial_trxn_id AND batch.entity_table='civicrm_financial_trxn' " . "INNER JOIN civicrm_contribution           AS contribution ON trxn2c.entity_id=contribution.id AND trxn2c.entity_table='civicrm_contribution' " . "WHERE batch.batch_id = {$batch_id};";
         $result = CRM_Core_DAO::executeQuery($query);
         while ($result->fetch()) {
             array_push($contributionIDs, $result->contribution_id);
         }
         // now, set them all to completed:
         foreach ($contributionIDs as $contribution_id) {
             $result = civicrm_api('Contribution', 'create', array('version' => 3, 'id' => $contribution_id, 'contribution_status_id' => $contribution_status_completed, 'pay_later' => 0));
             if ($result['is_error']) {
                 CRM_Core_Session::setStatus(sprintf(ts("Internal error! Cannot complete contribution %s. Error message was: '%s'"), $contribution_id, $result['error_message']), ts('Error'), 'error');
             }
         }
         // update the batch
         $batch_status_received = banking_helper_optionvalue_by_groupname_and_name('batch_status', 'Received');
         $update_batch_query = array('version' => 3, 'id' => $batch_id, 'modified_date' => date('YmdHis'), 'status_id' => $batch_status_received);
         $result = civicrm_api('Batch', 'create', $update_batch_query);
         if ($result['is_error']) {
             CRM_Core_Session::setStatus(sprintf(ts("Internal error! Cannot find batch %s"), $match->getParameter('batch_id')), ts('Error'), 'error');
         }
         // notify the user
         CRM_Core_Session::setStatus(sprintf(ts("Completed all %d contributions."), count($contributionIDs)), ts('Batch completed'), 'info');
         // complete by setting the status to 'processed'
         $newStatus = banking_helper_optionvalueid_by_groupname_and_name('civicrm_banking.bank_tx_status', 'Processed');
         $btx->setStatus($newStatus);
         parent::execute($suggestion, $btx);
         return true;
     } else {
         // this means, there ARE contributions in a non-pending state, AND the override was not requested:
         CRM_Core_Session::setStatus(sprintf(ts("Some contribtions in batch %s are not in state 'pending', and override was not enabled. The payment was NOT processed!"), $batch_id), ts('Error'), 'error');
     }
     return false;
 }