In a subscription business model, a customer has to pay a subscription price to have access to a product or service. The model was started by magazines and newspaper businesses and is now used by many ecommerce sites. OFBiz, as a powerful ERP framework, supports subscriptions business model.

Subscription types that OFBiz supports OOTB are Newsgroup, Product Info, Product and Others. In this article we will cover a basic overview of how OFBiz handles Subscription Products which may be a digital product or a service.

How do subscriptions work in OFBiz and Opentaps?

In subscription business model, organization can have many goods/services to sell like Newsletters, e-magazines etc and customer has to subscribes these products which may be of different time periods like a week, a month or a year (OFBiz supports many UOMs for time period OOTB to facilitate subscription model). We have to setup a single product for each of the subscription period that is three different products corresponding to each subscription time period.

Below are the basic steps to configure subscription for a digital product -

1. Create a product of type DIGITAL_GOOD.

2. Create SubscriptionResource record – We will have to create a record for each content resource, such as a file or a set of files, or a publication etc.

3. Now associate this SubscriptionResource with your Product by creating ProductSubscriptionResource record. Here you can specify how much time and to what resources the customer is entitled to when they purchase the Product.

4. When customer purchases this product system automatically creates a Subscription record which keeps a track of entitlement to SubscriptionResource for a certain period of time i.e. history of what was purchased, use to check permission to access etc.

5. After customer has purchased this subscription product, now for actual fulfillment of this digital good we need to define logic according to our requirement. This can be done by writing a new service and put it in serviceName field in Content entity which is associated to SubscriptionResource. In this external service, one can define logic how they want to serve the Subscription (subscription may be a product or a service) via sending an email to customer or by giving them access to download it from the site according to the time period of the subscription.

Subscription data model also supports the useCountLimit and with some customization we can limit number of users who can access the subscription resource well. Above is just a basic overview of how OFBiz handles Subscription products.

Now, we will cover the fulfillment process in detail with some use cases like automatic extension of Subscription.

Some screen shots to manage subscriptions -
1. Catalog Manager->Subscriptions — Search Options/Search Result for Subscriptions – http://screencast.com/t/JMHNdtDB0

2. Catalog Manager->Subscriptions->New Subscription – http://screencast.com/t/WIMgRObTjr

3. Catalog Manager->Subscriptions->on Search Result list click the subscription you want to edit – http://screencast.com/t/mrX1k8Zk

4. Catalog Manager->Subscriptions->Find Subscription Resource – http://screencast.com/t/miU4MPdpuUqd

5. Catalog Manager->Subscriptions->Find Subscription Resource->New Subscription Resource – http://screencast.com/t/K9tu1d7wLZqw

6. ProductSubscriptionResource can be Added/Edited from here – http://screencast.com/t/Yw6sWqxx6

Subscription Types -

1. Free Subscriptions – Subscriptions which are free and its time duration is lifetime unless user unsubscribes. This has been implemented using Contact List facility. Example is Newsletter subscription.

2. Paid Subscription – Subscriptions for which customer has to pay for each subscription that is they have to place an order. Time period of subscription is predefined and later it can be extended according to customer’s need.

What is available OOTB -

Subscription Data Model is completely available OOTB. It means all the required entities and their relationships are already there. This model can support almost all the common use cases for subscription business model. Almost all the core CRUD services are available corresponding to subscription entities.

What is not available OOTB -

Except for the free Subscription type mentioned below, everything else is not 100% complete. We need minor customization per the business requirement. Only few use cases are supported by code that are available OOTB, and for remaining use-cases services that implement the business logic are missing, however data models are in place.

Use cases -

Below uses case is the one which is mostly supported OOTB but it is not 100% complete. Environment -

A. Subscription product is a DIGITAL_GOOD and

B. It is content managed. We can content manage a binary file which could be software/pdf file or any text content.

C. Product’s content type is ONLINE_ACCESS which means customer will have to access it online. For this scenario almost all the required business logic is there but the missing part is how they are going to serve this subscription. Complete front-end UI is missing and process is not clear that how customer will access it online, how we are going to check the access permissions. There can be many ways to serve it but it is not available OOTB and this needs to be implemented.

Various Subscription related fields and their purpose -

Subscription.automaticExtend - If this flag is set to Y then only that subscription record will be eligible for auto extension. This is basically set in ProductSubscriptionResorce entity and from there it gets populated in Subscription entity when an Order gets placed.

Subscription.useTime – The length of time this subscription can be used. It is a numeric value so it has an association with useTimeUomId.

Subscription.fromDate – Date from which this Subscription is going to be active.

Subscription.thruDate – Date after which this subscription is going to be expired.

Subscription.purchaseFromDate – Date from which subscription can be purchased.

Subscription.purchaseThruDate – Date after which subscription cannot be purchased.

Subscription.maxLifeTime – The length in time of the Subscription. This time period is set actually in ProductSubscriptionResource entity and from there it gets populated to Subscription entity.

Subscription.availableTime – It may be used for systems in which time can be consumed, so it can be total time consumed.

