dolibarr 21.0.4
cunits.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2007-2011 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
4 * Copyright (C) 2024 Frédéric France <frederic.france@free.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
26// Put here all includes required by your class file
27require_once DOL_DOCUMENT_ROOT.'/core/class/commondict.class.php';
28
29
33class CUnits extends CommonDict
34{
38 public $records = array();
39
40 // public $element = 'cunits'; //!< Id that identify managed objects
41 // public $table_element = 'c_units'; //!< Name of table without prefix where object is stored
42
48 public $libelle;
49
53 public $sortorder;
54
58 public $short_label;
59
63 public $unit_type;
64
68 public $scale;
69
70
76 public function __construct($db)
77 {
78 $this->db = $db;
79 }
80
81
89 public function create($user, $notrigger = 0)
90 {
91 $error = 0;
92
93 // Clean parameters
94
95 if (isset($this->id)) {
96 $this->id = (int) $this->id;
97 }
98 if (isset($this->code)) {
99 $this->code = trim($this->code);
100 }
101 if (isset($this->label)) {
102 $this->libelle = trim($this->label);
103 }
104 if (isset($this->short_label)) {
105 $this->libelle = trim($this->short_label);
106 }
107 if (isset($this->unit_type)) {
108 $this->unit_type = trim($this->unit_type);
109 }
110 if (isset($this->active)) {
111 $this->active = (int) $this->active;
112 }
113 if (isset($this->scale)) {
114 $this->scale = (int) $this->scale;
115 }
116
117 // Check parameters
118 // Put here code to add control on parameters values
119
120 // Insert request
121 $sql = "INSERT INTO ".$this->db->prefix()."c_units(";
122 $sql .= "rowid,";
123 $sql .= "code,";
124 $sql .= "label,";
125 $sql .= "short_label,";
126 $sql .= "unit_type,";
127 $sql .= "scale";
128 $sql .= ") VALUES (";
129 $sql .= " ".(!isset($this->id) ? 'NULL' : "'".$this->db->escape($this->id)."'").",";
130 $sql .= " ".(!isset($this->code) ? 'NULL' : "'".$this->db->escape($this->code)."'").",";
131 $sql .= " ".(!isset($this->label) ? 'NULL' : "'".$this->db->escape($this->label)."'").",";
132 $sql .= " ".(!isset($this->short_label) ? 'NULL' : "'".$this->db->escape($this->short_label)."'").",";
133 $sql .= " ".(!isset($this->unit_type) ? 'NULL' : "'".$this->db->escape($this->unit_type)."'").",";
134 $sql .= " ".(!isset($this->scale) ? 'NULL' : (int) $this->scale);
135 $sql .= ")";
136
137 $this->db->begin();
138
139 dol_syslog(get_class($this)."::create", LOG_DEBUG);
140 $resql = $this->db->query($sql);
141 if (!$resql) {
142 $error++;
143 $this->errors[] = "Error ".$this->db->lasterror();
144 }
145
146 if (!$error) {
147 $this->id = $this->db->last_insert_id($this->db->prefix()."c_units");
148 }
149
150 // Commit or rollback
151 if ($error) {
152 foreach ($this->errors as $errmsg) {
153 dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
154 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
155 }
156 $this->db->rollback();
157 return -1 * $error;
158 } else {
159 $this->db->commit();
160 return $this->id;
161 }
162 }
163
164
174 public function fetch($id, $code = '', $short_label = '', $unit_type = '')
175 {
176 $sql = "SELECT";
177 $sql .= " t.rowid,";
178 $sql .= " t.code,";
179 $sql .= " t.label,";
180 $sql .= " t.short_label,";
181 $sql .= " t.scale,";
182 $sql .= " t.unit_type,";
183 $sql .= " t.active";
184 $sql .= " FROM ".$this->db->prefix()."c_units as t";
185 $sql_where = array();
186 if ($id) {
187 $sql_where[] = " t.rowid = ".((int) $id);
188 }
189 if ($unit_type) {
190 $sql_where[] = " t.unit_type = '".$this->db->escape($unit_type)."'";
191 }
192 if ($code) {
193 $sql_where[] = " t.code = '".$this->db->escape($code)."'";
194 }
195 if ($short_label) {
196 $sql_where[] = " t.short_label = '".$this->db->escape($short_label)."'";
197 }
198 if (count($sql_where) > 0) {
199 $sql .= ' WHERE '.implode(' AND ', $sql_where);
200 }
201
202 $resql = $this->db->query($sql);
203 if ($resql) {
204 if ($this->db->num_rows($resql)) {
205 $obj = $this->db->fetch_object($resql);
206
207 $this->id = (int) $obj->rowid;
208 $this->code = $obj->code;
209 $this->label = $obj->label;
210 $this->short_label = $obj->short_label;
211 // Preserve scale=0 (e.g. the kg row). A truthy test on $obj->scale would
212 // collapse the legitimate scale of "0" into null and, downstream, the
213 // "weight unit" dropdown comparison in selectMeasuringUnits would no
214 // longer match the stored value under PHP 8 strict numeric-string
215 // rules, silently switching saved products to the first option (see
216 // issue #38497).
217 $this->scale = isset($obj->scale) ? (int) $obj->scale : null;
218 $this->unit_type = $obj->unit_type;
219 $this->active = (int) $obj->active;
220 }
221 $this->db->free($resql);
222
223 return 1;
224 } else {
225 $this->error = "Error ".$this->db->lasterror();
226 return -1;
227 }
228 }
229
230
242 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
243 {
244 dol_syslog(__METHOD__, LOG_DEBUG);
245
246 $sql = "SELECT";
247 $sql .= " t.rowid,";
248 $sql .= " t.code,";
249 $sql .= " t.sortorder,";
250 $sql .= " t.label,";
251 $sql .= " t.short_label,";
252 $sql .= " t.unit_type,";
253 $sql .= " t.scale,";
254 $sql .= " t.active";
255 $sql .= " FROM ".$this->db->prefix()."c_units as t";
256 $sql .= " WHERE 1 = 1";
257
258 // Manage filter
259 if (is_array($filter)) {
260 $sqlwhere = array();
261 if (count($filter) > 0) {
262 foreach ($filter as $key => $value) {
263 if ($key == 't.rowid' || $key == 't.active' || $key == 't.scale') {
264 $sqlwhere[] = $this->db->sanitize($key)." = ".((int) $value);
265 } elseif (strpos($key, 'date') !== false) {
266 $sqlwhere[] = $this->db->sanitize($key)." = '".$this->db->idate($value)."'";
267 } elseif ($key == 't.unit_type' || $key == 't.code' || $key == 't.short_label') {
268 $sqlwhere[] = $this->db->sanitize($key)." = '".$this->db->escape($value)."'";
269 } else {
270 $sqlwhere[] = $this->db->sanitize($key)." LIKE '%".$this->db->escape($this->db->escapeforlike($value))."%'";
271 }
272 }
273 }
274 if (count($sqlwhere) > 0) {
275 $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')';
276 }
277
278 $filter = '';
279 }
280
281 // Manage filter
282 $errormessage = '';
283 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
284 if ($errormessage) {
285 $this->errors[] = $errormessage;
286 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
287 return -1;
288 }
289
290 if (!empty($sortfield)) {
291 $sql .= $this->db->order($sortfield, $sortorder);
292 }
293 if (!empty($limit)) {
294 $sql .= $this->db->plimit($limit, $offset);
295 }
296
297 $resql = $this->db->query($sql);
298 if ($resql) {
299 $this->records = array();
300 $num = $this->db->num_rows($resql);
301 if ($num > 0) {
302 while ($obj = $this->db->fetch_object($resql)) {
303 $record = new self($this->db);
304
305 $record->id = (int) $obj->rowid;
306 $record->code = $obj->code;
307 $record->sortorder = $obj->sortorder;
308 $record->label = $obj->label;
309 $record->short_label = $obj->short_label;
310 $record->unit_type = $obj->unit_type;
311 // Same scale-preservation as in fetch(): see issue #38497.
312 $record->scale = isset($obj->scale) ? (int) $obj->scale : null;
313 $record->active = (int) $obj->active;
314
315 $this->records[$record->id] = $record;
316 }
317 }
318 $this->db->free($resql);
319
320 return $this->records;
321 } else {
322 $this->errors[] = 'Error '.$this->db->lasterror();
323 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
324
325 return -1;
326 }
327 }
328
329
337 public function update($user = null, $notrigger = 0)
338 {
339 $error = 0;
340
341 // Clean parameters
342 if (isset($this->code)) {
343 $this->code = trim($this->code);
344 }
345 if (isset($this->sortorder)) {
346 $this->sortorder = trim($this->sortorder);
347 }
348 if (isset($this->label)) {
349 $this->libelle = trim($this->label);
350 }
351 if (isset($this->short_label)) {
352 $this->libelle = trim($this->short_label);
353 }
354 if (isset($this->unit_type)) {
355 $this->libelle = trim($this->unit_type);
356 }
357 if (isset($this->scale)) {
358 $this->scale = (int) $this->scale;
359 }
360 if (isset($this->active)) {
361 $this->active = (int) $this->active;
362 }
363
364 // Check parameters
365 // Put here code to add control on parameters values
366
367 // Update request
368 $sql = "UPDATE ".$this->db->prefix()."c_units SET";
369 $sql .= " code=".(isset($this->code) ? "'".$this->db->escape($this->code)."'" : "null").",";
370 $sql .= " sortorder=".(isset($this->sortorder) ? "'".$this->db->escape($this->sortorder)."'" : "null").",";
371 $sql .= " label=".(isset($this->label) ? "'".$this->db->escape($this->label)."'" : "null").",";
372 $sql .= " short_label=".(isset($this->short_label) ? "'".$this->db->escape($this->short_label)."'" : "null").",";
373 $sql .= " unit_type=".(isset($this->unit_type) ? "'".$this->db->escape($this->unit_type)."'" : "null").",";
374 $sql .= " scale=".(isset($this->scale) ? "'".$this->db->escape($this->scale)."'" : "null").",";
375 $sql .= " active=".(isset($this->active) ? $this->active : "null");
376 $sql .= " WHERE rowid=".((int) $this->id);
377
378 $this->db->begin();
379
380 dol_syslog(get_class($this)."::update", LOG_DEBUG);
381 $resql = $this->db->query($sql);
382 if (!$resql) {
383 $error++;
384 $this->errors[] = "Error ".$this->db->lasterror();
385 }
386
387 // Commit or rollback
388 if ($error) {
389 foreach ($this->errors as $errmsg) {
390 dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
391 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
392 }
393 $this->db->rollback();
394 return -1 * $error;
395 } else {
396 $this->db->commit();
397 return 1;
398 }
399 }
400
401
409 public function delete($user, $notrigger = 0)
410 {
411 $error = 0;
412
413 $sql = "DELETE FROM ".$this->db->prefix()."c_units";
414 $sql .= " WHERE rowid=".((int) $this->id);
415
416 $this->db->begin();
417
418 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
419 $resql = $this->db->query($sql);
420 if (!$resql) {
421 $error++;
422 $this->errors[] = "Error ".$this->db->lasterror();
423 }
424
425 // Commit or rollback
426 if ($error) {
427 foreach ($this->errors as $errmsg) {
428 dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
429 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
430 }
431 $this->db->rollback();
432 return -1 * $error;
433 } else {
434 $this->db->commit();
435 return 1;
436 }
437 }
438
439
447 public function getUnitFromCode($code, $mode = 'code', $unit_type = '')
448 {
449 if ($mode == 'short_label' || $mode == 'code') {
450 return dol_getIdFromCode($this->db, $code, 'c_units', $mode, 'rowid', 0, " AND unit_type = '".$this->db->escape($unit_type)."'");
451 }
452 return $code;
453 }
454
462 public function unitConverter($value, $fk_unit, $fk_new_unit = 0)
463 {
464 $value = (float) price2num($value);
465 $fk_unit = intval($fk_unit);
466
467 // Calcul en unité de base
468 $scaleUnitPow = $this->scaleOfUnitPow($fk_unit);
469
470 // convert to standard unit
471 $value *= $scaleUnitPow;
472 if ($fk_new_unit != 0) {
473 // Calcul en unité de base
474 $scaleUnitPow = $this->scaleOfUnitPow($fk_new_unit);
475 if (!empty($scaleUnitPow)) {
476 // convert to new unit
477 $value /= $scaleUnitPow;
478 }
479 }
480 return round($value, 2);
481 }
482
489 public function scaleOfUnitPow($id)
490 {
491 $base = 10;
492
493 $sql = "SELECT scale, unit_type FROM ".$this->db->prefix()."c_units WHERE rowid = ".((int) $id);
494
495 $resql = $this->db->query($sql);
496 if ($resql) {
497 // TODO : add base col into unit dictionary table
498 $unit = $this->db->fetch_object($sql);
499 if ($unit) {
500 // TODO : if base exists in unit dictionary table, remove this conversion exception and update conversion infos in database.
501 // Example time hour currently scale 3600 will become scale 2 base 60
502 if ($unit->unit_type == 'time') {
503 return (float) $unit->scale;
504 }
505
506 return pow($base, (float) $unit->scale);
507 }
508 }
509
510 return 0;
511 }
512}
Class of dictionary type of thirdparty (used by imports)
getUnitFromCode($code, $mode='code', $unit_type='')
Get unit from code.
unitConverter($value, $fk_unit, $fk_new_unit=0)
Unit converter.
scaleOfUnitPow($id)
Get scale of unit factor.
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter='', $filtermode='AND')
Load list of objects in memory from the database.
fetch($id, $code='', $short_label='', $unit_type='')
Load object in memory from database.
create($user, $notrigger=0)
Create object into database.
__construct($db)
Constructor.
update($user=null, $notrigger=0)
Update object into database.
Parent class of all other dictionary classes.
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.