コード例 #1
0
 /** 
  * Generate a set of suggestions for the given bank transaction
  * 
  * @return array(match structures)
  */
 public function match(CRM_Banking_BAO_BankTransaction $btx, CRM_Banking_Matcher_Context $context)
 {
     $config = $this->_plugin_config;
     $threshold = $this->getThreshold();
     $penalty = $this->getPenalty($btx);
     $data_parsed = $btx->getDataParsed();
     // first see if all the required values are there
     if (!$this->requiredValuesPresent($btx)) {
         return null;
     }
     // then look up potential contacts
     $contacts_found = $context->findContacts($threshold, $data_parsed['name'], $config->lookup_contact_by_name);
     // finally generate suggestions
     foreach ($contacts_found as $contact_id => $contact_probability) {
         $suggestion = new CRM_Banking_Matcher_Suggestion($this, $btx);
         $suggestion->setTitle(ts("Create a new contribution"));
         $suggestion->setId("create-{$contact_id}");
         $suggestion->setParameter('contact_id', $contact_id);
         // set probability manually, I think the automatic calculation provided by ->addEvidence might not be what we need here
         $contact_probability -= $penalty;
         if ($contact_probability >= $threshold) {
             $suggestion->setProbability($contact_probability);
             $btx->addSuggestion($suggestion);
         }
     }
     // that's it...
     return empty($this->_suggestions) ? null : $this->_suggestions;
 }
コード例 #2
0
 /** 
  * Generate a set of suggestions for the given bank transaction
  * 
  * @return array(match structures)
  */
 public function match(CRM_Banking_BAO_BankTransaction $btx, CRM_Banking_Matcher_Context $context)
 {
     $config = $this->_plugin_config;
     $threshold = $this->getThreshold();
     $data_parsed = $btx->getDataParsed();
     // find potential contacts
     $contacts_found = $context->findContacts($threshold, $data_parsed['name'], $config->lookup_contact_by_name);
     // with the identified contacts, look up matching memberships
     $memberships = $this->findMemberships($contacts_found, $btx, $context);
     // transform all memberships into suggestions
     foreach ($memberships as $membership) {
         $suggestion = new CRM_Banking_Matcher_Suggestion($this, $btx);
         if (isset($contact->general_options->suggestion_title)) {
             $suggestion->setTitle($contact->general_options->suggestion_title);
         } else {
             $suggestion->setTitle(ts("Record as Membership Fee"));
         }
         $suggestion->setId("existing-{$contribution_id}");
         $suggestion->setParameter('membership_id', $membership['id']);
         $suggestion->setParameter('last_fee_id', $membership['last_fee_id']);
         $suggestion->setProbability($membership['probability']);
         $btx->addSuggestion($suggestion);
     }
     // that's it...
     return empty($this->_suggestions) ? null : $this->_suggestions;
 }
