Renderer Classes for Backoffice Customization in SAP Commerce (Hybris)

Requirement : Here we are developing custom renderer class to retrive and sort somecondition entities by precedence
Format each condition as a string: code|precedence|Y/N (where Y/N (Yes or No) indicates the isAvailable flag) and Concatenate all conditions into a single string separated by commas (,) then display the formatted string in the backoffice list view.

Step 1: Define two custom item types: SomeProductRule and SomeCondition.
Location: /samplecore/resources/samplecore-items.xml
    <itemtype code="SomeProductRule" autocreate="true" generate="true">
        <description>Some Product Rules</description>
        <deployment table="someproductrules" typecode="15788"/>
        <attributes>
            <attribute qualifier="vendor" type="java.lang.String">
                <description>Vendor Identifier</description>
                <modifiers read="true" write="true" search="true" optional="false"/>
                <persistence type="property"/>
            </attribute>
            <attribute qualifier="domain" type="java.lang.String">
                <description>Domain Category Name</description>
                <modifiers read="true" write="true" search="true" optional="true"/>
                <persistence type="property"/>
            </attribute>
        </attributes>
  </itemtype>
<itemtype code="SomeCondition" autocreate="true" generate="true"> <description>Some Condition</description> <deployment table="someconditions" typecode="15789"/> <attributes> <attribute qualifier="code" type="java.lang.Integer"> <description>Some Condition Attribute Code</description> <modifiers read="true" write="true" search="true" optional="false"/> <persistence type="property"/> </attribute> <attribute qualifier="precedence" type="java.lang.Integer"> <description>Rule Condition Priority</description> <modifiers read="true" write="true" search="true" optional="true"/> <persistence type="property"/> </attribute> <attribute qualifier="isAvailable" type="java.lang.Boolean"> <description>Is Some Condition Available</description> <modifiers read="true" write="true" search="true" optional="true"/> <persistence type="property"/> </attribute> </attributes> </itemtype>
Step 2: Establish a one-to-many relation between SomeProductRule and SomeCondition.
One SomeProductRule can have multiple SomeCondition entities, and use a Set to store the associated conditions.

    <relations>
    <relation code="SomeProductRule2SomeCondition" localized="false" autocreate="true">
        <sourceElement qualifier="someRule" type="SomeProductRule" cardinality="one"/>
        <targetElement qualifier="someConditions" type="SomeCondition" cardinality="many" collectiontype="set"/>
    </relation>
    </relations>

Note: Follow the correct order in the items.xml file. The <relations> section should be defined before the <itemtypes> section.

Step 3: Perform an ant clean all in the platform. After a successful build, verify that SomeProductRuleModel.java and SomeConditionModel.java are generated.

Step 4: Define a unique identifier for the navigation node. For example, under the Rules section, you want to add the SomeProductRule node.

Location: samplebackoffice/resources/samplebackoffice-backoffice-config.xml
<context component="explorer-tree" parent="auto" merge-by="principal" principal="backofficeadministratorrole">
   <explorer-tree:explorer-tree xmlns:explorer-tree="http://www.hybris.com/cockpitng/config/explorertree">
     <explorer-tree:navigation-node id="hmc_typenode_some_product_rule">
         <explorer-tree:type-nodecode="SomeProductRule" id="hmc_typenode_some_product_rule_node" />
       </explorer-tree:navigation-node>
    </explorer-tree:explorer-tree>
 </context>

Step 5: Add below properties in /samplebackoffice/resources/samplebackoffice-backoffice-labels/labels_en.properties
hmc_typenode_some_product_rule = Rules
hmc_typenode_some_product_rule_node = Some Product Rules

Step 6: Add below properties in /samplebackoffice/resources/localization/samplebackoffice-locales_en.properties
type.SomeProductRule.vendor.name=Vendor
type.SomeProductRule.domain.name=Domain

Step 7: In this step, we will create a custom renderer for displaying SomeProductRule entities in the Backoffice list view. The custom renderer will process and display the SomeConditions associated with the SomeProductRuleModel in a formatted string.

Location: /samplebackoffice/backoffice/src/com/hybris/sample/backoffice/actions/SomeProductRuleOrderRenderer.java

