SCM Apex API Developer Reference

The FinancialForce Accounting API

For complete documentation, sample code, and developer community, visit developer.salesforce.com and developer.financialforce.com.

System Operations

The following operations relate to all FinancialForce services.

GetAPIVersion

Used to get the latest API version.
This operation takes no parameters.
The following value is returned:
Type: Text

GetServiceName

Used to get the name of the service.
This operation takes no parameters.
The following value is returned:
Type: Text

Using the API with Web Services

If you are integrating with FinancialForce through a platform/language not hosted on the Force.com platform, such as Java or .Net, you can make use of the FinancialForce Web Services. These take the same shape and form as their Apex equivalents except that they do require authentication via the standard Force.com Partner Web Service.

As is the case with other Force.com Web Services, the session ID returned by the login() operation must be present in all FinancialForce Web Service calls.

The steps are as follows:

  • Read the appropriate sections of the Force.com Web Services API Developer's Guide before you start. In particular, the "Security and the API" and "Login()" topics.
  • Download the Salesforce Enterprise WSDL file to a place accessible to your development environment - Setup | Develop | API.
  • Call the login() operation to obtain the sessionId, as in the example below. See the Force.com Web Services API Developer's Guide for more examples.
  • Salesforce checks the IP address from which the client application is logging in, and blocks logins from unknown IP addresses. If you get a login error, you must append your security token to the end of your password in order to log in. See "Security Tokens" below for more information.
  • Pass the sessionId to each subsequent call to the FinancialForce API, as shown in the example below.
  • Example (C#)

    SforceService service = new SforceService();
    String sessionId = service.login("user","password").sessionId;
    CODAAPISalesInvoice_7_0Service salesInvoiceService = new CODAAPISalesInvoice_7_0Service();
    salesInvoiceService.SessionHeaderValue = new SessionHeader();
    salesInvoiceService.SessionHeaderValue.sessionId = sessionId;

    Security Tokens

    A security token is an automatically-generated key that you must add to the end of your password in order to log in to Salesforce from an untrusted network. For example, if your password is mypassword, and your security token is XXXXXXXXXX, then you must enter mypasswordXXXXXXXXXX to log in.

    When accessing Salesforce from outside of your company's trusted networks, you must append a security token to your password to log in to the API or a desktop client.

    To reset your security token:

  • Navigate to Setup | Personal Setup | My Personal Information | Reset My Security Token.
  • Click Reset Security Token.
  • For security reasons, your security token is delivered to the email address associated with your account.

    Viewing FinancialForce API Apex Classes

    To view a list of all the relevant Apex classes:

  • Click Setup | Develop | Apex Classes.
  • From the View field, select the "FinancialForce API Classes" option. A list of all relevant Apex classes is displayed.
  • Click the relevant WSDL link to display its Web Services Definition Language (WSDL) document.
  • Using Custom Triggers on FinancialForce Accounting Objects

    FinancialForce Accounting API calls cannot be made within custom triggers on FinancialForce Accounting objects. To work around this limitation, make the FinancialForce Accounting API call from a different context such as a Batch Apex job.

    Writing Apex Tests

    When developing against the API you will likely be doing one or more of the following types of API integrations:

  • Use Case 1: Calling an FFA API directly to perform a task
  • Use Case 2: Calling a Salesforce DML API directly to perform a record operation
  • Use Case 3: Implementing a custom Apex Trigger
  • This code sample illustrates how to setup a basic environment within an Apex Test, to allow this type of code to be covered and tested as per the platform requirements and best practices.

    Note

    The CODAYearWebService and CODACompanyWebService classes are only supported in Apex Test context in accordance with this example.

    Code Sample

    @IsTest
    private class CreateTransactionTest {
    @IsTest
    private static void createTransaction() {
    // Setup Company and User association within runAs to avoid mixed DML restriction
    Group companyGroup = null;
    System.runAs([select Id from User where Id = :UserInfo.getUserId()][0]) {
    Test.startTest();
    // Create Company
    c2g__codaCompany__c company = new c2g__codaCompany__c();
    company.Name = 'ApexTestCompany';
    company.RecordTypeId = Schema.SObjectType.c2g__codaCompany__c.RecordTypeInfosByName.get('VAT').RecordTypeId;
    insert company;
    // Create Company Queue
    c2g.CODACompanyWebService.createQueue(company.Id, 'USD', company.Name);
    // Activate the Company
    c2g.CODAYearWebService.calculatePeriods(null); // Workaround to bug in company API's, safe to remain once fixed
    c2g.CODACompanyWebService.activateCompany(company.Id, 'USD', company.Name);
    // Assign the User to the Company
    c2g__codaUserCompany__c userCompany = new c2g__codaUserCompany__c();
    userCompany.c2g__Company__c = company.Id;
    userCompany.c2g__User__c = UserInfo.getUserId();
    insert userCompany;
    // Assign the User to the Company Queue
    String queueName = 'FF ' + company.Name;
    companyGroup = [select Id from Group where Name = :queueName And Type = 'Queue'];
    insert new GroupMember( GroupId = companyGroup.Id, UseroRGroupId = UserInfo.getUserId());
    Test.stopTest();
    }
    // Assert user logged into the company
    System.assertEquals('ApexTestCompany', c2g.CODAAPICompany_2_0.GetCurrentCompanies(null)[0]);
    // Create Year and Periods
    c2g__codaYear__c yr = new c2g__codaYear__c();
    yr.Name = String.valueOf(Date.today().year());
    yr.OwnerId = companyGroup.Id;
    yr.c2g__NumberOfPeriods__c = 12;
    yr.c2g__AutomaticPeriodList__c = true;
    yr.c2g__StartDate__c = Date.valueOf(Date.today().year() + '-01-01 00:00:00');
    yr.c2g__EndDate__c = Date.valueOf(Date.today().year() + '-12-31 00:00:00');
    yr.c2g__PeriodCalculationBasis__c = 'Month End';
    insert yr;
    c2g.CODAYearWebService.calculatePeriods(yr.Id);
    // Create Accounting Currency?
    if(UserInfo.isMultiCurrencyOrganization()) {
    c2g__codaAccountingCurrency__c testCurrency = new c2g__codaAccountingCurrency__c();
    testCurrency.Name = 'USD';
    testCurrency.c2g__DecimalPlaces__c = 2;
    testCurrency.c2g__Home__c = true;
    testCurrency.c2g__Dual__c = true;
    insert testCurrency;
    }
    // Create General Ledger Account
    c2g__codaGeneralLedgerAccount__c gla = new c2g__codaGeneralLedgerAccount__c();
    gla.Name = 'Brochures';
    gla.c2g__ReportingCode__c = 'xyz1';
    gla.c2g__Type__c = 'Balance Sheet';
    insert gla;
    // Create and Post a test Journal
    c2g__codaJournal__c journal = new c2g__codaJournal__c();
    journal.c2g__JournalDate__c = Date.today();
    journal.OwnerId = companyGroup.Id;
    insert journal;
    c2g__codaJournalLineItem__c journalLine1 = new c2g__codaJournalLineItem__c();
    journalLine1.c2g__LineType__c = 'General Ledger Account';
    journalLine1.c2g__Journal__c = journal.Id;
    journalLine1.c2g__GeneralLedgerAccount__c = gla.Id;
    journalLine1.c2g__Value__c = 42;
    c2g__codaJournalLineItem__c journalLine2 = new c2g__codaJournalLineItem__c();
    journalLine2.c2g__LineType__c = 'General Ledger Account';
    journalLine2.c2g__Journal__c = journal.Id;
    journalLine2.c2g__GeneralLedgerAccount__c = gla.Id;
    journalLine2.c2g__Value__c = -42;
    insert new List { journalLine1, journalLine2 };
    c2g.CODAAPIJournal_12_0.PostJournal(null, c2g.CODAAPICommon.getRef(journal.Id, null));
    System.assertEquals(0, [select c2g__DocumentTotal__c from c2g__codaTransaction__c LIMIT 1][0].c2g__DocumentTotal__c);
    } }

    IMPORTANT NOTE #1: The above example uses the Salesforce API to create Journals. For this part you must have the FinancialForce Journal Extension package installed.

    IMPORTANT NOTE #2: The above code is only supported from v13.2 onwards. As a workaround on earlier versions, when needing to cover code in a custom Apex Trigger (as per Use Case 3) consider leveraging an Apex Test like the one below. However once upgraded you should move to the recommended approach above. Unfortunately there are no workarounds on earlier versions for Use Cases 1 and 2.

    @IsTest
    private class UpdateTransactionTest {
    // This test is designed to allow for coverage and testing of custom Apex Triggers
    // (For v13.2 onwards, please see API documentation for an example not requiring SeeAllData)
    @IsTest(SeeAllData=true)
    private static void createTransaction() {
    List records = [select Id from c2g__codaTransaction__c limit 1];
    System.assert(1 == records.size(),
    'You must have at least one transaction in the system for this test to work');
    update records;
    }
    }

    Posting Sales Documents That Have Their Tax Value Calculated by AvaTax

    FinancialForce Accounting can be enabled to use Avalara®'s AvaTaxTM product for the calculation of Sales and Use Tax (SUT). But it is important to note that Salesforce imposes a restriction that prevents callouts to external systems when there are pending operations in the same database transaction. (You can get more information about this restriction from the Salesforce Help topic www.salesforce.com/us/developer/docs/apexcode/Content/apex_callouts_timeouts.htm.) So if your FinancialForce Accounting org is enabled to use AvaTax, any existing code you have written to post sales invoices and sales credit notes may run into unexpected errors if, for example, it undertakes database updates before making the call to PostInvoice, PostCreditNote, BulkPostInvoice or BulkPostCreditNote.

    If you are in this position, you can work around the issue by doing either of the following:

  • The recommended workaround is to use the new ScheduleInvoicesForPosting and ScheduleCreditNotesForPosting services to post your sales documents (either singly or in bulk). These services batch up the documents for posting by a scheduled job, and will deal with error handling and retry for the end user.
  • Alternatively you can modify your code to use asynchronous Apex, such as Batch Apex or @future, to separate pending operations (e.g. database updates) from the posting calls
  • For information about how to setup FinancialForce Accounting to use AvaTax for SUT calculation, see the FinancialForce Accounting Help topic "Setting up Tax Calculation for Sales and Use Tax".

    Note

    The ScheduleInvoicesForPosting and ScheduleCreditNotesForPosting services can be used to post sales documents even when the org is not integrated with AvaTax. But remember that the documents are batched up for posting by a scheduled job; they are not posted immediately. For details of how to set up the scheduler, see the FinancialForce Accounting Help topic "Setting up the Background Posting Scheduler".

    © Copyright 2009–2022 FinancialForce.com, inc. All rights reserved. Various trademarks held by their respective owners.