FinancialForce applications are native to the Salesforce Platform, and are as such accessible to developers through the Salesforce APIs (known as the Enterprise API to those who prefer Web Services) and also to native Salesforce Platform developers via Apex utilizing SOQL (Salesforce Object Query Language) and DML (Data Manipulation Language). Because FinancialForce applications are typically more than just about manipulating records (creating and updating Invoices, Credit Notes etc), we provide our own additional API, the FinancialForce API, which is also available to Web Service callers and native integrations via Apex calls.

Our additional FinancialForce API provides access to some of our core business processes and calculation engines, such as the ability to generate valid credit and debit entries in our transaction module with the appropriate balancing entries, analysis, currency and tax calculations applied. This process, known as "Posting" and can be invoked by calling the FinancialForce Post API. This is one of many such business process operations already available through the FinancialForce API today.

Now available since our Winter '11 release and subsequent extension packages (available from your Xtra login) is a new ability to manipulate records representing certain objects (Sales Invoice, Payable Invoice etc..) via the Salesforce APIs. This is specifically either via Apex DML or the equivalent Enterprise Web Service API methods. This now provides an even closer native experience for new developers and an exciting new alternative to those familiar with the existing FinancialForce API record manipulation operations, Create and Update.

The following sections will explain this new approach in more detail in terms of benefits, best practice and use in conjunction with the existing FinancialForce API. Also highlighting some additional fields that have been provided to give finer control of the underlying trigger behaviours around field value defaulting. The Question and Answers section is also useful for those already familiar with the existing FinancialForce API and also those who just want to learn more.

* This capability is only available on certain objects please refer to the Availability section below.

Creating and Posting an Invoice

The following code shows how to create a basic Sales Invoice using Apex DML and then using the FinancialForce API to post it. It also demonstrates how custom fields added by your administrator can also be set. Note that code used to obtain ID references for related records is not shown. Please ensure you observe good practice around bulkification by writing your SOQL to obtaining such IDs, especially when writing code within loops.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Insert Invoice header
c2g__codaInvoice__c invoice =
        new c2g__codaInvoice__c(c2g__Account__c = invoiceAccountId);
insert invoice;
// Insert Invoice line items
List invoiceLines = new List();
invoiceLines.add(
        new c2g__codaInvoiceLineItem__c(
                c2g__Invoice__c = invoice.Id,
                c2g__Product__c = product1Id,
                c2g__Quantity__c = 10,
                WorkOrderLineRef__c = 'W0123'));
invoiceLines.add(
        new c2g__codaInvoiceLineItem__c(
                c2g__Invoice__c = invoice.Id,
                c2g__Product__c = product2Id,
                c2g__Quantity__c = 2,
                WorkOrderLineRef__c = 'W0456'));
insert invoiceLines;
// Post the Invoice
c2g.CODAAPICommon.Reference ref = new c2g.CODAAPICommon.Reference();
ref.Id = invoice.Id;
c2g.CODAAPISalesInvoice_3_0.PostInvoice(null, ref);
//Note: The above code initializes the fields using the constructor
//syntax, this has been found to be more efficient in respect to
//statement governor usage.

Updating an Invoice

The following example illustrates how using the sub-select SOQL query syntax both the invoice header and lines can be retrieved for further manipulation. It also demonstrates how an additional line can be added. Note it is not necessary to have retrieved the invoice lines for this part of the sample.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Retrieve the Invoice and lines
c2g__codaInvoice__c invoice = [
    select
        Id,
        c2g__InvoiceDescription__c,
        (select c2g__LineDescription__c, c2g__Quantity__c from c2g__InvoiceLineItems__r)
    from c2g__codaInvoice__c
    where Name = 'SIN000039'
];
// Update the Invoice
invoice.c2g__InvoiceDescription__c = 'Changes to invoice for ' + System.today();
update invoice;
// Update the Invoice Line 1
c2g__codaInvoiceLineItem__c invoiceLine1 = invoice.c2g__InvoiceLineItems__r[0];
invoiceLine1.c2g__Quantity__c = 2;
invoiceLine1.c2g__LineDescription__c = 'Updated quantity on ' + System.today();
update invoiceLine1;
// Add a new invoice line
insert new c2g__codaInvoiceLineItem__c(
    c2g__Invoice__c = invoice.Id,
    c2g__Product__c = product3Id,
    c2g__Quantity__c = 2,
    WorkOrderLineRef__c = 'W0789'
);

Controlling the Field Value Defaulting Behaviours for Sales Invoice

There are many fields available on FinancialForce objects. Yet the above examples are quite simple in terms of the fields being set. This is due to the FinancialForce trigger behaviours defaulting other field values automatically for you. However, in some cases, you may wish to override this default behaviour. If you observe the layout used by these objects within the browser, as shown below, you will see that there are associated Boolean fields that can be used to disable various defaulting behaviours for associated fields.

invoicedetail

