Korrektur Buchungstexte bei Auslagenerstattungen

This commit is contained in:
2026-09-06 16:48:33 +02:00
parent a6bddf9fa5
commit e730d6db63
4 changed files with 83 additions and 2 deletions
@@ -93,7 +93,7 @@ class ExportController extends CommonController {
'amount' => $invoice->amount, 'amount' => $invoice->amount,
'recipient_name' => $invoice->contact_bank_owner, 'recipient_name' => $invoice->contact_bank_owner,
'recipient_iban' => $invoice->contact_bank_iban, 'recipient_iban' => $invoice->contact_bank_iban,
'payment_purpose' => $invoice->payment_purpose ?? 'Auslagenerstattung Rechnungsnummer ' . $invoice->invoice_number, 'payment_purpose' => $invoice->paymentPurposeText(),
]); ]);
} }
} }
+20
View File
@@ -71,6 +71,26 @@ class Invoice extends InstancedModel
'denied_reason', 'denied_reason',
]; ];
/**
* Der Verwendungszweck für Überweisung, Buchungstext und Anzeige.
*
* Der Freitext gewinnt, wenn einer erfasst wurde. Sonst benennt der Text den Vorgang: eine
* Beitragserstattung ist keine Auslage des Teilis, sondern die Rücknahme seiner Zahlung -- auf dem
* Kontoauszug muss der Unterschied erkennbar sein. Genannt wird die Abrechnungsnummer, und zwar als
* Belegnummer: unter "Rechnungsnummer" gibt es sie nirgends.
*/
public function paymentPurposeText() : string {
if ($this->payment_purpose !== null) {
return $this->payment_purpose;
}
$subject = $this->type === InvoiceType::INVOICE_TYPE_PARTICIPATION_REFUND
? 'Beitragserstattung'
: 'Auslagenerstattung';
return $subject . ' Belegnummer ' . $this->invoice_number;
}
public function costUnit() : BelongsTo{ public function costUnit() : BelongsTo{
return $this->belongsTo(CostUnit::class); return $this->belongsTo(CostUnit::class);
} }
+1 -1
View File
@@ -39,7 +39,7 @@ class InvoiceResource {
$returnData['id'] = $this->invoice->id; $returnData['id'] = $this->invoice->id;
$returnData['donation'] = $this->invoice->donation; $returnData['donation'] = $this->invoice->donation;
$returnData['externalPayment'] = null !== $this->invoice->payment_purpose; $returnData['externalPayment'] = null !== $this->invoice->payment_purpose;
$returnData['paymentPurpose'] = $this->invoice->payment_purpose ?? 'Auslagenerstattung Rechnungsnummer ' . $returnData['invoiceNumber']; $returnData['paymentPurpose'] = $this->invoice->paymentPurposeText();
$returnData['accountOwner'] = $this->invoice->contact_bank_owner ?? '--'; $returnData['accountOwner'] = $this->invoice->contact_bank_owner ?? '--';
$returnData['accountIban'] = $this->invoice->contact_bank_iban ?? '--'; $returnData['accountIban'] = $this->invoice->contact_bank_iban ?? '--';
$returnData['status'] = $this->invoice->status; $returnData['status'] = $this->invoice->status;
+61
View File
@@ -70,6 +70,16 @@ class RefundInvoiceTest extends TestCase
DB::table('participation_fee_types')->insert(['slug' => 'fixed', 'name' => 'Fix']); DB::table('participation_fee_types')->insert(['slug' => 'fixed', 'name' => 'Fix']);
DB::table('cost_unit_types')->insert(['slug' => CostUnitType::COST_UNIT_TYPE_EVENT, 'name' => 'Veranstaltung']); DB::table('cost_unit_types')->insert(['slug' => CostUnitType::COST_UNIT_TYPE_EVENT, 'name' => 'Veranstaltung']);
DB::table('invoice_status')->insert(['slug' => InvoiceStatus::INVOICE_STATUS_NEW]); DB::table('invoice_status')->insert(['slug' => InvoiceStatus::INVOICE_STATUS_NEW]);
// Ein gewöhnlicher Aufwandstyp zum Vergleich; die Beitragserstattung bringt die Migration mit.
DB::table('invoice_types')->insert([
'slug' => InvoiceType::INVOICE_TYPE_TRAVELLING,
'name' => 'Fahrtkosten',
'sort_order' => 1,
'selectable' => true,
'counts_as_expense' => true,
]);
PaymentMethod::create(['slug' => PaymentMethod::PAYMENT_ACCOUNT_TRANSACTION]); PaymentMethod::create(['slug' => PaymentMethod::PAYMENT_ACCOUNT_TRANSACTION]);
EfzStatus::create(['slug' => EfzStatus::EFZ_STATUS_NOT_REQUIRED, 'name' => 'Nicht erforderlich']); EfzStatus::create(['slug' => EfzStatus::EFZ_STATUS_NOT_REQUIRED, 'name' => 'Nicht erforderlich']);
@@ -433,4 +443,55 @@ class RefundInvoiceTest extends TestCase
$this->assertStringContainsString('300,00 Euro', Invoice::first()->comment); $this->assertStringContainsString('300,00 Euro', Invoice::first()->comment);
$this->assertEqualsWithDelta(80.0, $refund->participant->fresh()->amount_paid->getAmount(), 0.001); $this->assertEqualsWithDelta(80.0, $refund->participant->fresh()->amount_paid->getAmount(), 0.001);
} }
/*
|--------------------------------------------------------------------------
| Der Verwendungszweck der Überweisung
|--------------------------------------------------------------------------
*/
public function test_the_payment_purpose_of_a_refund_names_the_refund(): void
{
$this->runRefund();
$invoice = Invoice::first();
// Auf dem Kontoauszug des Teilis muss der Vorgang stehen, den es gab: Er hatte keine Auslage,
// er bekommt seinen Beitrag zurück.
$this->assertSame(
'Beitragserstattung Belegnummer ' . $invoice->invoice_number,
$invoice->paymentPurposeText()
);
}
public function test_an_ordinary_invoice_keeps_the_expense_wording(): void
{
$invoice = Invoice::create([
'tenant' => $this->tenant->slug,
'cost_unit_id' => $this->makeCostUnit()->id,
'invoice_number' => '2026-0042',
'status' => InvoiceStatus::INVOICE_STATUS_NEW,
'type' => InvoiceType::INVOICE_TYPE_TRAVELLING,
'contact_name' => 'Mika Muster',
'amount' => 42.0,
]);
$this->assertSame('Auslagenerstattung Belegnummer 2026-0042', $invoice->paymentPurposeText());
}
public function test_a_free_text_purpose_wins(): void
{
$invoice = Invoice::create([
'tenant' => $this->tenant->slug,
'cost_unit_id' => $this->makeCostUnit()->id,
'invoice_number' => '2026-0043',
'status' => InvoiceStatus::INVOICE_STATUS_NEW,
'type' => InvoiceType::INVOICE_TYPE_TRAVELLING,
'contact_name' => 'Mika Muster',
'amount' => 42.0,
'payment_purpose' => 'Sommerlager',
]);
$this->assertSame('Sommerlager', $invoice->paymentPurposeText());
}
} }