Implementation Guide for Oracle Self-Service E-Billing > Payment Processing > About Recurring Payment Processing >

Recurring Payment Job


The pmtRecurringPayment job gets bills and then schedules payments. The first process is called synchronization and the second process is called scheduling.

Recurring Payment Synchronization

During the synchronization process, the job retrieves a list of recurring payments to be synchronized, and then tries to get the bills for the recurring payments from the Command Center. Figure 14 illustrates the recurring payment synchronization process.

Figure 14. The Recurrent Payment Synchronization Process

Figure 15 shows the synchronization.

Figure 15. Recurring Payment Synchronization

Synchronization follows these steps:

  1. RecurPaymentTask.executeTask() is called when the job runs, which calls RecurringPaymentTask.synchronizeSummary().
  2. RecurringPaymentTask.synchronizeSummary() is called. This method does the real work of synchronization and following are the actions taken in this method.
  3. IRecurringPaymentLog.getRecurringPaymentsToBeSynchronized() is called to get a list of recurring payments to be synchronized. The query result is affected by the recurring payment job configuration parameter When to Synchronize Recurring Payment with Oracle. When this configuration is Whenever job runs, all the recurring payments are retrieved from the recurring_payments table with payee_id as the job DDN and status as active. If Only after current bill is scheduled is selected, then all payments with the payee_id as job DDN and status as active" and bill_scheduled as Y are retrieved from the recurring_payments table.
  4. For each recurring payment, IRecurringPaymentPlugIn.preGetLatestSummary() is called. This method allows the recurring payment plug-in code to decide whether to retrieve bills for a particular recurring payment based on biller-specific business rules.
  5. Call RecurPaymentTask.updateRecuringPaymentOnly() if the plug-in rejects this recurring payment by returning PRE_GET_LATEST_SUMMARY_REJECT. This method performs these functions:
    • Update last_process_time to the current time.
    • If the recurring payment pay date is fixed date (monthly/quarterly/weekly) and pay amount is based on (minimum) amount due, and no bill arrives for this pay period (bill_scheduled is Y and current time is after the current next_pay_date), then the last_pay_date is updated to current next_pay_date. This ensures that if no bill arrives for this pay period, then the next bill will be paid on the correct date.
    • Call IRecurringPayment.update(): this method calculates the next_pay_date based on the current last_pay_date.
  6. Call IBillDepot.getNewBillSummary(). This interface is implemented by com.edocs.payment.imported.eadirect.BillDepot. The BillDepot class retrieves the latest bill summary for the specified account.
    • BillDepot.getNewBillSummary() is called, which then calls BillDepot.getSummary().
    • BillDepot.getSummary() is called. This method calls IDataSource.getDocumentSummary() to get all the bills indexed for this account between the last_process_time of the recurring payment and the current job run time.
    • The returned bills are in the format of name value pairs with value of string. They are interpreted to retrieve due date, amount due, and the minimum amount due.
      • For each bill, if minimum amount due is not null, then call BillDepot.preParseMinAmountDue() to give a child class of BillDepot (through the plug-in) a chance to manipulate the minimum amount due string before it is parsed, then it parses min amount due.
      • If the bill's amount due is not null, call BillDepot.preParseAmountDue() to give child class of BillDepot (through the plug-in) a chance to manipulate the amount due string before it is parsed, then it parses the amount due. If the amount due fails to parse, then the bill is ignored.
      • If the bill has no amount due, or its amount due is set to null by preParseAmountDue(), or the amount due failed parsing, then the bill is ignored.
      • If the bill due date is not null, call BillDepot.preParseDueDate() to give child class of BillDepot (through the plug-in) a chance to manipulate the due date string before it is parsed, then it parses the due date.
      • If the bill has no due date, or its due date is set to null by preParseAmountDue(), or the due date failed parsing, then the bill is ignored.
    • All the successfully parsed bills are compared with the bill summary associated with the current recurring payment, if the summary is not null. The following business rules are used to decide which bill is the latest one:

      The due dates of the bill summaries retrieved are compared and the one with latest due date is chosen.

      For rebill, multiple bills with the same due date can be retrieved. In this case, a rebill is chosen based on the following rules: the one with latest Doc Date and in case of the same Doc Date, the one with the larger IVN number. This assumes that a rebill is indexed after its original bill. A rebill will be ignored if its original bill has been paid (the bill_scheduled flag of recurring payment is Y).

    • BillDepot.Summary() returns the latest bill if there is one found. Otherwise, it returns null.

Recurring Payment Scheduling