Subscription.useCountLimit – It can be used to count that how many times subscription has been used.

Subscription.canclAutmExtTime – The time period (before the end of the thrudate) after which the automatic extension of the subscription will be executed.

Process flow of Subscription business model in OFBiz -

Subscription extension is processed by SECA service “processExtendSubscriptionByOrder” which is initiated by order service “changeOrderStatus” where conditions are statusId is ORDER_APPROVED and orderTypeId is SALES_ORDER.

Case I: Customer places an order and if this customer already has subscribed to this subscription, then a new subscription record gets created corresponding to this new order but subscription period dates are calculated on the basis of last subscription that customer already has. For example – if customer has already purchased subscription GZ-NEWS-1MO, which is one month subscription and this subscription is from date as 2010-11-25 15:26:45.000 and thru date as 2010-12-25 15:26:45.000, Now in this period if customer again places an order for the same subacription then a new subscription record will get created whose subscription period dates will be fromDate=010-12-25 15:26:45.000 thruDate=2011-01-25 15:26:45.000.

Case II: Customer places an order for the same subscription but the order date is after the thruDate of the last subscription then from date of the new subscription record will be fromDate=nowTimeStamp thruDate=fromDate+(useTime * ordered quantity of subscription item). For our example subscription useTime is 1 that is one month because useTime’s UomId id is TF_Mon and quantity is 1 .

Case III: Customer places an order but this is first time this user is buying this Subscription so in this case a new subscription record will get created for which time period dates will be fromDate=nowTimeStamp thruDate=fromDate+(useTIme * ordered quantity of subscription item) Variables that can affect this process – 1. Indicator alwaysCreateNewRecord (Y/N) = if alwaysCreateNewRecord is null or Y then it always create a new subscription record in each of the above case. But if it is set to N then in case I, II it simply updates the orderId and old subscription’s dates that is fromDate and thruDate.

Case IV: Automatically extend subscription with recurring payment – There is a scheduled service “runSubscriptionAutoReorders” which runs every midnight (OOTB setting). This service goes through each subscription record for which indicator automaticExtend is set to “Y”. For each subscription record it checks conditions on below time period fields – Subscription.canclAutmExtTime = The time period (before the end of the thruDate) after which the automatic extension of the subscription will be executed. Subscription.thruDate

Scenario I: canclAutmExtTime and canclAutmExtTimeUomId is not null and nowTimeStamp+canclAutmExtTime BEFORE thruDate implies that this subscription is not expired yet so it doesn’t do anything.

Scenario II: canclAutmExtTime and canclAutmExtTimeUomId is not null and nowTimeStamp+canclAutmExtTime AFTER thruDate which implies that subscription is expired so for all such subscriptions it calls service “loadCartFromOrder” and it takes in account only those orderitems which are of subscription type and then it creates order. Once order gets created then it initiates the payment authorization process by calling CheckoutHelper.processPayment method. As soon as the order gets created, its status changes to ORDER_APPROVED then on changeOrderStatus service a SECA service “processExtendSubscriptionByOrder” gets called. This services extends the subscription and the new record gets automaticExtend flag set to ‘Y’ Variables that can affact the process

1. Indicator automaticExtend (Y/N) = If this flag is set to Y then only that subscription record will be eligible for auto extension. Notes regarding how content managed subscriptions are handled in OFBiz – This is the case in which customer subscribes for a product which has a content managed resource associated with it and according to the subscription period customer is assigned role/s for that content. OOTB OFBiz supports only product which has content that can be accessed online that is productContentTypeId=”ONLINE_ACCESS”, Refer ContentManagementServices.java , service updateContentSubscriptionByOrder). Process flow – Customer places an order for subscription and when this order gets status ORDER_APPROVED then a SECA “updateContentSubscriptionByOrder” gets called on “changeOrderStatus”. In this service it iterates order items of this order and process only those items which has associated product content of type productContentTypeId=”ONLINE_ACCESS”. For each such product it calls “updateContentSubscriptionByProduct” here it filters records on basis of condition that order created date should be between “purchaseFromDate” and “purchaseThruDate”. Then it calls the service “updateContentSubscription” where it creates or updates the ContentRole record.

Case I – If customer has already subscribed for that content and any extension to this subscription has taken place by auto re-ordering of that subscription then it updates existing ContentRole records and changes its fromDate and thruDate corresponding to that customer party.

Case II – If this is the first time customer is placing an order for this subscription then it creates new record of ContentRole for that party with fromDate and thruDate according to the subscription period that is useTime and useTimeUomId values. After this it creates PartyRole record. There can be different ContentRoles for a content and in ProductContent entity we have this field useRoleTypeId where we can define this role, so when we call “updateContentSubscriptionByOrder” means according to the subscription’s time period customer is assigned a role for that subscription content. So, for example, if a customer subscribes for a resource just for read only purpose then we will assign role specific for read only purpose.

NOTE:

1. fromDate and thruDate manipulations are done the same way as it is done for Subscription records.

