Not yet rated

Problem

Order management - workflow that allows users to place their order and being informed about order realization progress.

Solution

Sample process with dynamic PDF forms. It also generates watermaked, signed pdfs, that will be send as a confirmation

Detailed explanation

Recipe structure

  • In the first section there is a short description of a form and processes that will be created later.
  • In the second section there is a detailed instruction how to create application.

 

Form and Processes description

OrderForm short description

OrderForm is a PDF form used as a data input and output interface and as a process starting point.

It allows user to enter order data like client data, order positions etc. It reacts dynamicly to data changes (eg. change unit price when product has changed, recalculates total price when new product is added etc.).

 

Order management - workflow that allows users to place their order and being informed about order realization progress.

OrderProcess description

It is the main process in the application. It start when user submits form in workspace. Then orderId is assigned and order waits for the acceptance by at least 50 % memebers of selected user group. If at least one user rejects order process send that information using SendPdfProcess(se description below) and ends.

After approving order system also invokes SendPdfProcess and then decides(based on orderAmount) wheter it should wait for the payment first or can prepare and send and order.

If orderAmount is less than 300 it moves to CompleteOrder task in which user from Warehouse department completes order. Afterwards process goes to Accounting in which it stays until order is payed.

If orderAmount is greater than 300, payment have to be confirmed before sending it. So the process goes to Accounting first and waits for the confirmation. If no confirmation is made during 7 days or it is manually canceled by an operator process sends a suitable message using SendPdfProcess. When operator confirms payment process moves to the Warehouse when order is completed and send.

At the end order is given completed status and a suitable message is send to the orderer.

Order management - workflow that allows users to place their order and being informed about order realization progress.
 

SendPdfProcess description

This is a small helper process, which aim is to create a pdf form (using MarkAndCertifyProcess) and sents it in mail to the given recipient.

Order management - workflow that allows users to place their order and being informed about order realization progress.
 

MarkAndCertifyProcess

The aim of this process is to create a watermark, certified static pdf from given data and pdf template.
Firstly it renders active pdf, which is then converted into a static one. Next watermark is applied using AssemblerService and finally pdf is signed by SignatureService. 

Order management - workflow that allows users to place their order and being informed about order realization progress.

 

Creating application

First of all we create a new application (menu File->New->Application)  with the name "OrderManagementApp". As you can see Workbench has created new application with new application version (1.0). Then we create directory structure:

  Order management - workflow that allows users to place their order and being informed about order realization progress.


Afterwards we import prepared XML Schema (schema.xsd) into resources/xsd using import method from File menu or by simply draging file into destination.

To save application to the server we right-click on the application version and select deploy. 

Creating PDF form

If you don't want to create form, you can use one from the attachements. 

Right-click on the pdf directory and select New->Form. Name it OrderForm and select Next. Then choose "Select a data model from a LiveCycle application" and select imported schema.xsd file. On the next screen select both Form Submission forms (Livecycle Workspace and email) and select next. Now LiveCycle Designer will open. Proceed to the 3 screen and change Form type into pdf.

On the left side there is a Hierarchy view. Navigate to Data view and right-click on the existing DataConnection and select ConnectionProperties. On the second screen change value in combo box from Name into Order and select finish. Now you can see that Data view has changed. Now it depicts an Order object stucture.

Order management - workflow that allows users to place their order and being informed about order realization progress.

In the next few steps we will create fields on the form by draging object from the data view. It is faster then inserting fields from Object library because after draging fields will be binded to a suitable XML element.
First of all we change page layout by selecting page and setting it in Object->Subform view to flowed

Order management - workflow that allows users to place their order and being informed about order realization progress.

Order management - workflow that allows users to place their order and being informed about order realization progress.

Next we add new subform by simply clicking on a page 1 on a hierarchy a choosing insert subform.Change the name of new subform to header and place it on the top of the page and expand it to the page width. From the Object Library (should be on your right) drag Text element and place it in the center.

Change displayed text into Order Form and increase its size. Now your pdf should look like this one.


Order management - workflow that allows users to place their order and being informed about order realization progress.


Change view to Data view and drag IdOrder field and place it under Order Form text. Set this field as read only (Object ->Value->Type) As you can see in the Data View new icon has occured. It tells you that this data is connected to a field which means, that during export or form submision data will be assigned do IdOrder element.

Next create new section (name it ClientSubform) with border under Header and expand it to the screen size. To add border to this section go to Border (if you can see it righ-click on the object and select Border ) and set one (In attached example border is Dashed with circural corners). Drag Client to this section and organize it (see picture). Increase section size so there is a place for a check box (drag it from object library) and ShipmentAdress (drag it from Data view). Change chebox label to :"Different shipping adress". and label position to left in Layout view(if you can see it righ-click on the object and select Layout ). Add extra label saying "Client Details"
Order management - workflow that allows users to place their order and being informed about order realization progress.