Recurring payment scheduling processes as follows:

  1. Calls RecurPaymentTask.isValidBillSummar() to validate the latest retrieved bill summary. The latest bill summary could be ignored if it has no bill due date, or if the recurring payment is based on minimum amount due but the bill summary has no minimum amount due, or the recurring payment is based on amount due but the bill summary has no amount due.
  2. Now a valid bill summary exists. If the payment to the previous bill summary is still in scheduled status, then the following occurs:
    • Calls RecurPaymentTask.cancelScheduledPayment() to cancel this payment. The reason to cancel it is that the new bill summary just retrieved must include the balance of this scheduled bill, cancel the payment so that it will not pay the same bill twice.
    • Calls RecurPaymentTask.modifyLastPayDate(). If a recurring payment has a fixed pay date, but the amount is based on amount due or minimum amount due, then it is necessary to back date the last pay date because the previous bill payment has been cancelled. Failing to do so will cause the current new bill being paid in next pay interval, not the current one. For example, assume that current bill cycle is October, the previous bill was retrieved on October 10 and is scheduled to pay on October 15. As a result, the last_pay_date and next_pay_date of the recurring payment are updated to October 15 and November 15, respectively. On October 11, a new bill is retrieved and the payment is scheduled. If Oracle Self-Service E-Billing does not back up the last_pay_date, then the new bill will be scheduled to pay on November 15. But in this case, it is necessary to pay the bill on October 15 because it is still in the October billing cycle. To fulfill this goal, go back date the last_pay_date to Sep 15 so the next_pay_date will be calculated as October 15, which will be used as the pay date for the new bill.
  3. Calls RecurPaymentTask.insertNewBillAndUpdateRecurring(), which inserts the retrieved new bill and updates recurring payment accordingly.
    • Calls IRecurringPaymentPlugIn.preInsertLatestSummary() before inserting the bill summary in the payment_bill_summaries table.
    • If PRE_INSERT_LATEST_SUMMARY_REJECT is returned from the plug-in, then calls RecurPaymenTask.updateRecurringPaymentOnly() and return.
    • Calls IBillSummaryLog.insert() to insert this new bill summary.
    • If IBillSummaryLog.insert() generates the DuplicateKeyException indicating that this bill is already in the Oracle Self-Service E-Billing database, then calls RecurPaymenTask.updateRecurringPaymentOnly().
    • Sets the bill_scheduled flag to N if the payment amount is not negative, or Y if it is negative. This means that no credit or reversal will be issued from recurring payment, and the credit appears as part of the next bill.
    • Sets the bill_id of the recurring payment to the one of the new bill summary.
    • Calls IRecurringPaymentPlugIn.preUpdateSynchronizedRecurring().
    • If PRE_UPDATE_SYNCHRONIZED_RECURRING_REJECT is returned from the plug-in, then calls RecurPaymenTask.updateRecurringPaymentOnly() and return.
    • Calls IRecurringPaymentLog.update() to update the recurring payment. The following table lists the information updated.
      Column
      Value

      last_pay_date

      In the case where the pay date is fixed, but amount is based on amount due, last_pay_date could be moved one pay_interval back if a scheduled payment is cancelled because a new bill arrives. Otherwise, last_pay_date will stay the same.

      next_pay_date

      Next_pay_date will be updated in RecurringPaymentUtil.calculateInternal(). In the case of fixed pay date, it will be updated based on last_pay_date. In the case of before due, it will be updated based on the due date of the new bill. See Update Recurring Payment from the UI for more information.

      status

      Because next_pay_date is changed, the status could be changed to inactive if next_pay_date falls after end_date.

      bill_id

      It is set to the bill_id (doc ID) of the bill being inserted into the payment_bill_summaries table.

      bill_scheduled

      The bill_scheduled flag is set to N if the payment amount is not negative, Y if it is negative.

      last_process_time

      Set to the current time.

Recurring Payment Scheduling Workflow

Recurring Payment Scheduling Workflow schedules recurring payments for processing with the pmtRecurringPayment job. During scheduling processing, the pmtRecurringPayment job retrieves a list of recurring payments to be scheduled, and then schedules them, as shown in Figure 16.

Figure 16. Recurring Payment Scheduling Workflow

Figure 17 shows the action sequence:

Figure 17. Recurring Payment Scheduling Action Sequence

