Thursday, 30 April 2009

Agency Management

Agency Management often gets left to internally built systems - there are not the same number of systems vendors providing AMS systems as there are those that provide Policy Admin or other components. Further, the business rules around Agency Management are difficult to standardise into an off-the-shelf piece of software. And every insurance company seems to have decided that there are a couple of rules that provide them with a particular competitive advantage compared to how other companies manage their agency channel...

Functionality
So what is included in an AMS?
  • Agency Master record (individual details, addresses, bank accounts, etc)
  • Hierarchy Management
  • Training and Competency - qualifications, regular retraining, etc
  • Commission Generation, both basic and overrides, bonuses, etc
  • Loans
  • Competitions and campaigns
  • Management Reporting (including "Top 10" style reports)

Usually there will be some level of integration to an Agency Portal, or alternatively there will be portal functionality built into the system. This will allow the agent to see information on their commission/loans/points, plus information on their customers and their policies.

Vendors
Some companies that do offer Agency Management Systems:
  • Redland Business Solutions (UK)
  • Mastek (India)
Most of the main systems vendors (e.g. CSC, Bravura) have some level of agency functionality within their systems, however it is usually fairly basic. Key areas missing are override structures, competitions, loans, etc). Because the focus of these vendors is actually on Policy Administration, the functionality tends to stop at the point of generating the basic commission.

Monday, 27 April 2009

Tom Peters

A great quote from Tom Peters:

Whoever tries the most stuff and screws the most stuff up and most rapidly launches the next try wins. Failures are not to be 'tolerated,' they are to be celebrated.

Oracle and Sun

The Financial Times tech blog has an interesting take on the recent deal, particularly in how it may impact on Java. Interestingly IBM has "preferred customer" status for Java licensing, with current arrangements protected until 2016.

Saturday, 25 April 2009

Useful Seam Tip - Page Actions

The page-action tag is a useful way of settings things up in the backing bean, ready for rendering the page. However, it' important to note that the page action is re-fired on every submission.

In many cases, I use the page action to set up default data, and to populate lists for dropdowns, etc. I don't want this to be re-executed during the conversation, as this would result in loss of user-entered data (e.g. knowing which item they selected in a DataTable). I've spent time debugging strange behavior, only to realise that the problem was caused by Seam re-triggering the page action (usually the wire() function on the EntityHome).

It's pretty easy fix - just set on-postback to false:


<action execute="#{myEntityHome.wire}" on-postback="false">


This tells Seam not to trigger the function when a form is posted back to the server as a result of actions being executed/validation within the conversation.

Friday, 24 April 2009

Business Failure in the Downturn

Interesting article: 5 Myths About Business Failure in a Downturn

As someone pointed out, stop blaming others for your problems, and get on and do something about it.

Wednesday, 22 April 2009

Seam - Master-Detail Views

Building master-detail views using Seam is a regular topic on the forums, and with good reason. It's not trivial for new developers.

There are three levels that have to work together:
  1. The Hibernate mapping between the master and detail entities
  2. The Seam layer - the EntityHome or other bean
  3. The presentation layer
In terms of requirements for a maintenance screen that deals with both master and detail:
  • you want the user to update both master and detail records on the same page
  • you want to save changes to master and detail at the end (or optionally part-way through)
  • you should be able to add new detail rows or delete existing ones and see the changes reflected immediately on the screen, again without navigating between pages

So to an example. My two entities are Master and Detail, represented in the MySQL database as:



