1<?php 2/* Copyright (C) 2012 Regis Houssin <regis.houssin@inodbox.com> 3 * Copyright (C) 2013-2015 Laurent Destailleur <eldy@users.sourceforge.net> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <https://www.gnu.org/licenses/>. 17 */ 18 19/** 20 * \file htdocs/product/admin/product_tools.php 21 * \ingroup product 22 * \brief Setup page of product module 23 */ 24 25// TODO We must add a confirmation on button because this will make a mass change 26// FIXME Should also change table product_price for price levels 27 28require '../../main.inc.php'; 29require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; 30require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; 31require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; 32require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php'; 33 34// Load translation files required by the page 35$langs->loadLangs(array('admin', 'products')); 36 37// Security check 38if (!$user->admin) accessforbidden(); 39 40$action = GETPOST('action', 'aZ09'); 41$oldvatrate = GETPOST('oldvatrate', 'alpha'); 42$newvatrate = GETPOST('newvatrate', 'alpha'); 43//$price_base_type=GETPOST('price_base_type'); 44 45 46 47/* 48 * Actions 49 */ 50 51if ($action == 'convert') 52{ 53 $error = 0; 54 55 if ($oldvatrate == $newvatrate) 56 { 57 $langs->load("errors"); 58 setEventMessages($langs->trans("ErrorNewValueCantMatchOldValue"), null, 'errors'); 59 $error++; 60 } 61 62 if (!$error) 63 { 64 $country_id = $mysoc->country_id; // TODO Allow to choose country into form 65 66 $nbrecordsmodified = 0; 67 68 $db->begin(); 69 70 // Clean vat code old 71 $vat_src_code_old = ''; 72 if (preg_match('/\((.*)\)/', $oldvatrate, $reg)) 73 { 74 $vat_src_code_old = $reg[1]; 75 $oldvatrateclean = preg_replace('/\s*\(.*\)/', '', $oldvatrate); // Remove code into vatrate. 76 } else $oldvatrateclean = $oldvatrate; 77 78 // Clean vat code new 79 $vat_src_code_new = ''; 80 if (preg_match('/\((.*)\)/', $newvatrate, $reg)) 81 { 82 $vat_src_code_new = $reg[1]; 83 $newvatrateclean = preg_replace('/\s*\(.*\)/', '', $newvatrate); // Remove code into vatrate. 84 } else $newvatrateclean = $newvatrate; 85 86 // If country to edit is my country, so we change customer prices 87 if ($country_id == $mysoc->country_id) 88 { 89 $sql = 'SELECT rowid'; 90 $sql .= ' FROM '.MAIN_DB_PREFIX.'product'; 91 $sql .= ' WHERE entity IN ('.getEntity('product').')'; 92 $sql .= " AND tva_tx = '".$db->escape($oldvatrateclean)."'"; 93 if ($vat_src_code_old) $sql .= " AND default_vat_code = '".$db->escape($vat_src_code_old)."'"; 94 else " AND default_vat_code = IS NULL"; 95 96 $resql = $db->query($sql); 97 if ($resql) 98 { 99 $num = $db->num_rows($resql); 100 101 $i = 0; 102 while ($i < $num) 103 { 104 $obj = $db->fetch_object($resql); 105 106 $objectstatic = new Product($db); // Object init must be into loop to avoid to get value of previous step 107 $ret = $objectstatic->fetch($obj->rowid); 108 if ($ret > 0) 109 { 110 $ret = 0; $retm = 0; $updatelevel1 = false; 111 112 // Update multiprice 113 $listofmulti = array_reverse($objectstatic->multiprices, true); // To finish with level 1 114 foreach ($listofmulti as $level => $multiprices) 115 { 116 $price_base_type = $objectstatic->multiprices_base_type[$level]; // Get price_base_type of product/service to keep the same for update 117 if (empty($price_base_type)) continue; // Discard not defined price levels 118 119 if ($price_base_type == 'TTC') 120 { 121 $newprice = price2num($objectstatic->multiprices_ttc[$level], 'MU'); // Second param must be MU (we want a unit price so 'MU'. If unit price was on 4 decimal, we must keep 4 decimals) 122 $newminprice = $objectstatic->multiprices_min_ttc[$level]; 123 } else { 124 $newprice = price2num($objectstatic->multiprices[$level], 'MU'); // Second param must be MU (we want a unit price so 'MU'. If unit price was on 4 decimal, we must keep 4 decimals) 125 $newminprice = $objectstatic->multiprices_min[$level]; 126 } 127 if ($newminprice > $newprice) $newminprice = $newprice; 128 129 $newvat = str_replace('*', '', $newvatrate); 130 $localtaxes_type = getLocalTaxesFromRate($newvat, 0, $mysoc, $mysoc); 131 $newnpr = $objectstatic->multiprices_recuperableonly[$level]; 132 $newdefaultvatcode = $vat_src_code_new; 133 $newlevel = $level; 134 135 //print "$objectstatic->id $newprice, $price_base_type, $newvat, $newminprice, $newlevel, $newnpr<br>\n"; 136 $retm = $objectstatic->updatePrice($newprice, $price_base_type, $user, $newvatrateclean, $newminprice, $newlevel, $newnpr, 0, 0, $localtaxes_type, $newdefaultvatcode); 137 if ($retm < 0) 138 { 139 $error++; 140 break; 141 } 142 143 if ($newlevel == 1) $updatelevel1 = true; 144 } 145 146 // Update single price 147 $price_base_type = $objectstatic->price_base_type; // Get price_base_type of product/service to keep the same for update 148 if ($price_base_type == 'TTC') 149 { 150 $newprice = price2num($objectstatic->price_ttc, 'MU'); // Second param must be MU (we want a unit price so 'MU'. If unit price was on 4 decimal, we must keep 4 decimals) 151 $newminprice = $objectstatic->price_min_ttc; 152 } else { 153 $newprice = price2num($objectstatic->price, 'MU'); // Second param must be MU (we want a unit price so 'MU'. If unit price was on 4 decimal, we must keep 4 decimals) 154 $newminprice = $objectstatic->price_min; 155 } 156 if ($newminprice > $newprice) $newminprice = $newprice; 157 $newvat = str_replace('*', '', $newvatrate); 158 $localtaxes_type = getLocalTaxesFromRate($newvat, 0, $mysoc, $mysoc); 159 $newnpr = $objectstatic->recuperableonly; 160 $newdefaultvatcode = $vat_src_code_new; 161 $newlevel = 0; 162 if (!empty($price_base_type) && !$updatelevel1) 163 { 164 //print "$objectstatic->id $newprice, $price_base_type, $newvat, $newminprice, $newlevel, $newnpr<br>\n"; 165 $ret = $objectstatic->updatePrice($newprice, $price_base_type, $user, $newvatrateclean, $newminprice, $newlevel, $newnpr, 0, 0, $localtaxes_type, $newdefaultvatcode); 166 } 167 168 if ($ret < 0 || $retm < 0) $error++; 169 else $nbrecordsmodified++; 170 } 171 unset($objectstatic); 172 173 $i++; 174 } 175 } else dol_print_error($db); 176 } 177 178 $fourn = new Fournisseur($db); 179 180 // Change supplier prices 181 $sql = 'SELECT pfp.rowid, pfp.fk_soc, pfp.price as price, pfp.quantity as qty, pfp.fk_availability, pfp.ref_fourn'; 182 $sql .= ' FROM '.MAIN_DB_PREFIX.'product_fournisseur_price as pfp, '.MAIN_DB_PREFIX.'societe as s'; 183 $sql .= ' WHERE pfp.fk_soc = s.rowid AND pfp.entity IN ('.getEntity('product').')'; 184 $sql .= " AND tva_tx = '".$db->escape($oldvatrate)."'"; 185 if ($vat_src_code_old) $sql .= " AND default_vat_code = '".$db->escape($vat_src_code_old)."'"; 186 else " AND default_vat_code = IS NULL"; 187 $sql .= " AND s.fk_pays = ".((int) $country_id); 188 //print $sql; 189 $resql = $db->query($sql); 190 if ($resql) 191 { 192 $num = $db->num_rows($resql); 193 194 $i = 0; 195 while ($i < $num) 196 { 197 $obj = $db->fetch_object($resql); 198 199 $objectstatic2 = new ProductFournisseur($db); // Object init must be into loop to avoid to get value of previous step 200 $ret = $objectstatic2->fetch_product_fournisseur_price($obj->rowid); 201 if ($ret > 0) 202 { 203 $ret = 0; $retm = 0; $updatelevel1 = false; 204 205 $price_base_type = 'HT'; 206 //$price_base_type = $objectstatic2->price_base_type; // Get price_base_type of product/service to keep the same for update 207 //if ($price_base_type == 'TTC') 208 //{ 209 // $newprice=price2num($objectstatic2->price_ttc,'MU'); // Second param must be MU (we want a unit price so 'MU'. If unit price was on 4 decimal, we must keep 4 decimals) 210 // $newminprice=$objectstatic2->price_min_ttc; 211 //} 212 //else 213 //{ 214 $newprice = price2num($obj->price, 'MU'); // Second param must be MU (we want a unit price so 'MU'. If unit price was on 4 decimal, we must keep 4 decimals) 215 //$newminprice=$objectstatic2->fourn_price_min; 216 //} 217 //if ($newminprice > $newprice) $newminprice=$newprice; 218 $newvat = str_replace('*', '', $newvatrate); 219 $localtaxes_type = getLocalTaxesFromRate($newvat, 0, $mysoc, $mysoc); 220 //$newnpr=$objectstatic2->recuperableonly; 221 $newnpr = 0; 222 $newdefaultvatcode = $vat_src_code_new; 223 224 $newpercent = $objectstatic2->fourn_remise_percent; 225 $newdeliverydelay = $objectstatic2->delivery_time_days; 226 $newsupplierreputation = $objectstatic2->supplier_reputation; 227 228 $newlevel = 0; 229 if (!empty($price_base_type) && !$updatelevel1) 230 { 231 //print "$objectstatic2->id $newprice, $price_base_type, $newvat, $newminprice, $newlevel, $newnpr<br>\n"; 232 $fourn->id = $obj->fk_soc; 233 $ret = $objectstatic2->update_buyprice($obj->qty, $newprice, $user, $price_base_type, $fourn, $obj->fk_availability, $obj->ref_fourn, $newvat, '', $newpercent, 0, $newnpr, $newdeliverydelay, $newsupplierreputation, $localtaxes_type, $newdefaultvatcode); 234 } 235 236 if ($ret < 0 || $retm < 0) $error++; 237 else $nbrecordsmodified++; 238 } 239 unset($objectstatic2); 240 241 $i++; 242 } 243 } else dol_print_error($db); 244 245 if (!$error) 246 { 247 $db->commit(); 248 } else { 249 $db->rollback(); 250 } 251 252 // Output result 253 if (!$error) 254 { 255 if ($nbrecordsmodified > 0) setEventMessages($langs->trans("RecordsModified", $nbrecordsmodified), null, 'mesgs'); 256 else setEventMessages($langs->trans("NoRecordFound"), null, 'warnings'); 257 } else { 258 setEventMessages($langs->trans("Error"), null, 'errors'); 259 } 260 } 261} 262 263/* 264 * View 265 */ 266 267$form = new Form($db); 268 269$title = $langs->trans('ProductVatMassChange'); 270 271llxHeader('', $title); 272 273print load_fiche_titre($title, '', 'title_setup'); 274 275print $langs->trans("ProductVatMassChangeDesc").'<br><br>'; 276 277if (empty($mysoc->country_code)) 278{ 279 $langs->load("errors"); 280 $warnpicto = img_error($langs->trans("WarningMandatorySetupNotComplete")); 281 print '<br><a href="'.DOL_URL_ROOT.'/admin/company.php?mainmenu=home">'.$warnpicto.' '.$langs->trans("WarningMandatorySetupNotComplete").'</a>'; 282} else { 283 print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">'; 284 print '<input type="hidden" name="token" value="'.newToken().'" />'; 285 print '<input type="hidden" name="action" value="convert" />'; 286 287 print '<table class="noborder centpercent">'; 288 print '<tr class="liste_titre">'; 289 print '<td>'.$langs->trans("Parameters").'</td>'."\n"; 290 print '<td class="right" width="60">'.$langs->trans("Value").'</td>'."\n"; 291 print '</tr>'."\n"; 292 293 294 print '<tr class="oddeven">'."\n"; 295 print '<td>'.$langs->trans("OldVATRates").'</td>'."\n"; 296 print '<td width="60" class="right">'."\n"; 297 print $form->load_tva('oldvatrate', $oldvatrate, $mysoc, null, 0, 0, '', false, 1); 298 print '</td>'."\n"; 299 print '</tr>'."\n"; 300 301 302 print '<tr class="oddeven">'."\n"; 303 print '<td>'.$langs->trans("NewVATRates").'</td>'."\n"; 304 print '<td width="60" class="right">'."\n"; 305 print $form->load_tva('newvatrate', $newvatrate, $mysoc, null, 0, 0, '', false, 1); 306 print '</td>'."\n"; 307 print '</tr>'."\n"; 308 309 /* 310 311 print '<tr class="oddeven">'."\n"; 312 print '<td>'.$langs->trans("PriceBaseTypeToChange").'</td>'."\n"; 313 print '<td width="60" class="right">'."\n"; 314 print $form->selectPriceBaseType($price_base_type); 315 print '</td>'."\n"; 316 print '</tr>'."\n"; 317 */ 318 319 print '</table>'; 320 321 print '<br>'; 322 323 // Buttons for actions 324 325 print '<div class="center">'; 326 print '<input type="submit" id="convert_vatrate" name="convert_vatrate" value="'.$langs->trans("MassConvert").'" class="button" />'; 327 print '</div>'; 328 329 print '</form>'; 330} 331 332// End of page 333llxFooter(); 334$db->close(); 335