Add new section called "TableSubform" with border and expand it. Then add table from the object library with six columns, one row, header and footer row. Add extra footer row(right-click on hierarchy) below existing one and name it FooterRaw1. Select TableSubform and set its content(Object->Subform) to flowed. Also set its marigin (Layout view) so that table stays in the center.

Then select table and set its border to None. Click on Row1 and set it binding(Object->Binding) to $.OrderLines.OrderLine[*] and select "Repeat Row for Each Data Item".

Now drag each of the element from OrderLine (Data View) to te cell in Row1. Next add a suitable header for each collumn. Add a buttun to the last column and name it "Delete" and remove header from this column.

Make cells(onlu from Row1) from Id, UnitPrice and Price columns readOnly. Also make cell TotalPrice readOnly.

Change ProductId cell into Drop-down List. Also change collumn header into Produc Name.

Change all cell types in FooterLine (the first one) into textField by selecting them all and changing in Object->Cell->Type. While selected, remove binding (set "No data binding") and make them read only (Object->Value->Type).

Drag totalPrice fiield into field in the second footer in Price column. In the left cell write . Select the remaining four cells from that footer and remove their border.

Now add last section into form and name it "AddSubform" and place there AdditionalInformation field. Make this field big and select it as a multiline (Object->Field->AllowMultiple Lines)

Now your form should look nearly like attached one.

Making form dynamic.

Auto price for product

First of all add some products into ProductId drop-down list (Object->Cell->List Items) and select Specify Item Values (Object->Binding). In that way xml wil contain only this values not, text names.
Open change event and add the following code there. If you entered more values into productId drop-down than in prices Array extend it.
Order management - workflow that allows users to place their order and being informed about order realization progress.

var txt = xfa.event.newText;
var ind = (-1);
for( var i = 0; i < this.items.nodes.length; i++ ) {
if( this.items.nodes.item(i).value == txt ) {
ind = i;
break;
}
}
var prices = new Array(4,11,2,3,1,7,5,9,10,14);
UnitPrice.rawValue = prices[ind];

