CoC Checks now optional
This commit is contained in:
@@ -36,6 +36,12 @@ UI-Bezeichnungen.
|
|||||||
`/admin/settings`. Gelesen über `ParticipantGroupType::label()/pluralLabel()/labels()`. Texte ohne Artikel formulieren
|
`/admin/settings`. Gelesen über `ParticipantGroupType::label()/pluralLabel()/labels()`. Texte ohne Artikel formulieren
|
||||||
(„Bitte bei „{label}" eine Auswahl treffen."), weil der Artikel vom Wort abhängt.
|
(„Bitte bei „{label}" eine Auswahl treffen."), weil der Artikel vom Wort abhängt.
|
||||||
|
|
||||||
|
## eFZ-Prüfung pro Veranstaltung
|
||||||
|
|
||||||
|
`events.coc_check_required` (Default `true`, Checkbox in `CommonSettings.vue`, Resource-Feld `cocCheckRequired`). Ist
|
||||||
|
sie aus, liefert `CertificateOfConductionCheckCommand` ohne API-Aufruf `not_required`, und `SignUpCommand` belegt
|
||||||
|
`efz_status` mit `not_required` vor. Wirkt nur auf neue Anmeldungen, bestehende Status bleiben.
|
||||||
|
|
||||||
## Umsatzsteuer / Steuerinformationen
|
## Umsatzsteuer / Steuerinformationen
|
||||||
|
|
||||||
Rechtlich korrekter Begriff ist **Umsatzsteuer (USt)**, nicht MwSt. Ziel: tagesbasierte Anmelde-Rechnungen („Teilnahme
|
Rechtlich korrekter Begriff ist **Umsatzsteuer (USt)**, nicht MwSt. Ziel: tagesbasierte Anmelde-Rechnungen („Teilnahme
|
||||||
|
|||||||
+6
@@ -12,6 +12,12 @@ class CertificateOfConductionCheckCommand {
|
|||||||
public function execute() : CertificateOfConductionCheckResponse {
|
public function execute() : CertificateOfConductionCheckResponse {
|
||||||
$response = new CertificateOfConductionCheckResponse();
|
$response = new CertificateOfConductionCheckResponse();
|
||||||
|
|
||||||
|
// Verlangt die Veranstaltung kein eFZ, entfällt die Prüfung -- ohne Aufruf der Prüf-API.
|
||||||
|
if (!$this->request->participant->event()->first()?->coc_check_required) {
|
||||||
|
$response->status = EfzStatus::EFZ_STATUS_NOT_REQUIRED;
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
// Der Stamm ist optional (die Kurzanmeldung erhebt ihn nicht, in der Verwaltung kann er entfernt werden).
|
// Der Stamm ist optional (die Kurzanmeldung erhebt ihn nicht, in der Verwaltung kann er entfernt werden).
|
||||||
$localGroup = str_replace('Stamm ', '', $this->request->participant->localGroup()->first()?->name ?? '');
|
$localGroup = str_replace('Stamm ', '', $this->request->participant->localGroup()->first()?->name ?? '');
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,9 @@ class SignUpCommand {
|
|||||||
'payment_purpose' => $this->request->event->name . ' - Beitrag ' . $this->request->firstname . ' ' . $this->request->lastname,
|
'payment_purpose' => $this->request->event->name . ' - Beitrag ' . $this->request->firstname . ' ' . $this->request->lastname,
|
||||||
'payment_method' => $this->request->paymentMethod,
|
'payment_method' => $this->request->paymentMethod,
|
||||||
'payment_options' => $paymentOptions,
|
'payment_options' => $paymentOptions,
|
||||||
'efz_status' => $participantAge->isfullAged() ? EfzStatus::EFZ_STATUS_NOT_CHECKED : EfzStatus::EFZ_STATUS_NOT_REQUIRED,
|
'efz_status' => $participantAge->isfullAged() && $this->request->event->coc_check_required
|
||||||
|
? EfzStatus::EFZ_STATUS_NOT_CHECKED
|
||||||
|
: EfzStatus::EFZ_STATUS_NOT_REQUIRED,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class UpdateEventCommand {
|
|||||||
$this->request->event->registration_allowed = $this->request->registrationAllowed;
|
$this->request->event->registration_allowed = $this->request->registrationAllowed;
|
||||||
$this->request->event->short_registration = $this->request->shortRegistration;
|
$this->request->event->short_registration = $this->request->shortRegistration;
|
||||||
$this->request->event->swimming_permission_required = $this->request->swimmingPermissionRequired;
|
$this->request->event->swimming_permission_required = $this->request->swimmingPermissionRequired;
|
||||||
|
$this->request->event->coc_check_required = $this->request->cocCheckRequired;
|
||||||
|
|
||||||
// Umstellen zwischen Local und Parent Group nur ohne Anmeldungen -- sonst stünden in einer Veranstaltung
|
// Umstellen zwischen Local und Parent Group nur ohne Anmeldungen -- sonst stünden in einer Veranstaltung
|
||||||
// beide Arten von Antworten nebeneinander.
|
// beide Arten von Antworten nebeneinander.
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class UpdateEventRequest {
|
|||||||
public bool $registrationAllowed;
|
public bool $registrationAllowed;
|
||||||
public bool $shortRegistration;
|
public bool $shortRegistration;
|
||||||
public bool $swimmingPermissionRequired;
|
public bool $swimmingPermissionRequired;
|
||||||
|
public bool $cocCheckRequired;
|
||||||
public Amount $flatSupport;
|
public Amount $flatSupport;
|
||||||
public Amount $supportPerPerson;
|
public Amount $supportPerPerson;
|
||||||
public array $contributingLocalGroups;
|
public array $contributingLocalGroups;
|
||||||
@@ -29,9 +30,10 @@ class UpdateEventRequest {
|
|||||||
/** Wonach bei der Anmeldung gefragt wird; null = unverändert. Greift nur, solange es keine Anmeldungen gibt. */
|
/** Wonach bei der Anmeldung gefragt wird; null = unverändert. Greift nur, solange es keine Anmeldungen gibt. */
|
||||||
public ?ParticipantGroupType $participantGroupType;
|
public ?ParticipantGroupType $participantGroupType;
|
||||||
|
|
||||||
public function __construct(Event $event, string $eventName, string $eventLocation, string $postalCode, string $email, DateTime $earlyBirdEnd, DateTime $registrationFinalEnd, int $alcoholicsAge, bool $sendWeeklyReports, bool $registrationAllowed, Amount $flatSupport, Amount $supportPerPerson, array $contributingLocalGroups, array $eatingHabits, bool $shortRegistration = false, bool $swimmingPermissionRequired = true, ?string $street = null, ?string $houseNumber = null, ?ParticipantGroupType $participantGroupType = null)
|
public function __construct(Event $event, string $eventName, string $eventLocation, string $postalCode, string $email, DateTime $earlyBirdEnd, DateTime $registrationFinalEnd, int $alcoholicsAge, bool $sendWeeklyReports, bool $registrationAllowed, Amount $flatSupport, Amount $supportPerPerson, array $contributingLocalGroups, array $eatingHabits, bool $shortRegistration = false, bool $swimmingPermissionRequired = true, ?string $street = null, ?string $houseNumber = null, ?ParticipantGroupType $participantGroupType = null, bool $cocCheckRequired = true)
|
||||||
{
|
{
|
||||||
$this->participantGroupType = $participantGroupType;
|
$this->participantGroupType = $participantGroupType;
|
||||||
|
$this->cocCheckRequired = $cocCheckRequired;
|
||||||
$this->event = $event;
|
$this->event = $event;
|
||||||
$this->eventName = $eventName;
|
$this->eventName = $eventName;
|
||||||
$this->eventLocation = $eventLocation;
|
$this->eventLocation = $eventLocation;
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ class DetailsController extends CommonController {
|
|||||||
$request->input('street'),
|
$request->input('street'),
|
||||||
$request->input('houseNumber'),
|
$request->input('houseNumber'),
|
||||||
ParticipantGroupType::tryFrom((string) $request->input('participantGroupType')),
|
ParticipantGroupType::tryFrom((string) $request->input('participantGroupType')),
|
||||||
|
(bool)$request->input('cocCheckRequired', true),
|
||||||
);
|
);
|
||||||
|
|
||||||
$eventUpdateCommand = new UpdateEventCommand($eventUpdateRequest);
|
$eventUpdateCommand = new UpdateEventCommand($eventUpdateRequest);
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ const emit = defineEmits(['close'])
|
|||||||
registrationAllowed: props.event.registrationAllowed,
|
registrationAllowed: props.event.registrationAllowed,
|
||||||
shortRegistration: props.event.shortRegistration,
|
shortRegistration: props.event.shortRegistration,
|
||||||
swimmingPermissionRequired: props.event.swimmingPermissionRequired,
|
swimmingPermissionRequired: props.event.swimmingPermissionRequired,
|
||||||
|
cocCheckRequired: props.event.cocCheckRequired,
|
||||||
flatSupport: props.event.flatSupportEdit,
|
flatSupport: props.event.flatSupportEdit,
|
||||||
supportPerson: props.event.supportPersonIndex,
|
supportPerson: props.event.supportPersonIndex,
|
||||||
participantGroupType: props.event.participantGroupType ?? 'local_group',
|
participantGroupType: props.event.participantGroupType ?? 'local_group',
|
||||||
@@ -78,6 +79,7 @@ const emit = defineEmits(['close'])
|
|||||||
registrationAllowed: formData.registrationAllowed,
|
registrationAllowed: formData.registrationAllowed,
|
||||||
shortRegistration: formData.shortRegistration,
|
shortRegistration: formData.shortRegistration,
|
||||||
swimmingPermissionRequired: formData.swimmingPermissionRequired,
|
swimmingPermissionRequired: formData.swimmingPermissionRequired,
|
||||||
|
cocCheckRequired: formData.cocCheckRequired,
|
||||||
flatSupport: formData.flatSupport,
|
flatSupport: formData.flatSupport,
|
||||||
supportPerson: formData.supportPerson,
|
supportPerson: formData.supportPerson,
|
||||||
contributingLocalGroups: contributingLocalGroups.value,
|
contributingLocalGroups: contributingLocalGroups.value,
|
||||||
@@ -234,6 +236,16 @@ const emit = defineEmits(['close'])
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<input type="checkbox" v-model="formData.cocCheckRequired" id="cocCheckRequired" />
|
||||||
|
<label for="cocCheckRequired">Erweitertes Führungszeugnis (eFZ) prüfen</label><br />
|
||||||
|
<span style="font-size: 0.8rem; color: #6b7280;">
|
||||||
|
Ist die Prüfung deaktiviert, wird das eFZ bei neuen Anmeldungen als „Nicht erforderlich" hinterlegt.
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ use Illuminate\Support\Collection;
|
|||||||
* @property boolean $archived
|
* @property boolean $archived
|
||||||
* @property boolean $short_registration
|
* @property boolean $short_registration
|
||||||
* @property boolean $swimming_permission_required
|
* @property boolean $swimming_permission_required
|
||||||
|
* @property boolean $coc_check_required
|
||||||
* @property string|null $invoice_key
|
* @property string|null $invoice_key
|
||||||
* @property string $participant_group_type
|
* @property string $participant_group_type
|
||||||
*/
|
*/
|
||||||
@@ -102,6 +103,7 @@ class Event extends InstancedModel
|
|||||||
|
|
||||||
'short_registration',
|
'short_registration',
|
||||||
'swimming_permission_required',
|
'swimming_permission_required',
|
||||||
|
'coc_check_required',
|
||||||
|
|
||||||
'invoice_key',
|
'invoice_key',
|
||||||
'participant_group_type',
|
'participant_group_type',
|
||||||
@@ -137,6 +139,7 @@ class Event extends InstancedModel
|
|||||||
|
|
||||||
'short_registration' => 'boolean',
|
'short_registration' => 'boolean',
|
||||||
'swimming_permission_required' => 'boolean',
|
'swimming_permission_required' => 'boolean',
|
||||||
|
'coc_check_required' => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ class EventResource extends JsonResource{
|
|||||||
// Steuert im Frontend, welcher Anmelde-Wizard gerendert wird, und ob die Badeerlaubnis abgefragt wird.
|
// Steuert im Frontend, welcher Anmelde-Wizard gerendert wird, und ob die Badeerlaubnis abgefragt wird.
|
||||||
$returnArray['shortRegistration'] = (bool)$this->event->short_registration;
|
$returnArray['shortRegistration'] = (bool)$this->event->short_registration;
|
||||||
$returnArray['swimmingPermissionRequired'] = (bool)$this->event->swimming_permission_required;
|
$returnArray['swimmingPermissionRequired'] = (bool)$this->event->swimming_permission_required;
|
||||||
|
$returnArray['cocCheckRequired'] = (bool)$this->event->coc_check_required;
|
||||||
|
|
||||||
$returnArray['siblingReduction'] = $this->event->sibling_reduction ?? true;
|
$returnArray['siblingReduction'] = $this->event->sibling_reduction ?? true;
|
||||||
$returnArray['costUnit'] = new CostUnitResource($this->event->costUnit()->first())->toArray(true);
|
$returnArray['costUnit'] = new CostUnitResource($this->event->costUnit()->first())->toArray(true);
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration {
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('events', function (Blueprint $table) {
|
||||||
|
// Ob bei Anmeldungen das erweiterte Führungszeugnis geprüft wird. Ist die Prüfung aus, erhalten neue
|
||||||
|
// Anmeldungen immer „Nicht erforderlich". Default true, damit bestehende Veranstaltungen sich
|
||||||
|
// unverändert verhalten.
|
||||||
|
$table->boolean('coc_check_required')->default(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('events', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('coc_check_required');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace Tests\Feature;
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use App\Domains\Event\Actions\CertificateOfConductionCheck\CertificateOfConductionCheckCommand;
|
||||||
|
use App\Domains\Event\Actions\CertificateOfConductionCheck\CertificateOfConductionCheckRequest;
|
||||||
use App\Domains\Event\Actions\ShortSignUp\ShortSignUpCommand;
|
use App\Domains\Event\Actions\ShortSignUp\ShortSignUpCommand;
|
||||||
use App\Domains\Event\Actions\ShortSignUp\ShortSignUpRequest;
|
use App\Domains\Event\Actions\ShortSignUp\ShortSignUpRequest;
|
||||||
use App\Enumerations\EatingHabit;
|
use App\Enumerations\EatingHabit;
|
||||||
@@ -18,6 +20,7 @@ use App\Models\Tenant;
|
|||||||
use App\RelationModels\EventParticipationFee;
|
use App\RelationModels\EventParticipationFee;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
@@ -57,6 +60,7 @@ class ShortSignUpTest extends TestCase
|
|||||||
bool $swimmingPermissionRequired = true,
|
bool $swimmingPermissionRequired = true,
|
||||||
?float $amountReduced = 30.0,
|
?float $amountReduced = 30.0,
|
||||||
?float $amountSolidarity = 70.0,
|
?float $amountSolidarity = 70.0,
|
||||||
|
bool $cocCheckRequired = true,
|
||||||
): Event
|
): Event
|
||||||
{
|
{
|
||||||
$event = Event::create([
|
$event = Event::create([
|
||||||
@@ -66,6 +70,7 @@ class ShortSignUpTest extends TestCase
|
|||||||
'account_owner' => 'Owner', 'account_iban' => 'DE00', 'participation_fee_type' => 'FIXED',
|
'account_owner' => 'Owner', 'account_iban' => 'DE00', 'participation_fee_type' => 'FIXED',
|
||||||
'pay_per_day' => false, 'pay_direct' => false,
|
'pay_per_day' => false, 'pay_direct' => false,
|
||||||
'short_registration' => true, 'swimming_permission_required' => $swimmingPermissionRequired,
|
'short_registration' => true, 'swimming_permission_required' => $swimmingPermissionRequired,
|
||||||
|
'coc_check_required' => $cocCheckRequired,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($withFee) {
|
if ($withFee) {
|
||||||
@@ -217,6 +222,43 @@ class ShortSignUpTest extends TestCase
|
|||||||
$this->assertSame('maria@example.com', $response->participant->email_2);
|
$this->assertSame('maria@example.com', $response->participant->email_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_volljaehrige_ohne_efz_pruefung_brauchen_kein_efz(): void
|
||||||
|
{
|
||||||
|
Http::fake();
|
||||||
|
$event = $this->createEvent(cocCheckRequired: false);
|
||||||
|
|
||||||
|
$response = new ShortSignUpCommand($this->shortRequest($event))->execute();
|
||||||
|
|
||||||
|
$this->assertTrue($response->success, $response->message ?? '');
|
||||||
|
$this->assertSame(EfzStatus::EFZ_STATUS_NOT_REQUIRED, $response->participant->efz_status);
|
||||||
|
|
||||||
|
$cocResponse = new CertificateOfConductionCheckCommand(
|
||||||
|
new CertificateOfConductionCheckRequest($response->participant)
|
||||||
|
)->execute();
|
||||||
|
|
||||||
|
$this->assertSame(EfzStatus::EFZ_STATUS_NOT_REQUIRED, $cocResponse->status);
|
||||||
|
Http::assertNothingSent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_volljaehrige_mit_efz_pruefung_werden_geprueft(): void
|
||||||
|
{
|
||||||
|
putenv('COC_CHECK_URL=https://coc.test/check');
|
||||||
|
Http::fake(['*' => Http::response(['status' => '200/ok', 'efzStatus' => 'CHECKED_VALID'])]);
|
||||||
|
$event = $this->createEvent();
|
||||||
|
|
||||||
|
$response = new ShortSignUpCommand($this->shortRequest($event))->execute();
|
||||||
|
|
||||||
|
$this->assertTrue($response->success, $response->message ?? '');
|
||||||
|
$this->assertSame(EfzStatus::EFZ_STATUS_NOT_CHECKED, $response->participant->efz_status);
|
||||||
|
|
||||||
|
$cocResponse = new CertificateOfConductionCheckCommand(
|
||||||
|
new CertificateOfConductionCheckRequest($response->participant)
|
||||||
|
)->execute();
|
||||||
|
|
||||||
|
$this->assertSame(EfzStatus::EFZ_STATUS_CHECKED_VALID, $cocResponse->status);
|
||||||
|
Http::assertSentCount(1);
|
||||||
|
}
|
||||||
|
|
||||||
public function test_u18_uebernimmt_gewaehlte_badeerlaubnis(): void
|
public function test_u18_uebernimmt_gewaehlte_badeerlaubnis(): void
|
||||||
{
|
{
|
||||||
$event = $this->createEvent();
|
$event = $this->createEvent();
|
||||||
|
|||||||
Reference in New Issue
Block a user