Added tax support

This commit is contained in:
2026-08-06 11:49:58 +02:00
parent 6b33c1b4dd
commit c17facf063
15 changed files with 679 additions and 7 deletions
+67
View File
@@ -0,0 +1,67 @@
<?php
namespace App\Enumerations;
/**
* Gründe für eine Umsatzsteuerbefreiung. Jeder Fall kapselt sein UI-Label und den auf der Rechnung
* verpflichtenden Hinweis nach § 14 Abs. 4 Nr. 8 UStG, damit Label und Text nur an einer Stelle
* gepflegt werden. Gemeinnützigkeit allein befreit nicht die Befreiung braucht immer einen konkreten
* Rechtsgrund; die Vereins-Fälle sind über § 4 Nr. 22a / Nr. 25 abgedeckt.
*/
enum TaxExemptionReason: string
{
case SmallBusiness = 'small_business';
case Education = 'education';
case YouthWelfare = 'youth_welfare';
case Custom = 'custom';
public function label(): string
{
return match ($this) {
self::SmallBusiness => 'Kleinunternehmer (§ 19 UStG)',
self::Education => 'Bildungs-/Kursleistung (§ 4 Nr. 22a UStG)',
self::YouthWelfare => 'Kinder- und Jugendhilfe (§ 4 Nr. 25 UStG)',
self::Custom => 'Sonstiger Grund (Freitext)',
};
}
/**
* Pflichthinweis für die Rechnung. Bei einem individuellen Grund (Custom) wird der hinterlegte
* Freitext des Tenants verwendet.
*/
public function invoiceText(?string $customNote = null): string
{
return match ($this) {
self::SmallBusiness => 'Gemäß § 19 UStG wird keine Umsatzsteuer berechnet.',
self::Education => 'Die Leistung ist gemäß § 4 Nr. 22 Buchst. a UStG von der Umsatzsteuer befreit.',
self::YouthWelfare => 'Die Leistung ist gemäß § 4 Nr. 25 UStG von der Umsatzsteuer befreit.',
self::Custom => trim((string)$customNote),
};
}
/**
* Ob dieser Grund einen zusätzlichen Freitext des Tenants erfordert.
*/
public function requiresNote(): bool
{
return $this === self::Custom;
}
/**
* Optionen für das Frontend inkl. Vorschau-Text. Bei Custom ist `text` leer, da der Text erst aus
* dem Freitext des Tenants entsteht.
*
* @return array<int, array{value: string, label: string, text: string}>
*/
public static function options(): array
{
return array_map(
static fn(self $reason): array => [
'value' => $reason->value,
'label' => $reason->label(),
'text' => $reason->requiresNote() ? '' : $reason->invoiceText(),
],
self::cases(),
);
}
}