Wednesday, March 22, 2017

LDAP Integration & Customization Points

Introduction
When the authentication mode is set to LDAP, LogonCmdImpl invokes the LDAPIntegrationCmdImpl which contains the main customization points when dealing with the user and organization data flow to and from the WCS and LDAP.


LDAPIntegrationCmdImpl provides methods that can be overridden to customize the LDAP synchronization. Since LDAP integration requires a site-wide implementation, only one implementation of this command can be registered by using store 0.

Organization Structure Mapping between WCS & LDAP
It is recommended that the organization structure and distinguished names on the LDAP server match what is in WCS database. Following LDAPIntegrationCmd command methods are used for mapping between LDAP and WCS DNs:
public String getLDAPDN(String astrCommerceDN) throws ECException;
public String getCommerceDN(String astrLDAPDN, DataObject adoMember) throws ECException;

Callout to do extra processing during Single sign on (SSO) and Logon
In LogonCmdImpl.java, when the authentication mode is set to LDAP, and the authentication is successful,
if (MemberHelper.isLDAPUsedForAuthentication())
{
        postLDAPAuthenticationProcessing();
}

protected void postLDAPAuthenticationProcessing() throws ECException
   {
    LDAPIntegrationCmd cmdLDAPIntegration =
       (LDAPIntegrationCmd)CommandFactory.createCommand(
      LDAPIntegrationCmd.NAME,
      new Integer(0));    
    cmdLDAPIntegration.postLogonProcessing(getUserObject());
}


The following method of LDAPIntegrationCmdImpl.java is called to allow further processing to be done:
- public void postLogonProcessing(UserAccessBean aUserAccessBean) throws ECException;

- UserSyncBean.findByMemberId(aUserAccessBean.getMemberId())
   Can be called to get the UserSyncBean.
- UserSyncBean.getLDAPMember()
   Returns a DataObject representing the object in LDAP, which can be used for any further processing.

After single sign on takes place, the following method is called to handle any additional processing:
public void postSingleSignOnProcessing(UserSyncBean aUserSyncBean) throws ECException;

Callout to do extra processing in SyncBean
The following method can be overridden to do extra processing whenever LDAP is being updated using a sync bean:
public void LDAPIntegrationCmd.postUpdateToLDAP (UserSyncBean userSyncBean) throws ECException;

The following method can be overridden to do extra processing whenever the WebSphere Commerce database is being updated by data from LDAP:
public void LDAPIntegrationCmd.postRefreshFromLDAP (UserSyncBean userSyncBean) throws ECException;


Synchronizing User/Organization Data between WCS & LDAP
The ldapentry.xml file is used to configure which attributes are synchronized between the LDAP server and the WebSphere Commerce database. Some commonly used attributes are specified by default. The actual synchronization is done whenever the synchronization beans are used: UserSyncBean for user profile data, and OrganizationSyncBean for organization data.

UserSyncBean and OrganizationSyncBean read and write data to the database as well as to LDAP. Each class reads and writes to a default set of WCS database tables. Each of these tables has a corresponding sync helper data object (DO) class that is used by the sync bean to read and write to the table:

UserSyncBean-
UserDO                         <->      USERS
UserRegistryDO            <->     USERREG
UserDemographicsDO  <->      USERDEMO
SelfAddressDO              <->     ADDRESS (SELF ADDRESS)
BusinessProfileDO         <->     BUSPROF
UserProfileDO               <->     USERPROF
MemberAttributesDO    <->     MBRATTRVAL

OrganizationSyncBean-
OrgEntityDO                <->     ORGENTITY
SelfAddressDO             <->    ADDRESS (SELF ADDRESS)
MemberAttributesDO  <->     MBRATTRVAL

The DO classes to include for each sync bean can be specified and changed from the default implementation to match custom needs. The task command can be extended, and more DO classes can be added if you want to synchronize with new custom user/organization tables.

Limiting Synchronization of Data
In some cases, you might not want the OrganizationSyncBean to update the LDAP server whenever an organization is created or update WebSphere Commerce. This exclusion can be specified in the ldapentry.xml file by using the "ldapToWcs" or "ldapOnly" flow options. In other case "bothDirections" can be used.

wimconfig.xml(VMM- Virtual Member Manager)
Add a property mapping to the wimconfig.xml to correctly use a LDAP repository with VMM. Member manager is a service which runs on the WAS.



