Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.95% covered (success)
95.95%
71 / 74
83.33% covered (warning)
83.33%
15 / 18
CRAP
0.00% covered (danger)
0.00%
0 / 1
Bill
95.95% covered (success)
95.95%
71 / 74
83.33% covered (warning)
83.33%
15 / 18
19
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
1
 getId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 buildNumber
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
1
 getNumber
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getStatus
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setStatus
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPaymentStatus
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setPaymentStatus
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setCurrency
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCurrency
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getVouchers
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addVoucher
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTrackings
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addTracking
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getElements
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addElement
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 toArray
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
1
 jsonSerialize
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Jingga
4 *
5 * PHP Version 8.1
6 *
7 * @package   Modules\Billing\Models
8 * @copyright Dennis Eichhorn
9 * @license   OMS License 2.0
10 * @version   1.0.0
11 * @link      https://jingga.app
12 */
13declare(strict_types=1);
14
15namespace Modules\Billing\Models;
16
17use Modules\Admin\Models\Account;
18use Modules\Admin\Models\NullAccount;
19use Modules\ClientManagement\Models\Client;
20use Modules\Media\Models\Collection;
21use Modules\SupplierManagement\Models\Supplier;
22use phpOMS\Localization\ISO4217CharEnum;
23use phpOMS\Localization\ISO639x1Enum;
24use phpOMS\Stdlib\Base\FloatInt;
25
26/**
27 * Bill class.
28 *
29 * @package Modules\Billing\Models
30 * @license OMS License 2.0
31 * @link    https://jingga.app
32 * @since   1.0.0
33 */
34class Bill implements \JsonSerializable
35{
36    /**
37     * ID.
38     *
39     * @var int
40     * @since 1.0.0
41     */
42    public int $id = 0;
43
44    /**
45     * Sequence.
46     *
47     * Incrementing value depending on multiple columns e.g.:
48     *      id & unit
49     *      id & unit & type
50     *      id & unit & year
51     *
52     * @var int
53     * @since 1.0.0
54     */
55    public int $sequence = 0;
56
57    public int $unit = 0;
58
59    public int $source = 0;
60
61    /**
62     * Number ID.
63     *
64     * @var string
65     * @since 1.0.0
66     */
67    public string $number = '';
68
69    /**
70     * Bill type.
71     *
72     * @var BillType
73     * @since 1.0.0
74     */
75    public BillType $type;
76
77    public ?Collection $template = null;
78
79    /**
80     * Bill status.
81     *
82     * @var int
83     * @since 1.0.0
84     */
85    public int $status = BillStatus::DRAFT;
86
87    /**
88     * Bill payment status
89     *
90     * @var int
91     * @since 1.0.0
92     */
93    public int $paymentStatus = BillPaymentStatus::UNPAID;
94
95    /**
96     * Bill created at.
97     *
98     * @var \DateTimeImmutable
99     * @since 1.0.0
100     */
101    public \DateTimeImmutable $createdAt;
102
103    /**
104     * Bill created at.
105     *
106     * @var null|\DateTime
107     * @since 1.0.0
108     */
109    public ?\DateTime $billDate = null;
110
111    /**
112     * Bill created at.
113     *
114     * @var null|\DateTime
115     * @since 1.0.0
116     */
117    public ?\DateTime $performanceDate = null;
118
119    /**
120     * Bill send at.
121     *
122     * @var null|\DateTime
123     * @since 1.0.0
124     */
125    public ?\DateTime $send = null;
126
127    /**
128     * Creator.
129     *
130     * @var Account
131     * @since 1.0.0
132     */
133    public Account $createdBy;
134
135    public ?Client $client = null;
136
137    public ?Supplier $supplier = null;
138
139    public string $language = ISO639x1Enum::_EN;
140
141    public string $accountNumber = '';
142
143    /**
144     * Receiver.
145     *
146     * @var string
147     * @since 1.0.0
148     */
149    public string $shipTo = '';
150
151    /**
152     * For the attention of.
153     *
154     * @var string
155     * @since 1.0.0
156     */
157    public string $shipFAO = '';
158
159    /**
160     * Shipping address.
161     *
162     * @var string
163     * @since 1.0.0
164     */
165    public string $shipAddress = '';
166
167    /**
168     * Shipping city.
169     *
170     * @var string
171     * @since 1.0.0
172     */
173    public string $shipCity = '';
174
175    /**
176     * Shipping zip.
177     *
178     * @var string
179     * @since 1.0.0
180     */
181    public string $shipZip = '';
182
183    /**
184     * Shipping country.
185     *
186     * @var string
187     * @since 1.0.0
188     */
189    public string $shipCountry = '';
190
191    /**
192     * Billing.
193     *
194     * @var string
195     * @since 1.0.0
196     */
197    public string $billTo = '';
198
199    /**
200     * Billing for the attention of.
201     *
202     * @var string
203     * @since 1.0.0
204     */
205    public string $billFAO = '';
206
207    /**
208     * Billing address.
209     *
210     * @var string
211     * @since 1.0.0
212     */
213    public string $billAddress = '';
214
215    /**
216     * Billing city.
217     *
218     * @var string
219     * @since 1.0.0
220     */
221    public string $billCity = '';
222
223    /**
224     * Billing zip.
225     *
226     * @var string
227     * @since 1.0.0
228     */
229    public string $billZip = '';
230
231    /**
232     * Billing country.
233     *
234     * @var string
235     * @since 1.0.0
236     */
237    public string $billCountry = '';
238
239    public string $billEmail = '';
240
241    /**
242     * Person refering for this order.
243     *
244     * @var Account
245     * @since 1.0.0
246     */
247    public Account $referral;
248
249    public string $referralName = '';
250
251    /**
252     * Net amount.
253     *
254     * @var FloatInt
255     * @since 1.0.0
256     */
257    public FloatInt $netProfit;
258
259    /**
260     * Gross amount.
261     *
262     * @var FloatInt
263     * @since 1.0.0
264     */
265    public FloatInt $grossProfit;
266
267    /**
268     * Costs in net.
269     *
270     * @var FloatInt
271     * @since 1.0.0
272     */
273    public FloatInt $netCosts;
274
275    /**
276     * Profit in net.
277     *
278     * @var FloatInt
279     * @since 1.0.0
280     */
281    public FloatInt $grossCosts;
282
283    /**
284     * Costs in net.
285     *
286     * @var FloatInt
287     * @since 1.0.0
288     */
289    public FloatInt $netSales;
290
291    /**
292     * Profit in net.
293     *
294     * @var FloatInt
295     * @since 1.0.0
296     */
297    public FloatInt $grossSales;
298
299    /**
300     * Costs in net.
301     *
302     * @var FloatInt
303     * @since 1.0.0
304     */
305    public FloatInt $netDiscount;
306
307    /**
308     * Profit in net.
309     *
310     * @var FloatInt
311     * @since 1.0.0
312     */
313    public FloatInt $grossDiscount;
314
315    /**
316     * Insurance fees in net.
317     *
318     * @var FloatInt
319     * @since 1.0.0
320     */
321    public FloatInt $insurance;
322
323    /**
324     * Freight in net.
325     *
326     * @var FloatInt
327     * @since 1.0.0
328     */
329    public FloatInt $freight;
330
331    /**
332     * Currency.
333     *
334     * @var string
335     * @since 1.0.0
336     */
337    public string $currency = ISO4217CharEnum::_EUR;
338
339    /**
340     * Info text.
341     *
342     * @var string
343     * @since 1.0.0
344     */
345    public string $header = '';
346
347    /**
348     * Info text.
349     *
350     * @var string
351     * @since 1.0.0
352     */
353    public string $footer = '';
354
355    /**
356     * Info text.
357     *
358     * @var string
359     * @since 1.0.0
360     */
361    public string $info = '';
362
363    /**
364     * Payment type.
365     *
366     * @var int
367     * @since 1.0.0
368     */
369    public int $payment = 0;
370
371    /**
372     * Payment text.
373     *
374     * @var string
375     * @since 1.0.0
376     */
377    public string $paymentText = '';
378
379    /**
380     * Terms.
381     *
382     * @var int
383     * @since 1.0.0
384     */
385    public int $terms = 0;
386
387    /**
388     * Terms text.
389     *
390     * @var string
391     * @since 1.0.0
392     */
393    public string $termsText = '';
394
395    /**
396     * Shipping.
397     *
398     * @var int
399     * @since 1.0.0
400     */
401    public int $shipping = 0;
402
403    /**
404     * Shipping text.
405     *
406     * @var string
407     * @since 1.0.0
408     */
409    public string $shippingText = '';
410
411    /**
412     * Vouchers used.
413     *
414     * @var array
415     * @since 1.0.0
416     */
417    private array $vouchers = [];
418
419    /**
420     * Tracking ids for shipping.
421     *
422     * @var array
423     * @since 1.0.0
424     */
425    private array $trackings = [];
426
427    /**
428     * Bill elements / bill lines.
429     *
430     * @var BillElement[]
431     * @since 1.0.0
432     */
433    public array $elements = [];
434
435    /**
436     * Reference to other Bill (delivery note/credit note etc).
437     *
438     * @var int
439     * @since 1.0.0
440     */
441    public int $reference = 0;
442
443    /**
444     * Constructor.
445     *
446     * @since 1.0.0
447     */
448    public function __construct()
449    {
450        $this->netProfit     = new FloatInt(0);
451        $this->grossProfit   = new FloatInt(0);
452        $this->netCosts      = new FloatInt(0);
453        $this->grossCosts    = new FloatInt(0);
454        $this->netSales      = new FloatInt(0);
455        $this->grossSales    = new FloatInt(0);
456        $this->netDiscount   = new FloatInt(0);
457        $this->grossDiscount = new FloatInt(0);
458
459        $this->billDate  = new \DateTime('now');
460        $this->createdAt = new \DateTimeImmutable();
461        $this->createdBy = new NullAccount();
462        $this->referral  = new NullAccount();
463        $this->type      = new NullBillType();
464    }
465
466    /**
467     * Get id.
468     *
469     * @return int Model id
470     *
471     * @since 1.0.0
472     */
473    public function getId() : int
474    {
475        return $this->id;
476    }
477
478    /**
479     * Build the invoice number.
480     *
481     * @return void
482     *
483     * @since 1.0.0
484     */
485    public function buildNumber() : void
486    {
487        $this->number = \str_replace(
488            [
489                '{y}',
490                '{m}',
491                '{d}',
492                '{id}',
493                '{sequence}',
494                '{type}',
495            ],
496            [
497                $this->createdAt->format('Y'),
498                $this->createdAt->format('m'),
499                $this->createdAt->format('d'),
500                $this->id,
501                $this->sequence,
502                $this->type->id,
503            ],
504            $this->type->numberFormat
505        );
506    }
507
508    /**
509     * Get Bill number.
510     *
511     * @return string
512     *
513     * @since 1.0.0
514     */
515    public function getNumber() : string
516    {
517        if (empty($this->number)) {
518            $this->buildNumber();
519        }
520
521        return $this->number;
522    }
523
524    /**
525     * Get status
526     *
527     * @return int
528     *
529     * @since 1.0.0
530     */
531    public function getStatus() : int
532    {
533        return $this->status;
534    }
535
536    /**
537     * Set status
538     *
539     * @param int $status Status
540     *
541     * @return void
542     *
543     * @since 1.0.0
544     */
545    public function setStatus(int $status) : void
546    {
547        $this->status = $status;
548    }
549
550    /**
551     * Get paymentStatus
552     *
553     * @return int
554     *
555     * @since 1.0.0
556     */
557    public function getPaymentStatus() : int
558    {
559        return $this->paymentStatus;
560    }
561
562    /**
563     * Set paymentStatus
564     *
565     * @param int $paymentStatus Status
566     *
567     * @return void
568     *
569     * @since 1.0.0
570     */
571    public function setPaymentStatus(int $paymentStatus) : void
572    {
573        $this->paymentStatus = $paymentStatus;
574    }
575
576    /**
577     * Set currency.
578     *
579     * @param string $currency Currency
580     *
581     * @return void
582     *
583     * @since 1.0.0
584     */
585    public function setCurrency(string $currency) : void
586    {
587        $this->currency = $currency;
588    }
589
590    /**
591     * Get currency.
592     *
593     * @return string
594     *
595     * @since 1.0.0
596     */
597    public function getCurrency() : string
598    {
599        return $this->currency;
600    }
601
602    /**
603     * Get vouchers.
604     *
605     * @return array
606     *
607     * @since 1.0.0
608     */
609    public function getVouchers() : array
610    {
611        return $this->vouchers;
612    }
613
614    /**
615     * Add voucher.
616     *
617     * @param string $voucher Voucher code
618     *
619     * @return void
620     *
621     * @since 1.0.0
622     */
623    public function addVoucher(string $voucher) : void
624    {
625        $this->vouchers[] = $voucher;
626    }
627
628    /**
629     * Get tracking ids for shipment.
630     *
631     * @return array
632     *
633     * @since 1.0.0
634     */
635    public function getTrackings() : array
636    {
637        return $this->trackings;
638    }
639
640    /**
641     * Add tracking id.
642     *
643     * @param string $tracking Tracking id
644     *
645     * @return void
646     *
647     * @since 1.0.0
648     */
649    public function addTracking(string $tracking) : void
650    {
651        $this->trackings[] = $tracking;
652    }
653
654    /**
655     * Get Bill elements.
656     *
657     * @return BillElement[]
658     *
659     * @since 1.0.0
660     */
661    public function getElements() : array
662    {
663        return $this->elements;
664    }
665
666    /**
667     * Add Bill element.
668     *
669     * @param BillElement $element Bill element
670     *
671     * @return void
672     *
673     * @since 1.0.0
674     */
675    public function addElement(BillElement $element) : void
676    {
677        $this->elements[] = $element;
678
679        $this->netProfit->add($element->totalProfitNet->getInt());
680        $this->grossProfit->add($element->totalProfitGross->getInt());
681        $this->netCosts->add($element->totalPurchasePriceNet->getInt());
682        $this->grossCosts->add($element->totalPurchasePriceGross->getInt());
683        $this->netSales->add($element->totalSalesPriceNet->getInt());
684        $this->grossSales->add($element->totalSalesPriceGross->getInt());
685        $this->netDiscount->add($element->totalDiscountP->getInt());
686
687        // @todo: Discount might be in quantities
688        $this->grossDiscount->add((int) ($element->taxR->getInt() * $element->totalDiscountP->getInt() / 10000));
689    }
690
691    /**
692     * {@inheritdoc}
693     */
694    public function toArray() : array
695    {
696        return [
697            'id'           => $this->id,
698            'number'       => $this->number,
699            'type'         => $this->type,
700            'shipTo'       => $this->shipTo,
701            'shipFAO'      => $this->shipFAO,
702            'shipAddress'  => $this->shipAddress,
703            'shipCity'     => $this->shipCity,
704            'shipZip'      => $this->shipZip,
705            'shipCountry'  => $this->shipCountry,
706            'billTo'       => $this->billTo,
707            'billFAO'      => $this->billFAO,
708            'billAddress'  => $this->billAddress,
709            'billCity'     => $this->billCity,
710            'billZip'      => $this->billZip,
711            'billCountry'  => $this->billCountry,
712        ];
713    }
714
715    /**
716     * {@inheritdoc}
717     */
718    public function jsonSerialize() : mixed
719    {
720        return $this->toArray();
721    }
722
723    use \Modules\Attribute\Models\AttributeHolderTrait;
724    use \Modules\Editor\Models\EditorDocListTrait;
725    use \Modules\Media\Models\MediaListTrait;
726}