diff --git a/app/Domains/Event/Actions/CreateIncomeSurplusStatement/CreateIncomeSurplusStatementCommand.php b/app/Domains/Event/Actions/CreateIncomeSurplusStatement/CreateIncomeSurplusStatementCommand.php
index 987f089..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->type_other, $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,27 +167,6 @@ class CreateIncomeSurplusStatementCommand
return ['groups' => $groups, 'total' => $total];
}
- /**
- * Wofür der Beleg steht.
- *
- * `type_other` trägt seit der Pflichtangabe "Was wurde eingekauft" zu jeder Abrechnung den Zweck,
- * nicht mehr nur bei "Sonstige Kosten". Ältere Belege haben das Feld leer -- 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 $typeOther, ?string $comment): string
- {
- $parts = [];
-
- foreach ([$typeOther, $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/Event/Views/Partials/ParticipantData.vue b/app/Domains/Event/Views/Partials/ParticipantData.vue
index 98eed73..eb5b6b6 100644
--- a/app/Domains/Event/Views/Partials/ParticipantData.vue
+++ b/app/Domains/Event/Views/Partials/ParticipantData.vue
@@ -386,7 +386,9 @@ function saveParticipant() {
Bankverbindung des Teilis
- bestätigt am {{ props.participant.refund.acceptedAt }}
+ bestätigt am {{ props.participant.refund.acceptedAt }} – gespendet, keine Auszahlung
diff --git a/app/Domains/Event/Views/Partials/ParticipantsList.vue b/app/Domains/Event/Views/Partials/ParticipantsList.vue
index 5783a92..72ffa32 100644
--- a/app/Domains/Event/Views/Partials/ParticipantsList.vue
+++ b/app/Domains/Event/Views/Partials/ParticipantsList.vue
@@ -60,6 +60,7 @@ const refundErrors = reactive({amount: '', reason: '', reasonNote: '', accountOw
const refundReasons = ref([]);
const retentionReasons = ref([]);
const refundSaving = ref(false);
+const refundResending = ref(false);
const selectedRefundReason = computed(
() => refundReasons.value.find(r => r.value === refundForm.reason) ?? null
@@ -458,6 +459,8 @@ async function execRefund() {
// Leer beim Weg über den Teili -- dann verschickt der Server nur den Link.
accountOwner: refundForm.captureMode === 'management' ? refundForm.accountOwner : '',
accountIban: refundForm.captureMode === 'management' ? refundForm.accountIban : '',
+ // Spende: kein Konto, trotzdem sofort eingereicht.
+ donation: refundForm.captureMode === 'donation',
// Leer bei voller Erstattung -- dann gibt es nichts zu begründen.
retentionReason: hasRetention.value ? refundForm.retentionReason : '',
retentionReasonNote: hasRetention.value ? refundForm.retentionReasonNote : '',
@@ -496,6 +499,32 @@ async function execCancelRefund(participant) {
}
}
+/**
+ * Die Mail zur freigegebenen Erstattung noch einmal schicken -- ohne Rückfrage, es ändert sich nichts am
+ * Vorgang. Der Guard verhindert, dass ein zweiter Klick eine zweite Mail auslöst, bevor die erste durch ist.
+ */
+async function execResendRefundMail(participant) {
+ if (refundResending.value) {
+ return;
+ }
+
+ refundResending.value = true;
+
+ try {
+ const data = await request('/api/v1/participant-refund/' + participant.refund.token + '/resend-mail', {
+ method: "POST",
+ });
+
+ if (data?.status === 'success') {
+ toast.success(data.message);
+ } else {
+ toast.error(data?.message ?? 'Die Rückerstattungsmail konnte nicht versendet werden.');
+ }
+ } finally {
+ refundResending.value = false;
+ }
+}
+
async function downloadRefundDocument(participant) {
const ok = await download('/api/v1/participant-refund/' + participant.refund.token + '/document');
@@ -627,8 +656,9 @@ function mailToGroup(groupKey) {
> | Beitrag erstatten
- | Erstattung offen: {{ participant.refund.amount }},
- wartet auf Bankverbindung
+ | Rückerstattung vorgemerkt: {{ participant.refund.amount }}
+ am {{ participant.refund.releasedAt }}, wartet auf Bankverbindung
+ Rückerstattungsmail erneut sendenAbbrechen
@@ -772,8 +802,8 @@ function mailToGroup(groupKey) {
+
+
+ Der Betrag wird nicht ausgezahlt, sondern als Spende gebucht. Die Erstattung wird sofort
+ eingereicht; der Teili erhält den Beleg per E-Mail.
+
+
@@ -819,6 +858,7 @@ function mailToGroup(groupKey) {
>
Wird gespeichert…
Erstattung einreichen
+ Als Spende einreichen
Erstattung freigeben
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 () => {
+