2 /**********************************************************************
3 Copyright (C) FrontAccounting, LLC.
4 Released under the terms of the GNU General Public License, GPL,
5 as published by the Free Software Foundation, either version 3
6 of the License, or (at your option) any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ***********************************************************************/
13 // FrontAccounting extension modules integration.
14 // This file is included in session.inc even before session is started,
15 // and includes hooks.php connector files from all installed extensions.
16 // To make hooks active install_hooks() have to be called after interface
19 // To find how various hooks are processed look into respective hook_* functions below.
22 var $module_name; // extension module name.
25 // Helper for updating databases with extension scheme
27 // $comp can be company number, -1 for all,
28 // $updates - table of filename => array(table, field, property)
29 // $check_only - don't update database, check table/field/property existence only
31 function update_databases($comp, $updates, $check_only=false)
33 global $db_connections, $path_to_root;
36 $conn = $db_connections;
38 $conn = array( $comp => $db_connections[$comp]);
41 foreach($conn as $comp => $con) {
42 set_global_connection($comp);
43 foreach($updates as $file => $update) {
46 $properties = @$update[2];
48 $ok = check_table($con['tbpref'], $table, $field, $properties) == 0;
50 if (!$check_only && !$ok) {
51 $ok = db_import($path_to_root.'/modules/'.$this->module_name.'/sql/'.$file,
62 set_global_connection(0); // return to siteadmin account
67 // Install additional tabs provided by extension
69 function install_tabs($app)
71 // $app->add_application(new example_class); // add menu tab defined by example_class
74 // Install additonal menu options provided by extension
76 function install_options($app)
78 // global $path_to_root;
82 // $app->add_rapp_function( 0, _("&Example option"),
83 // $path_to_root.'/modules/example/example.php?', 'SA_OPEN');
87 function install_access()
89 // $security_areas['SA_EXAMPLE'] = array(SS_EXAMPLE|100, _("Example security area."));
91 // $security_sections = array(SS_EXAMPLE => _("Example module implementation"));
93 // return array($security_areas, $security_sections);
97 // Invoked for all modules before page header is displayed
99 function pre_header($fun_args)
103 // Invoked for all modules before page footer is displayed
105 function pre_footer($fun_args)
110 // Price in words. $doc_type is set to document type and can be used to suppress
111 // price in words printing for selected document types.
112 // Used instead of built in simple english price_in_words() function.
114 // Returns: amount in words as string.
116 function price_in_words($amount, $doc_type)
121 // Exchange rate currency $curr as on date $date.
122 // Keep in mind FA has internally implemented 3 exrate providers
123 // If any of them supports your currency, you can simply use function below
124 // with apprioprate provider set, otherwise implement your own.
125 // Returns: $curr value in home currency units as a real number.
127 function retrieve_exrate($curr, $date)
129 // $provider = 'ECB'; // 'ECB', 'YAHOO' or 'GOOGLE'
130 // return get_extern_rate($curr, $provider, $date);
134 // External authentication
135 // If used should return true after successfull athentication, false otherwise.
136 function authenticate($login, $password)
140 // Generic function called at the end of Tax Report (report 709)
141 // Can be used e.g. for special database updates on every report printing
142 // or to print special tax report footer
145 function tax_report_done()
148 // Following database transaction hooks akcepts array of parameters:
149 // 'cart' => transaction data
150 // 'trans_type' => transaction type
152 function db_prewrite(&$cart, $trans_type)
157 function db_postwrite(&$cart, $trans_type)
162 function db_prevoid($trans_type, $trans_no)
167 This method is called after module install.
169 function install_extension($check_only=true)
174 This method is called after module uninstall.
176 function uninstall_extension($check_only=true)
181 This method is called on extension activation for company.
183 function activate_extension($company, $check_only=true)
188 This method is called when extension is deactivated for company.
190 function deactivate_extension($company, $check_only=true)
196 * Returns the quantity allowed to be dispatched for a particular item
197 * and a status (which can be used to style the row).
198 * This quantity would be the default value on the delivery note.
199 * The usual use case for this is when a item is in stock,
200 * but has been reserved by someone else.
201 * This allows extensions to implements its own priority algorithm.
202 * This function is by detail_id and not item in case the item is present
203 * more than one in the cart.
205 /* Default behavior check if there is enough quantity on hand and change the css
207 static function default_get_dispatchable_quantity($line_item, $location, $date, $qoh) {
210 if ($SysPrefs->allow_negative_stock() || ($line_item->qty_dispatched <= $qoh)) {
213 return array($qoh, 'stockmankobg');
214 return array($line_item->qty_dispatched, 'stockmankobg');
220 Installs hooks provided by extension modules
222 function install_hooks()
224 global $path_to_root, $Hooks, $installed_extensions;
228 // include current language related $Hooks object if locale file exists
229 $lang_code = clean_file_name($_SESSION['language']->code);
230 if (file_exists($path_to_root . "/lang/" . $lang_code . "/locale.inc"))
232 include_once($path_to_root . "/lang/" . $lang_code . "/locale.inc");
233 $code = $_SESSION['language']->code;
234 $hook_class = 'hooks_'.$code;
235 $Hooks[$code] = new $hook_class;
236 unset($code, $hook_class);
238 // install hooks provided by active extensions
239 foreach($installed_extensions as $ext) {
240 $hook_class = 'hooks_'.$ext['package'];
241 if ($ext['active'] && class_exists($hook_class)) {
242 $Hooks[$ext['package']] = new $hook_class;
247 Non active hooks are not included in $Hooks array, so we can use special function to
250 function activate_hooks($ext, $comp)
254 $hooks = @$Hooks[$ext];
256 $hookclass = 'hooks_'.$ext;
257 if (class_exists($hookclass))
258 $hooks = new $hookclass;
260 return true; // extension does not have hooks file
265 return $hooks->activate_extension($comp, false);
268 Calls hook $method defined in extension $ext (if any)
270 function hook_invoke($ext, $method, &$data, $opts=null)
276 if (isset($Hooks[$ext]) && method_exists($Hooks[$ext], $method)) {
277 set_ext_domain('modules/'.$ext);
278 $ret = $Hooks[$ext]->$method($data, $opts);
285 Calls hook $methods defined in all extensions (if any)
287 function hook_invoke_all($method, &$data, $opts=null)
295 foreach($Hooks as $ext => $hook)
296 if (method_exists($hook, $method)) {
297 set_ext_domain('modules/'.$ext);
298 $result = $hook->$method($data, $opts);
299 if (isset($result) && is_array($result)) {
300 $return = array_merge_recursive($return, $result);
301 } else if (isset($result)) {
310 Returns first non-null result returned from hook.
312 function hook_invoke_first($method, &$data, $opts=null)
318 foreach($Hooks as $ext => $hook) {
319 if (method_exists($hook, $method)) {
320 set_ext_domain('modules/'.$ext);
321 $result = $hook->$method($data, $opts);
330 Returns last non-null result returned from modules method. Helps implement hooks overriding by
331 extensions installed later.
333 function hook_invoke_last($method, &$data, $opts=null)
339 $Reverse = array_reverse($Hooks);
340 foreach($Reverse as $ext => $hook) {
341 if (method_exists($hook, $method)) {
342 set_ext_domain('modules/'.$ext);
343 $result = $hook->$method($data, $opts);
351 //------------------------------------------------------------------------------------------
352 // Database transaction hooks.
353 // $type - type of transaction (simplifies cart processing)
354 // $cart - transaction cart
355 // $args is optional array of parameters
357 // For FA 2.3 prewrite, postwrite and prevoid hooks are implemented for following transaction types:
359 // ST_BANKPAYMENT, ST_BANKDEPOSIT, ST_BANKTRANSFER,
360 // ST_SALESORDER, ST_SALESQUOTE, ST_SALESINVOICE, ST_CUSTCREDIT, ST_CUSTPAYMENT, ST_CUSTDELIVERY,
361 // ST_LOCTRANSFER, ST_INVADJUST,
362 // ST_PURCHORDER, ST_SUPPINVOICE, ST_SUPPCREDIT, ST_SUPPAYMENT, ST_SUPPRECEIVE,
363 // ST_WORKORDER, ST_MANUISSUE, ST_MANURECEIVE,
366 Invoked after transaction has been read from database to cart.
369 //function hook_db_postread(&$cart, $type)
371 // hook_invoke_all('db_postread', $cart, $type);
375 Invoked before transaction is written to database.
377 function hook_db_prewrite(&$cart, $type)
379 return hook_invoke_all('db_prewrite', $cart, $type);
383 Invoked after transaction has been written to database.
385 function hook_db_postwrite(&$cart, $type)
387 return hook_invoke_all('db_postwrite', $cart, $type);
390 Invoked before transaction is voided
392 function hook_db_prevoid($type, $type_no)
394 return hook_invoke_all('db_prevoid', $type, $type_no);
397 //-------------------------------------------------------------------------------------------
401 // Alternative exchange rates feeds.
403 function hook_retrieve_exrate($currency, $date)
405 return hook_invoke_last('retrieve_exrate', $currency, $date);
408 // Generic function called at the end of Tax Report (report 709)
410 function hook_tax_report_done()
412 return hook_invoke_all('tax_report_done', $dummy);
415 // Amount in words displayed on various documents (especially sales invoice)
417 function hook_price_in_words($amount, $document)
419 return hook_invoke_last('price_in_words', $amount, $document);
422 // Session handling hook. This is special case of hook class which have to be run before session is started.
423 // If fa_session_manager class is defined in any installed extension, this class provides session handling
424 // for application, otherwise standard php session handling is used.
426 function hook_session_start($company)
428 if (class_exists('fa_session_manager')) {
429 global $SessionManager;
430 $SessionManager = new fa_session_manager($company);
431 return $SessionManager->installed;
436 // Third party authentication modules.
437 // Returns true after successfull authentication, false otherwise, null if no login hook is defined.
439 function hook_authenticate($login, $password)
441 return hook_invoke_last('authenticate', $login, $password);
445 * Returns the quantity allowed to be dispatched for a particular item
446 * and a "reason" (css classes).
447 * This quantity would be the default value on the delivery note.
448 * The usual use case for this is when a item is in stock,
449 * but has been reserved by someone else.
450 * This allows extensions to implements its own priority algorithm.
451 * This function is by detail_id and not item in case the item is present
452 * more than one in the cart.
453 * If 'skip' is returned, the line will be skipped and not displayed
455 function hook_get_dispatchable_quantity($line_item, $location, $date, $qoh) {
456 $result = hook_invoke_first('get_dispatchable_quantity', $line_item, array($location, $date, $qoh));
457 return $result !== null ? $result : hooks::default_get_dispatchable_quantity($line_item, $location, $date, $qoh);