Total Complexity | 129 |
Total Lines | 1016 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like Entrepot often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Entrepot, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
41 | class Entrepot extends CommonObject |
||
42 | { |
||
43 | /** |
||
44 | * @var string ID to identify managed object |
||
45 | */ |
||
46 | public $element = 'stock'; |
||
47 | |||
48 | /** |
||
49 | * @var string Name of table without prefix where object is stored |
||
50 | */ |
||
51 | public $table_element = 'entrepot'; |
||
52 | |||
53 | /** |
||
54 | * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png |
||
55 | */ |
||
56 | public $picto = 'stock'; |
||
57 | |||
58 | /** |
||
59 | * @var string Label |
||
60 | * @deprecated |
||
61 | * @see $label |
||
62 | */ |
||
63 | public $libelle; |
||
64 | |||
65 | /** |
||
66 | * @var string Label |
||
67 | */ |
||
68 | public $label; |
||
69 | |||
70 | /** |
||
71 | * @var string description |
||
72 | */ |
||
73 | public $description; |
||
74 | |||
75 | public $statut; |
||
76 | |||
77 | /** |
||
78 | * @var string Place |
||
79 | */ |
||
80 | public $lieu; |
||
81 | |||
82 | /** |
||
83 | * @var string Address |
||
84 | */ |
||
85 | public $address; |
||
86 | |||
87 | /** |
||
88 | * @var string Zipcode |
||
89 | */ |
||
90 | public $zip; |
||
91 | |||
92 | /** |
||
93 | * @var string Town |
||
94 | */ |
||
95 | public $town; |
||
96 | |||
97 | /** |
||
98 | * @var string Phone |
||
99 | */ |
||
100 | public $phone; |
||
101 | |||
102 | /** |
||
103 | * @var string Fax |
||
104 | */ |
||
105 | public $fax; |
||
106 | |||
107 | /** |
||
108 | * @var int ID of parent |
||
109 | */ |
||
110 | public $fk_parent; |
||
111 | |||
112 | /** |
||
113 | * @var int ID of project |
||
114 | */ |
||
115 | public $fk_project; |
||
116 | |||
117 | /** |
||
118 | * @var int Warehouse usage ID |
||
119 | */ |
||
120 | public $warehouse_usage; |
||
121 | |||
122 | /** |
||
123 | * 'type' field format: |
||
124 | * 'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]', |
||
125 | * 'select' (list of values are in 'options'), |
||
126 | * 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter[:CategoryIdType[:CategoryIdList[:SortField]]]]]]', |
||
127 | * 'chkbxlst:...', |
||
128 | * 'varchar(x)', |
||
129 | * 'text', 'text:none', 'html', |
||
130 | * 'double(24,8)', 'real', 'price', 'stock', |
||
131 | * 'date', 'datetime', 'timestamp', 'duration', |
||
132 | * 'boolean', 'checkbox', 'radio', 'array', |
||
133 | * 'mail', 'phone', 'url', 'password', 'ip' |
||
134 | * Note: Filter must be a Dolibarr Universal Filter syntax string. Example: "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.status:!=:0) or (t.nature:is:NULL)" |
||
135 | * 'label' the translation key. |
||
136 | * 'picto' is code of a picto to show before value in forms |
||
137 | * 'enabled' is a condition when the field must be managed (Example: 1 or 'getDolGlobalInt("MY_SETUP_PARAM")' or 'isModEnabled("multicurrency")' ...) |
||
138 | * 'position' is the sort order of field. |
||
139 | * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). |
||
140 | * '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) |
||
141 | * 'noteditable' says if field is not editable (1 or 0) |
||
142 | * 'alwayseditable' says if field can be modified also when status is not draft ('1' or '0') |
||
143 | * 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. |
||
144 | * 'index' if we want an index in database. |
||
145 | * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...). |
||
146 | * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. |
||
147 | * 'isameasure' must be set to 1 or 2 if field can be used for measure. Field type must be summable like integer or double(24,8). Use 1 in most cases, or 2 if you don't want to see the column total into list (for example for percentage) |
||
148 | * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200' |
||
149 | * 'help' and 'helplist' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click. |
||
150 | * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record |
||
151 | * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. |
||
152 | * 'arrayofkeyval' to set a list of values if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel"). Note that type can be 'integer' or 'varchar' |
||
153 | * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. |
||
154 | * 'comment' is not used. You can store here any text of your choice. It is not used by application. |
||
155 | * 'validate' is 1 if you need to validate the field with $this->validateField(). Need MAIN_ACTIVATE_VALIDATION_RESULT. |
||
156 | * 'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto after value) |
||
157 | * |
||
158 | * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. |
||
159 | */ |
||
160 | |||
161 | // BEGIN MODULEBUILDER PROPERTIES |
||
162 | /** |
||
163 | * @var array<string,array{type:string,label:string,enabled:int<0,2>|string,position:int,notnull?:int,visible:int,noteditable?:int,default?:string,index?:int,foreignkey?:string,searchall?:int,isameasure?:int,css?:string,csslist?:string,help?:string,showoncombobox?:int,disabled?:int,arrayofkeyval?:array<int,string>,comment?:string}> Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. |
||
|
|||
164 | */ |
||
165 | public $fields = array( |
||
166 | 'rowid' => array('type' => 'integer', 'label' => 'ID', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'position' => 10), |
||
167 | 'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 1, 'visible' => 0, 'default' => '1', 'notnull' => 1, 'index' => 1, 'position' => 15), |
||
168 | 'ref' => array('type' => 'varchar(255)', 'label' => 'Ref', 'enabled' => 1, 'visible' => 1, 'showoncombobox' => 1, 'position' => 25, 'searchall' => 1), |
||
169 | 'description' => array('type' => 'text', 'label' => 'Description', 'enabled' => 1, 'visible' => -2, 'position' => 35, 'searchall' => 1), |
||
170 | 'lieu' => array('type' => 'varchar(64)', 'label' => 'LocationSummary', 'enabled' => 1, 'visible' => 1, 'position' => 40, 'showoncombobox' => 2, 'searchall' => 1), |
||
171 | 'fk_parent' => array('type' => 'integer:Entrepot:product/stock/class/entrepot.class.php:1:((statut:=:1) AND (entity:IN:__SHARED_ENTITIES__))', 'label' => 'ParentWarehouse', 'enabled' => 1, 'visible' => -2, 'position' => 41), |
||
172 | 'fk_project' => array('type' => 'integer:Project:projet/class/project.class.php:1:(fk_statut:=:1)', 'label' => 'Project', 'enabled' => '$conf->project->enabled', 'visible' => -1, 'position' => 42), |
||
173 | 'address' => array('type' => 'varchar(255)', 'label' => 'Address', 'enabled' => 1, 'visible' => -2, 'position' => 45, 'searchall' => 1), |
||
174 | 'zip' => array('type' => 'varchar(10)', 'label' => 'Zip', 'enabled' => 1, 'visible' => -2, 'position' => 50, 'searchall' => 1), |
||
175 | 'town' => array('type' => 'varchar(50)', 'label' => 'Town', 'enabled' => 1, 'visible' => -2, 'position' => 55, 'searchall' => 1), |
||
176 | 'fk_departement' => array('type' => 'integer', 'label' => 'State', 'enabled' => 1, 'visible' => 0, 'position' => 60), |
||
177 | 'fk_pays' => array('type' => 'integer:Ccountry:core/class/ccountry.class.php', 'label' => 'Country', 'enabled' => 1, 'visible' => -1, 'position' => 65), |
||
178 | 'phone' => array('type' => 'varchar(20)', 'label' => 'Phone', 'enabled' => 1, 'visible' => -2, 'position' => 70, 'searchall' => 1), |
||
179 | 'fax' => array('type' => 'varchar(20)', 'label' => 'Fax', 'enabled' => 1, 'visible' => -2, 'position' => 75, 'searchall' => 1), |
||
180 | //'fk_user_author' =>array('type'=>'integer', 'label'=>'Fk user author', 'enabled'=>1, 'visible'=>-2, 'position'=>82), |
||
181 | 'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -2, 'position' => 300), |
||
182 | 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 301), |
||
183 | 'warehouse_usage' => array('type' => 'integer', 'label' => 'WarehouseUsage', 'enabled' => 'getDolGlobalInt("MAIN_FEATURES_LEVEL")', 'visible' => 1, 'position' => 400, 'default' => 1, 'arrayofkeyval' => array(1 => 'InternalWarehouse', 2 => 'ExternalWarehouse')), |
||
184 | //'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>1000), |
||
185 | //'model_pdf' =>array('type'=>'varchar(255)', 'label'=>'ModelPDF', 'enabled'=>1, 'visible'=>0, 'position'=>1010), |
||
186 | 'statut' => array('type' => 'tinyint(4)', 'label' => 'Status', 'enabled' => 1, 'visible' => 1, 'position' => 500, 'css' => 'minwidth50'), |
||
187 | ); |
||
188 | // END MODULEBUILDER PROPERTIES |
||
189 | |||
190 | |||
191 | /** |
||
192 | * Warehouse closed, inactive |
||
193 | */ |
||
194 | const STATUS_CLOSED = 0; |
||
195 | |||
196 | /** |
||
197 | * Warehouse open and any operations are allowed (customer shipping, supplier dispatch, internal stock transfers/corrections). |
||
198 | */ |
||
199 | const STATUS_OPEN_ALL = 1; |
||
200 | |||
201 | /** |
||
202 | * Warehouse open and only operations for stock transfers/corrections allowed (not for customer shipping and supplier dispatch). |
||
203 | */ |
||
204 | const STATUS_OPEN_INTERNAL = 2; |
||
205 | |||
206 | /** |
||
207 | * Warehouse open and any operations are allowed, but warehouse is not included into calculation of stock. |
||
208 | */ |
||
209 | const STATUS_OPENEXT_ALL = 3; // TODO Implement this |
||
210 | |||
211 | |||
212 | |||
213 | /** |
||
214 | * Constructor |
||
215 | * |
||
216 | * @param DoliDB $db Database handler |
||
217 | */ |
||
218 | public function __construct($db) |
||
219 | { |
||
220 | $this->db = $db; |
||
221 | |||
222 | $this->ismultientitymanaged = 1; |
||
223 | |||
224 | $this->labelStatus[self::STATUS_CLOSED] = 'Closed2'; |
||
225 | if (getDolGlobalString('ENTREPOT_EXTRA_STATUS')) { |
||
226 | $this->labelStatus[self::STATUS_OPEN_ALL] = 'OpenAnyMovement'; |
||
227 | $this->labelStatus[self::STATUS_OPEN_INTERNAL] = 'OpenInternal'; |
||
228 | } else { |
||
229 | $this->labelStatus[self::STATUS_OPEN_ALL] = 'Opened'; |
||
230 | } |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * Creation d'un entrepot en base |
||
235 | * |
||
236 | * @param User $user Object user that create the warehouse |
||
237 | * @param int $notrigger 0=launch triggers after, 1=disable triggers |
||
238 | * @return int Return >0 if OK, =<0 if KO |
||
239 | */ |
||
240 | public function create($user, $notrigger = 0) |
||
241 | { |
||
242 | global $conf; |
||
243 | |||
244 | $error = 0; |
||
245 | |||
246 | $this->label = trim($this->label); |
||
247 | |||
248 | // Error if label not defined |
||
249 | if ($this->label == '') { |
||
250 | $this->error = "ErrorFieldRequired"; |
||
251 | return 0; |
||
252 | } |
||
253 | |||
254 | $now = dol_now(); |
||
255 | |||
256 | $this->db->begin(); |
||
257 | |||
258 | $sql = "INSERT INTO " . $this->db->prefix() . "entrepot (ref, entity, datec, fk_user_author, fk_parent, fk_project)"; |
||
259 | $sql .= " VALUES ('" . $this->db->escape($this->label) . "', " . ((int) $conf->entity) . ", '" . $this->db->idate($now) . "', " . ((int) $user->id) . ", " . ($this->fk_parent > 0 ? ((int) $this->fk_parent) : "NULL") . ", " . ($this->fk_project > 0 ? ((int) $this->fk_project) : "NULL") . ")"; |
||
260 | |||
261 | dol_syslog(get_class($this) . "::create", LOG_DEBUG); |
||
262 | $result = $this->db->query($sql); |
||
263 | if ($result) { |
||
264 | $id = $this->db->last_insert_id($this->db->prefix() . "entrepot"); |
||
265 | if ($id > 0) { |
||
266 | $this->id = $id; |
||
267 | |||
268 | if (!$error) { |
||
269 | $result = $this->update($id, $user); |
||
270 | if ($result <= 0) { |
||
271 | $error++; |
||
272 | } |
||
273 | } |
||
274 | |||
275 | // Actions on extra fields |
||
276 | if (!$error) { |
||
277 | $result = $this->insertExtraFields(); |
||
278 | if ($result < 0) { |
||
279 | $error++; |
||
280 | } |
||
281 | } |
||
282 | |||
283 | if (!$error && !$notrigger) { |
||
284 | // Call triggers |
||
285 | $result = $this->call_trigger('WAREHOUSE_CREATE', $user); |
||
286 | if ($result < 0) { |
||
287 | $error++; |
||
288 | } |
||
289 | // End call triggers |
||
290 | } |
||
291 | |||
292 | if (!$error) { |
||
293 | $this->db->commit(); |
||
294 | return $id; |
||
295 | } else { |
||
296 | dol_syslog(get_class($this) . "::create return -3"); |
||
297 | $this->db->rollback(); |
||
298 | return -3; |
||
299 | } |
||
300 | } else { |
||
301 | $this->error = "Failed to get insert id"; |
||
302 | dol_syslog(get_class($this) . "::create return -2"); |
||
303 | return -2; |
||
304 | } |
||
305 | } else { |
||
306 | $this->error = $this->db->error(); |
||
307 | dol_syslog(get_class($this) . "::create Error " . $this->db->error()); |
||
308 | $this->db->rollback(); |
||
309 | return -1; |
||
310 | } |
||
311 | } |
||
312 | |||
313 | /** |
||
314 | * Update properties of a warehouse |
||
315 | * |
||
316 | * @param int $id id of warehouse to modify |
||
317 | * @param User $user User object |
||
318 | * @param int $notrigger 0=launch triggers after, 1=disable trigge |
||
319 | * @return int Return >0 if OK, <0 if KO |
||
320 | */ |
||
321 | public function update($id, $user, $notrigger = 0) |
||
322 | { |
||
323 | $error = 0; |
||
324 | |||
325 | if (empty($id)) { |
||
326 | $id = $this->id; |
||
327 | } |
||
328 | |||
329 | // Check if new parent is already a child of current warehouse |
||
330 | if (!empty($this->fk_parent)) { |
||
331 | $TChildWarehouses = array($id); |
||
332 | $TChildWarehouses = $this->get_children_warehouses($this->id, $TChildWarehouses); |
||
333 | if (in_array($this->fk_parent, $TChildWarehouses)) { |
||
334 | $this->error = 'ErrorCannotAddThisParentWarehouse'; |
||
335 | return -2; |
||
336 | } |
||
337 | } |
||
338 | |||
339 | $this->label = trim($this->label); |
||
340 | |||
341 | $this->description = trim($this->description); |
||
342 | |||
343 | $this->lieu = trim($this->lieu); |
||
344 | |||
345 | $this->address = trim($this->address); |
||
346 | $this->zip = trim($this->zip); |
||
347 | $this->town = trim($this->town); |
||
348 | $this->country_id = ($this->country_id > 0 ? $this->country_id : 0); |
||
349 | |||
350 | $sql = "UPDATE " . $this->db->prefix() . "entrepot"; |
||
351 | $sql .= " SET ref = '" . $this->db->escape($this->label) . "'"; |
||
352 | $sql .= ", fk_parent = " . (($this->fk_parent > 0) ? $this->fk_parent : "NULL"); |
||
353 | $sql .= ", fk_project = " . (($this->fk_project > 0) ? $this->fk_project : "NULL"); |
||
354 | $sql .= ", description = '" . $this->db->escape($this->description) . "'"; |
||
355 | $sql .= ", statut = " . ((int) $this->statut); |
||
356 | $sql .= ", lieu = '" . $this->db->escape($this->lieu) . "'"; |
||
357 | $sql .= ", address = '" . $this->db->escape($this->address) . "'"; |
||
358 | $sql .= ", zip = '" . $this->db->escape($this->zip) . "'"; |
||
359 | $sql .= ", town = '" . $this->db->escape($this->town) . "'"; |
||
360 | $sql .= ", fk_pays = " . ((int) $this->country_id); |
||
361 | $sql .= ", phone = '" . $this->db->escape($this->phone) . "'"; |
||
362 | $sql .= ", fax = '" . $this->db->escape($this->fax) . "'"; |
||
363 | $sql .= " WHERE rowid = " . ((int) $id); |
||
364 | |||
365 | $this->db->begin(); |
||
366 | |||
367 | dol_syslog(get_class($this) . "::update", LOG_DEBUG); |
||
368 | $resql = $this->db->query($sql); |
||
369 | |||
370 | if (!$resql) { |
||
371 | $error++; |
||
372 | $this->errors[] = "Error " . $this->db->lasterror(); |
||
373 | } |
||
374 | |||
375 | if (!$error) { |
||
376 | $result = $this->insertExtraFields(); |
||
377 | if ($result < 0) { |
||
378 | $error++; |
||
379 | } |
||
380 | } |
||
381 | |||
382 | if (!$error && !$notrigger) { |
||
383 | // Call triggers |
||
384 | $result = $this->call_trigger('WAREHOUSE_MODIFY', $user); |
||
385 | if ($result < 0) { |
||
386 | $error++; |
||
387 | } |
||
388 | // End call triggers |
||
389 | } |
||
390 | |||
391 | if (!$error) { |
||
392 | $this->db->commit(); |
||
393 | return 1; |
||
394 | } else { |
||
395 | $this->db->rollback(); |
||
396 | $this->error = $this->db->lasterror(); |
||
397 | return -1; |
||
398 | } |
||
399 | } |
||
400 | |||
401 | |||
402 | /** |
||
403 | * Delete a warehouse |
||
404 | * |
||
405 | * @param User $user Object user that made deletion |
||
406 | * @param int $notrigger 1=No trigger |
||
407 | * @return int Return integer <0 if KO, >0 if OK |
||
408 | */ |
||
409 | public function delete($user, $notrigger = 0) |
||
410 | { |
||
411 | global $conf; |
||
412 | |||
413 | $error = 0; |
||
414 | |||
415 | dol_syslog(get_class($this) . "::delete id=" . $this->id, LOG_DEBUG); |
||
416 | |||
417 | $this->db->begin(); |
||
418 | |||
419 | if (!$error && empty($notrigger)) { |
||
420 | // Call trigger |
||
421 | $result = $this->call_trigger('WAREHOUSE_DELETE', $user); |
||
422 | if ($result < 0) { |
||
423 | $error++; |
||
424 | } |
||
425 | // End call triggers |
||
426 | } |
||
427 | |||
428 | if (!$error) { |
||
429 | $sql = "DELETE FROM " . $this->db->prefix() . "product_batch"; |
||
430 | $sql .= " WHERE fk_product_stock IN (SELECT rowid FROM " . $this->db->prefix() . "product_stock as ps WHERE ps.fk_entrepot = " . ((int) $this->id) . ")"; |
||
431 | $result = $this->db->query($sql); |
||
432 | if (!$result) { |
||
433 | $error++; |
||
434 | $this->errors[] = $this->db->lasterror(); |
||
435 | } |
||
436 | } |
||
437 | |||
438 | if (!$error) { |
||
439 | $elements = array('stock_mouvement', 'product_stock'); |
||
440 | foreach ($elements as $table) { |
||
441 | if (!$error) { |
||
442 | $sql = "DELETE FROM " . $this->db->prefix() . $table; |
||
443 | $sql .= " WHERE fk_entrepot = " . ((int) $this->id); |
||
444 | |||
445 | $result = $this->db->query($sql); |
||
446 | if (!$result) { |
||
447 | $error++; |
||
448 | $this->errors[] = $this->db->lasterror(); |
||
449 | } |
||
450 | } |
||
451 | } |
||
452 | } |
||
453 | |||
454 | // Removed extrafields |
||
455 | if (!$error) { |
||
456 | $result = $this->deleteExtraFields(); |
||
457 | if ($result < 0) { |
||
458 | $error++; |
||
459 | dol_syslog(get_class($this) . "::delete Error " . $this->error, LOG_ERR); |
||
460 | } |
||
461 | } |
||
462 | |||
463 | if (!$error) { |
||
464 | $sql = "DELETE FROM " . $this->db->prefix() . "entrepot"; |
||
465 | $sql .= " WHERE rowid = " . ((int) $this->id); |
||
466 | $resql1 = $this->db->query($sql); |
||
467 | if (!$resql1) { |
||
468 | $error++; |
||
469 | $this->errors[] = $this->db->lasterror(); |
||
470 | dol_syslog(get_class($this) . "::delete Error " . $this->db->lasterror(), LOG_ERR); |
||
471 | } |
||
472 | } |
||
473 | |||
474 | if (!$error) { |
||
475 | // Update denormalized fields because we change content of produt_stock. Warning: Do not use "SET p.stock", does not works with pgsql |
||
476 | $sql = "UPDATE " . $this->db->prefix() . "product as p SET stock = (SELECT SUM(ps.reel) FROM " . $this->db->prefix() . "product_stock as ps WHERE ps.fk_product = p.rowid)"; |
||
477 | $resql2 = $this->db->query($sql); |
||
478 | if (!$resql2) { |
||
479 | $error++; |
||
480 | $this->errors[] = $this->db->lasterror(); |
||
481 | dol_syslog(get_class($this) . "::delete Error " . $this->db->lasterror(), LOG_ERR); |
||
482 | } |
||
483 | } |
||
484 | |||
485 | if (!$error) { |
||
486 | $this->db->commit(); |
||
487 | return 1; |
||
488 | } else { |
||
489 | $this->db->rollback(); |
||
490 | return -1; |
||
491 | } |
||
492 | } |
||
493 | |||
494 | |||
495 | /** |
||
496 | * Load warehouse data |
||
497 | * |
||
498 | * @param int $id Warehouse id |
||
499 | * @param string $ref Warehouse label |
||
500 | * @return int >0 if OK, <0 if KO |
||
501 | */ |
||
502 | public function fetch($id, $ref = '') |
||
503 | { |
||
504 | global $conf; |
||
505 | |||
506 | dol_syslog(get_class($this) . "::fetch id=" . $id . " ref=" . $ref); |
||
507 | |||
508 | // Check parameters |
||
509 | if (!$id && !$ref) { |
||
510 | $this->error = 'ErrorWrongParameters'; |
||
511 | dol_syslog(get_class($this) . "::fetch " . $this->error); |
||
512 | return -1; |
||
513 | } |
||
514 | |||
515 | $sql = "SELECT rowid, entity, fk_parent, fk_project, ref as label, description, statut, lieu, address, zip, town, fk_pays as country_id, phone, fax,"; |
||
516 | $sql .= " model_pdf, import_key"; |
||
517 | $sql .= " FROM " . $this->db->prefix() . "entrepot"; |
||
518 | if ($id) { |
||
519 | $sql .= " WHERE rowid = " . ((int) $id); |
||
520 | } else { |
||
521 | $sql .= " WHERE entity IN (" . getEntity('stock') . ")"; |
||
522 | if ($ref) { |
||
523 | $sql .= " AND ref = '" . $this->db->escape($ref) . "'"; |
||
524 | } |
||
525 | } |
||
526 | |||
527 | $result = $this->db->query($sql); |
||
528 | if ($result) { |
||
529 | if ($this->db->num_rows($result) > 0) { |
||
530 | $obj = $this->db->fetch_object($result); |
||
531 | |||
532 | $this->id = $obj->rowid; |
||
533 | $this->entity = $obj->entity; |
||
534 | $this->fk_parent = $obj->fk_parent; |
||
535 | $this->fk_project = $obj->fk_project; |
||
536 | $this->ref = $obj->label; |
||
537 | $this->label = $obj->label; |
||
538 | $this->description = $obj->description; |
||
539 | $this->statut = $obj->statut; |
||
540 | $this->lieu = $obj->lieu; |
||
541 | $this->address = $obj->address; |
||
542 | $this->zip = $obj->zip; |
||
543 | $this->town = $obj->town; |
||
544 | $this->country_id = $obj->country_id; |
||
545 | $this->phone = $obj->phone; |
||
546 | $this->fax = $obj->fax; |
||
547 | |||
548 | $this->model_pdf = $obj->model_pdf; |
||
549 | $this->import_key = $obj->import_key; |
||
550 | |||
551 | // Retrieve all extrafield |
||
552 | // fetch optionals attributes and labels |
||
553 | $this->fetch_optionals(); |
||
554 | |||
555 | include_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php'; |
||
556 | $tmp = getCountry($this->country_id, 'all'); |
||
557 | $this->country = $tmp['label']; |
||
558 | $this->country_code = $tmp['code']; |
||
559 | |||
560 | return 1; |
||
561 | } else { |
||
562 | $this->error = "Record Not Found"; |
||
563 | return 0; |
||
564 | } |
||
565 | } else { |
||
566 | $this->error = $this->db->error(); |
||
567 | return -1; |
||
568 | } |
||
569 | } |
||
570 | |||
571 | |||
572 | /** |
||
573 | * Load warehouse info data |
||
574 | * |
||
575 | * @param int $id warehouse id |
||
576 | * @return void |
||
577 | */ |
||
578 | public function info($id) |
||
579 | { |
||
580 | $sql = "SELECT e.rowid, e.datec, e.tms as datem, e.fk_user_author"; |
||
581 | $sql .= " FROM " . $this->db->prefix() . "entrepot as e"; |
||
582 | $sql .= " WHERE e.rowid = " . ((int) $id); |
||
583 | |||
584 | dol_syslog(get_class($this) . "::info", LOG_DEBUG); |
||
585 | $result = $this->db->query($sql); |
||
586 | if ($result) { |
||
587 | if ($this->db->num_rows($result)) { |
||
588 | $obj = $this->db->fetch_object($result); |
||
589 | |||
590 | $this->id = $obj->rowid; |
||
591 | |||
592 | $this->user_creation_id = $obj->fk_user_author; |
||
593 | $this->date_creation = $this->db->jdate($obj->datec); |
||
594 | $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem); |
||
595 | } |
||
596 | |||
597 | $this->db->free($result); |
||
598 | } else { |
||
599 | dol_print_error($this->db); |
||
600 | } |
||
601 | } |
||
602 | |||
603 | |||
604 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
||
605 | /** |
||
606 | * Return list of all warehouses |
||
607 | * |
||
608 | * @param int $status Status |
||
609 | * @return array Array list of warehouses |
||
610 | */ |
||
611 | public function list_array($status = 1) |
||
612 | { |
||
613 | // phpcs:enable |
||
614 | $liste = array(); |
||
615 | |||
616 | $sql = "SELECT rowid, ref as label"; |
||
617 | $sql .= " FROM " . $this->db->prefix() . "entrepot"; |
||
618 | $sql .= " WHERE entity IN (" . getEntity('stock') . ")"; |
||
619 | $sql .= " AND statut = " . ((int) $status); |
||
620 | |||
621 | $result = $this->db->query($sql); |
||
622 | $i = 0; |
||
623 | $num = $this->db->num_rows($result); |
||
624 | if ($result) { |
||
625 | while ($i < $num) { |
||
626 | $row = $this->db->fetch_row($result); |
||
627 | $liste[$row[0]] = $row[1]; |
||
628 | $i++; |
||
629 | } |
||
630 | $this->db->free($result); |
||
631 | } |
||
632 | return $liste; |
||
633 | } |
||
634 | |||
635 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
||
636 | /** |
||
637 | * Return number of unique different product into a warehouse |
||
638 | * |
||
639 | * @return array|int Array('nb'=>Nb, 'value'=>Value) |
||
640 | */ |
||
641 | public function nb_different_products() |
||
642 | { |
||
643 | // phpcs:enable |
||
644 | $ret = array(); |
||
645 | |||
646 | $sql = "SELECT count(distinct p.rowid) as nb"; |
||
647 | $sql .= " FROM " . $this->db->prefix() . "product_stock as ps"; |
||
648 | $sql .= ", " . $this->db->prefix() . "product as p"; |
||
649 | $sql .= " WHERE ps.fk_entrepot = " . ((int) $this->id); |
||
650 | $sql .= " AND ps.fk_product = p.rowid"; |
||
651 | |||
652 | //print $sql; |
||
653 | $result = $this->db->query($sql); |
||
654 | if ($result) { |
||
655 | $obj = $this->db->fetch_object($result); |
||
656 | $ret['nb'] = $obj->nb; |
||
657 | $this->db->free($result); |
||
658 | } else { |
||
659 | $this->error = $this->db->lasterror(); |
||
660 | return -1; |
||
661 | } |
||
662 | |||
663 | return $ret; |
||
664 | } |
||
665 | |||
666 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
||
667 | /** |
||
668 | * Return stock and value of warehosue |
||
669 | * |
||
670 | * @return array|int Array('nb'=>Nb, 'value'=>Value) |
||
671 | */ |
||
672 | public function nb_products() |
||
673 | { |
||
674 | global $conf; |
||
675 | // phpcs:enable |
||
676 | $ret = array(); |
||
677 | |||
678 | //For MultiCompany PMP per entity |
||
679 | $separatedPMP = false; |
||
680 | if (getDolGlobalString('MULTICOMPANY_PRODUCT_SHARING_ENABLED') && getDolGlobalString('MULTICOMPANY_PMP_PER_ENTITY_ENABLED')) { |
||
681 | $separatedPMP = true; |
||
682 | } |
||
683 | |||
684 | if ($separatedPMP) { |
||
685 | $sql = "SELECT sum(ps.reel) as nb, sum(ps.reel * pa.pmp) as value"; |
||
686 | } else { |
||
687 | $sql = "SELECT sum(ps.reel) as nb, sum(ps.reel * p.pmp) as value"; |
||
688 | } |
||
689 | $sql .= " FROM " . $this->db->prefix() . "product_stock as ps"; |
||
690 | $sql .= ", " . $this->db->prefix() . "product as p"; |
||
691 | if ($separatedPMP) { |
||
692 | $sql .= ", " . $this->db->prefix() . "product_perentity as pa"; |
||
693 | } |
||
694 | $sql .= " WHERE ps.fk_entrepot = " . ((int) $this->id); |
||
695 | if ($separatedPMP) { |
||
696 | $sql .= " AND pa.fk_product = p.rowid AND pa.entity = " . (int) $conf->entity; |
||
697 | } |
||
698 | $sql .= " AND ps.fk_product = p.rowid"; |
||
699 | //print $sql; |
||
700 | $result = $this->db->query($sql); |
||
701 | if ($result) { |
||
702 | $obj = $this->db->fetch_object($result); |
||
703 | $ret['nb'] = $obj->nb; |
||
704 | $ret['value'] = $obj->value; |
||
705 | $this->db->free($result); |
||
706 | } else { |
||
707 | $this->error = $this->db->lasterror(); |
||
708 | return -1; |
||
709 | } |
||
710 | |||
711 | return $ret; |
||
712 | } |
||
713 | |||
714 | /** |
||
715 | * Return label of status of object |
||
716 | * |
||
717 | * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto |
||
718 | * @return string Label of status |
||
719 | */ |
||
720 | public function getLibStatut($mode = 0) |
||
721 | { |
||
722 | return $this->LibStatut($this->statut, $mode); |
||
723 | } |
||
724 | |||
725 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
||
726 | /** |
||
727 | * Return label of a given status |
||
728 | * |
||
729 | * @param int $status Id status |
||
730 | * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto |
||
731 | * @return string Label of status |
||
732 | */ |
||
733 | public function LibStatut($status, $mode = 0) |
||
734 | { |
||
735 | // phpcs:enable |
||
736 | global $langs; |
||
737 | |||
738 | $statusType = 'status5'; |
||
739 | if ($status > 0) { |
||
740 | $statusType = 'status4'; |
||
741 | } |
||
742 | |||
743 | $langs->load('stocks'); |
||
744 | $label = $langs->transnoentitiesnoconv($this->labelStatus[$status]); |
||
745 | $labelshort = $langs->transnoentitiesnoconv($this->labelStatus[$status]); |
||
746 | |||
747 | return dolGetStatus($label, $labelshort, '', $statusType, $mode); |
||
748 | } |
||
749 | |||
750 | /** |
||
751 | * getTooltipContentArray |
||
752 | * |
||
753 | * @param array $params Params to construct tooltip data |
||
754 | * @since v18 |
||
755 | * @return array |
||
756 | */ |
||
757 | public function getTooltipContentArray($params) |
||
758 | { |
||
759 | global $conf, $langs, $user; |
||
760 | |||
761 | $langs->load('stocks'); |
||
762 | |||
763 | $datas = []; |
||
764 | |||
765 | $option = $params['option'] ?? ''; |
||
766 | $nofetch = !empty($params['nofetch']); |
||
767 | |||
768 | if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { |
||
769 | return ['optimize' => $langs->trans("Warehouse")]; |
||
770 | } |
||
771 | $datas['picto'] = img_picto('', $this->picto) . ' <u class="paddingrightonly">' . $langs->trans("Warehouse") . '</u>'; |
||
772 | if (isset($this->statut)) { |
||
773 | $datas['picto'] .= ' ' . $this->getLibStatut(5); |
||
774 | } |
||
775 | $datas['ref'] = '<br><b>' . $langs->trans('Ref') . ':</b> ' . (empty($this->ref) ? $this->label : $this->ref); |
||
776 | if (!empty($this->lieu)) { |
||
777 | $datas['locationsummary'] = '<br><b>' . $langs->trans('LocationSummary') . ':</b> ' . $this->lieu; |
||
778 | } |
||
779 | // show categories for this record only in ajax to not overload lists |
||
780 | if (!$nofetch && isModEnabled('category')) { |
||
781 | $form = new Form($this->db); |
||
782 | $datas['categories_warehouse'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_WAREHOUSE, 1, 1); |
||
783 | } |
||
784 | |||
785 | return $datas; |
||
786 | } |
||
787 | |||
788 | /** |
||
789 | * Return clickable name (possibility with the pictogram) |
||
790 | * |
||
791 | * @param int $withpicto with pictogram |
||
792 | * @param string $option Where the link point to |
||
793 | * @param int $showfullpath 0=Show ref only. 1=Show full path instead of Ref (this->fk_parent must be defined) |
||
794 | * @param int $notooltip 1=Disable tooltip |
||
795 | * @param string $morecss Add more css on link |
||
796 | * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking |
||
797 | * @return string String with URL |
||
798 | */ |
||
799 | public function getNomUrl($withpicto = 0, $option = '', $showfullpath = 0, $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) |
||
800 | { |
||
801 | global $conf, $langs, $hookmanager; |
||
802 | $langs->load("stocks"); |
||
803 | |||
804 | if (!empty($conf->dol_no_mouse_hover)) { |
||
805 | $notooltip = 1; // Force disable tooltips |
||
806 | } |
||
807 | |||
808 | if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER') && $withpicto) { |
||
809 | $withpicto = 0; |
||
810 | } |
||
811 | |||
812 | $result = ''; |
||
813 | $params = [ |
||
814 | 'id' => $this->id, |
||
815 | 'objecttype' => $this->element, |
||
816 | 'option' => $option, |
||
817 | 'nofetch' => 1, |
||
818 | ]; |
||
819 | $classfortooltip = 'classfortooltip'; |
||
820 | $dataparams = ''; |
||
821 | if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) { |
||
822 | $classfortooltip = 'classforajaxtooltip'; |
||
823 | $dataparams = ' data-params="' . dol_escape_htmltag(json_encode($params)) . '"'; |
||
824 | $label = 'ToComplete'; |
||
825 | } else { |
||
826 | $label = implode($this->getTooltipContentArray($params)); |
||
827 | } |
||
828 | |||
829 | $url = constant('BASE_URL') . '/product/stock/card.php?id=' . $this->id; |
||
830 | |||
831 | if ($option != 'nolink') { |
||
832 | // Add param to save lastsearch_values or not |
||
833 | $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0); |
||
834 | if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) { |
||
835 | $add_save_lastsearch_values = 1; |
||
836 | } |
||
837 | if ($add_save_lastsearch_values) { |
||
838 | $url .= '&save_lastsearch_values=1'; |
||
839 | } |
||
840 | } |
||
841 | |||
842 | $linkclose = ''; |
||
843 | if (empty($notooltip)) { |
||
844 | if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { |
||
845 | $label = $langs->trans("Warehouse"); |
||
846 | $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"'; |
||
847 | } |
||
848 | $linkclose .= ($label ? ' title="' . dol_escape_htmltag($label, 1) . '"' : ' title="tocomplete"'); |
||
849 | $linkclose .= $dataparams . ' class="' . $classfortooltip . '"'; |
||
850 | } |
||
851 | |||
852 | $linkstart = '<a href="' . $url . '"'; |
||
853 | $linkstart .= $linkclose . '>'; |
||
854 | $linkend = '</a>'; |
||
855 | |||
856 | $result .= $linkstart; |
||
857 | if ($withpicto) { |
||
858 | $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . '"'), 0, 0, $notooltip ? 0 : 1); |
||
859 | } |
||
860 | if ($withpicto != 2) { |
||
861 | $result .= (($showfullpath || getDolGlobalString('STOCK_ALWAYS_SHOW_FULL_ARBO')) ? $this->get_full_arbo() : $this->label); |
||
862 | } |
||
863 | $result .= $linkend; |
||
864 | |||
865 | global $action; |
||
866 | $hookmanager->initHooks(array('warehousedao')); |
||
867 | $parameters = array('id' => $this->id, 'getnomurl' => &$result, 'withpicto' => $withpicto, 'option' => $option, 'showfullpath' => $showfullpath, 'notooltip' => $notooltip); |
||
868 | $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks |
||
869 | if ($reshook > 0) { |
||
870 | $result = $hookmanager->resPrint; |
||
871 | } else { |
||
872 | $result .= $hookmanager->resPrint; |
||
873 | } |
||
874 | |||
875 | return $result; |
||
876 | } |
||
877 | |||
878 | /** |
||
879 | * Initialise an instance with random values. |
||
880 | * Used to build previews or test instances. |
||
881 | * id must be 0 if object instance is a specimen. |
||
882 | * |
||
883 | * @return int |
||
884 | */ |
||
885 | public function initAsSpecimen() |
||
886 | { |
||
887 | global $user, $langs, $conf, $mysoc; |
||
888 | |||
889 | $now = dol_now(); |
||
890 | |||
891 | // Initialize parameters |
||
892 | $this->id = 0; |
||
893 | $this->label = 'WAREHOUSE SPECIMEN'; |
||
894 | $this->description = 'WAREHOUSE SPECIMEN ' . dol_print_date($now, 'dayhourlog'); |
||
895 | $this->statut = 1; |
||
896 | $this->specimen = 1; |
||
897 | |||
898 | $this->lieu = 'Location test'; |
||
899 | $this->address = '21 jump street'; |
||
900 | $this->zip = '99999'; |
||
901 | $this->town = 'MyTown'; |
||
902 | $this->country_id = 1; |
||
903 | $this->country_code = 'FR'; |
||
904 | |||
905 | return 1; |
||
906 | } |
||
907 | |||
908 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
||
909 | /** |
||
910 | * Return full path to current warehouse |
||
911 | * |
||
912 | * @return string String full path to current warehouse separated by " >> " |
||
913 | */ |
||
914 | public function get_full_arbo() |
||
947 | } |
||
948 | |||
949 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
||
950 | /** |
||
951 | * Return array of children warehouses ids from $id warehouse (recursive function) |
||
952 | * |
||
953 | * @param int $id id parent warehouse |
||
954 | * @param integer[] $TChildWarehouses array which will contain all children (param by reference) |
||
955 | * @return integer[] $TChildWarehouses array which will contain all children |
||
956 | */ |
||
957 | public function get_children_warehouses($id, &$TChildWarehouses) |
||
974 | } |
||
975 | |||
976 | /** |
||
977 | * Create object on disk |
||
978 | * |
||
979 | * @param string $modele force le modele a utiliser ('' to not force) |
||
980 | * @param Translate $outputlangs Object langs to use for output |
||
981 | * @param int $hidedetails Hide details of lines |
||
982 | * @param int $hidedesc Hide description |
||
983 | * @param int $hideref Hide ref |
||
984 | * @return int 0 if KO, 1 if OK |
||
985 | */ |
||
986 | public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0) |
||
1006 | } |
||
1007 | |||
1008 | /** |
||
1009 | * Sets object to supplied categories. |
||
1010 | * |
||
1011 | * Deletes object from existing categories not supplied. |
||
1012 | * Adds it to non existing supplied categories. |
||
1013 | * Existing categories are left untouch. |
||
1014 | * |
||
1015 | * @param int[]|int $categories Category or categories IDs |
||
1016 | * @return int Return integer <0 if KO, >0 if OK |
||
1017 | */ |
||
1018 | public function setCategories($categories) |
||
1021 | } |
||
1022 | |||
1023 | /** |
||
1024 | * Return clicable link of object (with eventually picto) |
||
1025 | * |
||
1026 | * @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) |
||
1027 | * @param array $arraydata Array of data |
||
1028 | * @return string HTML Code for Kanban thumb. |
||
1029 | */ |
||
1030 | public function getKanbanView($option = '', $arraydata = null) |
||
1057 | } |
||
1058 | } |
||
1059 |