To use WCS with LDAP, WAS Administrative Security must be enabled and configured to use Federated Repositories. The Federated Repositories feature is implemented using another WAS component called Virtual Member Manager (VMM). com.ibm.commerce.member.syncbeans.VMMProxy is used by WebSphere Commerce to call VMM APIs to interact with the LDAP server.

Friday, March 10, 2017

Commerce Composer Customizations

Introduction
PFB the four main components of the online catalog navigation pages designed by the commerce composer architecture-
1. Page
2. Template
3. Layout
4. Widget

1. Page
We need to choose the targeted or create the new page.


2. Template 
We can make use of the OOB templates built on fluid grid system to fit in the intended UI structure.
If not addressed by the OOB template then we can create our own template by following below steps-

a. Defining the storefront assets for Commerce Composer layout templates
b. Registering a Commerce Composer layout template
c. Testing a custom layout template in Management Center


3. Layout
By leveraging the OOB/custom template underneath, we can fit in the custom/OOB widgets on the layout.

4.Commerce Composer Widgets
Depending upon the need we might have to create a fresh widget or customize the OOB widget by creating a replica or using the pure OOB widget.

Please find below the high level steps to create a custom commerce composer widget-
Create Widget's Template base xml & base files generation
A. Create a temporary project which will hold the template assets for the newly creates widget,
B. Create a XML pattern input file in it with below format and supply the entries in it  as per the need-
e.g.
<pageLayout vendor="myCompany" targetFolder="NewWidgetProject">
  <widget>
    <widgetDef identifier="myNewContentRecommendationWidget" 
     UIObjectName="myNewContentRecommendationWidgetObject"
     displayName="My New Content Recommendation Widget"
     description="This widget displays marketing content, such as ads, on a store page"
     widgetDisplayGroups="AnyPage,SearchPage"
     widgetRestrictionGroups="AnyPage,SearchPage" >
      <property name="widgetOrientation"   
       displayName="Widget Orientation"/>
      <property name="numberOfContentToDisplay"   
       displayName="Maximum number of content to display"/>
    </widgetDef>
    </widget>
</pageLayout>

C. Select the modified xml and run the JET transfarmation on it. In the Transformation section, select com.ibm.commerce.toolkit.internal.pattern.pageLayout.
D. Store,LOBTools and Dataload related material is generated

Customize the generated widget JSP files
Copy the generated JSPs into Store project and customize the JSPs as per the need-
myNewContentRecommendationWidget_Data.jspf
myNewContentRecommendationWidget_UI.jspf
myNewContentRecommendationWidget.jsp
mywidgettext_en_US.properties
mywidgettext.properties

Register the Widget through Dataload
To register a widget, use the Data Load utility to load the widget identifier and definition XML into the PLWIDGETDEF database table. Copy the registerWidgetdef.csv and subscribeWidgetDef.csv and modify them accordingly for registering and subscribing to the widget through dataload-
registerWidgetdef.csv
subscribeWidgetDef.csv
wc-dataload-widget.xml
wc-dataload-env.xml   
wc-loader-registerWidgetdef.xml   
wc-loader-subscribeWidgetdef.xml

Add CMC support for the custom Widget
Update the Management Center framework to support displaying your custom widget in the Commerce Composer tool-
WidgetObjectDefinition.def
WidgetPropertiesView.def
mycompanyPageLayoutResourceBundle.lzx
PageLayoutLOB_en_US.properties
PageLayoutLOB.properties

Thursday, March 9, 2017

Calculation Framework

Introduction
Calculation framework helps us determining the monetary amounts associated with each orderitems since every orderitem can have reference to the offer, shipping mode, fulfillment center and contract. Consolidated calculated orderitems amount is applied to the order eventually.

High Level Steps of Calculation Framework
--------------------------------------------------------
OrderCalculate interface invokes the class PromotionEngineOrderCalculateCmdImpl which in turn invokes the four major steps mentioned below-
1. InitializeCalculationUsage  ---- Clears up the existing adjustments on orderitems and order
2. ApplyCalculationUsage calls:  -- Calculates and applies the amounts
     a. CalculationCodeCombine calls:
               CalculationCodeQualify
      b. CalculationCodeCalculate calls:
                 CalculationRuleCombine calls:
                               CalculationRuleQualify
                 CalculationRuleCalculate calls:
                              CalculationScaleLookup
                              CalculationRange
       c. CalculationCodeApply
