feat: additional receipts as attachments to teamer invoices

addresses #869dv97u9
This commit is contained in:
fromme committed 2026-09-09 11:10:57 +02:00
1 parent 16d847137d
commit 52926ec6cc
29 files changed
+682 -23

No files matched your search

+17
View File
@@ -4,13 +4,25 @@ namespace App\Model;
class UploadDto
{
/**
* The oneup_uploader mapping the file was uploaded through, which is 1:1 with the
* Upload::TYPE_* values. Deliberately not a promoted constructor property: the enclosing
* UploadSessionDto is serialized into the PHP session, and a promoted property carries no
* class-level default, so entries written before this field existed would deserialize
* uninitialized and throw on access. Nullable with a real default lets them come back as
* "unknown type", which matches no type and is therefore ignored.
*/
private ?string $type = null;
public function __construct(
private readonly string $uuid,
private readonly string $filename,
private readonly string $originalFilename,
private readonly string $mimeType,
private readonly int $size,
?string $type = null,
) {
$this->type = $type;
}
public function getUuid(): string
@@ -37,4 +49,9 @@ class UploadDto
{
return $this->size;
}
public function getType(): ?string
{
return $this->type;
}
}
+23
View File
@@ -52,6 +52,29 @@ class UploadSessionDto
return $this->uploads;
}
/**
* The uploads that came in through one oneup_uploader mapping. Two dropzones can be live on
* the same page (the Honorarnote and its Belege), and the session is one flat list, so a
* consumer must never take getUploads()->first() and hope.
*
* @return Collection<int, UploadDto>
*/
public function getUploadsByType(string $type): Collection
{
return $this->uploads->filter(function (UploadDto $upload) use ($type) {
return $type === $upload->getType();
});
}
public function removeUploadsByType(string $type): static
{
foreach ($this->getUploadsByType($type) as $upload) {
$this->uploads->removeElement($upload);
}
return $this;
}
public function flushUploads(): static
{
$this->uploads->clear();