Skip to main content

Creating Extensions & Modules in FrontAccounting


Software customization is important for your business, It's allows you to meet unique business requirements, streamline processes and integrate with other software.
FrontAccounting is a free opensource software, and using easiest scripting language PHP to make customization more easier and faster, thus minimize costs.

The customization can be done via creating extensions, and this is a better way as in future software upgrading will not affect the extensions module.

This article is a Quick start guide that help developers who are new to FrontAccounting, I am using a simple example to walk you though the creating extension and report process.

The follow diagram shows the structure of extension folders (blue) and files (green).


Not all files are necessary, to create an extension without additional MySql table and report, you'll only need the hooks.php file and your extension program file, I am going to use a program "item inquiry" to illustrate the procedure of creating an extension in FA.

If you would like a detailed explanation of the process, program code syntax and functions, please refer to my YouTube video.

Item Inquiry extension contains an item search box, item select drop-down combo box and a table for display search results. 


item_inquiry.php
<?php
/**********************************************************************
   Description: Item Inquiry extension, a simple demo program for 
                illustrate the procedure of creating an extension in FA
***********************************************************************/

$page_security = 'SA_OPEN';

$path_to_root = "../..";
include_once($path_to_root . "/includes/session.inc");
include_once($path_to_root . "/includes/ui.inc");

page(_("Item Inquiry"));

check_db_has_stock_items(_("There are no items defined in the system."));

start_form();
if (!isset($_POST['stock_id']))
$_POST['stock_id'] = get_global_stock_item();

echo "<center> " . _("Item:"). " ";
// Item field, combo box, advance search window and the item select function.
echo stock_costable_items_list('stock_id', $_POST['stock_id'], false, true);
echo "<br>";
echo "<hr></center>";
if (list_updated('stock_id'))
$Ajax->activate('status_tbl');
div_start('status_tbl');

start_table(TABLESTYLE);
$th = array(_("Description"), _("Quantity On Hand"), _("Currency"),
        _("Sales Type"),_("Price"));
table_header($th);

$row = get_item($_POST['stock_id']);
label_cell($row['long_description']);

$qoh = get_qoh_on_date($_POST['stock_id']);
qty_cell($qoh, false, 0);

$prices_list = get_prices($_POST['stock_id']);

while ($myrow = db_fetch($prices_list))
{
    if ($not1strow++)
    {
        label_cell ('');
        label_cell ('');
    }
    label_cell($myrow["curr_abrev"]);
    label_cell($myrow["sales_type"]);
    amount_cell($myrow["price"]);
    end_row();
}
 
end_table();
div_end();
end_form();

The page security is set to SA_OPEN (open for everyone), you can use any pre-define page security from include/access_level.inc, or define a new page security, which is discuss later on this page.
The code is straightforward, for examples:
page() create a new page. 
check_db_has_stock_items check whether there are items in db.
stock_costable_items_list() create the item search function with Item field, combo box and pop-up advance search window.
As you can see, it's save a lot of work by using FrontAccounting pre-define functions. It's less than 40 lines of code to create the Item Inquiry extension.
 
The hooks.php is used to hooks Item Inquiry module on FrontAccounting->Item and Inventory tag 2nd section.

hooks.php
<?php
class hooks_items_inquiry extends hooks {
var $module_name = 'Items Inquiry'; 

/*
Install additonal menu options provided by module
*/
function install_options($app) {
global $path_to_root;

switch($app->id) {
case 'stock':
$app->add_rapp_function(1, _('Items Inquiry'), 
$path_to_root.'/modules/items_inquiry/items_inquiry.php', 'SA_OPEN');
}
}
}

You can change where you want to hook the extension on FA menu by changing the install_options function case statement: 

The first parameter of add_rapp_function is the row number of window.


All the extensions are located in "Frontaccounting installed folder"->modules folder, so we need to create item_inquiry folder in modules folder, and copy item_inquiry.php and hooks.php to "FA installed directory"->modules->item_inquiry folder.


That's all, we need to activate the extension before we can use it.
Log in to the first registered company (only the system administrator of the first registered company have the access rights to create companies and install chart of accounts).

