Invoice Layout Extension

The Invoice Layout Extension is a report extension for printing invoices.

It is used on the 

  • Accounting file 
    • Menu Reports > Customers > Print invoices...
  • In the Estimate & Invoice
    • Menu Invoices > Print invoice...
    • Menu Invoices > Print estimate...

Structure of the extensions

The Invoice Layout Extension need to contains the following elements:

  • The extension attribute with 
    @task = report.customer.invoice.
  • printDocument(jsonContent, repDocObj, repStyleObj [, prefSelected])
    the main function that is called by the program
    Is use the content of the invoice json object to add element to the reportDocObj.
  • settingsDialog() (optional)
    called from user to set up parameters like colour or additional text.
  • getPrintPreferences() (optional)
    returns a JSON object with the available print options.
    Invoice Json Properties.

Extension attributes

// @id = scriptfilename.js
// @api = 1.0
// @pubdate = yyyy-mm-dd
// @publisher = yourName
// @description = script description
// @task = report.customer.statement

Function printDocument

The main function is printDocument(jsonStatement, repDocObj, repStyleObj [, format]). The  parameter jsonStatement object contains the data, repDocObj is the document object and repStyleObj is the stylesheet object where you can add styles.

function printDocument(jsonStatement, repDocObj, repStyleObj) {
  var param = initParam();
  var savedParam = Banana.document.getScriptSettings();
  if (savedParam.length > 0) {
    param = JSON.parse(savedParam);
    param = verifyParam(param);
  }
  printInvoice(jsonInvoice, repDocObj, repStyleObj, param);
}

Function settingsDialog

The function settingsDialog() is called from Banana when you select the button Params... from dialog Manage apps. You can write any code you need for your script.

/*Update script's parameters*/
function settingsDialog() {
   var param = initParam();
   var savedParam = Banana.document.getScriptSettings();
   if (savedParam.length > 0) {
      param = JSON.parse(savedParam);
   }   
   param = verifyParam(param);
   ...
   var paramToString = JSON.stringify(param);
   var value = Banana.document.scriptSaveSettings(paramToString);
}

 

Invoice Json Object

Data structure used by the Invoice Layout Extension to print an invoice. 


