Advanced Oracle Policy Automation – Recoupment Example Project

Disclaimer: There will be advanced concepts that require the reader to have a firm foundation in OPA.


It is finally time! As promised…


This blog presents an example project for the following:

  • Determines eligibility for a fictitious entitlement program
  • Determines a financial benefit
  • Creates a plan of future benefit payments
  • Allows rules to change over time
  • Allows rule errors that went into production to be corrected retroactively
  • Allows data to change over time
  • Creates a recoupment plan for benefits overpaid to clients (with interest)
  • Can reproduce a historical determination
  • Determines if a determination change is based on a historical rule change (such as a rule error) or a circumstance change and notifies agents about issues that negatively impact clients.


Sound fun (hard)?


I propose we use the following quickly-invented policy statements as an example.

In much of real-life, I get statements in email, voice, etc. I write them down as thus:


The Example Abbreviated Policy


Elig 1: The payment, adjustment, and asset events need to be summed. Payment and adjustment events are summed on their transaction start dates. Asset events are summed every day they are an asset.

Elig 2: Before January 1st 2016 the maximum qualifying asset value was $10,000. From January 1st 2016 to December 31st 2016 the maximum qualifying asset value was $11,000. On January 1st 2017, the qualifying asset value was raised to $12,000.

Elig 3: The maximum total asset value on any day in a month must be used to determine eligibility.

Elig 4: To be eligible for payment a person must have an active case, their asset value must be less than the maximum monthly allowance. As of January 1st, 2016 the person must be older than 18. As of January 1st, 2017, the person must be at least 65.

Elig 5: The person's eligible monthly payment amount is computed on the last day of the month. The person must be eligible and the rate is based on the maximum monthly asset value. Rate tables are attached. The eligible monthly payment amount cannot be less than $0.


Bal 1: The daily payment amount is the amount paid in sum to the person each day. This includes any adjustments.

Bal 2: The person's monthly eligibility total is the amount the person has been eligible for from the start of the person's case.

Bal 3: The person's monthly payment total is the amount the person has received from the start of the person's case.

Bal 4: The person's balance is the amount the person has been paid - the amount the person has been eligible for.


Rcp 1: Recoupment is required if the person's balance falls below -$20.00

Rcp 2: Recoupment is in arrears if recoupment is required and the person is no longer eligible for payments.

Rcp 3: Recoupment in arrears for more than 90 days should be collected with interest.

Rcp 4: Recoupment comes in 3 flavors:

1) Forgive the balance, which results in a monetary adjustment. This option is only allowed if the balance owed is less than $100.00. We don't forgive positive amounts.

2) Collect the balance by taking 25% from the benefit every month. The person must be eligible for benefits for this option to work.

3) The recoupment can always happen in full. There are actually two variations of this option. First, if the person is no longer eligible, then the balance must be returned immediately, or after 90 days an interest of 12% will begin. Second, if the person is eligible, benefits will be used to pay off the balance.

Rcp 5: If recoupment status is currently not required, but recoupment is required, that implies that this is the first month recoupment decisions are needed. In that instance, if the recoupment amount can be forgiven or the recoupment amount can be collected at 25%, an agent should be asked which type of recoupment to use. Otherwise, recoupment will be full recoupment.

Rcp 6: If recoupment is required, the current recoupment plan should be set to any manual answer provided. Manual answers must be provided if the most recent historical recoupment status = "not required." Otherwise, the most recent historical status is used.


Pln 1: The accounting day that all the eligible amounts, payments, and adjustments are combined to determine the next payment is the last day of the month.

Pln 2: The person's planned balance = the person's historical balance prior to the assessment date. The person's planned balance = the balance on the prior day – any planned payments for today + any eligible monthly payments today + any balance adjustments today from the assessment date to the global end date.

Pln 3: The person's payment plan is the person's eligible monthly payment – any recoupment prior to the first of the month if that balance is at least $20.00, otherwise it is $0. Never collect negative payments unless the person is not eligible.

Pln 4: The person's recoupment plan is as follows on the last day of the month:

1) if the plan is forgive, then recoup 0 and adjust the balance to remove debt.

2) if the plan is 25%, recoup 25% of the eligible monthly payment.

3) if the current balance is less than 0, recoup the lesser of the current balance plus adjustments or the next eligible monthly payment and any adjustments

4) if the person is not eligible, recoup the current balance


Pln 5: There are two types of balance adjustments. There is forgiveness, in which the whole balance of the day prior to the next accounting day is forgiven on the accounting day. There is interest, in which a recoupment in arrears has been waiting too long and interest needs to be added. Otherwise, there is no adjustment.

Pln 6: The goal is to find the next payment amount which is the amount in the plan at the next payment date.

Corrective Notification

On January 1st, 2017, an incorrect eligibility rule was coded. The rule was corrected retroactive to the first of the month. For every client that will be negatively impacted due to this rule correction create a notification, otherwise do nothing.

Inputs and Outputs

As input, for each client, all the historical transactions will be provided in an events entity.

If a recoupment decision is needed, collect it from the user.

As output, for each client, a plan of necessary recoupment status, plan for the next payment adjustment, and the current payment plan for the following year should be provided in the plan entity...

Simple enough?


The example recoupment project is attached.


Because this project contains complex time reasoning, we will use the OPA Warehouse Pattern. Because we want some readability of temporal rules by the business, we will use the OPA Access Timeline Pattern. Because this project processes rules that change retroactively we will use the OPA Rule Revision Pattern. Because this project wants corrective notifications we will use the OPA Context Pattern.


The project is attached and can be downloaded and examined.

I am not going to speak too much to the project except to provide the following information:

  • A sanity test case is provided. I recommend that you use these test cases and then examine the outputs in temporal visualization.
  • The value of "the current date" can be overridden by the global input attribute "the current date for assessment".  It is stored in the global attribute "today".  For repairing past errors, the global input attribute "the prior date for assessment" can be set which will make "today" temporal.
  • I add tags to all the substantive rules. Among other benefits, this has the benefit of tagging conclusions with the reference tags in the "Decision" tab when debugging. In this manner it is easier to follow the logic. I would consider tagging all rules (not just substantive rules) depending upon how much time I have to develop the model.
    See the following image with the tags such as "Elig 4".

Recommendation: If for no other reason, consider tagging all rules for ease of debugging in the decision tab.

Next time someone doubts whether OPA can really handle the most complex of financial eligibility logic, say "yes" and point them at this example!  The gauntlet has been tossed.