dolibarr  19.0.0-dev
server_productorservice.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2006-2016 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2012 JF FERRY <jfefe@aternatik.fr>
4  * Copyright (C) 2020 Frédéric France <frederic.france@netlogic.fr>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  *
19  * Path to WSDL is: http://localhost/dolibarr/webservices/server_productorservice.php?wsdl
20  */
21 
27 if (!defined('NOCSRFCHECK')) {
28  define('NOCSRFCHECK', '1'); // Do not check anti CSRF attack test
29 }
30 if (!defined('NOTOKENRENEWAL')) {
31  define('NOTOKENRENEWAL', '1'); // Do not check anti POST attack test
32 }
33 if (!defined('NOREQUIREMENU')) {
34  define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu
35 }
36 if (!defined('NOREQUIREHTML')) {
37  define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php
38 }
39 if (!defined('NOREQUIREAJAX')) {
40  define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library
41 }
42 if (!defined("NOLOGIN")) {
43  define("NOLOGIN", '1'); // If this page is public (can be called outside logged session)
44 }
45 if (!defined("NOSESSION")) {
46  define("NOSESSION", '1');
47 }
48 
49 require '../main.inc.php';
50 require_once NUSOAP_PATH.'/nusoap.php'; // Include SOAP
51 require_once DOL_DOCUMENT_ROOT.'/core/lib/ws.lib.php';
52 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions.lib.php';
53 require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
54 
55 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
56 require_once DOL_DOCUMENT_ROOT."/categories/class/categorie.class.php";
57 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
58 
59 
60 
61 dol_syslog("Call Dolibarr webservices interfaces");
62 
63 $langs->load("main");
64 
65 // Enable and test if module web services is enabled
66 if (empty($conf->global->MAIN_MODULE_WEBSERVICES)) {
67  $langs->load("admin");
68  dol_syslog("Call Dolibarr webservices interfaces with module webservices disabled");
69  print $langs->trans("WarningModuleNotActive", 'WebServices').'.<br><br>';
70  print $langs->trans("ToActivateModule");
71  exit;
72 }
73 
74 // Create the soap Object
75 $server = new nusoap_server();
76 $server->soap_defencoding = 'UTF-8';
77 $server->decode_utf8 = false;
78 $ns = 'http://www.dolibarr.org/ns/';
79 $server->configureWSDL('WebServicesDolibarrProductOrService', $ns);
80 $server->wsdl->schemaTargetNamespace = $ns;
81 
82 
83 // Define WSDL Authentication object
84 $server->wsdl->addComplexType(
85  'authentication',
86  'complexType',
87  'struct',
88  'all',
89  '',
90  array(
91  'dolibarrkey' => array('name'=>'dolibarrkey', 'type'=>'xsd:string'),
92  'sourceapplication' => array('name'=>'sourceapplication', 'type'=>'xsd:string'),
93  'login' => array('name'=>'login', 'type'=>'xsd:string'),
94  'password' => array('name'=>'password', 'type'=>'xsd:string'),
95  'entity' => array('name'=>'entity', 'type'=>'xsd:string')
96  )
97 );
98 // Define WSDL Return object
99 $server->wsdl->addComplexType(
100  'result',
101  'complexType',
102  'struct',
103  'all',
104  '',
105  array(
106  'result_code' => array('name'=>'result_code', 'type'=>'xsd:string'),
107  'result_label' => array('name'=>'result_label', 'type'=>'xsd:string')
108  )
109 );
110 
111 $productorservice_fields = array(
112  'id' => array('name'=>'id', 'type'=>'xsd:string'),
113  'ref' => array('name'=>'ref', 'type'=>'xsd:string'),
114  'ref_ext' => array('name'=>'ref_ext', 'type'=>'xsd:string'),
115  'type' => array('name'=>'type', 'type'=>'xsd:string'),
116  'label' => array('name'=>'label', 'type'=>'xsd:string'),
117  'description' => array('name'=>'description', 'type'=>'xsd:string'),
118  'date_creation' => array('name'=>'date_creation', 'type'=>'xsd:dateTime'),
119  'date_modification' => array('name'=>'date_modification', 'type'=>'xsd:dateTime'),
120  'note' => array('name'=>'note', 'type'=>'xsd:string'),
121  'status_tobuy' => array('name'=>'status_tobuy', 'type'=>'xsd:string'),
122  'status_tosell' => array('name'=>'status_tosell', 'type'=>'xsd:string'),
123  'barcode' => array('name'=>'barcode', 'type'=>'xsd:string'),
124  'barcode_type' => array('name'=>'barcode_type', 'type'=>'xsd:string'),
125  'country_id' => array('name'=>'country_id', 'type'=>'xsd:string'),
126  'country_code' => array('name'=>'country_code', 'type'=>'xsd:string'),
127  'customcode' => array('name'=>'customcode', 'type'=>'xsd:string'),
128 
129  'price_net' => array('name'=>'price_net', 'type'=>'xsd:string'),
130  'price' => array('name'=>'price', 'type'=>'xsd:string'),
131  'price_min_net' => array('name'=>'price_min_net', 'type'=>'xsd:string'),
132  'price_min' => array('name'=>'price_min', 'type'=>'xsd:string'),
133 
134  'price_base_type' => array('name'=>'price_base_type', 'type'=>'xsd:string'),
135 
136  'vat_rate' => array('name'=>'vat_rate', 'type'=>'xsd:string'),
137  'vat_npr' => array('name'=>'vat_npr', 'type'=>'xsd:string'),
138  'localtax1_tx' => array('name'=>'localtax1_tx', 'type'=>'xsd:string'),
139  'localtax2_tx' => array('name'=>'localtax2_tx', 'type'=>'xsd:string'),
140 
141  'stock_alert' => array('name'=>'stock_alert', 'type'=>'xsd:string'),
142  'stock_real' => array('name'=>'stock_real', 'type'=>'xsd:string'),
143  'stock_pmp' => array('name'=>'stock_pmp', 'type'=>'xsd:string'),
144  'warehouse_ref' => array('name'=>'warehouse_ref', 'type'=>'xsd:string'), // Used only for create or update to set which warehouse to use for stock correction if stock_real differs from database
145 
146  'canvas' => array('name'=>'canvas', 'type'=>'xsd:string'),
147  'import_key' => array('name'=>'import_key', 'type'=>'xsd:string'),
148 
149  'dir' => array('name'=>'dir', 'type'=>'xsd:string'),
150  'images' => array('name'=>'images', 'type'=>'tns:ImagesArray')
151 );
152 
153 
154 $elementtype = 'product';
155 
156 
157 //Retrieve all extrafield for product
158 // fetch optionals attributes and labels
159 $extrafields = new ExtraFields($db);
160 $extrafields->fetch_name_optionals_label($elementtype, true);
161 $extrafield_array = null;
162 if (is_array($extrafields) && count($extrafields) > 0) {
163  $extrafield_array = array();
164 }
165 if (isset($extrafields->attributes[$elementtype]['label']) && is_array($extrafields->attributes[$elementtype]['label']) && count($extrafields->attributes[$elementtype]['label'])) {
166  foreach ($extrafields->attributes[$elementtype]['label'] as $key => $label) {
167  $type = $extrafields->attributes[$elementtype]['type'][$key];
168  if ($type == 'date' || $type == 'datetime') {
169  $type = 'xsd:dateTime';
170  } else {
171  $type = 'xsd:string';
172  }
173 
174  $extrafield_array['options_'.$key] = array('name'=>'options_'.$key, 'type'=>$type);
175  }
176 }
177 
178 if (!empty($extrafield_array) && is_array($extrafield_array)) {
179  $productorservice_fields = array_merge($productorservice_fields, $extrafield_array);
180 }
181 
182 // Define other specific objects
183 $server->wsdl->addComplexType(
184  'product',
185  'complexType',
186  'struct',
187  'all',
188  '',
189  $productorservice_fields
190 );
191 
192 
193 /*
194  * Image of product
195  */
196 $server->wsdl->addComplexType(
197  'ImagesArray',
198  'complexType',
199  'array',
200  'sequence',
201  '',
202  array(
203  'image' => array(
204  'name' => 'image',
205  'type' => 'tns:image',
206  'minOccurs' => '0',
207  'maxOccurs' => 'unbounded'
208  )
209  )
210 );
211 
212 /*
213  * An image
214  */
215 $server->wsdl->addComplexType(
216  'image',
217  'complexType',
218  'struct',
219  'all',
220  '',
221  array(
222  'photo' => array('name'=>'photo', 'type'=>'xsd:string'),
223  'photo_vignette' => array('name'=>'photo_vignette', 'type'=>'xsd:string'),
224  'imgWidth' => array('name'=>'imgWidth', 'type'=>'xsd:string'),
225  'imgHeight' => array('name'=>'imgHeight', 'type'=>'xsd:string')
226  )
227 );
228 
229 
230 // Define other specific objects
231 $server->wsdl->addComplexType(
232  'filterproduct',
233  'complexType',
234  'struct',
235  'all',
236  '',
237  array(
238  //'limit' => array('name'=>'limit','type'=>'xsd:string'),
239  'type' => array('name'=>'type', 'type'=>'xsd:string'),
240  'status_tobuy' => array('name'=>'status_tobuy', 'type'=>'xsd:string'),
241  'status_tosell' => array('name'=>'status_tosell', 'type'=>'xsd:string'),
242  )
243 );
244 
245 $server->wsdl->addComplexType(
246  'ProductsArray2',
247  'complexType',
248  'array',
249  'sequence',
250  '',
251  array(
252  'product' => array(
253  'name' => 'product',
254  'type' => 'tns:product',
255  'minOccurs' => '0',
256  'maxOccurs' => 'unbounded'
257  )
258  )
259 );
260 
261 
262 // 5 styles: RPC/encoded, RPC/literal, Document/encoded (not WS-I compliant), Document/literal, Document/literal wrapped
263 // Style merely dictates how to translate a WSDL binding to a SOAP message. Nothing more. You can use either style with any programming model.
264 // http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/
265 $styledoc = 'rpc'; // rpc/document (document is an extend into SOAP 1.0 to support unstructured messages)
266 $styleuse = 'encoded'; // encoded/literal/literal wrapped
267 // Better choice is document/literal wrapped but literal wrapped not supported by nusoap.
268 
269 
270 // Register WSDL
271 $server->register(
272  'getProductOrService',
273  // Entry values
274  array('authentication'=>'tns:authentication', 'id'=>'xsd:string', 'ref'=>'xsd:string', 'ref_ext'=>'xsd:string', 'lang'=>'xsd:string'),
275  // Exit values
276  array('result'=>'tns:result', 'product'=>'tns:product'),
277  $ns,
278  $ns.'#getProductOrService',
279  $styledoc,
280  $styleuse,
281  'WS to get product or service'
282 );
283 
284 // Register WSDL
285 $server->register(
286  'createProductOrService',
287  // Entry values
288  array('authentication'=>'tns:authentication', 'product'=>'tns:product'),
289  // Exit values
290  array('result'=>'tns:result', 'id'=>'xsd:string'),
291  $ns,
292  $ns.'#createProductOrService',
293  $styledoc,
294  $styleuse,
295  'WS to create a product or service'
296 );
297 
298 // Register WSDL
299 $server->register(
300  'updateProductOrService',
301  // Entry values
302  array('authentication'=>'tns:authentication', 'product'=>'tns:product'),
303  // Exit values
304  array('result'=>'tns:result', 'id'=>'xsd:string'),
305  $ns,
306  $ns.'#updateProductOrService',
307  $styledoc,
308  $styleuse,
309  'WS to update a product or service'
310 );
311 
312 // Register WSDL
313 $server->register(
314  'deleteProductOrService',
315  // Entry values
316  array('authentication'=>'tns:authentication', 'listofid'=>'xsd:string'),
317  // Exit values
318  array('result'=>'tns:result', 'nbdeleted'=>'xsd:int'),
319  $ns,
320  $ns.'#deleteProductOrService',
321  $styledoc,
322  $styleuse,
323  'WS to delete a product or service'
324 );
325 
326 // Register WSDL
327 $server->register(
328  'getListOfProductsOrServices',
329  // Entry values
330  array('authentication'=>'tns:authentication', 'filterproduct'=>'tns:filterproduct'),
331  // Exit values
332  array('result'=>'tns:result', 'products'=>'tns:ProductsArray2'),
333  $ns,
334  $ns.'#getListOfProductsOrServices',
335  $styledoc,
336  $styleuse,
337  'WS to get list of all products or services id and ref'
338 );
339 
340 // Register WSDL
341 $server->register(
342  'getProductsForCategory',
343  // Entry values
344  array('authentication'=>'tns:authentication', 'id'=>'xsd:string', 'lang'=>'xsd:string'),
345  // Exit values
346  array('result'=>'tns:result', 'products'=>'tns:ProductsArray2'),
347  $ns,
348  $ns.'#getProductsForCategory',
349  $styledoc,
350  $styleuse,
351  'WS to get list of all products or services for a category'
352 );
353 
354 
365 function getProductOrService($authentication, $id = '', $ref = '', $ref_ext = '', $lang = '')
366 {
367  global $db, $conf, $langs;
368 
369  dol_syslog("Function: getProductOrService login=".$authentication['login']." id=".$id." ref=".$ref." ref_ext=".$ref_ext);
370 
371  $langcode = ($lang ? $lang : (empty($conf->global->MAIN_LANG_DEFAULT) ? 'auto' : $conf->global->MAIN_LANG_DEFAULT));
372  $langs->setDefaultLang($langcode);
373 
374  if ($authentication['entity']) {
375  $conf->entity = $authentication['entity'];
376  }
377 
378  // Init and check authentication
379  $objectresp = array();
380  $errorcode = '';
381  $errorlabel = '';
382  $error = 0;
383  $fuser = check_authentication($authentication, $error, $errorcode, $errorlabel);
384  // Check parameters
385  if (!$error && (($id && $ref) || ($id && $ref_ext) || ($ref && $ref_ext))) {
386  $error++;
387  $errorcode = 'BAD_PARAMETERS'; $errorlabel = "Parameter id, ref and ref_ext can't be both provided. You must choose one or other but not both.";
388  }
389 
390  if (!$error) {
391  $langcode = ($lang ? $lang : (empty($conf->global->MAIN_LANG_DEFAULT) ? 'auto' : $conf->global->MAIN_LANG_DEFAULT));
392  $langs->setDefaultLang($langcode);
393 
394  $fuser->getrights();
395 
396  $nbmax = 10;
397  if ($fuser->rights->produit->lire || $fuser->rights->service->lire) {
398  $product = new Product($db);
399  $result = $product->fetch($id, $ref, $ref_ext);
400 
401  if ($result > 0) {
402  $product->load_stock();
403 
404  $dir = (!empty($conf->product->dir_output) ? $conf->product->dir_output : $conf->service->dir_output);
405  $pdir = get_exdir($product->id, 2, 0, 0, $product, 'product').$product->ref."/";
406  $dir = $dir.'/'.$pdir;
407 
408  if (!empty($product->multilangs[$langs->defaultlang]["label"])) {
409  $product->label = $product->multilangs[$langs->defaultlang]["label"];
410  }
411  if (!empty($product->multilangs[$langs->defaultlang]["description"])) {
412  $product->description = $product->multilangs[$langs->defaultlang]["description"];
413  }
414  if (!empty($product->multilangs[$langs->defaultlang]["note"])) {
415  $product->note = $product->multilangs[$langs->defaultlang]["note"];
416  }
417 
418  $productorservice_result_fields = array(
419  'id' => $product->id,
420  'ref' => $product->ref,
421  'ref_ext' => $product->ref_ext,
422  'label' => $product->label,
423  'description' => $product->description,
424  'date_creation' => dol_print_date($product->date_creation, 'dayhourrfc'),
425  'date_modification' => dol_print_date($product->date_modification, 'dayhourrfc'),
426  'note' => $product->note,
427  'status_tosell' => $product->status,
428  'status_tobuy' => $product->status_buy,
429  'type' => $product->type,
430  'barcode' => $product->barcode,
431  'barcode_type' => $product->barcode_type,
432  'country_id' => $product->country_id > 0 ? $product->country_id : '',
433  'country_code' => $product->country_code,
434  'custom_code' => $product->customcode,
435 
436  'price_net' => $product->price,
437  'price' => $product->price_ttc,
438  'price_min_net' => $product->price_min,
439  'price_min' => $product->price_min_ttc,
440  'price_base_type' => $product->price_base_type,
441  'vat_rate' => $product->tva_tx,
443  'vat_npr' => $product->tva_npr,
445  'localtax1_tx' => $product->localtax1_tx,
446  'localtax2_tx' => $product->localtax2_tx,
447 
448  'stock_real' => $product->stock_reel,
449  'stock_virtual' => $product->stock_theorique,
450  'stock_alert' => $product->seuil_stock_alerte,
451  'pmp' => $product->pmp,
452  'import_key' => $product->import_key,
453  'dir' => $pdir,
454  'images' => $product->liste_photos($dir, $nbmax)
455  );
456 
457  $elementtype = 'product';
458 
459  //Retrieve all extrafield for thirdsparty
460  // fetch optionals attributes and labels
461  $extrafields = new ExtraFields($db);
462  $extrafields->fetch_name_optionals_label($elementtype, true);
463  //Get extrafield values
464  $product->fetch_optionals();
465 
466  if (isset($extrafields->attributes[$elementtype]['label']) && is_array($extrafields->attributes[$elementtype]['label']) && count($extrafields->attributes[$elementtype]['label'])) {
467  foreach ($extrafields->attributes[$elementtype]['label'] as $key => $label) {
468  $productorservice_result_fields = array_merge($productorservice_result_fields, array('options_'.$key => $product->array_options['options_'.$key]));
469  }
470  }
471 
472  // Create
473  $objectresp = array(
474  'result'=>array('result_code'=>'OK', 'result_label'=>''),
475  'product'=>$productorservice_result_fields
476  );
477  } else {
478  $error++;
479  $errorcode = 'NOT_FOUND'; $errorlabel = 'Object not found for id='.$id.' nor ref='.$ref.' nor ref_ext='.$ref_ext;
480  }
481  } else {
482  $error++;
483  $errorcode = 'PERMISSION_DENIED'; $errorlabel = 'User does not have permission for this request';
484  }
485  }
486 
487  if ($error) {
488  $objectresp = array('result'=>array('result_code' => $errorcode, 'result_label' => $errorlabel));
489  }
490  //var_dump($objectresp);exit;
491  return $objectresp;
492 }
493 
494 
502 function createProductOrService($authentication, $product)
503 {
504  global $db, $conf;
505 
506  $now = dol_now();
507 
508  dol_syslog("Function: createProductOrService login=".$authentication['login']);
509 
510  if ($authentication['entity']) {
511  $conf->entity = $authentication['entity'];
512  }
513 
514  // Init and check authentication
515  $objectresp = array();
516  $errorcode = '';
517  $errorlabel = '';
518  $error = 0;
519  $fuser = check_authentication($authentication, $error, $errorcode, $errorlabel);
520  // Check parameters
521  if (empty($product['price_base_type'])) {
522  if (isset($product['price_net']) && $product['price_net'] > 0) {
523  $product['price_base_type'] = 'HT';
524  }
525  if (isset($product['price']) && $product['price'] > 0) {
526  $product['price_base_type'] = 'TTC';
527  }
528  }
529 
530  if (isset($product['price_net']) && $product['price_net'] > 0 && isset($product['price']) && $product['price'] > 0) {
531  $error++; $errorcode = 'KO'; $errorlabel = "You must choose between price or price_net to provide price.";
532  }
533 
534  if (!empty($product['barcode']) && empty($product['barcode_type'])) {
535  $error++; $errorcode = 'KO'; $errorlabel = "You must set a barcode type when setting a barcode.";
536  }
537 
538  if (!$error) {
539  include_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
540 
541  $newobject = new Product($db);
542  $newobject->ref = $product['ref'];
543  $newobject->ref_ext = empty($product['ref_ext']) ? '' : $product['ref_ext'];
544  $newobject->type = empty($product['type']) ? 0 : $product['type'];
545  $newobject->label = empty($product['label']) ? '' : $product['label'];
546  $newobject->description = empty($product['description']) ? '' : $product['description'];
547  $newobject->note_public = empty($product['note_public']) ? '' : $product['note_public'];
548  $newobject->note_private = empty($product['note_private']) ? '' : $product['note_private'];
549  $newobject->status = empty($product['status_tosell']) ? 0 : $product['status_tosell'];
550  $newobject->status_buy = empty($product['status_tobuy']) ? 0 : $product['status_tobuy'];
551  $newobject->price = isset($product['price_net']) ? $product['price_net'] : 0;
552  $newobject->price_ttc = isset($product['price']) ? $product['price'] : 0;
553  $newobject->tva_tx = empty($product['vat_rate']) ? 0 : $product['vat_rate'];
554  $newobject->price_base_type = $product['price_base_type'];
555  $newobject->date_creation = $now;
556 
557  if (!empty($product['barcode'])) {
558  $newobject->barcode = $product['barcode'];
559  $newobject->barcode_type = $product['barcode_type'];
560  }
561 
562  $newobject->stock_reel = isset($product['stock_real']) ? $product['stock_real'] : null;
563  $newobject->pmp = isset($product['pmp']) ? $product['pmp'] : null;
564  $newobject->seuil_stock_alerte = isset($product['stock_alert']) ? $product['stock_alert'] : null;
565 
566  $newobject->country_id = isset($product['country_id']) ? $product['country_id'] : 0;
567  if (!empty($product['country_code'])) {
568  $newobject->country_id = getCountry($product['country_code'], 3);
569  }
570  $newobject->customcode = isset($product['customcode']) ? $product['customcode'] : '';
571 
572  $newobject->canvas = isset($product['canvas']) ? $product['canvas'] : '';
573  /*foreach($product['lines'] as $line)
574  {
575  $newline=new FactureLigne($db);
576  $newline->type=$line['type'];
577  $newline->desc=$line['desc'];
578  $newline->fk_product=$line['fk_product'];
579  $newline->total_ht=$line['total_net'];
580  $newline->total_vat=$line['total_vat'];
581  $newline->total_ttc=$line['total'];
582  $newline->vat=$line['vat_rate'];
583  $newline->qty=$line['qty'];
584  $newline->fk_product=$line['product_id'];
585  }*/
586  //var_dump($product['ref_ext']);
587  //var_dump($product['lines'][0]['type']);
588 
589  $elementtype = 'product';
590 
591  $extrafields = new ExtraFields($db);
592  $extrafields->fetch_name_optionals_label($elementtype, true);
593  if (isset($extrafields->attributes[$elementtype]['label']) && is_array($extrafields->attributes[$elementtype]['label']) && count($extrafields->attributes[$elementtype]['label'])) {
594  foreach ($extrafields->attributes[$elementtype]['label'] as $key => $label) {
595  $key = 'options_'.$key;
596  $newobject->array_options[$key] = $product[$key];
597  }
598  }
599 
600  $db->begin();
601 
602  $result = $newobject->create($fuser, 0);
603  if ($result <= 0) {
604  $error++;
605  }
606 
607  if (!$error) {
608  // Update stock if stock count is provided and differs from database after creation or update
609  if (isset($product['stock_real']) && $product['stock_real'] != '' && !empty($conf->global->stock->enabled)) {
610  include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
611 
612  $savstockreal = $newobject->stock_reel;
613  $newobject->load_stock('novirtual,nobatch'); // This overwrite ->stock_reel, surely 0 because we have just created product
614  $getstockreal = $newobject->stock_reel;
615 
616  if ($savstockreal != $getstockreal) {
617  $warehouse = new Entrepot($db);
618  $warehouse->fetch(0, $product['warehouse_ref']);
619  if ($warehouse->id > 0) {
620  if (($savstockreal - $getstockreal) > 0) {
621  $result = $newobject->correct_stock($fuser, $warehouse->id, ($savstockreal - $getstockreal), 0, 'Correction from external call (Web Service)', 0, 'WS'.dol_print_date($now, 'dayhourlog'));
622  }
623  if (($savstockreal - $getstockreal) > 0) {
624  $result = $newobject->correct_stock($fuser, $warehouse->id, ($savstockreal - $getstockreal), 1, 'Correction from external call (Web Service)', 0, 'WS'.dol_print_date($now, 'dayhourlog'));
625  }
626  if ($result <= 0) {
627  $error++;
628  $newobject->error = 'You set a different value for stock, but correction of stock count (before='.$getstockreal.', after='.$savstockreal.') fails with error '.$newobject->error;
629  }
630  } else {
631  $error++;
632  $newobject->error = 'You set a different value for stock but we failed to find warehouse '.$product['warehouse_ref'].' to make correction.';
633  }
634  }
635  }
636  }
637 
638  if (!$error) {
639  $db->commit();
640  $objectresp = array('result'=>array('result_code'=>'OK', 'result_label'=>''), 'id'=>$newobject->id, 'ref'=>$newobject->ref);
641  } else {
642  $db->rollback();
643  $error++;
644  $errorcode = 'KO';
645  $errorlabel = $newobject->error;
646  }
647  }
648 
649  if ($error) {
650  $objectresp = array('result'=>array('result_code' => $errorcode, 'result_label' => $errorlabel));
651  }
652 
653  return $objectresp;
654 }
655 
656 
664 function updateProductOrService($authentication, $product)
665 {
666  global $db, $conf;
667 
668  $now = dol_now();
669 
670  dol_syslog("Function: updateProductOrService login=".$authentication['login']);
671 
672  if ($authentication['entity']) {
673  $conf->entity = $authentication['entity'];
674  }
675 
676  // Init and check authentication
677  $objectresp = array();
678  $errorcode = '';
679  $errorlabel = '';
680  $error = 0;
681  $fuser = check_authentication($authentication, $error, $errorcode, $errorlabel);
682  // Check parameters
683  if ($product['price_net'] > 0) {
684  $product['price_base_type'] = 'HT';
685  }
686  if ($product['price'] > 0) {
687  $product['price_base_type'] = 'TTC';
688  }
689 
690  if ($product['price_net'] > 0 && $product['price'] > 0) {
691  $error++; $errorcode = 'KO'; $errorlabel = "You must choose between price or price_net to provide price.";
692  }
693 
694 
695  if ($product['barcode'] && !$product['barcode_type']) {
696  $error++; $errorcode = 'KO'; $errorlabel = "You must set a barcode type when setting a barcode.";
697  }
698 
699  if (!$error) {
700  include_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
701 
702  $newobject = new Product($db);
703  $newobject->fetch($product['id']);
704 
705  if (isset($product['ref'])) {
706  $newobject->ref = $product['ref'];
707  }
708  if (isset($product['ref_ext'])) {
709  $newobject->ref_ext = $product['ref_ext'];
710  }
711  $newobject->type = $product['type'];
712  $newobject->label = $product['label'];
713  $newobject->description = $product['description'];
714  $newobject->note = $product['note'];
715  $newobject->status = $product['status_tosell'];
716  $newobject->status_buy = $product['status_tobuy'];
717  $newobject->price = $product['price_net'];
718  $newobject->price_ttc = $product['price'];
719  $newobject->tva_tx = $product['vat_rate'];
720  $newobject->price_base_type = $product['price_base_type'];
721  $newobject->date_creation = $now;
722 
723  if ($product['barcode']) {
724  $newobject->barcode = $product['barcode'];
725  $newobject->barcode_type = $product['barcode_type'];
726  }
727 
728  $newobject->stock_reel = isset($product['stock_real']) ? $product['stock_real'] : null;
729  $newobject->pmp = isset($product['pmp']) ? $product['pmp'] : null;
730  $newobject->seuil_stock_alerte = isset($product['stock_alert']) ? $product['stock_alert'] : null;
731 
732  $newobject->country_id = isset($product['country_id']) ? $product['country_id'] : 0;
733  if (!empty($product['country_code'])) {
734  $newobject->country_id = getCountry($product['country_code'], 3);
735  }
736  $newobject->customcode = isset($product['customcode']) ? $product['customcode'] : '';
737 
738  $newobject->canvas = isset($product['canvas']) ? $product['canvas'] : '';
739 
740  $elementtype = 'product';
741 
742  $extrafields = new ExtraFields($db);
743  $extrafields->fetch_name_optionals_label($elementtype, true);
744  if (isset($extrafields->attributes[$elementtype]['label']) && is_array($extrafields->attributes[$elementtype]['label']) && count($extrafields->attributes[$elementtype]['label'])) {
745  foreach ($extrafields->attributes[$elementtype]['label'] as $key => $label) {
746  $key = 'options_'.$key;
747  $newobject->array_options[$key] = $product[$key];
748  }
749  }
750 
751  $db->begin();
752 
753  $result = $newobject->update($newobject->id, $fuser);
754  if ($result <= 0) {
755  $error++;
756  } else {
757  // Update stock if stock count is provided and differs from database after creation or update
758  if (isset($product['stock_real']) && $product['stock_real'] != '' && !empty($conf->global->stock->enabled)) {
759  include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
760 
761  $savstockreal = $newobject->stock_reel;
762  $newobject->load_stock('novirtual,nobatch'); // This overwrite ->stock_reel
763  $getstockreal = $newobject->stock_reel;
764 
765  if ($savstockreal != $getstockreal) {
766  $warehouse = new Entrepot($db);
767  $warehouse->fetch(0, $product['warehouse_ref']);
768  if ($warehouse->id > 0) {
769  if (($savstockreal - $getstockreal) > 0) {
770  $result = $newobject->correct_stock($fuser, $warehouse->id, ($savstockreal - $getstockreal), 0, 'Correction from external call (Web Service)', 0, 'WS'.dol_print_date($now, 'dayhourlog'));
771  }
772  if (($savstockreal - $getstockreal) > 0) {
773  $result = $newobject->correct_stock($fuser, $warehouse->id, ($savstockreal - $getstockreal), 1, 'Correction from external call (Web Service)', 0, 'WS'.dol_print_date($now, 'dayhourlog'));
774  }
775  if ($result <= 0) {
776  $error++;
777  $newobject->error = 'You set a different value for stock, but correction of stock count (before='.$getstockreal.', after='.$savstockreal.') fails with error '.$newobject->error;
778  }
779  } else {
780  $error++;
781  $newobject->error = 'You set a different value for stock but we failed to find warehouse '.$product['warehouse_ref'].' to make correction.';
782  }
783  }
784  }
785  }
786 
787  if (!$error) {
788  if ($newobject->price_base_type == 'HT') {
789  $result = $newobject->updatePrice($newobject->price, $newobject->price_base_type, $fuser);
790  if ($result <= 0) {
791  $error++;
792  }
793  } elseif ($newobject->price_base_type == 'TTC') {
794  $result = $newobject->updatePrice($newobject->price_ttc, $newobject->price_base_type, $fuser);
795  if ($result <= 0) {
796  $error++;
797  }
798  }
799  }
800 
801  if (!$error) {
802  $db->commit();
803  $objectresp = array('result'=>array('result_code'=>'OK', 'result_label'=>''), 'id'=>$newobject->id, 'ref'=>$newobject->ref);
804  } else {
805  $db->rollback();
806  $error++;
807  $errorcode = 'KO';
808  $errorlabel = $newobject->error;
809  }
810  }
811 
812  if ($error) {
813  $objectresp = array('result'=>array('result_code' => $errorcode, 'result_label' => $errorlabel));
814  }
815 
816  return $objectresp;
817 }
818 
819 
827 function deleteProductOrService($authentication, $listofidstring)
828 {
829  global $db, $conf;
830 
831  dol_syslog("Function: deleteProductOrService login=".$authentication['login']);
832 
833  if ($authentication['entity']) {
834  $conf->entity = $authentication['entity'];
835  }
836 
837  // Init and check authentication
838  $objectresp = array();
839  $errorcode = '';
840  $errorlabel = '';
841  $error = 0;
842  $fuser = check_authentication($authentication, $error, $errorcode, $errorlabel);
843 
844  // User must be defined to user authenticated
845  global $user;
846  $user = $fuser;
847 
848  $listofid = explode(',', trim($listofidstring));
849  $listofiddeleted = array();
850 
851  // Check parameters
852  if (count($listofid) == 0 || empty($listofid[0])) {
853  $error++; $errorcode = 'KO'; $errorlabel = "List of Id of products or services to delete are required.";
854  }
855 
856  if (!$error) {
857  $firsterror = '';
858 
859  $db->begin();
860 
861  foreach ($listofid as $id) {
862  $newobject = new Product($db);
863  $result = $newobject->fetch($id);
864 
865  if ($result == 0) {
866  $error++;
867  $firsterror = 'Product or service with id '.$id.' not found';
868  break;
869  } else {
870  $result = $newobject->delete($user);
871  if ($result <= 0) {
872  $error++;
873  $firsterror = $newobject->error;
874  break;
875  }
876 
877  $listofiddeleted[] = $id;
878  }
879  }
880 
881  if (!$error) {
882  $db->commit();
883  //$objectresp=array('result'=>array('result_code'=>'OK', 'result_label'=>''), 'listofid'=>$listofiddeleted);
884  $objectresp = array('result'=>array('result_code'=>'OK', 'result_label'=>''), 'nbdeleted'=>count($listofiddeleted));
885  } else {
886  $db->rollback();
887  $error++;
888  $errorcode = 'KO';
889  $errorlabel = $firsterror;
890  }
891  }
892 
893  if ($error) {
894  //$objectresp = array('result'=>array('result_code' => $errorcode, 'result_label' => $errorlabel), 'listofid'=>$listofiddeleted);
895  $objectresp = array('result'=>array('result_code' => $errorcode, 'result_label' => $errorlabel), 'nbdeleted'=>0);
896  } elseif (count($listofiddeleted) == 0) {
897  //$objectresp=array('result'=>array('result_code'=>'NOT_FOUND', 'result_label'=>'No product or service with id '.join(',',$listofid).' found'), 'listofid'=>$listofiddeleted);
898  $objectresp = array('result'=>array('result_code'=>'NOT_FOUND', 'result_label'=>'No product or service with id '.join(',', $listofid).' found'), 'nbdeleted'=>0);
899  }
900 
901  return $objectresp;
902 }
903 
904 
912 function getListOfProductsOrServices($authentication, $filterproduct)
913 {
914  global $db, $conf;
915 
916  dol_syslog("Function: getListOfProductsOrServices login=".$authentication['login']);
917 
918  if ($authentication['entity']) {
919  $conf->entity = $authentication['entity'];
920  }
921 
922  // Init and check authentication
923  $objectresp = array();
924  $arrayproducts = array();
925  $errorcode = '';
926  $errorlabel = '';
927  $error = 0;
928  $fuser = check_authentication($authentication, $error, $errorcode, $errorlabel);
929  // Check parameters
930 
931  if (!$error) {
932  $sql = "SELECT rowid, ref, ref_ext";
933  $sql .= " FROM ".MAIN_DB_PREFIX."product";
934  $sql .= " WHERE entity=".$conf->entity;
935  foreach ($filterproduct as $key => $val) {
936  if ($key == 'type' && $val >= 0) {
937  $sql .= " AND fk_product_type = ".((int) $val);
938  }
939  if ($key == 'status_tosell') {
940  $sql .= " AND tosell = ".((int) $val);
941  }
942  if ($key == 'status_tobuy') {
943  $sql .= " AND tobuy = ".((int) $val);
944  }
945  }
946  $resql = $db->query($sql);
947  if ($resql) {
948  $num = $db->num_rows($resql);
949 
950  $i = 0;
951  while ($i < $num) {
952  $obj = $db->fetch_object($resql);
953  $arrayproducts[] = array('id'=>$obj->rowid, 'ref'=>$obj->ref, 'ref_ext'=>$obj->ref_ext);
954  $i++;
955  }
956  } else {
957  $error++;
958  $errorcode = $db->lasterrno();
959  $errorlabel = $db->lasterror();
960  }
961  }
962 
963  if ($error) {
964  $objectresp = array(
965  'result'=>array('result_code' => $errorcode, 'result_label' => $errorlabel),
966  'products'=>$arrayproducts
967  );
968  } else {
969  $objectresp = array(
970  'result'=>array('result_code' => 'OK', 'result_label' => ''),
971  'products'=>$arrayproducts
972  );
973  }
974 
975  return $objectresp;
976 }
977 
978 
987 function getProductsForCategory($authentication, $id, $lang = '')
988 {
989  global $db, $conf, $langs;
990 
991  $langcode = ($lang ? $lang : (empty($conf->global->MAIN_LANG_DEFAULT) ? 'auto' : $conf->global->MAIN_LANG_DEFAULT));
992  $langs->setDefaultLang($langcode);
993 
994  dol_syslog("Function: getProductsForCategory login=".$authentication['login']." id=".$id);
995 
996  if ($authentication['entity']) {
997  $conf->entity = $authentication['entity'];
998  }
999 
1000  $objectresp = array();
1001  $errorcode = ''; $errorlabel = '';
1002  $error = 0;
1003 
1004  $fuser = check_authentication($authentication, $error, $errorcode, $errorlabel);
1005 
1006 
1007  if (!$error && !$id) {
1008  $error++;
1009  $errorcode = 'BAD_PARAMETERS'; $errorlabel = "Parameter id must be provided.";
1010  }
1011 
1012 
1013  if (!$error) {
1014  $langcode = ($lang ? $lang : (empty($conf->global->MAIN_LANG_DEFAULT) ? 'auto' : $conf->global->MAIN_LANG_DEFAULT));
1015  $langs->setDefaultLang($langcode);
1016 
1017  $fuser->getrights();
1018 
1019  $nbmax = 10;
1020  if ($fuser->rights->produit->lire) {
1021  $categorie = new Categorie($db);
1022  $result = $categorie->fetch($id);
1023  if ($result > 0) {
1024  $table = "product";
1025  $field = "product";
1026  $sql = "SELECT fk_".$field." FROM ".MAIN_DB_PREFIX."categorie_".$table;
1027  $sql .= " WHERE fk_categorie = ".((int) $id);
1028  $sql .= " ORDER BY fk_".$field." ASC";
1029 
1030 
1031  dol_syslog("getProductsForCategory get id of product into category", LOG_DEBUG);
1032  $res = $db->query($sql);
1033  if ($res) {
1034  $iProduct = 0;
1035  $tmpproduct = new Product($db);
1036  $products = array();
1037  while ($rec = $db->fetch_array($res)) {
1038  $tmpproduct->fetch($rec['fk_'.$field]);
1039  if ($tmpproduct->status > 0) {
1040  $dir = (!empty($conf->product->dir_output) ? $conf->product->dir_output : $conf->service->dir_output);
1041  $pdir = get_exdir($tmpproduct->id, 2, 0, 0, $tmpproduct, 'product').$tmpproduct->id."/photos/";
1042  $dir = $dir.'/'.$pdir;
1043 
1044  $products[] = array(
1045  'id' => $tmpproduct->id,
1046  'ref' => $tmpproduct->ref,
1047  'ref_ext' => $tmpproduct->ref_ext,
1048  'label' => !empty($tmpproduct->multilangs[$langs->defaultlang]["label"]) ? $tmpproduct->multilangs[$langs->defaultlang]["label"] : $tmpproduct->label,
1049  'description' => !empty($tmpproduct->multilangs[$langs->defaultlang]["description"]) ? $tmpproduct->multilangs[$langs->defaultlang]["description"] : $tmpproduct->description,
1050  'date_creation' => dol_print_date($tmpproduct->date_creation, 'dayhourrfc'),
1051  'date_modification' => dol_print_date($tmpproduct->date_modification, 'dayhourrfc'),
1052  'note' => !empty($tmpproduct->multilangs[$langs->defaultlang]["note"]) ? $tmpproduct->multilangs[$langs->defaultlang]["note"] : $tmpproduct->note,
1053  'status_tosell' => $tmpproduct->status,
1054  'status_tobuy' => $tmpproduct->status_buy,
1055  'type' => $tmpproduct->type,
1056  'barcode' => $tmpproduct->barcode,
1057  'barcode_type' => $tmpproduct->barcode_type,
1058  'country_id' => $tmpproduct->country_id > 0 ? $tmpproduct->country_id : '',
1059  'country_code' => $tmpproduct->country_code,
1060  'custom_code' => $tmpproduct->customcode,
1061 
1062  'price_net' => $tmpproduct->price,
1063  'price' => $tmpproduct->price_ttc,
1064  'vat_rate' => $tmpproduct->tva_tx,
1065 
1066  'price_base_type' => $tmpproduct->price_base_type,
1067 
1068  'stock_real' => $tmpproduct->stock_reel,
1069  'stock_alert' => $tmpproduct->seuil_stock_alerte,
1070  'pmp' => $tmpproduct->pmp,
1071  'import_key' => $tmpproduct->import_key,
1072  'dir' => $pdir,
1073  'images' => $tmpproduct->liste_photos($dir, $nbmax)
1074  );
1075 
1076  $elementtype = 'product';
1077 
1078  //Retrieve all extrafield for thirdsparty
1079  // fetch optionals attributes and labels
1080  $extrafields = new ExtraFields($db);
1081  $extrafields->fetch_name_optionals_label($elementtype, true);
1082  //Get extrafield values
1083  $tmpproduct->fetch_optionals();
1084 
1085  if (isset($extrafields->attributes[$elementtype]['label']) && is_array($extrafields->attributes[$elementtype]['label']) && count($extrafields->attributes[$elementtype]['label'])) {
1086  foreach ($extrafields->attributes[$elementtype]['label'] as $key => $label) {
1087  $products[$iProduct] = array_merge($products[$iProduct], array('options_'.$key => $tmpproduct->array_options['options_'.$key]));
1088  }
1089  }
1090 
1091  $iProduct++;
1092  }
1093  }
1094 
1095  // Retour
1096  $objectresp = array(
1097  'result'=>array('result_code'=>'OK', 'result_label'=>''),
1098  'products'=> $products
1099  );
1100  } else {
1101  $errorcode = 'NORECORDS_FOR_ASSOCIATION'; $errorlabel = 'No products associated'.$sql;
1102  $objectresp = array('result'=>array('result_code' => $errorcode, 'result_label' => $errorlabel));
1103  dol_syslog("getProductsForCategory:: ".$errorcode, LOG_DEBUG);
1104  }
1105  } else {
1106  $error++;
1107  $errorcode = 'NOT_FOUND'; $errorlabel = 'Object not found for id='.$id;
1108  }
1109  } else {
1110  $error++;
1111  $errorcode = 'PERMISSION_DENIED'; $errorlabel = 'User does not have permission for this request';
1112  }
1113  }
1114 
1115  if ($error) {
1116  $objectresp = array('result'=>array('result_code' => $errorcode, 'result_label' => $errorlabel));
1117  }
1118 
1119  return $objectresp;
1120 }
1121 
1122 // Return the results.
1123 $server->service(file_get_contents("php://input"));
Class to manage categories.
Class to manage warehouses.
Class to manage standard extra fields.
Class to manage products or services.
getCountry($searchkey, $withcode='', $dbtouse=0, $outputlangs='', $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or label.
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
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getProductsForCategory($authentication, $id, $lang='')
Get list of products for a category.
getListOfProductsOrServices($authentication, $filterproduct)
getListOfProductsOrServices
updateProductOrService($authentication, $product)
Update a product or service.
createProductOrService($authentication, $product)
Create an invoice.
getProductOrService($authentication, $id='', $ref='', $ref_ext='', $lang='')
Get produt or service.
deleteProductOrService($authentication, $listofidstring)
Delete a product or service.
check_authentication($authentication, &$error, &$errorcode, &$errorlabel)
Check authentication array and set error, errorcode, errorlabel.
Definition: ws.lib.php:35