3. SummarizeCalculationUsage   --- Summarizes the total adjustments to the order
4. FinalizeCalculationUsage    --- Validates & finalizes the Promotion


Overall Flow
-----------------
STENCALUSG table entry for the calusage_id determines the business logic to be executed for the below four steps of calculation framework. Let us consider the example of -1 calcusage(i.e discount)-

1) InitializeCalculationUsage
First of all, initializeCalculationUsage() is invoked which invokes the InitializeAdjustmentCmd interface based upon the entry in STENCALUSG table for CALUSAGE_ID -1. Default class implementation for discount InitializeAdjustmentCmdImpl is invoked and resets the adjustments to zero.
InitializeAdjustmentCmdImpl performs below activities-

e.g. nOrderItemId=50001, original dOrderItemAdjustment=0.00000
initializing ORDERS.TOTALADJUSTMENT to zero, dOldOrderAdjustmentAmount=0.00000

2) ApplyCalculationUsage
This is the major step in terms of customizations. ApplyCalculationUsageCmd is invoked which further invokes the following methods inside ApplyCalculationUsageCmdImpl-

2A) CalculationCodeCombineCmd (Internally invokes CalculationCodeQualifyCmd, Tables- px_promotion,clcdpromo,calcode)

SELECT * FROM cmdreg c where c.INTERFACENAME like '%CalculationCodeCombineCmd%' gives me com.ibm.commerce.order.calculation.PromotionEngineDiscountCalculationCodeCombineCmdImpl
So CalculationCodeCombineCmd interface in turn invokes PromotionEngineDiscountCalculationCodeCombineCmdImpl command

This command collects the promotions- calcodes that are eligible for the given orderitems. The relationship between calculation code and promotion is defined in CLCDPROMO which is created during promotion creation.

More specifically, the applyCalculationUsage calls PromotionEngineCalculationCodeCombineCmdImpl version of the CalcodeCombineCmd which invokes promotion engine. Once the promotionEngine is invoked, this retrieves the associated promotion execution records which are converted into the format that the calculation framework can understand.

2B) CalculationCodeCalculateCmd
After the above step, the data read from the above is used to calculate the discounts(via calrule combine and calrule calculate methods).

2C) CalculationCodeApplyCmd
The calcodes determined in step a and adjustments calculated in step b are finally applied to the order items in this step via the DiscountCalculationCodeApplyCmdImpl implementation.
That is the ORDADJUST and ORDIADJUST tables are populated in this step.

We can customize any of these by overriding these with your version of method in CALMETHOD table or by overriding in CMDREG table.

3) SummarizeCalculationUsage
Default implementation SummarizeAdjustmentCmdImpl is invoked which summarizes the total adjustments to the order.

e.g. PFB the log snippet-
SummarizeAdjustmentCmdImpl.performExecute orderitem id=50001, status=P
SummarizeAdjustmentCmdImpl.performExecute nOrderItemId=50001, status=P, dOrderItemAdjustmentForUsage=-5.70000
SummarizeAdjustmentCmdImpl.performExecute summarizing ORDERS.TOTALADJUSTMENT to dOrderAdjustmentTotal=-5.70000
SummarizeAdjustmentCmdImpl.performExecute summarizing SUBORDERS.TOTALADJUSTMENT to dSubOrderAdjustmentTotal=-5.70000
SummarizeAdjustmentCmdImpl.performExecute Exit

4) finalizeCalculationUsages
Default implementation is FinalizeDiscountCalculationUsageCmdImpl command which validates the promotion code and finalizes the Promotion Argument.

e.g. PFB the log snippet-
com.ibm.commerce.order.calculation.CalculationHelper.finalizeCalculationUsages finalizeCalculationUsageMethodId(storeId=10152,usageId=-1)=-204
com.ibm.commerce.order.calculation.FinalizeDiscountCalculationUsageCmdImpl.performExecute Entry
com.ibm.commerce.order.calculation.FinalizeDiscountCalculationUsageCmdImpl.performExecute Exit

Note: The calculation framework is invoked when you call OrderCalculate or OrderPrepare which in turn invokes the promotion engine when we pass the usage -1 as we mentioned Or we can also invoke promotion engine by calling PromotionEngineOrderCalculateCmdImpl.
Therefore, we can also customize this command based upon the needs.

