1<?php 2/* Copyright (C) 2007-2019 Laurent Destailleur <eldy@users.sourceforge.net> 3 * Copyright (C) 2014-2016 Juanjo Menent <jmenent@2byte.es> 4 * Copyright (C) 2015 Florian Henry <florian.henry@open-concept.pro> 5 * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <https://www.gnu.org/licenses/>. 19 */ 20 21/** 22 * \file product/inventory/class/inventory.class.php 23 * \ingroup inventory 24 * \brief This file is a CRUD class file for Inventory (Create/Read/Update/Delete) 25 */ 26 27// Put here all includes required by your class file 28require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; 29//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; 30//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; 31 32/** 33 * Class for Inventory 34 */ 35class Inventory extends CommonObject 36{ 37 /** 38 * @var string ID to identify managed object 39 */ 40 public $element = 'inventory'; 41 42 /** 43 * @var string Name of table without prefix where object is stored 44 */ 45 public $table_element = 'inventory'; 46 47 /** 48 * @var array Does inventory support multicompany module ? 0=No test on entity, 1=Test with field entity, 2=Test with link by societe 49 */ 50 public $ismultientitymanaged = 1; 51 52 /** 53 * @var int Does object support extrafields ? 0=No, 1=Yes 54 */ 55 public $isextrafieldmanaged = 1; 56 57 /** 58 * @var string String with name of icon for inventory 59 */ 60 public $picto = 'stock'; 61 62 const STATUS_DRAFT = 0; 63 const STATUS_VALIDATED = 1; 64 const STATUS_RECORDED = 2; 65 const STATUS_CANCELED = 9; 66 67 /** 68 * 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') 69 * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" 70 * 'label' the translation key. 71 * 'enabled' is a condition when the field must be managed. 72 * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) 73 * 'noteditable' says if field is not editable (1 or 0) 74 * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). 75 * 'default' is a default value for creation (can still be replaced by the global setup of default values) 76 * 'index' if we want an index in database. 77 * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). 78 * 'position' is the sort order of field. 79 * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. 80 * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8). 81 * 'css' is the CSS style to use on field. For example: 'maxwidth200' 82 * 'help' is a string visible as a tooltip on field 83 * 'comment' is not used. You can store here any text of your choice. It is not used by application. 84 * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record 85 * 'arraykeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel") 86 */ 87 88 // BEGIN MODULEBUILDER PROPERTIES 89 /** 90 * @var array Array with all fields and their property 91 */ 92 public $fields = array( 93 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'visible'=>-1, 'enabled'=>1, 'position'=>1, 'notnull'=>1, 'index'=>1, 'comment'=>'Id',), 94 'ref' => array('type'=>'varchar(64)', 'label'=>'Ref', 'visible'=>1, 'enabled'=>1, 'position'=>10, 'notnull'=>1, 'index'=>1, 'searchall'=>1, 'comment'=>'Reference of object', 'css'=>'maxwidth200'), 95 'entity' => array('type'=>'integer', 'label'=>'Entity', 'visible'=>0, 'enabled'=>1, 'position'=>20, 'notnull'=>1, 'index'=>1,), 96 'title' => array('type'=>'varchar(255)', 'label'=>'Label', 'visible'=>1, 'enabled'=>1, 'position'=>25, 'css'=>'minwidth300'), 97 'fk_warehouse' => array('type'=>'integer:Entrepot:product/stock/class/entrepot.class.php', 'label'=>'Warehouse', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'index'=>1, 'help'=>'InventoryForASpecificWarehouse'), 98 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php', 'label'=>'Product', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'InventoryForASpecificProduct'), 99 'date_inventory' => array('type'=>'date', 'label'=>'DateValue', 'visible'=>1, 'enabled'=>1, 'position'=>35), 100 101 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>500), 102 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>501), 103 'date_validation' => array('type'=>'datetime', 'label'=>'DateValidation', 'visible'=>-2, 'enabled'=>1, 'position'=>502), 104 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>510, 'foreignkey'=>'user.rowid'), 105 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-2, 'notnull'=>-1, 'position'=>511), 106 'fk_user_valid' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserValidation', 'visible'=>-2, 'enabled'=>1, 'position'=>512), 107 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'notnull'=>-1, 'index'=>0, 'position'=>1000), 108 109 'status' => array('type'=>'integer', 'label'=>'Status', 'visible'=>4, 'enabled'=>1, 'position'=>1000, 'notnull'=>1, 'default'=>0, 'index'=>1, 'arrayofkeyval'=>array(0=>'Draft', 1=>'Validated', 2=>'Recorded', 9=>'Canceled')) 110 ); 111 112 /** 113 * @var int ID 114 */ 115 public $rowid; 116 117 /** 118 * @var string Ref 119 */ 120 public $ref; 121 122 /** 123 * @var int Entity 124 */ 125 public $entity; 126 127 /** 128 * @var int ID 129 */ 130 public $fk_warehouse; 131 132 /** 133 * @var int ID 134 */ 135 public $fk_product; 136 137 public $date_inventory; 138 public $title; 139 140 /** 141 * @var int Status 142 */ 143 public $status; 144 145 /** 146 * @var integer|string date_creation 147 */ 148 public $date_creation; 149 150 /** 151 * @var integer|string date_validation 152 */ 153 public $date_validation; 154 155 156 public $tms; 157 158 /** 159 * @var int ID 160 */ 161 public $fk_user_creat; 162 163 /** 164 * @var int ID 165 */ 166 public $fk_user_modif; 167 168 /** 169 * @var int ID 170 */ 171 public $fk_user_valid; 172 173 /** 174 * @var string import key 175 */ 176 public $import_key; 177 // END MODULEBUILDER PROPERTIES 178 179 180 181 // If this object has a subtable with lines 182 183 /** 184 * @var string Name of subtable line 185 */ 186 public $table_element_line = 'inventorydet'; 187 188 /** 189 * @var string Field with ID of parent key if this field has a parent 190 */ 191 public $fk_element = 'fk_inventory'; 192 193 /** 194 * @var string Name of subtable class that manage subtable lines 195 */ 196 public $class_element_line = 'Inventoryline'; 197 198 /** 199 * @var array List of child tables. To test if we can delete object. 200 */ 201 protected $childtables = array(); 202 /** 203 * @var array List of child tables. To know object to delete on cascade. 204 */ 205 protected $childtablesoncascade = array('inventorydet'); 206 207 /** 208 * @var InventoryLine[] Array of subtable lines 209 */ 210 public $lines = array(); 211 212 213 214 /** 215 * Constructor 216 * 217 * @param DoliDb $db Database handler 218 */ 219 public function __construct(DoliDB $db) 220 { 221 global $conf; 222 223 $this->db = $db; 224 225 if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID)) $this->fields['rowid']['visible'] = 0; 226 if (empty($conf->multicompany->enabled)) $this->fields['entity']['enabled'] = 0; 227 } 228 229 230 /** 231 * Create object into database 232 * 233 * @param User $user User that creates 234 * @param bool $notrigger false=launch triggers after, true=disable triggers 235 * @return int <0 if KO, Id of created object if OK 236 */ 237 public function create(User $user, $notrigger = false) 238 { 239 $result = $this->createCommon($user, $notrigger); 240 241 return $result; 242 } 243 244 /** 245 * Validate inventory (start it) 246 * 247 * @param User $user User that creates 248 * @param bool $notrigger false=launch triggers after, true=disable triggers 249 * @return int <0 if KO, Id of created object if OK 250 */ 251 public function validate(User $user, $notrigger = false) 252 { 253 $this->db->begin(); 254 255 $result = 0; 256 257 if ($this->status == self::STATUS_DRAFT) { 258 // Delete inventory 259 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'inventorydet WHERE fk_inventory = '.$this->id; 260 $resql = $this->db->query($sql); 261 if (!$resql) { 262 $this->error = $this->db->lasterror(); 263 $this->db->rollback(); 264 return -1; 265 } 266 267 // Scan existing stock to prefill the inventory 268 $sql = 'SELECT ps.rowid, ps.fk_entrepot as fk_warehouse, ps.fk_product, ps.reel,'; 269 $sql .= ' pb.batch, pb.qty'; 270 $sql .= ' FROM '.MAIN_DB_PREFIX.'product_stock as ps'; 271 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_batch as pb ON pb.fk_product_stock = ps.rowid,'; 272 $sql .= ' '.MAIN_DB_PREFIX.'product as p, '.MAIN_DB_PREFIX.'entrepot as e'; 273 $sql .= ' WHERE p.entity IN ('.getEntity('product').')'; 274 $sql .= ' AND ps.fk_product = p.rowid AND ps.fk_entrepot = e.rowid'; 275 if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) $sql .= " AND p.fk_product_type = 0"; 276 if ($this->fk_product > 0) $sql .= ' AND ps.fk_product = '.$this->fk_product; 277 if ($this->fk_warehouse > 0) $sql .= ' AND ps.fk_entrepot = '.$this->fk_warehouse; 278 279 $inventoryline = new InventoryLine($this->db); 280 281 $resql = $this->db->query($sql); 282 if ($resql) 283 { 284 $num = $this->db->num_rows($resql); 285 286 $i = 0; 287 while ($i < $num) 288 { 289 $obj = $this->db->fetch_object($resql); 290 291 $inventoryline->fk_inventory = $this->id; 292 $inventoryline->fk_warehouse = $obj->fk_warehouse; 293 $inventoryline->fk_product = $obj->fk_product; 294 $inventoryline->batch = $obj->batch; 295 $inventoryline->qty_stock = ($obj->batch ? $obj->qty : $obj->reel); // If there is batch detail, we take qty for batch, else global qty 296 $inventoryline->datec = dol_now(); 297 298 $resultline = $inventoryline->create($user); 299 if ($resultline <= 0) { 300 $this->error = $inventoryline->error; 301 $this->errors = $inventoryline->errors; 302 $result = -1; 303 break; 304 } 305 306 $i++; 307 } 308 } else { 309 $result = -1; 310 $this->error = $this->db->lasterror(); 311 } 312 } 313 314 if ($result >= 0) { 315 $result = $this->setStatut($this::STATUS_VALIDATED, null, '', 'INVENTORY_VALIDATED'); 316 } 317 318 if ($result > 0) { 319 $this->db->commit(); 320 } else { 321 $this->db->rollback(); 322 } 323 } 324 325 /** 326 * Go back to draft 327 * 328 * @param User $user User that creates 329 * @param bool $notrigger false=launch triggers after, true=disable triggers 330 * @return int <0 if KO, Id of created object if OK 331 */ 332 public function setDraft(User $user, $notrigger = false) 333 { 334 $this->db->begin(); 335 336 // Delete inventory 337 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.'inventorydet WHERE fk_inventory = '.$this->id; 338 $resql = $this->db->query($sql); 339 if (!$resql) { 340 $this->error = $this->db->lasterror(); 341 $this->db->rollback(); 342 return -1; 343 } 344 345 $result = $this->setStatut($this::STATUS_DRAFT, null, '', 'INVENTORY_DRAFT'); 346 347 if ($result > 0) { 348 $this->db->commit(); 349 } else { 350 $this->db->rollback(); 351 } 352 } 353 354 /** 355 * Clone and object into another one 356 * 357 * @param User $user User that creates 358 * @param int $fromid Id of object to clone 359 * @return mixed New object created, <0 if KO 360 */ 361 public function createFromClone(User $user, $fromid) 362 { 363 global $hookmanager, $langs; 364 $error = 0; 365 366 dol_syslog(__METHOD__, LOG_DEBUG); 367 368 $object = new self($this->db); 369 370 $this->db->begin(); 371 372 // Load source object 373 $object->fetchCommon($fromid); 374 // Reset some properties 375 unset($object->id); 376 unset($object->fk_user_creat); 377 unset($object->import_key); 378 379 // Clear fields 380 $object->ref = "copy_of_".$object->ref; 381 $object->title = $langs->trans("CopyOf")." ".$object->title; 382 // ... 383 384 // Create clone 385 $object->context['createfromclone'] = 'createfromclone'; 386 $result = $object->createCommon($user); 387 if ($result < 0) { 388 $error++; 389 $this->error = $object->error; 390 $this->errors = $object->errors; 391 } 392 393 unset($object->context['createfromclone']); 394 395 // End 396 if (!$error) { 397 $this->db->commit(); 398 return $object; 399 } else { 400 $this->db->rollback(); 401 return -1; 402 } 403 } 404 405 /** 406 * Load object in memory from the database 407 * 408 * @param int $id Id object 409 * @param string $ref Ref 410 * @return int <0 if KO, 0 if not found, >0 if OK 411 */ 412 public function fetch($id, $ref = null) 413 { 414 $result = $this->fetchCommon($id, $ref); 415 //if ($result > 0 && ! empty($this->table_element_line)) $this->fetchLines(); 416 return $result; 417 } 418 419 /** 420 * Load object lines in memory from the database 421 * 422 * @return int <0 if KO, 0 if not found, >0 if OK 423 */ 424 /*public function fetchLines() 425 { 426 $this->lines=array(); 427 428 // Load lines with object MyObjectLine 429 430 return count($this->lines)?1:0; 431 }*/ 432 433 /** 434 * Update object into database 435 * 436 * @param User $user User that modifies 437 * @param bool $notrigger false=launch triggers after, true=disable triggers 438 * @return int <0 if KO, >0 if OK 439 */ 440 public function update(User $user, $notrigger = false) 441 { 442 return $this->updateCommon($user, $notrigger); 443 } 444 445 /** 446 * Delete object in database 447 * 448 * @param User $user User that deletes 449 * @param bool $notrigger false=launch triggers after, true=disable triggers 450 * @return int <0 if KO, >0 if OK 451 */ 452 public function delete(User $user, $notrigger = false) 453 { 454 return $this->deleteCommon($user, $notrigger); 455 } 456 457 /** 458 * Delete a line of object in database 459 * 460 * @param User $user User that delete 461 * @param int $idline Id of line to delete 462 * @param bool $notrigger false=launch triggers after, true=disable triggers 463 * @return int >0 if OK, <0 if KO 464 */ 465 public function deleteLine(User $user, $idline, $notrigger = false) 466 { 467 if ($this->status < 0) 468 { 469 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus'; 470 return -2; 471 } 472 473 return $this->deleteLineCommon($user, $idline, $notrigger); 474 } 475 476 /** 477 * Return a link to the object card (with optionaly the picto) 478 * 479 * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) 480 * @param string $option On what the link point to 481 * @param int $notooltip 1=Disable tooltip 482 * @param string $morecss Add more css on link 483 * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking 484 * @return string String with URL 485 */ 486 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) 487 { 488 global $db, $conf, $langs; 489 global $dolibarr_main_authentication, $dolibarr_main_demo; 490 global $menumanager; 491 492 if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips 493 494 $result = ''; 495 $companylink = ''; 496 497 $label = '<u>'.$langs->trans("Inventory").'</u>'; 498 $label .= '<br>'; 499 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref; 500 501 $url = dol_buildpath('/product/inventory/card.php', 1).'?id='.$this->id; 502 503 $linkclose = ''; 504 if (empty($notooltip)) 505 { 506 if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) 507 { 508 $label = $langs->trans("ShowInventory"); 509 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; 510 } 511 $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; 512 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"'; 513 } else $linkclose = ($morecss ? ' class="'.$morecss.'"' : ''); 514 515 $linkstart = '<a href="'.$url.'"'; 516 $linkstart .= $linkclose.'>'; 517 $linkend = '</a>'; 518 519 $result .= $linkstart; 520 if ($withpicto) $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); 521 if ($withpicto != 2) $result .= $this->ref; 522 $result .= $linkend; 523 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); 524 525 return $result; 526 } 527 528 /** 529 * Retourne le libelle du status d'un user (actif, inactif) 530 * 531 * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto 532 * @return string Label of status 533 */ 534 public function getLibStatut($mode = 0) 535 { 536 return $this->LibStatut($this->status, $mode); 537 } 538 539 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps 540 /** 541 * Return the status 542 * 543 * @param int $status Id status 544 * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 5=Long label + Picto, 6=Long label + Picto 545 * @return string Label of status 546 */ 547 public static function LibStatut($status, $mode = 0) 548 { 549 // phpcs:enable 550 global $langs; 551 552 $labelStatus = array(); 553 $labelStatus[self::STATUS_DRAFT] = $langs->trans('Draft'); 554 $labelStatus[self::STATUS_VALIDATED] = $langs->trans('Validated').' ('.$langs->trans('Started').')'; 555 $labelStatus[self::STATUS_CANCELED] = $langs->trans('Canceled'); 556 $labelStatusShort[self::STATUS_DRAFT] = $langs->trans('Draft'); 557 $labelStatusShort[self::STATUS_VALIDATED] = $langs->trans('Started'); 558 $labelStatusShort[self::STATUS_CANCELED] = $langs->trans('Canceled'); 559 560 return dolGetStatus($labelStatus[$status], $labelStatusShort[$status], '', 'status'.$status, $mode); 561 } 562 563 /** 564 * Charge les informations d'ordre info dans l'objet commande 565 * 566 * @param int $id Id of order 567 * @return void 568 */ 569 public function info($id) 570 { 571 $sql = 'SELECT rowid, date_creation as datec, tms as datem,'; 572 $sql .= ' fk_user_creat, fk_user_modif'; 573 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; 574 $sql .= ' WHERE t.rowid = '.$id; 575 $result = $this->db->query($sql); 576 if ($result) 577 { 578 if ($this->db->num_rows($result)) 579 { 580 $obj = $this->db->fetch_object($result); 581 $this->id = $obj->rowid; 582 if ($obj->fk_user_author) 583 { 584 $cuser = new User($this->db); 585 $cuser->fetch($obj->fk_user_author); 586 $this->user_creation = $cuser; 587 } 588 589 if ($obj->fk_user_valid) 590 { 591 $vuser = new User($this->db); 592 $vuser->fetch($obj->fk_user_valid); 593 $this->user_validation = $vuser; 594 } 595 596 if ($obj->fk_user_cloture) 597 { 598 $cluser = new User($this->db); 599 $cluser->fetch($obj->fk_user_cloture); 600 $this->user_cloture = $cluser; 601 } 602 603 $this->date_creation = $this->db->jdate($obj->datec); 604 $this->date_modification = $this->db->jdate($obj->datem); 605 $this->date_validation = $this->db->jdate($obj->datev); 606 } 607 608 $this->db->free($result); 609 } else { 610 dol_print_error($this->db); 611 } 612 } 613 614 /** 615 * Initialise object with example values 616 * Id must be 0 if object instance is a specimen 617 * 618 * @return void 619 */ 620 public function initAsSpecimen() 621 { 622 $this->initAsSpecimenCommon(); 623 } 624} 625 626/** 627 * Class InventoryLine 628 */ 629class InventoryLine extends CommonObjectLine 630{ 631 /** 632 * @var string ID to identify managed object 633 */ 634 public $element = 'inventoryline'; 635 636 /** 637 * @var string Name of table without prefix where object is stored 638 */ 639 public $table_element = 'inventorydet'; 640 641 /** 642 * @var array Does inventory support multicompany module ? 0=No test on entity, 1=Test with field entity, 2=Test with link by societe 643 */ 644 public $ismultientitymanaged = 0; 645 646 /** 647 * @var int Does object support extrafields ? 0=No, 1=Yes 648 */ 649 public $isextrafieldmanaged = 0; 650 651 /** 652 * @var string String with name of icon for inventory 653 */ 654 public $picto = 'stock'; 655 656 /** 657 * 'type' if the field format. 658 * 'label' the translation key. 659 * 'enabled' is a condition when the field must be managed. 660 * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only. Using a negative value means field is not shown by default on list but can be selected for viewing) 661 * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). 662 * 'index' if we want an index in database. 663 * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). 664 * 'position' is the sort order of field. 665 * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. 666 * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8). 667 * 'help' is a string visible as a tooltip on field 668 * 'comment' is not used. You can store here any text of your choice. It is not used by application. 669 * 'default' is a default value for creation (can still be replaced by the global setup of default values) 670 * 'showoncombobox' if field must be shown into the label of combobox 671 */ 672 673 // BEGIN MODULEBUILDER PROPERTIES 674 /** 675 * @var array Array with all fields and their property 676 */ 677 public $fields = array( 678 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'visible'=>-1, 'enabled'=>1, 'position'=>1, 'notnull'=>1, 'index'=>1, 'comment'=>'Id',), 679 'fk_inventory' => array('type'=>'integer:Inventory:product/inventory/class/inventory.class.php', 'label'=>'Inventory', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'index'=>1, 'help'=>'LinkToInventory'), 680 'fk_warehouse' => array('type'=>'integer:Entrepot:product/stock/class/entrepot.class.php', 'label'=>'Warehouse', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'index'=>1, 'help'=>'LinkToThirparty'), 681 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php', 'label'=>'Product', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'LinkToProduct'), 682 'batch' => array('type'=>'string', 'label'=>'Batch', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'LinkToProduct'), 683 'datec' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>500), 684 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>501), 685 'qty_stock' => array('type'=>'double', 'label'=>'QtyFound', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'Qty we found/want (to define during draft edition)'), 686 'qty_view' => array('type'=>'double', 'label'=>'QtyBefore', 'visible'=>1, 'enabled'=>1, 'position'=>33, 'index'=>1, 'help'=>'Qty before (filled once movements are validated)'), 687 'qty_regulated' => array('type'=>'double', 'label'=>'QtyDelta', 'visible'=>1, 'enabled'=>1, 'position'=>34, 'index'=>1, 'help'=>'Qty aadded or removed (filled once movements are validated)'), 688 ); 689 690 /** 691 * @var int ID 692 */ 693 public $rowid; 694 695 public $fk_inventory; 696 public $fk_warehouse; 697 public $fk_product; 698 public $batch; 699 public $datec; 700 public $tms; 701 public $qty_stock; 702 public $qty_view; 703 public $qty_regulated; 704 705 706 /** 707 * Create object in database 708 * 709 * @param User $user User that creates 710 * @param bool $notrigger false=launch triggers after, true=disable triggers 711 * @return int <0 if KO, >0 if OK 712 */ 713 public function create(User $user, $notrigger = false) 714 { 715 return $this->createCommon($user, $notrigger); 716 } 717 718 /** 719 * Load object in memory from the database 720 * 721 * @param int $id Id object 722 * @param string $ref Ref 723 * @return int <0 if KO, 0 if not found, >0 if OK 724 */ 725 public function fetch($id, $ref = null) 726 { 727 $result = $this->fetchCommon($id, $ref); 728 //if ($result > 0 && ! empty($this->table_element_line)) $this->fetchLines(); 729 return $result; 730 } 731 732 /** 733 * Update object into database 734 * 735 * @param User $user User that modifies 736 * @param bool $notrigger false=launch triggers after, true=disable triggers 737 * @return int <0 if KO, >0 if OK 738 */ 739 public function update(User $user, $notrigger = false) 740 { 741 return $this->updateCommon($user, $notrigger); 742 } 743 744 /** 745 * Delete object in database 746 * 747 * @param User $user User that deletes 748 * @param bool $notrigger false=launch triggers after, true=disable triggers 749 * @return int <0 if KO, >0 if OK 750 */ 751 public function delete(User $user, $notrigger = false) 752 { 753 return $this->deleteCommon($user, $notrigger); 754 //return $this->deleteCommon($user, $notrigger, 1); 755 } 756} 757