{
    "billing_info": {
        "discount": {
            "amount_vat_exclusive": "2.20"
        },
        "due_date": "2020-06-17",
        "total_advance_payment": "",
        "total_amount_vat_exclusive": "122.15",
        "total_amount_vat_exclusive_before_discount": "124.35",
        "total_amount_vat_inclusive": "131.56",
        "total_amount_vat_inclusive_before_discount": "133.93",
        "total_categories": [],
        "total_discount_percent": "1.8",
        "total_discount_vat_exclusive": "2.20",
        "total_discount_vat_inclusive": "2.37",
        "total_rounding_difference": "",
        "total_to_pay": "131.56",
        "total_vat_amount": "9.41",
        "total_vat_amount_before_discount": "9.58",
        "total_vat_codes": [
            {
                "total_amount_vat_exclusive": "122.15",
                "total_amount_vat_inclusive": "131.56",
                "total_vat_amount": "9.41",
                "vat_code": "V77"
            }
        ],
        "total_vat_rates": [
            {
                "total_amount_vat_exclusive": "122.15",
                "total_amount_vat_inclusive": "131.56",
                "total_vat_amount": "9.41",
                "vat_rate": "7.70"
            }
        ]
    },
    "creator_info": {
        "name": "ch.banana.application.invoice.default",
        "pubdate": "2021-09-24",
        "publisher": "Banana.ch SA",
        "version": ""
    },
    "customer_info": {
        "address1": "Via ai Salici 12",
        "address2": "",
        "address3": "",
        "business_name": "La stanza del Te SA",
        "city": "Lugano",
        "country": "",
        "country_code": "CH",
        "courtesy": "",
        "email": "",
        "first_name": "pinco",
        "iban": "",
        "last_name": "",
        "mobile": "",
        "number": "1",
        "phone": "",
        "postal_code": "6900",
        "web": ""
    },
    "document_info": {
        "currency": "CHF",
        "customer_reference": "asdf",
        "date": "2020-06-17",
        "decimals_amounts": 2,
        "description": "Fornitura merce (esempio iva esclusa)",
        "doc_type": "10",
        "locale": "it",
        "number": "3",
        "rounding_totals": "0.05",
        "text_begin": "",
        "title": "Fornitura merce (esempio iva esclusa)",
        "vat_mode": "vat_excl"
        "custom_info": [
            {
                "id": "custom_field_1",
                "title": "Weight",
                "value": "45 kg"
            },
            {
                "id": "custom_field_2",
                "title": "Packages",
                "value": "3"
            }
        ]
    },
    "items": [
        {
            "description": "Te\n1\n2\n3",
            "item_type": "item",
            "mesure_unit": "pz",
            "number": "1000",
            "price": "",
            "quantity": "4.00",
            "total": "",
            "total_amount_vat_exclusive": "19.68",
            "total_amount_vat_inclusive": "21.20",
            "total_vat_amount": "1.52",
            "unit_price": {
                "amount_vat_exclusive": null,
                "amount_vat_inclusive": "5.30",
                "calculated_amount_vat_exclusive": "4.92",
                "calculated_amount_vat_inclusive": "5.30",
                "calculated_vat_amount": "0.38",
                "vat_code": "V77",
                "vat_rate": "7.70"
            },
            "vat_code": "",
            "vat_rate": ""
        },
        {
            "description": "Te",
            "discount": {
                "percent": "30."
            },
            "item_type": "item",
            "mesure_unit": "pz",
            "number": "1000",
            "quantity": "4.00",
            "total": "",
            "total_amount_vat_exclusive": "13.78",
            "total_amount_vat_inclusive": "14.84",
            "total_vat_amount": "1.06",
            "unit_price": {
                "amount_vat_exclusive": null,
                "amount_vat_inclusive": "5.30",
                "calculated_amount_vat_exclusive": "4.92",
                "calculated_amount_vat_inclusive": "5.30",
                "calculated_vat_amount": "0.38",
                "discounted_amount_vat_exclusive": "3.44",
                "discounted_amount_vat_inclusive": "3.71",
                "discounted_vat_amount": "0.27",
                "vat_code": "V77",
                "vat_rate": "7.70"
            }
        },
        {
            "description": "Te",
            "discount": {
                "amount": "1.60"
            },
            "item_type": "item",
            "mesure_unit": "pz",
            "number": "1000",
            "quantity": "4.00",
            "total": "",
            "total_amount_vat_exclusive": "13.74",
            "total_amount_vat_inclusive": "14.80",
            "total_vat_amount": "1.06",
            "unit_price": {
                "amount_vat_exclusive": null,
                "amount_vat_inclusive": "5.30",
                "calculated_amount_vat_exclusive": "4.92",
                "calculated_amount_vat_inclusive": "5.30",
                "calculated_vat_amount": "0.38",
                "discounted_amount_vat_exclusive": "3.44",
                "discounted_amount_vat_inclusive": "3.70",
                "discounted_vat_amount": "0.26",
                "vat_code": "V77",
                "vat_rate": "7.70"
            }
        },
        {
            "description": "Te",
            "item_type": "item",
            "mesure_unit": "pz",
            "number": "",
            "quantity": "10000",
            "total_amount_vat_exclusive": "17.18",
            "total_amount_vat_inclusive": "18.50",
            "total_vat_amount": "1.32",
            "unit_price": {
                "amount_vat_exclusive": null,
                "amount_vat_inclusive": "0.00185",
                "calculated_amount_vat_exclusive": "0.00172",
                "calculated_amount_vat_inclusive": "0.00185",
                "calculated_vat_amount": "0.00013",
                "vat_code": "V77",
                "vat_rate": "7.70"
            }
        },
        {
            "description": "Te",
            "discount": {
                "amount": "0.00035"
            },
            "item_type": "item",
            "mesure_unit": "pz",
            "number": "1000",
            "quantity": "10000",
            "total": "",
            "total_amount_vat_exclusive": "13.93",
            "total_amount_vat_inclusive": "15.00",
            "total_vat_amount": "1.07",
            "unit_price": {
                "amount_vat_exclusive": null,
                "amount_vat_inclusive": "0.00185",
                "calculated_amount_vat_exclusive": "0.00172",
                "calculated_amount_vat_inclusive": "0.00185",
                "calculated_vat_amount": "0.00013",
                "discounted_amount_vat_exclusive": "0.00139",
                "discounted_amount_vat_inclusive": "0.00150",
                "discounted_vat_amount": "0.00011",
                "vat_code": "V77",
                "vat_rate": "7.70"
            }
        },
        {
            "description": "Te",
            "discount": {
                "percent": "3."
            },
            "item_type": "item",
            "mesure_unit": "pz",
            "number": "1000",
            "quantity": "10000",
            "total": "",
            "total_amount_vat_exclusive": "16.67",
            "total_amount_vat_inclusive": "17.95",
            "total_vat_amount": "1.28",
            "unit_price": {
                "amount_vat_exclusive": null,
                "amount_vat_inclusive": "0.00185",
                "calculated_amount_vat_exclusive": "0.00172",
                "calculated_amount_vat_inclusive": "0.00185",
                "calculated_vat_amount": "0.00013",
                "discounted_amount_vat_exclusive": "0.00167",
                "discounted_amount_vat_inclusive": "0.00179",
                "discounted_vat_amount": "0.00013",
                "vat_code": "V77",
                "vat_rate": "7.70"
            }
        },
        {
            "description": "Te",
            "item_type": "item",
            "mesure_unit": "pz",
            "number": "",
            "quantity": "0.00025",
            "total_amount_vat_exclusive": "9.33",
            "total_amount_vat_inclusive": "10.05",
            "total_vat_amount": "0.72",
            "unit_price": {
                "amount_vat_exclusive": null,
                "amount_vat_inclusive": "40200.00",
                "calculated_amount_vat_exclusive": "37325.91",
                "calculated_amount_vat_inclusive": "40200.00",
                "calculated_vat_amount": "2874.09",
                "vat_code": "V77",
                "vat_rate": "7.70"
            }
        },
        {
            "description": "Te",
            "discount": {
                "amount": "8000"
            },
            "item_type": "item",
            "mesure_unit": "pz",
            "number": "1000",
            "quantity": "0.00025",
            "total": "",
            "total_amount_vat_exclusive": "7.47",
            "total_amount_vat_inclusive": "8.05",
            "total_vat_amount": "0.58",
            "unit_price": {
                "amount_vat_exclusive": null,
                "amount_vat_inclusive": "40200.00",
                "calculated_amount_vat_exclusive": "37325.91",
                "calculated_amount_vat_inclusive": "40200.00",
                "calculated_vat_amount": "2874.09",
                "discounted_amount_vat_exclusive": "29897.86",
                "discounted_amount_vat_inclusive": "32200.00",
                "discounted_vat_amount": "2302.14",
                "vat_code": "V77",
                "vat_rate": "7.70"
            }
        },
        {
            "description": "Te",
            "discount": {
                "percent": "25."
            },
            "item_type": "item",
            "mesure_unit": "pz",
            "number": "1000",
            "quantity": "0.00025",
            "total": "",
            "total_amount_vat_exclusive": "7.00",
            "total_amount_vat_inclusive": "7.54",
            "total_vat_amount": "0.54",
            "unit_price": {
                "amount_vat_exclusive": null,
                "amount_vat_inclusive": "40200.00",
                "calculated_amount_vat_exclusive": "37325.91",
                "calculated_amount_vat_inclusive": "40200.00",
                "calculated_vat_amount": "2874.09",
                "discounted_amount_vat_exclusive": "27994.43",
                "discounted_amount_vat_inclusive": "30150.00",
                "discounted_vat_amount": "2155.57",
                "vat_code": "V77",
                "vat_rate": "7.70"
            }
        },
        {
            "description": "Spese di spedizione",
            "item_type": "item",
            "mesure_unit": "",
            "number": "4000",
            "price": "",
            "quantity": "1.00",
            "total": "",
            "total_amount_vat_exclusive": "5.57",
            "total_amount_vat_inclusive": "6.00",
            "total_vat_amount": "0.43",
            "unit_price": {
                "amount_vat_exclusive": null,
                "amount_vat_inclusive": "6.00",
                "calculated_amount_vat_exclusive": "5.57",
                "calculated_amount_vat_inclusive": "6.00",
                "calculated_vat_amount": "0.43",
                "vat_code": "V77",
                "vat_rate": "7.70"
            },
            "vat_code": "",
            "vat_rate": ""
        }
    ],
    "note": [
        {
            "date": null,
            "description": "aFASD\nF AS\nDF\n AS\nDF ASDF"
        }
    ],
    "payment_info": {
        "due_date": "2020-07-17"
    },
    "supplier_info": {
        "address1": "VIa alle colline 12",
        "address2": "",
        "address3": "",
        "business_name": "My Company",
        "city": "Lugano",
        "country": "Svizzera",
        "country_code": "CH",
        "courtesy": "",
        "email": "info@mycompany.zz",
        "first_name": "",
        "fiscal_number": "",
        "iban_number": "CH93 0076 2011 6238 5295 7",
        "last_name": "",
        "mobile": "",
        "phone": "+41 56 777 999",
        "postal_code": "600",
        "vat_number": "CHE-111.333.999 IVA",
        "web": "https://www.mycompany.zz"
    },
    "type": "invoice",
    "version": "1.0"
}

