From: Janusz Dobrowolski Date: Thu, 19 Nov 2009 16:03:05 +0000 (+0000) Subject: New/obsolete files update on 2.2 X-Git-Tag: 2.3-final~1122 X-Git-Url: https://delta.frontaccounting.com/gitweb/?a=commitdiff_plain;ds=sidebyside;h=74eabb5769f01203484f13b9736c8a56011b48f4;p=fa-stable.git New/obsolete files update on 2.2 --- diff --git a/access/timeout.php b/access/timeout.php new file mode 100644 index 00000000..c91dbc08 --- /dev/null +++ b/access/timeout.php @@ -0,0 +1,32 @@ +. +***********************************************************************/ +/* + 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 ""; +} +?> diff --git a/admin/db/security_db.inc b/admin/db/security_db.inc new file mode 100644 index 00000000..4af9fde6 --- /dev/null +++ b/admin/db/security_db.inc @@ -0,0 +1,67 @@ +. +***********************************************************************/ +//-------------------------------------------------------------------------------------------------- + +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 diff --git a/admin/db/tags_db.inc b/admin/db/tags_db.inc new file mode 100644 index 00000000..6b6aec4d --- /dev/null +++ b/admin/db/tags_db.inc @@ -0,0 +1,193 @@ +. +***********************************************************************/ + +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 diff --git a/admin/security_roles.php b/admin/security_roles.php new file mode 100644 index 00000000..bce6661f --- /dev/null +++ b/admin/security_roles.php @@ -0,0 +1,257 @@ +. +***********************************************************************/ +$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 "
"; + +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(); + +?> diff --git a/admin/tags.php b/admin/tags.php new file mode 100644 index 00000000..f87d98d6 --- /dev/null +++ b/admin/tags.php @@ -0,0 +1,179 @@ +. +***********************************************************************/ +$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(); + +?> diff --git a/config.default.php b/config.default.php new file mode 100644 index 00000000..0acd7b83 --- /dev/null +++ b/config.default.php @@ -0,0 +1,214 @@ +. +***********************************************************************/ + //-------------------------------------------------- + + // 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 diff --git a/config.php b/config.php deleted file mode 100644 index 7ab4f10f..00000000 --- a/config.php +++ /dev/null @@ -1,210 +0,0 @@ -. -***********************************************************************/ - //-------------------------------------------------- - - // 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 diff --git a/config_db.php b/config_db.php deleted file mode 100644 index 1c06397b..00000000 --- a/config_db.php +++ /dev/null @@ -1,36 +0,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 diff --git a/doc/2.2_Beta.txt b/doc/2.2_Beta.txt new file mode 100644 index 00000000..00f5d8a3 --- /dev/null +++ b/doc/2.2_Beta.txt @@ -0,0 +1,64 @@ +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. + diff --git a/doc/access_levels.txt b/doc/access_levels.txt new file mode 100644 index 00000000..4d647fcf --- /dev/null +++ b/doc/access_levels.txt @@ -0,0 +1,126 @@ + 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: + + + +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. + diff --git a/doc/calculate_price.txt b/doc/calculate_price.txt new file mode 100644 index 00000000..321185c6 --- /dev/null +++ b/doc/calculate_price.txt @@ -0,0 +1,58 @@ +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. + diff --git a/doc/sales_quotations.txt b/doc/sales_quotations.txt new file mode 100644 index 00000000..47f6da65 --- /dev/null +++ b/doc/sales_quotations.txt @@ -0,0 +1,21 @@ +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. diff --git a/gl/inquiry/journal_inquiry.php b/gl/inquiry/journal_inquiry.php new file mode 100644 index 00000000..f2aee15b --- /dev/null +++ b/gl/inquiry/journal_inquiry.php @@ -0,0 +1,180 @@ +. +***********************************************************************/ + +$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(); + +?> diff --git a/includes/access_levels.inc b/includes/access_levels.inc new file mode 100644 index 00000000..9c502deb --- /dev/null +++ b/includes/access_levels.inc @@ -0,0 +1,306 @@ +. +***********************************************************************/ +/* + 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 diff --git a/includes/db/audit_trail_db.inc b/includes/db/audit_trail_db.inc new file mode 100644 index 00000000..f9efe9a0 --- /dev/null +++ b/includes/db/audit_trail_db.inc @@ -0,0 +1,140 @@ +. +***********************************************************************/ + +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); +} + +?> diff --git a/includes/reserved.inc b/includes/reserved.inc deleted file mode 100644 index 5cc1fcdd..00000000 --- a/includes/reserved.inc +++ /dev/null @@ -1,58 +0,0 @@ -. -***********************************************************************/ -// 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 diff --git a/installed_extensions.php b/installed_extensions.php deleted file mode 100644 index 00225612..00000000 --- a/installed_extensions.php +++ /dev/null @@ -1,22 +0,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 diff --git a/js/payalloc.js b/js/payalloc.js new file mode 100644 index 00000000..7bdd9914 --- /dev/null +++ b/js/payalloc.js @@ -0,0 +1,64 @@ +/********************************************************************** + 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 . +***********************************************************************/ +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); diff --git a/lang/installed_languages.inc b/lang/installed_languages.inc deleted file mode 100644 index 158bab00..00000000 --- a/lang/installed_languages.inc +++ /dev/null @@ -1,19 +0,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 diff --git a/modules/installed_modules.php b/modules/installed_modules.php deleted file mode 100644 index bc13fe98..00000000 --- a/modules/installed_modules.php +++ /dev/null @@ -1,9 +0,0 @@ - \ No newline at end of file diff --git a/reporting/rep111.php b/reporting/rep111.php new file mode 100644 index 00000000..a16a1d7f --- /dev/null +++ b/reporting/rep111.php @@ -0,0 +1,160 @@ +. +***********************************************************************/ +$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 diff --git a/reporting/rep305.php b/reporting/rep305.php new file mode 100644 index 00000000..b752c6ef --- /dev/null +++ b/reporting/rep305.php @@ -0,0 +1,139 @@ +. +***********************************************************************/ +$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 diff --git a/reporting/rep409.php b/reporting/rep409.php new file mode 100644 index 00000000..bf6bb3d4 --- /dev/null +++ b/reporting/rep409.php @@ -0,0 +1,146 @@ +. +***********************************************************************/ +$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 diff --git a/reporting/rep710.php b/reporting/rep710.php new file mode 100644 index 00000000..befed437 --- /dev/null +++ b/reporting/rep710.php @@ -0,0 +1,119 @@ +. +***********************************************************************/ +$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 diff --git a/sql/alter2.2.php b/sql/alter2.2.php new file mode 100644 index 00000000..c5345233 --- /dev/null +++ b/sql/alter2.2.php @@ -0,0 +1,340 @@ +. +***********************************************************************/ + +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" + .':
'. 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") + .':
'. 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 diff --git a/sql/alter2.2.sql b/sql/alter2.2.sql new file mode 100644 index 00000000..a08cc397 --- /dev/null +++ b/sql/alter2.2.sql @@ -0,0 +1,148 @@ +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`; diff --git a/sql/alter2.2rc.sql b/sql/alter2.2rc.sql new file mode 100644 index 00000000..aff4c0a7 --- /dev/null +++ b/sql/alter2.2rc.sql @@ -0,0 +1,15 @@ +# 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; diff --git a/themes/aqua/images/escape.png b/themes/aqua/images/escape.png new file mode 100644 index 00000000..4d84554d Binary files /dev/null and b/themes/aqua/images/escape.png differ diff --git a/themes/cool/images/escape.png b/themes/cool/images/escape.png new file mode 100644 index 00000000..4d84554d Binary files /dev/null and b/themes/cool/images/escape.png differ