Now when user selects product from drop down list its price is automatically into suitable field. In order to calculate order line price add the following code(on Price cell set calculate script(don't forget to change Langugage to FormCalc!!!)), that will multiply single product price by product count

UnitPrice*Quantity

Total order price calculation

To calculate total price we need to sum all line prices. To do so on totalPrice cell set calculate(change Langugage to FormCalc!!!) to: 

Sum(Row1[*].Price)

Adding more lines to order

On default this form has one line, in order to add more user has to to click on the empty footer line. To make this work you need to set on all cells int FooterLine click script to() :

_Row1.addInstance(1);

Also on delete button set click script to:

this.parent.instanceManager.removeInstance(this.parent.index);

xfa.form.recalculate(true);

Line index autocalculate

On LineId cell set calculate script(set Langugage to FormCalc!!!) to:

this.parent.index + 1

Hidding delete line button

When cell IdOrder is not empty it means, that order was submitted, so there it shouldn't be changed. To do so set initialize script on that button to:

if(header.IdOrder.rawValue != null){
this.presence = "invisible";
}

Showing/hidding shippment adress depends on checkbox status

On ShiplmentAdress field set Initialize event to:

this.presence = "hidden";

It will make that text field invisible on startup. On CheckBox1 set click event script to:

if (ShipmentAdress.presence == "hidden"){

ShipmentAdress.presence = "visible";

}else{
ShipmentAdress.presence = "hidden";
ShipmentAdress.rawValue = "";
}

so that after clicking it, text field magically appears.

Disabling fields

On page1 subform set initialize event script to :

if(header.IdOrder.rawValue != null){
ClientSubform.Client.Name.access="nonInteractive";
ClientSubform.Client.Name.mandatory="disabled";
ClientSubform.Client.Surname.access="nonInteractive";
ClientSubform.Client.Surname.mandatory="disabled";
ClientSubform.Client.Email.access="nonInteractive";
ClientSubform.Client.Email.mandatory="disabled";
ClientSubform.Client.Date.access="nonInteractive";
ClientSubform.Client.Date.mandatory="disabled";
ClientSubform.Client.Adress.access="nonInteractive";
ClientSubform.Client.Adress.mandatory="disabled";
ClientSubform.Client.CheckBox1.access="nonInteractive";
ClientSubform.Client.CheckBox1.mandatory="disabled";
ClientSubform.Client.ShipmentAdress.access="nonInteractive";
ClientSubform.Client.ShipmentAdress.mandatory="disabled";
TableSubform.Table1.Row1.ProductId.access="nonInteractive";
TableSubform.Table1.Row1.ProductId.mandatory="disabled";
TableSubform.Table1.Row1.Quantity.access="nonInteractive";
TableSubform.Table1.Row1.Quantity.mandatory="disabled";
AddSubform.AdditionalInformation.access="nonInteractive";
AddSubform.AdditionalInformation.mandatory="disabled";

}

Setting fields as required

Finally set fields Name, Surname, Email, BirthDate, ProductId, Quantity as reqired (Object->Value->Type->User entered-Required) and add exit script:

if(this.rawValue != null){
this.mandatory = "disabled";
}else{
this.mandatory = "error";
}

Adding this code, is a cosmetical trick that will remove red required border, when field is filled.

Finished.

 

Creating MarkAndCertifyProcess

Create new process ( File->New->Process ) named MarkAndCertifyProcess in processes->helper directory. It should have only default start point, because it will be invoked from other processes only.

First of all we need to add process variables(on the variable section (bottom) select plus sign) according to this list (name- type-purpouse):

  • - watermark - string - input
  • - pdfTemplate - document - input
  • - pdf - document - output
  • - data - xml - input
  • - assResult - AssemblerResult - nothing selected

 

Next add new operation (by dragging and dropping activity picker (gray rectangle with a orange star) ) called "renderPDFForm". Double click it and view its properties on the left side. In the Input section select:

  • - Form -> pdfTemplate variable (in the left corner change the value type from literal value to variable)
  • - Form Data -> data

 

In the Output section select: Rendered Form -> pdf

Next add "transformPDF" action. In input section select pdf variable as a Input PDF document. Also assign output to pdf variable. 

Next step is an adding watermark. First we create new assembly descriptor from template in ddx directory (File->New->Assembly Descriptor) with name WatermarkDDX. Remember to select initial content as Dynamic Watermark Example. You can test it by using Preview Result. Remember to use static pdf!
In order to use this assembly descriptor, we need to ask new operation called invoke DDX. In the input section select created ddx file as a "Input DDX Document". Afterwards refresh next section and assign pdf variable to sourcePDF key(you should see /process_data/@pdf) and watermark variable to watermarkString key. Don't forget to assign Assembler Result to assResult variable. 

In the next step we need to extract pdf document from Assembler result. To do that, add setValue operation and create assigment(Location - Expression) /process_data/@pdf - /process_data/assResult/object/documents.
Last operation to add is Certify PDF. In the common section select pdf variable as a Input PDF and in Certyfying Credential choose one you would like to use (for developmen you can choose on from existing). Assign output to the pdf variable. 

In the end you can connect all operation in a row.

Testing

To test this process simply deploy application and select right-click and select invoke. 

Select OrderForm.pdf file for pdfTemplate and arbitrary text for watermark. Data field can be left blank. As a result you can see watermaked, signed pdf.

Creating SendPdfProcess 

Create new process named SendPdfProcess with default start point only. Add 7 variables:

  • - watermark - string- input
  • - pdfTemplate - document - input
  • - pdf - document - output
  • - emailSubject - String - input
  • - emailMessage - String - input
  • - emailAdress - String - input
  • - data - xml - input

 

Add activity called MarkAndCertifyPdfProcess (process we just created) and assign(names are equal) its input and output variables to process variables. 

Next add activity called Send With Document. Fill in suitable input variables (put pdf variable as an attachment). In From Adress section you can put adrres from which mail is send.

Finally connect activities. 

Testing

Before testing this process you have to configure mail server (or if you have one running on localhost:25 use it :)). You can do this either from component view in Workbench or from adminui. We will do the second option. 
Open Adminui (probably your_host:8080/adminui ) and log in. Navigate to: Home > Services > Applications and Services > Service Management > Configure EmailService. Then fill your mail service configuration. 

Creating main Process

Finally we will create main process. Create new process with name OrderProcess(don't click finish now, use next button instead) , next select "When a user submits a task in Workspace" option from the second screen. Next select "Use an existing Form" option and show created previously OrderForm.pdf. On the next screen fill the following: 

  • - Create a New Workspace Category -> OrderManagement
  • - Workspace Process Name -> Place an order
  • - Description -> Click here to place an new Order

 

then click finish. 

First add addtional two swimlanes (right-clik on the existing one and select insert).

Then name swimlanes: Sales, Warehouse, Accounting. Putting activities in swimlanes makes process more legible.

Add new setValue activity in which IdOrder is set. (To make life easier we will use processId). /process_data/OrderData/xdp/datasets/data/Order/IdOrder - /process_data/@id

Order Approval 

Next add Assign Multiple Tasks activity and name it "Order Approval" and connect to the previus activity. Set "Please review this order and approve or reject it." as a Task instruction. In Participant section add new group - "All principals in domain SampleOrganization...." and select Assign to every user in this group. In that way all users from this group will have their seperate copy of this task.
In the Presentation and data section select OrderForm.pdf as an asset and OrderData process variable as a InitialTaskData.
In the Workspace User interface section deselct "Must open the form to complete task". This will allow users to use complete task on their mobiles. Mobile client doesn't allow to open task (However you can preview PDF, thats why we are using it). 

Now hop to the next activities and later return to fill User Action section.
Add two copies of SendPDFProcess and name them: Send Order Rejected Message and Send Order Accepted Message. Using this activities process will send mail to the email adress that was entered by the process initiator. In both activities assign:

  • - data (change from literal value to variable) - OrderData
  • - emailAdress(change from literal value to XPath) - /process_data/OrderData/xdp/datasets/data/Order/Client/Email
  • - pdfTemplate - OrderForm

For the watermark write Order accepted in one case and Order rejected in the other one. The same can be use for email subject, however if you want something more complex you can add IdOrder to this. To do that change emailSubject type to XPath and enter this: concat('Order: ',/process_data/OrderData/xdp/datasets/data/Order/IdOrder ,' was accepted')

Now connect both activities to Order Approval task.

As it was mentioned before, we need to fill UserAction section in Order Approval task. First add two custom names for actions: Approve, Deny. Next select Use completionPolicies and start creating two policies:
Go to Send Order Rejected Message when at least 1 user(s) pick the Deny action.
Go to Send Order Accepted Message when more than 50 % pick the Approve action.
This policies defines, when Order Approval task should finish and which route will be selected. If no policy is defined, all users must complete task, before continuing process.
Now Order Approval task is ready, lets move to the next ones.

Add decision point activity name it: "Wait for payment ?", and connect it with "SendOrderAcceptedMessage".
Then create three Assign tasks (normaln ones, not multiple) and put one in the Warehouse (name it: "Complete order") and two Accounting("Confirm payment", "Confirm payment for sent order") swimlanes. Fill in "Workspace User Interface" and "Presetnation & data section" like in Order Approval. Connect "Confirm payment" and "Complete order" to the Decision point.

As it says in the process description, when order amount is lower than 300, order can be proceeded to the warehouse without waiting for the payment. To do so click on the route name it 'NO'and add condition: number(/process_data/OrderData/xdp/datasets/data/Order/TotalPrice) < 300Name the second route YES. Check whether route evaloution order in the decision point is ok (NO, YES). If no, fix it.

For all Assign tasks (three) select any user in Initial User Selection. For this tutorial it does'nt metter who exactly you select.

Confirm Payment

There will be three possible routes from "Confirm Payment" task: confirmation, rejection, deadline. Add two SendPDFProcess activities and name them: "Send Order Deadline Canceled Message" and "Send Order Canceled Message".Fill them by analogy to the previous ones and connect them to the task.

Add also three setValue activities and name them: "Order status -> dedline canceled", "Order status -> manually canceled", "Order status -> paid". First two connect to the proper SendPDFProcess activities, the third one connect directly to the "ConfirmPayment" task. Finally name route from "Confirm Payment" to "Send Order Deadline Canceled Message" "deadline";

Now in the "Confirm Payment" task open deadline section (first set All button next to the Basic at the top of the properties view ) and select "Enable deadline" and specify deadline value. Also select "Follow a specific route on dealine" option and choose "deadline" route. In user Actions section specify two actions: "confirm"-> "Order status -> paid" and "cancel"->"Send Order Canceled Message".

From "Order status -> paid" add route to "Complete order" task.

Add setValue (name it "Order status -> completed") and SendPDFProcess(name it "Send Order Completed Message" and set input by analogy to the previously filled) activities into Sales swimlane and connect them together.

Complete order

Connect "Complete order" with "Order status -> completed" and "Confirm payment for sent order". Name the second route: "Order status != paid" and add condition /process_data/OrderData/xdp/datasets/data/Order/OrderStatus != 'paid'
Check route evaluation order on the "Complete order" task. "Order status != paid" route must be the first one.

Connect "Confirm payment for sent order" with the "Order status -> completed" activity.

Finally fill in empty setValue activities with analogous values to (this is for "Order status -> paid")
/process_data/OrderData/xdp/datasets/data/Order/OrderStatus - 'paid'

Now you can deploy your application and test in the workspace.
 

Resources

As a attachement to this site you can find zip file with this application. If you want to deploy it straight to the Livecycle just change the extension to .lca and import it to Livecycle. You can also unpack it and use it during making this tutorial.

 


 


+
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

Report abuse

Related recipes