Conditions | 107 |
Paths | > 20000 |
Total Lines | 465 |
Code Lines | 309 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.
There are several approaches to avoid long parameter lists:
1 | <?php |
||
200 | public function _create($user, $fk_product, $entrepot_id, $qty, $type, $price = 0, $label = '', $inventorycode = '', $datem = '', $eatby = '', $sellby = '', $batch = '', $skip_batch = false, $id_product_batch = 0, $disablestockchangeforsubproduct = 0, $donotcleanemptylines = 0, $force_update_batch = false) |
||
201 | { |
||
202 | // phpcs:enable |
||
203 | global $conf, $langs; |
||
204 | |||
205 | |||
206 | $error = 0; |
||
207 | dol_syslog(get_class($this) . "::_create start userid=$user->id, fk_product=$fk_product, warehouse_id=$entrepot_id, qty=$qty, type=$type, price=$price, label=$label, inventorycode=$inventorycode, datem=" . $datem . ", eatby=" . $eatby . ", sellby=" . $sellby . ", batch=" . $batch . ", skip_batch=" . json_encode($skip_batch)); |
||
208 | |||
209 | // Call hook at beginning |
||
210 | global $action, $hookmanager; |
||
211 | $hookmanager->initHooks(array('mouvementstock')); |
||
212 | |||
213 | if (is_object($hookmanager)) { |
||
214 | $parameters = array( |
||
215 | 'currentcontext' => 'mouvementstock', |
||
216 | 'user' => &$user, |
||
217 | 'fk_product' => &$fk_product, |
||
218 | 'entrepot_id' => &$entrepot_id, |
||
219 | 'qty' => &$qty, |
||
220 | 'type' => &$type, |
||
221 | 'price' => &$price, |
||
222 | 'label' => &$label, |
||
223 | 'inventorycode' => &$inventorycode, |
||
224 | 'datem' => &$datem, |
||
225 | 'eatby' => &$eatby, |
||
226 | 'sellby' => &$sellby, |
||
227 | 'batch' => &$batch, |
||
228 | 'skip_batch' => &$skip_batch, |
||
229 | 'id_product_batch' => &$id_product_batch |
||
230 | ); |
||
231 | $reshook = $hookmanager->executeHooks('stockMovementCreate', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks |
||
232 | |||
233 | if ($reshook < 0) { |
||
234 | if (!empty($hookmanager->resPrint)) { |
||
235 | dol_print_error(null, $hookmanager->resPrint); |
||
236 | } |
||
237 | return $reshook; |
||
238 | } elseif ($reshook > 0) { |
||
239 | return $hookmanager->resPrint; |
||
240 | } |
||
241 | } |
||
242 | // end hook at beginning |
||
243 | |||
244 | // Clean parameters |
||
245 | $price = price2num($price, 'MU'); // Clean value for the casse we receive a float zero value, to have it a real zero value. |
||
246 | if (empty($price)) { |
||
247 | $price = 0; |
||
248 | } |
||
249 | $now = (!empty($datem) ? $datem : dol_now()); |
||
250 | |||
251 | // Check parameters |
||
252 | if (!($fk_product > 0)) { |
||
253 | return 0; |
||
254 | } |
||
255 | if (!($entrepot_id > 0)) { |
||
256 | return 0; |
||
257 | } |
||
258 | |||
259 | if (is_numeric($eatby) && $eatby < 0) { |
||
260 | dol_syslog(get_class($this) . "::_create start ErrorBadValueForParameterEatBy eatby = " . $eatby); |
||
261 | $this->errors[] = 'ErrorBadValueForParameterEatBy'; |
||
262 | return -1; |
||
263 | } |
||
264 | if (is_numeric($sellby) && $sellby < 0) { |
||
265 | dol_syslog(get_class($this) . "::_create start ErrorBadValueForParameterSellBy sellby = " . $sellby); |
||
266 | $this->errors[] = 'ErrorBadValueForParameterSellBy'; |
||
267 | return -1; |
||
268 | } |
||
269 | |||
270 | // Set properties of movement |
||
271 | $this->product_id = $fk_product; |
||
272 | $this->entrepot_id = $entrepot_id; // deprecated |
||
273 | $this->warehouse_id = $entrepot_id; |
||
274 | $this->qty = $qty; |
||
275 | $this->type = $type; |
||
276 | $this->price = price2num($price); |
||
277 | $this->label = $label; |
||
278 | $this->inventorycode = $inventorycode; |
||
279 | $this->datem = $now; |
||
280 | $this->batch = $batch; |
||
281 | |||
282 | $mvid = 0; |
||
283 | |||
284 | $product = new Product($this->db); |
||
285 | |||
286 | $result = $product->fetch($fk_product); |
||
287 | if ($result < 0) { |
||
288 | $this->error = $product->error; |
||
289 | $this->errors = $product->errors; |
||
290 | dol_print_error(null, "Failed to fetch product"); |
||
291 | return -1; |
||
292 | } |
||
293 | if ($product->id <= 0) { // Can happen if database is corrupted (a product id exist in stock with product that has been removed) |
||
294 | return 0; |
||
295 | } |
||
296 | |||
297 | // Define if we must make the stock change (If product type is a service or if stock is used also for services) |
||
298 | // Only record into stock tables will be disabled by this (the rest like writing into lot table or movement of subproucts are done) |
||
299 | $movestock = 0; |
||
300 | if ($product->type != Product::TYPE_SERVICE || getDolGlobalString('STOCK_SUPPORTS_SERVICES')) { |
||
301 | $movestock = 1; |
||
302 | } |
||
303 | |||
304 | $this->db->begin(); |
||
305 | |||
306 | // Set value $product->stock_reel and detail per warehouse into $product->stock_warehouse array |
||
307 | if ($movestock) { |
||
308 | $product->load_stock('novirtual'); |
||
309 | } |
||
310 | |||
311 | // Test if product require batch data. If yes, and there is not or values are not correct, we throw an error. |
||
312 | if (isModEnabled('productbatch') && $product->hasbatch() && !$skip_batch) { |
||
313 | if (empty($batch)) { |
||
314 | $langs->load("errors"); |
||
315 | $this->errors[] = $langs->transnoentitiesnoconv("ErrorTryToMakeMoveOnProductRequiringBatchData", $product->ref); |
||
316 | dol_syslog("Try to make a movement of a product with status_batch on without any batch data", LOG_ERR); |
||
317 | |||
318 | $this->db->rollback(); |
||
319 | return -2; |
||
320 | } |
||
321 | |||
322 | // Check table llx_product_lot from batchnumber for same product |
||
323 | // If found and eatby/sellby defined into table and provided and differs, return error |
||
324 | // If found and eatby/sellby defined into table and not provided, we take value from table |
||
325 | // If found and eatby/sellby not defined into table and provided, we update table |
||
326 | // If found and eatby/sellby not defined into table and not provided, we do nothing |
||
327 | // If not found, we add record |
||
328 | $sql = "SELECT pb.rowid, pb.batch, pb.eatby, pb.sellby FROM " . $this->db->prefix() . "product_lot as pb"; |
||
329 | $sql .= " WHERE pb.fk_product = " . ((int) $fk_product) . " AND pb.batch = '" . $this->db->escape($batch) . "'"; |
||
330 | |||
331 | dol_syslog(get_class($this) . "::_create scan serial for this product to check if eatby and sellby match", LOG_DEBUG); |
||
332 | |||
333 | $resql = $this->db->query($sql); |
||
334 | if ($resql) { |
||
335 | $num = $this->db->num_rows($resql); |
||
336 | $i = 0; |
||
337 | if ($num > 0) { |
||
338 | while ($i < $num) { |
||
339 | $obj = $this->db->fetch_object($resql); |
||
340 | if ($obj->eatby) { |
||
341 | if ($eatby) { |
||
342 | $tmparray = dol_getdate($eatby, true); |
||
343 | $eatbywithouthour = dol_mktime(0, 0, 0, $tmparray['mon'], $tmparray['mday'], $tmparray['year']); |
||
344 | if ($this->db->jdate($obj->eatby) != $eatby && $this->db->jdate($obj->eatby) != $eatbywithouthour) { // We test date without hours and with hours for backward compatibility |
||
345 | // If found and eatby/sellby defined into table and provided and differs, return error |
||
346 | $langs->load("stocks"); |
||
347 | $this->errors[] = $langs->transnoentitiesnoconv("ThisSerialAlreadyExistWithDifferentDate", $batch, dol_print_date($this->db->jdate($obj->eatby), 'dayhour'), dol_print_date($eatbywithouthour, 'dayhour')); |
||
348 | dol_syslog("ThisSerialAlreadyExistWithDifferentDate batch=" . $batch . ", eatby found into product_lot = " . $obj->eatby . " = " . dol_print_date($this->db->jdate($obj->eatby), 'dayhourrfc') . " so eatbywithouthour = " . $eatbywithouthour . " = " . dol_print_date($eatbywithouthour) . " - eatby provided = " . $eatby . " = " . dol_print_date($eatby, 'dayhourrfc'), LOG_ERR); |
||
349 | $this->db->rollback(); |
||
350 | return -3; |
||
351 | } |
||
352 | } else { |
||
353 | $eatby = $obj->eatby; // If found and eatby/sellby defined into table and not provided, we take value from table |
||
354 | } |
||
355 | } else { |
||
356 | if ($eatby) { // If found and eatby/sellby not defined into table and provided, we update table |
||
357 | $productlot = new Productlot($this->db); |
||
358 | $result = $productlot->fetch($obj->rowid); |
||
359 | $productlot->eatby = $eatby; |
||
360 | $result = $productlot->update($user); |
||
361 | if ($result <= 0) { |
||
362 | $this->error = $productlot->error; |
||
363 | $this->errors = $productlot->errors; |
||
364 | $this->db->rollback(); |
||
365 | return -5; |
||
366 | } |
||
367 | } |
||
368 | } |
||
369 | if ($obj->sellby) { |
||
370 | if ($sellby) { |
||
371 | $tmparray = dol_getdate($sellby, true); |
||
372 | $sellbywithouthour = dol_mktime(0, 0, 0, $tmparray['mon'], $tmparray['mday'], $tmparray['year']); |
||
373 | if ($this->db->jdate($obj->sellby) != $sellby && $this->db->jdate($obj->sellby) != $sellbywithouthour) { // We test date without hours and with hours for backward compatibility |
||
374 | // If found and eatby/sellby defined into table and provided and differs, return error |
||
375 | $this->errors[] = $langs->transnoentitiesnoconv("ThisSerialAlreadyExistWithDifferentDate", $batch, dol_print_date($this->db->jdate($obj->sellby)), dol_print_date($sellby)); |
||
376 | dol_syslog($langs->transnoentities("ThisSerialAlreadyExistWithDifferentDate", $batch, dol_print_date($this->db->jdate($obj->sellby)), dol_print_date($sellby)), LOG_ERR); |
||
377 | $this->db->rollback(); |
||
378 | return -3; |
||
379 | } |
||
380 | } else { |
||
381 | $sellby = $obj->sellby; // If found and eatby/sellby defined into table and not provided, we take value from table |
||
382 | } |
||
383 | } else { |
||
384 | if ($sellby) { // If found and eatby/sellby not defined into table and provided, we update table |
||
385 | $productlot = new Productlot($this->db); |
||
386 | $result = $productlot->fetch($obj->rowid); |
||
387 | $productlot->sellby = $sellby; |
||
388 | $result = $productlot->update($user); |
||
389 | if ($result <= 0) { |
||
390 | $this->error = $productlot->error; |
||
391 | $this->errors = $productlot->errors; |
||
392 | $this->db->rollback(); |
||
393 | return -5; |
||
394 | } |
||
395 | } |
||
396 | } |
||
397 | |||
398 | $i++; |
||
399 | } |
||
400 | } else { // If not found, we add record |
||
401 | $productlot = new Productlot($this->db); |
||
402 | $productlot->origin = !empty($this->origin_type) ? $this->origin_type : ''; |
||
|
|||
403 | $productlot->origin_id = !empty($this->origin_id) ? $this->origin_id : 0; |
||
404 | $productlot->entity = $conf->entity; |
||
405 | $productlot->fk_product = $fk_product; |
||
406 | $productlot->batch = $batch; |
||
407 | // If we are here = first time we manage this batch, so we used dates provided by users to create lot |
||
408 | $productlot->eatby = $eatby; |
||
409 | $productlot->sellby = $sellby; |
||
410 | $result = $productlot->create($user); |
||
411 | if ($result <= 0) { |
||
412 | $this->error = $productlot->error; |
||
413 | $this->errors = $productlot->errors; |
||
414 | $this->db->rollback(); |
||
415 | return -4; |
||
416 | } |
||
417 | } |
||
418 | } else { |
||
419 | dol_print_error($this->db); |
||
420 | $this->db->rollback(); |
||
421 | return -1; |
||
422 | } |
||
423 | } |
||
424 | |||
425 | // Check if stock is enough when qty is < 0 |
||
426 | // Note that qty should be > 0 with type 0 or 3, < 0 with type 1 or 2. |
||
427 | if ($movestock && $qty < 0 && !getDolGlobalInt('STOCK_ALLOW_NEGATIVE_TRANSFER')) { |
||
428 | if (isModEnabled('productbatch') && $product->hasbatch() && !$skip_batch) { |
||
429 | $foundforbatch = 0; |
||
430 | $qtyisnotenough = 0; |
||
431 | if (isset($product->stock_warehouse[$entrepot_id])) { |
||
432 | foreach ($product->stock_warehouse[$entrepot_id]->detail_batch as $batchcursor => $prodbatch) { |
||
433 | if ((string) $batch != (string) $batchcursor) { // Lot '59' must be different than lot '59c' |
||
434 | continue; |
||
435 | } |
||
436 | |||
437 | $foundforbatch = 1; |
||
438 | if ($prodbatch->qty < abs($qty)) { |
||
439 | $qtyisnotenough = $prodbatch->qty; |
||
440 | } |
||
441 | break; |
||
442 | } |
||
443 | } |
||
444 | if (!$foundforbatch || $qtyisnotenough) { |
||
445 | $langs->load("stocks"); |
||
446 | include_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php'; |
||
447 | $tmpwarehouse = new Entrepot($this->db); |
||
448 | $tmpwarehouse->fetch($entrepot_id); |
||
449 | |||
450 | $this->error = $langs->trans('qtyToTranferLotIsNotEnough', $product->ref, $batch, $qtyisnotenough, $tmpwarehouse->ref); |
||
451 | $this->errors[] = $langs->trans('qtyToTranferLotIsNotEnough', $product->ref, $batch, $qtyisnotenough, $tmpwarehouse->ref); |
||
452 | $this->db->rollback(); |
||
453 | return -8; |
||
454 | } |
||
455 | } else { |
||
456 | if (isset($product->stock_warehouse[$entrepot_id]) && (empty($product->stock_warehouse[$entrepot_id]->real) || $product->stock_warehouse[$entrepot_id]->real < abs($qty))) { |
||
457 | $langs->load("stocks"); |
||
458 | $this->error = $langs->trans('qtyToTranferIsNotEnough') . ' : ' . $product->ref; |
||
459 | $this->errors[] = $langs->trans('qtyToTranferIsNotEnough') . ' : ' . $product->ref; |
||
460 | $this->db->rollback(); |
||
461 | return -8; |
||
462 | } |
||
463 | } |
||
464 | } |
||
465 | |||
466 | if ($movestock) { // Change stock for current product, change for subproduct is done after |
||
467 | // Set $origin_type, origin_id and fk_project |
||
468 | $fk_project = $this->fk_project; |
||
469 | if (!empty($this->origin_type)) { // This is set by caller for tracking reason |
||
470 | $origin_type = $this->origin_type; |
||
471 | $origin_id = $this->origin_id; |
||
472 | if (empty($fk_project) && $origin_type == 'project') { |
||
473 | $fk_project = $origin_id; |
||
474 | $origin_type = ''; |
||
475 | $origin_id = 0; |
||
476 | } |
||
477 | } else { |
||
478 | $fk_project = 0; |
||
479 | $origin_type = ''; |
||
480 | $origin_id = 0; |
||
481 | } |
||
482 | |||
483 | $sql = "INSERT INTO " . $this->db->prefix() . "stock_mouvement("; |
||
484 | $sql .= " datem, fk_product, batch, eatby, sellby,"; |
||
485 | $sql .= " fk_entrepot, value, type_mouvement, fk_user_author, label, inventorycode, price, fk_origin, origintype, fk_projet"; |
||
486 | $sql .= ")"; |
||
487 | $sql .= " VALUES ('" . $this->db->idate($this->datem) . "', " . ((int) $this->product_id) . ", "; |
||
488 | $sql .= " " . ($batch ? "'" . $this->db->escape($batch) . "'" : "null") . ", "; |
||
489 | $sql .= " " . ($eatby ? "'" . $this->db->idate($eatby) . "'" : "null") . ", "; |
||
490 | $sql .= " " . ($sellby ? "'" . $this->db->idate($sellby) . "'" : "null") . ", "; |
||
491 | $sql .= " " . ((int) $this->entrepot_id) . ", " . ((float) $this->qty) . ", " . ((int) $this->type) . ","; |
||
492 | $sql .= " " . ((int) $user->id) . ","; |
||
493 | $sql .= " '" . $this->db->escape($label) . "',"; |
||
494 | $sql .= " " . ($inventorycode ? "'" . $this->db->escape($inventorycode) . "'" : "null") . ","; |
||
495 | $sql .= " " . ((float) price2num($price)) . ","; |
||
496 | $sql .= " " . ((int) $origin_id) . ","; |
||
497 | $sql .= " '" . $this->db->escape($origin_type) . "',"; |
||
498 | $sql .= " " . ((int) $fk_project); |
||
499 | $sql .= ")"; |
||
500 | |||
501 | dol_syslog(get_class($this) . "::_create insert record into stock_mouvement", LOG_DEBUG); |
||
502 | $resql = $this->db->query($sql); |
||
503 | |||
504 | if ($resql) { |
||
505 | $mvid = $this->db->last_insert_id($this->db->prefix() . "stock_mouvement"); |
||
506 | $this->id = $mvid; |
||
507 | } else { |
||
508 | $this->error = $this->db->lasterror(); |
||
509 | $this->errors[] = $this->error; |
||
510 | $error = -1; |
||
511 | } |
||
512 | |||
513 | // Define current values for qty and pmp |
||
514 | $oldqty = $product->stock_reel; |
||
515 | $oldpmp = $product->pmp; |
||
516 | $oldqtywarehouse = 0; |
||
517 | |||
518 | // Test if there is already a record for couple (warehouse / product), so later we will make an update or create. |
||
519 | $alreadyarecord = 0; |
||
520 | if (!$error) { |
||
521 | $sql = "SELECT rowid, reel FROM " . $this->db->prefix() . "product_stock"; |
||
522 | $sql .= " WHERE fk_entrepot = " . ((int) $entrepot_id) . " AND fk_product = " . ((int) $fk_product); // This is a unique key |
||
523 | |||
524 | dol_syslog(get_class($this) . "::_create check if a record already exists in product_stock", LOG_DEBUG); |
||
525 | $resql = $this->db->query($sql); |
||
526 | if ($resql) { |
||
527 | $obj = $this->db->fetch_object($resql); |
||
528 | if ($obj) { |
||
529 | $alreadyarecord = 1; |
||
530 | $oldqtywarehouse = $obj->reel; |
||
531 | $fk_product_stock = $obj->rowid; |
||
532 | } |
||
533 | $this->db->free($resql); |
||
534 | } else { |
||
535 | $this->errors[] = $this->db->lasterror(); |
||
536 | $error = -2; |
||
537 | } |
||
538 | } |
||
539 | |||
540 | // Calculate new AWP (PMP) |
||
541 | $newpmp = 0; |
||
542 | if (!$error) { |
||
543 | if ($type == 0 || $type == 3) { |
||
544 | // After a stock increase |
||
545 | // Note: PMP is calculated on stock input only (type of movement = 0 or 3). If type == 0 or 3, qty should be > 0. |
||
546 | // Note: Price should always be >0 or 0. PMP should be always >0 (calculated on input) |
||
547 | if ($price > 0 || (getDolGlobalString('STOCK_UPDATE_AWP_EVEN_WHEN_ENTRY_PRICE_IS_NULL') && $price == 0 && in_array($this->origin_type, array('order_supplier', 'invoice_supplier')))) { |
||
548 | $oldqtytouse = ($oldqty >= 0 ? $oldqty : 0); |
||
549 | // We make a test on oldpmp>0 to avoid to use normal rule on old data with no pmp field defined |
||
550 | if ($oldpmp > 0) { |
||
551 | $newpmp = price2num((($oldqtytouse * $oldpmp) + ($qty * $price)) / ($oldqtytouse + $qty), 'MU'); |
||
552 | } else { |
||
553 | $newpmp = $price; // For this product, PMP was not yet set. We set it to input price. |
||
554 | } |
||
555 | //print "oldqtytouse=".$oldqtytouse." oldpmp=".$oldpmp." oldqtywarehousetouse=".$oldqtywarehousetouse." "; |
||
556 | //print "qty=".$qty." newpmp=".$newpmp; |
||
557 | //exit; |
||
558 | } else { |
||
559 | $newpmp = $oldpmp; |
||
560 | } |
||
561 | } else { |
||
562 | // ($type == 1 || $type == 2) |
||
563 | // -> After a stock decrease, we don't change value of the AWP/PMP of a product. |
||
564 | // else |
||
565 | // Type of movement unknown |
||
566 | $newpmp = $oldpmp; |
||
567 | } |
||
568 | } |
||
569 | // Update stock quantity |
||
570 | if (!$error) { |
||
571 | if ($alreadyarecord > 0) { |
||
572 | $sql = "UPDATE " . $this->db->prefix() . "product_stock SET reel = " . ((float) $oldqtywarehouse + (float) $qty); |
||
573 | $sql .= " WHERE fk_entrepot = " . ((int) $entrepot_id) . " AND fk_product = " . ((int) $fk_product); |
||
574 | } else { |
||
575 | $sql = "INSERT INTO " . $this->db->prefix() . "product_stock"; |
||
576 | $sql .= " (reel, fk_entrepot, fk_product) VALUES "; |
||
577 | $sql .= " (" . ((float) $qty) . ", " . ((int) $entrepot_id) . ", " . ((int) $fk_product) . ")"; |
||
578 | } |
||
579 | |||
580 | dol_syslog(get_class($this) . "::_create update stock value", LOG_DEBUG); |
||
581 | $resql = $this->db->query($sql); |
||
582 | if (!$resql) { |
||
583 | $this->errors[] = $this->db->lasterror(); |
||
584 | $error = -3; |
||
585 | } elseif (empty($fk_product_stock)) { |
||
586 | $fk_product_stock = $this->db->last_insert_id($this->db->prefix() . "product_stock"); |
||
587 | } |
||
588 | } |
||
589 | |||
590 | // Update detail of stock for the lot. |
||
591 | if (!$error && isModEnabled('productbatch') && (($product->hasbatch() && !$skip_batch) || $force_update_batch)) { |
||
592 | if ($id_product_batch > 0) { |
||
593 | $result = $this->createBatch($id_product_batch, $qty); |
||
594 | if ($result == -2 && $fk_product_stock > 0) { // The entry for this product batch does not exists anymore, bu we already have a llx_product_stock, so we recreate the batch entry in product_batch |
||
595 | $param_batch = array('fk_product_stock' => $fk_product_stock, 'batchnumber' => $batch); |
||
596 | $result = $this->createBatch($param_batch, $qty); |
||
597 | } |
||
598 | } else { |
||
599 | $param_batch = array('fk_product_stock' => $fk_product_stock, 'batchnumber' => $batch); |
||
600 | $result = $this->createBatch($param_batch, $qty); |
||
601 | } |
||
602 | if ($result < 0) { |
||
603 | $error++; |
||
604 | } |
||
605 | } |
||
606 | |||
607 | // Update PMP and denormalized value of stock qty at product level |
||
608 | if (!$error) { |
||
609 | $newpmp = price2num($newpmp, 'MU'); |
||
610 | |||
611 | // $sql = "UPDATE ".$this->db->prefix()."product SET pmp = ".$newpmp.", stock = ".$this->db->ifsql("stock IS NULL", 0, "stock") . " + ".$qty; |
||
612 | // $sql.= " WHERE rowid = ".((int) $fk_product); |
||
613 | // Update pmp + denormalized fields because we change content of produt_stock. Warning: Do not use "SET p.stock", does not works with pgsql |
||
614 | $sql = "UPDATE " . $this->db->prefix() . "product as p SET pmp = " . ((float) $newpmp) . ","; |
||
615 | $sql .= " stock=(SELECT SUM(ps.reel) FROM " . $this->db->prefix() . "product_stock as ps WHERE ps.fk_product = p.rowid)"; |
||
616 | $sql .= " WHERE rowid = " . ((int) $fk_product); |
||
617 | |||
618 | dol_syslog(get_class($this) . "::_create update AWP", LOG_DEBUG); |
||
619 | $resql = $this->db->query($sql); |
||
620 | if (!$resql) { |
||
621 | $this->errors[] = $this->db->lasterror(); |
||
622 | $error = -4; |
||
623 | } |
||
624 | } |
||
625 | |||
626 | if (empty($donotcleanemptylines)) { |
||
627 | // If stock is now 0, we can remove entry into llx_product_stock, but only if there is no child lines into llx_product_batch (detail of batch, because we can imagine |
||
628 | // having a lot1/qty=X and lot2/qty=-X, so 0 but we must not loose repartition of different lot. |
||
629 | $sql = "DELETE FROM " . $this->db->prefix() . "product_stock WHERE reel = 0 AND rowid NOT IN (SELECT fk_product_stock FROM " . $this->db->prefix() . "product_batch as pb)"; |
||
630 | $resql = $this->db->query($sql); |
||
631 | // We do not test error, it can fails if there is child in batch details |
||
632 | } |
||
633 | } |
||
634 | |||
635 | // Add movement for sub products (recursive call) |
||
636 | if (!$error && getDolGlobalString('PRODUIT_SOUSPRODUITS') && !getDolGlobalString('INDEPENDANT_SUBPRODUCT_STOCK') && empty($disablestockchangeforsubproduct)) { |
||
637 | $error = $this->_createSubProduct($user, $fk_product, $entrepot_id, $qty, $type, 0, $label, $inventorycode, $datem); // we use 0 as price, because AWP must not change for subproduct |
||
638 | } |
||
639 | |||
640 | if ($movestock && !$error) { |
||
641 | // Call trigger |
||
642 | $result = $this->call_trigger('STOCK_MOVEMENT', $user); |
||
643 | if ($result < 0) { |
||
644 | $error++; |
||
645 | } |
||
646 | // End call triggers |
||
647 | // Check unicity for serial numbered equipment once all movement were done. |
||
648 | if (!$error && isModEnabled('productbatch') && $product->hasbatch() && !$skip_batch) { |
||
649 | if ($product->status_batch == 2 && $qty > 0) { // We check only if we increased qty |
||
650 | if ($this->getBatchCount($fk_product, $batch) > 1) { |
||
651 | $error++; |
||
652 | $this->errors[] = $langs->trans("TooManyQtyForSerialNumber", $product->ref, $batch); |
||
653 | } |
||
654 | } |
||
655 | } |
||
656 | } |
||
657 | |||
658 | if (!$error) { |
||
659 | $this->db->commit(); |
||
660 | return $mvid; |
||
661 | } else { |
||
662 | $this->db->rollback(); |
||
663 | dol_syslog(get_class($this) . "::_create error code=" . $error, LOG_ERR); |
||
664 | return -6; |
||
665 | } |
||
1323 |
This property has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.