As with the user experience when utilising these layouts in the browser, the same applies during your code, such as the samples above. The defaulting checkboxes are all automatically set to True when you first insert a record (Salesforce applies defaults during the trigger phases). Then, once the record is written to the database, they are set to False. So, after initial creation of the records, during subsequent updates they are set to False and no defaulting takes place. To better appreciate this behaviour it is well worth spending some time utilizing these layouts and creating some records through the browser user interface during your development.

We chose this strategy for controlling field defaulting as it is simpler to understand and reflect in the user interface. The user or the Apex code opts in or out of the defaulting behaviour explicitly themselves in this way. There are no rules that determine when a field is overwritten with a default or not, other than these checkboxes.

Controlling the Field Value Defaulting Behaviours for Journal

The following code example shows the previous Sales Invoice scenario but with the Jornal object.

1
2
3
4
5
6
7
8
9
10
11
12
//Insert Journal header, specify Derive Currency and Period values
c2g__codaJournal__c journal = new c2g__codaJournal__c();
journal.c2g__Type__c = 'Manual Journal';
journal.c2g__JournalDate__c = System.today();
journal.c2g__OwnerCompany__c = companyId;
journal.ffgl__DeriveCurrency__c = true;
journal.ffgl__DerivePeriod__c = false;
insert journal;
// Reapply the defaulting to an existing journal
c2g__codaJournal__c journalToUpdate = [select ffgl__DerivePeriod__c from c2g__codaJournal__c where Name = 'JNL000112'];
journalToUpdate.ffgl__DerivePeriod__c = true; // Enable defaulting for Period, disabled automatically after the update
update journalToUpdate;

Error Handling and Database Transaction Management

Unlike the FinancialForce API record manipulation equivalents, Create and Update, validation errors relating to API field values your code sets do not automatically rollback earlier DML / database changes (this is a standard Apex behaviour) relating to FinancialForce objects. As such it is the developer’s responsibility to consider error handling and transactional semantics when taking the approach described in this article. This also provides more control to the developer in situations where advanced database transaction management is required.

For example, the following extension to the earlier sample utilizes the Apex Savepoint feature to ensure if any error occurs during the process of creating the relevant records, none remain on the database. Note that Salesforce only automatically rolls back database changes when errors are left unhandled, this may not always be a desirable solution for your end users.

For example, in cases where Visualforce is used, a better user experience is to utilize the ApexPages.addMessages and tag to surface such errors and prompt corrections. So in cases, where DML exceptions are “caught” extra care must be taken when handling errors in these cases.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Capture rollback / save point before creating and posting the Invoice
System.Savepoint createInvoiceSavePoint = Database.setSavepoint();
try
{
    // Insert Invoice header
    c2g__codaInvoice__c invoice = new c2g__codaInvoice__c();
    // ...
    insert invoice;
    // Insert Invoice line items
    List invoiceLines = new List();
    // ...
    insert invoiceLines;
    // Post the Invoice
    // ...
    c2g.CODAAPISalesInvoice_3_0.PostInvoice(null, ref);
}
catch (Exception e)
{
    // Rollback any partial invoice written to the database
    Database.rollback(createInvoiceSavePoint);
    // Display errors to the user via
    ApexPages.addMessages(e);
}

Further Documentation and References

The main source of information regarding these objects and fields can be found in the FinancialForce API Reference Guide. As you can see in the above examples, if you remove the c2g__ prefix and __c suffix the field names are identical to those described.

There is also the option of using the Salesforce browser tools to browse our objects, under the Setup > Create > Objects menu. In respect to understanding the fields controlling the aforementioned defaulting behaviour. It is advisable to review the layouts via the browser user interface to understand which fields you may want to override during insert. You can obtain the actual API field names by reviewing the object fields under Setup > Create > Objects again.

You may also want to take a look at a SchemaSpy, it is a tool that will generate graphic diagrams of all custom objects in your organisation, including those you’ve created for your integrations. http://code.google.com/p/force-metadata-jdbc-driver/. In due course we will be publishing prebuilt diagrams of the objects referenced in this article, and later some further diagrams for other areas of the system to aid the writing of SOQL queries.

Availability

 The following table cross references by the required extension package the objects that presently support manipulation via the Salesforce API.

FinancialForce Extension Package *
FinancialForce Object
Accounts Payable Extension c2g__codaPurhaseInvoice__c
c2g__codaPurchaseInvoiceLineItem__c
c2g__codaPurchaseInvoiceExpenseLineItem__c
c2g__codaPurchaseCreditNote__c
c2g__codaPurchaseCreditNoteLineItem__c
c2g__codaPurchaseCreditNoteExpLineItem__c
Cash Entry Extension c2g__codaCashEntry__c
c2g__codaCashEntryLineItem__c
Journal Extension c2g__codaJournal__c
c2g__codaJournalLineItem__c

From v10 onwards, the following packages have been merged into the main FinancialForce Accounting application.

Package merged into FFA **
FinancialForce Object
Billing Extension c2g__codaInvoice__c
c2g__codaInvoiceLineItem__c
c2g__codaInvoiceInstallmentLineItem__c
c2g__codaScheduleLineItem__c
c2g__codaCreditNote__c
c2g__codaCreditNoteLineItem__c