2. OOTB there is not functionality or UI available that how subscribed content is going to be served to the client, and how access permission will be granted to customer. We can define our own service which is going to serve the digital content. We can define it in entity field Content.serviceName. There is a service “fulfillDigitalItems” which uses this external service Content.serviceName for fulfillment.

3. Per our knowledge except cases mentioned in all my docs are incomplete or not available. Some of which are tracking of subscription activity, subscription fulfillment piece, use of subscription attributes etc.

Demo Data -

There is OOTB demo data available for 2 products – GZ-NEWS-1MO and GZ-DIG. We will test against a new digital product – GZ-DIG-TEST.

  <!-- Below is the product data you need to import for demo -->
<!-- Test product for content based subscription product which is of type Online access -->
 <Product productId="GZ-DIG-TEST" productTypeId="DIGITAL_GOOD" primaryProductCategoryId="101" productName="Digital Gizmo Test" internalName="Digital Gizmo Test" description="A digital gizmo: can be downloaded immediately after purchase." longDescription="This gizmo is part of an exciting new breed that needs no corporeal form: it is all digital! Buy and download it now!" taxable="Y" chargeShipping="N" autoCreateKeywords="Y" isVirtual="N" isVariant="N" createdDate="2001-05-13 12:00:00.0" createdByUserLogin="admin" lastModifiedDate="2001-05-13 12:00:00.0" lastModifiedByUserLogin="admin"/>
 <DataResource dataResourceId="GZ-DIG-TEST" dataResourceTypeId="OFBIZ_FILE_BIN" mimeTypeId="image/gif" dataResourceName="Digital Gizmo Image" objectInfo="framework/images/webapp/images/ofbiz_logo.gif"/>
 <Content contentId="GZ-DIG-TEST" contentTypeId="DOCUMENT" dataResourceId="GZ-DIG-TEST" mimeTypeId="image/gif" contentName="ofbiz_logo.gif" description="Image of Digital Gizmo (actually the OFBiz logo)"/>
 <ProductContent productId="GZ-DIG-TEST" contentId="GZ-DIG-TEST" productContentTypeId="ONLINE_ACCESS" fromDate="2001-05-13 12:00:00.0" useTime="3" useTimeUomId="TF_mon" useRoleTypeId="CONTENT_ADMIN"/>
 <ProductPrice productId="GZ-DIG-TEST" productPricePurposeId="PURCHASE" productPriceTypeId="DEFAULT_PRICE" currencyUomId="USD" productStoreGroupId="_NA_" fromDate="2001-05-13 12:00:00.0" price="55.99" createdDate="2001-05-13 12:00:00.0" createdByUserLogin="admin" lastModifiedDate="2001-05-13 12:00:00.0" lastModifiedByUserLogin="admin"/>
 <ProductPrice productId="GZ-DIG-TEST" productPricePurposeId="PURCHASE" productPriceTypeId="LIST_PRICE" currencyUomId="USD" productStoreGroupId="_NA_" fromDate="2001-05-13 12:00:00.0" price="80.0" createdDate="2001-05-13 12:00:00.0" createdByUserLogin="admin" lastModifiedDate="2001-05-13 12:00:00.0" lastModifiedByUserLogin="admin"/>
 <SubscriptionResource subscriptionResourceId="GZ-DIG-SUBRES" description="GZ-DIG Subscription Resource" contentId="GZ-DIG-TEST" webSiteId="WebStore" lastUpdatedStamp="2010-11-23 16:56:21.0" lastUpdatedTxStamp="2010-11-23 16:56:21.0" createdStamp="2010-11-23 16:56:21.0" createdTxStamp="2010-11-23 16:56:21.0"/>
 <ProductSubscriptionResource productId="GZ-DIG-TEST" subscriptionResourceId="GZ-DIG-SUBRES" fromDate="2010-11-29 17:21:56.0" useTime="1" useTimeUomId="TF_mon" automaticExtend="Y" canclAutmExtTime="2" canclAutmExtTimeUomId="TF_wk" lastUpdatedStamp="2010-12-22 17:37:04.0" lastUpdatedTxStamp="2010-12-22 17:37:04.0" createdStamp="2010-11-29 17:24:05.0" createdTxStamp="2010-11-29 17:24:05.0"/>

NOTE:

1. Currently we have given ProductContent.useRoleTypeId=”CONTENT_ADMIN”, we can create seed data for content roles according to our business need. For example, here we can define new content role for read only purpose so customer can only read that online.

2. ProductContent of productContentTypeId=”ONLINE_ACCESS” and productContentTypeId=”DIGITAL_DOWNLOAD” are treated differently.

3. Go to E-commerce site main page -> Quick Add -> Enter Product Id -> and the start the process to place an order, due to some reason this test product is not showing in category on main page.

4. Then go on Catalog Manager -> Subscription -> press Find. It will show you the list of Subscriptions. Please refer to the screen shots listed above.

Pointers for code flow for content based subscription-

1. look at SECA “updateContentSubscriptionByOrder” on service “changeOrderStatus”. updateContentSubscriptionByOrder -> updateContentSubscriptionByProduct -> updateContentSubscription (ContentManagementServices.java)