dolibarr 25.0.0-alpha
commonsubtotal.class.php
1<?php
2/* Copyright (C) 2014-2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
4 * Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
5 * Copyright (C) 2025 Charlene Benke <charlene@patas-monkey.com>
6 * Copyright (C) 2026 Lionel Vessiller <lvessiller@open-dsi.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 * or see https://www.gnu.org/
21 */
22
23
30trait CommonSubtotal
31{
36 public static $PRODUCT_TYPE = 9;
37
42 public static $TITLE_OPTIONS = ['titleshowuponpdf', 'titleshowtotalexludingvatonpdf', 'titleforcepagebreak'];
43
48 public static $SUBTOTAL_OPTIONS = ['subtotalshowtotalexludingvatonpdf'];
49
53 public static $ALLOWED_TYPES = [
54 'propal',
55 'commande',
56 'facture',
57 'facturerec',
58 'shipping',
59 'supplier_proposal',
60 'order_supplier',
61 'invoice_supplier',
62 'fichinter',
63 ];
64
65
80 public function addSubtotalLine($langs, $desc, $depth, $options = array(), $parent_line = 0)
81 {
82 if (empty($desc)) {
83 $this->errors[] = $langs->trans("TitleNeedDesc");
84 return -1;
85 }
86 $current_module = $this->element;
87 // Ensure the object is one of the supported types
88 if (!in_array($current_module, self::$ALLOWED_TYPES)) {
89 $this->errors[] = $langs->trans("UnsupportedModuleError");
90 return -1; // Unsupported type
91 }
92 $error = 0;
93 $desc = dol_html_entity_decode($desc, ENT_QUOTES);
94 $rang = -1;
95 $next_line = false;
96 $result = 0;
97
98 if ($depth < 0 && $current_module != 'shipping') {
99 foreach ($this->lines as $line) {
100 if (!$next_line && $line->desc == $desc && $line->qty == -$depth) {
101 $next_line = true;
102 continue;
103 }
104 if ($next_line && $line->desc == $desc && $line->qty == $depth) {
105 $next_line = false;
106 continue;
107 }
108 if ($next_line && $line->special_code == SUBTOTALS_SPECIAL_CODE && abs($line->qty) <= abs($depth)) {
109 $rang = $line->rang;
110 break;
111 }
112 }
113 }
114
115 if ($depth > 0 && $current_module != 'shipping') {
116 $max_existing_level = 0;
117
118 foreach ($this->lines as $line) {
119 if ($line->special_code == SUBTOTALS_SPECIAL_CODE && $line->qty > $max_existing_level) {
120 $max_existing_level = $line->qty;
121 }
122 }
123
124 if ($max_existing_level+1 < $depth) {
125 $depth = $max_existing_level+1;
126 $this->errors[] = $langs->trans("TitleAddedLevelTooHigh", $depth);
127
128 $error ++;
129 }
130 }
131
132 // Add the line calling the right module
133 if ($current_module == 'facture' && $this instanceof Facture) {
134 $result = $this->addline(
135 $desc, // Description
136 0, // Unit price
137 $depth, // Quantity
138 0, // VAT rate
139 0, // Local tax 1
140 0, // Local tax 2
141 0, // FK product
142 0, // Discount percentage
143 '', // Date start
144 '', // Date end
145 0, // FK code ventilation
146 0, // Info bits
147 0, // FK remise except
148 '', // Price base type
149 0, // PU ttc
150 self::$PRODUCT_TYPE, // Type
151 $rang, // Rang
152 SUBTOTALS_SPECIAL_CODE // Special code
153 );
154 } elseif ($current_module == 'propal' && $this instanceof Propal) {
155 $result = $this->addline(
156 $desc, // Description
157 0, // Unit price
158 $depth, // Quantity
159 0, // VAT rate
160 0, // Local tax 1
161 0, // Local tax 2
162 0, // FK product
163 0, // Discount percentage
164 '', // Price base type
165 0, // PU ttc
166 0, // Info bits
167 self::$PRODUCT_TYPE, // Type
168 $rang, // Rang
169 SUBTOTALS_SPECIAL_CODE // Special code
170 );
171 } elseif ($current_module == 'commande' && $this instanceof Commande) {
172 $result = $this->addline(
173 $desc, // Description
174 0, // Unit price
175 $depth, // Quantity
176 0, // VAT rate
177 0, // Local tax 1
178 0, // Local tax 2
179 0, // FK product
180 0, // Discount percentage
181 0, // Info bits
182 0, // FK remise except
183 '', // Price base type
184 0, // PU ttc
185 '', // Date start
186 '', // Date end
187 self::$PRODUCT_TYPE, // Type
188 $rang, // Rang
189 SUBTOTALS_SPECIAL_CODE // Special code
190 );
191 } elseif ($current_module == 'shipping' && $this instanceof Expedition) {
192 $result = $this->addline(
193 0, // Warehouse ID
194 (int) $parent_line, // Source line
195 $depth // Quantity
196 );
197 } elseif ($current_module == 'facturerec' && $this instanceof FactureRec) {
198 $rang = $rang == -1 ? $rang : $rang-1;
199 $result = $this->addline(
200 $desc, // Description
201 0, // Unit price
202 $depth, // Quantity
203 0, // VAT rate
204 0, // Local tax 1
205 0, // Local tax 2
206 0, // FK product
207 0, // Discount percentage
208 '', // Price base type
209 0, // Info bits
210 0, // FK remise except
211 0, // PU ttc
212 self::$PRODUCT_TYPE, // Type
213 $rang, // Rang
214 SUBTOTALS_SPECIAL_CODE // Special code
215 );
216 $this->fetch_lines();
217 } elseif ($current_module == 'supplier_proposal' && $this instanceof SupplierProposal) {
218 $rang = $rang == -1 ? $rang : $rang-1;
219 $result = $this->addline(
220 $desc, // Description
221 0, // Unit price
222 $depth, // Quantity
223 0, // VAT rate
224 0, // Local tax 1
225 0, // Local tax 2
226 0, // FK product
227 0, // Discount percentage
228 '', // Price base type
229 0, // PU ttc
230 0, // Info bits
231 self::$PRODUCT_TYPE, // Type
232 $rang, // Rang
233 SUBTOTALS_SPECIAL_CODE // Special code
234 );
235 } elseif ($current_module == 'order_supplier' && $this instanceof CommandeFournisseur) {
236 $rang = $rang == -1 ? $rang : $rang-1;
237 $result = $this->addline(
238 $desc, // Description
239 0, // Unit price
240 $depth, // Quantity
241 0, // VAT rate
242 0, // Local tax 1
243 0, // Local tax 2
244 0, // FK product
245 0, // fk fourn price
246 '', // ref supplier
247 0, // Remise percent
248 '', // Price base type
249 0, // PU ttc
250 self::$PRODUCT_TYPE, // Type
251 0, // info bits
252 0, // no trigger
253 null, // Date start
254 null, // Date end
255 [], // array_options
256 null, // fk_unit
257 0, // pu ht devise
258 '', // origin type
259 0, // origin id
260 $rang, // Rang
261 SUBTOTALS_SPECIAL_CODE // Special code
262 );
263 } elseif ($current_module == 'invoice_supplier' && $this instanceof FactureFournisseur) {
264 $rang = $rang == -1 ? $rang : $rang-1;
265 $result = $this->addline(
266 $desc, // Description
267 0, // Unit price
268 0, // VAT rate
269 0, // Local tax 1
270 0, // Local tax 2
271 $depth, // Quantity
272 0, // FK product
273 0, // Remise percent
274 '', // Date start
275 '', // Date end
276 0, // Code ventilation
277 0, // info bits
278 '', // Price base type
279 self::$PRODUCT_TYPE, // Type
280 $rang, // Rang
281 0, // no trigger
282 [], // array_options
283 null, // fk_unit
284 0, // origin id
285 0, // pu ht devise
286 '', // ref supplier
287 SUBTOTALS_SPECIAL_CODE // Special code
288 );
289 } elseif ($current_module == 'fichinter' && $this instanceof Fichinter) {
290 global $user;
291 $result = $this->addline(
292 $user, // user
293 $this->id, // fk_fichinter
294 $desc, // Description
295 0, // dateintervention
296 $depth, // duration
297 [], // arrayoption
298 self::$PRODUCT_TYPE, // Type
299 $rang, // Rang
300 SUBTOTALS_SPECIAL_CODE // Special code
301 );
302 }
303
304
305 if ($current_module != 'shipping') {
306 foreach ($this->lines as $line) {
307 '@phan-var-force CommonObjectLine $line';
309 if ($line->id == $result) {
310 $line->extraparams["subtotal"] = $options;
311 $line->setExtraParameters();
312 }
313 }
314 }
315
316 if ($result < 0) {
317 return $result;
318 }
319
320 return $error > 0 ? 0 : $result;
321 }
322
336 public function deleteSubtotalLine($langs, $id, $correspondingstline = false, $user = null)
337 {
338 $current_module = $this->element;
339 // Ensure the object is one of the supported types
340 if (!in_array($current_module, self::$ALLOWED_TYPES)) {
341 $this->errors[] = $langs->trans("UnsupportedModuleError");
342 return -1; // Unsupported type
343 }
344
345 $result = 0;
346
347 if ($correspondingstline) {
348 $oldDesc = "";
349 $oldDepth = 0;
350 foreach ($this->lines as $line) {
351 if ($line->id == $id) {
352 $oldDesc = $line->desc;
353 $oldDepth = $line->qty;
354 }
355 if ($line->special_code == SUBTOTALS_SPECIAL_CODE && $line->qty == -$oldDepth && $line->desc == $oldDesc) {
356 $this->deleteSubtotalLine($langs, $line->id, false, $user);
357 break;
358 }
359 }
360 }
361
362 // Add the line calling the right module
363 if ($current_module == 'facture' && $this instanceof Facture) {
364 $rowid = $id; // for phan suspicious parameter order...
365 $result = $this->deleteLine($rowid);
366 } elseif ($current_module == 'propal' && $this instanceof Propal) {
367 $rowid = $id; // for phan suspicious parameter order...
368 $result = $this->deleteLine($rowid);
369 } elseif ($current_module == 'commande' && $this instanceof Commande) {
370 $lineid = $id; // for phan suspicious parameter order...
371 $result = $this->deleteLine($user, $lineid);
372 } elseif ($current_module == 'facturerec') {
373 $line = new FactureLigneRec($this->db);
374 $line->id = $id;
375 $result = $line->delete($user);
376 } elseif ($current_module == 'shipping') {
377 $line = new ExpeditionLigne($this->db);
378 $line->id = $id;
379 $result = $line->delete($user);
380 } elseif ($current_module == 'supplier_proposal') {
381 $line = new SupplierProposalLine($this->db);
382 $line->id = $id;
383 $result = $line->delete($user);
384 } elseif ($current_module == 'order_supplier') {
385 $line = new CommandeFournisseurLigne($this->db);
386 $line->id = $id;
387 $result = $line->delete($user);
388 } elseif ($current_module == 'invoice_supplier') {
389 $line = new SupplierInvoiceLine($this->db);
390 $line->id = $id;
391 $result = $line->delete();
392 } elseif ($current_module == 'fichinter') {
393 $line = new FichinterLigne($this->db);
394 $line->id = $id;
395 $result = $line->deleteLine($user);
396 }
397
398 return $result >= 0 ? $result : -1; // Return line ID or false
399 }
400
416 public function updateSubtotalLine($langs, $lineid, $desc, $depth, $options) // @phpstan-ignore-line
417 {
418 $current_module = $this->element;
419 // Ensure the object is one of the supported types
420 if (!in_array($current_module, self::$ALLOWED_TYPES)) {
421 $this->errors[] = $langs->trans("UnsupportedModuleError");
422 return -1; // Unsupported type
423 }
424
425 $result = 0;
426 $error = 0;
427
428 $max_existing_level = 0;
429
430 if ($depth>0) {
431 foreach ($this->lines as $line) {
432 if ($line->special_code == SUBTOTALS_SPECIAL_CODE && $line->qty > $max_existing_level && $line->id != $lineid) {
433 $max_existing_level = $line->qty;
434 }
435 }
436 }
437
438 if ($max_existing_level+1 < $depth) {
439 $depth = $max_existing_level+1;
440 $this->errors[] = $langs->trans("TitleEditedLevelTooHigh");
441 $error ++;
442 }
443
444 if ($depth>0) {
445 $oldDesc = "";
446 $oldDepth = 0;
447 foreach ($this->lines as $line) {
448 if ($line->id == $lineid) {
449 $oldDesc = $line->desc;
450 $oldDepth = $line->qty;
451 }
452 if ($line->special_code == SUBTOTALS_SPECIAL_CODE && $line->qty == -$oldDepth && $line->desc == $oldDesc) {
453 $this->updateSubtotalLine($langs, $line->id, $desc, -$depth, !empty($line->extraparams["subtotal"]) ? $line->extraparams["subtotal"] : array());
454 break;
455 }
456 }
457 }
458
459 // Update the line calling the right module
460 if ($current_module == 'facture' && $this instanceof Facture) {
461 $result = $this->updateline(
462 $lineid, // ID of line to change
463 $desc, // Description
464 0, // Unit price
465 $depth, // Quantity
466 0, // Discount percentage
467 '', // Date start
468 '', // Date end
469 0, // VAT rate
470 0, // Local tax 1
471 0, // Local tax 2
472 '', // Price base type
473 0, // Info bits
474 self::$PRODUCT_TYPE, // Type
475 0, // FK parent line
476 0, // Skip update total
477 0, // FK fournprice
478 0, // PA ht
479 '', // Label
480 SUBTOTALS_SPECIAL_CODE // Special code
481 );
482 } elseif ($current_module == 'propal' && $this instanceof Propal) {
483 $result = $this->updateline(
484 $lineid, // ID of line to change
485 0, // Unit price
486 $depth, // Quantity
487 0, // Discount percentage
488 0, // VAT rate
489 0, // Local tax 1
490 0, // Local tax 2
491 $desc, // Description
492 '', // Price base type
493 0, // Info bits
494 SUBTOTALS_SPECIAL_CODE, // Special code
495 0, // FK parent line
496 0, // Skip update total
497 0, // FK fournprice
498 0, // PA ht
499 '', // Label
500 self::$PRODUCT_TYPE // Type
501 );
502 } elseif ($current_module == 'commande' && $this instanceof Commande) {
503 $result = $this->updateline(
504 $lineid, // ID of line to change
505 $desc, // Description
506 0, // Unit price
507 $depth, // Quantity
508 0, // Discount percentage
509 0, // VAT rate
510 0, // Local tax 1
511 0, // Local tax 2
512 '', // Price base type
513 0, // Info bits
514 '', // Date start
515 '', // Date end
516 self::$PRODUCT_TYPE, // Type
517 0, // FK parent line
518 0, // Skip update total
519 0, // FK fournprice
520 0, // PA ht
521 '', // Label
522 SUBTOTALS_SPECIAL_CODE // Special code
523 );
524 } elseif ($current_module == 'facturerec' && $this instanceof FactureRec) {
525 $objectline = new FactureLigneRec($this->db);
526 $objectline->fetch($lineid);
527 $line_rang = $objectline->rang;
528 $result = $this->updateline(
529 $lineid, // ID of line to change
530 $desc, // Description
531 0, // Unit price
532 $depth, // Quantity
533 0, // VAT rate
534 0, // Local tax 1
535 0, // Local tax 2
536 0, // FK parent line
537 0, // Discount percentage
538 '', // Price base type
539 0, // Info bits
540 0, // FK parent line
541 0, // PU ttc
542 self::$PRODUCT_TYPE, // Type
543 $line_rang, // Rang
544 SUBTOTALS_SPECIAL_CODE // Special code
545 );
546 } elseif ($current_module == 'supplier_proposal' && $this instanceof SupplierProposal) {
547 $objectline = new SupplierProposalLine($this->db);
548 $objectline->fetch($lineid);
549 $line_rang = $objectline->rang;
550 $result = $this->updateline(
551 $lineid, // ID of line to change
552 0, // Unit price
553 $depth, // Quantity
554 0, // Discount percentage
555 0, // VAT rate
556 0, // Local tax 1
557 0, // Local tax 2
558 $desc, // Description
559 '', // Price base type
560 0, // Info bits
561 SUBTOTALS_SPECIAL_CODE, // Special code
562 0, // FK parent line
563 0, //
564 0, //
565 0, //
566 '', //
567 self::$PRODUCT_TYPE // Type
568 );
569 } elseif ($current_module == 'order_supplier' && $this instanceof CommandeFournisseur) {
570 $objectline = new CommandeFournisseurLigne($this->db);
571 $objectline->fetch($lineid);
572 $line_rang = $objectline->rang;
573 // special code comes from old line
574 $result = $this->updateline(
575 $lineid, // ID of line to change
576 $desc, // Description
577 0, // Unit price
578 $depth, // Quantity
579 0, // Discount percentage
580 0, // VAT rate
581 0, // Local tax 1
582 0, // Local tax 2
583 '', // Price base type
584 0, // Info bits
585 self::$PRODUCT_TYPE, // Type
586 0, // no trigger
587 0, //
588 0, //
589 [], //
590 null //
591 );
592 } elseif ($current_module == 'invoice_supplier' && $this instanceof FactureFournisseur) {
593 $objectline = new SupplierInvoiceLine($this->db);
594 $objectline->fetch($lineid);
595 $line_rang = $objectline->rang;
596 $result = $this->updateline(
597 $lineid, // ID of line to change
598 $desc, // Description
599 0, // Unit price
600 0, // VAT rate
601 0, // Local tax 1
602 0, // Local tax 2
603 $depth, // Quantity
604 0, // product id
605 '', // Price base type
606 0, // Info bits
607 self::$PRODUCT_TYPE, // Type
608 0 // Discount percentage
609 );
610 }
611
612 foreach ($this->lines as $line) {
613 '@phan-var-force CommonObjectLine $line';
615 if ($line->id == $lineid) {
616 $line->extraparams["subtotal"] = $options;
617 $line->setExtraParameters();
618 }
619 }
620
621 if ($result < 0) {
622 return $result;
623 }
624
625 return $error > 0 ? 0 : $result;
626 }
627
640 public function updateSubtotalLineBlockLines($langs, $linerang, $mode, $value) // @phpstan-ignore-line
641 {
642 $current_module = $this->element;
643 // Ensure the object is one of the supported types
644 if (!in_array($current_module, self::$ALLOWED_TYPES)) {
645 $this->errors[] = $langs->trans("UnsupportedModuleError");
646 return -1; // Unsupported type
647 }
648
649 $result = 0;
650 $linerang -= 1;
651
652 $nb_lines = count($this->lines)+1;
653
654 for ($i = $linerang+1; $i < $nb_lines; $i++) {
655 if ($this->lines[$i]->special_code == SUBTOTALS_SPECIAL_CODE) {
656 if (abs($this->lines[$i]->qty) <= (int) $this->lines[$linerang]->qty) {
657 return 1;
658 }
659 } else {
660 if ($current_module == 'facture' && $this instanceof Facture) {
661 // Preserve the original entry mode of the line so the total is not drifted by rounding.
662 $line_price_base_type = $this->lines[$i]->getPriceBaseType();
663 $line_pu = ($line_price_base_type === 'TTC') ? $this->lines[$i]->subprice_ttc : $this->lines[$i]->subprice;
664 $result = $this->updateline(
665 $this->lines[$i]->id,
666 $this->lines[$i]->desc,
667 $line_pu,
668 $this->lines[$i]->qty,
669 $mode == 'discount' ? $value : $this->lines[$i]->remise_percent,
670 $this->lines[$i]->date_start,
671 $this->lines[$i]->date_end,
672 $mode == 'tva' ? $value : $this->lines[$i]->tva_tx,
673 $this->lines[$i]->localtax1_tx,
674 $this->lines[$i]->localtax2_tx,
675 $line_price_base_type,
676 $this->lines[$i]->info_bits,
677 $this->lines[$i]->product_type,
678 $this->lines[$i]->fk_parent_line,
679 0,
680 $this->lines[$i]->fk_fournprice,
681 $this->lines[$i]->pa_ht,
682 $this->lines[$i]->label,
683 $this->lines[$i]->special_code,
684 $this->lines[$i]->array_options,
685 $this->lines[$i]->situation_percent,
686 $this->lines[$i]->fk_unit,
687 $this->lines[$i]->multicurrency_subprice
688 );
689 } elseif ($current_module == 'commande' && $this instanceof Commande) {
690 // Preserve the original entry mode of the line so the total is not drifted by rounding.
691 $line_price_base_type = $this->lines[$i]->getPriceBaseType();
692 $line_pu = ($line_price_base_type === 'TTC') ? $this->lines[$i]->subprice_ttc : $this->lines[$i]->subprice;
693 $result = $this->updateline(
694 $this->lines[$i]->id,
695 $this->lines[$i]->desc,
696 $line_pu,
697 $this->lines[$i]->qty,
698 $mode == 'discount' ? $value : $this->lines[$i]->remise_percent,
699 $mode == 'tva' ? $value : $this->lines[$i]->tva_tx,
700 $this->lines[$i]->localtax1_rate,
701 $this->lines[$i]->localtax2_rate,
702 $line_price_base_type,
703 $this->lines[$i]->info_bits,
704 $this->lines[$i]->date_start,
705 $this->lines[$i]->date_end,
706 $this->lines[$i]->product_type,
707 $this->lines[$i]->fk_parent_line,
708 0,
709 $this->lines[$i]->fk_fournprice,
710 $this->lines[$i]->pa_ht,
711 $this->lines[$i]->label,
712 $this->lines[$i]->special_code,
713 $this->lines[$i]->array_options,
714 $this->lines[$i]->fk_unit,
715 $this->lines[$i]->multicurrency_subprice
716 );
717 } elseif ($current_module == 'propal' && $this instanceof Propal) {
718 // Preserve the original entry mode of the line so the total is not drifted by rounding.
719 $line_price_base_type = $this->lines[$i]->getPriceBaseType();
720 $line_pu = ($line_price_base_type === 'TTC') ? $this->lines[$i]->subprice_ttc : $this->lines[$i]->subprice;
721 $result = $this->updateline(
722 $this->lines[$i]->id,
723 $line_pu,
724 $this->lines[$i]->qty,
725 $mode == 'discount' ? $value : $this->lines[$i]->remise_percent,
726 $mode == 'tva' ? $value : $this->lines[$i]->tva_tx,
727 $this->lines[$i]->localtax1_rate,
728 $this->lines[$i]->localtax2_rate,
729 $this->lines[$i]->desc,
730 $line_price_base_type,
731 $this->lines[$i]->info_bits,
732 $this->lines[$i]->special_code,
733 $this->lines[$i]->fk_parent_line,
734 0,
735 $this->lines[$i]->fk_fournprice,
736 $this->lines[$i]->pa_ht,
737 $this->lines[$i]->label,
738 $this->lines[$i]->product_type,
739 $this->lines[$i]->date_start,
740 $this->lines[$i]->date_end,
741 $this->lines[$i]->array_options,
742 $this->lines[$i]->fk_unit,
743 $this->lines[$i]->multicurrency_subprice
744 );
745 }
746 if ($result < 0) {
747 return $result;
748 }
749 }
750 }
751 return 1;
752 }
753
763 public function getSubtotalLineAmount($line)
764 {
765 $final_amount = 0;
766 for ($i = $line->rang-1; $i > 0; $i--) {
767 if (is_null($this->lines[$i-1]) || $this->lines[$i-1]->rang >= $line->rang) {
768 continue;
769 }
770 if ($this->lines[$i-1]->special_code == SUBTOTALS_SPECIAL_CODE && $this->lines[$i-1]->qty > 0) {
771 if ($this->lines[$i-1]->qty <= abs($line->qty)) {
772 return price($final_amount);
773 }
774 } else {
775 $final_amount += $this->lines[$i-1]->total_ht;
776 }
777 }
778 return price($final_amount);
779 }
780
790 public function getSubtotalLineMulticurrencyAmount($line)
791 {
792 $final_amount = 0;
793 for ($i = $line->rang-1; $i > 0; $i--) {
794 if (is_null($this->lines[$i-1]) || $this->lines[$i-1]->rang >= $line->rang) {
795 continue;
796 }
797 if ($this->lines[$i-1]->special_code == SUBTOTALS_SPECIAL_CODE && $this->lines[$i-1]->qty>0) {
798 if ($this->lines[$i-1]->qty <= abs($line->qty)) {
799 return price($final_amount);
800 }
801 } else {
802 $final_amount += $this->lines[$i-1]->multicurrency_total_ht;
803 }
804 }
805 return price($final_amount);
806 }
807
814 public function getSubtotalColors($level)
815 {
816 return getDolGlobalString('SUBTOTAL_BACK_COLOR_LEVEL_'.abs($level));
817 }
818
826 public function getPossibleTitles()
827 {
828 $titles = array();
829 foreach ($this->lines as $line) {
830 if ($line->special_code == SUBTOTALS_SPECIAL_CODE && $line->qty > 0) {
831 $titles[$line->desc] = $line->desc;
832 }
833 if ($line->special_code == SUBTOTALS_SPECIAL_CODE && $line->qty < 0) {
834 unset($titles[$line->desc]);
835 }
836 }
837 return $titles;
838 }
839
848 public function getPossibleLevels($langs)
849 {
850 $depth_array = array();
851 $max_depth = getDolGlobalString('SUBTOTAL_'.strtoupper($this->element).'_MAX_DEPTH', 2);
852 for ($i = 0; $i < $max_depth; $i++) {
853 $depth_array[$i + 1] = $langs->trans("SubtotalLevel", $i + 1);
854 }
855 return $depth_array;
856 }
857
866 public function getPredefinedTitles()
867 {
868 $titles = array();
869
870 $sql = "SELECT label FROM ".MAIN_DB_PREFIX."c_subtotals_titles";
871 $sql .= " WHERE active = 1 AND entity IN (".getEntity('c_subtotals_titles').")";
872 $sql .= " ORDER BY label ASC";
873
874 $resql = $this->db->query($sql);
875 if ($resql) {
876 while ($obj = $this->db->fetch_object($resql)) {
877 $titles[dol_escape_htmltag($obj->label)] = $obj->label;
878 }
879 }
880
881 return $titles;
882 }
883
892 public function getPredefinedTexts()
893 {
894 $texts = array();
895
896 $sql = "SELECT rowid, label, content FROM ".MAIN_DB_PREFIX."c_subtotals_texts";
897 $sql .= " WHERE active = 1 AND entity IN (".getEntity('c_subtotals_texts').")";
898 $sql .= " ORDER BY label ASC";
899
900 $resql = $this->db->query($sql);
901 if ($resql) {
902 while ($obj = $this->db->fetch_object($resql)) {
903 $texts[(int) $obj->rowid] = array('label' => $obj->label, 'content' => $obj->content);
904 }
905 }
906
907 return $texts;
908 }
909
917 public function getDisabledShippmentSubtotalLines()
918 {
919 $toDisableLines = array();
920 $toDisable = true;
921 $oldDesc = "";
922 $oldDepth = 0;
923
924 foreach ($this->lines as $titleLine) {
925 if ($titleLine->special_code != SUBTOTALS_SPECIAL_CODE || $titleLine->qty <= 0) {
926 continue;
927 }
928 foreach ($this->lines as $line) {
929 if ($line->id == $titleLine->id) {
930 $oldDesc = $line->desc;
931 $oldDepth = $line->qty;
932 }
933 if ($line->special_code != SUBTOTALS_SPECIAL_CODE && $line->fk_product_type == 0 && !empty($oldDesc) && !empty($oldDepth)) {
934 $toDisable = false;
935 }
936 if ($line->special_code == SUBTOTALS_SPECIAL_CODE && $line->qty == -$oldDepth && $line->desc == $oldDesc) {
937 if ($toDisable) {
938 $toDisableLines = array_merge($toDisableLines, array($titleLine->id, $line->id));
939 }
940 $oldDesc = "";
941 $oldDepth = 0;
942 $toDisable = true;
943 break;
944 }
945 }
946 }
947 return $toDisableLines;
948 }
949}
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
Class to manage predefined suppliers products.
Class to manage line orders.
Class to manage customers orders.
Class to manage lines of shipment.
Class to manage suppliers invoices.
Class to manage invoices.
Class to manage invoice lines of templates.
Class to manage invoice templates.
Class to manage intervention lines.
Class to manage proposals.
Class to manage line invoices.
Class to manage price ask supplier.
Class to manage supplier_proposal lines.
dol_html_entity_decode($a, $b, $c='UTF-8', $keepsomeentities=0)
Replace html_entity_decode functions to manage errors.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
Definition html.lib.php:172