CREATE TABLE master (
id int(11) NOT NULL AUTO_INCREMENT,
master_description varchar(100) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM

CREATE TABLE detail (
id int(11) NOT NULL AUTO_INCREMENT,
master_id int(11) NOT NULL,
detail_description varchar(100) NOT NULL,
PRIMARY KEY (id),
KEY newfk (master_id)
) ENGINE=MyISAM



The Hibernate mappings need to reflect the one-to-many relationship from master to detail.



@Entity
@Table(name = "master", catalog = "test")
public class Master implements java.io.Serializable {

private Integer id;
private String masterDescription;
private List<detail> details = new Vector<detail>(0);

public Master() {
}

public Master(String masterDescription, List<detail>details) {
this.masterDescription = masterDescription;
this.details = details;
}

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

@Column(name = "master_description", length = 100)
@Length(max = 100)
public String getMasterDescription() {
return this.masterDescription;
}

public void setMasterDescription(String masterDescription) {
this.masterDescription = masterDescription;
}

@OneToMany(cascade = CascadeType.ALL,
fetch = FetchType.LAZY, mappedBy = "master")
public List<detail> getDetails() {
return this.details;
}

public void setDetails(List<detail> details) {
this.details = details;
}
}


Note that this example uses List and Vector instead of the Sets that Seam-gen uses by default. Select lists and some other presentation widgets seem to require Lists rather than Sets, and it's become a habit to use them instead of the default Seam-gen code.


@Entity
@Table(name = "detail", catalog = "test")
public class Detail implements java.io.Serializable {

private Integer id;
private String detailDescription;
private Master master;

public Detail() {
}

public Detail(Master master, String detailDescription) {
this.master = master;
this.detailDescription = detailDescription;
}

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "master_id", nullable = false)
@NotNull
public Master getMaster() {
return this.master;
}

public void setMaster(Master master) {
this.master = master;
}

@Column(name = "detail_description", nullable = false, length = 100)
@NotNull
@Length(max = 100)
public String getDetailDescription() {
return this.detailDescription;
}

public void setDetailDescription(String detailDescription) {
this.detailDescription = detailDescription;
}
}


MappedBy = "master" identifies the name of the property on the detail entity that links back to the master entity.


Now we need a backing bean for the maintenance page. Seam-gen will give you a set of XXXList, XXX, and XXXEdit pages for each entity. The XXX and XXXEdit pages refer to an EntityHome instance for the entity to be viewed/edited. So after running Seam-gen to reverse-engineer from the MySQL database we will have a set of XHTML pages
  • Master.xhtml
  • MasterEdit.xhtml
  • MasterList.xhtml
  • Detail.xhtml
  • DetailEdit.xhtml
  • DetailList.xhtml
and a set of four backing beans:
  • MasterHome
  • MasterList
  • DetailHome
  • DetailList
Really we want to end up with a single page, and therefore a single backing bean that encompasses the functions of both MasterHome and DetailHome.


@Name("masterEditor")
public class MasterEditor extends EntityHome<Master> {

@In EntityManager entityManager;

@DataModel private List<Detail> detailListFromMaster = new Vector<Detail>(0);
@DataModelSelection @Out(required=false) private Detail currentlySelectedDetail;

//For the selection on the detail list
public void select() {}

public void createNewDetail() {
Detail detail = new Detail();
detail.setMaster(getInstance());
detailListFromMaster.add(detail);
currentlySelectedDetail = detail;
}

public void cancelNewDetail() {
removeDetail();
}

//Delete a detail item
public void removeDetail() {
detailListFromMaster.remove(currentlySelectedDetail);
entityManager.remove(currentlySelectedDetail);
}

public void setMasterId(Integer id) {
setId(id);
}

public Integer getMasterId() {
return (Integer) getId();
}

@Override
public String update() {
return super.update();
}

@Override
protected Master createInstance() {
Master master = new Master();
return master;
}

public void wire() {
//Both triggers getInstance() and sets the local variable
//to the list of Detail items from the Master entity
detailListFromMaster = getInstance().getDetails();
}

public boolean isWired() {
return true;
}

public Master getDefinedInstance() {
return isIdDefined() ? getInstance() : null;
}
}


This is an edited EntityHome, which started life as MasterHome. A few things to note:
  • we want to use a DataModel and DataModelSelection to link with the presentation layer
  • the wire() function now gets the list of Detail objects from the Master object and pushes them into the DataModel list
  • there are a few simple functions added to be triggered from the presentation layer to do simple CRUD stuff (add a new Detail, remove, etc)


So on to the presentation layer. This is in two parts - the main page, plus a Modal Panel, all using RichFaces.