OrderItemAddCmd/OrderItemUpdate/OrderPrepare commands calls the first three steps of the calculation framework whereas OrderProcess command calls the final step i.e. finalizeCalculationUsages of the calculation framework.

Five Major Components
---------------------------
1. Calculation methods
2. Calculation usages (-1 discount,-2 shipping,-3 sales tax,-4 shipping tax,-5 coupon,-6 surcharge,-7 shipping adjustment)      
3. Calculation codes
4. Calculation rules
5. Calculation scales and calculation ranges

Sequence of activities
------------------------
Define the calculation codes.
Define the calculation rules.
Define the calculation scales.
Define the calculation ranges.
Define the look-up results for the calculation ranges.
Associate the calculation scales with the calculation rules.
Attach the calculation code with the all catalog entries.

Customizations
If we do not have the monetary amounts to be applied on orderitems in the WCS DB and are to be retrieved from elsewhere then we can write our custom java classes for the calmethods by associating them inside the stencalusg table.

The custom java classes can make the real time call to retrieve the monetary amounts from the ultimate source e.g. shipping charges can be retrieved from the third party by adding the real time call inside the custom java class MyApplyShippingCmdImpl and the same class entru need to make inside the stencalusg table for the calusage_id -2.

This is how the custom ApplyShippingCmdImpl command would look like-

@Override
    public void performExecute() throws ECException {
        super.performExecute();
       
        if (iItems != null && iItems.length > 0) {
           try {
               for (int index = 0; index < iItems.length; index++) {
                    Item iItem = iItems[index];
                       //Setting dummy price which can be retrieved from third party
                       iItem.setShippingTotal(new BigDecimal(111));
                       iItem.commit();
               }
           }catch (Exception e) {
               e.printStackTrace();
           }
        }
    }

@Override
    public void setItems(Item[] aItems) {
        iItems = aItems;
        super.setItems(aItems);
    }

Wednesday, March 8, 2017

Payment Flow

Overall OOB Payment Flow
------------------------------------ 
1. When the buyer lands on Shipping-Billing page, Payment section drop down lists the various payment options. All of these payment options are configured in WCS DB as payment business policies for the store.

Tables used-
Policy/Policydesc/Policycmd/Policytype/Policytyc

2. Once buyer fills the credit card details and click next, AjaxRestOrderPrepare & AjaxRestOrderPIAdd Ajax REST calls are made (after successfull server side validation of credit card details using CheckCCNumberCmdImpl) which results in OrderPrepare and PIAddCmdImpl invocation respectively. PIAddComImpl adds the payment instructions to the order i.e. in PPCPAYINST and PPCEXTDATA WCS tables.
    CheckoutPayments.js -> processCheckout -> processPIAndCheckout -> addPaymentInstructions

3. Once buyer submits the order, payment plugin will be invoked and entries are made in ORDPAYINFO, PPCPAYMENT and PPCPAYTRAN tables-
    CheckoutHelper.js -> checkoutOrder -> AjaxRESTOrderSubmit

Typical Punchout Payment Setup Steps

In a typical punchout payment configuration below steps are being followed-
- Configuring the new Payment method in the DB
- Configuring the new Payment method in the payment xml files 
- Create the payment method jsp and place it at intended location. 
- Creating a Payment Plug-in
- Customizing the Billing Page Storefront
- Customizing the CallBackCmd with action registration in struts-confog-ext.xml and ACP load
- Configuring merchant related information
- Configuring certificate for the handshake
- Testing the setup with PSP test account.

These steps are explained in detail below-

Configuring a new Payment/Refund method 
-------------------------------------------------------------
In order to add a new payment/refund method we would be required to-
a. Make entries in OOB WCS tables (POLICY/POLICYDESC/POLICYCMD with the Payment/ReturnPayment type)
b. Define the payment/refund actions/rules in XML files.

1. Configure Payment
toolkitDir/workspace/WC/xml/config/payments/ppc/plugins/PSP/PluginDeployment.xml
2. Configure Payment Method
PaymentMethodConfigurations.xml
3. Configure Action Rules
toolkitDir/workspace/WC/xml/config/payments/edp/groups/default/PSP/ with all the files copied from toolkitDir/workspace/WC/xml/config/payments/edp/groups/default/CreditCardOffline
4. Add Payment Mappings
toolkitDir/workspace/WC/xml/config/payments/edp/groups/default/PaymentMappings.xml
5. Map payment systems to payment plug-ins
PaymentSystemPluginMapping.xml

