Order confirmation customizations / email templates


#1

I need to customize the process which takes place when an order is successfully placed, and in the case of subscription sales, each time a renewal notification is received as well. Rather than conflate the two issues, let me start by asking about the initial order first.

When a customer makes a purchase in the store, they are sent an “order confirmation” email, and then an “order completed” email. For my purposes, when the “order completed” email is sent that represents the timing of the event I need to detect (confirmed payment). Upon that event, I need to invoke additional business logic, and subsequently send a customized version of that “order completed” email using data generated by the additional process. In my specific use case, I will be generating software license keys (and other related values to be stored in a database), and then those keys need to be added to the email sent so the client can install the software.

So, my questions are:

A) Where in the code is the point that this order completed email is being generated? I’d like to call a custom function or two right at that part of the procedure (at least that superficially seems like a logical place to do so).

B) How do I modify the email template and fill it in with the right data?

Note, that my data will be stored in a database which is external to the primary Scipio db. Must I add OfizBiz style data abstraction (entities?), or is there a reasonable way to “cheat” and just inject strings into some text via generic Java? I’d like to strike a balance between doing this the “right” way per OfizBiz/Scipio design, and doing this the fast way / the way which would be clear and obvious to any random Java developer who knows nothing about this framework per se.


#2

Hi Buvin,

ok, before we get into your specific requirements, let me also quickly say that Scipio ERP is based on an event-driven architecture, so anything you do (database changes, services being triggered, or requests being made) are events that you can hook your own code to. Anytime the event gets triggered, your code will too. Have a quick look at the following documentation for an overview on the overall concepts (and the SECA, EECA, Controller Events and JobSandbox pages too): https://www.scipioerp.com/community/developer/events-actions/

For the purpose of adding additional code once an order is in a specific status, you can either:

a) Use an EECA (entity event condition action) and hook it up to the OrderHeader entity. For example:

   <eca entity="OrderHeader" operation="create-store" event="return">
        <condition field-name="statusId" operator="equals" value="ORDER_COMPLETED"/>
        <action service="myOwnService" mode="sync"/>
    </eca>

b) Or you can use the services that update the order status:

   <eca service="storeOrder" event="return">
        <action service="myOwnService" mode="sync"/>
    </eca>

All that you then have to do is create your own service, that gets triggered on those events (in my example titled"myOwnService") That is much easier than messing with the actual code that triggers the mailing.

Note: there are several status that an order and return goes through, the orderHeader (and returnheader) entity:

Taken from: https://www.scipioerp.com/community/end-user/applications/order-management/


To answer your particular question:

You can actually set your own email templates. There are several ProductStoreEmailSettings configurations in your database, which define what mail templates to use for your emails. You will notice that these point you to screen definition files, which makes it very easy to extend from. So I recommend that you start by copying over those screen definitions into your own *Screens.xml file (inside of your hot-deploy/your-component/widget/ file. If you don’t have a custom shop app yet, you can create one with

./ant create-component-shop-override

Once you got it copied over, you can copy the ftl you need into your components sub directory (I recommend hot-deploy/my-component/templates/email/ and update the location specified in the ScreenWidget file. The original definitions are in applications/shop/widget/EmailOrderScreens.xml. The original templates in applications/shop/templates/email/.

To give you a quick example how that looks like for the order confirmation:

<screen name="OrderConfirmNotice">
        <section>
            <actions>
                <property-map resource="ShopUiLabels" map-name="uiLabelMap" global="true"/>
                <property-map resource="EcommerceUiLabels" map-name="uiLabelMap" global="true"/>
                <property-map resource="AccountingUiLabels" map-name="uiLabelMap" global="true"/>
                <property-map resource="OrderUiLabels" map-name="uiLabelMap" global="true"/>
                <property-map resource="PartyUiLabels" map-name="uiLabelMap" global="true"/>
                <property-map resource="CommonUiLabels" map-name="uiLabelMap" global="true"/>
                <set field="title" value="${uiLabelMap.PageTitleOrderConfirmationNotice}"/>
                <set field="baseEcommerceSecureUrl" value="${baseSecureUrl}${baseWebappPath}"/>
                <set field="allowAnonymousView" value="Y"/>  <!-- this field will instruction OrderStatus.groovy to allow an anonymous order to be viewed by anybody, so the email confirmation screen will work -->
                <script location="component://shop/webapp/shop/WEB-INF/actions/order/OrderStatus.groovy"/>
            </actions>
            <widgets>
                <decorator-screen name="ScipioEmailDecorator" location="component://common/widget/CommonScreens.xml">
                    <decorator-section name="body">
                        <platform-specific><email><html-template location="component://my-component/templates/email/OrderNoticeEmail.ftl"/></email></platform-specific>
                    </decorator-section>
                </decorator-screen>
            </widgets>
        </section>
    </screen>

You can inject your own code here via groovy scripts or your own service that generates and stores the license key for the order by calling a service in the “actions” part of this definition.
The example i gave you already does it with the orderStatus information: component://shop/webapp/shop/WEB-INF/actions/order/OrderStatus.groovy. I recommend taking a quick look at that file, so that you understand how you parse information from the groovy code to your template.

To answer your last question: I would recommend to duplicate the information here, simply for historical reasons (perhaps you can store them as an Order or Subscription Attribute), but there is no necessity. You can also just call your own service that fetches the information outside. You can always cheat, of course, and it all depends on how much effort you want to put into it, but generally speaking, writing your own service to fetch information and store it to and another one to fetch information from scipio sounds like a good exercise regardless.