1. Go to Setup->Install/Activate Extensions.

2. The Item Inquiry should appear in the extension list, click on download icon. the extension will be installed and the download icon will replace with a delete icon for you to uninstall later.

3. Click on Extensions drop down combo box and select Activate for "Company name" you want to activate, the list of installed extensions will appear, tick the box for the required extension and then click on "Update" button, the Item Inquiry extension will be added to "Items and Inventory" menu.

That's easy, Item Inquiry extension is created on 2 simple php files. 

Page Security

To implement a security access function on extensions or reports, you'll need to add the install_access() method in hooks.php file, below are the added code for security access in hooks.php and item_inquiry.php files.

hooks.php
define ('SS_ITEMINQ', 110<<8 );
function install_options($app) {
..
..
$app->add_rapp_function(1, _('Item Inquiry'),
$path_to_root.'/modules/item_inquiry/item_inquiry.php', 'SA_ITEMINQ');
..
function install_access()
{
$security_sections[SS_ITEMINQ] = _("Item Inquiry");
$security_areas['SA_ITEMINQ'] = array(SS_ITEMINQ|111, _("Item Inquiry"));
return array($security_areas, $security_sections);
}
You can use any numbers from 100<<8 to 155<<8 for security section id, and any number from 101 to 255 for security area id. The "<<" is the php shift bitwise operator.

item_inquiry.php

$page_security = 'SA_ITEMINQ';

.

.

include_once($path_to_root . "/includes/session.inc");

add_access_extensions()


Assign $page_security to "SA_ITEMINQ" and add the add_access_extensions() function in item_inquiry.php file.

After the security functions are added, you have to assign access right for user before he/she can access to Item Inquiry extension.
Go to Setup->Access Setup, select the User Role from the drop down box you want to assign access right, click on the Item Inquiry section tick-box and then click on the "Save Role" button. 

Data Manipulation in Extension 

Most extensions are need to create new tables in FA database, to do this, first create a sql script file for creating tables and another sql script file for dropping tables, then add the activate_extension() and deactivate_extension() functions in hooks.php file. To better illustrate this, I have created a "Save inquired item" function to insert record to the new item_inquiry table.

Diagram below shows the folders and files required for additional data manipulation. 
The SQL script will execute when you activate or deactivate extension for a company from FA setup->Install/Activate Extensions.
 
update.sql
DROP TABLE IF EXISTS `0_item_inquiry`;
CREATE TABLE IF NOT EXISTS `0_item_inquiry` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `inquiry_date` TIMESTAMP NOT NULL DEFAULT  current_timestamp(),
    `stock_id` varchar(20) NOT NULL DEFAULT '',
    `description` varchar(200) NOT NULL DEFAULT '',
    `qoh` double NOT NULL DEFAULT '1',
    PRIMARY KEY (`id`),
    KEY `inquiry_date` (`inquiry_date`,`id`)
) ENGINE=InnoDB;

remove.sql
DROP TABLE IF EXISTS `0_item_inquiry`;
hooks.php add activate_extension and deactivate_extension functions.
    function activate_extension($company, $check_only=true) {
        global $db_connections;
        $updates = array( 'update.sql' => array('inquiry'));
        return $this->update_databases($company, $updates, $check_only);
    }

    function deactivate_extension($company, $check_only=true) {
        global $db_connections;
        $updates = array('remote.sql' => array('inquiry'));
        return $this->update_databases($company, $updates, $check_only);
    }

