dolibarr 24.0.0-beta
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-2025 Frédéric France <frederic.france@free.fr>
5 * Copyright (C) 2025 Charlene Benke <charlene@patas-monkey.com>
6
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 ];
63
64
79 public function addSubtotalLine($langs, $desc, $depth, $options = array(), $parent_line = 0)
80 {
81 if (empty($desc)) {
82 $this->errors[] = $langs->trans("TitleNeedDesc");
83 return -1;
84 }
85 $current_module = $this->element;
86 // Ensure the object is one of the supported types
87 if (!in_array($current_module, self::$ALLOWED_TYPES)) {
88 $this->errors[] = $langs->trans("UnsupportedModuleError");
89 return -1; // Unsupported type
90 }
91 $error = 0;
92 $desc = dol_html_entity_decode($desc, ENT_QUOTES);
93 $rang = -1;
94 $next_line = false;
95 $result = 0;
96
97 if ($depth < 0 && $current_module != 'shipping') {
98 foreach ($this->lines as $line) {
99 if (!$next_line && $line->desc == $desc && $line->qty == -$depth) {
100 $next_line = true;
101 continue;
102 }
103 if ($next_line && $line->desc == $desc && $line->qty == $depth) {
104 $next_line = false;
105 continue;
106 }
107 if ($next_line && $line->special_code == SUBTOTALS_SPECIAL_CODE && abs($line->qty) <= abs($depth)) {
108 $rang = $line->rang;
109 break;
110 }
111 }
112 }
113
114 if ($depth > 0 && $current_module != 'shipping') {
115 $max_existing_level = 0;
116
117 foreach ($this->lines as $line) {
118 if ($line->special_code == SUBTOTALS_SPECIAL_CODE && $line->qty > $max_existing_level) {
119 $max_existing_level = $line->qty;
120 }
121 }
122
123 if ($max_existing_level+1 < $depth) {
124 $depth = $max_existing_level+1;
125 $this->errors[] = $langs->trans("TitleAddedLevelTooHigh", $depth);
126
127 $error ++;
128 }
129 }
130
131 // Add the line calling the right module
132 if ($current_module == 'facture' && $this instanceof Facture) {
133 $result = $this->addline(
134 $desc, // Description
135 0, // Unit price
136 $depth, // Quantity
137 0, // VAT rate
138 0, // Local tax 1
139 0, // Local tax 2
140 0, // FK product
141 0, // Discount percentage
142 '', // Date start
143 '', // Date end
144 0, // FK code ventilation
145 0, // Info bits
146 0, // FK remise except
147 '', // Price base type
148 0, // PU ttc
149 self::$PRODUCT_TYPE, // Type
150 $rang, // Rang
151 SUBTOTALS_SPECIAL_CODE // Special code
152 );
153 } elseif ($current_module == 'propal' && $this instanceof Propal) {
154 $result = $this->addline(
155 $desc, // Description
156 0, // Unit price
157 $depth, // Quantity
158 0, // VAT rate
159 0, // Local tax 1
160 0, // Local tax 2
161 0, // FK product
162 0, // Discount percentage
163 '', // Price base type
164 0, // PU ttc
165 0, // Info bits
166 self::$PRODUCT_TYPE, // Type
167 $rang, // Rang
168 SUBTOTALS_SPECIAL_CODE // Special code
169 );
170 } elseif ($current_module == 'commande' && $this instanceof Commande) {
171 $result = $this->addline(
172 $desc, // Description
173 0, // Unit price
174 $depth, // Quantity
175 0, // VAT rate
176 0, // Local tax 1
177 0, // Local tax 2
178 0, // FK product
179 0, // Discount percentage
180 0, // Info bits
181 0, // FK remise except
182 '', // Price base type
183 0, // PU ttc
184 '', // Date start
185 '', // Date end
186 self::$PRODUCT_TYPE, // Type
187 $rang, // Rang
188 SUBTOTALS_SPECIAL_CODE // Special code
189 );
190 } elseif ($current_module == 'shipping' && $this instanceof Expedition) {
191 $result = $this->addline(
192 0, // Warehouse ID
193 (int) $parent_line, // Source line
194 $depth // Quantity
195 );
196 } elseif ($current_module == 'facturerec' && $this instanceof FactureRec) {
197 $rang = $rang == -1 ? $rang : $rang-1;
198 $result = $this->addline(
199 $desc, // Description
200 0, // Unit price
201 $depth, // Quantity
202 0, // VAT rate
203 0, // Local tax 1
204 0, // Local tax 2
205 0, // FK product
206 0, // Discount percentage
207 '', // Price base type
208 0, // Info bits
209 0, // FK remise except
210 0, // PU ttc
211 self::$PRODUCT_TYPE, // Type
212 $rang, // Rang
213 SUBTOTALS_SPECIAL_CODE // Special code
214 );
215 $this->fetch_lines();
216 } elseif ($current_module == 'supplier_proposal' && $this instanceof SupplierProposal) {
217 $rang = $rang == -1 ? $rang : $rang-1;
218 $result = $this->addline(
219 $desc, // Description
220 0, // Unit price
221 $depth, // Quantity
222 0, // VAT rate
223 0, // Local tax 1
224 0, // Local tax 2
225 0, // FK product
226 0, // Discount percentage
227 '', // Price base type
228 0, // PU ttc
229 0, // Info bits
230 self::$PRODUCT_TYPE, // Type
231 $rang, // Rang
232 SUBTOTALS_SPECIAL_CODE // Special code
233 );
234 } elseif ($current_module == 'order_supplier' && $this instanceof CommandeFournisseur) {
235 $rang = $rang == -1 ? $rang : $rang-1;
236 $result = $this->addline(
237 $desc, // Description
238 0, // Unit price
239 $depth, // Quantity
240 0, // VAT rate
241 0, // Local tax 1
242 0, // Local tax 2
243 0, // FK product
244 0, // fk fourn price
245 '', // ref supplier
246 0, // Remise percent
247 '', // Price base type
248 0, // PU ttc
249 self::$PRODUCT_TYPE, // Type
250 0, // info bits
251 0, // no trigger
252 null, // Date start
253 null, // Date end
254 [], // array_options
255 null, // fk_unit
256 0, // pu ht devise
257 '', // origin type
258 0, // origin id
259 $rang, // Rang
260 SUBTOTALS_SPECIAL_CODE // Special code
261 );
262 } elseif ($current_module == 'invoice_supplier' && $this instanceof FactureFournisseur) {
263 $rang = $rang == -1 ? $rang : $rang-1;
264 $result = $this->addline(
265 $desc, // Description
266 0, // Unit price
267 0, // VAT rate
268 0, // Local tax 1
269 0, // Local tax 2
270 $depth, // Quantity
271 0, // FK product
272 0, // Remise percent
273 '', // Date start
274 '', // Date end
275 0, // Code ventilation
276 0, // info bits
277 '', // Price base type
278 self::$PRODUCT_TYPE, // Type
279 $rang, // Rang
280 0, // no trigger
281 [], // array_options
282 null, // fk_unit
283 0, // origin id
284 0, // pu ht devise
285 '', // ref supplier
286 SUBTOTALS_SPECIAL_CODE // Special code
287 );
288 } elseif ($current_module == 'fichinter' && $this instanceof Fichinter) {
289 global $user;
290 $result = $this->addline(
291 $user, // user
292 $this->id, // fk_fichinter
293 $desc, // Description
294 0, // dateintervention
295 $depth, // duration
296 [], // arrayoption
297 self::$PRODUCT_TYPE, // Type
298 $rang, // Rang
299 SUBTOTALS_SPECIAL_CODE // Special code
300 );
301 }
302
303
304 if ($current_module != 'shipping') {
305 foreach ($this->lines as $line) {
306 '@phan-var-force CommonObjectLine $line';
308 if ($line->id == $result) {
309 $line->extraparams["subtotal"] = $options;
310 $line->setExtraParameters();
311 }
312 }
313 }
314
315 if ($result < 0) {
316 return $result;
317 }
318
319 return $error > 0 ? 0 : $result;
320 }
321
335 public function deleteSubtotalLine($langs, $id, $correspondingstline = false, $user = null)
336 {
337 $current_module = $this->element;
338 // Ensure the object is one of the supported types
339 if (!in_array($current_module, self::$ALLOWED_TYPES)) {
340 $this->errors[] = $langs->trans("UnsupportedModuleError");
341 return -1; // Unsupported type
342 }
343
344 $result = 0;
345
346 if ($correspondingstline) {
347 $oldDesc = "";
348 $oldDepth = 0;
349 foreach ($this->lines as $line) {
350 if ($line->id == $id) {
351 $oldDesc = $line->desc;
352 $oldDepth = $line->qty;
353 }
354 if ($line->special_code == SUBTOTALS_SPECIAL_CODE && $line->qty == -$oldDepth && $line->desc == $oldDesc) {
355 $this->deleteSubtotalLine($langs, $line->id, false, $user);
356 break;
357 }
358 }
359 }
360
361 // Add the line calling the right module
362 if ($current_module == 'facture' && $this instanceof Facture) {
363 $rowid = $id; // for phan suspicious parameter order...
364 $result = $this->deleteLine($rowid);
365 } elseif ($current_module == 'propal' && $this instanceof Propal) {
366 $rowid = $id; // for phan suspicious parameter order...
367 $result = $this->deleteLine($rowid);
368 } elseif ($current_module == 'commande' && $this instanceof Commande) {
369 $lineid = $id; // for phan suspicious parameter order...
370 $result = $this->deleteLine($user, $lineid);
371 } elseif ($current_module == 'facturerec') {
372 $line = new FactureLigneRec($this->db);
373 $line->id = $id;
374 $result = $line->delete($user);
375 } elseif ($current_module == 'shipping') {
376 $line = new ExpeditionLigne($this->db);
377 $line->id = $id;
378 $result = $line->delete($user);
379 } elseif ($current_module == 'supplier_proposal') {
380 $line = new SupplierProposalLine($this->db);
381 $line->id = $id;
382 $result = $line->delete($user);
383 } elseif ($current_module == 'order_supplier') {
384 $line = new CommandeFournisseurLigne($this->db);
385 $line->id = $id;
386 $result = $line->delete($user);
387 } elseif ($current_module == 'invoice_supplier') {
388 $line = new SupplierInvoiceLine($this->db);
389 $line->id = $id;
390 $result = $line->delete();
391 }
392
393 return $result >= 0 ? $result : -1; // Return line ID or false
394 }
395
411 public function updateSubtotalLine($langs, $lineid, $desc, $depth, $options) // @phpstan-ignore-line
412 {
413 $current_module = $this->element;
414 // Ensure the object is one of the supported types
415 if (!in_array($current_module, self::$ALLOWED_TYPES)) {
416 $this->errors[] = $langs->trans("UnsupportedModuleError");
417 return -1; // Unsupported type
418 }
419
420 $result = 0;
421 $error = 0;
422
423 $max_existing_level = 0;
424
425 if ($depth>0) {
426 foreach ($this->lines as $line) {
427 if ($line->special_code == SUBTOTALS_SPECIAL_CODE && $line->qty > $max_existing_level && $line->id != $lineid) {
428 $max_existing_level = $line->qty;
429 }
430 }
431 }
432
433 if ($max_existing_level+1 < $depth) {
434 $depth = $max_existing_level+1;
435 $this->errors[] = $langs->trans("TitleEditedLevelTooHigh");
436 $error ++;
437 }
438
439 if ($depth>0) {
440 $oldDesc = "";
441 $oldDepth = 0;
442 foreach ($this->lines as $line) {
443 if ($line->id == $lineid) {
444 $oldDesc = $line->desc;
445 $oldDepth = $line->qty;
446 }
447 if ($line->special_code == SUBTOTALS_SPECIAL_CODE && $line->qty == -$oldDepth && $line->desc == $oldDesc) {
448 $this->updateSubtotalLine($langs, $line->id, $desc, -$depth, !empty($line->extraparams["subtotal"]) ? $line->extraparams["subtotal"] : array());
449 break;
450 }
451 }
452 }
453
454 // Update the line calling the right module
455 if ($current_module == 'facture' && $this instanceof Facture) {
456 $result = $this->updateline(
457 $lineid, // ID of line to change
458 $desc, // Description
459 0, // Unit price
460 $depth, // Quantity
461 0, // Discount percentage
462 '', // Date start
463 '', // Date end
464 0, // VAT rate
465 0, // Local tax 1
466 0, // Local tax 2
467 '', // Price base type
468 0, // Info bits
469 self::$PRODUCT_TYPE, // Type
470 0, // FK parent line
471 0, // Skip update total
472 0, // FK fournprice
473 0, // PA ht
474 '', // Label
475 SUBTOTALS_SPECIAL_CODE // Special code
476 );
477 } elseif ($current_module == 'propal' && $this instanceof Propal) {
478 $result = $this->updateline(
479 $lineid, // ID of line to change
480 0, // Unit price
481 $depth, // Quantity
482 0, // Discount percentage
483 0, // VAT rate
484 0, // Local tax 1
485 0, // Local tax 2
486 $desc, // Description
487 '', // Price base type
488 0, // Info bits
489 SUBTOTALS_SPECIAL_CODE, // Special code
490 0, // FK parent line
491 0, // Skip update total
492 0, // FK fournprice
493 0, // PA ht
494 '', // Label
495 self::$PRODUCT_TYPE // Type
496 );
497 } elseif ($current_module == 'commande' && $this instanceof Commande) {
498 $result = $this->updateline(
499 $lineid, // ID of line to change
500 $desc, // Description
501 0, // Unit price
502 $depth, // Quantity
503 0, // Discount percentage
504 0, // VAT rate
505 0, // Local tax 1
506 0, // Local tax 2
507 '', // Price base type
508 0, // Info bits
509 '', // Date start
510 '', // Date end
511 self::$PRODUCT_TYPE, // Type
512 0, // FK parent line
513 0, // Skip update total
514 0, // FK fournprice
515 0, // PA ht
516 '', // Label
517 SUBTOTALS_SPECIAL_CODE // Special code
518 );
519 } elseif ($current_module == 'facturerec' && $this instanceof FactureRec) {
520 $objectline = new FactureLigneRec($this->db);
521 $objectline->fetch($lineid);
522 $line_rang = $objectline->rang;
523 $result = $this->updateline(
524 $lineid, // ID of line to change
525 $desc, // Description
526 0, // Unit price
527 $depth, // Quantity
528 0, // VAT rate
529 0, // Local tax 1
530 0, // Local tax 2
531 0, // FK parent line
532 0, // Discount percentage
533 '', // Price base type
534 0, // Info bits
535 0, // FK parent line
536 0, // PU ttc
537 self::$PRODUCT_TYPE, // Type
538 $line_rang, // Rang
539 SUBTOTALS_SPECIAL_CODE // Special code
540 );
541 } elseif ($current_module == 'supplier_proposal' && $this instanceof SupplierProposal) {
542 $objectline = new SupplierProposalLine($this->db);
543 $objectline->fetch($lineid);
544 $line_rang = $objectline->rang;
545 $result = $this->updateline(
546 $lineid, // ID of line to change
547 0, // Unit price
548 $depth, // Quantity
549 0, // Discount percentage
550 0, // VAT rate
551 0, // Local tax 1
552 0, // Local tax 2
553 $desc, // Description
554 '', // Price base type
555 0, // Info bits
556 SUBTOTALS_SPECIAL_CODE, // Special code
557 0, // FK parent line
558 0, //
559 0, //
560 0, //
561 '', //
562 self::$PRODUCT_TYPE // Type
563 );
564 } elseif ($current_module == 'order_supplier' && $this instanceof CommandeFournisseur) {
565 $objectline = new CommandeFournisseurLigne($this->db);
566 $objectline->fetch($lineid);
567 $line_rang = $objectline->rang;
568 // special code comes from old line
569 $result = $this->updateline(
570 $lineid, // ID of line to change
571 $desc, // Description
572 0, // Unit price
573 $depth, // Quantity
574 0, // Discount percentage
575 0, // VAT rate
576 0, // Local tax 1
577 0, // Local tax 2
578 '', // Price base type
579 0, // Info bits
580 self::$PRODUCT_TYPE, // Type
581 0, // no trigger
582 0, //
583 0, //
584 [], //
585 null //
586 );
587 } elseif ($current_module == 'invoice_supplier' && $this instanceof FactureFournisseur) {
588 $objectline = new SupplierInvoiceLine($this->db);
589 $objectline->fetch($lineid);
590 $line_rang = $objectline->rang;
591 $result = $this->updateline(
592 $lineid, // ID of line to change
593 $desc, // Description
594 0, // Unit price
595 0, // VAT rate
596 0, // Local tax 1
597 0, // Local tax 2
598 $depth, // Quantity
599 0, // product id
600 '', // Price base type
601 0, // Info bits
602 self::$PRODUCT_TYPE, // Type
603 0 // Discount percentage
604 );
605 }
606
607 foreach ($this->lines as $line) {
608 '@phan-var-force CommonObjectLine $line';
610 if ($line->id == $lineid) {
611 $line->extraparams["subtotal"] = $options;
612 $line->setExtraParameters();
613 }
614 }
615
616 if ($result < 0) {
617 return $result;
618 }
619
620 return $error > 0 ? 0 : $result;
621 }
622
635 public function updateSubtotalLineBlockLines($langs, $linerang, $mode, $value) // @phpstan-ignore-line
636 {
637 $current_module = $this->element;
638 // Ensure the object is one of the supported types
639 if (!in_array($current_module, self::$ALLOWED_TYPES)) {
640 $this->errors[] = $langs->trans("UnsupportedModuleError");
641 return -1; // Unsupported type
642 }
643
644 $result = 0;
645 $linerang -= 1;
646
647 $nb_lines = count($this->lines)+1;
648
649 for ($i = $linerang+1; $i < $nb_lines; $i++) {
650 if ($this->lines[$i]->special_code == SUBTOTALS_SPECIAL_CODE) {
651 if (abs($this->lines[$i]->qty) <= (int) $this->lines[$linerang]->qty) {
652 return 1;
653 }
654 } else {
655 if ($current_module == 'facture' && $this instanceof Facture) {
656 $result = $this->updateline(
657 $this->lines[$i]->id,
658 $this->lines[$i]->desc,
659 $this->lines[$i]->subprice,
660 $this->lines[$i]->qty,
661 $mode == 'discount' ? $value : $this->lines[$i]->remise_percent,
662 $this->lines[$i]->date_start,
663 $this->lines[$i]->date_end,
664 $mode == 'tva' ? $value : $this->lines[$i]->tva_tx,
665 $this->lines[$i]->localtax1_tx,
666 $this->lines[$i]->localtax2_tx,
667 'HT',
668 $this->lines[$i]->info_bits,
669 $this->lines[$i]->product_type,
670 $this->lines[$i]->fk_parent_line,
671 0,
672 $this->lines[$i]->fk_fournprice,
673 $this->lines[$i]->pa_ht,
674 $this->lines[$i]->label,
675 $this->lines[$i]->special_code,
676 $this->lines[$i]->array_options,
677 $this->lines[$i]->situation_percent,
678 $this->lines[$i]->fk_unit,
679 $this->lines[$i]->multicurrency_subprice
680 );
681 } elseif ($current_module == 'commande' && $this instanceof Commande) {
682 $result = $this->updateline(
683 $this->lines[$i]->id,
684 $this->lines[$i]->desc,
685 $this->lines[$i]->subprice,
686 $this->lines[$i]->qty,
687 $mode == 'discount' ? $value : $this->lines[$i]->remise_percent,
688 $mode == 'tva' ? $value : $this->lines[$i]->tva_tx,
689 $this->lines[$i]->localtax1_rate,
690 $this->lines[$i]->localtax2_rate,
691 'HT',
692 $this->lines[$i]->info_bits,
693 $this->lines[$i]->date_start,
694 $this->lines[$i]->date_end,
695 $this->lines[$i]->product_type,
696 $this->lines[$i]->fk_parent_line,
697 0,
698 $this->lines[$i]->fk_fournprice,
699 $this->lines[$i]->pa_ht,
700 $this->lines[$i]->label,
701 $this->lines[$i]->special_code,
702 $this->lines[$i]->array_options,
703 $this->lines[$i]->fk_unit,
704 $this->lines[$i]->multicurrency_subprice
705 );
706 } elseif ($current_module == 'propal' && $this instanceof Propal) {
707 // Preserve the original entry mode of the line so the total is not drifted by rounding.
708 $line_price_base_type = $this->lines[$i]->wasEnteredIncludingTax() ? 'TTC' : 'HT';
709 $line_pu = ($line_price_base_type === 'TTC') ? $this->lines[$i]->subprice_ttc : $this->lines[$i]->subprice;
710 $result = $this->updateline(
711 $this->lines[$i]->id,
712 $line_pu,
713 $this->lines[$i]->qty,
714 $mode == 'discount' ? $value : $this->lines[$i]->remise_percent,
715 $mode == 'tva' ? $value : $this->lines[$i]->tva_tx,
716 $this->lines[$i]->localtax1_rate,
717 $this->lines[$i]->localtax2_rate,
718 $this->lines[$i]->desc,
719 $line_price_base_type,
720 $this->lines[$i]->info_bits,
721 $this->lines[$i]->special_code,
722 $this->lines[$i]->fk_parent_line,
723 0,
724 $this->lines[$i]->fk_fournprice,
725 $this->lines[$i]->pa_ht,
726 $this->lines[$i]->label,
727 $this->lines[$i]->product_type,
728 $this->lines[$i]->date_start,
729 $this->lines[$i]->date_end,
730 $this->lines[$i]->array_options,
731 $this->lines[$i]->fk_unit,
732 $this->lines[$i]->multicurrency_subprice
733 );
734 }
735 if ($result < 0) {
736 return $result;
737 }
738 }
739 }
740 return 1;
741 }
742
752 public function getSubtotalLineAmount($line)
753 {
754 $final_amount = 0;
755 for ($i = $line->rang-1; $i > 0; $i--) {
756 if (is_null($this->lines[$i-1]) || $this->lines[$i-1]->rang >= $line->rang) {
757 continue;
758 }
759 if ($this->lines[$i-1]->special_code == SUBTOTALS_SPECIAL_CODE && $this->lines[$i-1]->qty > 0) {
760 if ($this->lines[$i-1]->qty <= abs($line->qty)) {
761 return price($final_amount);
762 }
763 } else {
764 $final_amount += $this->lines[$i-1]->total_ht;
765 }
766 }
767 return price($final_amount);
768 }
769
779 public function getSubtotalLineMulticurrencyAmount($line)
780 {
781 $final_amount = 0;
782 for ($i = $line->rang-1; $i > 0; $i--) {
783 if (is_null($this->lines[$i-1]) || $this->lines[$i-1]->rang >= $line->rang) {
784 continue;
785 }
786 if ($this->lines[$i-1]->special_code == SUBTOTALS_SPECIAL_CODE && $this->lines[$i-1]->qty>0) {
787 if ($this->lines[$i-1]->qty <= abs($line->qty)) {
788 return price($final_amount);
789 }
790 } else {
791 $final_amount += $this->lines[$i-1]->multicurrency_total_ht;
792 }
793 }
794 return price($final_amount);
795 }
796
803 public function getSubtotalColors($level)
804 {
805 return getDolGlobalString('SUBTOTAL_BACK_COLOR_LEVEL_'.abs($level));
806 }
807
815 public function getPossibleTitles()
816 {
817 $titles = array();
818 foreach ($this->lines as $line) {
819 if ($line->special_code == SUBTOTALS_SPECIAL_CODE && $line->qty > 0) {
820 $titles[$line->desc] = $line->desc;
821 }
822 if ($line->special_code == SUBTOTALS_SPECIAL_CODE && $line->qty < 0) {
823 unset($titles[$line->desc]);
824 }
825 }
826 return $titles;
827 }
828
837 public function getPossibleLevels($langs)
838 {
839 $depth_array = array();
840 $max_depth = getDolGlobalString('SUBTOTAL_'.strtoupper($this->element).'_MAX_DEPTH', 2);
841 for ($i = 0; $i < $max_depth; $i++) {
842 $depth_array[$i + 1] = $langs->trans("SubtotalLevel", $i + 1);
843 }
844 return $depth_array;
845 }
846
854 public function getDisabledShippmentSubtotalLines()
855 {
856 $toDisableLines = array();
857 $toDisable = true;
858 $oldDesc = "";
859 $oldDepth = 0;
860
861 foreach ($this->lines as $titleLine) {
862 if ($titleLine->special_code != SUBTOTALS_SPECIAL_CODE || $titleLine->qty <= 0) {
863 continue;
864 }
865 foreach ($this->lines as $line) {
866 if ($line->id == $titleLine->id) {
867 $oldDesc = $line->desc;
868 $oldDepth = $line->qty;
869 }
870 if ($line->special_code != SUBTOTALS_SPECIAL_CODE && $line->fk_product_type == 0 && !empty($oldDesc) && !empty($oldDepth)) {
871 $toDisable = false;
872 }
873 if ($line->special_code == SUBTOTALS_SPECIAL_CODE && $line->qty == -$oldDepth && $line->desc == $oldDesc) {
874 if ($toDisable) {
875 $toDisableLines = array_merge($toDisableLines, array($titleLine->id, $line->id));
876 }
877 $oldDesc = "";
878 $oldDepth = 0;
879 $toDisable = true;
880 break;
881 }
882 }
883 }
884 return $toDisableLines;
885 }
886}
$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 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.