0a2584d346a77ebd6f7dc3294959224d081e7f53
[fa-stable.git] / sql / alter2.4.php
1 <?php
2 /**********************************************************************
3     Copyright (C) FrontAccounting, LLC.
4         Released under the terms of the GNU General Public License, GPL, 
5         as published by the Free Software Foundation, either version 3 
6         of the License, or (at your option) any later version.
7     This program is distributed in the hope that it will be useful,
8     but WITHOUT ANY WARRANTY; without even the implied warranty of
9     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
10     See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ***********************************************************************/
12 class fa2_4 {
13         var $version = '2.4.0'; // version installed
14         var $description;
15         var $sql = 'alter2.4.sql';
16         var $preconf = true;
17         
18         function fa2_4() {
19                 $this->description = _('Upgrade from version 2.3 to 2.4');
20         }
21         
22         //
23         //      Install procedure. All additional changes 
24         //      not included in sql file should go here.
25         //
26         function install($company, $force=false) 
27         {
28                 global $db_version, $db_connections;
29
30                 $pref = $db_connections[$company]['tbpref'];
31
32                 if (get_company_pref('grn_clearing_act') === null) { // available form 2.3.1, can be not defined on pre-2.4 installations
33                         set_company_pref('grn_clearing_act', 'glsetup.purchase', 'varchar', 15, 0);
34                 }
35                 if (get_company_pref('default_receival_required') === null) { // new in 2.4 installations
36                         set_company_pref('default_receival_required', 'glsetup.purchase', 'smallint', 6, 10);
37                 }
38                 if (get_company_pref('default_quote_valid_days') === null) { // new in 2.3.23 installations
39                         set_company_pref('default_quote_valid_days', 'glsetup.sales', 'smallint', 6, 30);
40                 }
41                 if (get_company_pref('no_zero_lines_amount') === null) { // new in 2.4 installations
42                         set_company_pref('no_zero_lines_amount', 'glsetup.sales', 'tinyint', 1, '1');
43                         refresh_sys_prefs();
44                 }
45                 if (get_company_pref('show_po_item_codes') === null) { // new in 2.4 installations
46                         set_company_pref('show_po_item_codes', 'glsetup.purchase', 'tinyint', 1, '0');
47                         refresh_sys_prefs();
48                 }
49                 if (get_company_pref('accounts_alpha') === null) { // new in 2.4 installations
50                         set_company_pref('accounts_alpha', 'glsetup.general', 'tinyint', 1, '0');
51                         refresh_sys_prefs();
52                 }
53                 if (get_company_pref('loc_notification') === null) { // new in 2.4 installations
54                         set_company_pref('loc_notification', 'glsetup.inventory', 'tinyint', 1, '0');
55                         refresh_sys_prefs();
56                 }
57                 if (get_company_pref('print_invoice_no') === null) { // new in 2.4 installations
58                         set_company_pref('print_invoice_no', 'glsetup.sales', 'tinyint', 1, '0');
59                         refresh_sys_prefs();
60                 }
61                 if (get_company_pref('allow_negative_prices') === null) { // new in 2.4 installations
62                         set_company_pref('allow_negative_prices', 'glsetup.inventory', 'tinyint', 1, '1');
63                         refresh_sys_prefs();
64                 }
65                 if (get_company_pref('print_item_images_on_quote') === null) { // new in 2.4 installations
66                         set_company_pref('print_item_images_on_quote', 'glsetup.inventory', 'tinyint', 1, '0');
67                         refresh_sys_prefs();
68                 }
69                 if (get_company_pref('bcc_email') === null) { // available from 2.3.14, can be not defined on pre-2.4 installations
70                         set_company_pref('bcc_email', 'setup.company', 'varchar', 100, '');
71                         refresh_sys_prefs();
72                 }
73                 if (get_company_pref('alternative_tax_include_on_docs') === null) { // available from 2.3.14, can be not defined on pre-2.4 installations
74                         set_company_pref('alternative_tax_include_on_docs', 'setup.company', 'tinyint', 1, '0');
75                         refresh_sys_prefs();
76                 }
77                 if (get_company_pref('suppress_tax_rates') === null) { // available from 2.3.14, can be not defined on pre-2.4 installations
78                         set_company_pref('suppress_tax_rates', 'setup.company', 'tinyint', 1, '0');
79                         refresh_sys_prefs();
80                 }
81
82 $result = $this->update_workorders()  && $this->update_grn_rates() && $this->switch_database_to_utf($pref);
83
84                 if ($result)
85                         $result = $this->do_cleanup();
86
87                 return  update_company_prefs(array('version_id'=>$db_version));
88         }
89         //
90         //      Checking before install
91         //
92         function pre_check($pref, $force)
93         {
94                 return true;
95         }
96
97         //
98         // optional procedure done after upgrade fail, before backup is restored
99         //
100         function post_fail($pref)
101         {
102                 db_query("DROP TABLE IF EXISTS " . $pref . 'wo_costing');
103         }
104         //
105         //      Test if patch was applied before.
106         //
107         function installed($pref)
108         {
109                 $n = 2; // number of patches to be installed
110                 $patchcnt = 0;
111
112                 if (!check_table($pref, 'suppliers', 'tax_algorithm')) $patchcnt++;
113                 if (!check_table($pref, 'wo_costing')) $patchcnt++;
114                 return $n == $patchcnt ? true : ($patchcnt ? ($patchcnt.'/'. $n) : 0);
115         }
116
117         function update_workorders()
118         {
119                 global $db;
120
121                 $sql = "SELECT DISTINCT type, type_no, tran_date, person_id FROM ".TB_PREF."gl_trans WHERE `type`=".ST_WORKORDER
122                 ." AND person_type_id=1";
123                 $res = db_query($sql);
124                 if (!$res)
125                 {
126                         display_error("Cannot update work orders costs"
127                                 .':<br>'. db_error_msg($db));
128                         return false;
129                 }
130                 while ($row = db_fetch($res))
131                 {
132                         $journal_id = get_next_trans_no(ST_JOURNAL);
133
134                         $sql1 = "UPDATE ".TB_PREF."gl_trans SET `type`=".ST_JOURNAL.", type_no={$journal_id},
135                                 person_type_id=NULL, person_id=0
136                                 WHERE `type`=".ST_WORKORDER." AND type_no={$row['type_no']} AND tran_date='{$row['tran_date']}'
137                                 AND person_id='{$row['person_id']}'";
138                         if (!db_query($sql1)) return false;
139                         
140                         $sql2 = "INSERT INTO ".TB_PREF."wo_costing (workorder_id, cost_type, trans_no) 
141                                 VALUES ({$row['type_no']}, {$row['person_id']}, {$journal_id})";
142                         if (!db_query($sql2)) return false;
143                 }
144                 return true;
145         }
146
147 /*
148         In previous versions FA ignored encoding settings on database/tables, so it depended on server settings,
149         but data stored is encoded in user language encoding. Now we switch to utf8 internal database encoding, while
150         user encoding can be selected independently.
151
152         To perform safe FA database switch to utf-8 encoding we have to first ensure that all text/char columns 
153         have properly set encoding (the same as its content), so the algorithm performed on every table is as follows:
154         . set default table encoding for the table to currently used on client side;
155         . for all text/char column:
156          - suppress autorecoding by change of the type to related binary/blob type
157          - change column to utf8 encodding and selected collation.
158         . change default table encoding to utf8
159 */
160         function switch_database_to_utf($pref, $test = false) {
161
162                 global $installed_languages, $dflt_lang;
163
164                 $old_encoding = 'latin1'; // default client encoding
165
166                  // site default encoding is presumed as encoding for all databases!
167                 $lang = array_search_value($dflt_lang, $installed_languages, 'code');
168                 $new_encoding = get_mysql_encoding_name(strtoupper($lang['encoding']));
169         //      get_usec();
170                 if ($test)
171                         error_log('Switching database to utf8 encoding from '.$old_encoding);
172                 $collation = get_mysql_collation();
173                 $tsql = "SHOW TABLES LIKE '".($pref=='' ? '' : substr($pref, 0, -1).'\\_')."%'";
174                 $tresult = db_query($tsql, "Cannot select all tables with prefix '$pref'");
175                 while($tbl = db_fetch($tresult)) {
176                         $table = $tbl[0];
177                 // if ($table != '1_chart_master') continue; _vd($table); get_usec(); // fast debug on single table
178
179                         db_query("ALTER TABLE `$table` CONVERT TO CHARACTER SET $old_encoding"); // convert encoding on utf-8 tables
180
181                         // set proper default table encoding for current user language (used on binary->text conversion)
182                         db_query("ALTER TABLE `$table` CHARSET $new_encoding");
183                         $csql = "SHOW COLUMNS FROM $table";
184                         $cresult = db_query($csql, "Cannot select column names for table '$table'");
185                         $convert = false;
186
187                         $to_binary = $to_default = $to_utf = array();
188                         while($col = db_fetch($cresult)) {
189
190                                 $bintype = strtr($col['Type'], array('varchar' => 'varbinary', 'char'=>'varbinary', 'text'=>'blob', 'tinytext'=>'tinyblob'));
191
192                                 if ($bintype != $col['Type'])
193                                 { // this is char/text column, so change encoding to proper encoding
194                                         if ($test)
195                                                 error_log($table.'.'.$col['Field']);
196
197                                         $null = $col['Null'] === 'YES' ? ' NULL ' : ' NOT NULL ';
198                                         $default = $col['Null'] !== 'YES' && isset($col['Default']) ? ' DEFAULT '.db_escape($col['Default']) : '';
199
200                                         // to avoid column width multiplication x3 we old->binary->ui->utf column type change instead of column CONVERT
201
202                                         $to_binary[] = "CHANGE `".$col['Field']."` `".$col['Field']."` ".$bintype;
203                                         $to_default[] = "CHANGE `".$col['Field']."` `".$col['Field']."` ".$col['Type'].$null.$default;
204                                         $to_utf[] = "MODIFY COLUMN `".$col['Field']."` ".$col['Type']." COLLATE ".$collation.$null.$default;
205                                         $convert = true;
206                                 }
207                         }
208                         if(count($to_binary))
209                         {
210                                 $sql = "ALTER TABLE `$table` ".implode(',',$to_binary);
211                                 db_query($sql);
212                                 $sql = "ALTER TABLE `$table` ".implode(',',$to_default);
213                                 db_query($sql);
214                                 $sql = "ALTER TABLE `$table` ".implode(',',$to_utf);
215                                 db_query($sql);
216                         }
217                         db_query("ALTER TABLE `$table` COLLATE $collation");
218                 }
219                 db_query("ALTER DATABASE COLLATE $collation");
220                 if ($test)
221                         error_log('Convertion to utf8 done.');
222
223                 return true;
224         }
225
226         function update_grn_rates()
227         {
228                 $sql = "SELECT grn.id, grn.delivery_date, supp.curr_code 
229                         FROM ".TB_PREF."grn_batch grn, ".TB_PREF."suppliers supp
230                         WHERE supp.supplier_id=grn.supplier_id AND supp.curr_code!='".get_company_pref('curr_default')."'";
231                 $result = db_query($sql);
232
233                 if (!$result)
234                         return false;
235
236                 $sql = "UPDATE ".TB_PREF."grn_batch SET rate=%s WHERE id=%d";
237                 while ($grn = db_fetch($result))
238                         db_query(sprintf($sql, get_exchange_rate_from_home_currency($grn['curr_code'], sql2date($grn['delivery_date'])), $grn['id']));
239
240                 return true;
241         }
242
243         function do_cleanup()
244         {
245                 $dropcol = array(
246                                 'tax_group_items' => array('rate'),
247                                 'budget_trans' => array('type', 'type_no', 'person_id', 'person_type_id', 'memo_'),
248                 );
249
250                 foreach($dropcol as $table => $columns)
251                         foreach($columns as $col) {
252                                 if (db_query("ALTER TABLE `".TB_PREF."{$table}` DROP `$col`") == false) {
253                                         display_error("Cannot drop {$table}.{$col} column:<br>".db_error_msg($db));
254                                         return false;
255                                 }
256                         }
257         }
258 }
259
260 $install = new fa2_4;