Invoice Json Properties Explanation

The Json has the following main elements:

  • type
    "invoice"
  • version
    "1.0"
  • document_info
    • Information relative to the invoice or estimate (currency, doctype,...) 
    • Initial texts, before Items
  • payment_info
    Invoice due date.
  • supplier_info
    Address of the company that issue/send the invoice.customer_info
  • Address of one receiving the invoice.
  • shipping_info
    Shipping Address  
  • items
    The list of items
  • billing_info
    Total of the invoices.note
  • note
    Array that contains the notes, to be printed at the end.
  • parameters
    Not used
  • template_parameters
  • Texts that are defined in the Invoice Dialogs
  • transactions
    Payment information (not used in transactions)

 

Source of data

This list explains where the actual information on your invoice json object is coming from

Invoice Object PropertySource
customer_info.address1Table: Accounts, View: Address, Column: Street
customer_info.address2Table: Accounts, View: Address, Column: AddressExtra
customer_info.address3Table: Accounts, View: Address, Column: POBox
customer_info.balanceTable: Accounts, View: Address, Column: Balance
customer_info.balance_base_currencyTable: Accounts, View: Address, Column: BalanceCurrency
customer_info.bank_accountTable: Accounts, View: Address, Column: BankAccount
customer_info.bank_clearingTable: Accounts, View: Address, Column: BankClearing
customer_info.bank_nameTable: Accounts, View: Address, Column: BankName
customer_info.business_nameTable: Accounts, View: Address, Column: OrganisationName
customer_info.cityTable: Accounts, View: Address, Column: Locality
customer_info.countryTable: Accounts, View: Address, Column: Country
customer_info.country_codeTable: Accounts, View: Address, Column: CountryCode
customer_info.courtesyTable: Accounts, View: Address, Column: NamePrefix
customer_info.credit_limitTable: Accounts, View: Address, Column: CreditLimit
customer_info.currencyTable: Accounts, View: Address, Column: Currency
customer_info.date_birthTable: Accounts, View: Address, Column: DateOfBirth
customer_info.emailTable: Accounts, View: Address, Column: EmailWork
customer_info.faxTable: Accounts, View: Address, Column: Fax
customer_info.first_nameTable: Accounts, View: Address, Column: FirstName
customer_info.fiscal_numberTable: Accounts, View: Address, Column: FiscalNumber
customer_info.iban_numberTable: Accounts, View: Address, Column: BankIban
customer_info.langTable: Accounts, View: Address, Column: Language
customer_info.last_nameTable: Accounts, View: Address, Column: FamilyName
customer_info.member_feeTable: Accounts, View: Address, Column: MemberFee
customer_info.mobileTable: Accounts, View: Address, Column: PhoneMobile
customer_info.numberTable: Accounts, View: Address, Column: Account
customer_info.payment_term_daysTable: Accounts, View: Address, Column: PaymentTermInDays
customer_info.phoneTable: Accounts, View: Address, Column: PhoneMain
customer_info.postal_codeTable: Accounts, View: Address, Column: PostalCode
customer_info.stateTable: Accounts, View: Address, Column: Region
customer_info.vat_numberTable: Accounts, View: Address, Column: VatNumber
customer_info.webTable: Accounts, View: Address, Column: Website
document_info.currencyInvoice currency which usually corresponds to the customer account currency
document_info.dateTable: Transactions, Column: DateDocument or Date
document_info.decimals_amountsDecimals are the same as the decimals used in the accounting file
document_info.descriptionNot used
document_info.doc_typeTable: Transactions, Column: DocType
document_info.greetingsTable: Transactions, Column: DocType
Transactions with DocType=10:gre
If there are many rows with 10:gre the texts are joined with ','.
More info...
document_info.localeMenu: File-File and accounting properties, Other, current Language
document_info.numberTable: Transactions, Column: DocInvoice
document_info.order_dateTable: Transactions, Column: DocType
Transactions with DocType=10:ordd
More info...
document_info.order_numberTable: Transactions, Column: DocType
Transactions with DocType=10:ordn
More info...
document_info.origin_rowRow index of source transaction
document_info.origin_tableTable name of source transaction
document_info.rounding_totalDefault value for CHF: 0.05
You can overwrite this value with the menu command: Account2 - Customers - Settings - Advanced - Invoice rounding
For multicurrency accounting: you can setup the rounding value for each currency in the table ExchangeRates, column DecimalPoints
document_info.text_beginTable: Transactions, Column: DocType
Transactions with DocType=10:beg
More info...
document_info.typeinvoice
itemsTable: Transactions
All rows with the same invoice number and transaction date are invoice's items (lines)
noteTable: Transactions, Column: DocType
Transactions with DocType=10:not.
More info...
parametersTable: Transactions, Column: DocType
Transactions with DocType=10:par:key
Key: any key text you wish
Value: is taken from column Description
More info...
payment_infoCalculated from journal
shipping_infoDelivery address if different from the invoice address (customer_info)
Table: Transactions, Column: DocType
Transactions with DocType=10:sadr
More info...
supplier_info.address1Menu: File-File and accounting properties, Address, Address 1
supplier_info.address2Menu: File-File and accounting properties, Address, Address 2
supplier_info.business_nameMenu: File-File and accounting properties, Address, Company
supplier_info.cityMenu: File-File and accounting properties, Address, City
supplier_info.countryMenu: File-File and accounting properties, Address, Country
supplier_info.courtesyMenu: File-File and accounting properties, Address, Courtesy
supplier_info.emailMenu: File-File and accounting properties, Address, Email
supplier_info.faxMenu: File-File and accounting properties, Address, Fax
supplier_info.first_nameMenu: File-File and accounting properties, Address, Name
supplier_info.fiscal_numberMenu: File-File and accounting properties, Address, Fiscal Number
supplier_info.last_nameMenu: FilevFile and accounting properties, Address, Family Name
supplier_info.mobileMenu: File-File and accounting properties, Address, Mobile
supplier_info.phoneMenu: File-File and accounting properties, Address, Phone
supplier_info.postal_codeMenu: File-File and accounting properties, Address, Zip
supplier_info.stateMenu: File-File and accounting properties, Address, Region
supplier_info.vat_numberMenu: File-File and accounting properties, Address, Vat Number
supplier_info.webMenu: File-File and accounting properties, Address, Web
transactionsTable: Transactions
All rows with the same invoice number and different transaction date, which are not considered invoice items, like payments transactions

 

 

 

