Calculation errors for refunded amounts

This commit is contained in:
2026-09-04 01:15:37 +02:00
parent 5beb2b1d97
commit c1c1a4f143
28 changed files with 1436 additions and 26 deletions
+19 -10
View File
@@ -11,6 +11,7 @@ use App\Enumerations\EfzStatus;
use App\Enumerations\InvoiceStatus;
use App\Enumerations\InvoiceType;
use App\Enumerations\RefundReason;
use App\Enumerations\RetentionReason;
use App\Enumerations\UserRole;
use App\Mail\InvoiceMails\InvoiceMailsSubmittedConfirmationMail;
use App\Models\CostUnit;
@@ -200,11 +201,16 @@ class RefundInvoiceTest extends TestCase
], $attributes));
}
/** Der ganze Ablauf: Freigabe durch die Aktionsleitung, Bestätigung durch den Teili. */
/**
* Der ganze Ablauf: Freigabe durch die Aktionsleitung, Bestätigung durch den Teili.
*
* 220 von 300 gezahlten Euro -- es bleibt etwas beim Verband, deshalb der Einbehaltungsgrund.
*/
private function runRefund(
?EventParticipant $participant = null,
float $amount = 220.0,
string $reason = RefundReason::SICKNESS,
?string $retentionReason = RetentionReason::CANCELLATION_FEE,
): ParticipantRefund {
$participant ??= $this->makeParticipant($this->makeEvent());
@@ -212,6 +218,7 @@ class RefundInvoiceTest extends TestCase
participant: $participant,
amount: new Amount($amount, 'Euro'),
reason: $reason,
retentionReason: $retentionReason,
))->execute()->refund;
new AcceptRefundCommand(new AcceptRefundRequest(
@@ -359,6 +366,7 @@ class RefundInvoiceTest extends TestCase
participant: $participant,
amount: new Amount(220.0, 'Euro'),
reason: RefundReason::SICKNESS,
retentionReason: RetentionReason::CANCELLATION_FEE,
))->execute()->refund;
$response = new AcceptRefundCommand(new AcceptRefundRequest(
@@ -403,25 +411,26 @@ class RefundInvoiceTest extends TestCase
Mail::assertSent(InvoiceMailsSubmittedConfirmationMail::class);
}
public function test_amount_paid_is_cleared_once_the_invoice_exists(): void
public function test_amount_paid_is_settled_once_the_invoice_exists(): void
{
$participant = $this->makeParticipant($this->makeEvent());
$this->runRefund($participant);
// Mit der eingereichten Abrechnung ist der Beitrag auf dem Weg zurück und darf in den
// Zahlungsübersichten nicht länger als eingegangen stehen.
$this->assertEqualsWithDelta(0.0, $participant->fresh()->amount_paid->getAmount(), 0.001);
// 300 gezahlt, 220 erstattet: `amount_paid` führt danach den Rest, der beim Verband bleibt.
$this->assertEqualsWithDelta(80.0, $participant->fresh()->amount_paid->getAmount(), 0.001);
// Der Sollbetrag bleibt: was der Teili hätte zahlen müssen, ändert die Erstattung nicht.
$this->assertEqualsWithDelta(300.0, $participant->fresh()->amount->getAmount(), 0.001);
}
public function test_the_receipt_is_written_before_the_amount_is_cleared(): void
public function test_the_receipt_is_written_before_the_amount_is_settled(): void
{
$refund = $this->runRefund();
// Reihenfolge-Falle: Beleg und Anmerkung weisen den gezahlten Beitrag aus. Wird zu früh genullt,
// stünde dort 0,00 €. Der Beleg selbst liegt als PDF vor; nachprüfbar ist die Reihenfolge an der
// Anmerkung, die im selben Schritt und aus derselben Quelle entsteht.
// Reihenfolge-Falle: Beleg und Anmerkung weisen den gezahlten Beitrag aus. Wird zu früh
// verrechnet, stünden dort 80,00 € statt 300,00 €. Der Beleg selbst liegt als PDF vor;
// nachprüfbar ist die Reihenfolge an der Anmerkung, die im selben Schritt entsteht.
$this->assertStringContainsString('300,00 Euro', Invoice::first()->comment);
$this->assertEqualsWithDelta(0.0, $refund->participant->fresh()->amount_paid->getAmount(), 0.001);
$this->assertEqualsWithDelta(80.0, $refund->participant->fresh()->amount_paid->getAmount(), 0.001);
}
}