コード例 #3
0
 public function match(CRM_Banking_BAO_BankTransaction $btx, CRM_Banking_Matcher_Context $context)
 {
     // get list of existing batches (cache in context)
     $existing_batches = $context->getCachedEntry('banking.pluginimpl.matcher.batch');
     if ($existing_batches == NULL) {
         $existing_batches = $this->generateBatchList();
         $context->setCachedEntry('banking.pluginimpl.matcher.batch', $existing_batches);
     }
     // look for a matching batch
     $config = $this->_plugin_config;
     $booking_date = strtotime($btx->booking_date);
     $matching_batches = array();
     foreach ($existing_batches as $batch) {
         $total_amount = $batch['total'];
         if (!empty($batch['export_date'])) {
             $submission_date = strtotime($batch['export_date']);
         } elseif ($batch['modified_date']) {
             $submission_date = strtotime($batch['modified_date']);
         } else {
             $submission_date = strtotime($batch['created_date']);
         }
         // check amount
         if (abs(1 - $total_amount / $btx->amount) > $config->total_amount_tolerance) {
             continue;
         }
         // check export_date_to_payment_min / max
         if ($booking_date < strtotime($config->export_date_to_payment_min, $submission_date)) {
             continue;
         }
         if ($booking_date > strtotime($config->export_date_to_payment_max, $submission_date)) {
             continue;
         }
         // batch is accepted -> calculate probability:
         // first factor: expected income time
         $time_penalty_total = strtotime('-' . $config->export_date_to_payment_tolerance, abs($booking_date - $submission_date));
         $time_penalty = min(1.0, 1 - $time_penalty_total / (strtotime($config->export_date_to_payment_max) - strtotime($config->export_date_to_payment_min)));
         // second factor: equal amount
         $amount_penalty = 1.0 - abs(1 - $total_amount / $btx->amount) / $config->total_amount_tolerance;
         // third factor: statmentes pending
         $status_penalty = 1.0 - count($this->getNonPendingContributionIDs($batch['id'])) / $batch['item_count'];
         $matching_batches[$batch['id']] = $time_penalty * $amount_penalty * $status_penalty;
     }
     // for each matched batch, create a suggestion
     foreach ($matching_batches as $batch_id => $batch_probability) {
         $suggestion = new CRM_Banking_Matcher_Suggestion($this, $btx);
         $suggestion->setTitle(ts("Settles a contribution batch"));
         $suggestion->setParameter('batch_id', $batch_id);
         $suggestion->setId("batch-" . $batch_id);
         $suggestion->setProbability($batch_probability);
         $btx->addSuggestion($suggestion);
     }
     // that's it...
     return empty($this->_suggestions) ? null : $this->_suggestions;
 }
コード例 #4
0
 public function match(CRM_Banking_BAO_BankTransaction $btx, CRM_Banking_Matcher_Context $context)
 {
     $config = $this->_plugin_config;
     // create 'manually processed' suggestion, if applicable
     if ($config->manual_enabled) {
         if ($config->manual_show_always || $this->has_other_suggestions($btx)) {
             $manually_processed = new CRM_Banking_Matcher_Suggestion($this, $btx);
             $manually_processed->setProbability($this->get_probability($config->manual_probability, $btx));
             $manually_processed->setTitle($config->manual_title);
             $manually_processed->setId('manual');
             // add related contacts
             $data_parsed = $btx->getDataParsed();
             $contacts = $context->findContacts(0, $data_parsed['name'], $config->lookup_contact_by_name);
             $manually_processed->setParameter('contact_ids', implode(',', array_keys($contacts)));
             $manually_processed->setParameter('contact_ids2probablility', json_encode($contacts));
             $btx->addSuggestion($manually_processed);
         }
     }
     // create 'not relevant' suggestion, if applicable
     if ($config->ignore_enabled) {
         if ($config->ignore_show_always || $this->has_other_suggestions($btx)) {
             $not_relevant = new CRM_Banking_Matcher_Suggestion($this, $btx);
             $not_relevant->addEvidence($this->get_probability($config->ignore_probability, $btx));
             $not_relevant->setTitle($config->ignore_title);
             $not_relevant->setId('ignore');
             $btx->addSuggestion($not_relevant);
         }
     }
     // that's it...
     return empty($this->_suggestions) ? null : $this->_suggestions;
 }
