Tuesday, 14 December 2010

Workflow Actions

Let me apologize now for the extended duration between this post and my last, Dreamforce took over my life the last two weeks. That being said it was great to meet all my clients face-to-face and I even signed on to do a few non-profit projects in my free time. I correlate this success to finally having some nice K2 Partnering business cards.

Our last course of action for the object is to add Workflow Actions, which is a fairly simple process. Click ‘Add Workflow Action’ and select ‘New Field Update’. We want to make the name ‘Mark Payment Past Due’ and change the field from update to ‘Status’. Finally we need to change the Picklist Options to ‘Past Due’ and hit ‘Save’.

There is one last important thing we need to cover before we can finally say we are done. An immediate action needs to take place that marks a payment as past due if an employee creates an invoice with the effective date in the past. Begin by again clicking ‘Add Workflow Action’ and then ‘Select Existing Action’. Finally change the choose action type drop-down to ‘Field Update’; then go to the Selected Actions list an add the ‘Mark Payment Past Due’ action. Click ‘Save’ and then ‘Done’.  

Finally it is very important that you click the ‘Activate’ link next to the newly created workflow rule, or it will remain dormant and all this work would have gone to waste. Pat yourself on the back…the application is complete. This is just like winning a gold medal at the Olympics.

We will wrap everything up in the next post.

Monday, 29 November 2010

Workflow Rules

When we left off last week our next step was to add functionality to the object that would automatically mark overdue payments. This is done by using the SFDC workflow engine, and more specifically workflow rules. Workflow rules allow the end user to initiate actions based on new records entered, field updates, or even the passage of time. When one of these rules is triggered it can create tasks on Salesforce and assign them to the end user or automatically update field values, send email alerts, and send outbound XML messages.

For our particular object we are going to create a workflow rule that will mark a payment as past due once it has exceeded its due date and has a status of pending. An important thing to remember if you are using a new system is that you will have to set-up a default workflow user. You can set yourself up as the default workflow user by going to
‘Set-Up’, then ‘Customize’, then ‘Workflows & Approvals’, and finally ‘Settings’. Utilize the lookup button next to the ‘Default Workflow User’ field and set yourself up and click ‘Save’.

Once the user is established go to ‘Workflow Rules’ under the ‘Workflows & Approvals’ tab and click ‘New Rule’. Select our Scheduled Payment object and hit ‘Next’. Make the rule name “Schedule Payment – Process Past Due”. Leave the evaluation criteria as the default but add the following new ‘Rules Criteria’:

-         Scheduled Payment: Status Equals Pending
-         Scheduled Payment: Due Date less than TODAY

Click ‘Save’ and hit ‘Next’. Following all of this the workflow actions screen should appear. Basically this screen allows you to set up an action, most likely a field update, to our particular trigger. Initiate this by clicking ‘Add time trigger’, set the time to zero hours after Scheduled Payment: Due Date and click ‘Save’. The following is an example of what the screen should look like:



We will add Workflow Actions in the next post. Until then everyone should go run off all the food you ate this weekend…or at least try. I need to lose the 10 pounds I gained on Thanksgiving.

Monday, 22 November 2010

Creating the Default View

I might attempt to write two posts in the next three days primarily due to the fact that Thanksgiving is coming up. I’m sure that I will be living in the local bars over the long weekend. If you spot me at First & Main, Old Pro, Blue Chalk, or Nola’s I’ll be sure to buy you a beer…or five.

When we left off we wanted to assign the page we created as the default view for the Scheduled Invoice object. Begin by going to the custom object definition for the Scheduled Invoice object and click ‘Setup’, then ‘Build’, then ‘Objects’ and scroll down to the ‘Standard Buttons and Links’ section. We can change the default view by clicking the ‘Override’ link next to ‘View’. The last step is to change the Content Type to ‘Page’ and the Content Name to ‘Scheduled Invoice View’. After hitting ‘Save’ we should have the following Visualforce page:



We need to go the Scheduled Invoice tab to open to invoice we created. Below the detail header there will be a ‘Paid Payments’ section that outlines the list of paid payments, their due dates, and their amounts. Test this page by creating a new invoice and marking a few of the payments as paid.

In the next post we will add a remarkable functionality to the object that will automatically mark overdue payments.

Monday, 15 November 2010

Utilizing Visualforce Pages

