AFFIRM for Annuities

Can AFFIRM Map a Distributor’s Custom Question to a Carrier Fulfillment Question?

There is no feature that exists today to map a response to a distributor custom question to a carrier’s fulfillment question. If the distributor tells the carrier what the DataMember is for the question, the carrier can map the response directly to their form. Note: A carrier would not be able to test this. Instead, they would have to set up the mapping and have their distributor test the form and mapping. Additionally the carrier could pull the distributor’s prompt as the text of the question that was asked and map it to a carrier form.

Below are some macros that can be used to pull the answers to Distributor suitability questions. You should plug in the Distributor’s DataMember and use the macros in your forms mappings.

Get the Displayed Question Text


For example, if you wanted to save the actual prompt (displayed question text) to your form


Get the Answer Value for the DataMember/Question


For example, some distributors want to know what Sales Materials were used in the solicitation of a sale. At the same time, some of the carrier state replacement forms also ask about what sales materials were used.


Does AFFIRM Support the Application Date Record B3302 record in the DTCC App?

AFFIRM does not currently output the B3302 record in the DTCC App file by default. Currently it is only supported with customizations for a few carriers.

Currently the B3302 record is not associated with the electronic signature process. The current custom implementation collects a date based on the carrier’s requirements and outputs that date in the B3302 record with qualifier 03 Application Signed Date.

How To Use Collection() In Business Rules Validation

The collection() function is used heavily in conjunction with the in and not-in operators in Business Rules validation. This is due to a variety of business logic testing a Class or Data-member for membership within an enumeration set — commonly called Restricted Enumeration Formulas. Using this and $VALUE keywords (case-sensitive), a Business Rule can reference the Class/Instance name, or a Data-member and test its membership in a collection of ACORD enumeration.

As an illustration, if the reader wishes to exclude Florida and North Carolina from all state drop-down lists for all Partys’ addresses (regardless of who a particular Party is: Owner, Beneficiary, etc.), the following Class-level Validation formula can be used:

Instance: Address

Class: Address

Data Member: AddressStateTC

Validation Formula:  $VALUE not-in collection($ACORD/OLI_USA_FL, $ACORD/OLI_USA_NC)​

The above example illustrates how a Business Rule can eliminate certain values from a list of values available within a context. The reverse behavior can be achieved by replacing not-in with in operator in the above formula.

If One Rule in a Sequence has a Syntax Error, Will the Rest of the Rules Work?

Yes. If you have a set of rules which are loaded in sequence by Affirm and the fifth one has a syntax error, the rest of the rules will work properly. The execution of successive Business Rules does not depend on the failure of any one of them.

What Are “Instance Names?”

Instance Names are key to writing out the form mappings and creating suitability/fulfillment rules as well. While not absolutely necessary, you can write out the full complete XPath notation, they provide a short cut, or macro, that resolves for you a specific reference or pointer to an instance of an object in the annuity order.

For example, for any data you want that is part of the annuity order holding, instead of the below:


You can simply have:


What Are the Requirements to Transmit to DTCC?

Should the carrier have the DTCC Fulfillment Question support enabled, these question and answers can define their ID’s, which will be transmitted thru the DTCCs question and answer record.

What Can I Do If the Max() Function Is Not Working?

The below example results in incorrect interpretation of data member types.

[FeeType=$ACORD/OLI_FEE_SURRENDER]/TableRefs/TableIdentity]/Tables/Values/Axes[Y > 0]/T).

Determining the maximum of integer collection (1, 2, 3, 10, 20, 30) is different than determining the maximum of a string collection (‘1’, ‘2’, ‘3’, ’10’, ’20’, ’30’, ‘4’).

The max() function will give the intuitive result in case of integer collection, which is 30, however, the maximum of string collection will be ‘4’ — the real sort order for string collection is (‘1′, ’10’, ‘2’, ’20’, ‘3’, ’30’, ‘4’). Now, T is an ACORD data member of string type.

Invoking max() over T will treat it as a string collection.

As a workaround try:

