dolibarr  19.0.0-dev
product_tools.php
Go to the documentation of this file.
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 
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 
28 // Load Dolibarr environment
29 require '../../main.inc.php';
30 require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
31 require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
32 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
34 
35 // Load translation files required by the page
36 $langs->loadLangs(array('admin', 'products'));
37 
38 // Security check
39 if (!$user->admin) {
41 }
42 
43 $action = GETPOST('action', 'aZ09');
44 $oldvatrate = GETPOST('oldvatrate', 'alpha');
45 $newvatrate = GETPOST('newvatrate', 'alpha');
46 //$price_base_type=GETPOST('price_base_type');
47 
48 
49 
50 /*
51  * Actions
52  */
53 
54 if ($action == 'convert') {
55  $error = 0;
56 
57  if ($oldvatrate == $newvatrate) {
58  $langs->load("errors");
59  setEventMessages($langs->trans("ErrorNewValueCantMatchOldValue"), null, 'errors');
60  $error++;
61  }
62 
63  if (!$error) {
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  $vat_src_code_old = $reg[1];
74  $oldvatrateclean = preg_replace('/\s*\‍(.*\‍)/', '', $oldvatrate); // Remove code into vatrate.
75  } else {
76  $oldvatrateclean = $oldvatrate;
77  }
78 
79  // Clean vat code new
80  $vat_src_code_new = '';
81  if (preg_match('/\‍((.*)\‍)/', $newvatrate, $reg)) {
82  $vat_src_code_new = $reg[1];
83  $newvatrateclean = preg_replace('/\s*\‍(.*\‍)/', '', $newvatrate); // Remove code into vatrate.
84  } else {
85  $newvatrateclean = $newvatrate;
86  }
87 
88  // If country to edit is my country, so we change customer prices
89  if ($country_id == $mysoc->country_id) {
90  $sql = 'SELECT rowid';
91  $sql .= ' FROM '.MAIN_DB_PREFIX.'product';
92  $sql .= ' WHERE entity IN ('.getEntity('product').')';
93  $sql .= " AND tva_tx = '".$db->escape($oldvatrateclean)."'";
94  if ($vat_src_code_old) {
95  $sql .= " AND default_vat_code = '".$db->escape($vat_src_code_old)."'";
96  } else {
97  " AND default_vat_code = IS NULL";
98  }
99 
100  $resql = $db->query($sql);
101  if ($resql) {
102  $num = $db->num_rows($resql);
103 
104  $i = 0;
105  while ($i < $num) {
106  $obj = $db->fetch_object($resql);
107 
108  $objectstatic = new Product($db); // Object init must be into loop to avoid to get value of previous step
109  $ret = $objectstatic->fetch($obj->rowid);
110  if ($ret > 0) {
111  $ret = 0; $retm = 0; $updatelevel1 = false;
112 
113  // Update multiprice
114  $listofmulti = array_reverse($objectstatic->multiprices, true); // To finish with level 1
115  foreach ($listofmulti as $level => $multiprices) {
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)) {
118  continue; // Discard not defined price levels
119  }
120 
121  if ($price_base_type == 'TTC') {
122  $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)
123  $newminprice = $objectstatic->multiprices_min_ttc[$level];
124  } else {
125  $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)
126  $newminprice = $objectstatic->multiprices_min[$level];
127  }
128  if ($newminprice > $newprice) {
129  $newminprice = $newprice;
130  }
131 
132  $newvat = str_replace('*', '', $newvatrate);
133  $localtaxes_type = getLocalTaxesFromRate($newvat, 0, $mysoc, $mysoc);
134  $newnpr = $objectstatic->multiprices_recuperableonly[$level];
135  $newdefaultvatcode = $vat_src_code_new;
136  $newlevel = $level;
137 
138  //print "$objectstatic->id $newprice, $price_base_type, $newvat, $newminprice, $newlevel, $newnpr<br>\n";
139  $retm = $objectstatic->updatePrice($newprice, $price_base_type, $user, $newvatrateclean, $newminprice, $newlevel, $newnpr, 0, 0, $localtaxes_type, $newdefaultvatcode);
140  if ($retm < 0) {
141  $error++;
142  break;
143  }
144 
145  if ($newlevel == 1) {
146  $updatelevel1 = true;
147  }
148  }
149 
150  // Update single price
151  $price_base_type = $objectstatic->price_base_type; // Get price_base_type of product/service to keep the same for update
152  if ($price_base_type == 'TTC') {
153  $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)
154  $newminprice = $objectstatic->price_min_ttc;
155  } else {
156  $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)
157  $newminprice = $objectstatic->price_min;
158  }
159  if ($newminprice > $newprice) {
160  $newminprice = $newprice;
161  }
162  $newvat = str_replace('*', '', $newvatrate);
163  $localtaxes_type = getLocalTaxesFromRate($newvat, 0, $mysoc, $mysoc);
164  $newnpr = $objectstatic->recuperableonly;
165  $newdefaultvatcode = $vat_src_code_new;
166  $newlevel = 0;
167  if (!empty($price_base_type) && !$updatelevel1) {
168  //print "$objectstatic->id $newprice, $price_base_type, $newvat, $newminprice, $newlevel, $newnpr<br>\n";
169  $ret = $objectstatic->updatePrice($newprice, $price_base_type, $user, $newvatrateclean, $newminprice, $newlevel, $newnpr, 0, 0, $localtaxes_type, $newdefaultvatcode);
170  }
171 
172  if ($ret < 0 || $retm < 0) {
173  $error++;
174  } else {
175  $nbrecordsmodified++;
176  }
177  }
178  unset($objectstatic);
179 
180  $i++;
181  }
182  } else {
183  dol_print_error($db);
184  }
185  }
186 
187  $fourn = new Fournisseur($db);
188 
189  // Change supplier prices
190  $sql = 'SELECT pfp.rowid, pfp.fk_soc, pfp.price as price, pfp.quantity as qty, pfp.fk_availability, pfp.ref_fourn';
191  $sql .= ' FROM '.MAIN_DB_PREFIX.'product_fournisseur_price as pfp, '.MAIN_DB_PREFIX.'societe as s';
192  $sql .= ' WHERE pfp.fk_soc = s.rowid AND pfp.entity IN ('.getEntity('product').')';
193  $sql .= " AND tva_tx = '".$db->escape($oldvatrate)."'";
194  if ($vat_src_code_old) {
195  $sql .= " AND default_vat_code = '".$db->escape($vat_src_code_old)."'";
196  } else {
197  " AND default_vat_code = IS NULL";
198  }
199  $sql .= " AND s.fk_pays = ".((int) $country_id);
200  //print $sql;
201  $resql = $db->query($sql);
202  if ($resql) {
203  $num = $db->num_rows($resql);
204 
205  $i = 0;
206  while ($i < $num) {
207  $obj = $db->fetch_object($resql);
208 
209  $objectstatic2 = new ProductFournisseur($db); // Object init must be into loop to avoid to get value of previous step
210  $ret = $objectstatic2->fetch_product_fournisseur_price($obj->rowid);
211  if ($ret > 0) {
212  $ret = 0; $retm = 0; $updatelevel1 = false;
213 
214  $price_base_type = 'HT';
215  //$price_base_type = $objectstatic2->price_base_type; // Get price_base_type of product/service to keep the same for update
216  //if ($price_base_type == 'TTC')
217  //{
218  // $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)
219  // $newminprice=$objectstatic2->price_min_ttc;
220  //}
221  //else
222  //{
223  $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)
224  //$newminprice=$objectstatic2->fourn_price_min;
225  //}
226  //if ($newminprice > $newprice) $newminprice=$newprice;
227  $newvat = str_replace('*', '', $newvatrate);
228  $localtaxes_type = getLocalTaxesFromRate($newvat, 0, $mysoc, $mysoc);
229  //$newnpr=$objectstatic2->recuperableonly;
230  $newnpr = 0;
231  $newdefaultvatcode = $vat_src_code_new;
232 
233  $newpercent = $objectstatic2->fourn_remise_percent;
234  $newdeliverydelay = $objectstatic2->delivery_time_days;
235  $newsupplierreputation = $objectstatic2->supplier_reputation;
236 
237  $newlevel = 0;
238  if (!empty($price_base_type) && !$updatelevel1) {
239  //print "$objectstatic2->id $newprice, $price_base_type, $newvat, $newminprice, $newlevel, $newnpr<br>\n";
240  $fourn->id = $obj->fk_soc;
241  $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);
242  }
243 
244  if ($ret < 0 || $retm < 0) {
245  $error++;
246  } else {
247  $nbrecordsmodified++;
248  }
249  }
250  unset($objectstatic2);
251 
252  $i++;
253  }
254  } else {
255  dol_print_error($db);
256  }
257 
258  if (!$error) {
259  $db->commit();
260  } else {
261  $db->rollback();
262  }
263 
264  // Output result
265  if (!$error) {
266  if ($nbrecordsmodified > 0) {
267  setEventMessages($langs->trans("RecordsModified", $nbrecordsmodified), null, 'mesgs');
268  } else {
269  setEventMessages($langs->trans("NoRecordFound"), null, 'warnings');
270  }
271  } else {
272  setEventMessages($langs->trans("Error"), null, 'errors');
273  }
274  }
275 }
276 
277 /*
278  * View
279  */
280 
281 $form = new Form($db);
282 
283 $title = $langs->trans('ProductVatMassChange');
284 
285 llxHeader('', $title);
286 
287 print load_fiche_titre($title, '', 'title_setup');
288 
289 print $langs->trans("ProductVatMassChangeDesc").'<br><br>';
290 
291 if (empty($mysoc->country_code)) {
292  $langs->load("errors");
293  $warnpicto = img_error($langs->trans("WarningMandatorySetupNotComplete"));
294  print '<br><a href="'.DOL_URL_ROOT.'/admin/company.php?mainmenu=home">'.$warnpicto.' '.$langs->trans("WarningMandatorySetupNotComplete").'</a>';
295 } else {
296  print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
297  print '<input type="hidden" name="token" value="'.newToken().'" />';
298  print '<input type="hidden" name="action" value="convert" />';
299 
300  print '<table class="noborder centpercent">';
301  print '<tr class="liste_titre">';
302  print '<td>'.$langs->trans("Parameters").'</td>'."\n";
303  print '<td class="right" width="60">'.$langs->trans("Value").'</td>'."\n";
304  print '</tr>'."\n";
305 
306 
307  print '<tr class="oddeven">'."\n";
308  print '<td>'.$langs->trans("OldVATRates").'</td>'."\n";
309  print '<td width="60" class="right">'."\n";
310  print $form->load_tva('oldvatrate', $oldvatrate, $mysoc, null, 0, 0, '', false, 1);
311  print '</td>'."\n";
312  print '</tr>'."\n";
313 
314 
315  print '<tr class="oddeven">'."\n";
316  print '<td>'.$langs->trans("NewVATRates").'</td>'."\n";
317  print '<td width="60" class="right">'."\n";
318  print $form->load_tva('newvatrate', $newvatrate, $mysoc, null, 0, 0, '', false, 1);
319  print '</td>'."\n";
320  print '</tr>'."\n";
321 
322  /*
323 
324  print '<tr class="oddeven">'."\n";
325  print '<td>'.$langs->trans("PriceBaseTypeToChange").'</td>'."\n";
326  print '<td width="60" class="right">'."\n";
327  print $form->selectPriceBaseType($price_base_type);
328  print '</td>'."\n";
329  print '</tr>'."\n";
330  */
331 
332  print '</table>';
333 
334  print '<br>';
335 
336  // Buttons for actions
337 
338  print '<div class="center">';
339  print '<input type="submit" id="convert_vatrate" name="convert_vatrate" value="'.$langs->trans("MassConvert").'" class="button" />';
340  print '</div>';
341 
342  print '</form>';
343 }
344 
345 // End of page
346 llxFooter();
347 $db->close();
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:56
llxFooter()
Empty footer.
Definition: wrapper.php:70
Class to manage generation of HTML components Only common components must be here.
Class to manage suppliers.
Class to manage predefined suppliers products.
Class to manage products or services.
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
img_error($titlealt='default')
Show error logo.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.