Workflow Description. This workflow performs the following actions:

  1. RecurPaymentTask.execute().
  2. RecurringPaymentTask.schedulePayments(). This step performs the scheduling work.
  3. IRecurringPaymentLog.getRecurringPaymentsToBeScheduled(). This step gets a list of recurring payments to be scheduled. The result is affected by the recurring payment job configuration parameter Number of days before pay date to schedule the payment, which is a number, N. The SQL query finds all the recurring payments where the payee_id is the job's DDN reference, bill_scheduled is N and next_pay_date is less than or equal to today plus N.
  4. IPayUserAccountAccessor.getPaymentAccount(). This step gets the current payment account information associated with this recurring payment. A sanity check is done on the retrieved payment account and different actions can be take based on the result:
    • If no payment account has been retrieved, which means it has been deleted from the Oracle Self-Service E-Billing database, then the current recurring payment setup will be de-activated (IRecurringPaymentLog.update() is called to update status to Inactive) and no payment is scheduled.
    • If the payment account is a check account, its status is cancelled, and the job configuration parameter "Cancel recurring payment if payment account is canceled?" is true, then the current recurring payment setup is de- activated (IRecurringPaymentLog.update() is called to update status to Inactive) and no payment is scheduled.
    • If the payment account is a credit card account, it has expired, and the job configuration parameter Cancel recurring payment if payment account is canceled? is true, then the current recurring payment setup is de-activated (IRecurringPaymentLog.update() is called to update status to Inactive) and no payment is scheduled.
  5. RecurPaymentTask.createPaymentTransaction(). This step creates a new payment transaction (either a check or a credit card) with status as scheduled and pay date and amount as specified by recurring payment setup.
  6. IRecurringPaymentPlugin.preSchedulePayment(). This step gives PS a change to customize the payment transaction before it is inserted into the Oracle Self-Service E-Billing database. If this method returns PRE_SCHEDUE_PAYMENT_REJECT, then the payment will not be scheduled, and the program return to process next recurring payment. If not, then the program will go to the next step to schedule the payment.
  7. ICheckPaymentLog.insert(). This step inserts a check or ICreditCardPaymentLog.insert() to insert a credit card if the amount of the payment is not negative (it will never be negative because the bill_scheduled will not be N if amount is negative. See job synchronization part for detail). The following table lists part of the payment information inserted into the payment tables:
    Column
    Value

    status

    6

    pay_date

    The next_pay_date (calculated during synchronization process) of the current recurring payment. Because recurring payment will be updated after this insert operation, this value is the same value as last_pay_date of the updated recurring payment.

    Amount

    This value is decided by amount_type and the amount of the recurring payment. It is calculated when RecurPaymentTask.createPaymentTransaction() is called. It must be the same as the amount column of the recurring payment if amount_type is Fixed. It must be the same as the amount_due or min_amount_due of the bill associated with current recurring payment if amount_type is amount due or minimal due, respectively. If amount_type is Less Due, then the payment amount is the amount due of the bill if amount due is less than or equal to the amount column value of the recurring payment. Otherwise, the payment amount value is 0. If amount_type is upto amount, then the payment amount is the amount due of the bill if amount due is less than or equal to the amount column value of the recurring payment. Otherwise, the payment amount is the amount column value of the recurring payment.

    bill_id

    Same as the one from recurring_payment.

    Pid

    Same as the one from recurring_payment.

    payer_id

    Same as the one from recurring_payment.

    payer_acct_number

    Same as the one from recurring_payment.

  8. IRecurringPaymentLog.update(). This step updates the recurring payment. The following information of the recurring payment will be updated:
    Column
    Value

    Curr_num_payments

    Increased by 1

    Bill_scheduled

    N if pay date is on fixed date (monthly, quarterly or weekly) and pay amount is fixed amount. Otherwise, Y.

    Last_pay_date

    The last_pay_date is set to the current next_pay_date of the recurring payment.

    Next_pay_date

    After last_pay_date is set to the current next_pay_date, the next_pay_date is calculated again by RecurringPaymentUtil.calculateInternal(). If the payment is using a fixed pay date (weekly, quarterly or weekly), then next_pay_date is calculated and moved to the next pay date in the next pay interval. In the case of before due date, the next pay date will be calculated based on the current due date (whose bill has been paid), so this next_pay_date has no meaning until the next bill is synchronized.

    Status

    Status is recalculated and will be changed to inactive if next_pay_date is after end_date, or curr_num_payments is greater than max_num_payments.

  9. IRecurringPaymentPlugIn.preSendEmail(). This step lets the plug-in customize the email being sent out. The email is not sent out if this method returns PRE_SEND_EMAIL_REJECT.
  10. Template.parse(). This step parses the email template and generates the content of email.
  11. PaymentMailer.send(). This step sends email.
Implementation Guide for Oracle Self-Service E-Billing Copyright © 2014, Oracle and/or its affiliates. All rights reserved. Legal Notices.