コード例 #5
0
 /** 
  * Generate a set of suggestions for the given bank transaction
  * 
  * @return array(match structures)
  */
 public function match(CRM_Banking_BAO_BankTransaction $btx, CRM_Banking_Matcher_Context $context)
 {
     $config = $this->_plugin_config;
     $threshold = $this->getThreshold();
     $data_parsed = $btx->getDataParsed();
     $penalty = $this->getPenalty();
     // find potential contacts
     $contactID2probability = array();
     if (empty($config->contact_id_list)) {
         $nameSearch = $context->findContacts($threshold, $data_parsed['name'], $config->lookup_contact_by_name);
         foreach ($nameSearch as $contact_id => $probability) {
             if ($probability - $penalty < $threshold) {
                 continue;
             }
             $contactID2probability[$contact_id] = $probability;
         }
     } else {
         if (!empty($data_parsed[$config->contact_id_list])) {
             $id_list = explode(',', $data_parsed[$config->contact_id_list]);
             foreach ($id_list as $contact_id) {
                 $contact_id = (int) $contact_id;
                 if ($contact_id > 0) {
                     $contactID2probability[$contact_id] = 1.0;
                 }
             }
         }
     }
     // create suggestions
     if (!empty($config->search_terms)) {
         $query = $this->getPropagationSet($btx, $suggestion, '', $config->search_terms);
     } else {
         $query = array();
     }
     if ($config->search_wo_contacts) {
         $suggestions = $this->createRecurringContributionSuggestions($query, 1.0, $btx, $context);
     } else {
         $suggestions = array();
         foreach ($contactID2probability as $contact_id => $probability) {
             $query['contact_id'] = $contact_id;
             $new_suggestions = $this->createRecurringContributionSuggestions($query, $probability, $btx, $context);
             $suggestions = array_merge($suggestions, $new_suggestions);
         }
     }
     // apply penalties and threshold
     foreach ($suggestions as $suggestion) {
         $probability = $suggestion->getProbability();
         $probability -= $penalty;
         if ($probability >= $threshold) {
             if ($penalty) {
                 $suggestion->addEvidence($penalty, ts("A general penalty was applied."));
             }
             $suggestion->setProbability($probability);
             $btx->addSuggestion($suggestion);
         }
     }
     // that's it...
     return empty($this->_suggestions) ? null : $this->_suggestions;
 }