For new entry inside POLICY table, Business Policy Name must match the payment/refund method ID configured in payment rules (the paymentMethod value in the PaymentMethodConfigurations.xml file, or the refundMethod value in the RefundMethodConfigurations.xml file).

Merchant Feature
---------------------------
Merchant information is managed in below WCS tables-
MERCHANT, MERCHCONF, MERCHCONFINFO and STOREMERCH

Creating a Payment Plug-in
---------------------------------
Create an EJB stateless session bean.
Ensure your plug-in remote interface extends the Plugin or QueryablePlugin interface.
Create a plug-in deployment descriptor.
Create a JAR file (EJB module).

Payment Business flow: Extension Points
------------------------------------------------------
In a typical setup which is subject to customization-
On WCS order submission, payment is authorized with order total amount and order is transferred to the external system( subject to customization ). After order fulfilment by the external OMS, a shipment confirmation message is sent back to WCS to capture payment for the shipped order items in this package.

For Payment, PrimePaymentCmd is called at Order Submission ( ProcessOrderCmdImpl )
ReservePaymentCmd is called at ReleaseToFulfillment
FinalizePaymentCmd is called at shipment confirmation

Bypassing Payments : Void Implementations
----------------------------------------------------------
Though bypassing the OOB payment flow can be done through bypassing the ajax calls from shipping billing page to bypass the call to PIAddCmd however below OOB void commands can also be used-
e.g. com.ibm.commerce.edp.commands.PrimePaymentCmd                 com.ibm.commerce.edp.commands.PrimePaymentVoidCmdImpl

Payment life cycle
-----------------------
a. There are three stages to payment processing: validation, reservation, and finalization.

b. The payment life cycle is related to the order life cycle stages: order capture, release to fulfillment, and shipping.

c. Order capture- Payment validated
Release to fulfillment- Payment reserved
Order Shipping- Payment finalized

Friday, January 27, 2017

Customizing REST service over Solr to include custom table data in WCS 8 Mod Pack1

Introduction
--------------
PFB the steps to include the custom table XI_RATING data in Solr response and then in REST response in WCS 8-

1) Create the new DB table which will keep the ratings of the products loaded through third party system, populate it with some data for testing-
CREATE TABLE "WCSDB"."X_RATINGS"  (
"CATENTRY_ID" BIGINT NOT NULL ,
"RATING" BIGINT NOT NULL)  

2) Create the custom preprocess file to pick the data from the custom table X_ratings and populate the tem ptable XI_Ratings
File name - WCDE80\search\pre-processConfig\MC_10001\DB2\wc-dataimport-preprocess-custom.xml

<_config:DIHPreProcessConfig xmlns:_config="http://www.ibm.com/xmlns/prod/commerce/foundation/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ibm.com/xmlns/prod/commerce/foundation/config ../../xsd/wc-dataimport-preprocess.xsd ">
  <_config:data-processing-config processor="com.ibm.commerce.foundation.dataimport.preprocess.StaticAttributeDataPreProcessor" batchSize="500">
      <_config:table definition="CREATE TABLE XI_RATINGS ( CATENTRY_ID BIGINT NOT NULL, RATING BIGINT, PRIMARY KEY (CATENTRY_ID))" name="XI_RATINGS"/>
         
   <_config:query sql="SELECT DISTINCT CATENTRY.CATENTRY_ID,X_RATINGS.RATING FROM CATENTRY,X_RATINGS WHERE CATENTRY.CATENTRY_ID = X_RATINGS.CATENTRY_ID"/>
       <_config:mapping>
          <_config:key queryColumn="CATENTRY_ID" tableColumn="CATENTRY_ID"/>
             <_config:column-mapping>
                <_config:column-column-mapping>
                    <_config:column-column queryColumn="RATING" tableColumn="RATING" />
                </_config:column-column-mapping>
             </_config:column-mapping>
        </_config:mapping>   
  </_config:data-processing-config>
</_config:DIHPreProcessConfig>

3) Modify the Solr extension files as follow-
a)x-schema.xml-
<field name="rating" type="string" indexed="true" stored="true" required="false" multiValued="false"/>