Ok let’s just get into this….we have completed testing our Apex Triggers and now we are going to use Visualforce pages to fix the display and usability issues we have encountered by creating the presentation page for the Scheduled Invoice object. In case you forgot, in my previous posts I mentioned that Visualforce follows the MVC (Model View Controller) paradigm. Hence the VF pages provide tight integration with the Salesforce database. Visualforce pages are made up of components (custom or already available). These components basically render HTML tags when called from the browser. Once the VF pages are constructed and saved in the Salesforce servers the users can access those pages using URL links in the browser.  When a call is made to the Salesforce servers for those pages, the VF tags are rendered as HTML tags instead and an HTML page is displayed at the browser.
The new page we are creating will display the scheduled payments from the Scheduled Invoice object in three separate lists: ‘Pending’, ‘Past Due’, and ‘Paid’. Payment lists that have no entries (i.e. no past due payments) will be hidden on the page. This will allow us to mark the payment as ‘Paid’ straight from the invoice screen.
The step we are going over in this post is creating the controller class. We are building this class for the Visualforce page to override the standard view of the Scheduled Invoice object. This will the end users to mark payments as paid with a single click and separate payments into groups by status (Pending, Past Due, and Paid). Begin by going to ‘Setup’, then ‘Build’, and finally ‘Code’. This controller class uses the standard Apex Code with methods that are captured from our Visualforce page. Click the ‘New’ button to create the new class and then insert the following code into the body of the class:
public class ScheduledInvoiceControllerExtension
{
    // Store a constant reference to the page's underlying
    // Scheduled_Invoice__c object. The reference is set in
    // the constructor.
    private final Scheduled_Invoice__c cInvoice;
    // Categorized lists of the scheduled payments.
    private List<Scheduled_Payment__c> pastDuePayments =
        new List<Scheduled_Payment__c>();
    private List<Scheduled_Payment__c> pendingPayments =
        new List<Scheduled_Payment__c>();
    private List<Scheduled_Payment__c> paidPayments =
        new List<Scheduled_Payment__c>();
    // This controller is being written as an extension to the
    // standard system controller for the custom object so
    // you can utilize all the standard functionality without
    // having to re-write it. The parameter being passed in
    // is a reference to the standard controller, which you'll
    // use to get a reference to underlying invoice being
    // displayed by the page.
    public ScheduledInvoiceControllerExtension(
        ApexPages.StandardController controller )
    {
        // Get the reference to the current invoice.
        cInvoice = (Scheduled_Invoice__c)controller.getSubject();
        // Load the list of scheduled payments for this invoice.
        loadScheduledPayments();
    }
    // Load the scheduled payments from Salesforce.com and then
    // break them out into categorized lists for use in the page.
    private void loadScheduledPayments()
    {
        List<Scheduled_Payment__c> payments;
        // Load all payments for the current invoice from Salesforce.com.
        // SOQL (Salesforce Object Query Language) statements are wrapped
        // in brackets and can return either an array/list of objects or
        // a single object and variables can be passed into the query by
        // prepending them with a colon.
        payments = [SELECT Id, Name, Status__c, Amount_Due__c,
            Due_Date__c FROM Scheduled_Payment__c
            WHERE Invoice__c = :cInvoice.Id
            ORDER BY Due_Date__c ASC];
        // Split the payment list into categorized list by status.
        for ( Scheduled_Payment__c payment : payments )
        {
            if ( payment.Status__c == 'Pending' )
            {
                pendingPayments.add( payment );
            }
            else if ( payment.Status__c == 'Paid' )
            {
                paidPayments.add( payment );
            }
            else if ( payment.Status__c == 'Past Due' )
            {
                pastDuePayments.add( payment );
            }
        }
    }
    // This method is used by the page to retrieve the pending payments.
    public List<Scheduled_Payment__c> getPendingPayments()
    {
        return pendingPayments;
    }
    // This method is used by the page to retrieve the paid payments.
    public List<Scheduled_Payment__c> getPaidPayments()
    {
        return paidPayments;
    }
    // This method is used by the page to retrieve the past due payments.
    public List<Scheduled_Payment__c> getPastDuePayments()
    {
        return pastDuePayments;
    }
    // This method pulls the parameter paymentId from the
    // the current page and then marks that payment as paid
    // and causes the page to be reloaded.
    // The paymentId parameter is set by the apex:param element
    // of the apex:commandLink element and represents the ID
    // of the payment associated with the row of the commandLink
    // that was clicked to call this method.
    public PageReference markPaymentPaid()
    {
        // Get a reference to the current page.
        PageReference curPage = System.currentPageReference();
        Id paymentId = curPage.getParameters().get( 'paymentId' );
        Scheduled_Payment__c payment;
        // You're creating a new payment object in code, but since
        // you provide it with an ID and then use a database update
        // call it's only updating the existing payment in the
        // database, not creating a new one.
        payment = new Scheduled_Payment__c( Id = paymentId,
            Status__c = 'Paid' );
        Database.update( payment );
        // This creates a new page reference to the invoice you're
        // currently looking at, causing the page to be reloaded
        // when this method returns.
        return new PageReference( '/' + cInvoice.Id );
    }
}
With our controller in place our next course of action is to actually build the page. Once again start by going to ‘Setup’, then ‘Build’, then ‘Page’ and hit ‘New’. Set the label to "Scheduled Invoice View" and the name to "Scheduled_Invoice_View". Finish by replacing the default code with the following:
<!-- When defining the page you can either reference the    -->
<!-- standardController for an object (such as the invoice  -->
<!-- object) or a completely custom controller. If you      -->
<!-- reference the standard controller you can also specify -->
<!-- extensions to that controller, such as the extension   -->
<!-- class.                                                -->
<apex:page standardController="Scheduled_Invoice__c"
  extensions="ScheduledInvoiceControllerExtension" cache="false">
