dolibarr  13.0.2
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) 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 
51 if ($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 
271 llxHeader('', $title);
272 
273 print load_fiche_titre($title, '', 'title_setup');
274 
275 print $langs->trans("ProductVatMassChangeDesc").'<br><br>';
276 
277 if (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
333 llxFooter();
334 $db->close();
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
Class to manage products or services.
Class to manage suppliers.
llxHeader()
Empty header.
Definition: wrapper.php:45
setEventMessages($mesg, $mesgs, $style= 'mesgs', $messagekey= '')
Set event messages in dol_events session object.
img_error($titlealt= 'default')
Show error logo.
Class to manage generation of HTML components Only common components must be here.
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 &#39;...
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 ...
print
Draft customers invoices.
Definition: index.php:89
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1232
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.
llxFooter()
Empty footer.
Definition: wrapper.php:59
Class to manage predefined suppliers products.