[UPDATE: Note that if you want a presentation technique that does not use Modal Panels, try this more recent post.]


<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
template="layout/template.xhtml">

<ui:define name="body">

<rich:modalPanel id="detailEditWizard"
minHeight="200"
minWidth="500"
autosized="true">

<f:facet name="header"><h:outputText value="Edit Detail..." /></f:facet>
<f:facet name="controls">
<h:graphicImage value="/img/ico_close.gif"
styleClass="linkImage"
onclick="#{rich:component('detailEditWizard')}.hide()" />
</f:facet>

<h:form id="detailEditForm" styleClass="edit">

<h:messages globalOnly="true"/>

<s:decorate id="masterIdField" template="layout/edit.xhtml">
<ui:define name="label">Master id</ui:define>
<h:inputText id="masterId"
required="true"
value="#{currentlySelectedDetail.master.id}">
<a:support event="onblur" reRender="masterIdField" bypassUpdates="true" ajaxSingle="true"/>
</h:inputText>
</s:decorate>

<s:decorate id="detailDescriptionField" template="layout/edit.xhtml">
<ui:define name="label">Detail description</ui:define>
<h:inputText id="detailDescription"
required="true"
size="100"
maxlength="100"
value="#{currentlySelectedDetail.detailDescription}">
<a:support event="onblur" reRender="detailDescriptionField" bypassUpdates="true" ajaxSingle="true"/>
</h:inputText>
</s:decorate>

<div class="actionButtons" style="clear:both">

<a:commandButton id="detailEditMPClose"
onclick="#{rich:component('detailEditWizard')}.hide()"
reRender="detailListTable"
value="Close" />

<a:commandButton id="detailEditMPCancel"
onclick="#{rich:component('detailEditWizard')}.hide()"
action="#{masterEditor.cancelNewDetail()}"
reRender="detailListTable"
value="Cancel" />

</div>
</h:form>

</rich:modalPanel>



<h:form id="master" styleClass="edit">

<rich:panel>
<f:facet name="header">#{masterEditor.managed ? 'Edit' : 'Add'} Master</f:facet>

<s:decorate id="masterDescriptionField" template="layout/edit.xhtml">
<ui:define name="label">Master description</ui:define>
<h:inputText id="masterDescription"
size="100"
maxlength="100"
value="#{masterEditor.instance.masterDescription}">
<a:support event="onblur" reRender="masterDescriptionField" bypassUpdates="true" ajaxSingle="true"/>
</h:inputText>
</s:decorate>

<div style="clear:both">
<span class="required">*</span>
required fields
</div>

</rich:panel>


<!-- Detail section -->
<rich:panel>
<f:facet name="header">Detail List</f:facet>
<div class="results" id="detailList">

<h:outputText value="The detail search returned no results."
rendered="#{empty masterEditor.instance.details}"/>

<rich:dataTable id="detailListTable"
var="_detail"
value="#{detailListFromMaster}"
rendered="#{not empty detailListFromMaster}">
<h:column>
<f:facet name="header">
<ui:include src="layout/sort.xhtml">
<ui:param name="propertyLabel" value="Id"/>
</ui:include>
</f:facet>
<h:outputText value="#{_detail.id}"/>
</h:column>
<h:column>
<f:facet name="header">
<ui:include src="layout/sort.xhtml">
<ui:param name="propertyLabel" value="Master id"/>
</ui:include>
</f:facet>
<h:outputText value="#{_detail.master.id}"/>
</h:column>
<h:column>
<f:facet name="header">
<ui:include src="layout/sort.xhtml">
<ui:param name="propertyLabel" value="Detail description"/>
</ui:include>
</f:facet>
<h:outputText value="#{_detail.detailDescription}"/>
</h:column>
<rich:column styleClass="action">
<f:facet name="header">Action</f:facet>
<a:commandLink id="editDetailMP"
action="#{masterEditor.select()}"
oncomplete="javascript:Richfaces.showModalPanel('detailEditWizard')"
reRender="detailEditForm"
value="Edit">
<s:conversationId />
</a:commandLink>
#{' '}
<a:commandLink id="removeDetail"
action="#{masterEditor.removeDetail()}"
reRender="detailListTable"
value="Delete">
<s:conversationId />
</a:commandLink>