<!-- Here you include the detail section of the object, also      -->
<!-- referred to as the header, without including the related      -->
<!-- lists. This allows you to include insert code between the    -->
<!-- object's header and it's related list sections. That's      -->
<!-- where you'll place the payment lists. The detail section     -->
<!-- of the object will display the object as you have configured -->
<!-- its page layout. Including it in this manner allows this    -->
<!-- page to be maintained primarily from the page layout screen  -->
<!-- rather than having to modify code here.                     -->
  <apex:detail relatedList="false"/>
<!-- The payments form will include three lists of payments -->
<!-- grouped by status.                                   -->
  <apex:form id="paymentsForm">
<!-- This pageBlock section creates a section on the screen that -->
<!-- utilizes Salesforce.com's standard page block look and feel -->
<!-- and uses the custom style you've chosen for your tab.      -->
<!-- Each payment list group is in it's own page block.         -->
    <apex:pageBlock id="pastDueBlock" title="Past Due Payments">
  
<!-- DataTable tags create an HTML table based on data from your   -->
<!-- controller class. The value tag specifies the data that is   -->
<!-- to be retrieved from the controller. The value specified     -->
<!-- below {!PastDuePayments} instructs the page to call the       -->
<!-- getPastDuePayments() method in your controller (or extension) -->
<!-- class. It expects a List or Array as a return value and then -->
<!-- loops through the list creating a row for each entry. The    -->
<!-- var tag is the name to be used for the object containing the  -->
<!-- current row's data and is used by the column elements within  -->
<!-- the table.
<!-- -->
<!-- The CSS styles classes utilized below are predefined          -->
<!-- and more information can be located on the Apex Developer     -->
<!-- network.                                                     -->
      <apex:dataTable width="80%" value="{!PastDuePayments}"
        var="payment" id="pastDueTable" headerClass="headerRow"
        rowClasses="dataRow" styleClass="list">
<!-- This column contains both a facet and a commandLink. The      -->
<!-- facet determines how the column is displayed depending on       -->
<!-- which portion of the table is being rendered. In this case    -->
<!-- the facet provides the display value for the column's header. -->
<!-- -->
<!-- The commandLink in this column displays a link with the label   -->
<!-- "Mark Paid" and executes the markPaymentPaid() method in the    -->
<!-- controller extension. It also contains an apex:param child     -->
<!-- element that sets the page parameter "paymentId" to the Id      -->
<!-- of the scheduled payment object used when rendering the current -->
<!-- row.                                                           -->
        <apex:column>
          <apex:facet name="header"><b>Action</b></apex:facet>
          <apex:commandLink style="font-weight: bold"
            action="{!markPaymentPaid}" value="Mark Paid">
            <apex:param name="paymentId" value="{!payment.Id}"/>
          </apex:commandLink>
        </apex:column>
<!-- The next two columns use an apex:outputField tag to output -->
<!-- properties of the current object for the row when looping  -->
<!-- through the list the table is based on. It also takes     -->
<!-- the display properties of the underlying object's field    -->
<!-- into account when generating the output, using             -->
<!-- localization where necessary.                             -->
        <apex:column>
          <apex:facet name="header"><b>Due Date</b></apex:facet>
          <apex:outputField value="{!payment.Due_Date__c}"/>
        </apex:column>
        <apex:column>
          <apex:facet name="header"><b>Amount Due</b></apex:facet>
          <apex:outputField value="{!payment.Amount_Due__c}"/>
        </apex:column>
      </apex:dataTable>
    </apex:pageBlock>
