How to change the relationship of a record from one module to another

Sugar On Demand | 9.1 | Professional

Our Flow & Some Background Info:

Unclaimed Lead(Leads Module) -> Prospect(Opportunities Module) -> Current Account(Accounts Module)

Our marketing department uploads pre-qualified leads to our 'Unclaimed Leads' module. Our sales team(users) then  pick and choose leads and convert them to a Prospect to begin the sales cycle. When the lead is converted, the user creates a contact record and a prospect record that are related. Once the sales stage is Closed Won, the prospect then converts to a current account via a logic hook.

My Question:

Everything is currently working as it should, however the issue I am running into is once a Prospect converts to a Current Account, how do I take the contact that was linked to the Prospect record and link it to the new Current Account record?

Thanks in advance for pointing me in the right direction.

  • all you need to make a "after save" logic hook which will do rest of job. focus bean will be Prospect

    1) Check if previous prospect status was not "Converted" and current status is, it is by using $bean->fetched_row.

    2) If above condition met, then Pull contact_id & account_id of current bean.

    3) Load account bean using account_id and use load_relationship function to retrieve it's contact relationship link.

    4) just use function "add" to attach contact_id with account bean.

    Little suggesion on flow.

    Usually, Sugar assumes the first stage of the record is Prospect, then Lead and then final conversion to set of Account + Contact + Sale.

    Not sure how you managing it but this is what I learned over years of practice.

  • Thanks Ashish Dwivedi

    I am still learning best practices with Sugar, but this is my code below. Can you (or anyone else) give me some advice or help me correct this? Thanks.

    <?php

    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');

    class CreateAccountHook
    {

        function after_save_method($bean, $event, $arguments)
        {
            //check if the sales stage value has changed and reached contract signed
            if(isset($arguments['dataChanges']['sales_stage']) && $bean->sales_stage=='Closed Won')
            {  
                //create a new account record from prospect(opportunity) if conditions are met
                $newAcc = BeanFactory::newBean('Accounts');

                //load relationship of prospect(opportunity) to contact and add to the new account record
                $rel_name = 'opportunities_contacts_1';
                $bean->load_relationship($rel_name);
                $relatedBeans = $bean->$rel_name->getBeans();
                $newAcc->$rel_name->add($bean->id);

                //copy the name from prospect to the new current account record           
                $newAcc->name = $bean->name;
                $newAcc->save();
            }
        }
    }

    ?>
  • In your code you are mixing the relationship between the opportunity and the contact and that between the contact and the account. 

    Your process is:

    Unclaimed Lead(Leads Module) -> Prospect(Opportunities Module) -> Current Account(Accounts Module)

    So when you claim the Lead you create an Opportunity record (Prospect) related to a Contact record via the link

    'opportunities_contacts_1'

    When your opportunity is Won you want to create an Account and relate that Account to the Opportunity.

    My assumption is that the Account will be in the Contact's name. That is the accounts.name field will be the contacts.name field. 

    So your steps will be as follow:

    Check if the Opportunity already has an Account related to it. If so, stop there, you don't want to create another one.

    If not then create the Account with minimal information, for example by setting the Account name to the Contact's name.

    Then relate the newly created Account to the Opportunity via the appropriate relationship "accounts"; and the Account to the Contact.

    So let's start from the Opportunity.

    Create an after-save logic hook on Opportunity:

    custom/modules/Opportunities/logic_hooks.php

    I prefer to call my logic hook class with the name of the module so OppLogic.php will have Opportunities Logic. I prefer to put all the logic hooks into that one class so I can see them all in one place.

    Inside the class I will sort them in the order they fire, so the before_save then the after_save etc.. and I will make a note in the code of when it fires. Within each type of hook they will be sorted in the order given by the array, that way I can see what the code is doing in order, as often order matters.

    I will explain the before save fetch_row logic hook in a minute.

    $hook_version = 1;
    $hook_array = Array();
    $hook_array['before_save'][] = Array(1, 'fetchPreviousBean', 'custom/modules/Opportunities/OppLogic.php','OppLogic', 'fetch_row');
    $hook_array['after_save'][] = Array(1, 'createAccount', 'custom/modules/Opportunities/OppLogic.php','OppLogic', 'create_account');

    Now create the logic

    custom/modules/Opportunities/OppLogic.php

     

    Note that in an after_save logic hook we don't know what has changed anymore, so we use a before save logic hook to copy the prior state of the bean into a protected static array: $fetchedRow which we can then use in the after_save to compare values.

     

    class OppLogic
    {

       //before_save
       //before we save, make a copy of the fetchedRow, that is a copy of the bean before the save
       protected static $fetchedRow = array();
       function fetch_row($bean,$event,$arguments)
         if (isset($bean->fetched_row)) {
           self::$fetchedRow = $bean->fetched_row;
         }
       }

       //after_save
       function create_account($bean,$event,$arguments){
         //we are in the Opportunities Logic therefore the $bean is the opportunity.
         //check if the Opportunity has just changed status to Won
         if($bean->sales_stage == 'Closed Won' && $fetchedRow['sales_stage'] != 'Closed Won'){
           //ok, we won this Opportunity, check if it has an Account related to it
           $account_rel = 'accounts';
             /*this is the standard relationship between Accounts and Opportunities in
               Sugar, the relationship 'accounts_opportunities"  is called "accounts" from
               the opportunity side, and "opportunities" from the Account side. We are on
               the opportunity logic. You can check the names out by looking at the cached
               vardefs on your system if you have file system
               access: cache/modules/Opportunities/Opportunityvardefs.php
             */

           if($bean->load_relationship($account_rel)){
             //the relationship was loaded lets get the account IDs
             //we can use a simple get because we're just checking if one exists, we don't need to load all the account beans
             $relatedAccountIDs = $bean->$account_rel->get();
             if(empty($relatedAccountIDs)){
               //there are no accounts we can create one
               //get the contact information, we will need it to copy data to the account
               $contact_rel = 'opportunities_contacts_1'; //I got this name from your code above
               if($bean->load_relationship($contact_rel)){
                 // the relationship was loaded lets get the contacts and their beans so we can use that data
                 $relatedContacts = $bean->$contact_rel->getBeans();
                 //let us assume that you are going to use the data from the first Contact you find related to this Opportunity
                 //I don't know the cardinality of your relationship so let's just get the first one
                 if(!empty($relatedContacts)){
                   reset($relatedContacts);
                   $contactBean = current($relatedContacts);

                   //we have the data we need to create the Account
                   $accountBean = BeanFactory::newBean('Account');
                   //set the name to that of the contact
                   $accountBean->name = $contactBean->name;
                   //save the account Bean
                   $accountBean->save();
                   //get the id of the account you just created
                   $accountID = $accountBean->id;
         
                   //now you can relate the account to the Opportunity ($bean)
                   //load the oppotunity-account relationship
                   if($bean->load_relationship($account_rel)){
                     //add the account to the opportunity
                     $bean->$account_rel->add($accountID);
                   }
         
                   //load the contact-account relationship
                   $contact_account_rel = 'accounts';
                   if($contactBean->load_relationship($contact_account_rel)){
                     //add the account to the contact
                     $contactBean->$contact_account_rel->add($accountID);
                   }
                 }
               }
             }
           }
         }
       }
    }

    Keep in mind that I just wrote this code here in this post, it's not tested, so check for syntax and logic errors etc.

    I hope this helps clarify some of the mechanisms used in logic hooks.

    Let me know if you have any questions.


    FrancescaS

  • Francesca Shiekh

    VERY helpful. Thank you for your guidance. Once I make sure everything works, I will update this in case it might help other people in the future.