package com.hybris.sample.backoffice.actions;
import  java.util.ArrayList;
import  java.util.Comparator;
import  java.util.List;
import  java.util.Set;
import org.zkoss.zul.Listcell;
import org.apache.commons.lang.BooleanUtils;
import org.springframework.util.CollectionUtils;
import org.zkoss.zul.Label;
import com.hybris.cockpitng.core.config.impl.jaxb.listview.ListColumn;
import com.hybris.cockpitng.dataaccess.facades.type.DataType;
import com.hybris.cockpitng.engine.WidgetInstanceManager;
import com.hybris.cockpitng.widgets.common.AbstractWidgetComponentRenderer;
import com.hybris.sample.core.model.SomeConditionModel;
import com.hybris.sample.core.model.SomeProductRuleModel;

public class  SomeProductRuleOrderRenderer extends AbstractWidgetComponentRenderer<Listcell, ListColumn, Object> 
{
    private static final String PIPE = "|";
    private static final String COMMA = ",";

    @Override
    public void render(Listcell parent, ListColumn configuration, Object data, DataType dataType, 
                       WidgetInstanceManager widgetInstanceManager) {
        if (data instanceof SomeProductRuleModel) {
            Set<SomeConditionModel> conditions = ((SomeProductRuleModel) data).getSomeConditions();
            if (!CollectionUtils.isEmpty(conditions)) {
                List<SomeConditionModel> sortedConditions = new ArrayList<>(conditions);
                sortedConditions.sort(Comparator.comparingInt(SomeConditionModel::getPrecedence));
                StringBuilder labelBuilder = new StringBuilder();
                for (int i = 0; i < sortedConditions.size(); i++) {
                    SomeConditionModel condition = sortedConditions.get(i);
                    char isAvailableFlag = BooleanUtils.isTrue(condition.getIsAvailable()) ? 'Y' : 'N';
                    labelBuilder.append(condition.getCode()).append(PIPE).append(condition.getPrecedence()).append(PIPE).append(isAvailableFlag);
                    if (i < sortedConditions.size() - 1) {
                        labelBuilder.append(COMMA);
                    }
                }
                Label  label = new Label(labelBuilder.toString());
                parent.appendChild(label);
                this.fireComponentRendered(label, parent, configuration, data);
            }
        }
    }
}


Step 8: Register the Renderer in spring.xml to ensure that the custom renderer is recognized and used by the Backoffice configuration.

Location: /samplebackoffice/resources/samplebackoffice-backoffice-spring.xml

<bean id="someProductRuleOrderRenderer"
         class="com.hybris.sample.backoffice.actions.SomeProductRuleOrderRenderer"
         scope="prototype" />

Step 9: Define a list view for the SomeProductRule context, Add columns for vendor and domain. For someConditions, add a spring-bean pointing to the custom renderer (SomeProductRuleOrderRenderer).

Location: samplebackoffice/resources/samplebackoffice-backoffice-config.xml
   <context type="SomeProductRule" component="listview">
      <list:list-view xmlns:list="http://www.hybris.com/cockpitng/component/listView">
         <list:column qualifier="vendor" />
         <list:column qualifier="domain" />
         <list:column qualifier="someConditions" spring-bean=someProductRuleOrderRenderer" />
      </list:list-view>
   </context>


Step 10: After a successful build, bring the Hybris server up. Then, perform a HAC (Hybris Administration Console) update by selecting the specific extensions (such as samplecore and samplebackoffice) and check the options to "Update running system" and "Localize types".

Step 11: We can add data through impex or backoffice ,currently im adding data for SomeProductRule,SomeCondition through backoffice

Here im adding Vendor1(vendor),Electronics(Domain) in SomeProductRule

Here im adding SC001(code),10(precedence),TRUE(isAvailableFlag), similar with (SC002,20,FALSE)&(SC003,30,TRUE)&(SC004,40,TRUE)

Here add all Conditions in Product Rule


It retrives and sort conditions in product rule entities by precedence

Comments

Sandhya said…
Useful information, Thanks for sharing
Anonymous said…
Excellent content
Anonymous said…
Great jobs, Excellent content , please make a post on creating new wizard in backoffice
https://sapcommercecloudsimplified.blogspot.com/2024/12/backoffice-customizations-in-sap.html please do read this article

Popular posts from this blog

Latest SAP Commerce (Hybris) Interview Questions

Steps to Install SAP Commerce Cloud 2211/Install SAP Hybris 2105 to 2211

OCC Webservices in SAP Commerce(hybris) 2211 using YOCC template – Part 1