<!-- This section is the same as the above section, but displays -->
<!-- pending payments only.                                     -->
    <apex:pageBlock id="pendingBlock" title="Pending Payments">
      <apex:dataTable width="80%" value="{!PendingPayments}"
        var="payment" id="pendingTable" headerClass="headerRow"
        rowClasses="dataRow" styleClass="list">
        <apex:column>
          <apex:facet name="header"><b>Action</b></apex:facet>
          <apex:commandLink style="font-weight: bold"
            action="{!markPaymentPaid}" value="Mark Paid">
            <apex:param name="paymentId" value="{!payment.Id}"/>
          </apex:commandLink>
        </apex:column>
        <apex:column>
          <apex:facet name="header"><b>Due Date</b></apex:facet>
          <apex:outputField value="{!payment.Due_Date__c}"/>
        </apex:column>
        <apex:column>
          <apex:facet name="header"><b>Amount Due</b></apex:facet>
          <apex:outputField value="{!payment.Amount_Due__c}"/>
        </apex:column>
      </apex:dataTable>
    </apex:pageBlock>
    
<!-- This section is the same as the above two sections, but -->
<!-- only displays Paid payments and does not have an Action -->
<!-- column since there's no need for it.                   -->
    <apex:pageBlock id="paidBlock" title="Paid Payments">
      <apex:dataTable width="80%" value="{!PaidPayments}"
        var="payment" id="paidTable" headerClass="headerRow"
        rowClasses="dataRow" styleClass="list">
        <apex:column>
          <apex:facet name="header"><b>Due Date</b></apex:facet>
          <apex:outputField value="{!payment.Due_Date__c}"/>
        </apex:column>
        <apex:column>
          <apex:facet name="header"><b>Amount Due</b></apex:facet>
          <apex:outputField value="{!payment.Amount_Due__c}"/>
        </apex:column>
      </apex:dataTable>
    </apex:pageBlock>
  </apex:form>
We will begin the last step of making the page the default display for the  Scheduled Invoice object in the next post.

Monday, 8 November 2010

Testing Apex Triggers

It’s been awhile since my last post but that was primarily due to the Giants winning the World Series last week. Between the in street celebrations and the victory parade I have not found time to even study. That being said everything is over now and I no longer have any excuses to put off my work. So let’s get to it….

Since both Apex triggers have been created we need to start testing them. Begin by going to the Scheduled Invoice table and creating a new Scheduled Invoice. We have two triggers so we will set the ‘Duration’ to two and leave the schedule type as ‘Monthly’.  This will add the two scheduled payments to the scheduled payment list for invoice. At this point the scheduled payment list should only be showing the scheduled payment ID. Before we correct this display issue we will edit each payment by changing the status to ‘Paid’. The invoice should now read ‘Paid in Full’.

By making this simple edit we have highlighted two other issues with our application. Marking payments as ‘Paid’ is more work than needed since we are changing only a single value. This basically means that we never have to go from a Paid Status to Pending or Past due (of course this is theoretically speaking). That being said we should never have to manually mark a payment as late; that should be conducted by the system.

Before we cover automatically marking late payments in the workflow section, we need to correct the display and usability issues. VisualForce pages are utilized to complete these tasks; which we will dive into with the next post.

Monday, 1 November 2010

Apex Trigger #2

I hope everyone enjoyed their Halloween weekend. Halloween weekend in San Francisco is amazing; as is every weekend I have spent here. Out of all the cities I have ever been to, east coast and west coast, San Francisco is hands down the most fun. That being said not everything is about my wild nights in the city; my time is primarily focused on becoming a better developer. This leads us into creating our 2nd Apex trigger…. (I’m really good at transitions)

We will utilize the Apex Code editor again to develop our second trigger.  Here is a repeat screen shot of what the editor looks like on the Salesforce page:



The trigger we are creating will maintain the invoice’s payment status based on the scheduled payments. Begin by opening the Scheduled Payment object definition by going to ‘Setup’, ‘Build’, then ‘Objects’. Scroll down to the triggers section and hit ‘New’. Replace the blank trigger template with the following code:

