Updated upgraded procedures, application version and gettext templates.
[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
13 class fa2_4 extends fa_patch {
14         var $previous = '2.3rc';                // applicable database version
15         var $version = '2.4.1'; // version installed
16         var $description;
17         var $sql = 'alter2.4.sql';
18         var $preconf = true;
19         
20         function fa2_4() {
21                 parent::fa_patch();
22                 $this->description = _('Upgrade from version 2.3 to 2.4');
23         }
24         
25     /*
26             Shows parameters to be selected before upgrade (if any)
27         */
28     function show_params($comp)
29         {
30           display_note(_('Set optimal parameters and start upgrade:'));
31           start_table(TABLESTYLE);
32           start_row();
33                 collations_list_row(_('Text collation optimization:'), 'collation', substr($_SESSION['language']->code, 0, 2));
34           end_row();
35           end_table();
36           br();
37     }
38
39         /*
40             Fetches selected upgrade parameters.
41     */
42         function prepare()
43     {
44                 $this->collation = get_mysql_collation(get_post('collation'));
45                 return true;
46         }
47
48         //
49         //      Install procedure. All additional changes 
50         //      not included in sql file should go here.
51         //
52         function install($company, $force=false)
53         {
54                 global $db_version, $db_connections;
55
56                 $pref = $db_connections[$company]['tbpref'];
57
58                 if (get_company_pref('grn_clearing_act') === null) { // available form 2.3.1, can be not defined on pre-2.4 installations
59                         set_company_pref('grn_clearing_act', 'glsetup.purchase', 'varchar', 15, 0);
60                 }
61                 if (get_company_pref('default_quote_valid_days') === null) { // new in 2.3.23 installations
62                         set_company_pref('default_quote_valid_days', 'glsetup.sales', 'smallint', 6, 30);
63                 }
64                 if (get_company_pref('bcc_email') === null) { // available from 2.3.14, can be not defined on pre-2.4 installations
65                         set_company_pref('bcc_email', 'setup.company', 'varchar', 100, '');
66                 }
67                 if (get_company_pref('alternative_tax_include_on_docs') === null) { // available from 2.3.14, can be not defined on pre-2.4 installations
68                         set_company_pref('alternative_tax_include_on_docs', 'setup.company', 'tinyint', 1, '0');
69                 }
70                 if (get_company_pref('suppress_tax_rates') === null) { // available from 2.3.14, can be not defined on pre-2.4 installations
71                         set_company_pref('suppress_tax_rates', 'setup.company', 'tinyint', 1, '0');
72                 }
73
74                 $result = $this->update_workorders()  && $this->update_grn_rates() && $this->switch_database_to_utf($pref);
75
76                 if ($result)
77                         $result = $this->do_cleanup();
78
79                 return $result;
80         }
81
82         //
83         // optional procedure done after upgrade fail, before backup is restored
84         //
85         function post_fail($company)
86         {
87                 $pref = $this->companies[$company]['tbpref'];
88                 db_query("DROP TABLE IF EXISTS " . $pref . 'wo_costing');
89                 db_query("DROP TABLE IF EXISTS " . $pref . 'stock_fa_class');
90         }
91
92         function update_workorders()
93         {
94                 global $db;
95
96                 $sql = "SELECT DISTINCT type, type_no, tran_date, person_id FROM ".TB_PREF."gl_trans WHERE `type`=".ST_WORKORDER
97                 ." AND person_type_id=1";
98                 $res = db_query($sql);
99                 if (!$res)
100                         return $this->log_error(sprintf(_("Cannot update work orders costs:\n%s"), db_error_msg($db)));
101
102                 while ($row = db_fetch($res))
103                 {
104                         $journal_id = get_next_trans_no(ST_JOURNAL);
105
106                         $sql1 = "UPDATE ".TB_PREF."gl_trans SET `type`=".ST_JOURNAL.", type_no={$journal_id},
107                                 person_type_id=NULL, person_id=0
108                                 WHERE `type`=".ST_WORKORDER." AND type_no={$row['type_no']} AND tran_date='{$row['tran_date']}'
109                                 AND person_id='{$row['person_id']}'";
110                         if (!db_query($sql1)) return false;
111
112                         $sql2 = "INSERT INTO ".TB_PREF."wo_costing (workorder_id, cost_type, trans_no) 
113                                 VALUES ({$row['type_no']}, {$row['person_id']}, {$journal_id})";
114                         if (!db_query($sql2)) return false;
115                 }
116                 return true;
117         }
118
119 /*
120         In previous versions FA ignored encoding settings on database/tables, so it depended on server settings,
121         but data stored is encoded in user language encoding. Now we switch to utf8 internal database encoding, while
122         user encoding can be selected independently.
123
124         To perform safe FA database switch to utf-8 encoding we have to first ensure that all text/char columns 
125         have properly set encoding (the same as its content), so the algorithm performed on every table is as follows:
126         . set default table encoding for the table to currently used on client side;
127         . for all text/char column:
128          - suppress autorecoding by change of the type to related binary/blob type
129          - change column to utf8 encodding and selected collation.
130         . change default table encoding to utf8 and selected collation
131 */
132         function switch_database_to_utf($pref, $dbg = false) {
133
134                 global $installed_languages, $dflt_lang;
135
136                 $old_encoding = 'latin1'; // default client encoding
137
138                  // site default encoding is presumed as encoding for all databases!
139                 $lang = array_search_value($dflt_lang, $installed_languages, 'code');
140                 $new_encoding = get_mysql_encoding_name(strtoupper($lang['encoding']));
141
142                 $this->log_error(sprintf('Switching database to utf8 encoding from %s', $old_encoding), 'Info');
143                 $collation = $this->collation;
144                 $tsql = "SHOW TABLES LIKE '".($pref=='' ? '' : substr($pref, 0, -1).'\\_')."%'";
145                 $tresult = db_query($tsql, "Cannot select all tables with prefix '$pref'");
146                 while($tbl = db_fetch($tresult)) {
147                         $table = $tbl[0];
148
149                         db_query("ALTER TABLE `$table` CONVERT TO CHARACTER SET $old_encoding"); // convert encoding on utf-8 tables
150
151                         // set proper default table encoding for current user language (used on binary->text conversion)
152                         db_query("ALTER TABLE `$table` CHARSET $new_encoding");
153                         $csql = "SHOW COLUMNS FROM $table";
154                         $cresult = db_query($csql, "Cannot select column names for table '$table'");
155                         $convert = false;
156
157                         $to_binary = $to_default = $to_utf = array();
158                         while($col = db_fetch($cresult)) {
159
160                                 $bintype = strtr($col['Type'], array('varchar' => 'varbinary', 'char'=>'varbinary', 'text'=>'blob', 'tinytext'=>'tinyblob'));
161
162                                 if ($bintype != $col['Type'])
163                                 { // this is char/text column, so change encoding to proper encoding
164                                         if ($dbg)
165                                                 $this->log_error(sprintf('%s switched to uft8.', $table.'.'.$col['Field']), 'Debug');
166
167                                         $null = $col['Null'] === 'YES' ? ' NULL ' : ' NOT NULL ';
168                                         $default = $col['Null'] !== 'YES' && isset($col['Default']) ? ' DEFAULT '.db_escape($col['Default']) : '';
169
170                                         // to avoid column width multiplication x3 we old->binary->ui->utf column type change instead of column CONVERT
171
172                                         $to_binary[] = "CHANGE `".$col['Field']."` `".$col['Field']."` ".$bintype;
173                                         $to_default[] = "CHANGE `".$col['Field']."` `".$col['Field']."` ".$col['Type'].$null.$default;
174                                         $to_utf[] = "MODIFY COLUMN `".$col['Field']."` ".$col['Type']." COLLATE ".$collation.$null.$default;
175                                         $convert = true;
176                                 }
177                         }
178                         if(count($to_binary))
179                         {
180                                 $sql = "ALTER TABLE `$table` ".implode(',',$to_binary);
181                                 db_query($sql);
182                                 $sql = "ALTER TABLE `$table` ".implode(',',$to_default);
183                                 db_query($sql);
184                                 $sql = "ALTER TABLE `$table` ".implode(',',$to_utf);
185                                 db_query($sql);
186                         }
187                         db_query("ALTER TABLE `$table` COLLATE $collation");
188                 }
189                 db_query("ALTER DATABASE COLLATE $collation");
190                 $this->log_error(_('Convertion to utf8 done.'), 'Info');
191
192                 return true;
193         }
194
195         function update_grn_rates()
196         {
197                 $sql = "SELECT grn.id, grn.delivery_date, supp.curr_code 
198                         FROM ".TB_PREF."grn_batch grn, ".TB_PREF."suppliers supp
199                         WHERE supp.supplier_id=grn.supplier_id AND supp.curr_code!='".get_company_pref('curr_default')."'";
200                 $result = db_query($sql);
201
202                 if (!$result)
203                         return false;
204
205                 $sql = "UPDATE ".TB_PREF."grn_batch SET rate=%s WHERE id=%d";
206                 while ($grn = db_fetch($result))
207                         db_query(sprintf($sql, get_exchange_rate_from_home_currency($grn['curr_code'], sql2date($grn['delivery_date'])), $grn['id']));
208
209                 return true;
210         }
211
212         function do_cleanup()
213         {
214                 global $db;
215
216                 //remove obsolete and temporary columns.
217                 // this have to be done here as db_import rearranges alter query order
218                 $dropcol = array(
219                                 'tax_groups' => array('tax_shipping'),
220                                 'tax_group_items' => array('rate'),
221                                 'budget_trans' => array('type', 'type_no', 'person_id', 'person_type_id', 'memo_'),
222                                 'cust_branch' => array('contact_name', 'disable_trans'),
223                                 'stock_moves' => array('discount_percent', 'visible', 'person_id'),
224                 );
225
226                 foreach($dropcol as $table => $columns)
227                         foreach($columns as $col) {
228                                 if (db_query("ALTER TABLE `".TB_PREF."{$table}` DROP `$col`") == false) {
229                                         return $this->log_error(sprintf(_("Cannot drop column in %s table: %s"), $table, db_error_msg($db)));
230                                 }
231                         }
232                 return true;
233   }
234 }
235
236 $install = new fa2_4;