--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+/*
+ User authentication page popped up after login timeout during ajax call.
+*/
+$path_to_root = '..';
+$page_security = 'SA_OPEN';
+include_once($path_to_root . "/includes/session.inc");
+
+include($path_to_root .'/access/login.php');
+
+if (get_post('SubmitUser') && $_SESSION['wa_current_user']->logged_in()) {
+ // After successfull login repeat last ajax call.
+ // Login form consists all post variables from last ajax call.
+echo "<script>
+ var o = opener;
+ if (o) {
+ o.JsHttpRequest.request(document.getElementsByName('SubmitUser')[0], o.document.forms[0]);
+ close();
+ }
+</script>";
+}
+?>
--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+//--------------------------------------------------------------------------------------------------
+
+function get_security_role($id)
+{
+ $sql = "SELECT * FROM ".TB_PREF."security_roles WHERE id='$id'";
+ $ret = db_query($sql, "could not retrieve security roles");
+ $row = db_fetch($ret);
+ if ($row != false) {
+ $row['areas'] = explode(';', $row['areas']);
+ $row['sections'] = explode(';', $row['sections']);
+ }
+ return $row;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+function add_security_role($name, $description, $sections, $areas)
+{
+ $sql = "INSERT INTO ".TB_PREF."security_roles (role, description, sections, areas)
+ VALUES ("
+ .db_escape($name).","
+ .db_escape($description).","
+ .db_escape(implode(';', $sections)).","
+ .db_escape(implode(';', $areas)).")";
+
+ db_query($sql, "could not add new security role");
+}
+
+//--------------------------------------------------------------------------------------------------
+
+function update_security_role($id, $name, $description, $sections, $areas)
+{
+ $sql = "UPDATE ".TB_PREF."security_roles SET role=".db_escape($name)
+ .",description=".db_escape($description)
+ .",sections=".db_escape(implode(';', $sections))
+ .",areas=".db_escape(implode(';', $areas))
+ ." WHERE id=$id";
+ db_query($sql, "could not update role");
+}
+//--------------------------------------------------------------------------------------------------
+
+function delete_security_role($id)
+{
+ $sql = "DELETE FROM ".TB_PREF."security_roles WHERE id=$id";
+
+ db_query($sql, "could not delete role");
+}
+//--------------------------------------------------------------------------------------------------
+
+function check_role_used($id) {
+ $sql = "SELECT count(*) FROM ".TB_PREF."users WHERE role_id=$id";
+ $ret = db_query($sql, 'cannot check role usage');
+ $row = db_fetch($ret);
+ return $row[0];
+}
+?>
\ No newline at end of file
--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+
+function add_tag($type, $name, $description)
+{
+ $sql = "INSERT INTO ".TB_PREF."tags (type, name, description)
+ VALUES (".db_escape($type).", ".db_escape($name).", ".db_escape($description).")";
+
+ return db_query($sql);
+}
+
+//--------------------------------------------------------------------------------------
+
+function update_tag($id, $name, $description, $type=null)
+{
+ $sql = "UPDATE ".TB_PREF."tags SET name=".db_escape($name).",
+ description=".db_escape($description);
+ if ($type != null)
+ $sql .= ", type=".db_escape($type);
+
+ $sql .= " WHERE id = ".db_escape($id);
+
+ return db_query($sql);
+}
+
+//--------------------------------------------------------------------------------------
+
+function get_tags($type, $all=false)
+{
+ $sql = "SELECT * FROM ".TB_PREF."tags WHERE type=".db_escape($type);
+
+ if (!$all) $sql .= " AND !inactive";
+
+ $sql .= " ORDER BY name";
+
+ return db_query($sql, "could not get tags");
+}
+
+//--------------------------------------------------------------------------------------
+
+function get_tag($id)
+{
+ $sql = "SELECT * FROM ".TB_PREF."tags WHERE id = ".db_escape($id);
+
+ $result = db_query($sql, "could not get tag");
+
+ return db_fetch($result);
+}
+
+//--------------------------------------------------------------------------------------
+
+function get_tag_type($id)
+{
+ $sql = "SELECT type FROM ".TB_PREF."tags WHERE id = ".db_escape($id);
+
+ $result = db_query($sql, "could not get tag type");
+
+ $row = db_fetch_row($result);
+ return $row[0];
+}
+
+//--------------------------------------------------------------------------------------
+
+function get_tag_name($id)
+{
+ $sql = "SELECT name FROM ".TB_PREF."tags WHERE id = ".db_escape($id);
+
+ $result = db_query($sql, "could not get tag name");
+
+ $row = db_fetch_row($result);
+ return $row[0];
+}
+
+//--------------------------------------------------------------------------------------
+
+function get_tag_description($id)
+{
+ $sql = "SELECT description FROM ".TB_PREF."tags WHERE id = ".db_escape($id);
+
+ $result = db_query($sql, "could not get tag description");
+
+ $row = db_fetch_row($result);
+ return $row[0];
+}
+
+//--------------------------------------------------------------------------------------
+
+function delete_tag($id)
+{
+ $sql = "DELETE FROM ".TB_PREF."tags WHERE id = ".db_escape($id);
+
+ db_query($sql, "could not delete tag");
+}
+
+//--------------------------------------------------------------------------------------
+
+function add_tag_associations($recordid, $tagids)
+{
+ foreach($tagids as $tagid) {
+ if (!$tagid) continue;
+ $sql = "INSERT INTO ".TB_PREF."tag_associations (record_id, tag_id)
+ VALUES (".db_escape($recordid).", ".db_escape($tagid).")";
+
+ db_query($sql, "could not add tag association");
+ }
+}
+
+//--------------------------------------------------------------------------------------
+
+function update_tag_associations($type, $recordid, $tagids)
+{
+ // Delete the old associations
+ delete_tag_associations($type, $recordid, false);
+ // Add the new associations
+ add_tag_associations($recordid, $tagids);
+}
+
+//--------------------------------------------------------------------------------------
+// To delete tag associations, we need to specify the tag type.
+// Otherwise we may inadvertantly delete records for another type of tag
+//
+function delete_tag_associations($type, $recordid, $all=false)
+{
+/* multiply table DELETE syntax available since MySQL 4.0.0:
+ $sql = "DELETE ta FROM ".TB_PREF."tag_associations ta
+ INNER JOIN ".TB_PREF."tags tags ON tags.id = ta.tag_id
+ WHERE tags.type = ".db_escape($type)." AND ta.record_id = ".db_escape($recordid);
+*/
+ // To support MySQL 3.xx we have to use multiply queries
+ $sql = "SELECT * FROM ".TB_PREF."tag_associations ta
+ INNER JOIN ".TB_PREF."tags tags ON tags.id = ta.tag_id
+ WHERE tags.type = ".db_escape($type)." AND ta.record_id = ".db_escape($recordid);
+ if (!$all)
+ $sql .= " AND tags.inactive = 0";
+ $result = db_query($sql, "could not select tag associations");
+
+ while($ta = db_fetch($result)) {
+ $sql2 = "DELETE FROM ".TB_PREF."tag_associations WHERE
+ record_id = '".$ta['record_id']."' AND tag_id=".$ta['tag_id'];
+ db_query($sql2, "could not delete tag associations");
+ }
+}
+
+//--------------------------------------------------------------------------------------
+
+function get_records_associated_with_tag($id)
+{
+ // Which table we query is based on the tag type
+ $type = get_tag_type($id);
+
+ $table = $key = '';
+ switch ($type) {
+ case TAG_ACCOUNT:
+ $table = TB_PREF."chart_master";
+ $key = "account_code";
+ break;
+ case TAG_DIMENSION:
+ $table = TB_PREF."dimensions";
+ $key = "id";
+ break;
+ }
+
+ $sql = "SELECT $table.* FROM $table
+ INNER JOIN ".TB_PREF."tag_associations AS ta ON ta.record_id = $table.$key
+ INNER JOIN ".TB_PREF."tags AS tags ON ta.tag_id = tags.id
+ WHERE tags.id = ".db_escape($id);
+
+ return db_query($sql, "could not get tag associations for tag");
+}
+
+//--------------------------------------------------------------------------------------
+
+function get_tags_associated_with_record($type, $recordid)
+{
+ $sql = "SELECT tags.* FROM ".TB_PREF."tag_associations AS ta
+ INNER JOIN ".TB_PREF."tags AS tags ON tags.id = ta.tag_id
+ WHERE tags.type = $type AND ta.record_id = ".db_escape($recordid);
+
+ return db_query($sql, "could not get tags associations for record");
+}
+
+//--------------------------------------------------------------------------------------
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+$page_security = 'SA_SECROLES';
+$path_to_root = "..";
+include_once($path_to_root . "/includes/session.inc");
+
+add_access_extensions();
+
+page(_($help_context = "Access setup"));
+
+include_once($path_to_root . "/includes/ui.inc");
+include_once($path_to_root . "/includes/access_levels.inc");
+include_once($path_to_root . "/admin/db/security_db.inc");
+
+$new_role = get_post('role')=='' || get_post('cancel') || get_post('clone');
+//--------------------------------------------------------------------------------------------------
+// Following compare function is used for sorting areas
+// in such a way that security areas defined by module/plugin
+// is properly placed under related section regardless of
+// unique extension number, with order inside sections preserved.
+//
+function comp_areas($area1, $area2)
+{
+ $sec_comp = ($area1[0]&0xff00)-($area2[0]&0xff00);
+ return $sec_comp == 0 ? ($area1[2]-$area2[2]) : $sec_comp;
+}
+
+function sort_areas($areas)
+{
+ $old_order = 0;
+ foreach($areas as $key => $area) {
+ $areas[$key][] = $old_order++;
+ }
+ uasort($areas,'comp_areas');
+ return $areas;
+}
+//--------------------------------------------------------------------------------------------------
+if (list_updated('role')) {
+ $Ajax->activate('details');
+ $Ajax->activate('controls');
+}
+
+function clear_data()
+{
+ unset($_POST);
+}
+
+if (get_post('addupdate'))
+{
+ $input_error = 0;
+ if ($_POST['description'] == '')
+ {
+ $input_error = 1;
+ display_error( _("Role description cannot be empty."));
+ set_focus('description');
+ }
+ elseif ($_POST['name'] == '')
+ {
+ $input_error = 1;
+ display_error( _("Role name cannot be empty."));
+ set_focus('name');
+ }
+ // prevent accidental editor lockup by removing SA_SECROLES
+ if (get_post('role') == $_SESSION['wa_current_user']->access) {
+ if (!isset($_POST['Area'.$security_areas['SA_SECROLES'][0]])
+ || !isset($_POST['Section'.SS_SETUP])) {
+ display_error(_("Access level edition in Company setup section have to be enabled for your account."));
+ $input_error = 1;
+ set_focus(!isset($_POST['Section'.SS_SETUP])
+ ? 'Section'.SS_SETUP : 'Area'.$security_areas['SA_SECROLES'][0]);
+ }
+ }
+
+ if ($input_error == 0)
+ {
+ $sections = array();
+ $areas = array();
+ foreach($_POST as $p =>$val) {
+ if (substr($p,0,4) == 'Area') {
+ $a = substr($p, 4);
+ if (($a&~0xffff) && (($a&0xff00)<(99<<8))) {
+ $sections[] = $a&~0xff; // add extended section for plugins
+ }
+ $areas[] = $a;
+ }
+ if (substr($p,0,7) == 'Section')
+ $sections[] = substr($p, 7);
+ }
+// $areas = sort_areas($areas);
+
+ $sections = array_values($sections);
+
+ if ($new_role)
+ {
+ add_security_role($_POST['name'], $_POST['description'], $sections, $areas);
+ display_notification(_("New security role has been added."));
+ } else
+ {
+ update_security_role($_POST['role'], $_POST['name'], $_POST['description'],
+ $sections, $areas);
+ update_record_status($_POST['role'], get_post('inactive'),
+ 'security_roles', 'id');
+
+ display_notification(_("Security role has been updated."));
+ }
+ $new_role = true;
+ clear_data();
+ $Ajax->activate('_page_body');
+ }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+if (get_post('delete'))
+{
+ if (check_role_used(get_post('role'))) {
+ display_error(_("This role is currently assigned to some users and cannot be deleted"));
+ } else {
+ delete_security_role(get_post('role'));
+ display_notification(_("Security role has been sucessfully deleted."));
+ unset($_POST['role']);
+ }
+ $Ajax->activate('_page_body');
+}
+
+if (get_post('cancel'))
+{
+ unset($_POST['role']);
+ $Ajax->activate('_page_body');
+}
+
+if (!isset($_POST['role']) || get_post('clone') || list_updated('role')) {
+ $id = get_post('role');
+ $clone = get_post('clone');
+
+ unset($_POST);
+ if ($id) {
+ $row = get_security_role($id);
+ $_POST['description'] = $row['description'];
+ $_POST['name'] = $row['role'];
+// if ($row['inactive']
+// $_POST['inactive'] = 1;
+
+ $_POST['inactive'] = $row['inactive'];
+ $access = $row['areas'];
+ $sections = $row['sections'];
+ }
+ else {
+ $_POST['description'] = $_POST['name'] = '';
+ unset($_POST['inactive']);
+ $access = $sections = array();
+ }
+ foreach($access as $a) $_POST['Area'.$a] = 1;
+ foreach($sections as $s) $_POST['Section'.$s] = 1;
+
+ if($clone) {
+ set_focus('name');
+ $Ajax->activate('_page_body');
+ } else
+ $_POST['role'] = $id;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+start_form();
+
+start_table("class='tablestyle_noborder'");
+start_row();
+security_roles_list_cells(_("Role:"). " ", 'role', null, true, true, check_value('show_inactive'));
+$new_role = get_post('role')=='';
+check_cells(_("Show inactive:"), 'show_inactive', null, true);
+end_row();
+end_table();
+echo "<hr>";
+
+if (get_post('_show_inactive_update')) {
+ $Ajax->activate('role');
+ set_focus('role');
+}
+if (find_submit('_Section')) {
+ $Ajax->activate('details');
+}
+//-----------------------------------------------------------------------------------------------
+div_start('details');
+start_table($table_style2);
+ text_row(_("Role name:"), 'name', null, 20, 22);
+ text_row(_("Role description:"), 'description', null, 50, 52);
+ record_status_list_row(_("Current status:"), 'inactive');
+end_table(1);
+
+ start_table("$table_style width=40%");
+
+ $k = $j = 0; //row colour counter
+ $ext = $sec = $m = -1;
+
+ foreach(sort_areas($security_areas) as $area =>$parms ) {
+ // system setup areas are accessable only for site admins i.e.
+ // admins of first registered company
+ if (user_company() && (($parms[0]&0xff00) == SS_SADMIN)) continue;
+
+ $newsec = ($parms[0]>>8)&0xff;
+ $newext = $parms[0]>>16;
+ if ($newsec != $sec || (($newext != $ext) && ($newsec>99)))
+ { // features set selection
+ $ext = $newext;
+ $sec = $newsec;
+ $m = $parms[0] & ~0xff;
+// if(!isset($security_sections[$m]))
+// display_error(sprintf("Bad section %X:", $m));
+ label_row($security_sections[$m].':',
+ checkbox( null, 'Section'.$m, null, true,
+ _("On/off set of features")),
+ "class='tableheader2'", "class='tableheader'");
+ }
+ if (check_value('Section'.$m)) {
+ alt_table_row_color($k);
+ check_cells($parms[1], 'Area'.$parms[0], null,
+ false, '', "align='center'");
+ end_row();
+ } else {
+ hidden('Area'.$parms[0]);
+ }
+ }
+ end_table(1);
+div_end();
+
+div_start('controls');
+
+if ($new_role)
+{
+ submit_center_first('Update', _("Update view"), '', null);
+ submit_center_last('addupdate', _("Insert New Role"), '', 'default');
+}
+else
+{
+ submit_center_first('addupdate', _("Save Role"), '', 'default');
+ submit('Update', _("Update view"), true, '', null);
+ submit('clone', _("Clone This Role"), true, '', true);
+ submit('delete', _("Delete This Role"), true, '', true);
+ submit_center_last('cancel', _("Cancel"), _("Cancel Edition"), 'cancel');
+}
+
+div_end();
+
+end_form();
+end_page();
+
+?>
--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+$path_to_root = "..";
+include($path_to_root . "/includes/session.inc");
+include_once($path_to_root . "/includes/types.inc"); // For tag constants
+include_once($path_to_root . "/admin/db/tags_db.inc");
+include($path_to_root . "/includes/ui.inc");
+
+// Set up page security based on what type of tags we're working with
+if (@$_GET['type'] == "account" || get_post('type') == TAG_ACCOUNT) {
+ $page_security = 'SA_GLACCOUNTTAGS';
+} else if(@$_GET['type'] == "dimension" || get_post('type') == TAG_DIMENSION) {
+ $page_security = 'SA_DIMTAGS';
+}
+
+// We use $_POST['type'] throughout this script, so convert $_GET vars
+// if $_POST['type'] is not set.
+if (!isset($_POST['type'])) {
+ if ($_GET['type'] == "account")
+ $_POST['type'] = TAG_ACCOUNT;
+ elseif ($_GET['type'] == "dimension")
+ $_POST['type'] = TAG_DIMENSION;
+ else
+ die(_("Unspecified tag type"));
+}
+
+// Set up page based on what type of tags we're working with
+switch ($_POST['type']) {
+ case TAG_ACCOUNT:
+ // Account tags
+ $_SESSION['page_title'] = _($help_context = "Account Tags");
+ break;
+ case TAG_DIMENSION:
+ // Dimension tags
+ $_SESSION['page_title'] = _($help_context = "Dimension Tags");
+}
+
+page($_SESSION['page_title']);
+
+simple_page_mode(true);
+
+//-----------------------------------------------------------------------------------
+
+function can_process()
+{
+ if (strlen($_POST['name']) == 0)
+ {
+ display_error( _("The tag name cannot be empty."));
+ set_focus('name');
+ return false;
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------------------
+
+if ($Mode=='ADD_ITEM' || $Mode=='UPDATE_ITEM')
+{
+ if (can_process())
+ {
+ if ($selected_id != -1)
+ {
+ if( $ret = update_tag($selected_id, $_POST['name'], $_POST['description']))
+ display_notification(_('Selected tag settings have been updated'));
+ }
+ else
+ {
+ if( $ret = add_tag($_POST['type'], $_POST['name'], $_POST['description']))
+ display_notification(_('New tag has been added'));
+ }
+ if ($ret) $Mode = 'RESET';
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+function can_delete($selected_id)
+{
+ if ($selected_id == -1)
+ return false;
+ $result = get_records_associated_with_tag($selected_id);
+
+ if (db_num_rows($result) > 0)
+ {
+ display_error(_("Cannot delete this tag because records have been created referring to it."));
+ return false;
+ }
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------------
+
+if ($Mode == 'Delete')
+{
+ if (can_delete($selected_id))
+ {
+ delete_tag($selected_id);
+ display_notification(_('Selected tag has been deleted'));
+ }
+ $Mode = 'RESET';
+}
+
+//-----------------------------------------------------------------------------------
+
+if ($Mode == 'RESET')
+{
+ $selected_id = -1;
+ $_POST['name'] = $_POST['description'] = '';
+}
+
+//-----------------------------------------------------------------------------------
+
+$result = get_tags($_POST['type'], check_value('show_inactive'));
+
+start_form();
+start_table($table_style);
+$th = array(_("Tag Name"), _("Tag Description"), "", "");
+inactive_control_column($th);
+table_header($th);
+
+$k = 0;
+while ($myrow = db_fetch($result))
+{
+ alt_table_row_color($k);
+
+ label_cell($myrow['name']);
+ label_cell($myrow['description']);
+ inactive_control_cell($myrow["id"], $myrow["inactive"], 'tags', 'id');
+ edit_button_cell("Edit".$myrow["id"], _("Edit"));
+ delete_button_cell("Delete".$myrow["id"], _("Delete"));
+ end_row();
+}
+
+inactive_control_row($th);
+end_table(1);
+
+//-----------------------------------------------------------------------------------
+
+start_table($table_style2);
+
+if ($selected_id != -1) // We've selected a tag
+{
+ if ($Mode == 'Edit') {
+ // Editing an existing tag
+ $myrow = get_tag($selected_id);
+
+ $_POST['name'] = $myrow["name"];
+ $_POST['description'] = $myrow["description"];
+ }
+ // Note the selected tag
+ hidden('selected_id', $selected_id);
+}
+
+text_row_ex(_("Tag Name:"), 'name', 15, 30);
+text_row_ex(_("Tag Description:"), 'description', 40, 60);
+hidden('type');
+
+end_table(1);
+
+submit_add_or_update_center($selected_id == -1, '', 'both');
+
+end_form();
+
+//------------------------------------------------------------------------------------
+
+end_page();
+
+?>
--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+ //--------------------------------------------------
+
+ // User configurable variables
+ //---------------------------------------------------
+
+ /*Show debug messages returned from an error on the page.
+ Debugging info level also determined by settings in PHP.ini
+ if $debug=1 show debugging info, dont show if $debug=0 */
+
+if (!isset($path_to_root) || isset($_GET['path_to_root']) || isset($_POST['path_to_root']))
+ die("Restricted access");
+ // Log file for error/warning messages. Should be set to any location
+ // writable by www server. When set to empty string logging is switched off.
+ // Special value 'syslog' can be used for system logger usage (see php manual).
+ //$error_logfile = '';
+ $error_logfile = dirname(__FILE__).'/tmp/errors.log';
+ $debug = 1;
+ $show_sql = 0;
+ $go_debug = 0;
+ $pdf_debug = 0;
+ // set $sql_trail to 1 only if you want to perform bugtracking sql trail
+ // Warning: this produces huge amount of data in sql_trail table.
+ // Don't forget switch the option off and flush the table manually after
+ // trail, or your future backup files are overloaded with unneeded data.
+ //
+ $sql_trail = 0; // save all sql queries in sql_trail
+ $select_trail = 0; // track also SELECT queries
+ if ($go_debug == 1)
+ {
+ error_reporting(E_ALL);
+ ini_set("display_errors", "On");
+ }
+ else
+ {
+ error_reporting(E_USER_WARNING|E_USER_ERROR|E_USER_NOTICE);
+ // ini_alter("error_reporting","E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR|E_PARSE");
+ ini_set("display_errors", "On");
+ }
+
+ if($error_logfile != '') {
+ ini_set("error_log", $error_logfile);
+ ini_set("ignore_repeated_errors", "On");
+ ini_set("log_errors", "On");
+ }
+ // Main Title
+ $app_title = "FrontAccounting";
+ // application version
+ $version = "2.2";
+
+ // Build for development purposes
+ $build_version = date("d.m.Y", filemtime("$path_to_root/CHANGELOG.txt"));
+
+ // Powered by
+ $power_by = "FrontAccounting";
+ $power_url = "http://frontaccounting.net";
+
+ /* use popup windows for views */
+ $use_popup_windows = 1;
+
+ /* use date picker for all date fields */
+ $use_date_picker = 1;
+
+ /* use Audit Trails in GL */
+ $use_audit_trail = 0;
+
+ /* use old style convert (income and expense in BS, PL) */
+ $use_oldstyle_convert = 0;
+
+ /* show users online discretely in the footer */
+ $show_users_online = 0;
+
+ // Wiki context help configuration
+ // If your help wiki use translated page titles uncomment next line
+ // $old_style_help = 1; // this setting is depreciated and subject to removal in next FA versions
+ // locally installed wiki module
+ // $help_base_url = $path_to_root.'/modules/wiki/index.php?n='._('Help').'.';
+ // context help feed from frontaccounting.net
+ // $help_base_url = 'http://frontaccounting.net/fawiki/index.php?n=Help.';
+ // not used
+ $help_base_url = null;
+
+ /* per user data/cache directory */
+ $comp_path = $path_to_root.'/company';
+
+ /* allow alpha characters in accounts. 0 = numeric, 1 = alpha numeric, 2 = uppercase alpha numeric */
+ $accounts_alpha = 0;
+
+ /* Date systems. 0 = traditional, 1 = Jalali used by Iran, nabour countries, Afghanistan and some other Central Asian nations,
+ 2 = Islamic used by other arabic nations. 3 = traditional, but where non-workday is Friday and start of week is Saturday */
+ $date_system = 0;
+
+ /* email stock location if order below reorder-level */
+ $loc_notification = 0;
+
+ /* print_invoice_no. 0 = print reference number, 1 = print invoice number */
+ $print_invoice_no = 0;
+
+ $dateformats = array("MMDDYYYY", "DDMMYYYY", "YYYYMMDD");
+ $dateseps = array("/", ".", "-", " ");
+ $thoseps = array(",", ".", " ");
+ $decseps = array(".", ",");
+ // defalt dateformats and dateseps indexes used before user login
+ $dflt_date_fmt = 0;
+ $dflt_date_sep = 0;
+
+ $pagesizes = array("Letter", "A4"); // default PDF pagesize
+
+ /* Default border and spacing for tables */
+ /* Should be moved to CSS */
+
+ if (!isset($_SESSION['bordercolor']))
+ $_SESSION['bordercolor'] = "#8cacbb";
+ $table_style = "cellpadding=3 border=1 bordercolor='".$_SESSION['bordercolor']."' class='tablestyle'";
+ $table_style2 = "cellpadding=3 border=1 bordercolor='#cccccc' class='tablestyle2'";
+
+ /* Accounts Payable */
+ /* System check to see if quantity charged on purchase invoices exceeds the quantity received.
+ If this parameter is checked the proportion by which the purchase invoice is an overcharge
+ referred to before reporting an error */
+
+ $check_qty_charged_vs_del_qty = true;
+
+ /* System check to see if price charged on purchase invoices exceeds the purchase order price.
+ If this parameter is checked the proportion by which the purchase invoice is an overcharge
+ referred to before reporting an error */
+
+ $check_price_charged_vs_order_price = True;
+
+ $config_allocation_settled_allowance = 0.005;
+
+ // Internal configurable variables
+ //-----------------------------------------------------------------------------------
+
+ /* Whether to display the demo login and password or not */
+
+ $allow_demo_mode = false;
+
+ /* for uploaded item pictures */
+ $pic_width = 80;
+ $pic_height = 50;
+ $max_image_size = 500;
+
+ /* skin for Business Graphics, 1, 2 or 3 */
+ $graph_skin = 1;
+
+/*
+ Before upgrade from pre-2.2 FA you have to move here your customized
+ security roles definitions. If you have used standard roles, you
+ can simply uncomment following two arrays. After upgrade both arrays need
+ to be deleted or commented out. You may wish to change user roles to
+ new better defined in Users Setup. Old not used roles can be set inactive
+ or deleted.
+*/
+/* Standard FA2.1 Security Group definitions
+
+ $security_headings = array(
+ _("Inquiries"),
+ _("Accountant"),
+ _("System Administrator"),
+ );
+
+ $security_groups = array(
+ array(1,2),
+ array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,16),
+ array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,20),
+ );
+*/
+
+ //MySQL Backup and Restore Settings
+
+if(isset($_SESSION["wa_current_user"])) {
+ define("BACKUP_PATH", $comp_path.'/'.user_company()."/backup/");
+}
+ // static js files path
+ $js_path = $path_to_root.'/js/';
+ // standard external js scripts included in all files
+ $js_static = array('JsHttpRequest.js', 'behaviour.js', 'utils.js', 'inserts.js');
+ // additional js source included in header
+ $js_lib = $js_userlib = array();
+
+if (!defined('ICON_EDIT'))
+{
+ define("ICON_EDIT", "edit.gif");
+ define("ICON_DELETE", "delete.gif");
+ define("ICON_ADD", "ok.gif");
+ define("ICON_UPDATE", "ok.gif");
+ define("ICON_OK", "ok.gif");
+ define("ICON_CANCEL", "cancel.png");
+ define("ICON_GL", "gl.png");
+ define("ICON_PRINT", "print.png");
+ define("ICON_PDF", "pdf.gif");
+ define("ICON_DOC", "invoice.gif");
+ define("ICON_CREDIT", "credit.gif");
+ define("ICON_RECEIVE", "receive.gif");
+ define("ICON_DOWN", "download.gif");
+ define("ICON_MONEY", "money.png");
+ define("ICON_REMOVE", "remove.png");
+ define("ICON_REPORT", "report.png");
+ define("ICON_VIEW", "view.gif");
+ define("ICON_SUBMIT", "ok.gif");
+ define("ICON_ESCAPE", "escape.png");
+}
+?>
\ No newline at end of file
+++ /dev/null
-<?php
-/**********************************************************************
- Copyright (C) FrontAccounting, LLC.
- Released under the terms of the GNU General Public License, GPL,
- as published by the Free Software Foundation, either version 3
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
-***********************************************************************/
- //--------------------------------------------------
-
- // User configurable variables
- //---------------------------------------------------
-
- /*Show debug messages returned from an error on the page.
- Debugging info level also determined by settings in PHP.ini
- if $debug=1 show debugging info, dont show if $debug=0 */
-
-if (!isset($path_to_root) || isset($_GET['path_to_root']) || isset($_POST['path_to_root']))
- die("Restricted access");
- // Log file for error/warning messages. Should be set to any location
- // writable by www server. When set to empty string logging is switched off.
- // Special value 'syslog' can be used for system logger usage (see php manual).
- $error_logfile = '';
- //$error_logfile = dirname(__FILE__).'/tmp/errors.log';
- $debug = 1;
- $show_sql = 0;
- $go_debug = 0;
- $pdf_debug = 0;
- // set $sql_trail to 1 only if you want to perform bugtracking sql trail
- // Warning: this produces huge amount of data in sql_trail table.
- // Don't forget switch the option off and flush the table manually after
- // trail, or your future backup files are overloaded with unneeded data.
- //
- $sql_trail = 0; // save all sql queries in sql_trail
- $select_trail = 0; // track also SELECT queries
- if ($go_debug == 1)
- {
- error_reporting(E_ALL);
- ini_set("display_errors", "On");
- }
- else
- {
- error_reporting(E_USER_WARNING|E_USER_ERROR|E_USER_NOTICE);
- // ini_alter("error_reporting","E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR|E_PARSE");
- ini_set("display_errors", "On");
- }
-
- if($error_logfile != '') {
- ini_set("error_log", $error_logfile);
- ini_set("ignore_repeated_errors", "On");
- ini_set("log_errors", "On");
- }
- // Main Title
- $app_title = "FrontAccounting";
- // application version
- $version = "2.1.7";
-
- // Build for development purposes
- $build_version = date("d.m.Y", filemtime("$path_to_root/CHANGELOG.txt"));
-
- // Powered by
- $power_by = "FrontAccounting";
- $power_url = "http://frontaccounting.net";
-
- /* use popup windows for views */
- $use_popup_windows = 1;
-
- /* use date picker for all date fields */
- $use_date_picker = 1;
-
- /* use Audit Trails in GL */
- $use_audit_trail = 0;
-
- /* use old style convert (income and expense in BS, PL) */
- $use_oldstyle_convert = 0;
-
- /* Integrated base Wiki Help URL or null if not used */
- //$help_base_url = $path_to_root.'/modules/wiki/index.php?n='._('Help').'.';
- $help_base_url = null;
-
- /* per user data/cache directory */
- $comp_path = $path_to_root.'/company';
-
- /* allow alpha characters in accounts. 0 = numeric, 1 = alpha numeric, 2 = uppercase alpha numeric */
- $accounts_alpha = 0;
-
- /* Date systems. 0 = traditional, 1 = Jalali used by Iran, nabour countries, Afghanistan and some other Central Asian nations,
- 2 = Islamic used by other arabic nations */
- $date_system = 0;
-
- /* email stock location if order below reorder-level */
- $loc_notification = 0;
-
- /* print_invoice_no. 0 = print reference number, 1 = print invoice number */
- $print_invoice_no = 0;
-
- $dateformats = array("MMDDYYYY", "DDMMYYYY", "YYYYMMDD");
- $dateseps = array("/", ".", "-", " ");
- $thoseps = array(",", ".", " ");
- $decseps = array(".", ",");
-
- $pagesizes = array("Letter", "A4"); // default PDF pagesize
-
- /* Default border and spacing for tables */
- /* Should be moved to CSS */
-
- $table_style = "cellpadding=3 border=1 bordercolor='#8cacbb' style='border-collapse: collapse'";
- $table_style2 = "cellpadding=3 border=1 bordercolor='#cccccc' style='border-collapse: collapse'";
-
- /* Accounts Payable */
- /* System check to see if quantity charged on purchase invoices exceeds the quantity received.
- If this parameter is checked the proportion by which the purchase invoice is an overcharge
- referred to before reporting an error */
-
- $check_qty_charged_vs_del_qty = true;
-
- /* System check to see if price charged on purchase invoices exceeds the purchase order price.
- If this parameter is checked the proportion by which the purchase invoice is an overcharge
- referred to before reporting an error */
-
- $check_price_charged_vs_order_price = True;
-
- $config_allocation_settled_allowance = 0.005;
-
- // Internal configurable variables
- //-----------------------------------------------------------------------------------
-
- /* Whether to display the demo login and password or not */
-
- $allow_demo_mode = false;
-
- /* for uploaded item pictures */
- $pic_width = 80;
- $pic_height = 50;
- $max_image_size = 500;
-
- /* skin for Business Graphics, 1, 2 or 3 */
- $graph_skin = 1;
-
- /*Security Group definitions - Depending on the AccessLevel of the user defined in the user set up
- the areas of functionality accessible can be modified.
- Each AccessLevel is associated with an array containing the security categories that the user is entitled to access
- Each script has a particular security category associated with it.
- If the security setting of the page is contained in the security group as determined by the access level then the user will be allowed access.
- Each page has a $page_security = x; variable
- This value is compared to contents of the array applicable which is based on the access level of the user.
- Access authorisation is checked in session.inc. If you wish to add more security groups
- with then you must add a new SecurityHeading to the security_headings array
- and a new array of Security categories to the Security Groups _at_the_end_ of the array
- This mechanism allows more fine grained control of access
- security_groups is an array of arrays
- The index is the order in which the array of allowed pages is defined new ones can be defined at will
- or by changing the numbers in each array the security access can be tailored. These numbers need to read
- in conjunction with the Page Security index
- Special case is security level 20 which is reserved for admins of first
- registered company (site admins). All potentially dangerous for whole FA
- site operations like installing addon modules require access level 20.
- */
-
- $security_headings = array(
- _("Inquiries"),
- _("Accountant"),
- _("System Administrator"),
- );
-
- $security_groups = array(
- array(1,2),
- array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,16),
- array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,20),
- );
-
- /* default start-up tab (orders/AP/stock/manuf/proj/GL/system) */
- $def_app = "orders";
-
- //MySQL Backup and Restore Settings
-
-if(isset($_SESSION["wa_current_user"])) {
- define("BACKUP_PATH", $comp_path.'/'.user_company()."/backup/");
-}
- // static js files path
- $js_path = $path_to_root.'/js/';
- // standard external js scripts included in all files
- $js_static = array('JsHttpRequest.js', 'behaviour.js', 'utils.js', 'inserts.js');
- // additional js source included in header
- $js_lib = $js_userlib = array();
-
-if (!defined('ICON_EDIT'))
-{
- define("ICON_EDIT", "edit.gif");
- define("ICON_DELETE", "delete.gif");
- define("ICON_ADD", "ok.gif");
- define("ICON_UPDATE", "ok.gif");
- define("ICON_OK", "ok.gif");
- define("ICON_CANCEL", "cancel.png");
- define("ICON_GL", "gl.png");
- define("ICON_PRINT", "print.png");
- define("ICON_PDF", "pdf.gif");
- define("ICON_DOC", "invoice.gif");
- define("ICON_CREDIT", "credit.gif");
- define("ICON_RECEIVE", "receive.gif");
- define("ICON_DOWN", "download.gif");
- define("ICON_MONEY", "money.png");
- define("ICON_REMOVE", "remove.png");
- define("ICON_REPORT", "report.png");
- define("ICON_VIEW", "view.gif");
-}
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-
-/*Connection Information for the database
-- $def_coy is the default company that is pre-selected on login
-
-- host is the computer ip address or name where the database is the default is localhost assuming that the web server is also the sql server
-
-- user is the user name under which the database should be accessed - need to change to the mysql (or other DB) user set up for purpose
- NB it is not secure to use root as the user with no password - a user with appropriate privileges must be set up
-
-- password is the password the user of the database requires to be sent to authorise the above database user
-
-- DatabaseName is the name of the database as defined in the RDMS being used. Typically RDMS allow many databases to be maintained under the same server.
- The scripts for MySQL provided use the name logicworks */
-
-
-$def_coy = 0;
-
-/*--- for advanced users, manually install, uncomment this, fill in the correct information and erase the rows below
-$tb_pref_counter = 1;
-
-$db_connections = array (
- 0 => array ('name' => 'Training Co.',
- 'host' => 'localhost',
- 'dbuser' => 'your_db_user_name',
- 'dbpassword' => 'your_db_password',
- 'dbname' => 'your_db_name',
- 'tbpref' => '0_')
- );
-*/
-
-$tb_pref_counter = 0;
-
-$db_connections = array ();
-
-?>
\ No newline at end of file
--- /dev/null
+News in FrontAccounting 2.2 Beta
+--------------------------------
+
+Common
+------
+- Quick Entries uses Tax Types instead of Item Tax Types
+- Support for default buttons with Ctrl-Enter/Escape hotkeys
+- Arrow navigations in menus
+- Option to use last document date on subsequent new documents.
+- Full support for inactive records
+- Time Zone on Reports
+- Audit Trail for all operations with Report
+- Bank Charge field in Customer/Supplier Payment.
+- New default fields in Company table for Bank Charge, Retained Earnings and
+ Profit/Loss Year.
+- Direct Allocation of Invoices in Customer/Supplier Payments
+- New Access Levels/Security Roles system enables fine tunning person access rights.
+- Item Tax Types moved to Setup module
+- Default Start-up Tab set by user.
+- Authorization timeout parameter set in Company preferences
+
+Sales
+-----
+- Customer/Supplier Balance Reports now with Open Balance from selected date
+- Added Sales Quotations, Inquiry and Report
+
+Purchasing
+----------
+- Better support for conversion factor in Purchasing Prices.
+- Purchasing price can have up to 6 decimals allowing fractions of hundredths in
+ prices.
+
+Items and Inventory
+-------------------
+- Item Categories contains default parameters for new items.
+- Excluded from Sale. Non Sales Items from Categories.
+- GRN Valuation Report
+- Automatic price-calculation of Items from Std. Cost (if no prices set on items)
+- Rounding of prices to nearest XX Cent after calculations.
+
+Manufacturing
+-------------
+- Printing/Emailing of Work Orders
+
+Dimensions
+----------
+- Re-opening of Closed dimensions
+
+Banking and General Ledger
+--------------------------
+- Closing a fiscal year also closes the balances and brings forward retained earnings
+- Deleting a fiscal year removes all transactions and convert into relevant Open
+ Balances.
+- Journal Enquiry
+- Edition/view of Journal Entries.
+- Group Sorting by Id in Account Selectors
+- Default per currency bank accounts (used in reports). The Bank Account selection on
+ documents has been replaced by this.
+
+Bugs fixed in this release
+--------------------------
+- Fixed php 5 warnings flood in error log.
+- All bugs up to release 2.1.6 are fixed in this release too.
+
--- /dev/null
+ FrontAccounting access control system
+ =====================================
+
+Since version 2.2 FrontAccounting has new, flexible access level control system.
+In contrast to previous system based on arrays stored in global config.php file,
+the new system uses per company security_roles tables. This approach makes
+FrontAccounting finally suitable for multicompany installation involving
+various types of companies.
+
+1. Security schema
+------------------
+
+New access control system uses following concepts:
+
+. Security area - elementary fragment of application functionality which
+ is placed under control of access system;
+
+. Security role - set of security areas which is accessable for user with
+ some role in company;
+
+. Security section - a couple of security areas of similar application grouped
+ together to make roles defining easier.
+
+Security areas stored in global $security_areas array have two properties:
+identifier (in numeric and string form) and description. Description is used
+only to identify area in security roles editor, while string identifiers are
+used in various places of source code to be checked against current user
+permissions.
+
+Every security area belongs to one security section, which can be considered
+as upper level of access control. All defined security sections are stored
+in global $security_sections array together with descriptions used in roles
+editor.
+
+2. Access Setup
+---------------
+
+FrontAccounting since version 2.2 has role based access system. It means that
+every user defined in a system has assigned role related to his position in
+company. For any user only security areas which belong to user's role are
+accesible.
+
+To grant access to any security area for any role administrator first have to
+make accessible also related area's security section. Switching security section
+off disables access to all related security areas.
+
+Security roles predefined in FrontAccounting initial database can be customized
+or completely rewritten by administrator according to company internal security
+policy.
+
+Some security areas crucial for overall site security are accesible only for
+administrators of the first installed company, who can be considered as
+superadmins. All those important areas are grouped in section 0
+(System administration), and as of FA 2.2 involve:
+ . Installing/update of companies
+ . Installing/update language message files
+ . Installing/activation system extensions
+ . System upgrades
+
+3. How all it works
+-------------------
+
+Every user defined in a system has one security role assigned. List of
+all accesible security areas/sections codes is retrieved from security_roles
+table on user login, and cached in user session variable for fast checking.
+Every page in a system has at least one related security area, which is
+assigned to $page_security global variable at the beginning of the page script.
+
+Page access control is performed by check_page_security() call in
+page() function (used for every displayed page) or by can_access_page()
+call in FrontReport constructor for all reports. When user has granted access
+rights to checked security area, selected page is displayed or report generated.
+Otherwise information message is displayed and page/report generation is aborted.
+
+4. Security extensions
+----------------------
+
+FrontAccounting application accepts two forms of functionality additions:
+extension modules and extension plugins. Both types of extensions can use
+standard security areas/sections to control access to introduced functionality,
+or define its own security areas and/or sections.
+
+To extend access control system with additional sections/areas, extension
+need to contain a file were all new extensions are defined. The access control
+file relative path should be entered during extension install process on
+Install/Activate Extensions page, or as 'access' property during direct entry
+in installed_extensions.php file.
+
+Every php script using security extensions have to call function
+add_security_extensions() to make defined extensions active. The call should
+be placed between session.inc inclusion and page() or FrontReport() call.
+
+5. Example access control configuration file
+--------------------------------------------
+
+This is content of sample access control file for CRM extension module:
+
+<?php
+/*
+ Define security section codes
+*/
+define('SS_CRM_C', 101<<8);
+define('SS_CRM', 102<<8);
+define('SS_CRM_A', 103<<8);
+
+/*
+ Additional security sections for CRM module
+*/
+$security_sections[SS_CRM_C] = _("CRM configuration");
+$security_sections[SS_CRM] = _("CRM transactions");
+$security_sections[SS_CRM_A] = _("CRM analytics");
+/*
+ Additional security areas for CRM module
+*/
+$security_areas['SA_CRMSETUP'] = array(SS_CRM_C|1, _("CRM module setup"));
+$security_areas['SA_CRMCONTACTENTRY'] = array(SS_CRM|1, _("Customer contact entry"));
+$security_areas['SA_CRMANALYITCS'] = array(SS_CRM|1, _("Pre-sale contact analytics"));
+
+?>
+
+The exact values used for security section codes are not very important,
+as they are rewritten by access control system during integration of
+access extensions. Therefore numeric values of security sections/areas should
+never be used directly in the extensions source. Use string representations
+instead when needed, or values retrieved from $security_areas array.
+
--- /dev/null
+Calculate sales price from standard cost
+----------------------------------------
+
+You can have automatic sales price calculation for items that do not have any
+prices in Sales Prices entered. This works independently from the Base Price
+List setting, but if the factor is set in the other Sales Type Lists it works
+together with them.
+
+Preparing and operation
+-----------------------
+
+Go into Setup tab - Company Setup.
+
+In the field, Base for auto price calculation, set a Base Price List.
+In the field, Add Price from Std cost, enter the % that you want to increase
+from the average standard costs for the items not listed in the Item Price List.
+If this value is empty there are no automatic price calculations. BE aware that
+an increase value of 0 will calculate the price to be the same as the Std cost.
+So to remove the calculation, just empty the field. It will then get an internal
+value of -1.
+If the average standard costs is 0, the calculation would result in 0 as well.
+
+The field, Round to nearest xxx Cents, will round the calculated result to the
+nearest Cent entered. If you have 2 decimals in the amounts the value 100 would
+be divided by the xxx value. If you have 3 decimals in the amounts the value
+1000 will be divided by the xxx value. If there is no fraction, the value will
+be rounded up to the nearest xxx value. If there is a fraction, the value xxx
+will be subtracted from the value (100-xxx) or (1000-xxx).
+
+Let us take an example:
+----------------------
+
+Item standard cost = 20.77
+Decimals = 2
+Value to increase the items with = 70 (%)
+Round to nearest value = 5
+
+the pow(10, 2) = 100. 100 divided by 5 = 20 and no fraction. Price after increase
+= 20.77 * (1 + 70 / 100) = 35.309. Rounded to nearest 5 cent value = 35.35;
+
+Let us set the Round to nearest value = 95.
+
+The value 100 / 95 = 1 and a fraction of 95. The Price will still be calculated
+to 35.309. Now the value will be rounded to 36.00 and subtracted by (100 - 95) =
+35.95.
+
+So you see it is very flexible. If you have larger prices you can even round up
+to nearest 10, 100 by setting the rounding to nearest value = 1000 or 10000.
+But take care if you have different prices, large prices and small prices. It might
+not be a good idea to round a value of 10.77 to 100.
+
+If there is a base price list set and for instance a factor 0.7 the price list in
+foreign currencies are calculated as well. And again, if a 'Round to nearest' value
+is set to other than 1 the foreign prices are rounded in the same way as explained
+above.
+
+This new price calculaton should work with sales kits too.
+
--- /dev/null
+Sales Quotations as a separate menu option
+------------------------------------------
+
+You can now create Sales Quotations in a separate form. You enter the 'Valid until'
+date. These Sales Quotations can later be used for creating a Sales Order.
+
+There is a new menu choice under Inquiries, Sales Quotation Inquiry. If the
+'Valid until' has been passed, the Sales Quotation is not shown. But you can
+select 'Show All' and all the Sales Quotation inside the period will be shown.
+
+In this Inquiry you have the option to look at the entire Quotation, edit the
+Quotation, print the Quotation and make a Sales Order from the Quotation.
+
+The Sales Quotations will not be deleted, so it is possible to use it agan and
+maybe edit it for use again.
+
+The Sales Quotations can however be deleted when editing. And when deleting a
+fiscal year, the Quotations will be deleted.
+
+The Sales Order print out can still be selected to be printed as a Quote should
+you prefer that.
--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+
+$page_security = 'SA_GLANALYTIC';
+$path_to_root="../..";
+
+include($path_to_root . "/includes/db_pager.inc");
+include_once($path_to_root . "/includes/session.inc");
+
+include_once($path_to_root . "/includes/date_functions.inc");
+include_once($path_to_root . "/includes/ui.inc");
+$js = "";
+if ($use_popup_windows)
+ $js .= get_js_open_window(800, 500);
+if ($use_date_picker)
+ $js .= get_js_date_picker();
+
+page(_($help_context = "Journal Inquiry"), false, false, "", $js);
+
+//-----------------------------------------------------------------------------------
+// Ajax updates
+//
+if (get_post('Search'))
+{
+ $Ajax->activate('journal_tbl');
+}
+//--------------------------------------------------------------------------------------
+if (!isset($_POST['filterType']))
+ $_POST['filterType'] = -1;
+
+start_form();
+
+start_table("class='tablestyle_noborder'");
+start_row();
+
+ref_cells(_("Reference:"), 'Ref', '',null, _('Enter reference fragment or leave empty'));
+
+journal_types_list_cells(_("Type:"), "filterType");
+date_cells(_("From:"), 'FromDate', '', null, 0, -1, 0);
+date_cells(_("To:"), 'ToDate');
+
+check_cells( _("Show closed:"), 'AlsoClosed', null);
+
+submit_cells('Search', _("Search"), '', '', 'default');
+
+end_row();
+end_table();
+
+function journal_pos($row)
+{
+ return $row['gl_seq'] ? $row['gl_seq'] : '-';
+}
+
+function systype_name($dummy, $type)
+{
+ global $systypes_array;
+
+ return $systypes_array[$type];
+}
+
+function view_link($row)
+{
+ return get_trans_view_str($row["type"], $row["type_no"]);
+}
+
+function gl_link($row)
+{
+ return get_gl_view_str($row["type"], $row["type_no"]);
+}
+
+$editors = array(
+ 0 => "/gl/gl_journal.php?ModifyGL=Yes&trans_no=%d&trans_type=%d",
+// 1=> Bank Payment,
+// 2=> Bank Deposit,
+// 4=> Funds Transfer,
+ ST_SALESINVOICE => "/sales/customer_invoice.php?ModifyInvoice=%d",
+// 11=>
+// free hand (debtors_trans.order_==0)
+// "/sales/credit_note_entry.php?ModifyCredit=%d"
+// credit invoice
+// "/sales/customer_credit_invoice.php?ModifyCredit=%d"
+// 12=> Customer Payment,
+ ST_CUSTDELIVERY => "/sales/customer_delivery.php?ModifyDelivery=%d",
+// 16=> Location Transfer,
+// 17=> Inventory Adjustment,
+// 20=> Supplier Invoice,
+// 21=> Supplier Credit Note,
+// 22=> Supplier Payment,
+// 25=> Purchase Order Delivery,
+// 28=> Work Order Issue,
+// 29=> Work Order Production",
+// 35=> Cost Update,
+);
+
+function edit_link($row)
+{
+ global $editors;
+
+ return isset($editors[$row["type"]]) && !is_closed_trans($row["type"], $row["type_no"]) ?
+ pager_link(_("Edit"),
+ sprintf($editors[$row["type"]], $row["type_no"], $row["type"]),
+ ICON_EDIT) : '';
+}
+
+// Tom Hallman 11 Nov 2009
+// IF(gl.type = 1... statement is for deposits/payments that may not actually result
+// in a deposit, such as when a fix is made. Without that statement (and the
+// joining of the bank_trans table), the fix deposit/payment amount would show up
+// incorrectly as only the positive side of the fix.
+$sql = "SELECT IF(ISNULL(a.gl_seq),0,a.gl_seq) as gl_seq,
+ gl.tran_date,
+ gl.type,
+ gl.type_no,
+ refs.reference,
+ IF(gl.type = 1 OR gl.type = 2,
+ bank_trans.amount,
+ SUM(IF(gl.amount>0, gl.amount,0))) as amount,
+ com.memo_,
+ IF(ISNULL(u.user_id),'',u.user_id) as user_id
+ FROM ".TB_PREF."gl_trans as gl
+ LEFT JOIN ".TB_PREF."audit_trail as a ON
+ (gl.type=a.type AND gl.type_no=a.trans_no)
+ LEFT JOIN ".TB_PREF."comments as com ON
+ (gl.type=com.type AND gl.type_no=com.id)
+ LEFT JOIN ".TB_PREF."refs as refs ON
+ (gl.type=refs.type AND gl.type_no=refs.id)
+ LEFT JOIN ".TB_PREF."users as u ON
+ a.user=u.id
+ LEFT JOIN ".TB_PREF."bank_trans as bank_trans ON
+ (gl.type=bank_trans.type AND gl.type_no=bank_trans.trans_no)
+ WHERE gl.tran_date >= '" . date2sql($_POST['FromDate']) . "'
+ AND gl.tran_date <= '" . date2sql($_POST['ToDate']) . "'
+ AND gl.amount!=0";
+if (isset($_POST['Ref']) && $_POST['Ref'] != "") {
+ $sql .= " AND reference LIKE '%". $_POST['Ref'] . "%'";
+}
+if (get_post('filterType') != -1) {
+ $sql .= " AND gl.type=".get_post('filterType');
+}
+if (!check_value('AlsoClosed')) {
+ $sql .= " AND gl_seq=0";
+}
+$sql .= " GROUP BY gl.type, gl.type_no";
+
+$cols = array(
+ _("#") => array('fun'=>'journal_pos', 'align'=>'center'),
+ _("Date") =>array('name'=>'tran_date','type'=>'date','ord'=>'desc'),
+ _("Type") => array('fun'=>'systype_name'),
+ _("Trans #") => array('fun'=>'view_link'),
+ _("Reference"),
+ _("Amount") => array('type'=>'amount'),
+ _("Memo"),
+ _("User"),
+ _("View") => array('insert'=>true, 'fun'=>'gl_link'),
+ array('insert'=>true, 'fun'=>'edit_link')
+);
+
+if (!check_value('AlsoClosed')) {
+ $cols[_("#")] = 'skip';
+}
+
+$table =& new_db_pager('journal_tbl', $sql, $cols);
+
+$table->width = "80%";
+
+display_db_pager($table);
+
+end_form();
+end_page();
+
+?>
--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+/*
+ Security sections groups various areas on both functionality and privilege levels.
+ Often analytic inquires are available only for management, and configuration
+ for administration or management staff. This is why we have those three
+ section type inside near every FA module.
+
+ Section codes 0-99 are reserved for core FA functionalities.
+ Every security section can contain up to 256 different areas.
+ External modules can extend security roles system by adding rows to
+ $security_sections and $security_areas using section codes >=100.
+ Security areas and sections created by extension modules/plugins
+ have dynamically assigned 3-byte integer codes. The highest byte is zero
+ for sections/areas defined in this file, and extid+1 for those defined
+ by extensions
+*/
+define('SS_SADMIN', 1<<8); // site admin
+define('SS_SETUP', 2<<8); // company level setup
+define('SS_SPEC', 3<<8); // special administration
+
+define('SS_SALES_C',11<<8); // configuration
+define('SS_SALES', 12<<8); // transactions
+define('SS_SALES_A',13<<8); // analytic functions/reports/inquires
+
+define('SS_PURCH_C',21<<8);
+define('SS_PURCH', 22<<8);
+define('SS_PURCH_A',23<<8);
+
+define('SS_ITEMS_C',31<<8);
+define('SS_ITEMS', 32<<8);
+define('SS_ITEMS_A',33<<8);
+
+define('SS_MANUF_C',41<<8);
+define('SS_MANUF', 42<<8);
+define('SS_MANUF_A',43<<8);
+
+define('SS_DIM_C', 51<<8);
+define('SS_DIM', 52<<8);
+define('SS_DIM_A', 53<<8);
+
+define('SS_GL_C', 61<<8);
+define('SS_GL', 62<<8);
+define('SS_GL_A', 63<<8);
+
+$security_sections = array(
+ SS_SADMIN => _("System administration"),
+ SS_SETUP => _("Company setup"),
+ SS_SPEC => _("Special maintenance"),
+ SS_SALES_C => _("Sales configuration"),
+ SS_SALES => _("Sales transactions"),
+ SS_SALES_A => _("Sales related reports"),
+ SS_PURCH_C => _("Purchase configuration"),
+ SS_PURCH => _("Purchase transactions"),
+ SS_PURCH_A => _("Purchase analytics"),
+ SS_ITEMS_C => _("Inventory configuration"),
+ SS_ITEMS => _("Inventory operations"),
+ SS_ITEMS_A => _("Inventory analytics"),
+ SS_MANUF_C => _("Manufacturing configuration"),
+ SS_MANUF => _("Manufacturing transations"),
+ SS_MANUF_A => _("Manufacturing analytics"),
+ SS_DIM_C => _("Dimensions configuration"),
+ SS_DIM => _("Dimensions"),
+ SS_GL_C => _("Banking & GL configuration"),
+ SS_GL => _("Banking & GL transactions"),
+ SS_GL_A => _("Banking & GL analytics")
+);
+
+/*
+ This table stores security areas available in FA.
+ Key is area identifier used to check user rights, values are
+ codes stored for each role in security_roles table and description used
+ in roles editor.
+
+ Set of allowed access areas codes is retrieved during user login from
+ security_roles table, and cached in user profile.
+
+ Special value 'SA_OPEN' is used for publicly available pages like login/logout.
+*/
+$security_areas =array(
+//
+// Site administration
+//
+ 'SA_CREATECOMPANY' =>array(SS_SADMIN|1, _("Install/update companies")),
+ 'SA_CREATELANGUAGE' => array(SS_SADMIN|2, _("Install/update languages")),
+ 'SA_CREATEMODULES' => array(SS_SADMIN|3, _("Install/upgrade modules")),
+ 'SA_SOFTWAREUPGRADE' => array(SS_SADMIN|4, _("Software upgrades")),
+//
+// Company setup
+//
+ 'SA_SETUPCOMPANY' => array(SS_SETUP|1, _("Company parameters")),
+ 'SA_SECROLES' => array(SS_SETUP|2, _("Access levels edition")),
+ 'SA_USERS' => array(SS_SETUP|3, _("Users setup")),
+ 'SA_POSSETUP' => array(SS_SETUP|4, _("Point of sales definitions")),
+ 'SA_PRINTERS' => array(SS_SETUP|5, _("Printers configuration")),
+ 'SA_PRINTPROFILE' => array(SS_SETUP|6, _("Print profiles")),
+ 'SA_PAYTERMS' => array(SS_SETUP|7, _("Payment terms")),
+ 'SA_SHIPPING' => array(SS_SETUP|8, _("Shipping ways")),
+ 'SA_CRSTATUS' => array(SS_SETUP|9, _("Credit status definitions changes")),
+ 'SA_INVENTORYLOCATION' => array(SS_SETUP|10, _("Inventory locations changes")),
+ 'SA_INVENTORYMOVETYPE' => array(SS_SETUP|11, _("Inventory movement types")),
+ 'SA_WORKCENTRES' => array(SS_SETUP|12, _("Manufacture work centres")),
+ 'SA_FORMSETUP' => array(SS_SETUP|13, _("Forms setup")),
+//
+// Special and common functions
+//
+ 'SA_VOIDTRANSACTION' => array(SS_SPEC|1, _("Voiding transactions")),
+ 'SA_BACKUP' => array(SS_SPEC|2, _("Database backup/restore")),
+ 'SA_VIEWPRINTTRANSACTION' => array(SS_SPEC|3, _("Common view/print transactions interface")),
+ 'SA_ATTACHDOCUMENT' => array(SS_SPEC|4, _("Attaching documents")),
+ 'SA_SETUPDISPLAY' => array(SS_SPEC|5, _("Display preferences")), //???
+ 'SA_CHGPASSWD' => array(SS_SPEC|6, _("Password changes")), //???
+
+//
+// Sales related functionality
+//
+ 'SA_SALESTYPES' => array(SS_SALES_C|1, _("Sales types")),
+ 'SA_SALESPRICE' => array(SS_SALES_C|2, _("Sales prices edition")),
+ 'SA_SALESMAN' => array(SS_SALES_C|3, _("Sales staff maintenance")),
+ 'SA_SALESAREA' => array(SS_SALES_C|4, _("Sales areas maintenance")),
+ 'SA_SALESGROUP' => array(SS_SALES_C|5, _("Sales groups changes")),
+ 'SA_STEMPLATE' => array(SS_SALES_C|6, _("Sales templates")),
+ 'SA_SRECURRENT' => array(SS_SALES_C|7, _("Recurrent invoices definitions")),
+
+ 'SA_SALESTRANSVIEW' => array(SS_SALES|1, _("Sales transactions view")),
+ 'SA_CUSTOMER' => array(SS_SALES|2, _("Sales customer and branches changes")),
+ 'SA_SALESQUOTE' => array(SS_SALES|10, _("Sales quotations")),
+ 'SA_SALESORDER' => array(SS_SALES|3, _("Sales orders edition")),
+ 'SA_SALESDELIVERY' => array(SS_SALES|4, _("Sales deliveries edition")),
+ 'SA_SALESINVOICE' => array(SS_SALES|5, _("Sales invoices edition")),
+ 'SA_SALESCREDITINV' => array(SS_SALES|6, _("Sales credit notes against invoice")),
+ 'SA_SALESCREDIT' => array(SS_SALES|7, _("Sales freehand credit notes")),
+ 'SA_SALESPAYMNT' => array(SS_SALES|8, _("Customer payments entry")),
+ 'SA_SALESALLOC' => array(SS_SALES|9, _("Customer payments allocation")),
+
+ 'SA_SALESANALYTIC' => array(SS_SALES_A|1, _("Sales analytical reports")),
+ 'SA_SALESBULKREP' => array(SS_SALES_A|2, _("Sales document bulk reports")),
+ 'SA_PRICEREP' => array(SS_SALES_A|3, _("Sales prices listing")),
+ 'SA_SALESMANREP' => array(SS_SALES_A|4, _("Sales staff listing")),
+ 'SA_CUSTBULKREP' => array(SS_SALES_A|5, _("Customer bulk listing")),
+ 'SA_CUSTSTATREP' => array(SS_SALES_A|6, _("Customer status report")),
+ 'SA_CUSTPAYMREP' => array(SS_SALES_A|7, _("Customer payments report")),
+
+//
+// Purchase related functions
+//
+ 'SA_PURCHASEPRICING' => array(SS_PURCH_C|1, _("Purchase price changes")),
+
+ 'SA_SUPPTRANSVIEW' => array(SS_PURCH|1, _("Supplier transactions view")),
+ 'SA_SUPPLIER' => array(SS_PURCH|2, _("Suppliers changes")),
+ 'SA_PURCHASEORDER' => array(SS_PURCH|3, _("Purchase order entry")),
+ 'SA_GRN' => array(SS_PURCH|4, _("Purchase receive")),
+ 'SA_SUPPLIERINVOICE' => array(SS_PURCH|5, _("Supplier invoices")),
+ 'SA_GRNDELETE' => array(SS_PURCH|9, _("Deleting GRN items during invoice entry")),
+ 'SA_SUPPLIERCREDIT' => array(SS_PURCH|6, _("Supplier credit notes")),
+ 'SA_SUPPLIERPAYMNT' => array(SS_PURCH|7, _("Supplier payments")),
+ 'SA_SUPPLIERALLOC' => array(SS_PURCH|8, _("Supplier payments allocations")),
+
+ 'SA_SUPPLIERANALYTIC' => array(SS_PURCH_A|1, _("Supplier analytical reports")),
+ 'SA_SUPPBULKREP' => array(SS_PURCH_A|2, _("Supplier document bulk reports")),
+ 'SA_SUPPPAYMREP' => array(SS_PURCH_A|3, _("Supplier payments report")),
+//
+// Inventory
+//
+ 'SA_ITEM' => array(SS_ITEMS_C|1, _("Stock items add/edit")),
+ 'SA_SALESKIT' => array(SS_ITEMS_C|2, _("Sales kits")),
+ 'SA_ITEMCATEGORY' => array(SS_ITEMS_C|3, _("Item categories")),
+ 'SA_UOM' => array(SS_ITEMS_C|4, _("Units of measure")),
+
+ 'SA_ITEMSSTATVIEW' => array(SS_ITEMS|1, _("Stock status view")),
+ 'SA_ITEMSTRANSVIEW' => array(SS_ITEMS|2, _("Stock transactions view")),
+ 'SA_FORITEMCODE' => array(SS_ITEMS|3, _("Foreign item codes entry")),
+ 'SA_LOCATIONTRANSFER' => array(SS_ITEMS|4, _("Inventory location transfers")),
+ 'SA_INVENTORYADJUSTMENT' => array(SS_ITEMS|5, _("Inventory adjustments")),
+
+ 'SA_REORDER' => array(SS_ITEMS_A|1, _("Reorder levels")),
+ 'SA_ITEMSANALYTIC' => array(SS_ITEMS_A|2, _("Items analytical reports and inquiries")),
+ 'SA_ITEMSVALREP' => array(SS_ITEMS_A|3, _("Inventory valuation report")),
+
+//
+// Manufacturing module
+//
+ 'SA_BOM' => array(SS_MANUF_C|1, _("Bill of Materials")),
+
+ 'SA_MANUFTRANSVIEW' => array(SS_MANUF|1, _("Manufacturing operations view")),
+ 'SA_WORKORDERENTRY' => array(SS_MANUF|2, _("Work order entry")),
+ 'SA_MANUFISSUE' => array(SS_MANUF|3, _("Material issues entry")),
+ 'SA_MANUFRECEIVE' => array(SS_MANUF|4, _("Final product receive")),
+ 'SA_MANUFRELEASE' => array(SS_MANUF|5, _("Work order releases")),
+
+ 'SA_WORKORDERANALYTIC' => array(SS_MANUF_A|1, _("Work order analytical reports and inquiries")),
+ 'SA_WORKORDERCOST' => array(SS_MANUF_A|2, _("Manufacturing cost inquiry")),
+ 'SA_MANUFBULKREP' => array(SS_SALES_A|3, _("Work order bulk reports")),
+ 'SA_BOMREP' => array(SS_MANUF_A|4, _("Bill of materials reports")),
+//
+// Dimensions
+//
+ 'SA_DIMTAGS' => array(SS_DIM_C|1, _("Dimension tags")),
+
+ 'SA_DIMTRANSVIEW' => array(SS_DIM|1, _("Dimension view")),
+
+ 'SA_DIMENSION' => array(SS_DIM|2, _("Dimension entry")),
+
+ 'SA_DIMENSIONREP' => array(SS_DIM|3, _("Dimension reports")),
+//
+// Banking and General Ledger
+//
+ 'SA_ITEMTAXTYPE' => array(SS_GL_C|1, _("Item tax type definitions")),
+ 'SA_GLACCOUNT' => array(SS_GL_C|2, _("GL accounts edition")),
+ 'SA_GLACCOUNTGROUP' => array(SS_GL_C|3, _("GL account groups")),
+ 'SA_GLACCOUNTCLASS' => array(SS_GL_C|4, _("GL account classes")),
+ 'SA_QUICKENTRY' => array(SS_GL_C|5, _("Quick GL entry definitions")),
+ 'SA_CURRENCY' => array(SS_GL_C|6, _("Currencies")),
+ 'SA_BANKACCOUNT' => array(SS_GL_C|7, _("Bank accounts")),
+ 'SA_TAXRATES' => array(SS_GL_C|8, _("Tax rates")),
+ 'SA_TAXGROUPS' => array(SS_GL_C|8, _("Tax groups")),
+ 'SA_FISCALYEARS' => array(SS_GL_C|9, _("Fiscal years maintenance")),
+ 'SA_GLSETUP' => array(SS_GL_C|10, _("Company GL setup")),
+ 'SA_GLACCOUNTTAGS' => array(SS_GL_C|11, _("GL Account tags")),
+
+ 'SA_BANKTRANSVIEW' => array(SS_GL|1, _("Bank transactions view")),
+ 'SA_GLTRANSVIEW' => array(SS_GL|2, _("GL postings view")),
+ 'SA_EXCHANGERATE' => array(SS_GL|3, _("Exchange rate table changes")),
+ 'SA_PAYMENT' => array(SS_GL|4, _("Bank payments")),
+ 'SA_DEPOSIT' => array(SS_GL|5, _("Bank deposits")),
+ 'SA_BANKTRANSFER' => array(SS_GL|6, _("Bank account transfers")),
+ 'SA_RECONCILE' => array(SS_GL|7, _("Bank reconciliation")),
+ 'SA_JOURNALENTRY' => array(SS_GL|8, _("Manual journal entries")),
+ 'SA_BANKJOURNAL' => array(SS_GL|11, _("Journal entries to bank related accounts")),
+ 'SA_BUDGETENTRY' => array(SS_GL|9, _("Budget edition")),
+ 'SA_STANDARDCOST' => array(SS_GL|10, _("Item standard costs")),
+
+ 'SA_GLANALYTIC' => array(SS_GL_A|1, _("GL analytical reports and inquiries")),
+ 'SA_TAXREP' => array(SS_GL_A|2, _("Tax reports and inquiries")),
+ 'SA_BANKREP' => array(SS_GL_A|3, _("Bank reports and inquiries")),
+ 'SA_GLREP' => array(SS_GL_A|4, _("GL reports and inquiries")),
+);
+/*
+ This function should be called whenever we want to extend core access level system
+ with new security areas and/or sections i.e.:
+ . on any page with non-standard security areas
+ . in security roles editor
+ The call should be placed between session.inc inclusion and page() call.
+ Up to 155 security sections and 155 security areas for any extension can be installed.
+*/
+function add_access_extensions()
+{
+ global $security_areas, $security_sections, $installed_extensions;
+
+ foreach($installed_extensions as $extid => $ext) {
+ $scode = 100;
+ $acode = 100;
+ $accext = get_access_extensions($extid);
+ $extsections = $accext[1];
+ $extareas = $accext[0];
+ $extcode = $extid<<16;
+
+ $trans = array();
+ foreach($extsections as $code =>$name) {
+ $trans[$code] = $scode<<8;
+ // reassign section codes
+ $security_sections[$trans[$code]|$extcode] = $name;
+ $scode++;
+ }
+ foreach($extareas as $code => $area) {
+ $section = $area[0]&0xff00;
+ // extension modules:
+ // if area belongs to nonstandard section
+ // use translated section codes and
+ // preserve lower part of area code
+ if (isset($trans[$section])) {
+ $section = $trans[$section];
+ }
+ // otherwise assign next available
+ // area code >99
+ $area[0] = $extcode | $section | ($acode++);
+ $security_areas[$code] = $area;
+ }
+ }
+}
+/*
+ Helper function to retrieve extension access definitions in isolated environment.
+*/
+function get_access_extensions($id) {
+ global $path_to_root, $installed_extensions;
+
+ $ext = $installed_extensions[$id];
+
+ $security_sections = $security_areas = array();
+
+ if (isset($ext['acc_file']))
+ include($path_to_root.($ext['type'] == 'plugin' ? '/modules/':'/').$ext['path'].'/'.$ext['acc_file']);
+
+ return array($security_areas, $security_sections);
+}
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+
+function add_audit_trail($trans_type, $trans_no, $trans_date, $descr='')
+{
+ $sql = "INSERT INTO ".TB_PREF."audit_trail"
+ . " (type, trans_no, user, fiscal_year, gl_date, description, gl_seq)
+ VALUES(".db_escape($trans_type).", ".db_escape($trans_no).","
+ . $_SESSION["wa_current_user"]->user. ","
+ . get_company_pref('f_year') .","
+ . "'". date2sql($trans_date) ."',"
+ . db_escape($descr). ", 0)";
+
+ db_query($sql, "Cannot add audit info");
+
+ // all audit records beside latest one should have gl_seq set to NULL
+ // to avoid need for subqueries (not existing in MySQL 3) all over the code
+ $sql = "UPDATE ".TB_PREF."audit_trail SET gl_seq = NULL"
+ . " WHERE type=".db_escape($trans_type)." AND trans_no="
+ .db_escape($trans_no)." AND id!=".db_insert_id();
+
+ db_query($sql, "Cannot update audit gl_seq");
+}
+
+function get_audit_trail_all($trans_type, $trans_no)
+{
+ $sql = "SELECT * FROM ".TB_PREF."audit_trail"
+ ." WHERE type=".db_escape($trans_type)." AND trans_no="
+ .db_escape($trans_no);
+
+ return db_query($sql, "Cannot get all audit info for transaction");
+}
+
+function get_audit_trail_last($trans_type, $trans_no)
+{
+ $sql = "SELECT * FROM ".TB_PREF."audit_trail"
+ ." WHERE type=".db_escape($trans_type).
+ " AND trans_no=".db_escape($trans_no)." AND NOT ISNULL(gl_seq)";
+
+ $res = db_query($sql, "Cannot get last audit info for transaction");
+ if ($res)
+ $row = db_fetch($res);
+
+ return $row;
+}
+
+/*
+ Confirm and close for edition all transactions up to date $todate,
+ and reindex journal.
+*/
+function close_transactions($todate) {
+ $errors = 0;
+ $sql = "SELECT DISTINCT a.id, a.gl_date, a.fiscal_year"
+ ." FROM ".TB_PREF."gl_trans gl"
+ ." LEFT JOIN ". TB_PREF."audit_trail a ON
+ (gl.type=a.type AND gl.type_no=a.trans_no)"
+ . " WHERE gl_date<='". date2sql($todate) ."'"
+ . " AND NOT ISNULL(gl_seq)"
+ . " ORDER BY a.fiscal_year, a.gl_date, a.id";
+
+ $result = db_query($sql, "Cannot select transactions for closing");
+
+ if (db_num_rows($result)) {
+ $last_year = 0;
+
+ while ($row = db_fetch($result)) {
+ if ($row['fiscal_year'] == null) {
+ $errors = 1; continue;
+ }
+ if ($last_year != $row['fiscal_year']) {
+ $last_year = $row['fiscal_year'];
+ $counter = 1; // reset counter on fiscal year change
+ } else
+ $counter++;
+ $sql2 = "UPDATE ".TB_PREF."audit_trail SET"
+ . " gl_seq=$counter"
+ . " WHERE id=".$row['id'];
+
+ db_query($sql2, "Cannot reindex journal");
+ }
+ }
+
+ if ($errors)
+ display_warning(_("Some transactions journal GL postings were not indexed due to lack of audit trail record."));
+}
+
+/*
+ Reopen all transactions for edition up from date $fromdate
+*/
+function open_transactions($fromdate) {
+
+ $sql = "SELECT a.id, a.gl_date, a.fiscal_year"
+ ." FROM ".TB_PREF."gl_trans gl"
+ ." LEFT JOIN ". TB_PREF."audit_trail a ON
+ (gl.type=a.type AND gl.type_no=a.trans_no)"
+ . " WHERE gl_date>='". date2sql($fromdate) ."'"
+ . " AND !ISNULL(gl_seq)"
+ . " ORDER BY a.fiscal_year, a.gl_date, a.id";
+
+ $result = db_query($sql, "Cannot select transactions for openning");
+
+ if (db_num_rows($result)) {
+ $last_year = 0;
+
+ while ($row = db_fetch($result)) {
+ if ($row['fiscal_year'] == null) {
+ continue;
+ }
+ $sql2 = "UPDATE ".TB_PREF."audit_trail SET"
+ . " gl_seq=0"
+ . " WHERE id=".$row['id'];
+
+ db_query($sql2, "Cannot clear journal order");
+ }
+ }
+}
+/*
+ Closed transactions have gl_seq number assigned.
+*/
+function is_closed_trans($type, $trans_no) {
+ $sql = "SELECT gl_seq FROM ".TB_PREF."audit_trail"
+ . " WHERE type=".db_escape($type)
+ ." AND trans_no=".db_escape($trans_no)
+ ." AND gl_seq>0";
+
+ $res = db_query($sql, "Cannot check transaction");
+
+ return db_num_rows($res);
+}
+
+?>
+++ /dev/null
-<?php
-/**********************************************************************
- Copyright (C) FrontAccounting, LLC.
- Released under the terms of the GNU General Public License, GPL,
- as published by the Free Software Foundation, either version 3
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
-***********************************************************************/
-// always use capitals in reserved words (for is_reserved_word comparisons)
-
-$any_item = 'AN';
-$any_number = -1;
-$all_option = '';
-$all_option_numeric = -1;
-
-class reserved_words
-{
-
- function get_any()
- {
- global $any_item;
- return $any_item;
- }
-
- function get_any_numeric()
- {
- global $any_number;
- return $any_number;
- }
-
- function get_all()
- {
- global $all_option;
- return $all_option;
- }
-
- function get_all_numeric()
- {
- global $all_option_numeric;
- return $all_option_numeric;
- }
-
- function is_reserved_word($str)
- {
- $str = strtoupper($str);
- if ($str == get_any())
- return true;
- if ($str == get_all())
- return true;
- return false;
- }
-
-}
-
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-
-/* How to make new entries here
-
--- if adding extensions at the beginning of the list, make sure it's index is set to 0 (it has ' 0 => ')
--- 'app_file' is the application file name to be put into folder applications
--- 'name' is the name of the extension module. Will become the index of the application
--- 'title' is the Menu Title
--- 'folder' is the folder where the extension files exist
-
-*/
-
-$installed_extensions = array ();
-
-// example
-/*
-$installed_extensions = array (
- 0 => array ('app_file' => 'organizer.php', 'name' => 'organizer', 'title' => 'Organizer', 'folder' => 'organizer'),
- array ('app_file' => 'payroll.php', 'name' => 'payroll', 'title' => 'Payroll', 'folder' => 'payroll')
- );
-*/
-?>
\ No newline at end of file
--- /dev/null
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+function focus_alloc(i) {
+ save_focus(i);
+ i.setAttribute('_last', get_amount(i.name));
+}
+
+function blur_alloc(i) {
+ var change = get_amount(i.name);
+ price_format(i.name, change, user.pdec);
+ if (i.name != 'amount' && i.name != 'charge') {
+ if (change<0) change = 0;
+ change = change-i.getAttribute('_last');
+ if (i.name == 'discount') change = -change;
+
+ var total = get_amount('amount')+change;
+ price_format('amount', total, user.pdec, 0);
+ }
+}
+
+function allocate_all(doc) {
+ var amount = get_amount('amount'+doc);
+ var unallocated = get_amount('un_allocated'+doc);
+ var total = get_amount('amount');
+ var left = 0;
+ total -= (amount-unallocated);
+ left -= (amount-unallocated);
+ amount = unallocated;
+ if(left<0) {
+ total += left;
+ amount += left;
+ left = 0;
+ }
+ price_format('amount'+doc, amount, user.pdec);
+ price_format('amount', total, user.pdec);
+}
+
+function allocate_none(doc) {
+ amount = get_amount('amount'+doc);
+ total = get_amount('amount');
+ price_format('amount'+doc, 0, user.pdec);
+ price_format('amount', total-amount, user.pdec);
+}
+
+var allocations = {
+ '.amount': function(e) {
+ e.onblur = function() {
+ blur_alloc(this);
+ };
+ e.onfocus = function() {
+ focus_alloc(this);
+ };
+ }
+}
+
+Behaviour.register(allocations);
+++ /dev/null
-<?php
-
-/* How to make new entries here
-
--- if adding languages at the beginning of the list, make sure it's index is set to 0 (it has ' 0 => ')
--- 'code' should match the name of the directory for the language under \lang
--- 'name' is the name that will be displayed in the language selection list (in Users and Display Setup)
--- 'rtl' only needs to be set for right-to-left languages like Arabic and Hebrew
-
-*/
-
-
-$installed_languages = array (
- 0 => array ('code' => 'en_GB', 'name' => 'English', 'encoding' => 'iso-8859-1'),
- array ('code' => 'en_US', 'name' => 'English (US)', 'encoding' => 'iso-8859-1'),
- );
-
-$dflt_lang = 'en_GB';
-?>
\ No newline at end of file
+++ /dev/null
-<?php
-
-/*****************************************************************
-External modules for FrontAccounting
-******************************************************************/
-
-
-$installed_modules = array ();
-?>
\ No newline at end of file
--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+$page_security = $_POST['PARAM_0'] == $_POST['PARAM_1'] ?
+ 'SA_SALESTRANSVIEW' : 'SA_SALESBULKREP';
+// ----------------------------------------------------------------
+// $ Revision: 2.0 $
+// Creator: Joe Hunt
+// date_: 2005-05-19
+// Title: Print Sales Quotations
+// ----------------------------------------------------------------
+$path_to_root="..";
+
+include_once($path_to_root . "/includes/session.inc");
+include_once($path_to_root . "/includes/date_functions.inc");
+include_once($path_to_root . "/includes/data_checks.inc");
+include_once($path_to_root . "/sales/includes/sales_db.inc");
+
+//----------------------------------------------------------------------------------------------------
+
+print_sales_quotations();
+
+function print_sales_quotations()
+{
+ global $path_to_root, $print_as_quote;
+
+ include_once($path_to_root . "/reporting/includes/pdf_report.inc");
+
+ $from = $_POST['PARAM_0'];
+ $to = $_POST['PARAM_1'];
+ $currency = $_POST['PARAM_2'];
+ $email = $_POST['PARAM_3'];
+ $comments = $_POST['PARAM_4'];
+
+ if ($from == null)
+ $from = 0;
+ if ($to == null)
+ $to = 0;
+ $dec = user_price_dec();
+
+ $cols = array(4, 60, 225, 300, 325, 385, 450, 515);
+
+ // $headers in doctext.inc
+ $aligns = array('left', 'left', 'right', 'left', 'right', 'right', 'right');
+
+ $params = array('comments' => $comments);
+
+ $cur = get_company_Pref('curr_default');
+
+ if ($email == 0)
+ {
+ $rep = new FrontReport(_("SALES QUOTATION"), "SalesQuotationBulk", user_pagesize());
+ $rep->currency = $cur;
+ $rep->Font();
+ $rep->Info($params, $cols, null, $aligns);
+ }
+
+ for ($i = $from; $i <= $to; $i++)
+ {
+ $myrow = get_sales_order_header($i, ST_SALESQUOTE);
+ $baccount = get_default_bank_account($myrow['curr_code']);
+ $params['bankaccount'] = $baccount['id'];
+ $branch = get_branch($myrow["branch_code"]);
+ if ($email == 1)
+ {
+ $rep = new FrontReport("", "", user_pagesize());
+ $rep->currency = $cur;
+ $rep->Font();
+ $rep->filename = "SalesQuotation" . $i . ".pdf";
+ $rep->Info($params, $cols, null, $aligns);
+ }
+ $rep->title = _("SALES QUOTATION");
+ $rep->Header2($myrow, $branch, $myrow, $baccount, 7);
+
+ $result = get_sales_order_details($i, ST_SALESQUOTE);
+ $SubTotal = 0;
+ while ($myrow2=db_fetch($result))
+ {
+ $Net = round2(((1 - $myrow2["discount_percent"]) * $myrow2["unit_price"] * $myrow2["quantity"]),
+ user_price_dec());
+ $SubTotal += $Net;
+ $DisplayPrice = number_format2($myrow2["unit_price"],$dec);
+ $DisplayQty = number_format2($myrow2["quantity"],get_qty_dec($myrow2['stk_code']));
+ $DisplayNet = number_format2($Net,$dec);
+ if ($myrow2["discount_percent"]==0)
+ $DisplayDiscount ="";
+ else
+ $DisplayDiscount = number_format2($myrow2["discount_percent"]*100,user_percent_dec()) . "%";
+ $rep->TextCol(0, 1, $myrow2['stk_code'], -2);
+ $oldrow = $rep->row;
+ $rep->TextColLines(1, 2, $myrow2['description'], -2);
+ $newrow = $rep->row;
+ $rep->row = $oldrow;
+ $rep->TextCol(2, 3, $DisplayQty, -2);
+ $rep->TextCol(3, 4, $myrow2['units'], -2);
+ $rep->TextCol(4, 5, $DisplayPrice, -2);
+ $rep->TextCol(5, 6, $DisplayDiscount, -2);
+ $rep->TextCol(6, 7, $DisplayNet, -2);
+ $rep->row = $newrow;
+ //$rep->NewLine(1);
+ if ($rep->row < $rep->bottomMargin + (15 * $rep->lineHeight))
+ $rep->Header2($myrow, $branch, $myrow, $baccount, 9);
+ }
+ if ($myrow['comments'] != "")
+ {
+ $rep->NewLine();
+ $rep->TextColLines(1, 5, $myrow['comments'], -2);
+ }
+ $DisplaySubTot = number_format2($SubTotal,$dec);
+ $DisplayFreight = number_format2($myrow["freight_cost"],$dec);
+
+ $rep->row = $rep->bottomMargin + (15 * $rep->lineHeight);
+ $linetype = true;
+ $doctype = 9;
+ if ($rep->currency != $myrow['curr_code'])
+ {
+ include($path_to_root . "/reporting/includes/doctext2.inc");
+ }
+ else
+ {
+ include($path_to_root . "/reporting/includes/doctext.inc");
+ }
+
+ $rep->TextCol(3, 6, $doc_Sub_total, -2);
+ $rep->TextCol(6, 7, $DisplaySubTot, -2);
+ $rep->NewLine();
+ $rep->TextCol(3, 6, $doc_Shipping, -2);
+ $rep->TextCol(6, 7, $DisplayFreight, -2);
+ $rep->NewLine();
+ $DisplayTotal = number_format2($myrow["freight_cost"] + $SubTotal, $dec);
+ $rep->Font('bold');
+ $rep->TextCol(3, 6, $doc_TOTAL_ORDER, - 2);
+ $rep->TextCol(6, 7, $DisplayTotal, -2);
+ $rep->Font();
+ if ($email == 1)
+ {
+ if ($myrow['contact_email'] == '')
+ {
+ $myrow['contact_email'] = $branch['email'];
+ if ($myrow['contact_email'] == '')
+ $myrow['contact_email'] = $myrow['master_email'];
+ $myrow['DebtorName'] = $branch['br_name'];
+ }
+ //$myrow['reference'] = $i;
+ $rep->End($email, $doc_Invoice_no . " " . $i, $myrow);
+ }
+ }
+ if ($email == 0)
+ $rep->End();
+}
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+$page_security = 'SA_SUPPLIERANALYTIC';
+// ----------------------------------------------------------------
+// $ Revision: 2.0 $
+// Creator: Joe Hunt
+// date_: 2005-05-19
+// Title: GRN Valuation Report
+// ----------------------------------------------------------------
+$path_to_root="..";
+
+include_once($path_to_root . "/includes/session.inc");
+include_once($path_to_root . "/includes/date_functions.inc");
+include_once($path_to_root . "/includes/data_checks.inc");
+include_once($path_to_root . "/includes/banking.inc");
+include_once($path_to_root . "/gl/includes/gl_db.inc");
+include_once($path_to_root . "/inventory/includes/db/items_category_db.inc");
+
+//----------------------------------------------------------------------------------------------------
+
+print_grn_valuation();
+
+function getTransactions($from, $to)
+{
+ $from = date2sql($from);
+ $to = date2sql($to);
+ $sql = "SELECT ".TB_PREF."grn_batch.delivery_date, ".TB_PREF."grn_batch.supplier_id,
+ ".TB_PREF."purch_order_details.*,
+ ".TB_PREF."stock_master.description
+ FROM ".TB_PREF."stock_master,
+ ".TB_PREF."purch_order_details,
+ ".TB_PREF."grn_batch
+ WHERE ".TB_PREF."stock_master.stock_id=".TB_PREF."purch_order_details.item_code
+ AND ".TB_PREF."grn_batch.purch_order_no=".TB_PREF."purch_order_details.order_no
+ AND ".TB_PREF."purch_order_details.quantity_received>0
+ AND ".TB_PREF."grn_batch.delivery_date>='$from'
+ AND ".TB_PREF."grn_batch.delivery_date<='$to'
+ ORDER BY ".TB_PREF."stock_master.stock_id, ".TB_PREF."grn_batch.delivery_date";
+ return db_query($sql,"No transactions were returned");
+
+}
+
+//----------------------------------------------------------------------------------------------------
+
+function print_grn_valuation()
+{
+ global $path_to_root;
+
+ $from = $_POST['PARAM_0'];
+ $to = $_POST['PARAM_1'];
+ $comments = $_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");
+
+ $dec = user_price_dec();
+
+ $cols = array(0, 75, 225, 275, 345, 390, 445, 515);
+ $headers = array(_('Stock ID'), _('Description'), _('PO No'), _('Qty Received'), _('Unit Price'), _('Actual Price'), _('Total'));
+
+ $aligns = array('left', 'left', 'left', 'right', 'right', 'right', 'right');
+
+ $params = array( 0 => $comments,
+ 1 => array('text' => _('Period'),'from' => $from, 'to' => $to));
+
+ $rep = new FrontReport(_('GRN Valuation Report'), "GRNValuationReport", user_pagesize());
+
+ $rep->Font();
+ $rep->Info($params, $cols, $headers, $aligns);
+ $rep->Header();
+
+ $res = getTransactions($from, $to);
+ $total = $qtotal = $grandtotal = 0.0;
+ $stock_id = '';
+ while ($trans=db_fetch($res))
+ {
+ if ($stock_id != $trans['item_code'])
+ {
+ if ($stock_id != '')
+ {
+ $rep->Line($rep->row - 4);
+ $rep->NewLine(2);
+ $rep->TextCol(0, 3, _('Total'));
+ $rep->AmountCol(3, 4, $qtotal, $qdec);
+ $rep->AmountCol(6, 7, $total, $dec);
+ $rep->NewLine();
+ $total = $qtotal = 0;
+ }
+ $stock_id = $trans['item_code'];
+ }
+ $curr = get_supplier_currency($trans['supplier_id']);
+ $rate = get_exchange_rate_from_home_currency($curr, sql2date($trans['delivery_date']));
+ $trans['unit_price'] *= $rate;
+ $trans['act_price'] *= $rate;
+
+ $rep->NewLine();
+ $rep->TextCol(0, 1, $trans['item_code']);
+ $rep->TextCol(1, 2, $trans['description']);
+ $rep->TextCol(2, 3, $trans['order_no']);
+ $qdec = get_qty_dec($trans['item_code']);
+ $rep->AmountCol(3, 4, $trans['quantity_received'], $qdec);
+ $rep->AmountCol(4, 5, $trans['unit_price'], $dec);
+ $rep->AmountCol(5, 6, $trans['act_price'], $dec);
+ $amt = round2($trans['quantity_received'] * $trans['act_price'], $dec);
+ $rep->AmountCol(6, 7, $amt, $dec);
+ $total += $amt;
+ $qtotal += $trans['quantity_received'];
+ $grandtotal += $amt;
+ }
+ if ($stock_id != '')
+ {
+ $rep->Line($rep->row - 4);
+ $rep->NewLine(2);
+ $rep->TextCol(0, 3, _('Total'));
+ $rep->AmountCol(3, 4, $qtotal, $qdec);
+ $rep->AmountCol(6, 7, $total, $dec);
+ $rep->Line($rep->row - 4);
+ $rep->NewLine(2);
+ $rep->TextCol(0, 6, _('Grand Total'));
+ $rep->AmountCol(6, 7, $grandtotal, $dec);
+ }
+
+ $rep->Line($rep->row - 4);
+ $rep->NewLine();
+ $rep->End();
+}
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+$page_security = $_POST['PARAM_0'] == $_POST['PARAM_1'] ?
+ 'SA_MANUFTRANSVIEW' : 'SA_MANUFBULKREP';
+// ----------------------------------------------------------------
+// $ Revision: 2.0 $
+// Creator: Janusz Dobrowolski
+// date_: 2008-01-14
+// Title: Print Workorders
+// draft version!
+// ----------------------------------------------------------------
+$path_to_root="..";
+
+include_once($path_to_root . "/includes/session.inc");
+include_once($path_to_root . "/includes/date_functions.inc");
+include_once($path_to_root . "/includes/data_checks.inc");
+include_once($path_to_root . "/manufacturing/includes/manufacturing_db.inc");
+
+//----------------------------------------------------------------------------------------------------
+
+print_workorders();
+
+//----------------------------------------------------------------------------------------------------
+
+function print_workorders()
+{
+ global $path_to_root, $SysPrefs;
+
+ include_once($path_to_root . "/reporting/includes/pdf_report.inc");
+
+ $from = $_POST['PARAM_0'];
+ $to = $_POST['PARAM_1'];
+ $email = $_POST['PARAM_2'];
+ $comments = $_POST['PARAM_3'];
+
+ if ($from == null)
+ $from = 0;
+ if ($to == null)
+ $to = 0;
+ $dec = user_price_dec();
+
+ $fno = explode("-", $from);
+ $tno = explode("-", $to);
+
+ $cols = array(4, 60, 190, 255, 320, 385, 450, 515);
+
+ // $headers in doctext.inc
+ $aligns = array('left', 'left', 'left', 'left', 'right', 'right', 'right');
+
+ $params = array('comments' => $comments);
+
+ $cur = get_company_Pref('curr_default');
+
+ if ($email == 0)
+ {
+ $rep = new FrontReport(_('WORK ORDER'), "WorkOrderBulk", user_pagesize());
+ $rep->currency = $cur;
+ $rep->Font();
+ $rep->Info($params, $cols, null, $aligns);
+ }
+
+ for ($i = $fno[0]; $i <= $tno[0]; $i++)
+ {
+ $myrow = get_work_order($i);
+ if ($myrow === false)
+ continue;
+ $date_ = sql2date($myrow["date_"]);
+ if ($email == 1)
+ {
+ $rep = new FrontReport("", "", user_pagesize());
+ $rep->currency = $cur;
+ $rep->Font();
+ $rep->title = _('WORK ORDER');
+ $rep->filename = "WorkOrder" . $myrow['reference'] . ".pdf";
+ $rep->Info($params, $cols, null, $aligns);
+ }
+ else
+ $rep->title = _('WORK ORDER');
+ $rep->Header2($myrow, null, null, '', 26);
+
+ $result = get_wo_requirements($i);
+ $rep->TextCol(0, 5,_("Work Order Requirements"), -2);
+ $rep->NewLine(2);
+ $has_marked = false;
+ while ($myrow2=db_fetch($result))
+ {
+ $qoh = 0;
+ $show_qoh = true;
+ // if it's a non-stock item (eg. service) don't show qoh
+ if (!has_stock_holding($myrow2["mb_flag"]))
+ $show_qoh = false;
+
+ if ($show_qoh)
+ $qoh = get_qoh_on_date($myrow2["stock_id"], $myrow2["loc_code"], $date_);
+
+ if ($show_qoh && ($myrow2["units_req"] * $myrow["units_issued"] > $qoh) &&
+ !$SysPrefs->allow_negative_stock())
+ {
+ // oops, we don't have enough of one of the component items
+ $has_marked = true;
+ }
+ else
+ $has_marked = false;
+ if ($has_marked)
+ $str = $myrow2['stock_id']." ***";
+ else
+ $str = $myrow2['stock_id'];
+ $rep->TextCol(0, 1, $str, -2);
+ $rep->TextCol(1, 2, $myrow2['description'], -2);
+
+ $rep->TextCol(2, 3, $myrow2['location_name'], -2);
+ $rep->TextCol(3, 4, $myrow2['WorkCentreDescription'], -2);
+ $dec = get_qty_dec($myrow2["stock_id"]);
+
+ $rep->AmountCol(4, 5, $myrow2['units_req'], $dec, -2);
+ $rep->AmountCol(5, 6, $myrow2['units_req'] * $myrow['units_issued'], $dec, -2);
+ $rep->AmountCol(6, 7, $myrow2['units_issued'], $dec, -2);
+ $rep->NewLine(1);
+ if ($rep->row < $rep->bottomMargin + (15 * $rep->lineHeight))
+ $rep->Header2($myrow, null, null,'',26);
+ }
+ $rep->NewLine(1);
+ $rep->TextCol(0, 5," *** = "._("Insufficient stock"), -2);
+
+ $comments = get_comments(ST_WORKORDER, $i);
+ if ($comments && db_num_rows($comments))
+ {
+ $rep->NewLine();
+ while ($comment=db_fetch($comments))
+ $rep->TextColLines(0, 6, $comment['memo_'], -2);
+ }
+ }
+ if ($email == 0)
+ $rep->End();
+}
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+$page_security = 'SA_GLANALYTIC';
+// ----------------------------------------------------------------
+// $ Revision: 2.0 $
+// Creator: Joe Hunt
+// date_: 2005-05-19
+// Title: Audit Trail
+// ----------------------------------------------------------------
+$path_to_root="..";
+
+include_once($path_to_root . "/includes/session.inc");
+include_once($path_to_root . "/includes/date_functions.inc");
+include_once($path_to_root . "/includes/data_checks.inc");
+include_once($path_to_root . "/gl/includes/gl_db.inc");
+include_once($path_to_root . "/includes/ui/ui_view.inc");
+
+//----------------------------------------------------------------------------------------------------
+
+print_audit_trail();
+
+function getTransactions($from, $to, $type, $user)
+{
+ $fromdate = date2sql($from) . " 00:00:00";
+ $todate = date2sql($to). " 23:59.59";
+
+ $sql = "SELECT a.*,
+ SUM(IF(ISNULL(g.amount), NULL, IF(g.amount > 0, g.amount, 0))) AS amount,
+ u.user_id,
+ UNIX_TIMESTAMP(a.stamp) as unix_stamp
+ FROM ".TB_PREF."audit_trail AS a JOIN ".TB_PREF."users AS u
+ LEFT JOIN ".TB_PREF."gl_trans AS g ON (g.type_no=a.trans_no
+ AND g.type=a.type)
+ WHERE a.user = u.id ";
+ if ($type != -1)
+ $sql .= "AND a.type=$type ";
+ if ($user != -1)
+ $sql .= "AND a.user='$user' ";
+ $sql .= "AND a.stamp >= '$fromdate'
+ AND a.stamp <= '$todate'
+ GROUP BY a.trans_no,a.gl_seq,a.stamp
+ ORDER BY a.stamp,a.gl_seq";
+ return db_query($sql,"No transactions were returned");
+}
+//----------------------------------------------------------------------------------------------------
+
+function print_audit_trail()
+{
+ global $path_to_root, $systypes_array;
+
+ $from = $_POST['PARAM_0'];
+ $to = $_POST['PARAM_1'];
+ $systype = $_POST['PARAM_2'];
+ $user = $_POST['PARAM_3'];
+ $comments = $_POST['PARAM_4'];
+ $destination = $_POST['PARAM_5'];
+ if ($destination)
+ include_once($path_to_root . "/reporting/includes/excel_report.inc");
+ else
+ include_once($path_to_root . "/reporting/includes/pdf_report.inc");
+
+ $dec = user_price_dec();
+
+ $cols = array(0, 60, 120, 180, 240, 340, 400, 460, 520);
+
+ $headers = array(_('Date'), _('Time'), _('User'), _('Trans Date'),
+ _('Type'), _('#'), _('Action'), _('Amount'));
+
+ $aligns = array('left', 'left', 'left', 'left', 'left', 'left', 'left', 'right');
+
+ $usr = get_user($user);
+ $user_id = $usr['user_id'];
+ $params = array( 0 => $comments,
+ 1 => array('text' => _('Period'), 'from' => $from,'to' => $to),
+ 2 => array('text' => _('Type'), 'from' => ($systype != -1 ? $systypes_array[$systype] : _('All')), 'to' => ''),
+ 3 => array('text' => _('User'), 'from' => ($user != -1 ? $user_id : _('All')), 'to' => ''));
+
+ $rep = new FrontReport(_('Audit Trail'), "AuditTrail", user_pagesize());
+
+ $rep->Font();
+ $rep->Info($params, $cols, $headers, $aligns);
+ $rep->Header();
+
+ $trans = getTransactions($from, $to, $systype, $user);
+
+ while ($myrow=db_fetch($trans))
+ {
+ $rep->TextCol(0, 1, sql2date(date("Y-m-d", $myrow['unix_stamp'])));
+ if (user_date_format() == 0)
+ $rep->TextCol(1, 2, date("h:i:s a", $myrow['unix_stamp']));
+ else
+ $rep->TextCol(1, 2, date("H:i:s", $myrow['unix_stamp']));
+ $rep->TextCol(2, 3, $myrow['user_id']);
+ $rep->TextCol(3, 4, sql2date($myrow['gl_date']));
+ $rep->TextCol(4, 5, $systypes_array[$myrow['type']]);
+ $rep->TextCol(5, 6, $myrow['trans_no']);
+ if ($myrow['gl_seq'] == null)
+ $action = _('Changed');
+ else
+ $action = _('Closed');
+ $rep->TextCol(6, 7, $action);
+ if ($myrow['amount'] != null)
+ $rep->AmountCol(7, 8, $myrow['amount'], $dec);
+ $rep->NewLine(1, 2);
+ }
+ $rep->Line($rep->row + 4);
+ $rep->End();
+}
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+
+class fa2_2 {
+ var $version = '2.2'; // version installed
+ var $description;
+ var $sql = 'alter2.2.sql';
+ var $preconf = true;
+ var $beta = false; // upgrade from 2.1 or 2.2beta; set in pre_check
+
+ function fa2_2() {
+ global $security_groups;
+ $this->beta = !isset($security_groups);
+ $this->description = _('Upgrade from version 2.1/2.2beta to 2.2');
+ $this->preconf = fix_extensions();
+ }
+
+ //
+ // Install procedure. All additional changes
+ // not included in sql file should go here.
+ //
+ function install($pref, $force)
+ {
+ global $db, $systypes_array;
+
+ if (!$this->preconf)
+ return false;
+
+ // Until 2.2 sanitizing text input with db_escape was not
+ // consequent enough. To avoid comparision problems we have to
+ // fix this now.
+ sanitize_database($pref);
+
+ if ($this->beta) // nothing more to be done on upgrade from 2.2beta
+ return true;
+
+ // set item category dflt accounts to values from company GL setup
+ $prefs = get_company_prefs();
+ $sql = "UPDATE {$pref}stock_category SET "
+ ."dflt_sales_act = '" . $prefs['default_inv_sales_act'] . "',"
+ ."dflt_cogs_act = '". $prefs['default_cogs_act'] . "',"
+ ."dflt_inventory_act = '" . $prefs['default_inventory_act'] . "',"
+ ."dflt_adjustment_act = '" . $prefs['default_adj_act'] . "',"
+ ."dflt_assembly_act = '" . $prefs['default_assembly_act']."'";
+ if (db_query($sql)==false) {
+ display_error("Cannot update category default GL accounts"
+ .':<br>'. db_error_msg($db));
+ return false;
+ }
+ // add all references to refs table for easy searching via journal interface
+ foreach($systypes_array as $typeno => $typename) {
+ $info = get_systype_db_info($typeno);
+ if ($info == null || $info[3] == null) continue;
+ $tbl = str_replace(TB_PREF, $pref, $info[0]);
+ $sql = "SELECT DISTINCT {$info[2]} as id,{$info[3]} as ref FROM $tbl";
+ if ($info[1])
+ $sql .= " WHERE {$info[1]}=$typeno";
+ $result = db_query($sql);
+ if (db_num_rows($result)) {
+ while ($row = db_fetch($result)) {
+ $res2 = db_query("INSERT INTO {$pref}refs VALUES("
+ . $row['id'].",".$typeno.",'".$row['ref']."')");
+ if (!$res2) {
+ display_error(_("Cannot copy references from $tbl")
+ .':<br>'. db_error_msg($db));
+ return false;
+ }
+ }
+ }
+ }
+
+ if (!($ret = db_query("SELECT MAX(`order_no`) FROM `{$pref}sales_orders`")) ||
+ !db_num_rows($ret))
+ {
+ display_error(_('Cannot query max sales order number.'));
+ return false;
+ }
+ $row = db_fetch($ret);
+ $max_order = $row[0];
+ $next_ref = $max_order+1;
+ $sql = "UPDATE `{$pref}sys_types`
+ SET `type_no`='$max_order',`next_reference`='$next_ref'
+ WHERE `type_id`=30";
+ if(!db_query($sql))
+ {
+ display_error(_('Cannot store next sales order reference.'));
+ return false;
+ }
+ return convert_roles($pref);
+ }
+ //
+ // Checking before install
+ //
+ function pre_check($pref, $force)
+ {
+ global $security_groups;
+
+ if ($this->beta && !$force)
+ $this->sql = 'alter2.2rc.sql';
+ // return ok when security groups still defined (upgrade from 2.1)
+ // or usersonline not defined (upgrade from 2.2 beta)
+ return isset($security_groups) || (check_table($pref, 'usersonline')!=0);
+ }
+ //
+ // Test if patch was applied before.
+ //
+ function installed($pref) {
+ $n = 1; // number of patches to be installed
+ $patchcnt = 0;
+ if (!$this->beta) {
+ $n = 16;
+ if (check_table($pref, 'company', 'custom1_name')) $patchcnt++;
+ if (!check_table($pref, 'company', 'profit_loss_year_act')) $patchcnt++;
+ if (!check_table($pref, 'company', 'login_tout')) $patchcnt++;
+ if (!check_table($pref, 'stock_category', 'dflt_no_sale')) $patchcnt++;
+ if (!check_table($pref, 'users', 'sticky_doc_date')) $patchcnt++;
+ if (!check_table($pref, 'users', 'startup_tab')) $patchcnt++;
+ if (!check_table($pref, 'cust_branch', 'inactive')) $patchcnt++;
+ if (!check_table($pref, 'chart_class', 'ctype')) $patchcnt++;
+ if (!check_table($pref, 'audit_trail')) $patchcnt++;
+ if (!check_table($pref, 'currencies', 'auto_update')) $patchcnt++;
+ if (!check_table($pref, 'stock_master','no_sale')) $patchcnt++;
+ if (!check_table($pref, 'suppliers', 'supp_ref')) $patchcnt++;
+ if (!check_table($pref, 'users', 'role_id')) $patchcnt++;
+ if (!check_table($pref, 'sales_orders', 'reference')) $patchcnt++;
+ if (!check_table($pref, 'tags')) $patchcnt++;
+ }
+ if (!check_table($pref, 'useronline')) $patchcnt++;
+
+ $n -= $patchcnt;
+ return $n == 0 ? true : $patchcnt;
+ }
+};
+
+/*
+ Conversion of old security roles stored into $security_groups table
+*/
+function convert_roles($pref)
+{
+ global $security_groups, $security_headings, $security_areas, $path_to_root;
+ include_once($path_to_root."/includes/access_levels.inc");
+
+ $trans_sec = array(
+ 1 => array('SA_CHGPASSWD', 'SA_SETUPDISPLAY', 'SA_BANKTRANSVIEW',
+ 'SA_ITEMSTRANSVIEW','SA_SUPPTRANSVIEW', 'SA_SALESORDER',
+ 'SA_SALESALLOC', 'SA_SALESTRANSVIEW'),
+ 2 => array('SA_DIMTRANSVIEW', 'SA_STANDARDCOST', 'SA_ITEMSTRANSVIEW',
+ 'SA_ITEMSSTATVIEW', 'SA_SALESPRICE', 'SA_MANUFTRANSVIEW',
+ 'SA_WORKORDERANALYTIC', 'SA_WORKORDERCOST', 'SA_SUPPTRANSVIEW',
+ 'SA_SUPPLIERALLOC', 'SA_STEMPLATE', 'SA_SALESTRANSVIEW',
+ 'SA_SALESINVOICE', 'SA_SALESDELIVERY', 'SA_CUSTPAYMREP',
+ 'SA_CUSTBULKREP', 'SA_PRICEREP', 'SA_SALESBULKREP', 'SA_SALESMANREP',
+ 'SA_SALESBULKREP', 'SA_CUSTSTATREP', 'SA_SUPPLIERANALYTIC',
+ 'SA_SUPPPAYMREP', 'SA_SUPPBULKREP', 'SA_ITEMSVALREP', 'SA_ITEMSANALYTIC',
+ 'SA_BOMREP', 'SA_MANUFBULKREP', 'SA_DIMENSIONREP', 'SA_BANKREP', 'SA_GLREP',
+ 'SA_GLANALYTIC', 'SA_TAXREP', 'SA_SALESANALYTIC', 'SA_SALESQUOTE'),
+ 3 => array('SA_GLACCOUNTGROUP', 'SA_GLACCOUNTCLASS','SA_PAYMENT',
+ 'SA_DEPOSIT', 'SA_JOURNALENTRY', 'SA_INVENTORYMOVETYPE',
+ 'SA_LOCATIONTRANSFER', 'SA_INVENTORYADJUSTMENT', 'SA_WORKCENTRES',
+ 'SA_MANUFISSUE', 'SA_SUPPLIERALLOC', 'SA_CUSTOMER', 'SA_CRSTATUS',
+ 'SA_SALESMAN', 'SA_SALESAREA', 'SA_SALESALLOC', 'SA_SALESCREDITINV',
+ 'SA_SALESPAYMNT', 'SA_SALESCREDIT', 'SA_SALESGROUP', 'SA_SRECURRENT',
+ 'SA_TAXRATES', 'SA_ITEMTAXTYPE', 'SA_TAXGROUPS', 'SA_QUICKENTRY'),
+ 4 => array('SA_REORDER', 'SA_PURCHASEPRICING', 'SA_PURCHASEORDER'),
+ 5 => array('SA_VIEWPRINTTRANSACTION', 'SA_BANKTRANSFER', 'SA_SUPPLIER',
+ 'SA_SUPPLIERINVOICE', 'SA_SUPPLIERPAYMNT', 'SA_SUPPLIERCREDIT'),
+ 8 => array('SA_ATTACHDOCUMENT', 'SA_RECONCILE', 'SA_GLANALYTIC',
+ 'SA_TAXREP', 'SA_BANKTRANSVIEW', 'SA_GLTRANSVIEW'),
+ 9 => array('SA_FISCALYEARS', 'SA_CURRENCY', 'SA_EXCHANGERATE',
+ 'SA_BOM'),
+ 10 => array('SA_PAYTERMS', 'SA_GLSETUP', 'SA_SETUPCOMPANY',
+ 'SA_FORMSETUP', 'SA_DIMTRANSVIEW', 'SA_DIMENSION', 'SA_BANKACCOUNT',
+ 'SA_GLACCOUNT', 'SA_BUDGETENTRY', 'SA_MANUFRECEIVE',
+ 'SA_MANUFRELEASE', 'SA_WORKORDERENTRY', 'SA_MANUFTRANSVIEW',
+ 'SA_WORKORDERCOST'),
+ 11 => array('SA_ITEMCATEGORY', 'SA_ITEM', 'SA_UOM', 'SA_INVENTORYLOCATION',
+ 'SA_GRN', 'SA_FORITEMCODE', 'SA_SALESKIT'),
+ 14 => array('SA_SHIPPING', 'SA_VOIDTRANSACTION', 'SA_SALESTYPES'),
+ 15 => array('SA_PRINTERS', 'SA_PRINTPROFILE', 'SA_BACKUP', 'SA_USERS',
+ 'SA_POSSETUP'),
+ 20 => array('SA_CREATECOMPANY', 'SA_CREATELANGUAGE', 'SA_CREATEMODULES',
+ 'SA_SOFTWAREUPGRADE', 'SA_SECROLES', 'SA_DIMTAGS', 'SA_GLACCOUNTTAGS')
+ );
+ $new_ids = array();
+ foreach ($security_groups as $role_id => $areas) {
+ $area_set = array();
+ $sections = array();
+ foreach ($areas as $a) {
+ if (isset($trans_sec[$a]))
+ foreach ($trans_sec[$a] as $id) {
+ if ($security_areas[$id][0] != 0)
+// error_log('invalid area id: '.$a.':'.$id);
+ $area_set[] = $security_areas[$id][0];
+ $sections[$security_areas[$id][0]&~0xff] = 1;
+ }
+ }
+ $sections = array_keys($sections);
+ sort($sections); sort($area_set);
+ import_security_role($pref, $security_headings[$role_id], $sections, $area_set);
+ $new_ids[$role_id] = db_insert_id();
+ }
+ $result = get_users(true);
+ $users = array();
+ while($row = db_fetch($result)) { // complete old user ids and roles
+ $users[$row['role_id']][] = $row['id'];
+ }
+ foreach($users as $old_id => $uids)
+ foreach( $uids as $id) {
+ $sql = "UPDATE {$pref}users set role_id=".$new_ids[$old_id].
+ " WHERE id=$id";
+ $ret = db_query($sql, 'cannot update users roles');
+ if(!$ret) return false;
+ }
+ return true;
+}
+
+function import_security_role($pref, $name, $sections, $areas)
+{
+ $sql = "INSERT INTO {$pref}security_roles (role, description, sections, areas)
+ VALUES (".db_escape('FA 2.1 '.$name).",".db_escape($name).","
+ .db_escape(implode(';',$sections)).",".db_escape(implode(';',$areas)).")";
+
+ db_query($sql, "could not add new security role");
+}
+
+/*
+ Changes in extensions system.
+ This function is executed once on first Upgrade System display.
+*/
+function fix_extensions() {
+ global $path_to_root, $db_connections;
+
+ if (!file_exists($path_to_root.'/modules/installed_modules.php'))
+ return true; // already converted
+
+ if (!is_writable($path_to_root.'/modules/installed_modules.php')) {
+ display_error(_('Cannot upgrade extensions system: file /modules/installed_modules.php is not writeable'));
+ return false;
+ }
+
+ $exts = array();
+ include($path_to_root.'/installed_extensions.php');
+ foreach($installed_extensions as $ext) {
+ $ext['filename'] = $ext['app_file']; unset($ext['app_file']);
+ $ext['tab'] = $ext['name'];
+ $ext['name'] = access_string($ext['title'], true);
+ $ext['path'] = $ext['folder']; unset($ext['folder']);
+ $ext['type'] = 'module';
+ $ext['active'] = '1';
+ $exts[] = $ext;
+ }
+
+ include($path_to_root.'/modules/installed_modules.php');
+ foreach($installed_modules as $mod) {
+ $mod['title'] = $mod['name'];
+ $mod['name'] = access_string($mod['name'], true);
+ $mod['type'] = 'plugin';
+ $ext['active'] = '1';
+ $exts[] = $mod;
+ }
+ if (!write_extensions($exts))
+ return false;
+
+ $cnt = count($db_connections);
+ for ($i = 0; $i < $cnt; $i++)
+ write_extensions($exts, $i);
+
+ unlink($path_to_root.'/modules/installed_modules.php');
+ return true;
+}
+
+/*
+ Find and update all database records with special chars in text fields
+ to ensure all of them are changed to html entites.
+*/
+function sanitize_database($pref, $test = false) {
+
+ if ($test)
+ error_log('Sanitizing database ...');
+
+ $tsql = "SHOW TABLES LIKE '".($pref=='' ? '' : substr($pref,0,-1).'\\_')."%'";
+ $tresult = db_query($tsql, "Cannot select all tables with prefix '$pref'");
+ while($tbl = db_fetch($tresult)) {
+ $table = $tbl[0];
+ $csql = "SHOW COLUMNS FROM $table";
+ $cresult = db_query($csql, "Cannot select column names for table '$table'");
+ $textcols = $keys = array();
+ while($col = db_fetch($cresult)) {
+ if (strpos($col['Type'], 'char')!==false
+ || strpos($col['Type'], 'text')!==false)
+ $textcols[] = '`'.$col['Field'].'`';
+ if ($col['Key'] == 'PRI') {
+ $keys[] = '`'.$col['Field'].'`';
+ }
+ }
+
+ if ($test)
+ error_log("Table $table (".implode(',',$keys)."):(".implode(',',$textcols)."):");
+
+ if (!count($textcols)) continue;
+
+ // fetch all records containing special characters in text fields
+ $sql = "SELECT ".implode(',', array_unique(array_merge($keys,$textcols)))
+ ." FROM {$table} WHERE
+ CONCAT(".implode(',', $textcols).") REGEXP '[\\'\"><&]'";
+ $result = db_query($sql, "Cannot select all suspicious fields in $table");
+
+ // and fix them
+ while($rec= db_fetch($result)) {
+ $sql = "UPDATE {$table} SET ";
+ $val = $key = array();
+ foreach ($textcols as $f) {
+ $val[] = $f.'='.db_escape($rec[substr($f,1,-1)]);
+ }
+ $sql .= implode(',', $val). ' WHERE ';
+ foreach ($keys as $k) {
+ $key[] = $k.'=\''.$rec[substr($k,1,-1)].'\'';
+ }
+ $sql .= implode( ' AND ', $key);
+ if ($test)
+ error_log("\t(".implode(',',$val).") updated");
+ else
+ db_query($sql, 'cannot update record');
+ }
+ }
+ if ($test)
+ error_log('Sanitizing done.');
+}
+
+$install = new fa2_2;
+?>
\ No newline at end of file
--- /dev/null
+ALTER TABLE `0_company` DROP COLUMN `custom1_name`;
+ALTER TABLE `0_company` DROP COLUMN `custom2_name`;
+ALTER TABLE `0_company` DROP COLUMN `custom3_name`;
+ALTER TABLE `0_company` DROP COLUMN `custom1_value`;
+ALTER TABLE `0_company` DROP COLUMN `custom2_value`;
+ALTER TABLE `0_company` DROP COLUMN `custom3_value`;
+
+ALTER TABLE `0_company` ADD COLUMN `default_delivery_required` SMALLINT(6) NULL DEFAULT '1';
+ALTER TABLE `0_company` ADD COLUMN `version_id` VARCHAR(11) NOT NULL DEFAULT '';
+ALTER TABLE `0_company` DROP COLUMN `purch_exchange_diff_act`;
+ALTER TABLE `0_company` ADD COLUMN`profit_loss_year_act` VARCHAR(11) NOT NULL DEFAULT '' AFTER `exchange_diff_act`;
+ALTER TABLE `0_company` ADD COLUMN `time_zone` TINYINT(1) NOT NULL DEFAULT '0';
+ALTER TABLE `0_company` ADD COLUMN `add_pct` INT(5) NOT NULL DEFAULT '-1';
+ALTER TABLE `0_company` ADD COLUMN `round_to` INT(5) NOT NULL DEFAULT '1';
+ALTER TABLE `0_company` CHANGE `grn_act` `bank_charge_act` VARCHAR(11) NOT NULL DEFAULT '';
+#INSERT INTO `0_chart_master` VALUES ('9990', '', 'Profit and Loss this year', '52', '0');
+UPDATE `0_company` SET `profit_loss_year_act`='9990', `version_id`='2.2' WHERE `coy_code`=1;
+
+ALTER TABLE `0_stock_category` DROP COLUMN `stock_act`;
+ALTER TABLE `0_stock_category` DROP COLUMN `cogs_act`;
+ALTER TABLE `0_stock_category` DROP COLUMN `adj_gl_act`;
+ALTER TABLE `0_stock_category` DROP COLUMN `purch_price_var_act`;
+
+ALTER TABLE `0_stock_category` ADD COLUMN `dflt_tax_type` int(11) NOT NULL default '1';
+ALTER TABLE `0_stock_category` ADD COLUMN `dflt_units` varchar(20) NOT NULL default 'each';
+ALTER TABLE `0_stock_category` ADD COLUMN `dflt_mb_flag` char(1) NOT NULL default 'B';
+ALTER TABLE `0_stock_category` ADD COLUMN `dflt_sales_act` varchar(11) NOT NULL default '';
+ALTER TABLE `0_stock_category` ADD COLUMN `dflt_cogs_act` varchar(11) NOT NULL default '';
+ALTER TABLE `0_stock_category` ADD COLUMN `dflt_inventory_act` varchar(11) NOT NULL default '';
+ALTER TABLE `0_stock_category` ADD COLUMN `dflt_adjustment_act` varchar(11) NOT NULL default '';
+ALTER TABLE `0_stock_category` ADD COLUMN `dflt_assembly_act` varchar(11) NOT NULL default '';
+ALTER TABLE `0_stock_category` ADD COLUMN `dflt_dim1` int(11) default NULL;
+ALTER TABLE `0_stock_category` ADD COLUMN `dflt_dim2` int(11) default NULL;
+ALTER TABLE `0_stock_category` ADD COLUMN `dflt_no_sale` tinyint(1) NOT NULL default '0';
+
+ALTER TABLE `0_users` ADD COLUMN `sticky_doc_date` TINYINT(1) DEFAULT '0';
+ALTER TABLE `0_users` ADD COLUMN `startup_tab` VARCHAR(20) NOT NULL default 'orders' AFTER `sticky_doc_date`;
+
+ALTER TABLE `0_debtors_master` MODIFY COLUMN `name` varchar(100) NOT NULL default '';
+
+ALTER TABLE `0_cust_branch` ADD COLUMN `inactive` tinyint(1) NOT NULL default '0';
+
+ALTER TABLE `0_sys_types` DROP COLUMN `type_name`;
+
+ALTER TABLE `0_chart_class` CHANGE `balance_sheet` `ctype` TINYINT(1) NOT NULL DEFAULT '0';
+
+ALTER TABLE `0_chart_class` ADD COLUMN `inactive` tinyint(1) NOT NULL default '0';
+ALTER TABLE `0_chart_types` ADD COLUMN `inactive` tinyint(1) NOT NULL default '0';
+ALTER TABLE `0_movement_types` ADD COLUMN `inactive` tinyint(1) NOT NULL default '0';
+ALTER TABLE `0_item_tax_types` ADD COLUMN `inactive` tinyint(1) NOT NULL default '0';
+ALTER TABLE `0_tax_types` ADD COLUMN `inactive` tinyint(1) NOT NULL default '0';
+ALTER TABLE `0_tax_groups` ADD COLUMN `inactive` tinyint(1) NOT NULL default '0';
+
+ALTER TABLE `0_users` DROP PRIMARY KEY;
+ALTER TABLE `0_users` ADD `id` SMALLINT(6) AUTO_INCREMENT PRIMARY KEY FIRST;
+ALTER TABLE `0_users` ADD UNIQUE KEY (`user_id`);
+ALTER TABLE `0_users` ADD COLUMN `inactive` tinyint(1) NOT NULL default '0';
+
+DROP TABLE IF EXISTS `0_audit_trail`;
+# fiscal_year, gl_date, gl_seq - journal sequence data
+CREATE TABLE `0_audit_trail` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `type` smallint(6) unsigned NOT NULL default '0',
+ `trans_no` int(11) unsigned NOT NULL default '0',
+ `user` smallint(6) unsigned NOT NULL default '0',
+ `stamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
+ `description` varchar(60) default NULL,
+ `fiscal_year` int(11) NOT NULL,
+ `gl_date` date NOT NULL default '0000-00-00',
+ `gl_seq` int(11) unsigned default NULL,
+ PRIMARY KEY (`id`),
+ KEY (`fiscal_year`, `gl_seq`)
+) TYPE=InnoDB ;
+
+ALTER TABLE `0_stock_master` ADD COLUMN `no_sale` tinyint(1) NOT NULL default '0';
+ALTER TABLE `0_currencies` ADD COLUMN `auto_update` tinyint(1) NOT NULL default '1';
+
+ALTER TABLE `0_debtors_master` ADD COLUMN `debtor_ref` varchar(30) NOT NULL;
+UPDATE `0_debtors_master` SET `debtor_ref`=`name` WHERE 1;
+ALTER TABLE `0_suppliers` ADD COLUMN `supp_ref` varchar(30) NOT NULL;
+UPDATE `0_suppliers` SET `supp_ref`=`supp_name` WHERE 1;
+ALTER TABLE `0_cust_branch` ADD COLUMN `branch_ref` varchar(30) NOT NULL;
+UPDATE `0_cust_branch` SET `branch_ref`=`br_name` WHERE 1;
+
+DROP TABLE IF EXISTS `0_security_roles`;
+
+CREATE TABLE `0_security_roles` (
+ `id` int(11) NOT NULL auto_increment,
+ `role` varchar(30) NOT NULL,
+ `description` varchar(50) default NULL,
+ `sections` text,
+ `areas` text,
+ `inactive` tinyint(1) NOT NULL default '0',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `role` (`role`)
+) TYPE=MyISAM AUTO_INCREMENT=1;
+
+ALTER TABLE `0_company` ADD COLUMN `login_tout` SMALLINT(6) NOT NULL DEFAULT '600';
+ALTER TABLE `0_users` CHANGE COLUMN `full_access` `role_id` int(11) NOT NULL default '1';
+
+ALTER TABLE `0_sales_order_details` ADD COLUMN `trans_type` SMALLINT(6) NOT NULL DEFAULT '30' AFTER `order_no`;
+ALTER TABLE `0_sales_orders` CHANGE COLUMN `order_no` `order_no` int(11) NOT NULL;
+ALTER TABLE `0_sales_orders` ADD COLUMN `trans_type` SMALLINT(6) NOT NULL DEFAULT '30' AFTER `order_no`;
+ALTER TABLE `0_sales_orders` ADD COLUMN `reference` varchar(100) NOT NULL DEFAULT '' AFTER `branch_code`;
+ALTER TABLE `0_sales_orders` DROP PRIMARY KEY;
+ALTER TABLE `0_sales_orders` ADD PRIMARY KEY ( `trans_type` , `order_no` );
+UPDATE `0_sales_orders` SET `reference`=`order_no` WHERE 1;
+INSERT INTO `0_sys_types` (`type_id`, `type_no`, `next_reference`) VALUES (32, 0, '1');
+
+ALTER TABLE `0_bank_accounts` ADD COLUMN `dflt_curr_act` TINYINT(1) NOT NULL default '0' AFTER `bank_curr_code`;
+
+DROP TABLE IF EXISTS `0_tags`;
+
+CREATE TABLE `0_tags` (
+ `id` int(11) NOT NULL auto_increment,
+ `type` smallint(6) NOT NULL,
+ `name` varchar(30) NOT NULL,
+ `description` varchar(60) default NULL,
+ `inactive` tinyint(1) NOT NULL default '0',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY(`type`,`name`)
+) TYPE=MyISAM AUTO_INCREMENT=1;
+
+DROP TABLE IF EXISTS `0_tag_associations`;
+
+CREATE TABLE `0_tag_associations` (
+ `record_id` varchar(11) NOT NULL,
+ `tag_id` int(11) NOT NULL,
+ UNIQUE KEY(`record_id`,`tag_id`)
+) TYPE=MyISAM;
+
+DROP TABLE IF EXISTS `0_useronline` ;
+
+CREATE TABLE `0_useronline` (
+ `id` int(11) NOT NULL AUTO_INCREMENT ,
+ `timestamp` int(15) NOT NULL default '0',
+ `ip` varchar(40) NOT NULL default '',
+ `file` varchar(100) NOT NULL default '',
+ PRIMARY KEY `id` (`id`) ,
+ KEY (`timestamp`)
+) TYPE=MYISAM AUTO_INCREMENT=1;
+
+ALTER TABLE `0_suppliers` ADD COLUMN `phone2` varchar(30) NOT NULL default '' AFTER `phone`;
+ALTER TABLE `0_cust_branch` ADD COLUMN `phone2` varchar(30) NOT NULL default '' AFTER `phone`;
+ALTER TABLE `0_shippers` ADD COLUMN `phone2` varchar(30) NOT NULL default '' AFTER `phone`;
+ALTER TABLE `0_locations` ADD COLUMN `phone2` varchar(30) NOT NULL default '' AFTER `phone`;
+ALTER TABLE `0_debtors_master` ADD COLUMN `notes` tinytext NULL default '' AFTER `credit_limit`;
+ALTER TABLE `0_cust_branch` ADD COLUMN `notes` tinytext NULL default '' AFTER `group_no`;
--- /dev/null
+# Patch for upgrade from 2.2beta to 2.2RC/final
+
+ALTER TABLE `0_tag_associations` DROP COLUMN `id`;
+ALTER TABLE `0_tag_associations` ADD UNIQUE KEY(`record_id`,`tag_id`);
+
+DROP TABLE IF EXISTS `0_useronline` ;
+
+CREATE TABLE `0_useronline` (
+ `id` int(11) NOT NULL AUTO_INCREMENT ,
+ `timestamp` int(15) NOT NULL default '0',
+ `ip` varchar(40) NOT NULL default '',
+ `file` varchar(100) NOT NULL default '',
+ PRIMARY KEY `id` (`id`) ,
+ KEY (`timestamp`)
+) TYPE=MYISAM AUTO_INCREMENT=1;