// This trigger scans the list of updated Scheduled Payments 
// and updates the invoice status if it has changed as a result
// of one of the payments becoming past due or a payment has
// been made.
trigger ScheduledPayment_After_Update on Scheduled_Payment__c
  ( after update )
{
    // Apex Code's maximum batch size for updates, inserts and
    // deletes. The final key word indicates a constant.
    final Integer MAX_BATCH_SIZE = 200; 
    List<Scheduled_Payment__c> statusChanges;
    List<Scheduled_Invoice__c> updateInvoices;
    List<Scheduled_Invoice__c> queryResults;
    Set<Id> invoiceIds = new Set<Id>();
    statusChanges = new List<Scheduled_Payment__c>();
    updateInvoices = new List<Scheduled_Invoice__c>();
    // Loop through the updated payments and see if any statuses changed.
    // If they did, add them to the statusChanges list.
    // The trigger object has two properties containing lists of updated
    // objects, new and old. For insert triggers only the new property
    // has values.
    for ( Integer x = 0; x < trigger.new.size(); x++ )
    {
        if ( trigger.new[x].Status__c != trigger.old[x].Status__c )
            statusChanges.add( trigger.new[x] );
    }
    // If there aren't any status changes, exit.
    if ( statusChanges.size() == 0 )
        return;
    // Loop through the list of updated payments and get all the
    // unique invoice IDs.
    // Adding the Ids to a set will ensure that no Ids are
    // duplicated within the list.
    for ( Scheduled_Payment__c payment : statusChanges)
    {
        invoiceIds.add( payment.Invoice__c );
    }
  
    // Query both the invoice object and the related
    // payment objects at once to retrieve their status.
    // Only query invoices in invoice ID set.
    // Querying child objects is similar to a correlated sub-query
    // but the join to the parent object is implicit.
    queryResults = [SELECT Id, Status__c, (SELECT Id, Status__c
        FROM Scheduled_Payments__r) FROM Scheduled_Invoice__c
        WHERE Id IN :invoiceIds];
  
    // Loop through the results and check the status of the
    // payments for the affected invoices and add the invoice
    // to the update list if the status needs changing.
    for ( Scheduled_Invoice__c invoice : queryResults )
    {
        String newStatus = 'Paid in Full';
        
        // Loop through the Scheduled Payment child objects
        // of this invoice, using the Master-Detail relationship
        // you defined previously. The relationship name has
        // "__r" appended to it to indicate that it's a custom
        // relationship.
        // The status of each payment is checked. If any
        // payment is past due, the invoice is marked past due
        // and if all payments are paid, the invoice is marked
        // as paid in full, otherwise the invoice is marked as current.
        for ( Scheduled_Payment__c payment : 
            invoice.Scheduled_Payments__r )
        {
           if ( payment.Status__c != newStatus )
           {
               if ( payment.Status__c == 'Pending'
                   && newStatus == 'Paid in Full' )
               {
                   newStatus = 'Current';
               }
               else if ( payment.Status__c == 'Past Due' )
               {
                   newStatus = 'Past Due';
               }
           }
        } // payments loop
  
        if ( invoice.Status__c != newStatus )
        {
            // The invoice status needs to be changed.
            // Change the invoice's status and add it to the list
            // of invoices to update. Salesforce.com will only modify
            // the actual field you update in code, it will not re-save
            // the values you pulled from the database.
            invoice.Status__c = newStatus;
            updateInvoices.add( invoice );
        }
  
        // If you're at the batch size limit, update Salesforce.com
        // and clear the update list.
        if ( updateInvoices.size() == MAX_BATCH_SIZE )
        {
            Database.update( updateInvoices );
            updateInvoices.clear();
        }
    } // queryResults loop.
  
    // Update Salesforce.com if there are any pending changes.
    if ( updateInvoices.size() > 0 )
    {
        Database.update( updateInvoices );
    }
}
This trigger fires after a payment is updated, and if the payment's status changes it checks to see if the parent invoice needs its status updated as well. For example if the payment is past due, the parent invoice changes its status to past due.  

Now that both triggers have been completed we will need to test them, which will do in our next post.  

Monday, 25 October 2010

Apex Triggers

So this weekend, following the Giants punching their trip to the World Series (Fear the Beard), I officially registered for Dreamforce 2010. I advise that everyone who will be attending this year to create their Chatter profile and sign-up for sessions using the Agenda Builder as soon as possible. Also any recommendations would be appreciated since it will be my first time attending any type of cloud computing event.

Ok so let’s jump into Apex triggers. If you recall from my previous post, we will use Apex Code to create these triggers and complete our scheduled payments. Apex Triggers operate like most standard database triggers, you define the trigger name for when the trigger fires and write code to act on the event. This can be before or after insert, update, or delete.