Layout Preferences Json Object

The function getPrintPreferences() returns a list of user-selectable preferences for printing an invoice in Json format.

Banana takes care of checking whether the getPrintPreferences() function exists in the script and whether it returns the available choices. If found, the layout preferences are displayed within the dialogue for printing invoices, if not, no choices are displayed.

Layout preferences depend on the selected layout type, currently, the returning layouts of the preferences are:

This feature is available only with the Advanced plan, those who own another plan still see the layout preference box but the choices are disabled.

The layout preferences the user can choose from are:

  • Print as: The user can decide the type of document to print:
    • Automatic (default, depends on invoice status).
    • Invoice.
    • Delivery note.
    • Delivery note without amounts.
    • Reminder (number 1,2 or 3).

Print invoice with preferences dialog
 

Complete Json structure

This is the layout preferences structure with multiple elements, that serve as a reference for future implementation:

  • version: JSON structure version
  • id: Id of the structure.
  • text: Name of the structure.
  • base_options: Array of objects, each object represents a basic customization option, like the 'print as' options.
  • advanced_options_function: Object that contains advanced customization options.

The script defines the language in which to return the Json object, the structure remains the same, only the texts in the 'text' fields change.

The Json code include comments that should not be present in the code.


{
  "version" : "1.0",
  "id": "invoice_available_layout_preferences",
  "text":"Layout Preferences",
  "base_options" : [
  {
// first combo box
    "id": "invoice_available_print_as",
    "text": "Print as",
    "print_as": [
      {
        "id":"automatic",
        "text":"Automatic"
      },
      {
        "id":"invoice",
        "text": "Invoice"
      },
      {
        "id":"delivery_note" ,
        "text": "Delivery Note"
      },
      {
        "id":"reminder_1",
        "text": "Reminder 1"
      },
      {
        "id":"reminder_2",
        "text":"Reminder 2"
      },
      {
        "id":"reminder_3",
        "text": "Reminder 3"
      }
    ],
    "default": "automatic"
  },
],
// button.
//  When clicked the "function_name" is called
// Not yet implemented
"advanced_options_function" :{
  "text": "Print options",
  "function_name": "dialog_print_options"
}
}

