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