Customizing Zurmo: Invoice Example

Invoice sample application demonstrates how to leverage Zurmo to create custom applications. This tutorial highlights steps taken to create the sample application and leverages the “” article. Once you learn to navigate around the Zurmo code you will realize that Zurmo makes it really easy to add custom modules and extensions.



Invoice Example ERD

Invoice Header

  • Able to create an invoice with Invoice Date defaulting to today and auto generate Invoice number
  • Insert and Update invoice detail items as needed

Invoice Detail

  • Auto add item number
  • Automatically updated when invoice item is deleted
  • Calculated Total Price field using Unit Price and Quantity
  • Display Material description

Material (covered in part 1)

  • Ability to add images and other files to material

Print Invoice

  • Export invoice to a PDF


The first part of implementation is to set up a custom configuration file “perInstanceConfig” and custom extension “customext” that will be used to install the custom modules, see figure below.

InstanceConfig & Custom Extension

If the “perInstanceConfig.php” is present, it’s auto loaded by preInstance.php

if (is_file(INSTANCE_ROOT . ‘/protected/config/perInstanceConfig.php’)) { require_once INSTANCE_ROOT . ‘/protected/config/perInstanceConfig.php’; }

In custom configuration you define your custom modules, import all files related to custom modules and specify and import custom extensions, see figure below.

Instance Config

Custom Extension

The custom extension is relatively simple, it contains two files “CustomextCustomManagement.php” (not much to configure in this file) and “CustomextInstallUtil.php” (see image below).

The extension will add a menu item for the “c_materials” module on install. The extension also loads the default data for the custom modules.  The default data maker loads default data for any “OwnedCustomField”. Figure below shows default data maker class and what it looks like in the UI for the owned custom filed “C_materialType” in C_material module.

Besides the Menu and Default Data Load, Custom Metadata can also be declared in the CustomextInstallUtil (we will see an example of this in Invoice Details module).

Before reading further it’s beneficial to view the following screen casts:


Image below shows the folder structure and files needed for the module.

Module (C_materialsModule.php)

Module file specify following items:

  • Security
  • Menu
  • Module Labels
  • Default Data maker class
  • Demo Data maker class

Security labels can be easily defined, for example create security for Material module is called “Create Material Item”,  see image below

Defining Module Security & it's appearance in designer


Menu is defined in the getDefaultMetadata function (see for more information).  Figure below show how menu code translates to the UI.

Material Module Menu Setup & it’s appearance in UI
Module Labels

Module name labels are set by functions ”getSingularModuleLabel” and “getPluralModuleLabel”.

        protected static function getSingularModuleLabel()
            return ‘Material’;
        protected static function getPluralModuleLabel()
            return ‘Materials’;
Default Data Maker

As seen in earlier section default data maker class can used to populate default data custom field types, for example field typein C_material module.

Demo Data Maker

Upon installation demo data maker class can also load demo data, class  name should be returned by the static function getDemoDataMakerClassName.

Module Model (modules -> C_material.php)

Since “Item” class handles most of the tedious tasks such as created & modified by & on, and audit functionality,  the material model class extends “Item” class. In the model two functions that are worth mentioning are

  • __toString
  • getDefaultMetadata

__toString function is an easy way to specify what is displayed for module string. For Materials module material number - material name are displayed.

        public function __toString()
            if (trim($this->materialnum) == ”)
                return Yii::t(‘Default’, ‘(Unnamed)’);
            return $this->materialnum . ‘ – ‘ . $this->name;

Custom __toString function for Material Module


All class metadata information is defined in this function, see figure below.

Material Module Default Meta Data

This may seam like a lot of effort for a drop down list but this allows an application user to customize the drop down list options in the design page. Image below shows the impact on database relating to the CustomOwnedField has.

Material Type -> OwnedCustomField (Database schema & Designer View)

 Controller  (DefaultController.php )

Default controller for the module provides following actions:

  • actionList

List of materials with paging

Uses C_materialsListView to list the materials

Uses C_materialsSearchView to provide ability to search for specific material(s) in the list

Is the default action

  • actionCreate

Creates a new material item

Leverage’s the actionCreateByModel

  • actionCreateByModel

Presents the model in edit mode

Uses C_materialEditAndDetailsView

  • actionCreateFromRelation

Create the model

Sets the related attribute value (example: creating invoice detail item from invoice header)

Leverage’s the actionCreateByModel

  • actionDetails

Shows the detail’s view

Uses C_materialEditAndDetailsView in Detail mode

  • actionEdit

Uses C_materialEditAndDetailsView in Edit mode

  • actionDelete

Needs C_materialDeleteLinkActionElement (elements -> actions) to work propertly

Redirects to back to material list view

  • actionExport

Exposes the export functionality

  • actionSelectFromRelatedList
  • actionModalList

Modal list to select a material item (used in Invoice detail item)

Uses C_materialsModalListView & C_materialsModalSearchView

  • attemptToSaveModelFromPost & resolveModelsHasManyRelationsFromPost

Support multiple attachment files see ( )

  • filter

Check if user has access to the particular material item(s)


In this section we look at how to add parent child (or header and details) functionality. Invoice component of the application is made up of two separate modules C_inovices & C_invoiceitems. C_invoices is the parent (or header) and C_invoiceitems is child (or details).  Invoice items are only shown in Invoice details view, as seen in the figure below.

Parent & Child Relationship


In the C_inovices and C_invoiceitems models include reference to each other. C_invoices has many relationship with C_invoiceitems, see figure below. C_invoiceitems has one to one relationship with C_invoice, see figure below.


The actionDetails function in C_invoice default controller needs to be changed from using regular edit and details view to detail relations view, see figure below.


As we saw in the C_invoice default controller, the Invoice details views uses “C_invoiceDetailsAndRelationsView“. This view uses the regular details view and related invoice items view, see figure below. The “C_invoiceitemsForC_invoiceRelatedListView” can be found in modules >>  c_invoiceitems >> views >> related. This view extends the “C_invoiceitemsRelatedListView” and has only two functions (getRelationAttributeNamegetDisplayDescription). In summary, for parent and child relationships (or header and details) we had to create two separate modules (C_invoices & C_invoiceitems). Models of both modules reference each other with appropriate relationships. Invoice default controller was modified to use the relations view. Relations views were used to render the invoice items and invoice details on same page.

Other Requirements

Default Invoice Date

Default values are defined in the module’s model as part of the meta data.

Auto Create Invoice Item Number

Auto assigning an invoice item number is a two step process. First, create a function that will assign the item number. Second,, call the function in the controller after creating a new invoice item.

Export Invoice To PDF

Last major requirement for our sample is exporting the invoice to PDF.

Leave a Comment

  • Jake He


    I downloaded this example but cannot get it to work. Zurmo loads but c_invoice or c_material are not in the the home page menu. I can access c_invoices via http://localhost/zurmo_invoice/app/index.php/c_invoices. But every time I save the invoice it will download the corrupted pdf file. Please see my screenshoots. My source version is tag tip, 2456:707bef4a83d96d8fe2f303b496cd188fe31feecd. Is there another version that works?


  • Vikram Singh

    I have downloaded Zurmo Invoice module and install on 2.5 version but there is not menu for invoice creation I have accessed it directly using http://localhost/zurmo/app/index.php/c_invoices but a blank page comes. Can anyone tell me what is the problem I’m new to zurmo.