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 “http://zurmo.org/wiki/customizing-zurmo” 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.
Download
https://bitbucket.org/sanbrar/zurmo_invoice
Requirements
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
Implementation
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.
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.
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:
Materials
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
Security labels can be easily defined, for example create security for Material module is called “Create Material Item”, see image below
Menu
Menu is defined in the getDefaultMetadata function (see http://zurmo.org/wiki/zurmo-module-configurations-via-global-metadata for more information). Figure below show how menu code translates to the 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
__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;}
getDefaultMetadata
All class metadata information is defined in this function, see figure below.
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.
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 (http://zurmo.org/wiki/attachment-functionality )
- filter
Check if user has access to the particular material item(s)
Invoice
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
Model
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. 
Controller
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. 
Views
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 (getRelationAttributeName & getDisplayDescription).
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.