</rich:column>
</rich:dataTable>

</div>
<s:div styleClass="actionButtons" rendered="#{empty from}">
<a:commandLink id="editDetailMP"
action="#{masterEditor.createNewDetail()}"
oncomplete="javascript:Richfaces.showModalPanel('detailEditWizard')"
reRender="detailEditForm"
value="New Detail...">
<s:conversationId />
</a:commandLink>
</s:div>
</rich:panel>

<div class="actionButtons">

<h:commandButton id="save"
value="Save"
action="#{masterEditor.persist}"
disabled="#{!masterEditor.wired}"
rendered="#{!masterEditor.managed}"/>

<h:commandButton id="update"
value="Save"
action="#{masterEditor.update}"
rendered="#{masterEditor.managed}"/>

<h:commandButton id="delete"
value="Delete"
action="#{masterEditor.remove}"
immediate="true"
rendered="#{masterEditor.managed}"/>

<s:button id="done"
value="Done"
propagation="end"
view="/Master.xhtml"
rendered="#{masterEditor.managed}"/>

<s:button id="cancel"
value="Cancel"
action="#{masterEditor.cancelChanges}"
propagation="end"
view="/#{empty masterFrom ? 'MasterList' : masterFrom}.xhtml"
rendered="#{masterEditor.managed}"/>

</div>

</h:form>

</ui:define>

</ui:composition>

Systems: Automated Underwriting

What is Automated Underwriting?
Automated Underwriting systems are an attempt to reduce or remove the manual activities that have long formed part of the underwriting process. Instead of having underwriters of varying levels of experience evaluating proposals, an automated solution is designed to weed out the simpler cases. The underwriters are not removed from process entirely, but instead focus on the more complex cases, where their skills can be best applied.

Technology-wise, underwriting systems often take one of two main forms:
  • Back-office, rules engine integrated with the policy admin system
  • Point-of-sale integration of rule engine at proposal capture time
The system will normally comprise:
  • A rules database. This contains the accumulated wisdom regarding symptoms, risk factors for diseases, occupations, etc. Because the database captures this type of information, in practice it often comes from a reinsurer. Rules databases will normally include standard rules about diseases, traits, pursuits, and occupations. They will also include product-specific rules, which are often configured specifically for the company's products that will be evaluated.
  • Engine software. This is the relatively straight-forward software that evaluates a case (proposal), applying the rules database to determine a course of action.
Back-Office Use
In a back-office environment, the automated underwriting system is often integrated with a workflow system (although integration with the new business or policy admin system is the other approach). The workflow is usually managing a case through the New Business process, which include one or more iterations of evaluation by the underwriting system. The underwriting system will require data about the proposal, along with any existing policies the customer holds with the company (for aggregated risk calculations). In this scenario the automated underwriting system will normally respond with one of a limited set of recommendations:
  • Accept ordinary rates (cleanskin)
  • Decline
  • Refer for manual underwriting
As the company becomes more comfortable with the reliability of the automatic underwriting (in reality the quality of the rules database), the system may be entrusted with applying loadings or exclusions in more straightforward substandard cases.

Point Of Sale
Over the past few years, vendors (particularly in Life) have pushed automated underwriting tools integration in the proposal capture process at Point of Sale. This makes some sense, as the tool can prompt the customer/agent through a series of underwriting questions during the capture stage. If the case is evaluated as standard, the customer and agent have the benefit of knowing that the policy should be issued quickly. Alternatively the questions/responses may indicate to the customer that further medical evaluation will be required.

For cleanskin cases this offers the possibility of achieving the Straight-Through-Processing that has been discussed over the years. With POS integration of automated underwriting, combined with workflow/automation at the back office, a cleanskin proposal could be submitted electronically, and issued with little/no manual work.