The following item_inquiry.php added a submit_center() function to generate "Save Inquired Item" command button, click on it and the isset($_POST['add_query']) will return true and execute add_item_inquiry function in item_inquiry_db.inc.
item_inquiry_db.inc
function add_item_inquiry($stock_id,$description,$qoh)
{
    $sql = "insert into ". TB_PREF."item_inquiry
          (stock_id,description,qoh) values
           (". db_escape($stock_id). "," .
               db_escape($description). "," .
               db_escape($qoh). ")";

    if (db_query($sql,"inquiry item could not be added"))
        display_notification(_('Inquired item has been added'));
 }

item_inquiry.php
<?php
include_once($path_to_root . "/modules/item_inquiry/includes/item_inquiry_db.inc");
if (isset($_POST['add_query']))
add_item_inquiry($_POST['stock_id'],$_SESSION['desc'],$_SESSION['qoh']);

$_SESSION['desc'] = $row['description'];
$_SESSION['qoh'] = $qoh;

submit_center('add_query', _("Save Inquired Item"), true);

Code I have added in item inquiry php file.
First, include the item inquiry dot db inc file.
Two session variables to store description and quantity on hand.
A submit center function to generate "Save Inquired Item" command button on page.
and this command button will trigger the execution of add record function.

Reports

The last part is creating custom reports, the addReport function in reports_custom.php file is used to add your report(eg. rep1001.php) to specific report menu (report classes), and create parameters input box in report menu, please refer to reporting/includes/reports_classes.inc for the details of report classes and addReport function.


I am going to use the Inquired items report to illustrate the process of coding works. 


The reports_custom.php is using addReport constructor to add the report in report menu class.
addReport(Report class, Report name omitted 'rep' and '.php', Report name, Parameters array)
The report classes are: RC_CUSTOMER, RC_SUPPLIER, RC_INVENTORY, RC_MANUFACTURE, RC_DIMENSIONS, RC_BANKING, RC_GL, RC_FIXEDASSETS.

reports_custom.php

<?php
global $reports;
$reports->addReport(RC_INVENTORY, "1001", _('Inquired Items Report'),
array( _('Start Date') => 'DATEBEGINM',
_('End Date') => 'DATEENDM',
_('Orientation') => 'ORIENTATION',
_('Destination') => 'DESTINATION'));
?>

FrontReport Object.

The coding of output report is straight forward, you only need to get familiar with FrontReport object.
First create the new report object using constructor FrontReport(Tile, output file name(Excel), user_pagesize(),font size, paper orientation);
user_pagesize() = Your user preferences setting, on menu Preferences->Page Size.

Info is the other important method of FrontReport, it's used for headers, columns, alignment and so on.
Info(parameters array, columns position array, headers array, aligns array)
Columns position: A4, Width=595, Height=843, Margins Top:40, Bottom:30, Left=40, right=30.

other common methods are:
Font(style, font name)
Style:  empty: regular, B: bold, I: italic, U: underline, D: strike through.
Font name: empty = your installed language default font, please refer to /reporting/fonts for available fonts.
TextCol(Column Number,Next Column Number, Text), the next column is used to calculate the length.
AmountCol(Column Number, Next Column Number, Number, Decimal);
NewPage()
NewLine()
Line()
End() 
All are english-like syntax and easy to understand. 
For more details, please refer to reporting/includes/pdf_report.inc.
rep1001.php
<?php

$page_security = 'SA_ITEMINQ';
$path_to_root="..";
include_once($path_to_root . "/includes/session.inc");
add_access_extensions();

include_once($path_to_root . "/includes/date_functions.inc");
//----------------------------------------------------------------------------------------------------
print_inquired_items();

function getTransactions( $from, $to)
{
$from = date2sql($from);
$to = date2sql($to);
$sql = "SELECT date_format(inquiry_date,'%Y-%m-%d %H:%i') as dateinq,
  stock_id,description,qoh
FROM ".TB_PREF."item_inquiry
WHERE inquiry_date>='$from'
AND inquiry_date<='$to'
ORDER BY inquiry_date, id";
    return db_query($sql,"No transactions were returned");
}

//----------------------------------------------------------------------------------------------------

function print_inquired_items()
{
  global $path_to_root;

$from = $_POST['PARAM_0'];
$to = $_POST['PARAM_1'];
$orientation = $_POST['PARAM_2'];
$destination = $_POST['PARAM_3'];
if ($destination)
include_once($path_to_root . "/reporting/includes/excel_report.inc");
else
include_once($path_to_root . "/reporting/includes/pdf_report.inc");

$orientation = ($orientation ? 'L' : 'P');
  $dec = user_price_dec();

$cols = array(0, 100, 260, 500);
$headers = array(_('Date'), _('Item'), _('Description'), _('Qoh'));
$aligns = array('left','left', 'left', 'right');
  $params =   array(      0 => array('text' => _('Period'),'from' => $from, 'to' => $to));

  $rep = new FrontReport(_('Inquired Items Report'), "InquiredItemReport", user_pagesize(), 9, $orientation);
  if ($orientation == 'L')
     recalculate_cols($cols);

  $rep->Font();
  $rep->Info($params, $cols, $headers, $aligns);
  $rep->NewPage();

$res = getTransactions($from, $to);
$totalitems = 0;

while ($trans=db_fetch($res))
{

$rep->NewLine();
$rep->fontSize -= 2;
$rep->TextCol(0, 1, $trans['dateinq']);
$rep->TextCol(1, 2, $trans['stock_id']);
$rep->TextCol(2, 3, $trans['description']);
$rep->AmountCol(3, 4, $trans['qoh'], get_qty_dec($trans['stock_id']));
$rep->fontSize += 2;
++$totalitems;
}

  $rep->Line($rep->row  - 2);
$rep->NewLine(2, 3);
  $rep->Font('bold');
$rep->TextCol(0, 1, _('Total items'));

$rep->AmountCol(1, 2, $totalitems, 0);
$rep->NewLine();
    $rep->End();
}

index.php file in every folder 

You can copy index.php file in every folder to prevent direct access to folders.

<?php
header("Location: ../index.php");
The init folder and config file are not necessary for local extension.
By following this tutorial, you should be able to create simple extensions in FrontAccounting.
You are free to download and try the source code here.

Comments

Popular posts from this blog

Free Software for Everyone

Since Microsoft has tied up with all PC manufacturers to sell their PCs with pre-installed windows, most of us are familiar with Windows and proprietary software run on it, not many are aware of free software is now available for any task you want to do.
I am using Linux (Ubuntu) on Intel celeron N2840 notebook, which I had bought it a few years ago at the price of less than US$210, and I have no problem of using it for office tasks, video editing and software development, this is one of the great benefit once you are Linux user, it's not necessary to buy expensive notebook.
Below are the lists of free software I am using, and I think it is worth recommending, you can download and try it by clicking the software website link provided.
Linux is good enough to replace Windows: Most Linux distributions looks similar to Windows and Mac operating systems, and support most same types of software you are using before, such as word processors, photo video editors, and so on.
Linux is a lot mo…

Making Ukulele Tabs & Notation in MuseScore

MuseScore is a music score writer for you to create, play back and print beautiful sheet music on Windows, Mac and Linux system. It's a free software alternative to Finale, Sibelius, Guitar Pro and supporting a wide variety of file formats and input methods. 
You can download it for free at the website link here. To know more about MuseScore and learn how to use it, you can visit https://musescore.org/en/support for Handbook, video tutorials and other services.  Making Ukulele Tabs & Notation in MuseScoreThis article is shows you how to make ukulele music notation and tabs with lyrics, chord symbols and fretboard diagrams in MuseScore. I am going to use the Happy Birthday score as an example for my tutorial.
The first staff is standard music notation staff and the second staff is Ukulele tab (tablature),  this is call "linked staff" in MuseScore, any change to the notes in one staff will automatically reflect in the other.
Open MuseScore program and click on "Create…

How to Install FrontAccounting on Windows

You can install FrontAccounting with web server package on local PC for single user usage or testing, in this article I will show you how to install FrontAccounting with Xampp on Windows PC. Install XAMPP.Xampp is an easy to install web server package, consist of Apache HTTP Server, MariaDB and PHP programming languages.

You can download XAMPP from Apache Friends website.
Click on XAMPP for Windows button to download the installer file, once the download finishes, click on the downloaded file to run the installer.
The Warning window pop up, it's telling you to avoid installing Xampp into c:\program files. Press ok to confirm, and press ok again on another windows to continue the installation.
Select the components you want to install, we recommend you install all the components, click on Next button to continue.

This step is to choose the folder where the program is to be installed, it is recommended to choose the default c:\xampp. Click next button to continue.
Uncheck learn more about …