From 40d5634764ebba6edb415fb0d67e9f3ade954e8a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20G=C3=BCnrher?=
Date: Mon, 7 Sep 2026 14:17:50 +0200
Subject: [PATCH] Zahlungszwecke
---
.../CreateIncomeSurplusStatementCommand.php | 28 +--
.../CreateInvoice/CreateInvoiceCommand.php | 78 ++++++-
.../CreateInvoice/CreateInvoiceRequest.php | 22 +-
.../CreateInvoice/CreateInvoiceResponse.php | 4 +
.../CreateInvoiceReceiptCommand.php | 11 +-
.../UpdateInvoice/UpdateInvoiceCommand.php | 11 +
.../UpdateInvoice/UpdateInvoiceRequest.php | 4 +-
.../Invoice/Controllers/EditController.php | 74 +++---
.../Controllers/SaveInvoiceController.php | 75 +++----
.../invoiceDetails/DistanceAllowance.vue | 9 -
.../Partials/invoiceDetails/EditInvoice.vue | 16 +-
.../Views/Partials/invoiceDetails/Header.vue | 4 +
.../myInvoiceDetails/DistanceAllowance.vue | 9 -
.../Partials/newInvoice/payment-data.vue | 4 -
.../Views/Partials/newInvoice/refund-data.vue | 8 +-
.../newInvoice/travel-expense-accounting.vue | 91 +++++---
.../AcceptRefund/AcceptRefundCommand.php | 9 -
app/Enumerations/TravelReason.php | 72 ++++++
app/Models/Invoice.php | 55 ++++-
app/Providers/GlobalDataProvider.php | 6 +
app/Resources/InvoiceResource.php | 6 +-
...6_09_11_140010_add_purpose_to_invoices.php | 25 +++
...026_09_12_140010_create_travel_reasons.php | 70 ++++++
routes/web.php | 1 +
.../EventIncomeSurplusStatementTest.php | 35 ++-
tests/Feature/InvoicePurposeTest.php | 212 +++++++++++++++++-
tests/Feature/TravelReasonTest.php | 193 ++++++++++++++++
27 files changed, 927 insertions(+), 205 deletions(-)
create mode 100644 app/Enumerations/TravelReason.php
create mode 100644 database/migrations/2026_09_11_140010_add_purpose_to_invoices.php
create mode 100644 database/migrations/2026_09_12_140010_create_travel_reasons.php
create mode 100644 tests/Feature/TravelReasonTest.php
diff --git a/app/Domains/Event/Actions/CreateIncomeSurplusStatement/CreateIncomeSurplusStatementCommand.php b/app/Domains/Event/Actions/CreateIncomeSurplusStatement/CreateIncomeSurplusStatementCommand.php
index 824666a..4d9d49c 100644
--- a/app/Domains/Event/Actions/CreateIncomeSurplusStatement/CreateIncomeSurplusStatementCommand.php
+++ b/app/Domains/Event/Actions/CreateIncomeSurplusStatement/CreateIncomeSurplusStatementCommand.php
@@ -148,7 +148,9 @@ class CreateIncomeSurplusStatementCommand
$rows[] = [
'number' => (string) $invoice->invoice_number,
'date' => $invoice->created_at?->format('d.m.Y') ?? '',
- 'purpose' => $this->purpose($invoice->purposeText(), $invoice->comment),
+ // Ohne die Anmerkung: dort steht, was die Kassenwart*in beim Korrigieren notiert hat,
+ // und das gehört auf den Beleg, nicht in den Zweck.
+ 'purpose' => $invoice->purposeText(),
'amount' => Amount::fromString($invoice->amount),
];
}
@@ -165,30 +167,6 @@ class CreateIncomeSurplusStatementCommand
return ['groups' => $groups, 'total' => $total];
}
- /**
- * Wofür der Beleg steht, um die Anmerkung ergänzt.
- *
- * Den Zweck selbst bestimmt {@see \App\Models\Invoice::purposeText()} -- dieselbe Ermittlung wie in
- * der Beleg-Übersicht, damit ein Beleg nicht an zwei Stellen Verschiedenes über sich behauptet. Die
- * Anmerkung kommt nur hier dazu: Auf der Aufstellung steht der Beleg für sich, ohne die Detailansicht
- * daneben.
- *
- * Ältere Belege haben keinen Zweck erfasst -- dann bleibt die Anmerkung, und fehlt auch die, bleibt
- * die Zelle leer. Ein Platzhalter wie "--" würde in der Belegliste nur Platz kosten.
- */
- private function purpose(?string $purpose, ?string $comment): string
- {
- $parts = [];
-
- foreach ([$purpose, $comment] as $part) {
- if (trim((string) $part) !== '') {
- $parts[] = trim((string) $part);
- }
- }
-
- return implode(' — ', $parts);
- }
-
/**
* Ein Betrag in deutscher Schreibweise: Punkt als Tausender-, Komma als Dezimaltrennzeichen.
*
diff --git a/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceCommand.php b/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceCommand.php
index 4bd479d..a3cf03e 100644
--- a/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceCommand.php
+++ b/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceCommand.php
@@ -3,6 +3,8 @@
namespace App\Domains\Invoice\Actions\CreateInvoice;
use App\Enumerations\InvoiceStatus;
+use App\Enumerations\InvoiceType;
+use App\Enumerations\TravelReason;
use App\Mail\InvoiceMails\InvoiceMailsNewInvoiceMail;
use App\Mail\InvoiceMails\InvoiceMailsSubmittedConfirmationMail;
use App\Mail\ParticipantParticipationMails\EventSignUpSuccessfullMail;
@@ -19,10 +21,19 @@ class CreateInvoiceCommand {
public function execute() : CreateInvoiceResponse {
$response = new CreateInvoiceResponse();
+ $rejection = $this->rejectTravelReason();
+ if ($rejection !== null) {
+ $response->message = $rejection;
+
+ return $response;
+ }
+
if ($this->request->accountIban === 'undefined') {
$this->request->accountIban = null;
}
+ $travelReason = $this->travelReason();
+
$invoice = Invoice::create([
'tenant' => currentTenant()->slug,
'cost_unit_id' => $this->request->costUnit->id,
@@ -30,6 +41,7 @@ class CreateInvoiceCommand {
'status' => InvoiceStatus::INVOICE_STATUS_NEW,
'type' => $this->request->invoiceType,
'type_other' => $this->request->invoiceTypeExtended,
+ 'purpose' => $this->purpose($travelReason),
'donation' => $this->request->isDonation,
'user_id' => $this->request->paymentPurpose === null ? $this->request->userId : null,
'contact_name' => $this->request->contactName,
@@ -40,9 +52,7 @@ class CreateInvoiceCommand {
'amount' => $this->request->totalAmount,
'distance' => $this->request->distance,
'travel_direction' => $this->request->travelRoute,
- 'travel_reason' => $this->request->travelReason,
- 'passengers' => $this->request->passengers,
- 'transportation' => $this->request->transportations,
+ 'travel_reason' => $travelReason,
'payment_purpose' => $this->request->paymentPurpose,
'comment' => $this->request->notices,
'document_filename' => $this->request->receiptFile !== null ? $this->request->receiptFile->fullPath : null,
@@ -81,6 +91,68 @@ class CreateInvoiceCommand {
}
+ /**
+ * Der Zahlungsgrund, einmal beim Anlegen festgehalten.
+ *
+ * Danach ist er eine eigene Angabe: Die Kassenwart*in kann ihn korrigieren, und nichts schreibt ihn
+ * mehr um. Bei Fahrtkosten setzt er sich aus Reisegrund und den gefahrenen Personen zusammen, sonst
+ * trägt ihn "Was wurde eingekauft". Wo nichts erfasst wird -- Beitragserstattungen -- bleibt er leer.
+ *
+ * Steht er schon fest, wird er übernommen: Eine Abrechnungskorrektur kopiert den Beleg, und ein von
+ * Hand gesetzter Grund darf dabei nicht verloren gehen.
+ */
+ private function purpose(?string $travelReason) : ?string {
+ if (trim((string) $this->request->purpose) !== '') {
+ return $this->request->purpose;
+ }
+
+ $purpose = Invoice::joinPurposeParts(
+ $this->request->invoiceType === InvoiceType::INVOICE_TYPE_TRAVELLING
+ // Der Name des Grundes, nicht sein Schlüssel: In der Belegliste soll "Materialtransport"
+ // stehen, nicht "material_transport".
+ ? [TravelReason::text($travelReason), $this->request->travellers]
+ : [$this->request->invoiceTypeExtended]
+ );
+
+ return $purpose === '' ? null : $purpose;
+ }
+
+ /**
+ * Was in `travel_reason` landet: der Schlüssel des gewählten Grundes -- oder, bei "Anderer Grund",
+ * der Text selbst. Der Schlüssel `other` sagt für sich nichts aus, der Text alles.
+ *
+ * Ein unbekannter Wert ist deshalb kein Fehler, sondern genau dieser Fall: So kommen auch
+ * Bestandsbelege und Kopien durch, die ihren Freitext schon mitbringen.
+ */
+ private function travelReason() : ?string {
+ $reason = TravelReason::find($this->request->travelReason);
+
+ if ($reason === null) {
+ return $this->request->travelReason;
+ }
+
+ return $reason->requires_note
+ ? trim((string) $this->request->travelReasonNote)
+ : $reason->slug;
+ }
+
+ /**
+ * Sicherheitsnetz hinter der Oberfläche: Dort geht es erst weiter, wenn die Erläuterung steht. Über
+ * einen direkten Aufruf ginge das sonst vorbei, und ein "Anderer Grund" ohne Text sagt nichts aus --
+ * gespeichert würde ein leerer Reisegrund.
+ */
+ private function rejectTravelReason() : ?string {
+ $reason = TravelReason::find($this->request->travelReason);
+
+ if ($reason === null || !$reason->requires_note) {
+ return null;
+ }
+
+ return trim((string) $this->request->travelReasonNote) === ''
+ ? 'Bitte gib an, was der Grund für die Reise war.'
+ : null;
+ }
+
private function generateInvoiceNumber() : string {
$lastInvoiceNumber = Invoice::query()
->where('tenant', currentTenant()->slug)
diff --git a/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceRequest.php b/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceRequest.php
index bbe9593..57392b5 100644
--- a/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceRequest.php
+++ b/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceRequest.php
@@ -16,16 +16,24 @@ class CreateInvoiceRequest {
public ?string $invoiceTypeExtended;
public ?string $travelRoute;
public ?int $distance;
- public ?int $passengers;
- public ?int $transportations;
public ?InvoiceFile $receiptFile;
public float $totalAmount;
public bool $isDonation;
public ?int $userId;
+ /** Der Slug eines Reisegrundes -- oder ein Freitext, wenn er von einem Bestandsbeleg stammt. */
public ?string $travelReason;
+
+ /** Die Erläuterung zu "Anderer Grund"; nur bei einem Grund mit `requires_note` von Belang. */
+ public ?string $travelReasonNote;
public ?string $paymentPurpose;
public ?string $notices;
+ /** Wer gereist ist -- Freitext aus dem Fahrtkosten-Formular, geht in den Zahlungsgrund ein. */
+ public ?string $travellers;
+
+ /** Ein bereits feststehender Zahlungsgrund; gesetzt, gewinnt er über die Ermittlung im Command. */
+ public ?string $purpose;
+
public function __construct(
CostUnit $costUnit,
@@ -42,11 +50,12 @@ class CreateInvoiceRequest {
?string $invoiceTypeExtended = null,
?string $travelRoute = null,
?int $distance = null,
- ?int $passengers = null,
- ?int $transportations,
?string $travelReason = null,
+ ?string $travelReasonNote = null,
?string $paymentPurpose = null,
?string $notices = null,
+ ?string $travellers = null,
+ ?string $purpose = null,
) {
$this->costUnit = $costUnit;
@@ -55,8 +64,6 @@ class CreateInvoiceRequest {
$this->invoiceTypeExtended = $invoiceTypeExtended;
$this->travelRoute = $travelRoute;
$this->distance = $distance;
- $this->passengers = $passengers;
- $this->transportations = $transportations;
$this->receiptFile = $receiptFile;
$this->contactEmail = $contactEmail;
$this->contactPhone = $contactPhone;
@@ -66,8 +73,11 @@ class CreateInvoiceRequest {
$this->isDonation = $isDonation;
$this->userId = $userId;
$this->travelReason = $travelReason;
+ $this->travelReasonNote = $travelReasonNote;
$this->paymentPurpose = $paymentPurpose;
$this->notices = $notices;
+ $this->travellers = $travellers;
+ $this->purpose = $purpose;
if ($accountIban === 'undefined') {
$this->accountIban = null;
diff --git a/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceResponse.php b/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceResponse.php
index 357fed9..eeb6f9b 100644
--- a/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceResponse.php
+++ b/app/Domains/Invoice/Actions/CreateInvoice/CreateInvoiceResponse.php
@@ -8,8 +8,12 @@ class CreateInvoiceResponse {
public bool $success;
public ?Invoice $invoice;
+ /** Warum keine Abrechnung entstanden ist -- für die Rückmeldung an die einreichende Person. */
+ public ?string $message;
+
public function __construct() {
$this->success = false;
$this->invoice = null;
+ $this->message = null;
}
}
diff --git a/app/Domains/Invoice/Actions/CreateInvoiceReceipt/CreateInvoiceReceiptCommand.php b/app/Domains/Invoice/Actions/CreateInvoiceReceipt/CreateInvoiceReceiptCommand.php
index ffe696c..eb3c840 100644
--- a/app/Domains/Invoice/Actions/CreateInvoiceReceipt/CreateInvoiceReceiptCommand.php
+++ b/app/Domains/Invoice/Actions/CreateInvoiceReceipt/CreateInvoiceReceiptCommand.php
@@ -83,10 +83,8 @@ class CreateInvoiceReceiptCommand {
$travelPartTemplate = <<Reiseweg: | %1\$s |
- | Grund der Reise: | %6\$s |
+ | Grund der Reise: | %4\$s |
| Gesamtlänge der Strecke: | %2\$s km x %3\$s / km |
- | Materialtransport: | %4\$s |
- | Mitfahrende im PKW: | %5\$s |
HTML;
$flatTravelPart = sprintf(
@@ -94,8 +92,6 @@ HTML;
$invoiceReadable['travelDirection'] ,
$invoiceReadable['distance'],
$invoiceReadable['distanceAllowance'],
- $invoiceReadable['transportation'],
- $invoiceReadable['passengers'],
$invoiceReadable['travelReason'] ,
);
@@ -180,7 +176,10 @@ HTML;
$invoiceReadable['contactEmail'],
$invoiceReadable['contactPhone'],
$invoiceReadable['costUnitName'],
- $invoiceReadable['invoiceType'],
+ // Der erfasste Zahlungsgrund, nicht der Abrechnungstyp: Der steht eine Zeile darüber schon
+ // als Überschrift. Bei Fahrtkosten ist das die einzige Stelle, an der auf dem Beleg steht,
+ // wer gereist ist.
+ $invoiceReadable['purpose'],
$invoiceReadable['donationText'],
$paymentType,
$invoiceReadable['amount'],
diff --git a/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceCommand.php b/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceCommand.php
index d066221..47e17c3 100644
--- a/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceCommand.php
+++ b/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceCommand.php
@@ -34,6 +34,17 @@ class UpdateInvoiceCommand {
}
+ $purpose = trim((string) $this->request->purpose);
+ $purpose = $purpose === '' ? null : $purpose;
+
+ // Verglichen wird gegen den angezeigten Text, nicht gegen die Spalte: Das Formular ist damit
+ // vorbelegt, und wer ihn unverändert abschickt, hat nichts geändert. Ein Bestandsbeleg behält so
+ // seine leere Spalte und damit die Ableitung; wer das Feld leert, schaltet zurück auf automatisch.
+ if (($purpose ?? '') !== $this->request->invoice->purposeText()) {
+ $changes .= 'Zahlungsgrund geändert von ' . $this->request->invoice->purposeText() . ' auf ' . ($purpose ?? '--') . '.
';
+ $this->request->invoice->purpose = $purpose;
+ }
+
$this->request->invoice->comment = $this->request->comment;
$this->request->invoice->changes = $changes;
diff --git a/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceRequest.php b/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceRequest.php
index 571ecfa..4a42ef7 100644
--- a/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceRequest.php
+++ b/app/Domains/Invoice/Actions/UpdateInvoice/UpdateInvoiceRequest.php
@@ -13,9 +13,11 @@ class UpdateInvoiceRequest {
public CostUnit $costUnit;
public Invoice $invoice;
public Amount $amount;
+ public ?string $purpose;
- public function __construct(Invoice $invoice, ?string $comment, InvoiceType $invoiceType, CostUnit $costUnit, Amount $amount) {
+ public function __construct(Invoice $invoice, ?string $comment, InvoiceType $invoiceType, CostUnit $costUnit, Amount $amount, ?string $purpose = null) {
$this->comment = $comment;
+ $this->purpose = $purpose;
$this->invoiceType = $invoiceType;
$this->costUnit = $costUnit;
$this->invoice = $invoice;
diff --git a/app/Domains/Invoice/Controllers/EditController.php b/app/Domains/Invoice/Controllers/EditController.php
index 3dbec7b..38aca00 100644
--- a/app/Domains/Invoice/Controllers/EditController.php
+++ b/app/Domains/Invoice/Controllers/EditController.php
@@ -32,25 +32,26 @@ class EditController extends CommonController{
$receiptfile->fullPath = $invoice->document_filename;
}
$createInvoiceRequest = new CreateInvoiceRequest(
- $invoice->costUnit()->first(),
- $invoice->contact_name,
- $invoice->type,
- $invoice->amount,
- $receiptfile,
- $invoice->donation,
- $invoice->user_id,
- $invoice->contact_email,
- $invoice->contact_phone,
- $invoice->contact_bank_owner,
- $invoice->contact_bank_iban,
- $invoice->type_other,
- $invoice->travel_direction,
- $invoice->distance,
- $invoice->passengers,
- $invoice->transportation,
- $invoice->travel_reason,
- $invoice->payment_purpose,
- $invoice->comment,
+ costUnit: $invoice->costUnit()->first(),
+ contactName: $invoice->contact_name,
+ invoiceType: $invoice->type,
+ totalAmount: $invoice->amount,
+ receiptFile: $receiptfile,
+ isDonation: $invoice->donation,
+ userId: $invoice->user_id,
+ contactEmail: $invoice->contact_email,
+ contactPhone: $invoice->contact_phone,
+ accountOwner: $invoice->contact_bank_owner,
+ accountIban: $invoice->contact_bank_iban,
+ invoiceTypeExtended: $invoice->type_other,
+ travelRoute: $invoice->travel_direction,
+ distance: $invoice->distance,
+ travelReason: $invoice->travel_reason,
+ paymentPurpose: $invoice->payment_purpose,
+ notices: $invoice->comment,
+ // Die rohe Spalte, nicht purposeText(): Ein Beleg, der seinen Zahlungsgrund bisher ableitet,
+ // soll das als Kopie weiter tun.
+ purpose: $invoice->purpose,
);
$invoiceCreationCommand = new CreateInvoiceCommand($createInvoiceRequest);
@@ -92,7 +93,8 @@ class EditController extends CommonController{
$modifyData['notices'],
$invoiceType,
$newCostUnit,
- $newAmount
+ $newAmount,
+ $modifyData['purpose'] ?? null
);
$updateInvoiceCommand = new UpdateInvoiceCommand($updateInvoiceRequest);
$updateInvoiceCommand->execute();
@@ -107,22 +109,22 @@ class EditController extends CommonController{
$receiptfile->fullPath = $invoice->document_filename;
}
$createInvoiceRequest = new CreateInvoiceRequest(
- $invoice->costUnit()->first(),
- $invoice->contact_name,
- $invoice->type,
- $amountLeft->getAmount(),
- $receiptfile,
- $invoice->donation,
- $invoice->user_id,
- $invoice->contact_email,
- $invoice->contact_phone,
- $invoice->contact_bank_owner,
- $invoice->contact_bank_iban,
- $invoice->type_other,
- $invoice->travel_direction,
- $invoice->distance,
- $invoice->passengers,
- $invoice->transportation
+ costUnit: $invoice->costUnit()->first(),
+ contactName: $invoice->contact_name,
+ invoiceType: $invoice->type,
+ totalAmount: $amountLeft->getAmount(),
+ receiptFile: $receiptfile,
+ isDonation: $invoice->donation,
+ userId: $invoice->user_id,
+ contactEmail: $invoice->contact_email,
+ contactPhone: $invoice->contact_phone,
+ accountOwner: $invoice->contact_bank_owner,
+ accountIban: $invoice->contact_bank_iban,
+ invoiceTypeExtended: $invoice->type_other,
+ travelRoute: $invoice->travel_direction,
+ distance: $invoice->distance,
+ travelReason: $invoice->travel_reason,
+ purpose: $invoice->purpose,
);
$invoiceCreationCommand = new CreateInvoiceCommand($createInvoiceRequest);
diff --git a/app/Domains/Invoice/Controllers/SaveInvoiceController.php b/app/Domains/Invoice/Controllers/SaveInvoiceController.php
index 0c8f370..649958d 100644
--- a/app/Domains/Invoice/Controllers/SaveInvoiceController.php
+++ b/app/Domains/Invoice/Controllers/SaveInvoiceController.php
@@ -66,50 +66,43 @@ class SaveInvoiceController extends CommonController
}
$createInvoiceRequest = new CreateInvoiceRequest(
- $costUnit,
- $request->input('name'),
- InvoiceType::INVOICE_TYPE_TRAVELLING,
- $amount,
- $uploadedFile,
- 'donation' === $request->input('decision') ? true : false,
- $this->users->getCurrentUserDetails()['userId'],
- $request->input('email'),
- $request->input('telephone'),
- $request->input('accountOwner'),
- $request->input('accountIban'),
- null,
- $request->input('otherText'),
- $distance,
- $request->input('havePassengers'),
- $request->input('materialTransportation'),
- $request->input('travelReason'),
- null,
- $notices
+ costUnit: $costUnit,
+ contactName: $request->input('name'),
+ invoiceType: InvoiceType::INVOICE_TYPE_TRAVELLING,
+ totalAmount: $amount,
+ receiptFile: $uploadedFile,
+ isDonation: 'donation' === $request->input('decision') ? true : false,
+ userId: $this->users->getCurrentUserDetails()['userId'],
+ contactEmail: $request->input('email'),
+ contactPhone: $request->input('telephone'),
+ accountOwner: $request->input('accountOwner'),
+ accountIban: $request->input('accountIban'),
+ travelRoute: $request->input('otherText'),
+ distance: $distance,
+ travelReason: $request->input('travelReason'),
+ travelReasonNote: $request->input('travelReasonNote'),
+ notices: $notices,
+ travellers: $request->input('travellers')
);
break;
default:
$createInvoiceRequest = new CreateInvoiceRequest(
- $costUnit,
- $request->input('name'),
- $invoiceType,
- Amount::fromString($request->input('amount'))->getAmount(),
- $uploadedFile,
- 'donation' === $request->input('decision') ? true : false,
- $this->users->getCurrentUserDetails()['userId'],
- $request->input('email'),
- $request->input('telephone'),
- $request->input('accountOwner'),
- $request->input('accountIban'),
- $request->input('otherText'),
- null,
- null,
- $request->input('havePassengers'),
- $request->input('materialTransportation'),
- null,
- $paymentPurpose,
- $notices
+ costUnit: $costUnit,
+ contactName: $request->input('name'),
+ invoiceType: $invoiceType,
+ totalAmount: Amount::fromString($request->input('amount'))->getAmount(),
+ receiptFile: $uploadedFile,
+ isDonation: 'donation' === $request->input('decision') ? true : false,
+ userId: $this->users->getCurrentUserDetails()['userId'],
+ contactEmail: $request->input('email'),
+ contactPhone: $request->input('telephone'),
+ accountOwner: $request->input('accountOwner'),
+ accountIban: $request->input('accountIban'),
+ invoiceTypeExtended: $request->input('otherText'),
+ paymentPurpose: $paymentPurpose,
+ notices: $notices
);
break;
@@ -128,5 +121,11 @@ class SaveInvoiceController extends CommonController
'message' => 'Alright'
]);
}
+
+ return response()->json([
+ 'status' => 'error',
+ 'message' => $response->message
+ ?? 'Beim Speichern ist ein Fehler aufgetreten. Bitte starte den Vorgang erneut.'
+ ]);
}
}
diff --git a/app/Domains/Invoice/Views/Partials/invoiceDetails/DistanceAllowance.vue b/app/Domains/Invoice/Views/Partials/invoiceDetails/DistanceAllowance.vue
index 7ca8eff..28bfd99 100644
--- a/app/Domains/Invoice/Views/Partials/invoiceDetails/DistanceAllowance.vue
+++ b/app/Domains/Invoice/Views/Partials/invoiceDetails/DistanceAllowance.vue
@@ -37,15 +37,6 @@ const props = defineProps({
{{props.invoice.amount}} |
-
- | Marterialtransport |
- {{props.invoice.transportation}} |
-
-
-
- | Hat Personen mitgenommen |
- {{props.invoice.passengers}} |
-
diff --git a/app/Domains/Invoice/Views/Partials/invoiceDetails/EditInvoice.vue b/app/Domains/Invoice/Views/Partials/invoiceDetails/EditInvoice.vue
index 693ff09..de49093 100644
--- a/app/Domains/Invoice/Views/Partials/invoiceDetails/EditInvoice.vue
+++ b/app/Domains/Invoice/Views/Partials/invoiceDetails/EditInvoice.vue
@@ -16,11 +16,18 @@ const props = defineProps({
const emit = defineEmits(['submit', 'cancel'])
+/**
+ * Die Anmerkung heißt in der Resource `comment` und ist dort `'--'`, wenn keine gesetzt ist -- beides
+ * muss hier stimmen, sonst startet das Feld leer und das Speichern löscht die vorhandene Anmerkung.
+ */
+const existingComment = props.newInvoice.comment
+
const formData = reactive({
type_internal: props.newInvoice.internalType || '',
cost_unit: props.newInvoice.costUnitId || '',
amount: props.newInvoice.amountPlain || '',
- notices: props.newInvoice.comments || '',
+ purpose: props.newInvoice.purpose || '',
+ notices: !existingComment || existingComment === '--' ? '' : existingComment,
})
const submitForm = () => {
@@ -70,6 +77,13 @@ onMounted(async () => {
+
+ | Zahlungsgrund: |
+
+
+ |
+
+
| Anmerkungen: |
diff --git a/app/Domains/Invoice/Views/Partials/invoiceDetails/Header.vue b/app/Domains/Invoice/Views/Partials/invoiceDetails/Header.vue
index c8d268f..721397e 100644
--- a/app/Domains/Invoice/Views/Partials/invoiceDetails/Header.vue
+++ b/app/Domains/Invoice/Views/Partials/invoiceDetails/Header.vue
@@ -100,6 +100,10 @@ const emit = defineEmits(["accept", "deny", "fix", "reopen"])
| Rechnungszahlung |
Klassische Auszahlung |
+
+ | Zahlungsgrund: |
+ {{props.data.purpose}} |
+
| Status: |
{{props.data.readableStatus}} |
diff --git a/app/Domains/Invoice/Views/Partials/myInvoiceDetails/DistanceAllowance.vue b/app/Domains/Invoice/Views/Partials/myInvoiceDetails/DistanceAllowance.vue
index 34fd61f..6bcb6d6 100644
--- a/app/Domains/Invoice/Views/Partials/myInvoiceDetails/DistanceAllowance.vue
+++ b/app/Domains/Invoice/Views/Partials/myInvoiceDetails/DistanceAllowance.vue
@@ -32,15 +32,6 @@ const props = defineProps({
{{props.invoice.amount}} |
-
- | Marterialtransport |
- {{props.invoice.transportation}} |
-
-
-
- | Hat Personen mitgenommen |
- {{props.invoice.passengers}} |
-
diff --git a/app/Domains/Invoice/Views/Partials/newInvoice/payment-data.vue b/app/Domains/Invoice/Views/Partials/newInvoice/payment-data.vue
index 27abaab..32654f3 100644
--- a/app/Domains/Invoice/Views/Partials/newInvoice/payment-data.vue
+++ b/app/Domains/Invoice/Views/Partials/newInvoice/payment-data.vue
@@ -24,8 +24,6 @@ const props = defineProps({
userTelephone: String,
userAccountOwner: String,
userAccountIban: String,
- havePassengers: Number,
- materialTransportation: Boolean,
travelReason: String,
})
@@ -61,8 +59,6 @@ async function sendData() {
formData.append('accountOwner', userAccountOwner.value)
formData.append('accountIban', userIban.value)
formData.append('paymentPurpose', paymentPurpose.value)
- formData.append('havePassengers', props.havePassengers ? 1 : 0)
- formData.append('materialTransportation', props.materialTransportation ? 1 : 0)
formData.append('travelReason', props.travelReason)
if (props.receipt) {
diff --git a/app/Domains/Invoice/Views/Partials/newInvoice/refund-data.vue b/app/Domains/Invoice/Views/Partials/newInvoice/refund-data.vue
index 5381b9d..b3940aa 100644
--- a/app/Domains/Invoice/Views/Partials/newInvoice/refund-data.vue
+++ b/app/Domains/Invoice/Views/Partials/newInvoice/refund-data.vue
@@ -24,9 +24,9 @@ const props = defineProps({
userTelephone: String,
userAccountOwner: String,
userAccountIban: String,
- havePassengers: Number,
- materialTransportation: Boolean,
travelReason: String,
+ travelReasonNote: String,
+ travellers: String,
})
const finalStep = ref(true)
@@ -60,9 +60,9 @@ async function sendData() {
formData.append('decision', decision.value)
formData.append('accountOwner', userAccountOwner.value)
formData.append('accountIban', userIban.value)
- formData.append('havePassengers', props.havePassengers ? 1 : 0)
- formData.append('materialTransportation', props.materialTransportation ? 1 : 0)
formData.append('travelReason', props.travelReason)
+ formData.append('travelReasonNote', props.travelReasonNote ?? '')
+ formData.append('travellers', props.travellers ?? '')
formData.append('notices', notices.value)
if (props.receipt) {
diff --git a/app/Domains/Invoice/Views/Partials/newInvoice/travel-expense-accounting.vue b/app/Domains/Invoice/Views/Partials/newInvoice/travel-expense-accounting.vue
index c8d874f..1438c33 100644
--- a/app/Domains/Invoice/Views/Partials/newInvoice/travel-expense-accounting.vue
+++ b/app/Domains/Invoice/Views/Partials/newInvoice/travel-expense-accounting.vue
@@ -1,5 +1,5 @@