Mis-Use: some companies have been known to mis-use the automated underwriting tools, configuring "underwriting rules" that really should be handled within the New Business / Policy Admin system. For example, the maximum sum assured on a product. This really comes down to the perceived difficulty in making changes to the admin systems when compared with configuring the underwriting tools. Of course the disadvantage of this approach is that you are left with product rules spread around the systems rather than being grouped sensibly into a few maintainable locations.

Vendor Examples
SwissRe (www.swissre.com) - Magnum, supports both back-office and POS approaches.
MunichRe subsidiary - AllFinanz (www.allfinanz.com) - URE: Underwriting Rules Engine.
Insbridge (now part of Oracle), for P&C rather than Life/Pensions

Monday, 20 April 2009

Open Source in Financial Services

Open Source is often regarded as a bad thing in corporate Financial Services, although this does depend on the personal views of the IT architect and/or CIO. When open source software is used, it is often in the guise of a utility component within in-house developed systems, or similarly within vendor systems. No corporate that I am aware of would entrust their mission-critical data to an unsupported system. And that is generally how Open Source is viewed - unsupported.

An interesting move to change that is a consortium that is working on an Open Source insurance system. Currently only for non-Life, Insurance In a Box (iabforge.wikidot.com) is an interesting experiment. Built using Ruby on Rails, it also takes an interesting approach to how to store the data - as XML.

Systems: Direct Marketing and Lead Management

Direct Marketing in Life Insurance (in Asia at least) largely tends to come down to telemarketing. Either inbound in response to TV home shopping/commercials, or outbound to database lists obtained from sponsors.

The segment does not seem to be well served on the systems side, either in the planning or monitoring activities. Generic lead management tools are available, however event these are not well suited to insurance sales. The call center is better served, unsurprisingly since there are many vendors focused on call centers.

Planning/Monitoring
One solution that comes close on the execution side is Aprimo (http://aprimo.com/). This tool is focused on the sales process, with some functionality around campaign planning. It has inbuilt workflow definition and management tools, which are used to execute lead-level followup.

However the key lack (and in most/all other systems) is the profitability planning capabilities when it comes to insurance-product sales. The problem is that an insurance sale creates an annuity - an ongoing revenue stream. The sale is only profitable when you take into account the stream of premiums received over months and years. Tools like Aprimo's assume each sale is a lump sum amount.

An insurance planning tool needs to be able to evaluate how long it will take for the campaign to break even, which requires the system to model the spend and cash inflows over an extended period. There do not appear to be a wealth of options available in this area, and most insurance companies that do anything on this tend to use spreadsheets.

The downside of this approach is the restricted ability to monitor actual experience against the plan and projections. And if you don't know whether the campaign is profitable, how can you decide whether to continue, ramp up, or even stop?

Lead Management
Databases of customers and potential customers need to be sanitised, filtered, and passed to call centers for action. This tends to be fairly basic work, if tedious. Many organisations seem to rely on in-house systems, perhaps reflecting the custom nature of the data sources. A fairly simple set of database and query tools will usually suffice to load data from sponsors, perform the de-duplication checks, and re-extract data for passing to the call center.

For web-based sales channels (much discussed but not overly effective by nature), tools like Aprimo provide the ability to manage and in some cases automate parts of the sale process. Leads are captured in the internal database, and eventually the sale is passed to the back-office systems. The challenge here will be to retain the less-structured data that is captured during the sale process.

Sunday, 12 April 2009

Coignition

Well, possibly another victim of the markets? Coignition has shut it's doors in HK.

For anyone not aware, Coignition was a wholly owned subsidiary of Munich Re AG. Coignition was set up to be a professional services partner for businesses "seeking alternative routes of entry into life insurance". They offered to provide both services and an "end-to-end business platform".

I suspect that given the timing, the business was given a year to see whether they could make a success of things. However it's not been an ideal time to be building new insurance businesses, particularly in the banking world where they have enough existing problems to focus on.

At the time of writing, there were no official announcements on the Munich Re website. The Coignition website has been decommissioned.