/**
 * Creates a new household according to the specs
 */
function civicrm_api3_contact_create_household($params)
{
    if (empty($params['mode'])) {
        $params['mode'] = CRM_Householdmerge_Logic_Configuration::getHouseholdMode();
    }
    $head_id = NULL;
    switch ($params['mode']) {
        case 'hierarchy':
            $head_id = (int) $params['head_id'];
        case 'link':
            // get member IDs
            $member_ids = $params['member_ids'];
            if (is_string($member_ids)) {
                $member_ids = explode(',', $member_ids);
            }
            // sanitise member IDs
            $sanitised_member_ids = array();
            foreach ($member_ids as $member_id) {
                $sanitised_member_id = (int) $member_id;
                if ($sanitised_member_id) {
                    $sanitised_member_ids[] = $sanitised_member_id;
                }
            }
            // now pass the work on the the worker
            $worker = new CRM_Householdmerge_Logic_Worker();
            $household_id = $worker->createLinkedHousehold($params['household_name'], $sanitised_member_ids, $params['address'], $head_id);
            return civicrm_api3_create_success();
        default:
            return civicrm_api3_create_error("Contact.create_household cannot process mode '{$params['mode']}'.");
    }
}
 function postProcess()
 {
     // define some stats
     $activities_total = count($this->_activityHolderIds);
     $activities_processed = 0;
     $activities_detected = 0;
     $activities_fixed = 0;
     // filter for relevant activities
     $activity_type_id = (int) CRM_Householdmerge_Logic_Configuration::getCheckHouseholdActivityTypeID();
     $activity_status_ids = CRM_Householdmerge_Logic_Configuration::getFixableActivityStatusIDs();
     $activity_ids = implode(',', $this->_activityHolderIds);
     $filter_query = "SELECT id AS activity_id FROM civicrm_activity\n                     WHERE civicrm_activity.activity_type_id = {$activity_type_id} \n                       AND civicrm_activity.status_id IN ({$activity_status_ids})\n                       AND civicrm_activity.id IN ({$activity_ids});";
     $filtered_activities = CRM_Core_DAO::executeQuery($filter_query);
     // go through all activites and try to fix them
     while ($filtered_activities->fetch()) {
         $activities_processed += 1;
         $problem = CRM_Householdmerge_Logic_Problem::extractProblem($filtered_activities->activity_id);
         if ($problem) {
             $activities_detected += 1;
             if ($problem->fix()) {
                 $activities_fixed += 1;
             }
         }
     }
     // show stats
     CRM_Core_Session::setStatus(ts('%1 of the %2 selected activities were processed, %3 of them could be fixed.', array(1 => $activities_detected, 2 => $activities_total, 3 => $activities_fixed, 'domain' => 'de.systopia.householdmerge')), ts('%1 Household Problems Fixed', array(1 => $activities_fixed, 'domain' => 'de.systopia.householdmerge')), $activities_fixed > 0 ? 'info' : 'warn');
     parent::postProcess();
 }
 public function postProcess()
 {
     $values = $this->exportValues();
     // store settings
     $expected_values = array('hh_mode', 'hh_head_mode', 'hh_member_relation', 'hh_head_relation');
     foreach ($expected_values as $key) {
         if (isset($values[$key])) {
             CRM_Householdmerge_Logic_Configuration::setConfigValue($key, $values[$key]);
         }
     }
     parent::postProcess();
 }
 /**
  * Will link the contact to the given household
  * If $relation_type_id is empty, the default member relation will be used
  */
 public function linkContactToHousehold($contact_id, $household_id, $relation_type_id = NULL)
 {
     if (!$relation_type_id) {
         $relation_type_id = CRM_Householdmerge_Logic_Configuration::getMemberRelationID();
     }
     // look up the right parameters (direction)
     if (!isset($this->_relationID2fields[$relation_type_id])) {
         $relation_type = civicrm_api3('RelationshipType', 'getsingle', array('id' => $relation_type_id));
         if ($relation_type['contact_type_a'] == 'Household') {
             $this->_relationID2fields[$relation_type_id] = array('household' => 'contact_id_a', 'contact' => 'contact_id_b');
         } else {
             $this->_relationID2fields[$relation_type_id] = array('household' => 'contact_id_b', 'contact' => 'contact_id_a');
         }
     }
     // finally create the relationship
     $rspec = $this->_relationID2fields[$relation_type_id];
     civicrm_api3('Relationship', 'create', array('relationship_type_id' => $relation_type_id, $rspec['household'] => $household_id, $rspec['contact'] => $contact_id, 'is_active' => 1));
 }
 /**
  * Fix a "new houshold member" problem by connecting
  * the new contact to the household, unless he's already
  * connected
  */
 public static function fixHMNW($problem)
 {
     $activity_id = $problem->getActivityID();
     if (empty($activity_id)) {
         return FALSE;
     }
     // get all target contacts
     $contact_ids = CRM_Activity_BAO_ActivityTarget::retrieveTargetIdsByActivityId($activity_id);
     if (empty($contact_ids)) {
         return FALSE;
     }
     // load all contacts
     $new_contact_id = NULL;
     $contact_data = civicrm_api3('Contact', 'get', array('id' => array('IN' => $contact_ids)));
     foreach ($contact_data['values'] as $contact_id => $contact) {
         if ($contact['contact_type'] == 'Individual') {
             if ($new_contact_id === NULL) {
                 $new_contact_id = $contact['id'];
             } else {
                 // there are multiple new contacts here...
                 return FALSE;
             }
         }
     }
     if (empty($new_contact_id)) {
         // no contact found
         return FALSE;
     }
     // check if there is already a relationship
     $relation_ids[] = CRM_Householdmerge_Logic_Configuration::getMemberRelationID();
     $relation_ids[] = CRM_Householdmerge_Logic_Configuration::getHeadRelationID();
     $existing_relationship = civicrm_api3('Relationship', 'get', array('contact_id_a' => $new_contact_id, 'contact_id_b' => $problem->getHouseholdID(), 'relationship_type_id' => array('IN' => $relation_ids), 'is_active' => 1));
     if ($existing_relationship['count']) {
         // there already is a relationship, the problem IS fixed already...
     } else {
         // create a new relationship
         civicrm_api3('Relationship', 'create', array('contact_id_a' => $new_contact_id, 'contact_id_b' => $problem->getHouseholdID(), 'relationship_type_id' => CRM_Householdmerge_Logic_Configuration::getMemberRelationID(), 'is_active' => 1));
     }
     return TRUE;
 }
 /**
  * get the activty status IDs that are considered to be live and fixable
  * 
  * @return string  comma separated ids
  */
 public static function getFixableActivityStatusIDs()
 {
     if (self::$fixable_activity_status_ids === NULL) {
         $status_ids = array();
         $status_ids[] = CRM_Core_OptionGroup::getValue('activity_status', 'Scheduled', 'name');
         self::$fixable_activity_status_ids = implode(',', $status_ids);
     }
     return self::$fixable_activity_status_ids;
 }
 /**
  * Load all the household members
  */
 protected function getMembers($household_id)
 {
     $member_relation_id = CRM_Householdmerge_Logic_Configuration::getMemberRelationID();
     $head_relation_id = CRM_Householdmerge_Logic_Configuration::getHeadRelationID();
     $head_ids = array();
     $member_ids = array();
     // load the relationships (both ways)
     $query = array('relationship_type_id' => array('IN' => array($member_relation_id, $head_relation_id)), 'is_active' => 1, 'contact_id_a' => $household_id, 'option.limit' => 99999);
     $member_query = civicrm_api3('Relationship', 'get', $query);
     foreach ($member_query['values'] as $relationship) {
         $member_ids[] = $relationship['contact_id_b'];
         if ($relationship['relationship_type_id'] == $head_relation_id) {
             $head_ids[] = $relationship['contact_id_b'];
         }
     }
     $query['contact_id_b'] = $household_id;
     unset($query['contact_id_a']);
     $member_query = civicrm_api3('Relationship', 'get', $query);
     foreach ($member_query['values'] as $relationship) {
         $member_ids[] = $relationship['contact_id_a'];
         if ($relationship['relationship_type_id'] == $head_relation_id) {
             $head_ids[] = $relationship['contact_id_a'];
         }
     }
     if (!empty($member_ids)) {
         // and load the memeber contacts
         $contact_query = civicrm_api3('Contact', 'get', array('id' => array('IN' => $member_ids), 'contact_type' => 'Individual', 'is_deleted' => 0));
         $members = $contact_query['values'];
         // set the relationship type
         foreach ($members as &$member) {
             if (in_array($member['id'], $head_ids)) {
                 $member['hh_relation'] = 'head';
             } else {
                 $member['hh_relation'] = 'member';
             }
         }
         return $members;
     }
     return array();
 }
 /**
  * Identify the contact to be considered the HEAD under the given member_data objects
  * 
  * @return int  contact_id of the head
  */
 protected function identifyHead(&$members)
 {
     $method = CRM_Householdmerge_Logic_Configuration::getHouseholdHeadMode();
     if ($method == 'topdonor2y_m') {
         // init donations array
         $donations = array();
         foreach ($members as $member_id => $member) {
             $donations[$member_id] = 0;
         }
         $contact_ids = implode(',', array_keys($members));
         $td_amounts_sql = "\n          SELECT contact_id AS contact_id, \n                 SUM(total_amount) AS amount\n           FROM civicrm_contribution\n          WHERE contact_id IN ({$contact_ids})\n            AND (is_test IS NULL OR is_test = 0)\n            AND (contribution_status_id = 1)\n            AND (receive_date BETWEEN (NOW() - INTERVAL 2 YEAR) AND NOW())\n          GROUP BY contact_id;\n          ";
         $td_amounts = CRM_Core_DAO::executeQuery($td_amounts_sql);
         while ($td_amounts->fetch()) {
             $donations[$td_amounts->contact_id] = $td_amounts->amount;
         }
         // now determin the head
         $topdonor_id = NULL;
         $topdonor_amount = NULL;
         foreach ($donations as $member_id => $donation_amount) {
             if ($donation_amount > $topdonor_amount || $topdonor_amount === NULL) {
                 $topdonor_id = $member_id;
                 $topdonor_amount = $donation_amount;
             } elseif ($donation_amount == $topdonor_amount) {
                 if ($members[$member_id]['gender_id'] == 2) {
                     // if donor has same amount and is male => take over
                     $topdonor_id = $member_id;
                     $topdonor_amount = $donation_amount;
                 }
             }
         }
         // now $topdonor_id should be the HEAD
         return $topdonor_id;
     } else {
         error_log("UNDEFINED METHOD TO DETERMINE HEAD: {$method}");
         return reset(array_keys($members));
     }
 }
 /**
  * Check if there alread is an (active) 'check' activity with this household
  */
 protected function hasLiveActivity()
 {
     $activity_type_id = (int) CRM_Householdmerge_Logic_Configuration::getCheckHouseholdActivityTypeID();
     $household_id = (int) $this->household_id;
     $activity_status_ids = CRM_Householdmerge_Logic_Configuration::getLiveActivityStatusIDs();
     $sentinel = "[{$this->code}] %";
     if (empty($this->params['member_id'])) {
         $member_clause = "";
     } else {
         $member_id = (int) $this->params['member_id'];
         $member_clause = "AND EXISTS (SELECT id FROM civicrm_activity_contact WHERE activity_id = civicrm_activity.id AND contact_id = {$member_id} AND record_type_id = 3)";
     }
     $selector_sql = "SELECT civicrm_activity.id AS activity_id\n                     FROM civicrm_activity\n                     LEFT JOIN civicrm_activity_contact target ON target.activity_id = civicrm_activity.id AND target.record_type_id = 3\n                     WHERE civicrm_activity.activity_type_id = {$activity_type_id} \n                       AND civicrm_activity.status_id IN ({$activity_status_ids})\n                       AND civicrm_activity.subject LIKE %1\n                       AND target.contact_id = {$household_id}\n                       {$member_clause} ;";
     $selector_params = array(1 => array($sentinel, 'String'));
     $query = CRM_Core_DAO::executeQuery($selector_sql, $selector_params);
     return $query->fetch();
 }
/**
 * Set permissions for runner/engine API call
 */
function householdmerge_civicrm_alterAPIPermissions($entity, $action, &$params, &$permissions)
{
    $permissions['contact']['create_household'] = CRM_Householdmerge_Logic_Configuration::getCreateHouseholdPermission();
}