[FeeType=$ACORD/OLI_FEE_SURRENDER]/TableRefs/TableIdentity]/Tables/Values/Axes[Y + 0 > 0]/T + 0)).

What Data Can I Put on a Form?

If the data is in the order (ADM_OrderTrans), then it is available for you to place on a form. Data can come from one of three sources:

  1. User Input via the standard AFFIRM User Interface / Questions asked (and answered) by AFFIRM
  2. Data that was provided in pre-order (seed) data by the distributor. In some implementaions the Distributor will pass known data into the order. This informtation is then available for any for or business rule. Ask your distributor for details about any infformation they may be passing in seed data.
  3. Data generated by AFFIRM itself. There are not very many fields auto-generated by AFFIm; but these inlcude order start date, DTCC Application Number and several others.

Overall, if you run an order and using the Evaluation (Eval) window type key(‘ADM_OrderTrans’) or just simply a dot, you’ll see every data element possible. If this is not available, there is no way to write a rule to place it on a form.

What date is passed as the “Agent Submit Date” in the DTCC APP?

For DTCC APP item # 4030, AFFIRM sends the date the FA submits the order i.e. the date they press the submit button on the Forms Submit tab.



What is the Difference Between AllocPercent and TransferPct?

For a new business submission (i.e. order), the important value is the Initial Premium Financial Activity, TransferPct, which is literally expressing how you want this activity to be handled, (i.e. transferred via this percentage). Furthermore, AllocPercent identifies the “Standing,” or ongoing allocation to be used whenever an allocation is not expressed or provided.

What Should I Do If I Receive an “Expression Cannot Be Converted to SQL” Error?

If you receive the following error message in the FMS logs, this means that there was a Macro-To-SQL conversion failure.

Expression cannot be converted to SQL. Attempting partial execute: AdmTrans[!TransFamily>’ADM’ and TransCode in (‘ORDERTRANS’, ‘SUBPAYTRANS’) and AdmTransStage in (54, 64, 60, 7, 29, 5) and is-not-null(StageDate) and StageDate < dateTime(concat(AdjustDateByDays(current-date(),-50), ‘ 00:00:00’))]

To date, ADM Server Cores up to 7.1.1 do not support the concat function. Due to the failure, the ADM Server Core is designed to load AdmTrans records in memory for processing. The consequence is that a lot of memory will be consumed and the process will take a while. The severity of the problem would depend entirely on how many orders are there in the database. Beyond a point, the ADM Server may crash due to out-of-memory exception.

To resolve this issue, instead of using:

StageDate < dateTime(concat(AdjustDateByDays(current-date(),-50), '00:00:00'))


dayTimeDuration(StageDate, current-date()) >= 50

Why Am I Getting an ADM.Parser.ParserException?

If you are getting an ADM.Parser.ParserException when the following mark-to-purge fingerprint is passed by the FMS, it is likely that string operation on dates is not work properly.