b) x-data-config.xml-
<field column="RATING" name="rating"/>

c) solrcore.properties-
dataImporter.ext.querySelect=XI_RATINGS.RATING,
dataImporter.ext.queryFrom=LEFT OUTER JOIN XI_RATINGS ON (CATENTRY.CATENTRY_ID=XI_RATINGS.CATENTRY_ID)

4) Run preprocess with server stopped, and then start server and build Solr index
Newly included field can be validated using the Solr testing URL-
http://localhost/solr/MC_10001_CatalogEntry_en_US/select?q=catentry_id:<catentryId>

5) Make the new search profile in wc-search.xml by extending the existing search profile invoked in the REST service call under Search folder-
<_config:profile name="X_findCatalogEntry" extends="IBM_findProductByIds_Details">
   <_config:query inherits="true">
       <_config:postprocessor           classname="com.ibm.commerce.foundation.server.services.rest.search.postprocessor.solr.SolrRESTSearchCatalogEntryViewUserDataQueryPostprocessor" />
   </_config:query>
   <_config:result inherits="true">
           <_config:field name="rating" />
   </_config:result>  
</_config:profile>

6) Make the new wc-component.xml under Search folder ext folder- (It takes care of the mapping we used to have it under wc-business-object-mediator.xml prior to version 7 feature pack 7)

<?xml version="1.0" encoding="UTF-8"?>
<_config:DevelopmentComponentConfiguration
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.ibm.com/xmlns/prod/commerce/foundation/config ../xsd/wc-component.xsd "
    xmlns:_config="http://www.ibm.com/xmlns/prod/commerce/foundation/config">

    <_config:valuemappingservice>
        <_config:valuemapping externalName="CatalogEntryUserDataFieldNameMapping" internalName="CatalogEntryUserDataFieldNameMapping">
                <_config:valuemap externalValue="RATING" internalValue="rating" />
        </_config:valuemapping>
    </_config:valuemappingservice>
</_config:DevelopmentComponentConfiguration>

7) Make the new wc-rest-resourceconfig.xml file under /Search-Rest/WebContent/WEB-INF/config/com.ibm.commerce.rest-ext/wc-rest-resourceconfig.xml

<ResourceConfig>
    <Resource name="productview">
    <GetUri uri="store/{storeId}/productview/byId/{productId}"
            description="Get product by unique ID"                 searchProfile="X_findCatalogEntry,IBM_findProductByIds_Details,IBM_findProductByIdsWithAttributesAndAttachments,IBM_findProductByIds_Summary,IBM_findProductByIds_Summary_WithNoEntitlementCheck,IBM_Admin_findProductByIds"/>
</Resource>
</ResourceConfig>

8) Restart the server and access the new indexed fields in userdata section using rest call.

9) Testing
http://localhost/search/resources/store/10158/productview/byId/121892?responseFormat=xml&catalogId=10158&currency=USD

Thursday, January 26, 2017

Customizing REST service over Solr in WCS 8 Mod Pack1

Introduction
---------------
There is a slight difference in the way custom fields of the OOB WCS tables are added in Solr response and ultimately in REST response. Solr extensions now needed to be put in x-schema.xml, x-data-config.xml and solrcore.properties instead of schema.xml and wc-data-config.xml

Steps to include custom data catentdesc.AUXDESCRIPTION1 column on PDP page REST call
-----------------------------------------------------------------------------------------------------------------
1) Go to Path- toolkit\search\solr\home\MC_10001\en_US\CatalogEntry\conf
Modify x-schema. xml,solrcore.properties and x-data-config.xml as follow-

x-schema.xml-
<field name="auxdescription1" type="wc_text" indexed="true" stored="true" required="false" multiValued="false"/>

x-data-config.xml-
<field column="AUXDESCRIPTION1" name="auxdescription1"/>

solrcore.properties-
dataImporter.ext.querySelect=CATENTDESC.AUXDESCRIPTION1,

2) Run preprocess with server stopped, and then start server and build Solr index
Newly included field can be validated using the Solr testing URL-
http://localhost/solr/MC_10001_CatalogEntry_en_US/select?q=catentry_id:<catentryId>

3) Make the new search profile in wc-search.xml by extending the existing search profile invoked in the REST service call under Search folder-
<_config:profile name="X_findCatalogEntry" extends="IBM_findProductByIds_Details">
       <_config:query inherits="true">
           <_config:postprocessor           classname="com.ibm.commerce.foundation.server.services.rest.search.postprocessor.solr.SolrRESTSearchCatalogEntryViewUserDataQueryPostprocessor" />
       </_config:query>
       <_config:result inherits="true">
               <_config:field name="auxdescription1" />
       </_config:result>   
    </_config:profile>

4) Make the new wc-component.xml under Search folder ext folder- (It takes care of the mapping we used to have it under wc-business-object-mediator.xml prior to version 7 feature pack 7)

<?xml version="1.0" encoding="UTF-8"?>
<_config:DevelopmentComponentConfiguration
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.ibm.com/xmlns/prod/commerce/foundation/config ../xsd/wc-component.xsd "
    xmlns:_config="http://www.ibm.com/xmlns/prod/commerce/foundation/config">

    <_config:valuemappingservice>
        <_config:valuemapping externalName="CatalogEntryUserDataFieldNameMapping" internalName="CatalogEntryUserDataFieldNameMapping">
                <_config:valuemap externalValue="AUXDESCRIPTION1" internalValue="auxdescription1" />
        </_config:valuemapping>
    </_config:valuemappingservice>
</_config:DevelopmentComponentConfiguration>


5) Make the new wc-rest-resourceconfig.xml file under /Search-Rest/WebContent/WEB-INF/config/com.ibm.commerce.rest-ext/wc-rest-resourceconfig.xml
 
<ResourceConfig>
    <Resource name="productview">
        <GetUri uri="store/{storeId}/productview/byId/{productId}"
                description="Get product by unique ID"                 searchProfile="X_findCatalogEntry,IBM_findProductByIds_Details,IBM_findProductByIdsWithAttributesAndAttachments,IBM_findProductByIds_Summary,IBM_findProductByIds_Summary_WithNoEntitlementCheck,IBM_Admin_findProductByIds"/>
    </Resource>
</ResourceConfig>

6) Restart the server and access the new indexed fields in userdata section using rest call with new search profile.

7) Testing
http://localhost/search/resources/store/10158/productview/byId/121892?responseFormat=xml&catalogId=10158&currency=USD

Wednesday, November 30, 2016

B2B Contracts

Contracts
A Contract helps defining the terms & conditions for the online customer. It becomes very crucial in setting up the different shopping experiences on the same online store for different buyer accounts in B2B setup.

These T&Cs modify the online customer's shopping experience including-
Products entitlement,
Price entitlement,
Shipping and payment options,
Permissible order limit.

1. A contract can either be assigned to Member group or Organization.

2. Buyer can have multiple contracts setup and active during the shopping session and he can even avail distinct contracts for distinct orderitems of the same order(OrderItems.TRADING_ID & TERMCOND_ID) provided that the contracts are compatible against each other(OrderItemBaseCmdIml-> validateTradingPaymentMethods()).

3. ContractSetInSessionCmdImpl command helps to setup a particular contract during shopping (out of various active contracts created for the buyer organization) which is ultimately saved inside EntitlementContext context of Ctxdata table

Types
1) The default contract
A store has a default contract which allows guest and unregistered shoppers to shop in the store
            Storedef -> Store default contract & default shipmode (Buyer default contract through Contract.Usage column 0 value)
2) A base contract
Can be shared by many contracts
3) A customer contract.
A customer contract is one that has a Buyer participant

Data Model
STOREENT(STOREENT_ID) -> ORGENTITY(STORE OWNER) -> ACCOUNT(ACCOUNT_ID) -> TRADING(TRADING_ID)  -> PARTICIPNT

Store Contracts (STORECNTR)
    Store -> Contracts
Business Accounts (ACCOUNT)
    Store -> Accounts
Participants (PARTICIPNT)
    Buyer organization -> Contracts
Terms and Conditions (TERMCOND)
    Contract -> Terms & Conditions


Storcntr- Contains all contracts deployed in the store
Contract- Base table for contract
Account- Represents a business account between a Buyer organization and a Seller organization
Participnt- Contains the Buyer organization and Contract relationship
Trading- Contract is a specific type of trading
TermCond- Contains all the terms and conditions associated with the contract such as Price rule, Catalog filter, Price list, Payment and Shipping method, Approval required etc.
Catfilter- Base table for catalog filter
Pricerule- Base table for the price rule
Expression- Contains the solr runtime expression for the contract.
Tradeposcn- Contains the price list details