コード例 #6
0
 /** 
  * Generate a set of suggestions for the given bank transaction
  * 
  * @return array(match structures)
  */
 public function match(CRM_Banking_BAO_BankTransaction $btx, CRM_Banking_Matcher_Context $context)
 {
     $config = $this->_plugin_config;
     $threshold = $this->getThreshold();
     $penalty = $this->getPenalty($btx);
     $data_parsed = $btx->getDataParsed();
     // first see if all the required values are there
     if (!$this->requiredValuesPresent($btx)) {
         return null;
     }
     // resolve accepted states
     $accepted_status_ids = $this->getAcceptedContributionStatusIDs();
     $contributions = array();
     $contribution2contact = array();
     $contribution2totalamount = array();
     $contributions_identified = array();
     // check if this is actually enabled
     if ($config->contribution_search) {
         // find contacts
         $contacts_found = $context->findContacts($threshold, $data_parsed['name'], $config->lookup_contact_by_name);
         // with the identified contacts, look up contributions
         foreach ($contacts_found as $contact_id => $contact_probabiliy) {
             if ($contact_probabiliy < $threshold) {
                 continue;
             }
             $potential_contributions = $this->getPotentialContributionsForContact($contact_id, $context);
             foreach ($potential_contributions as $contribution) {
                 // check for expected status
                 if (!in_array($contribution['contribution_status_id'], $accepted_status_ids)) {
                     continue;
                 }
                 $contribution_probability = $this->rateContribution($contribution, $context);
                 // apply penalty
                 $contribution_probability -= $penalty;
                 if ($contribution_probability > $threshold) {
                     $contributions[$contribution['id']] = $contribution_probability;
                     $contribution2contact[$contribution['id']] = $contact_id;
                     $contribution2totalamount[$contribution['id']] = $contribution['total_amount'];
                 }
             }
         }
     }
     // add the contributions coming in from a list (if any)
     if (!empty($config->contribution_list)) {
         if (!empty($data_parsed[$config->contribution_list])) {
             $id_list = explode(',', $data_parsed[$config->contribution_list]);
             foreach ($id_list as $contribution_id_string) {
                 $contribution_id = (int) $contribution_id_string;
                 if ($contribution_id) {
                     $contribution_bao = new CRM_Contribute_DAO_Contribution();
                     if ($contribution_bao->get('id', $contribution_id)) {
                         $contribution = $contribution_bao->toArray();
                         // check for expected status
                         if (!in_array($contribution['contribution_status_id'], $accepted_status_ids)) {
                             continue;
                         }
                         $contribution_probability = $this->rateContribution($contribution, $context);
                         // apply penalty
                         $contribution_probability -= $penalty;
                         if ($contribution_probability > $threshold) {
                             $contributions[$contribution['id']] = $contribution_probability;
                             $contribution2contact[$contribution['id']] = $contribution['contact_id'];
                             $contribution2totalamount[$contribution['id']] = $contribution['total_amount'];
                             $contacts_found[$contribution['contact_id']] = 1.0;
                             $contributions_identified[] = $contribution['id'];
                         }
                     }
                 }
             }
         }
     }
     // transform all of the contributions found into suggestions
     foreach ($contributions as $contribution_id => $contribution_probability) {
         $contact_id = $contribution2contact[$contribution_id];
         $suggestion = new CRM_Banking_Matcher_Suggestion($this, $btx);
         if (!in_array($contribution_id, $contributions_identified)) {
             if ($contacts_found[$contact_id] >= 1.0) {
                 $suggestion->addEvidence(1.0, ts("Contact was positively identified."));
             } else {
                 $suggestion->addEvidence($contacts_found[$contact_id], ts("Contact was likely identified."));
             }
         }
         if ($contribution_probability >= 1.0) {
             $suggestion->setTitle(ts("Matching contribution found"));
             if ($config->mode != "cancellation") {
                 $suggestion->addEvidence(1.0, ts("A pending contribution matching the transaction was found."));
             } else {
                 $suggestion->addEvidence(1.0, ts("This transaction is the <b>cancellation</b> of the below contribution."));
             }
         } else {
             $suggestion->setTitle(ts("Possible matching contribution found"));
             if ($config->mode != "cancellation") {
                 $suggestion->addEvidence($contacts_found[$contact_id], ts("A pending contribution partially matching the transaction was found."));
             } else {
                 $suggestion->addEvidence($contacts_found[$contact_id], ts("This transaction could be the <b>cancellation</b> of the below contribution."));
             }
         }
         $suggestion->setId("existing-{$contribution_id}");
         $suggestion->setParameter('contribution_id', $contribution_id);
         $suggestion->setParameter('contact_id', $contact_id);
         $suggestion->setParameter('mode', $config->mode);
         // generate cancellation extra parameters
         if ($config->mode == 'cancellation') {
             if ($config->cancellation_cancel_reason) {
                 // determine the cancel reason
                 if (empty($data_parsed[$config->cancellation_cancel_reason_source])) {
                     $suggestion->setParameter('cancel_reason', $config->cancellation_cancel_reason_default);
                 } else {
                     $suggestion->setParameter('cancel_reason', $data_parsed[$config->cancellation_cancel_reason_source]);
                 }
             }
             if ($config->cancellation_cancel_fee) {
                 // calculate / determine the cancellation fee
                 try {
                     $meval = new EvalMath();
                     // first initialise variables 'difference' and 'source'
                     $meval->evaluate("difference = -{$btx->amount} - {$contribution2totalamount[$contribution_id]}");
                     if (empty($config->cancellation_cancel_fee_source) || empty($data_parsed[$config->cancellation_cancel_fee_source])) {
                         $meval->evaluate("source = 0.0");
                     } else {
                         $meval->evaluate("source = {$data_parsed[$config->cancellation_cancel_fee_source]}");
                     }
                     $suggestion->setParameter('cancel_fee', $meval->evaluate($config->cancellation_cancel_fee_default));
                 } catch (Exception $e) {
                     error_log("org.project60.banking.matcher.existing: Couldn't calculate cancellation_fee. Error was: {$e}");
                 }
             }
         }
         // set probability manually, I think the automatic calculation provided by ->addEvidence might not be what we need here
         $suggestion->setProbability($contribution_probability * $contacts_found[$contact_id]);
         // update title if requested
         if (!empty($config->title)) {
             $suggestion->setTitle($config->title);
         }
         $btx->addSuggestion($suggestion);
     }
     // that's it...
     return empty($this->_suggestions) ? null : $this->_suggestions;
 }