For our application we will be writing two triggers. The first trigger will create scheduled payment objects for an invoice when the invoice is created, and the second trigger will update the invoice's status when the status of a scheduled payment changes. Begin by opening the Scheduled Invoice object definition by clicking ‘Setup’, then ‘Build’, and finally ‘Objects’. At the bottom of the page you will find the ‘Triggers’ section, at which point you will select ‘New’. This will bring up the Apex Code editor, which you will see in the following screen shot:



For our first Trigger we need to replace the blank template by copying the following code and pasting it into the editor:


// After a new entry is insert into the Scheduled Invoice custom object table
// this trigger will fire and create all the scheduled payment objects for
// that invoice.
trigger ScheduledInvoice_After_Insert on Scheduled_Invoice__c
    ( after insert ) 
{
    // Apex Code's maximum batch size for updates, inserts
    // and deletes. The final key word indicates a constant.
    final Integer MAX_BATCH_SIZE = 200; 
    List<Scheduled_Payment__c> newPayments;
    Date endDate;
    Boolean isMonthly = false;
    Integer daysInPeriod = 0;
    Integer numberOfPeriods = 0;
    Double paymentPerPeriod = 0;
    Date dueDate;
    
    newPayments = new List<Scheduled_Payment__c>();
  
    // Loop through the new invoices and create scheduled payments
    // for each one depending on their settings.
    // The trigger object has two properties containing lists of updated
    // objects, new and old. For insert triggers, only the new property
    // has values.
    // The for loop below is similar to a foreach loop in C#. The C#
    // equivalent would be foreach ( Object var in varArray )
    for ( Scheduled_Invoice__c invoice : trigger.new )
    {
        // Convert the Duration in Months to an actual number of
        // periods. If the schedule type is monthly, then the number
        // of periods is equal to the duration in months, otherwise
        // you need to calculate it.
        if ( invoice.Schedule_Type__c == 'Monthly' )
        {
            numberOfPeriods = invoice.Duration_in_Months__c.intValue();
            isMonthly = true;
        }
        else
        {
            Integer numberOfDays;
  
            // For weekly and bi-weekly, calculate the end date first.
            endDate = invoice.Effective_Date__c.addMonths( 
                invoice.Duration_in_Months__c.intValue() );
            // Next, get the number of days.
            numberOfDays = invoice.Effective_Date__c.daysBetween(
                endDate );
            // Setup the number of days in the period for weekly and
            // bi-weekly payments.
            if ( invoice.Schedule_Type__c == 'Weekly' )
                daysInPeriod = 7;
            else
                daysInPeriod = 14;
            // Divide the number of days by the number of days in the
            // period to get the number of periods.
            numberOfPeriods = Math.floor( numberOfDays / 
                daysInPeriod ).intValue();
        }            
  
        // Calculate the payment per period.
        paymentPerPeriod = invoice.Total_Amount_Due__c / 
            numberOfPeriods;
        
        // Generate a new scheduled payment object for each
        // period of the invoice.
        for ( Integer x = 0; x < numberOfPeriods; x++ )
        {
            // Calcualte the due date for this period.
            if ( isMonthly )
            {
                dueDate = invoice.Effective_Date__c.addMonths( x + 1 );
            }
            else
            {
                dueDate = invoice.Effective_Date__c.addDays( 
                    daysInPeriod * ( x + 1 ) );
            }
            
            // Create the new scheduled payment object and add it
            // to the list of new payment objects to be inserted.
            // For SObjects (Salesforce Objects) you can specify the
            // property values in the constructor by using the syntax
            // <Property Name> = <value>.
            newPayments.add( new Scheduled_Payment__c(
                Invoice__c = invoice.Id, Status__c = 'Pending',
                Due_Date__c = dueDate,
                Amount_Due__c = paymentPerPeriod ) );
  
            // If you've hit the maximum batch size, insert the new
            // data and clear the list.
            if ( newPayments.size() == MAX_BATCH_SIZE )
            {
                Database.insert( newPayments );
                newPayments.clear();
            }
        }
    }
  
    // If you still have data you need to insert, insert it now.
    if ( newPayments.size() > 0 )
    {
        Database.insert( newPayments );
  }
}

Once again the final step is to simply click ‘Save’.  Normally this code would be placed in a completely separate Apex Code class editor, but in order to be concise we will include it directly into the trigger. We will go over Apex Code classes when we learn about VisualForce next week. It will make more sense in that context.

In the next post we will create the second Trigger and test both of them when they are in place.