Creating Contracts
1. Simplest way is to create a contract using accelerator,
2. We can also create a contract by extracting/loading the XML,
3. Creating a new version of a contract,
4. Creating a contract through custom dataload utility.


TermCond Mapping
TermCond table contains a number of generic columns used to store information about terms and condition with different terms and conditions use the columns differently. Each mapping shows how the information in the XML elements of the terms and conditions map to columns in the TERMCOND table-

PriceRuleTC
CatalogFilterTC
PriceTCMasterCatalogWithFiltering
ShippingTCShipToAddress
ShippingTCShippingMode
ShippingTCShippingCharge
OrderApprovalTC
RightToBuyTCByAmount
ObligationToBuyTCByAmount

Price List, Price Rule & Contracts
A very prominent usage of contracts in B2B system is to utilize it to setup the multiple pricing tier for the buyer aligned under different buyer organizations.

Price list can be created and assigned to the contract through price rule allowing the different set of buyers to avail different prices for the same products.
For a price rule to display offer prices on store pages, you must assign the price rule to a contract.

BUYER -> BUYER ORG -> CONTRACT <- PRICE RULE <- PRICE LIST <- PRICE

After you assign the price rule to a contract, customers shopping under the contract see and are entitled to prices from the price rule. Remember a price rule is one of many terms and conditions that a contract can have.

Tables-
PRICERULE: Each row of this table represents a price rule in a store. Price rule is a business rule which defines how to get a dynamic price under different business conditions
PRELEMENT: Each row of this table represents a price rule element.
PRELETEMPLATE: Each row of this table represents a price rule element template
PRELEMENTATTR: Each row of this table represents a price rule attribute in name value pair. P.S: This table maps the price rule of termcond table with actual price list in tradposcn table.

Data Flow-
CONTRACT -> TERMCOND(STRINGFIELD1) -> PRICERULE -> PRELEMENT -> PRELEMENTATTR -> TRADEPOSCN -> OFFER -> OFFERPRICE -> ACTUAL PRICE

CMC provides support for-
Price Rule,
Price List

UseCase: Applying Multiple Tier Pricing for different buyer orgs
Export an existing price list and then upload it again after modification as a new price list through CMC.
Now create a price rule to make use of this new price list
This price rule can be applied to a contract through accelerator
User logging into the buyer organization can avail the special pricing through the contract.

Catalog Filter and Contracts
Another prominent usage of contracts in B2B system is to utilize it to setup the multiple catalog tier for the buyer aligned under different buyer organizations.

Catalog filter can be created and assigned to the contract which allows the buyer to shop for the filtered items in the e-site.  
BUYER -> BUYER ORG -> CONTRACT <- CATALOG FILTER <- CATALOG ENTITY

Data Flow-
CONTRACT -> TERMCOND(BIGINTFIELD1) -> CATFILTER -> CFCATGROUP -> CFCONDGRP -> CFCOND -> CFCONDVAL

We can use catalog filters for the product entitlement, that is, to entitle customers to a subset of the catalog

Note: We can create catalog filters to filter objects for only our master catalog. We cannot create catalog filters for a sales catalog. So if we apply the catalog filer to the master catalog it eventually retrieves the entitled products from the sales catalog.

Catalog Filter Tables-
CATFILTER - Each row of this table represents a catalog filter.
CATFLTDSC- Each row of this table represents a language specific description of a certain catalog filter.
CFCATGROUP- Each row represents a selected catalog group in the catalog tree.
CFCONDGRP- Each row of this table represents a condition group in a certain catalog filter
CFCOND- Each row of this table represents a condition in a certain condition group
CFCONDVAL- Each row of this table represents the association between a condition and an attribute value.
PRODUCTSET- This table holds the definition of a product set. The actual representation of the product set is held in the PRSETCEREL table.
CFPRODUCTSET- Each row represents the relationship between a catalog filter and a product set used for filtering.

Unit Testing Contracts Filtering
Expression table entry helps building the solr expression for debugging  for catalog filter or productset-

e.g.
http://server/solr/MC_10001_CatalogEntry_en_US/select?q=*:*&fq=catalog_id:"11111"&fq=storeent_id:("22222" "33333")&fq=published:1&fq=((( +*:* -*:*) productset_id:("55555555") ) productset_id:("44444444") )