As a developer you should take into account that the Billing Extension package is no longer needed, so although it might be installed in your org, you should not use it. The code example above, can help you to work with other extensions packages, however, we recommend you to use c2g namespace instead of the ffbilling one, as illustrated in the example code below.

1
2
3
4
5
6
7
8
9
10
11
12
// Insert Invoice header, specificy our own Period and Due Dates
c2g__codaInvoice__c invoice = new c2g__codaInvoice__c();
invoice.c2g__DerivePeriod__c = false; // Disable defaulting for Period
invoice.c2g__DeriveDueDate__c = false; // Disable defaulting for Due Date
invoice.c2g__Account__c = invoiceAccountId;
invoice.c2g__Period__c = alternatePeriodId;
invoice.c2g__DueDate__c = System.today();             
insert invoice;
// Reapply the defaulting to an existing Invoice
c2g__codaInvoice__c invoiceToUpdate = [select c2g__DerivePeriod__c from c2g__codaInvoice__c where Name = 'SIN000039'];
invoiceToUpdate.c2g__DerivePeriod__c = true; // Enable defaulting for Period, disabled automatically after the update
update invoiceToUpdate;

* Packages are available through FinancialForce Community - AppExchange Packages. Note these packages also provide a new User Interface experience, please refer to the associated PDF for more details.

** FinancialForce Accounting

We are rolling out support for further objects throughout the year, please check back here for updates.

Conclusion

The ability to utilize DML against these objects is a very powerful feature, that gives greater flexibility and control to the developer. That said, please be sure to be fully confident with advanced aspects of dealing with SOQL, DML and Database Transactions with Apex, including managing code within governors.

Saleforce has full documentation and further examples on these areas on their developer site, http://developer.force.com. As FinancialForce is an accounting system, and as such its financial information subject to audit, it is not always possible to delete information completely. If at all possible fully test your integrations in a DE or Sandbox environment first.

We hope that this capability gives even greater flexibility to those building integrations with our applications. In a future article we will give more examples of how areas like Custom Object Loader / Data Loader, Salesforce Workflow, Approval Workflows and the new Salesforce Flow engine can be used to greater effect with this new flexibility.

Q & A

  •  Q1: Will the equivalent record manipulation functionality within the FinancialForce API still work and be supported if I use this approach?
     Answer: Yes, both are compatible alongside each other.
  •  Q2: Do I have to change anything in my current integrations?
     Answer: No, both API approaches are supported and can be used together side by side if you wish to start using the above approach for new extensions to your existing integrations.
  •  Q3: Can I starting using the DML approach even though I am using the FinancialForce API?
     Answer: Yes. In fact if you want to make subsequent updates to an invoice (for example) created with the FinancialForce API via DML you can!
  •  Q4: Are there any functional differences between the two API strategies when creating and updating?
     Answer: In respect to the underlying product functionality features, no. However the FinancialForce API equivalent operations do provide the added convenience of resolving Names to IDs for records referenced, such as Accounts, Products and General Ledger for example, saving you some coding *. Also as described above, the FinancialForce API will also manage database rollback of all related records for you, should validation errors occur. However the use of Salesforce Data API's does provide access to custom fields for documents and is more flexible in terms of making more granular changes or additions to records. Greater care around the use of governors in your code need be considered when using the Salesforce API's.
    *Having the FinancialForce API resolve Names to IDs for you should be used with caution, as the additional Apex script execution required will effect governor usage for large data volumes. Always test volumes of your solutions to be sure if you’re dealing with large volumes.
  •  Q5: Why have FinancialForce decided to open up Salesforce API access to certain objects this way?
     Answer: For many seasoned Apex developers and also learning the platform for the first time, using the built in database operations (DML) is more familiar. Though it does require slightly more knowledge of our database schema.
  •  Q6: How will I post documents with this new Salesforce API approach?
     Answer: This capability is only an alternative to manipulating records such as Invoices, Credit Notes etc. The business processing for generating our accounting transactions is complex and so our existing FinancialForce API is still the only way to invoke this logic. Note: DML access to our transaction objects is still blocked for data integrity and security reasons.
  •  Q7: I am a .Net or Java developer. Which is the best API to use?
     Answer: Webservices are available for both FinancialForce and Salesforce API for use in these environments. You may prefer to use the more structured FinancialForce API in these environments over the more generic Salesforce API. This will also ensure you don’t have to worry about the transactional semantics in these environments if validation errors occur.
  •  Q8: I am an Apex developer. Which API, FinancialForce or Salesforce, is best for creating and updating?
     Answer: If you are creating or updating FinancialForce records and are a proficient developer in Apex you might find the DML approach more familiar and flexible. Please observe standard Salesforce best practices for governors, such as bulkifcation. Also please observe good practice around managing data transactions, see the discussion above. If you are wanting to perform any kind of business process operation, such as posting, please use the FinancialForce API.