Passed
Push — master ( 667027...052b73 )
by Sylvain
04:09
created

Transaction::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 3
cts 3
cp 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Model;
6
7
use Application\Traits\HasInternalRemarks;
8
use Application\Traits\HasName;
9
use Application\Traits\HasRemarks;
10
use Cake\Chronos\Chronos;
11
use Doctrine\Common\Collections\ArrayCollection;
12
use Doctrine\Common\Collections\Collection;
13
use Doctrine\ORM\Mapping as ORM;
14
use Money\Currencies\ISOCurrencies;
15
use Money\Formatter\DecimalMoneyFormatter;
16
use Money\Money;
17
18
/**
19
 * An accounting journal entry (simple or compound)
20
 *
21
 * @ORM\Entity(repositoryClass="Application\Repository\TransactionRepository")
22
 * @ORM\HasLifecycleCallbacks
23
 */
24
class Transaction extends AbstractModel
25
{
26
    use HasName;
27
    use HasRemarks;
28
    use HasInternalRemarks;
29
30
    /**
31
     * @var Chronos
32
     * @ORM\Column(type="datetime")
33
     */
34
    private $transactionDate;
35
36
    /**
37
     * @var Collection
38
     * @ORM\OneToMany(targetEntity="TransactionLine", mappedBy="transaction")
39
     */
40
    private $transactionLines;
41
42
    /**
43
     * @var Collection
44
     * @ORM\OneToMany(targetEntity="AccountingDocument", mappedBy="transaction")
45
     */
46
    private $accountingDocuments;
47
48
    /**
49
     * @var ExpenseClaim
50
     *
51
     * @ORM\ManyToOne(targetEntity="ExpenseClaim", inversedBy="transactions")
52
     * @ORM\JoinColumns({
53
     *     @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
54
     * })
55
     */
56
    private $expenseClaim;
57
58
    /**
59
     * @var string
60
     *
61
     * @ORM\Column(type="string", length=18, options={"default" = ""})
62
     */
63
    private $datatransRef = '';
64
65
    /**
66
     * @var Money
67
     *
68
     * @ORM\Column(type="Money", nullable=true, options={"unsigned" = true})
69
     */
70
    private $balance;
71
72
    /**
73
     * Constructor
74
     */
75 25
    public function __construct()
76
    {
77 25
        $this->transactionLines = new ArrayCollection();
78 25
        $this->accountingDocuments = new ArrayCollection();
79 25
    }
80
81
    /**
82
     * Set date of transaction
83
     *
84
     * @param Chronos $transactionDate
85
     */
86 17
    public function setTransactionDate(Chronos $transactionDate): void
87
    {
88 17
        $this->transactionDate = $transactionDate;
89 17
    }
90
91
    /**
92
     * Get date of transaction
93
     *
94
     * @return Chronos
95
     */
96 8
    public function getTransactionDate(): Chronos
97
    {
98 8
        return $this->transactionDate;
99
    }
100
101
    /**
102
     * Notify when a transaction line is added
103
     * This should only be called by TransactionLine::setTransaction()
104
     *
105
     * @param TransactionLine $transactionLine
106
     */
107 16
    public function transactionLineAdded(TransactionLine $transactionLine): void
108
    {
109 16
        $this->transactionLines->add($transactionLine);
110 16
    }
111
112
    /**
113
     * Notify when a transaction line is removed
114
     * This should only be called by TransactionLine::setTransaction()
115
     *
116
     * @param TransactionLine $transactionLine
117
     */
118 1
    public function transactionLineRemoved(TransactionLine $transactionLine): void
119
    {
120 1
        $this->transactionLines->removeElement($transactionLine);
121 1
    }
122
123
    /**
124
     * @return Collection
125
     */
126 19
    public function getTransactionLines(): Collection
127
    {
128 19
        return $this->transactionLines;
129
    }
130
131
    /**
132
     * Notify the transaction that an accounting document was added
133
     * This should only be called by AccountingDocument::setTransaction()
134
     *
135
     * @param AccountingDocument $document
136
     */
137 1
    public function accountingDocumentAdded(AccountingDocument $document): void
138
    {
139 1
        $this->accountingDocuments->add($document);
140 1
    }
141
142
    /**
143
     * Notify the transaction that an accounting document was removed
144
     * This should only be called by AccountingDocument::setTransaction()
145
     *
146
     * @param AccountingDocument $document
147
     */
148 1
    public function accountingDocumentRemoved(AccountingDocument $document): void
149
    {
150 1
        $this->accountingDocuments->removeElement($document);
151 1
    }
152
153
    /**
154
     * Get accounting documents
155
     *
156
     * @return Collection
157
     */
158 1
    public function getAccountingDocuments(): Collection
159
    {
160 1
        return $this->accountingDocuments;
161
    }
162
163
    /**
164
     * Set expense claim
165
     *
166
     * @param null|ExpenseClaim $expenseClaim
167
     */
168 1
    public function setExpenseClaim(?ExpenseClaim $expenseClaim): void
169
    {
170 1
        if ($this->expenseClaim && $expenseClaim !== $this->expenseClaim) {
171 1
            $this->expenseClaim->transactionRemoved($this);
172
        }
173
174 1
        $this->expenseClaim = $expenseClaim;
175 1
        $this->expenseClaim && $this->expenseClaim->transactionAdded($this);
176 1
    }
177
178
    /**
179
     * Get expense claim
180
     *
181
     * @return null|ExpenseClaim
182
     */
183
    public function getExpenseClaim(): ?ExpenseClaim
184
    {
185
        return $this->expenseClaim;
186
    }
187
188
    /**
189
     * Get Datatrans payment reference number
190
     *
191
     * @param string $datatransRef
192
     */
193 4
    public function setDatatransRef(string $datatransRef): void
194
    {
195 4
        $this->datatransRef = $datatransRef;
196 4
    }
197
198
    /**
199
     * Set Datatrans payment reference number
200
     *
201
     * @return string
202
     */
203 2
    public function getDatatransRef(): string
204
    {
205 2
        return $this->datatransRef;
206
    }
207
208
    /**
209
     * Automatically called by Doctrine whenever a transaction is created or updated
210
     *
211
     * @ORM\PrePersist
212
     * @ORM\PreUpdate
213
     */
214 16
    public function checkBalance(): void
215
    {
216 16
        $totalDebit = Money::CHF(0);
217 16
        $totalCredit = Money::CHF(0);
218 16
        foreach ($this->getTransactionLines() as $i => $line) {
219 8
            if ($line->getDebit()) {
220 8
                $totalDebit = $totalDebit->add($line->getBalance());
221
            }
222 8
            if ($line->getCredit()) {
223 8
                $totalCredit = $totalCredit->add($line->getBalance());
224
            }
225
        }
226
227 16
        if (!$totalDebit->equals($totalCredit)) {
228 1
            $currencies = new ISOCurrencies();
229 1
            $moneyFormatter = new DecimalMoneyFormatter($currencies);
230
231 1
            throw new \Application\Api\Exception(sprintf('Transaction %s non-équilibrée, débits: %s, crédits: %s', $this->getId() ?? 'NEW', $moneyFormatter->format($totalDebit), $moneyFormatter->format($totalCredit)));
232
        }
233 15
    }
234
235
    /**
236
     * Get total balance
237
     *
238
     * Read only, computed by SQL triggers
239
     *
240
     * @return Money
241
     */
242
    public function getBalance(): Money
243
    {
244
        return $this->balance;
245
    }
246
}
247