Query="AdmTrans[TransFamily='ADM' and TransCode in ('ORDERTRANS', 'SUBPAYTRANS') and AdmTransStage in 
(1, 53, 64, 65) and is-not-null(StageDate) and StageDate < dateTime(concat(AdjustDateByDays(current-date(),-25), 

To resolve this issue, try the following expression instead:

AdmTrans[TransFamily='ADM' and TransCode in ('ORDERTRANS', 'SUBPAYTRANS') and AdmTransStage in 
(1, 53, 64, 65) and is-not-null(StageDate) and StageDate < AdjustDateByDays(current-date(),-25)]

Why Is My Embedded Business Rule Failing in Concact Function?

This issue likely has nothing to do with the concat() function and, instead, may be caused by any literal string used anywhere in any macro. Often times, the single quote (which appears below the double quote on the keyboard) is used as an apostrophe.  If text contains an actual Unicode apostrophe, the macro language will not treat it as a single quote. If the author of the macro expression uses a single quote as an apostrophe, then ADMServer cannot tell the difference.


If you put a single quote in the middle of a string that is delimited by single quotes, as in ‘Fred’s’, the macro language cannot tell that you meant for the quote between the d and the s to be an apostrophe. It assumes that your string is ‘Fred’, and then it is confused by the s’.

To resolve this issue, use double quotes to mark strings that have apostrophes in them, as in “Fred’s”. (Likewise, if your string contains double quotes, you must mark it with single quotes, as in ‘he said “she said” first’.

If your string contains both single and double quotes, then you must use the concat function to build the string. For example, if the string is Fred’s brother says “hello” you could write concat(“Fred’s brother says “, ‘”hello”‘)

Why Isn’t My Macro Language Expression Working?

There are two common causes that result in Macro-language expressions not working correctly: 1) incorrect implementation, and, 2) incorrect use.

Incorrect Implementations

A subset of incorrect implementations result in ADM Server flagging syntax problems. These can be recognized by looking for a string:

positionXYZ, where XYZ denotes a number which signifies the position at which ADM Server detected an ambiguity or an unimplemented behavior in syntax.

A common scenario where ADM Server will not flag a syntax problem is with misspelled ACORD object names, properties, and enumerations. The reason for this is that Macro language is declarative on the lines of XPath

Incorrect Use

There can also be problems with the Macro language expression. For example, there are two problems with the below expression.


  1. The expression to the right of = in Partys[PartyID=RelHoldingPartys… could potentially be a collection, hence, it should be Partys[PartyID in collection(RelHoldingPartys…
  2. RelHoldingPartys is a top-level object. This implies that the above expression should actually be Partys[PartyID in collection(../RelHoldingPartys…

Thus the correct expression would be:

Partys[PartyID in collection(../RelHoldingPartys[RelationRoleCode=$ACORD/OLI_REL_OWNER]/RelatedObjectID)]

Note: At a great cost of performance, the ADMServer can flag certain incorrect uses of Macro language expressions in development deployments. While this may not necessarily indicate

Why Isn’t an ACORD Enumeration Showing Up?

The ACORD model defines numerous properties to validate itself, for example, to refine its entity recognition rules. A common way to do that is by defining OLife LookUps (OLI_LUs) which are based on ACORD_TYPE_CODE (an XML schema definition of type xsd:nonNegativeInteger). These positive numbers, called enumerations in ADM Server parlance, are loaded on demand and are then cached for persistence and faster lookup.

The typical source of enumerations to the ADM Server are XML context files provided via BlueFrog’s XML repositories. Often they contain engagement specific BlueFrog extensions derived from BlueFrog’s KB – available for immediate use although not ratified by ACORD as yet. Once ratified by ACORD, these enumerations become standard, and are thus “turned-on” by default. Subsequently, this means the corresponding engagement specific BlueFrog extensions must be “turned-off,” as they are now official. If this is not done, enumerations will exist in duplicate, and to prevent invalidation of generated messages and transformations, ADM Server will turn-off both of them.

For prevention, duplicate BlueFrog extensions must be removed from the context files in XML repository once the extension becomes part of the ACORD standard.


The ACORD enumeration $ACORD/OLI_QUALPLN_419, a qualified plan with a tc of 70, is not showing up. QLI_QUALPLN_419 was a BlueFrog extension by the name OLI_LU_QUALPLAN_70 before it was ratified by ACORD in mid-2005. Pending that, the latter was subject to removal from all BlueFrog generic context files in all implementation libraries.

Why Isn’t My Famous Dashboard Formula Working?

This may not be working because the code is missing quotes.


The part of the below expression is missing quotes:

AdmTrans[TransFamily='ACORD' and TransCode=1201|1022500101 and TransactionFlavor='STD' and 
TransIdentifier='OWNERPERSON_SUP' and OriginatorCode='67891' and AdmTransStage=57 and 
(is-null(TransEffDate) or date(TransEffDate)<= date('04/07/2009 12:00:00 AM')) and 
(is-null(EndDate) or date(EndDate)>date('04/07/2009 12:00:00 AM'))] orderby-desc TransEffDate

This should be: