Sidebar

Using iTop

Creating your iTop

iTop Customization

"How to" examples
DataModel

User Interface

Automation & Ticket management

Portal Customization

Communications displayed on Condition

Prerequisite: You must be familiar with the Syntax used in Tutorials and have already created an extension.

learning:
Portal User Communication displayed if the user Organization matches some condition defined per Communication
level:
Intermediate
domains:
XML, PHP, Portal, Communication, Presentation
min version:
2.7.0

If you are a Service Provider, you may want to inform your customers as a Communication on the User Portal, when their contract is about to expire and need to be renewed, or when their credit consumption has expired.

For this you could define “permanent” Communication(s) which would be displayed only if the user's Organization match a particular condition. This condition would be dynamically defined through an OQL for each Communication, for example it would retrieve the Customer whose contract is about to expire and need to be renewed, or whose consumption of credit has expired or whatever logic.

Communication

In order to do this we will modify the Communications to the Customers extension, so you need to have it…

Fields

Add an oql value to the org_match_type field and create a new OQL field to allow any condition on the applicable Organizations

itop-design | class@Communication | fields
        <field id="org_match_type" xsi:type="AttributeEnum" _delta="must_exist">
          <values>
            <value id="oql" _delta="define">
              <!-- Cautious this part uses XML 3.0 format and <code> tag is not closed correctly due to wiki limitation -->
              <code>oql</ code> 
            </value>
          </values>
        </field>
        <field id="org_oql" xsi:type="AttributeOQL" _delta="define">
          <sql>org_oql</sql>
          <default_value/>
          <is_null_allowed>true</is_null_allowed>
          <width/>
          <height/>
          <tracking_level>all</tracking_level>
        </field>

Presentation

Modify the Communication presentation, to display the oql field

itop-design | class@Communication | presentation | details
        <details>
          <items>
            <item id="col:col0">
              <items>
                <item id="org_oql" _delta="define">
                  <rank>65</rank>
                </item>
              </items>
            </item>
          </items>
        </details>

Methods

  1. Modify IsUserInScope method to compute the case where organizations are specified through an OQL
  2. Modify the DoCheckToWrite method to guarantee that the OQL is set when needed, is a valid OQL and returns Organizations objects
  3. Create a DisplayBareRelations method to display the list of Organizations matching the OQL right now
Communication
    public function IsUserInScope(User $oUser)
    {
                // Is the user org within the target organizations
                $iContact = $oUser->Get('contactid');
                $oContact = MetaModel::GetObject('Contact', $iContact, true, true);
                $iUserOrg = $oContact->Get('org_id');
                $sMatchType = $this->Get('org_match_type');
        $bRet = false;
 
                if ($sMatchType == 'oql') {
                    // Target organizations defined as an OQL
                $oOrgSearch = DBSearch::FromOQL_AllData($this->Get('org_oql'));
                $oOrgSet = new DBObjectSet($oOrgSearch, array(), array());
                $aTargetOrgs = $oOrgSet->GetColumnAsArray('id');
                    $bRet = in_array($iUserOrg, $aTargetOrgs);
                } 
                else {
                    // Target organizations are those linked to the Communication
                        $oOrgSearch = DBSearch::FromOQL_AllData('SELECT lnkCommunicationToOrganization WHERE communication_id = :communication_id');
                    $oOrgSet = new DBObjectSet($oOrgSearch, array(), array('communication_id' => $this->GetKey()));
                    $aTargetOrgs = $oOrgSet->GetColumnAsArray('org_id');
                    if (count($aTargetOrgs) == 0) {
                        // Target organizations are "All organizations" when none are explicitly linked to the Communication
                            $bRet = true;
                    } 
                    elseif ($sMatchType == 'direct') {
                        // Target organizations are those directly linked to the communication
                        $bRet = in_array($iUserOrg, $aTargetOrgs);
                        }
                else { // ($sMatchType == 'cascade')
                    // Target organizations are those directly linked to the communication or one of their sub-organizations
                        $oOrgHierarchical = DBSearch::FromOQL_AllData('SELECT Organization AS child JOIN Organization AS root ON child.parent_id BELOW root.id WHERE root.id IN (:target_org_list) AND child.id = :contact_org_id');
                        $oOrgHSet = new DBObjectSet($oOrgHierarchical, array(), array('contact_org_id' => $iUserOrg, 'target_org_list' => $aTargetOrgs));
                        $bRet = $oOrgHSet->Count() > 0;
                }
        }
                return $bRet;
    }
public function DoCheckToWrite()
{
    parent::DoCheckToWrite();
    if ($this->Get('start_date') > $this->Get('end_date'))
    {
      $this->m_aCheckIssues[] = Dict::Format('Class:Communication/Error:EndDateMustBeGreaterThanStartDate');
    }
    if ($this->Get('org_match_type') == 'oql') {
        $sOql = $this->Get('org_oql');
        if (empty($sOql)) {
            $this->m_aCheckIssues[] = Dict::Format('Class:Communication/Error:OQLMustBeProvided');
        } else {
            try
                    {
                        $oSearch = DBObjectSearch::FromOQL($sOql);
                        $sOqlClass = $oSearch->GetClass();
                    if ($sOqlClass != 'Organization') {
                        $this->m_aCheckIssues[] = Dict::Format('Class:Communication/Error:OQLMustReturnOrganization');
                    }
                    }
                    catch(Exception $e)
                    {
                        $this->m_aCheckIssues[] = Dict::Format('Class:Communication/Error:OQLNotValid', $e->getMessage());
                    }
        }
    }
 
}
public function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
{
        parent::DisplayBareRelations($oPage, $bEditMode);
        if(!$bEditMode && ($this->Get('org_match_type') == 'oql'))         {
                $oPage->SetCurrentTab(Dict::S('Class:Communication/Tab:Preview'));
                $aParams = array(
                        'menu' => true,
                        'table_id' => 'communication_preview_orgs_'.$this->GetKey(),
        );
        $oSearch = DBSearch::FromOQL_AllData($this->Get('org_oql'));
        $oBlock = new DisplayBlock($oSearch, 'list', true, $aParams);
        $oBlock->Display($oPage, 'communication_preview_'.$this->GetKey(), $aParams);
        }
}

Dictionaries

Define corresponding dictionary entries

        <entry id="Class:Communication/Attribute:org_match_type/Value:oql" _delta="define"><![CDATA[Organizations from OQL]]></entry>
        <entry id="Class:Communication/Attribute:org_oql" _delta="define"><![CDATA[Organizations OQL]]></entry>
        <entry id="Class:Communication/Attribute:org_oql+" _delta="define"><![CDATA[This OQL must return Organizations. It is used only if 'target organizations...' is based on OQL=oql]]></entry>
        <entry id="Class:Communication/Error:OQLMustBeProvided" _delta="force"><![CDATA[Organizations OQL must be provided]]></entry>
        <entry id="Class:Communication/Error:OQLMustReturnOrganization" _delta="force"><![CDATA[OQL must return Organization objects]]></entry>
        <entry id="Class:Communication/Error:OQLNotValid" _delta="force"><![CDATA[OQL is not valid: %1$s]]></entry>
latest/customization/dynamic-communication.txt · Last modified: 2023/07/21 10:19 (external edit)
Back to top
Contact us