Base preferences JSON structure example

The basic layout preferences concern more basic customisations, such as the document type (invoice status). The Json for the basic options is structured as follows:

  • id: Id of the structure.
  • text: Name of the structure.
  • print_as: Array of objects, each object represents an available document type (or invoice status). Each element  has an id and a text that is displayed in the combo box.


{
  "version" : "1.0",
  "id": "invoice_available_layout_preferences",
  "text":"Layout Preferences",
  "base_options" : [
  {
    "id": "invoice_available_print_as",
    "text": "Print as",
    "print_as": [
      {
        "id":"automatic",
        "text":"Automatic"
      },
      {
        "id":"invoice",
        "text": "Invoice"
      },
      {
        "id":"delivery_note" ,
        "text": "Delivery Note"
      },
      {
        "id":"reminder_1",
        "text": "Reminder 1"
      },
      {
        "id":"reminder_2",
        "text":"Reminder 2"
      },
      {
        "id":"reminder_3",
        "text": "Reminder 3"
      }
    ],
    "default": "automatic"
  }],
}

Advanced preferences JSON structure example

The advanced print options concern more detailed customisations. (to define)



{
  "version" : "1.0",
  "id": "invoice_available_print_preferences",
  "text":"Layout Preferences",
  "base_options" : [{/*Base options*/}],
  "advanced_options_function" :{
    "text": "Print options",
    "function_name": "dialog_print_options"
}

Returned JSON structure example

Banana returns a Json with user-selected layout preferences to the invoice layout script.

This structure is passed to the script through printDocument function.

  • version: JSON structure version
  • id: Id of the structure.
  • print_choices: Object that contains the print choices selected by the user. We send to the script the id of the preference choosed by the user.

In the following example, the user chose to print the third reminder, the value returned to the script, in this case 'reminder_3'.



{
    "version" : "1.0",
    "id": "invoice_available_layout_preferences",
    "print_choices" : {
        "print_as":"reminder_3",
        //other preferences
    },
}

Adapt Existing Invoice Layouts

In Banana Accounting Plus (Advanced plan only) you can take an existing invoice layout, modify it and use it as a new custom layout.
A layout is an Extension that is specific for printing an invoice.

The following steps describe how to adapt to your needs the existing [CH10] Layout with Swiss QR Code and [UNI11] Layout 11 Programmable Invoice layouts.

  1. Choose the layout to start from
  2. Save the layout files
  3. Modify the layout
  4. Add your layout to the Banana Extensions
  5. View an invoice with the custom template

Choose the layout to start from

On GitHub you can find the following layouts:

These layouts extensions are packed into .sbaa files that include all the required files needed to run the extensions.

Save the layout files

Choose the layout you want to start from and download all the files included in the .sbaa package on your computer.

  • Open the links above.
  • Right click on the page.
  • Select Save page.

All the files must be saved in the same directory.

Modify the layout

  • Open the local file ch.banana.ch.invoice.ch10.js or ch.banana.uni.invoice.uni11.js with a text editor program.
    • Right click on the file.
    • Open with and select the text editor program.
  • Change the @id with a new one.
    Each new invoice layout must have a different @id text.
  • Change the @description with a new one.
    The description will appear in the print dialog window when selecting the invoice layout.
  • Modify then the script as you want.
    Find more information about the content of the Json Object of the invoice.
  • Save the file.

Add your layout to the Banana Extensions

At this point you can choose the way you want to add the layout to the Banana Extensions.

You have two options:

  • Install the layout without recreating a new package.
    • This can be useful if you don't need to share the layout with someone else, and also if you want to test your changes faster.
    • From Banana, menu Extensions → Manage Extensions.
    • Click on the button Add from file... and choose the file you just downloaded and modified (ch.banana.ch.invoice.ch10.js or ch.banana.uni.invoice.uni11.js).
  • Create a new Extension Package (.sbaa file).
    • This can be useful if you need to share the layout with someone else.
    • Use the following manifest and QRC files and adapt them as you need:
    • From Banana, menu Extensions → Manage Extensions.
    • Click on the button Add from file... and choose the file .sbaa you just created.

Important: Do not delete the extension file from your pc or move it to another directory after the installation, otherwise the extension will no longer work. If you want to move the extension to another directory, you must reinstall it from the new location.

View an invoice with the custom layout

  • From Banana, menu Reports Customers → Print Invoices select the layout you just added.
  • Confirm with Ok to see the preview.

 

Customize Invoice Layout

With the Advanced plan of Banana Accounting Plus, you can create your own Invoice Layout.
A Layout is an Extension that is specific for printing an Invoice.

The following steps describe how to create an invoice template starting from an existing one and adapting it to your needs.

Choose your print style

  • From the Banana program, select menu Extensions > Manage Extensions...
  • Select Online > Invoice.
  • Choose one of the existing templates (i.e. [UNI01] Layout 1)
  • Click on Show details.
  • Click on URL.

Manage extensions dialogue
 

Save the layout's script

A page with the JavaScript code opens. Save the script file to your documents folder (menu File > Save Page As) or right click somewhere on the page > Save As.

Manage extensions dialogue

Modify the template

  • Open the local file with a text editor program
    • Right click on the file.
    • Open with .... and select the text editor program.
  • Change the @description and the @id.
  • Save the file.



 

Add your layout to the Banana extensions

  • From the Banana program,  menu Extensions > Manage Extensions....
  • Click on the button Add from file... and choose the file you just downloaded and modified.


 

View an invoice with the custom template.

  • In menu Reports > Customers > Print Invoices select the layout Smith & Co. Invoice.
  • Click Ok.



Preview:


Additional changes


The images below illustrates how to carry out the following changes to your layout.

  • How to change the header position to the right:
    • Modify the lines as described here (see from row 683 to 686). Save changes.

 

  • How to change the text "Customer No" to "Customer" 


 

See your changes

Simply click on the refresh button

 

Exporting Invoices to XML

This page explains how to create a Banana Accounting Javascript Extension, that creates the invoice in a specific format. The explanation takes as example the extension Fattura Elettronica , which exports electronic invoices according to Italian B2B standards in XML format.

The Extension has the following steps:

  • Use the Banana API, to retrieve the list invoicesCustomers in Json format.
  • InvoiceCustomers includes the Invoice objects.
  • For the Italian export it is necessary to have also information regarding the Tax code. This supplementary information is calculated by the VAT Extension. That is why the Extensions includes different files.
  • The user is given the ability to enter data. So a dialog is displayed with the information required.
    See Extension documentation in Italian.
  • The Extension can also have parameters that can be set with the settings dialog.
  • Once you have all the information, you need to convert the data in the format that you need. In the Italian case, the invoice is in the XML format that follows the specific requirements.
  • At the end, the Extension calls a function that prompts the user to specify the file where he wants to save the XML data.
  • The Extension for Italy also includes a possibility to have a preview of the invoice and export it in PDF.

References:

 

Attributes list

Each extension must declare some attributes in order to run in Banana environment. For more info see Extension's Attributes page

  • @id: this is the script ID. It will be used by getScriptSettings() and setScriptSettings() to save params values for this script
  • @includejs: ch.banana.it.invoice.it05.js this is the invoice template used to print out the invoice in preview and PDF format. 
  • @includejs: ch.banana.script.italy_vat_2017.journal.js this file contains the class Journal, used to retrieve transactions and customer info such as adresses. Other includes are dependencies of ch.banana.script.italy_vat_2017.journal.js
// @id = ch.banana.it.efattura.b2b
// @api = 1.0
// @pubdate = 2019-04-25
// @publisher = Banana.ch SA
// @description = [BETA] Fattura elettronica (XML, PDF)...
// @description.it = [BETA] Fattura elettronica (XML, PDF)...
// @doctype = *
// @task = app.command
// @inputdatasource = none
// @timeout = -1
// @includejs = ch.banana.it.invoice.it05.js
// @includejs = ch.banana.script.italy_vat_2017.errors.js
// @includejs = ch.banana.script.italy_vat_2017.journal.js
// @includejs = ch.banana.script.italy_vat.daticontribuente.js
// @includejs = ch.banana.script.italy_vat_2017.xml.js

Function exec()

The exec() function is the main function, which is called when the extension is executed. This function does the following:

  • loads user parameters
  • creates an EFattura-class object
  • the EFattura object loads data according to user parameters
  • the EFattura object  issues invoices in xml format or in print preview


function exec(inData, options) {
...
   // creates the EFattura object that contains the logic to load the invoices 
   // and transform them into the required formats
   var eFattura = new EFattura(Banana.document);
   if (!eFattura.verifyBananaVersion())
      return "@Cancel";

   // user params can be retrieved using the method Banana.document.getScriptSettings()
   // they are saved in the system table syskey using the method Banana.document.setScriptSettings()
   var param = {};
...
   param = JSON.parse(Banana.document.getScriptSettings());
...   
   eFattura.setParam(param);
   //loadData() retrieves data from table invoicesCustomers() and returns an array of json invoices grouped by customer
   var jsonCustomerList = eFattura.loadData();
...      
   //output the data according to user param (xml or pdf)
   if (eFattura.param.output == 0) {
      var docs = [];
      var styles = [];
      for (var i in jsonCustomerList) {
         var jsonInvoices = jsonCustomerList[i];
         for (var j = 0; j < jsonInvoices.length; j++) {
            var jsonInvoice = jsonInvoices[j];
            if (jsonInvoice.customer_info) {
               var repDocObj = Banana.Report.newReport('');
               var repStyleObj = Banana.Report.newStyleSheet();
               eFattura.createReport(jsonInvoice, repDocObj, repStyleObj);
               docs.push(repDocObj);
               styles.push(repStyleObj);
            }
         }
      }
      if (docs.length) {
         Banana.Report.preview("", docs, styles);
      }
   }
   else {
      //output xml
      for (var i in jsonCustomerList) {
         var jsonInvoices = jsonCustomerList[i];
         var xmlDocument = Banana.Xml.newDocument("root");
         var output = eFattura.createXml(jsonInvoices, xmlDocument, true);
         if (output != "@Cancel") {
            var xslt = "";
            var outputStyled = output.slice(0, 39) + xslt + output.slice(39);
            eFattura.saveFile(outputStyled);
         }
      }
   }
}

 

Class EFattura()

This class contains all the logic of the application in order to print out the invoices. The costructor initializes some variables.



function EFattura(banDocument) {
   this.banDocument = banDocument;
   ...
   this.name = "Banana Accounting EFattura";
   this.version = "V1.0";
   this.helpId = "ch.banana.it.efattura.b2b.js";
   this.errorList = [];

   /* errors id*/
   this.ID_ERR_ACCOUNTING_TYPE_NOTVALID = "ID_ERR_ACCOUNTING_TYPE_NOTVALID";
   ...

   this.initParam();
   this.initNamespaces();
   this.initSchemarefs();
}

EFattura.initParam()

This method initializes the class parameters, which will resume user-set values using the setParam() method and the settingsDialog() function.



EFattura.prototype.initParam = function () {
   this.param = {};
   /*output format 0=pdf, 1=xml*/
   this.param.output = 0;
   /*selection 0=single invoice, 1=single customer 2=all*/
   this.param.selection = 0;
   /*invoice number*/
   this.param.selection_invoice = '';
   /*customer number*/
   this.param.selection_customer = '';
   
   /* periodSelected 0=none, 1=1.Q, 2=2.Q, 3=3Q, 4=4Q, 10=1.S, 12=2.S, 30=Year */
   this.param.periodAll = true;
   this.param.periodSelected = 1;
   this.param.periodStartDate = '';
   this.param.periodEndDate = '';
   
   /*params for xml format*/
   this.param.xml = {};
   this.param.xml.progressive = '1';
   this.param.xml.open_file = false;
   this.param.xml.destination_folder = '';

   /*params for pdf format*/
   this.param.report = {};
   this.param.report.print_header = true;
   this.param.report.print_logo = true;
   this.param.report.print_quantity = false;
   this.param.report.font_family = '';
   this.param.report.color_1 = '#337ab7';
   this.param.report.color_2 = '#ffffff';
   this.param.report.header_row_1 = '';
   this.param.report.header_row_2 = '';
   this.param.report.header_row_3 = '';
   this.param.report.header_row_4 = '';
   this.param.report.header_row_5 = '';
   this.param.report.footer = '';
}

EFattura.loadData()

The loadData() declares the following objects:

  • this.journal: this is an object available from the script Iva Italia. The journal contains all the accounting transactions and the list of customers, including their addresses.
    In order to use this object you need to include the file ch.banana.script.italy_vat_2017.journal.js using the statement @includejs = ch.banana.script.italy_vat_2017.journal.js in the attribute list of the script.
  • this.journalInvoices: this can be loaded directly from Banana.document.invoicesCustomers and contains all invoices.


EFattura.prototype.loadData = function () {

   //loads transactions, the journal is declared in script /iva/2017/ch.banana.script.italy_vat_2017.journal.js
   //the journal is used for retrieving the following data: "IT_TipoDoc" (type of document), "IT_Natura" (nature of the transaction)
   //see @includes at the beginning of this script
   if (!this.journal) {
      this.journal = new Journal(this.banDocument);
      this.journal.excludeVatTransactions = true;
      this.journal.load();
   }
   //loads list of invoices using the Banana.document object
   if (!this.journalInvoices) {
      this.journalInvoices = this.banDocument.invoicesCustomers();
   }

   var jsonInvoiceList = [];
   //if invoice filter is defined and invoice number is empty, no invoice is returned
   if (this.param.selection == 0 && this.param.selection_invoice.length <= 0)
      return jsonInvoiceList;
   //if customer filter is defined and customer number is empty, no invoice is returned
   if (this.param.selection == 1 && this.param.selection_customer.length <= 0)
      return jsonInvoiceList;
   //if tax payer data is not defined, no invoiced is returned
   if (!this.initDatiContribuente())
      return jsonInvoiceList;

   //set period of the transactions to be loaded
   var periodAll = this.param.periodAll;
   var startDate = this.param.periodStartDate;
   var endDate = this.param.periodEndDate;
  
   for (var i = 0; i < this.journalInvoices.rowCount; i++) {
      var tRow = this.journalInvoices.row(i);
      //the column 'ObjectJSonData', in the table journalInvoices, contains the invoice object
      if (tRow.value('ObjectJSonData') && tRow.value('ObjectType') === 'InvoiceDocument') {
         var jsonData = {};
         jsonData = JSON.parse(tRow.value('ObjectJSonData'));
         var addInvoice = true;
         if (parseInt(this.param.selection) === 0 && jsonData.InvoiceDocument.document_info.number !== this.param.selection_invoice) {
            addInvoice = false;
         }
         if (parseInt(this.param.selection) === 1 && jsonData.InvoiceDocument.customer_info.number !== this.param.selection_customer) {
            addInvoice = false;
         }
         if (addInvoice && !periodAll) {
            if (jsonData.InvoiceDocument.document_info.date < startDate || jsonData.InvoiceDocument.document_info.date > endDate) {
               addInvoice = false;
            }
         }
         if (addInvoice) {
            jsonInvoiceList.push(jsonData.InvoiceDocument);
         }
      }
   }

   if (jsonInvoiceList.length<=0) {
      var msg = this.getErrorMessage(this.ID_ERR_NOINVOICE);
      this.addMessage(msg, this.ID_ERR_NOINVOICE);
   }

   //data is grouped by customer because the xml file can contain only one customer per file
   //if many customers are printed, these will be splitted into many files
   var jsonCustomerList = {};
   for (var i = 0; i < jsonInvoiceList.length; i++) {
      var jsonInvoice = jsonInvoiceList[i];
      if (jsonInvoice.customer_info) {
         var accountId = jsonInvoice.customer_info.number;
         if (!jsonCustomerList[accountId])
            jsonCustomerList[accountId] = [];
         jsonCustomerList[accountId].push(jsonInvoice);
      }
   }
   
   return jsonCustomerList;
}

EFattura.createReport(jsonInvoice, report, stylesheet)

The createReport() generates the preview of the invoice. If you wish to change the layout of the invoice you can modify or replace the script ch.banana.it.invoice.it05.js
@jsonInvoice: this is the json invoice object which contains all data to print out
@report: this is the Banana.Report.ReportElement object which permits you to preview and print out the data
@stylesheet: this is the Banana.Report.ReportStyleSheet object which contains all css information for printing out the report.



   //print the single invoice to the object report, 
   //the methods printInvoice and setInvoiceStyle are declared in the file ch.banana.it.invoice.it05.js
   if (jsonInvoice && jsonInvoice.customer_info) {
      printInvoice(jsonInvoice, report, stylesheet, this.param.report);
...
      setInvoiceStyle(report, stylesheet, this.param.report);
      stylesheet.addStyle("@page").setAttribute("margin", "0");
   }

EFattura.createXml(jsonInvoiceList, xmlDocument, indent)

The createXml() generates the xml code of the invoice. The XML file will contains one or more invoices of a single customer.
@jsonInvoiceList: this is an array with the list of invoices which belong to a single customer
@xmlDocument: this is a Banana.Xml.XmlElement which contains all XML data
@indent: if true the string xml will be indented and formatted with spaces



if (!xmlDocument || jsonInvoiceList.length<=0)
      return "@Cancel";
      
   var nodeRoot = this.createXmlHeader(jsonInvoiceList[0], xmlDocument);
   if (!nodeRoot || this.isEmpty(nodeRoot))
      return "@Cancel";
   for (var i = 0; i < jsonInvoiceList.length; i++) {
      this.createXmlBody(jsonInvoiceList[i], nodeRoot);
   }
   return Banana.Xml.save(xmlDocument, indent);