.
***********************************************************************/
class fa2_3 {
var $version = '2.3'; // version installed
var $description;
var $sql = 'alter2.3.sql';
var $preconf = true;
var $beta = false; // upgrade from 2.2 or 2.3beta;
function fa2_3() {
$this->description = _('Upgrade from version 2.2 to 2.3');
}
//
// Install procedure. All additional changes
// not included in sql file should go here.
//
function install($pref, $force)
{
global $db_version, $dflt_lang;
if (!$this->preconf)
return false;
if (!$this->beta) {
// all specials below are already done on 2.3beta
$sql = "SELECT debtor_no, payment_terms FROM {$pref}debtors_master";
$result = db_query($sql);
if (!$result) {
display_error("Cannot read customers"
.':
'. db_error_msg($db));
return false;
}
// update all sales orders and transactions with customer std payment terms
while($cust = db_fetch($result)) {
$sql = "UPDATE {$pref}debtor_trans SET "
."payment_terms = '" .$cust['payment_terms']
."' WHERE debtor_no='".$cust['debtor_no']."'";
if (db_query($sql)==false) {
display_error("Cannot update cust trans payment"
.':
'. db_error_msg($db));
return false;
}
$sql = "UPDATE {$pref}sales_orders SET "
."payment_terms = '" .$cust['payment_terms']
."' WHERE debtor_no='".$cust['debtor_no']."'";
if (db_query($sql)==false) {
display_error("Cannot update sales order payment"
.':
'. db_error_msg($db));
return false;
}
}
if (!$this->update_totals($pref)) {
display_error("Cannot update order totals");
return false;
}
if (!$this->update_line_relations($pref)) {
display_error("Cannot update sales document links");
return false;
}
//remove obsolete and temporary columns.
// this have to be done here as db_import rearranges alter query order
$dropcol = array(
'crm_persons' => array('tmp_id','tmp_class'),
'debtors_master' => array('email'),
'cust_branch' => array('phone', 'phone2', 'fax', 'email'),
'suppliers' => array('phone', 'phone2', 'fax', 'email'),
'debtor_trans' => array('trans_link')
);
foreach($dropcol as $table => $columns)
foreach($columns as $col) {
if (db_query("ALTER TABLE `{$pref}{$table}` DROP `$col`")==false) {
display_error("Cannot drop {$table}.{$col} column:
".db_error_msg($db));
return false;
}
}
// remove old preferences table after upgrade script has been executed
$sql = "DROP TABLE IF EXISTS `{$pref}company`";
if (!db_query($sql))
return false;
}
$this->update_lang_cfg();
return update_company_prefs(array('version_id'=>$db_version), $pref);
}
//
// Checking before install
//
function pre_check($pref, $force)
{
if ($this->beta && !$force)
$this->sql = 'alter2.3rc.sql';
return true;
}
//
// Test if patch was applied before.
//
function installed($pref) {
$this->beta = !check_table($pref, 'suppliers', 'tax_included');
$this->preconf = $this->fix_extensions();
$n = 1; // number of patches to be installed
$patchcnt = 0;
if (!$this->beta) {
$n += 3;
if (!check_table($pref, 'comments', 'type', array('Key'=>'MUL'))) $patchcnt++;
if (!check_table($pref, 'sys_prefs')) $patchcnt++;
if (!check_table($pref, 'sales_orders', 'payment_terms')) $patchcnt++;
}
if (!check_table($pref, 'purch_orders', 'tax_included')) $patchcnt++;
return $n == $patchcnt ? true : ($patchcnt ? ($patchcnt.'/'. $n) : 0);
}
//=========================================================================================
// 2.3 specific update functions
//
/*
Update order totals
*/
function update_totals($pref)
{
global $path_to_root;
include_once("$path_to_root/sales/includes/cart_class.inc");
include_once("$path_to_root/purchasing/includes/po_class.inc");
$cart = new cart(ST_SALESORDER);
$sql = "SELECT order_no FROM {$pref}sales_orders";
$orders = db_query($sql);
if (!$orders)
return false;
while ($order_no = db_fetch($orders)) {
read_sales_order($order_no[0], $cart, ST_SALESORDER);
$result = db_query("UPDATE {$pref}sales_orders SET total=".$cart->get_trans_total());
unset($cart->line_items);
}
unset($cart);
$cart = new purch_order();
$sql = "SELECT order_no FROM {$pref}purch_orders";
$orders = db_query($sql);
if (!$orders)
return false;
while ($order_no = db_fetch($orders)) {
read_po($order_no[0], $cart);
$result = db_query("UPDATE {$pref}purch_orders SET total=".$cart->get_trans_total());
unset($cart->line_items);
}
return true;
}
//------------------------------------------------------------------------------
// Retreive parent document number(s) for given transaction
//
function get_parent_trans_2_2($trans_type, $trans_no) {
$sql = 'SELECT trans_link FROM
'.TB_PREF.'debtor_trans WHERE trans_no='.db_escape($trans_no)
.' AND type='.db_escape($trans_type).' AND trans_link!=0';
$result = db_query($sql, 'Parent document numbers cannot be retrieved');
if (db_num_rows($result)) {
$link = db_fetch($result);
return array($link['trans_link']);
}
if ($trans_type!=ST_SALESINVOICE) return 0; // this is credit note with no parent invoice
// invoice: find batch invoice parent trans.
$sql = 'SELECT trans_no FROM
'.TB_PREF.'debtor_trans WHERE
(trans_link='.db_escape($trans_no).' AND type='. get_parent_type($trans_type) .')';
$result = db_query($sql, 'Delivery links cannot be retrieved');
$delivery = array();
if(db_num_rows($result)>0) {
while($link = db_fetch($result)) {
$delivery[] = $link['trans_no'];
}
}
return count($delivery) ? $delivery : 0;
}
/*
Reorganizing document relations. Due to the design issue in pre 2.3 db structure
there can be sales documents with lines not properly linked to parents. This rare
cases will be described in error log.
*/
function update_line_relations($pref)
{
global $path_to_root, $systypes_array;
require_once("$path_to_root/includes/sysnames.inc");
$sql = "SELECT d.type, trans_no, order_ FROM {$pref}debtor_trans d
LEFT JOIN {$pref}voided v ON d.type=v.type AND d.trans_no=v.id
WHERE ISNULL(v.type) AND
(d.type=".ST_CUSTDELIVERY
." OR d.type=".ST_SALESINVOICE
." OR d.type=".ST_CUSTCREDIT.")";
$result = db_query($sql);
if (!$result)
return false;
while ($trans = db_fetch($result)) {
$type = $trans['type'];
$trans_no = $trans['trans_no'];
$invalid = 0;
$msg ='';
$lines = get_customer_trans_details($type, $trans_no);
$n = db_num_rows($lines);
if ($type==ST_CUSTDELIVERY)
$src_lines = get_sales_order_details($trans['order_'], ST_SALESORDER);
else
$src_lines = get_customer_trans_details(get_parent_type($type),
$this->get_parent_trans_2_2($type, $trans_no));
$src_n = db_num_rows($src_lines);
if (($type == ST_CUSTCREDIT) && ($src_n == 0))
continue; // free credit note has no src lines
$max = $type == ST_CUSTDELIVERY ? $n : max($src_n, $n);
for($i = 0, $j=0; $i < $max; $i++) {
if (!($doc_line = @db_fetch($lines)))
break;
if(!($src_line = @db_fetch($src_lines)))
break;
if ($type == ST_CUSTDELIVERY)
$src_line['stock_id'] = $src_line['stk_code']; // SO details has another field name
if ($src_line['stock_id'] == $doc_line['stock_id']
&& ($src_line['quantity'] >= $doc_line['quantity'])) {
$sql = "UPDATE {$pref}debtor_trans_details SET src_id = {$src_line['id']}
WHERE id = {$doc_line['id']}";
if (!db_query($sql))
return false;
$j++;
}
}
if ($j != $n) {
error_log("Line level relations error for ".$systypes_array[$type]." #$trans_no.");
}
}
return true;
}
function fix_extensions()
{
global $path_to_root, $next_extension_id, $installed_languages;
$lang_chd = false;
foreach($installed_languages as $i => $lang) {
if (!isset($lang['path'])) {
$code = $lang['code'];
$installed_languages[$i]['path'] = 'lang/'.$code;
$installed_languages[$i]['package'] = $code;
$lang_chd = true;
}
}
if ($lang_chd)
write_lang();
$installed_extensions= get_company_extensions();
if (!isset($next_extension_id))
$next_extension_id = 1;
$new_exts = array();
foreach($installed_extensions as $i => $ext)
{
if (isset($ext['title'])) // old type entry
{
if ($ext['type'] == 'module') {
$new['type'] = 'extension';
$new['tabs'][] = array(
'url' => $ext['filename'],
'access' => isset($ext['access']) ? $ext['access'] : 'SA_OPEN',
'tab_id' => $ext['tab'],
'title' => $ext['title']
);
$new['path'] = $ext['path'];
}
else // plugin
{
$new['type'] = 'extension';
$new['tabs'] = array();
$new['path'] = 'modules/'.$ext['path'];
$new['entries'][] = array(
'url' => $ext['filename'],
'access' => isset($ext['access']) ? $ext['access'] : 'SA_OPEN',
'tab_id' => $ext['tab'],
'title' => $ext['title']
);
}
if (isset($ext['acc_file']))
$new['acc_file'] = $ext['acc_file'];
$new['name'] = $ext['name']; // albo access_string(title)
$new['package'] = $new['package'] = '';
$new['active'] = 1;
$new_exts[$i] = $new;
}
}
// Add non-standard themes
$path = $path_to_root.'/themes/';
$themes = array();
$themedir = opendir($path);
while (false !== ($fname = readdir($themedir)))
{
if ($fname!='.' && $fname!='..' && $fname!='CVS' && is_dir($path.$fname)
&& !in_array($fname, array('aqua', 'cool', 'default')))
{
foreach($installed_extensions as $ext)
if ($ext['path'] == 'themes/'.$fname) // skip if theme is already listed
continue 2;
$new_exts[$next_extension_id++] = array(
'name' => 'Theme '. ucwords($fname),
'package' => $fname,
'type' => 'theme',
'active' => true,
'path' => 'themes/'.$fname
);
}
}
closedir($themedir);
if (count($new_exts)) {
return update_extensions($new_exts);
} else
return true;
}
function update_lang_cfg()
{
global $dflt_lang, $installed_languages;
foreach($installed_languages as $n => $lang) {
if ($lang['code'] == 'en_GB') {
$installed_languages[$n] = 'C';
if ($dflt_lang == 'en_GB')
$dflt_lang = 'C';
write_lang();
}
}
}
}
$install = new fa2_3;
?>