1
|
|
|
<?php |
2
|
|
|
/* |
3
|
|
|
* Copyright (C) 2020 Jan Böhmer |
4
|
|
|
* |
5
|
|
|
* This program is free software: you can redistribute it and/or modify |
6
|
|
|
* it under the terms of the GNU Affero General Public License as published |
7
|
|
|
* by the Free Software Foundation, either version 3 of the License, or |
8
|
|
|
* (at your option) any later version. |
9
|
|
|
* |
10
|
|
|
* This program is distributed in the hope that it will be useful, |
11
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
12
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13
|
|
|
* GNU Affero General Public License for more details. |
14
|
|
|
* |
15
|
|
|
* You should have received a copy of the GNU Affero General Public License |
16
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. |
17
|
|
|
*/ |
18
|
|
|
|
19
|
|
|
namespace App\Entity; |
20
|
|
|
|
21
|
|
|
use App\Entity\Contracts\DBElementInterface; |
22
|
|
|
use App\Entity\Contracts\TimestampedElementInterface; |
23
|
|
|
use App\Entity\Embeddable\PayeeInfo; |
24
|
|
|
use App\Repository\PaymentOrderRepository; |
25
|
|
|
use App\Validator\FSRNotBlocked; |
26
|
|
|
use DateTime; |
27
|
|
|
use Doctrine\Common\Collections\ArrayCollection; |
28
|
|
|
use Doctrine\Common\Collections\Collection; |
29
|
|
|
use Doctrine\ORM\Mapping as ORM; |
30
|
|
|
use Symfony\Component\Validator\Constraints as Assert; |
31
|
|
|
use Vich\UploaderBundle\Entity\File; |
32
|
|
|
use Vich\UploaderBundle\Mapping\Annotation as Vich; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* This entity represents a request to pay money for something to a persons bank account. |
36
|
|
|
* The applicant (which can be some other person than the payment receiver) submits a payment order ("Zahlungsauftrag") |
37
|
|
|
* via the front end form. The finance officers of the department for which the payment order was submitted receive an |
38
|
|
|
* email with a verification link where they have to confirm the payment oder. |
39
|
|
|
* In the backend the back office officers can see all submitted payment orders. In the first step it is checked if a |
40
|
|
|
* payment order is factually correct, then it is exported (as SEPA-XML) to the online banking system. Another officer |
41
|
|
|
* then checks if the payment order is factually correct and then approve the payment in the online banking. |
42
|
|
|
* |
43
|
|
|
* @ORM\Entity(repositoryClass=PaymentOrderRepository::class) |
44
|
|
|
* @ORM\Table("payment_orders") |
45
|
|
|
* @Vich\Uploadable() |
46
|
|
|
* @ORM\HasLifecycleCallbacks() |
47
|
|
|
*/ |
48
|
|
|
class PaymentOrder implements DBElementInterface, TimestampedElementInterface, \Serializable |
49
|
|
|
{ |
50
|
|
|
use TimestampTrait; |
51
|
|
|
|
52
|
|
|
public const FUNDING_ID_REGEX = '/^(FA|M)-\d{3,4}-20\d{2}(_\d{2})?$/'; |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* @ORM\Id() |
56
|
|
|
* @ORM\GeneratedValue() |
57
|
|
|
* @ORM\Column(type="integer") |
58
|
|
|
*/ |
59
|
|
|
private $id; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* @var PayeeInfo |
63
|
|
|
* @ORM\Embedded(class="App\Entity\Embeddable\PayeeInfo") |
64
|
|
|
* @Assert\Valid() |
65
|
|
|
*/ |
66
|
|
|
private $bank_info; |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* @var string "Vorname" |
70
|
|
|
* @ORM\Column(type="string") |
71
|
|
|
* @Assert\NotBlank() |
72
|
|
|
*/ |
73
|
|
|
private $first_name = ''; |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* @var string "Nachname" |
77
|
|
|
* @ORM\Column(type="string") |
78
|
|
|
* @Assert\NotBlank() |
79
|
|
|
*/ |
80
|
|
|
private $last_name = ''; |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* @var Department "Struktur/Organisation" |
84
|
|
|
* @ORM\ManyToOne(targetEntity="App\Entity\Department") |
85
|
|
|
* @ORM\JoinColumn(nullable=false) |
86
|
|
|
* @Assert\NotNull() |
87
|
|
|
* @FSRNotBlocked(groups={"fsr_blocked"}) |
88
|
|
|
*/ |
89
|
|
|
private $department; |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* @var string "Projektbezeichnung" |
93
|
|
|
* @Assert\NotBlank() |
94
|
|
|
* @Assert\Length(max=70, maxMessage="validator.project_name.too_long") |
95
|
|
|
* @ORM\Column(type="string") |
96
|
|
|
*/ |
97
|
|
|
private $project_name = ''; |
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* @var int "Betrag" |
101
|
|
|
* @ORM\Column(type="integer") |
102
|
|
|
* @Assert\Positive() |
103
|
|
|
*/ |
104
|
|
|
private $amount = null; |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* @var bool "mathematisch richtig" |
108
|
|
|
* @ORM\Column(type="boolean") |
109
|
|
|
*/ |
110
|
|
|
private $mathematically_correct = false; |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* @var bool |
114
|
|
|
* @ORM\Column(type="boolean") |
115
|
|
|
*/ |
116
|
|
|
private $exported = false; |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* @var bool "sachlich richtig" |
120
|
|
|
* @ORM\Column(type="boolean") |
121
|
|
|
*/ |
122
|
|
|
private $factually_correct = false; |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* @ORM\Column(type="text") |
126
|
|
|
*/ |
127
|
|
|
private $comment = ''; |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* @var string "Mittelfreigabe / Finanzantrag" |
131
|
|
|
* @ORM\Column(type="string") |
132
|
|
|
* @Assert\Regex(PaymentOrder::FUNDING_ID_REGEX) |
133
|
|
|
*/ |
134
|
|
|
private $funding_id = ''; |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* @var string|null |
138
|
|
|
* @ORM\Column(type="string", nullable=true) |
139
|
|
|
*/ |
140
|
|
|
private $confirm1_token = null; |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* @var DateTime|null |
144
|
|
|
* @ORM\Column(type="datetime", nullable=true) |
145
|
|
|
*/ |
146
|
|
|
private $confirm1_timestamp = null; |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* @var string|null |
150
|
|
|
* @ORM\Column(type="string", nullable=true) |
151
|
|
|
*/ |
152
|
|
|
private $confirm2_token = null; |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* @var DateTime|null |
156
|
|
|
* @ORM\Column(type="datetime", nullable=true) |
157
|
|
|
*/ |
158
|
|
|
private $confirm2_timestamp = null; |
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* @var bool Is FSR-Kom resolution |
162
|
|
|
* @ORM\Column(type="boolean") |
163
|
|
|
*/ |
164
|
|
|
private $fsr_kom_resolution = false; |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* @var DateTime|null |
168
|
|
|
* @ORM\Column(type="date", nullable=true) |
169
|
|
|
* @Assert\LessThanOrEqual(value="today", message="validator.resolution_must_not_be_in_future") |
170
|
|
|
* @Assert\GreaterThan(value="-3 years", message="validator.resolution_too_old") |
171
|
|
|
* @Assert\Expression("value !== null || (this.getDepartment() !== null && this.getDepartment().getType() != 'fsr' && this.isFsrKomResolution() === false)", message="validator.resolution_date.needed_for_fsr_fsrkom") |
172
|
|
|
*/ |
173
|
|
|
private $resolution_date = null; |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* @var string |
177
|
|
|
* @ORM\Column(type="string", nullable=false) |
178
|
|
|
* @Assert\Email() |
179
|
|
|
*/ |
180
|
|
|
private $contact_email = ''; |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* @var DateTime|null |
184
|
|
|
* @ORM\Column(type="datetime", nullable=true) |
185
|
|
|
*/ |
186
|
|
|
private $booking_date = null; |
187
|
|
|
|
188
|
|
|
/** |
189
|
|
|
* @var bool |
190
|
|
|
* @ORM\Column(type="boolean") |
191
|
|
|
*/ |
192
|
|
|
private $references_exported = false; |
193
|
|
|
|
194
|
|
|
/* |
195
|
|
|
* Associated files |
196
|
|
|
*/ |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* @Vich\UploadableField(mapping="payment_orders_form", fileNameProperty="printed_form.name", size="printed_form.size", mimeType="printed_form.mimeType", originalName="printed_form.originalName", dimensions="printed_form.dimensions") |
200
|
|
|
* |
201
|
|
|
* @var \Symfony\Component\HttpFoundation\File\File|null |
202
|
|
|
* @Assert\File( |
203
|
|
|
* maxSize = "1024k", |
204
|
|
|
* mimeTypes = {"application/pdf", "application/x-pdf"}, |
205
|
|
|
* mimeTypesMessage = "validator.upload_pdf" |
206
|
|
|
* ) |
207
|
|
|
*/ |
208
|
|
|
private $printed_form_file; |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* @ORM\Embedded(class="Vich\UploaderBundle\Entity\File") |
212
|
|
|
* |
213
|
|
|
* @var File |
214
|
|
|
*/ |
215
|
|
|
private $printed_form; |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* @Vich\UploadableField(mapping="payment_orders_references", fileNameProperty="references.name", size="references.size", mimeType="references.mimeType", originalName="references.originalName", dimensions="references.dimensions") |
219
|
|
|
* |
220
|
|
|
* @var \Symfony\Component\HttpFoundation\File\File|null |
221
|
|
|
* @Assert\NotBlank(groups={"frontend"}) |
222
|
|
|
* @Assert\File( |
223
|
|
|
* maxSize = "10M", |
224
|
|
|
* mimeTypes = {"application/pdf", "application/x-pdf"}, |
225
|
|
|
* mimeTypesMessage = "validator.upload_pdf" |
226
|
|
|
* ) |
227
|
|
|
*/ |
228
|
|
|
private $references_file; |
229
|
|
|
|
230
|
|
|
/** |
231
|
|
|
* @var Collection|SEPAExport[] |
232
|
|
|
* @ORM\ManyToMany(targetEntity="App\Entity\SEPAExport", mappedBy="associated_payment_orders") |
233
|
|
|
*/ |
234
|
|
|
private $associated_sepa_exports; |
235
|
|
|
|
236
|
|
|
/** |
237
|
|
|
* @ORM\Embedded(class="Vich\UploaderBundle\Entity\File") |
238
|
|
|
* |
239
|
|
|
* @var File |
240
|
|
|
*/ |
241
|
|
|
private $references; |
242
|
|
|
|
243
|
|
|
public function __construct() |
244
|
|
|
{ |
245
|
|
|
$this->bank_info = new PayeeInfo(); |
246
|
|
|
|
247
|
|
|
$this->associated_sepa_exports = new ArrayCollection(); |
248
|
|
|
|
249
|
|
|
$this->references = new File(); |
250
|
|
|
$this->printed_form = new File(); |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
public function getId(): ?int |
254
|
|
|
{ |
255
|
|
|
return $this->id; |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* Returns the bank info associated with this payment order. |
260
|
|
|
* |
261
|
|
|
*@see PayeeInfo |
262
|
|
|
*/ |
263
|
|
|
public function getBankInfo(): PayeeInfo |
264
|
|
|
{ |
265
|
|
|
return $this->bank_info; |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
/** |
269
|
|
|
* Returns the bank info associated with this payment order. |
270
|
|
|
* |
271
|
|
|
*@see PayeeInfo |
272
|
|
|
*/ |
273
|
|
|
public function setBankInfo(PayeeInfo $bank_info): PaymentOrder |
274
|
|
|
{ |
275
|
|
|
$this->bank_info = $bank_info; |
276
|
|
|
|
277
|
|
|
return $this; |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
/** |
281
|
|
|
* Returns the full name of person which has submitted this payment order. |
282
|
|
|
*/ |
283
|
|
|
public function getFullName(): string |
284
|
|
|
{ |
285
|
|
|
if (empty($this->getFirstName())) { |
286
|
|
|
return $this->getLastName(); |
287
|
|
|
} |
288
|
|
|
if (empty($this->getLastName())) { |
289
|
|
|
return $this->getFirstName(); |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
return $this->getFirstName().' '.$this->getLastName(); |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
/** |
296
|
|
|
* Returns the first name of the person which has submitted this payment order. |
297
|
|
|
*/ |
298
|
|
|
public function getFirstName(): string |
299
|
|
|
{ |
300
|
|
|
return $this->first_name; |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
/** |
304
|
|
|
* Sets the first name of the person which has submitted this payment order. |
305
|
|
|
*/ |
306
|
|
|
public function setFirstName(string $first_name): PaymentOrder |
307
|
|
|
{ |
308
|
|
|
$this->first_name = $first_name; |
309
|
|
|
|
310
|
|
|
return $this; |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
/** |
314
|
|
|
* Returns the last name of the person which has submitted this payment order. |
315
|
|
|
*/ |
316
|
|
|
public function getLastName(): string |
317
|
|
|
{ |
318
|
|
|
return $this->last_name; |
319
|
|
|
} |
320
|
|
|
|
321
|
|
|
/** |
322
|
|
|
* Sets the last name of the person which has submitted this payment order. |
323
|
|
|
*/ |
324
|
|
|
public function setLastName(string $last_name): PaymentOrder |
325
|
|
|
{ |
326
|
|
|
$this->last_name = $last_name; |
327
|
|
|
|
328
|
|
|
return $this; |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
/** |
332
|
|
|
* Returns the department for which this payment order was submitted. |
333
|
|
|
* |
334
|
|
|
* @return Department |
335
|
|
|
*/ |
336
|
|
|
public function getDepartment(): ?Department |
337
|
|
|
{ |
338
|
|
|
return $this->department; |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
/** |
342
|
|
|
* Returns the department for which this payment order was submitted. |
343
|
|
|
*/ |
344
|
|
|
public function setDepartment(Department $department): PaymentOrder |
345
|
|
|
{ |
346
|
|
|
$this->department = $department; |
347
|
|
|
|
348
|
|
|
return $this; |
349
|
|
|
} |
350
|
|
|
|
351
|
|
|
/** |
352
|
|
|
* Returns the name of the project which caused this payment order. |
353
|
|
|
* This value will be used in the bank reference value by default. |
354
|
|
|
*/ |
355
|
|
|
public function getProjectName(): string |
356
|
|
|
{ |
357
|
|
|
return $this->project_name; |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* Returns the name of the project which caused this payment order. |
362
|
|
|
* This value will be used in the bank reference value by default. |
363
|
|
|
*/ |
364
|
|
|
public function setProjectName(string $project_name): PaymentOrder |
365
|
|
|
{ |
366
|
|
|
$this->project_name = $project_name; |
367
|
|
|
|
368
|
|
|
return $this; |
369
|
|
|
} |
370
|
|
|
|
371
|
|
|
/** |
372
|
|
|
* Returns the amount that should be paid in (euro) cents. |
373
|
|
|
* |
374
|
|
|
* @return int |
375
|
|
|
*/ |
376
|
|
|
public function getAmount(): ?int |
377
|
|
|
{ |
378
|
|
|
return $this->amount; |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
/** |
382
|
|
|
* Sets the amount that should be paid in (euro) cents. |
383
|
|
|
*/ |
384
|
|
|
public function setAmount(int $amount): PaymentOrder |
385
|
|
|
{ |
386
|
|
|
$this->amount = $amount; |
387
|
|
|
|
388
|
|
|
return $this; |
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
/** |
392
|
|
|
* Returns the amount formatted as euro string (with dot as decimal separator) in the form "123.45" (only 2 digits). |
393
|
|
|
* Returns null if no amount was set. |
394
|
|
|
*/ |
395
|
|
|
public function getAmountString(): ?string |
396
|
|
|
{ |
397
|
|
|
if (null === $this->amount) { |
398
|
|
|
return null; |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
//%F (with big F) is important here, to always output with a dot |
402
|
|
|
return sprintf('%.2F', $this->amount / 100); |
403
|
|
|
} |
404
|
|
|
|
405
|
|
|
/** |
406
|
|
|
* Returns whether this payment order was checked as mathematically correct. |
407
|
|
|
* This means it was checked that the amount and data in this payment order matches the data on the invoice. |
408
|
|
|
*/ |
409
|
|
|
public function isMathematicallyCorrect(): bool |
410
|
|
|
{ |
411
|
|
|
return $this->mathematically_correct; |
412
|
|
|
} |
413
|
|
|
|
414
|
|
|
/** |
415
|
|
|
* Sets whether this payment order was checked as mathematically correct. |
416
|
|
|
* This means it was checked that the amount and data in this payment order matches the data on the invoice. |
417
|
|
|
*/ |
418
|
|
|
public function setMathematicallyCorrect(bool $mathematically_correct): PaymentOrder |
419
|
|
|
{ |
420
|
|
|
$this->mathematically_correct = $mathematically_correct; |
421
|
|
|
|
422
|
|
|
return $this; |
423
|
|
|
} |
424
|
|
|
|
425
|
|
|
/** |
426
|
|
|
* Returns whether this payment order was checked as factually correct. |
427
|
|
|
* This means it was checked that this payment is really needed. In our context it also means that an payment order |
428
|
|
|
* was payed out and is finished. |
429
|
|
|
*/ |
430
|
|
|
public function isFactuallyCorrect(): bool |
431
|
|
|
{ |
432
|
|
|
return $this->factually_correct; |
433
|
|
|
} |
434
|
|
|
|
435
|
|
|
/** |
436
|
|
|
* Sets whether this payment order was checked as factually correct. |
437
|
|
|
* This means it was checked that this payment is really needed. In our context it also means that an payment order |
438
|
|
|
* was payed out and is finished. |
439
|
|
|
*/ |
440
|
|
|
public function setFactuallyCorrect(bool $factually_correct): PaymentOrder |
441
|
|
|
{ |
442
|
|
|
$this->factually_correct = $factually_correct; |
443
|
|
|
|
444
|
|
|
//Update the status of booking date |
445
|
|
|
if ($factually_correct) { |
446
|
|
|
$this->booking_date = new \DateTime(); |
447
|
|
|
} else { |
448
|
|
|
$this->booking_date = null; |
449
|
|
|
} |
450
|
|
|
|
451
|
|
|
return $this; |
452
|
|
|
} |
453
|
|
|
|
454
|
|
|
/** |
455
|
|
|
* Returns whether this payment order was exported as SEPA-XML (and imported in online banking). |
456
|
|
|
* This is automatically set when payment orders are exported. |
457
|
|
|
*/ |
458
|
|
|
public function isExported(): bool |
459
|
|
|
{ |
460
|
|
|
return $this->exported; |
461
|
|
|
} |
462
|
|
|
|
463
|
|
|
/** |
464
|
|
|
* Sets whether this payment order was exported as SEPA-XML (and imported in online banking). |
465
|
|
|
* This is automatically set when payment orders are exported. |
466
|
|
|
*/ |
467
|
|
|
public function setExported(bool $exported): PaymentOrder |
468
|
|
|
{ |
469
|
|
|
$this->exported = $exported; |
470
|
|
|
|
471
|
|
|
return $this; |
472
|
|
|
} |
473
|
|
|
|
474
|
|
|
/** |
475
|
|
|
* Returns the comment associated with this payment order. |
476
|
|
|
* This can be HTML if changed in the backend. |
477
|
|
|
*/ |
478
|
|
|
public function getComment(): string |
479
|
|
|
{ |
480
|
|
|
return $this->comment; |
481
|
|
|
} |
482
|
|
|
|
483
|
|
|
/** |
484
|
|
|
* Returns the comment associated with this payment order. |
485
|
|
|
* This can be HTML if changed in the backend. |
486
|
|
|
*/ |
487
|
|
|
public function setComment(string $comment): PaymentOrder |
488
|
|
|
{ |
489
|
|
|
$this->comment = $comment; |
490
|
|
|
|
491
|
|
|
return $this; |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
/** |
495
|
|
|
* Returns the funding ID associated with this payment order (if it existing). |
496
|
|
|
* Returns an empty string if no funding ID is associated. |
497
|
|
|
*/ |
498
|
|
|
public function getFundingId(): string |
499
|
|
|
{ |
500
|
|
|
return $this->funding_id; |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
/** |
504
|
|
|
* Sets the funding ID associated with this payment order (if it existing). |
505
|
|
|
* Set to an empty string if no funding ID is associated. |
506
|
|
|
*/ |
507
|
|
|
public function setFundingId(string $funding_id): self |
508
|
|
|
{ |
509
|
|
|
$this->funding_id = $funding_id; |
510
|
|
|
|
511
|
|
|
return $this; |
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
/** |
515
|
|
|
* Return the HTTPFoundation File associated that contains the PDF version of this payment order. |
516
|
|
|
*/ |
517
|
|
|
public function getPrintedFormFile(): ?\Symfony\Component\HttpFoundation\File\File |
518
|
|
|
{ |
519
|
|
|
return $this->printed_form_file; |
520
|
|
|
} |
521
|
|
|
|
522
|
|
|
/** |
523
|
|
|
* Sets the HTTPFoundation File associated that contains the PDF version of this payment order. |
524
|
|
|
*/ |
525
|
|
|
public function setPrintedFormFile(?\Symfony\Component\HttpFoundation\File\File $printed_form_file): PaymentOrder |
526
|
|
|
{ |
527
|
|
|
$this->printed_form_file = $printed_form_file; |
528
|
|
|
|
529
|
|
|
if (null !== $printed_form_file) { |
530
|
|
|
/* It is required that at least one field changes if you are using doctrine |
531
|
|
|
otherwise the event listeners won't be called and the file is lost |
532
|
|
|
But we dont really want to change the last time value, so just copy it and create a new reference |
533
|
|
|
so doctrine thinks something has changed, but practically everything looks the same */ |
534
|
|
|
$this->last_modified = clone ($this->last_modified ?? new \DateTime()); |
535
|
|
|
} |
536
|
|
|
|
537
|
|
|
return $this; |
538
|
|
|
} |
539
|
|
|
|
540
|
|
|
/** |
541
|
|
|
* Return the Vich File associated that contains the PDF version of this payment order. |
542
|
|
|
*/ |
543
|
|
|
public function getPrintedForm(): File |
544
|
|
|
{ |
545
|
|
|
return $this->printed_form; |
546
|
|
|
} |
547
|
|
|
|
548
|
|
|
/** |
549
|
|
|
* Return the Vich File associated that contains the PDF version of this payment order. |
550
|
|
|
*/ |
551
|
|
|
public function setPrintedForm(File $printed_form): PaymentOrder |
552
|
|
|
{ |
553
|
|
|
$this->printed_form = $printed_form; |
554
|
|
|
|
555
|
|
|
return $this; |
556
|
|
|
} |
557
|
|
|
|
558
|
|
|
/** |
559
|
|
|
* Return the HTTPFoundation File associated that contains the invoice for this payment order. |
560
|
|
|
*/ |
561
|
|
|
public function getReferencesFile(): ?\Symfony\Component\HttpFoundation\File\File |
562
|
|
|
{ |
563
|
|
|
return $this->references_file; |
564
|
|
|
} |
565
|
|
|
|
566
|
|
|
/** |
567
|
|
|
* Sets the HTTPFoundation File associated that contains the invoice for this payment order. |
568
|
|
|
*/ |
569
|
|
|
public function setReferencesFile(?\Symfony\Component\HttpFoundation\File\File $references_file): PaymentOrder |
570
|
|
|
{ |
571
|
|
|
$this->references_file = $references_file; |
572
|
|
|
|
573
|
|
|
if (null !== $references_file) { |
574
|
|
|
/* It is required that at least one field changes if you are using doctrine |
575
|
|
|
otherwise the event listeners won't be called and the file is lost |
576
|
|
|
But we dont really want to change the last time value, so just copy it and create a new reference |
577
|
|
|
so doctrine thinks something has changed, but practically everything looks the same */ |
578
|
|
|
$this->last_modified = clone ($this->last_modified ?? new \DateTime()); |
579
|
|
|
} |
580
|
|
|
|
581
|
|
|
return $this; |
582
|
|
|
} |
583
|
|
|
|
584
|
|
|
/** |
585
|
|
|
* Return the Vich File associated that contains the invoice for this payment order. |
586
|
|
|
*/ |
587
|
|
|
public function getReferences(): File |
588
|
|
|
{ |
589
|
|
|
return $this->references; |
590
|
|
|
} |
591
|
|
|
|
592
|
|
|
/** |
593
|
|
|
* Sets the HTTPFoundation File associated that contains the invoice for this payment order. |
594
|
|
|
*/ |
595
|
|
|
public function setReferences(File $references): PaymentOrder |
596
|
|
|
{ |
597
|
|
|
$this->references = $references; |
598
|
|
|
|
599
|
|
|
return $this; |
600
|
|
|
} |
601
|
|
|
|
602
|
|
|
/** |
603
|
|
|
* Returns the (hashed) token that can be used to access the confirmation1 page of this payment page. |
604
|
|
|
* This value be verified with the password_verify() function. |
605
|
|
|
* Can be null if no confirmation should be possible for this payment order. |
606
|
|
|
*/ |
607
|
|
|
public function getConfirm1Token(): ?string |
608
|
|
|
{ |
609
|
|
|
return $this->confirm1_token; |
610
|
|
|
} |
611
|
|
|
|
612
|
|
|
/** |
613
|
|
|
* Returns the (hashed) token that can be used to access the confirmation1 page of this payment page. |
614
|
|
|
* This value be created with the password_hash() function. |
615
|
|
|
* Can be null if no confirmation should be possible for this payment order. |
616
|
|
|
*/ |
617
|
|
|
public function setConfirm1Token(?string $confirm1_token): PaymentOrder |
618
|
|
|
{ |
619
|
|
|
$this->confirm1_token = $confirm1_token; |
620
|
|
|
|
621
|
|
|
return $this; |
622
|
|
|
} |
623
|
|
|
|
624
|
|
|
/** |
625
|
|
|
* Returns the timestamp when the first confirmation for this payment order was submitted. |
626
|
|
|
* Returns null if this payment order is not confirmed (yet). |
627
|
|
|
*/ |
628
|
|
|
public function getConfirm1Timestamp(): ?DateTime |
629
|
|
|
{ |
630
|
|
|
return $this->confirm1_timestamp; |
631
|
|
|
} |
632
|
|
|
|
633
|
|
|
/** |
634
|
|
|
* Sets the timestamp when the first confirmation for this payment order was submitted. |
635
|
|
|
* Set to null if this payment order is not confirmed (yet). |
636
|
|
|
*/ |
637
|
|
|
public function setConfirm1Timestamp(?DateTime $confirm1_timestamp): PaymentOrder |
638
|
|
|
{ |
639
|
|
|
$this->confirm1_timestamp = $confirm1_timestamp; |
640
|
|
|
|
641
|
|
|
return $this; |
642
|
|
|
} |
643
|
|
|
|
644
|
|
|
/** |
645
|
|
|
* Returns the (hashed) token that can be used to access the confirmation2 page of this payment page. |
646
|
|
|
* This value be verified with the password_verify() function. |
647
|
|
|
* Can be null if no confirmation should be possible for this payment order. |
648
|
|
|
*/ |
649
|
|
|
public function getConfirm2Token(): ?string |
650
|
|
|
{ |
651
|
|
|
return $this->confirm2_token; |
652
|
|
|
} |
653
|
|
|
|
654
|
|
|
/** |
655
|
|
|
* Sets the (hashed) token that can be used to access the confirmation1 page of this payment page. |
656
|
|
|
* This value be created with the password_hash() function. |
657
|
|
|
* Can be null if no confirmation should be possible for this payment order. |
658
|
|
|
*/ |
659
|
|
|
public function setConfirm2Token(?string $confirm2_token): PaymentOrder |
660
|
|
|
{ |
661
|
|
|
$this->confirm2_token = $confirm2_token; |
662
|
|
|
|
663
|
|
|
return $this; |
664
|
|
|
} |
665
|
|
|
|
666
|
|
|
/** |
667
|
|
|
* Returns the timestamp when the second confirmation for this payment order was submitted. |
668
|
|
|
* Returns null if this payment order is not confirmed (yet). |
669
|
|
|
*/ |
670
|
|
|
public function getConfirm2Timestamp(): ?DateTime |
671
|
|
|
{ |
672
|
|
|
return $this->confirm2_timestamp; |
673
|
|
|
} |
674
|
|
|
|
675
|
|
|
/** |
676
|
|
|
* Sets the timestamp when the second confirmation for this payment order was submitted. |
677
|
|
|
* Set to null if this payment order is not confirmed (yet). |
678
|
|
|
*/ |
679
|
|
|
public function setConfirm2Timestamp(?DateTime $confirm2_timestamp): PaymentOrder |
680
|
|
|
{ |
681
|
|
|
$this->confirm2_timestamp = $confirm2_timestamp; |
682
|
|
|
|
683
|
|
|
return $this; |
684
|
|
|
} |
685
|
|
|
|
686
|
|
|
/** |
687
|
|
|
* Returns whether this payment order is confirmed (by both instances). |
688
|
|
|
*/ |
689
|
|
|
public function isConfirmed(): bool |
690
|
|
|
{ |
691
|
|
|
return null !== $this->confirm1_timestamp && null !== $this->confirm2_timestamp; |
692
|
|
|
} |
693
|
|
|
|
694
|
|
|
/** |
695
|
|
|
* Returns the email of the person which has submitted this payment order and which is used for answering questions. |
696
|
|
|
*/ |
697
|
|
|
public function getContactEmail(): string |
698
|
|
|
{ |
699
|
|
|
return $this->contact_email; |
700
|
|
|
} |
701
|
|
|
|
702
|
|
|
/** |
703
|
|
|
* Sets the email of the person which has submitted this payment order and which is used for answering questions. |
704
|
|
|
*/ |
705
|
|
|
public function setContactEmail(string $contact_email): PaymentOrder |
706
|
|
|
{ |
707
|
|
|
$this->contact_email = $contact_email; |
708
|
|
|
|
709
|
|
|
return $this; |
710
|
|
|
} |
711
|
|
|
|
712
|
|
|
/** |
713
|
|
|
* Returns whether this is an payment order for an resolution of the FSR-Kom (these are handled differently). |
714
|
|
|
*/ |
715
|
|
|
public function isFsrKomResolution(): bool |
716
|
|
|
{ |
717
|
|
|
return $this->fsr_kom_resolution; |
718
|
|
|
} |
719
|
|
|
|
720
|
|
|
/** |
721
|
|
|
* Sets whether this is an payment order for an resolution of the FSR-Kom (these are handled differently). |
722
|
|
|
*/ |
723
|
|
|
public function setFsrKomResolution(bool $fsr_kom_resolution): PaymentOrder |
724
|
|
|
{ |
725
|
|
|
$this->fsr_kom_resolution = $fsr_kom_resolution; |
726
|
|
|
|
727
|
|
|
return $this; |
728
|
|
|
} |
729
|
|
|
|
730
|
|
|
/** |
731
|
|
|
* Returns the date when the resolution that causes this payment order was passed. |
732
|
|
|
* This value is optional as not every payment order needs an resolution. |
733
|
|
|
* Only the date is shown for this DateTime. |
734
|
|
|
*/ |
735
|
|
|
public function getResolutionDate(): ?DateTime |
736
|
|
|
{ |
737
|
|
|
return $this->resolution_date; |
738
|
|
|
} |
739
|
|
|
|
740
|
|
|
/** |
741
|
|
|
* Sets the date when the resolution that causes this payment order was passed. |
742
|
|
|
* This value is optional as not every payment order needs an resolution. |
743
|
|
|
* Only the date is shown for this DateTime. |
744
|
|
|
*/ |
745
|
|
|
public function setResolutionDate(?DateTime $resolution_date): PaymentOrder |
746
|
|
|
{ |
747
|
|
|
$this->resolution_date = $resolution_date; |
748
|
|
|
|
749
|
|
|
return $this; |
750
|
|
|
} |
751
|
|
|
|
752
|
|
|
/** |
753
|
|
|
* Returns the datetime when this payment was booked in banking. |
754
|
|
|
* Returns null if payment_order was not booked yet. |
755
|
|
|
* The value is set automatically to now when the "factually_checked" field is set. |
756
|
|
|
*/ |
757
|
|
|
public function getBookingDate(): ?DateTime |
758
|
|
|
{ |
759
|
|
|
return $this->booking_date; |
760
|
|
|
} |
761
|
|
|
|
762
|
|
|
/** |
763
|
|
|
* Manually set the datetime when this payment was booked in banking. |
764
|
|
|
* Set to null if payment_order was not booked yet. |
765
|
|
|
* The value is set automatically to now when the "factually_checked" field is set. |
766
|
|
|
*/ |
767
|
|
|
public function setBookingDate(?DateTime $booking_date): PaymentOrder |
768
|
|
|
{ |
769
|
|
|
$this->booking_date = $booking_date; |
770
|
|
|
|
771
|
|
|
return $this; |
772
|
|
|
} |
773
|
|
|
|
774
|
|
|
/** |
775
|
|
|
* Returns whether the references for this payment order were already exported. |
776
|
|
|
*/ |
777
|
|
|
public function isReferencesExported(): bool |
778
|
|
|
{ |
779
|
|
|
return $this->references_exported; |
780
|
|
|
} |
781
|
|
|
|
782
|
|
|
/** |
783
|
|
|
* Sets whether the references for this payment order were already exported. |
784
|
|
|
*/ |
785
|
|
|
public function setReferencesExported(bool $references_exported): PaymentOrder |
786
|
|
|
{ |
787
|
|
|
$this->references_exported = $references_exported; |
788
|
|
|
|
789
|
|
|
return $this; |
790
|
|
|
} |
791
|
|
|
|
792
|
|
|
/** |
793
|
|
|
* @return SEPAExport[]|Collection |
794
|
|
|
*/ |
795
|
|
|
public function getAssociatedSepaExports() |
796
|
|
|
{ |
797
|
|
|
return $this->associated_sepa_exports; |
798
|
|
|
} |
799
|
|
|
|
800
|
|
|
|
801
|
|
|
|
802
|
|
|
public function serialize() |
803
|
|
|
{ |
804
|
|
|
return serialize($this->getId()); |
805
|
|
|
} |
806
|
|
|
|
807
|
|
|
public function unserialize($serialized) |
808
|
|
|
{ |
809
|
|
|
$this->id = unserialize($serialized); |
810
|
|
|
} |
811
|
|
|
|
812
|
|
|
/** |
813
|
|
|
* Get the ID as string like ZA0005. |
814
|
|
|
*/ |
815
|
|
|
public function getIDString(): string |
816
|
|
|
{ |
817
|
|
|
return sprintf('ZA%04d', $this->getId()); |
818
|
|
|
} |
819
|
|
|
} |
820
|
|
|
|