diff --git a/app/Enumerations/EfzStatus.php b/app/Enumerations/EfzStatus.php new file mode 100644 index 0000000..be5d5ae --- /dev/null +++ b/app/Enumerations/EfzStatus.php @@ -0,0 +1,27 @@ +installTenants(); - //$this->installUsers(); + $this->installTenants(); + $this->installUsers(); } diff --git a/app/Installer/ProductionDataSeeder.php b/app/Installer/ProductionDataSeeder.php index 9b67444..e05b79d 100644 --- a/app/Installer/ProductionDataSeeder.php +++ b/app/Installer/ProductionDataSeeder.php @@ -5,6 +5,7 @@ namespace App\Installer; use App\Enumerations\CostUnitType; use App\Enumerations\CronTaskType; use App\Enumerations\EatingHabit; +use App\Enumerations\EfzStatus; use App\Enumerations\FirstAidPermission; use App\Enumerations\InvoiceStatus; use App\Enumerations\InvoiceType; @@ -12,20 +13,30 @@ use App\Enumerations\ParticipationFeeType; use App\Enumerations\ParticipationType; use App\Enumerations\SwimmingPermission; use App\Enumerations\UserRole; +use App\Models\CronTask; use App\Models\Tenant; class ProductionDataSeeder { public function execute() { - /*$this->installCronTypes(); + $this->installCronTypes(); $this->installUserRoles(); $this->installCostUnitTypes(); $this->installSwimmingPermissions(); $this->installEatingHabits(); $this->installFirstAidPermissions(); $this->installTenants(); - $this->installInvoiceMetaData();*/ + $this->installInvoiceMetaData(); $this->installParticipationFeeTypes(); $this->installParticipationTypes(); + $this->installEfzStatus(); + $this->installCronTasks(); + } + + private function installEfzStatus() { + EfzStatus::create(['slug' => EfzStatus::EFZ_STATUS_NOT_CHECKED, 'name' => 'Nicht geprüft']); + EfzStatus::create(['slug' => EfzStatus::EFZ_STATUS_NOT_REQUIRED, 'name' => 'Nicht erforderlich']); + EfzStatus::create(['slug' => EfzStatus::EFZ_STATUS_CHECKED_VALID, 'name' => 'Geprüft und gültig']); + EfzStatus::create(['slug' => EfzStatus::EFZ_STATUS_CHECKED_INVALID, 'name' => 'Geprüft und ungültig']); } private function installParticipationTypes() { @@ -141,7 +152,12 @@ class ProductionDataSeeder { } private function installCronTypes() { - CronTaskType::creata(['slug' => CronTaskType::CRON_TASK_TYPE_REALTIME]); - CronTaskType::creata(['slug' => CronTaskType::CRON_TASK_TYPE_DAILY]); + CronTaskType::create(['slug' => CronTaskType::CRON_TASK_TYPE_REALTIME]); + CronTaskType::create(['slug' => CronTaskType::CRON_TASK_TYPE_DAILY]); + } + + private function installCronTasks() { + CronTask::create(['name' => 'UploadInvoices', 'execution_type' => CronTaskType::CRON_TASK_TYPE_REALTIME]); } } + diff --git a/app/Models/Event.php b/app/Models/Event.php index 8927e19..0d1a388 100644 --- a/app/Models/Event.php +++ b/app/Models/Event.php @@ -12,6 +12,7 @@ use App\Scopes\InstancedModel; use DateTime; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasMany; /** * @property string $tenant @@ -164,4 +165,8 @@ class Event extends InstancedModel return $this->belongsToMany(User::class, 'event_managers', 'event_id', 'user_id') ->withTimestamps(); } + + public function participants() : hasMany { + return $this->hasMany(EventParticipant::class); + } } diff --git a/app/Models/EventParticipant.php b/app/Models/EventParticipant.php new file mode 100644 index 0000000..2a47262 --- /dev/null +++ b/app/Models/EventParticipant.php @@ -0,0 +1,135 @@ + 'datetime', + 'arrival_date' => 'datetime', + 'departure_date' => 'datetime', + 'unregistered_at' => 'datetime', + + 'foto_socialmedia' => 'boolean', + 'foto_print' => 'boolean', + 'foto_webseite' => 'boolean', + 'foto_partner' => 'boolean', + 'foto_intern' => 'boolean', + + 'amount' => AmountCast::class, + 'amount_paid' => AmountCast::class, + ]; + + /* + |-------------------------------------------------------------------------- + | Relationships + |-------------------------------------------------------------------------- + */ + + public function event() + { + return $this->belongsTo(Event::class); + } + + public function user() + { + return $this->belongsTo(User::class); + } + + public function tenantRelation() + { + return $this->belongsTo(Tenant::class, 'tenant', 'slug'); + } + + public function localGroup() + { + return $this->belongsTo(Tenant::class, 'local_group', 'slug'); + } + + public function participationType() + { + return $this->belongsTo(ParticipationType::class, 'participation_type', 'slug'); + } + + public function swimmingPermission() + { + return $this->belongsTo(SwimmingPermission::class, 'swimming_permission', 'slug'); + } + + public function eatingHabit() + { + return $this->belongsTo(EatingHabit::class, 'eating_habits', 'slug'); + } + + public function firstAidPermission() + { + return $this->belongsTo(FirstAidPermission::class, 'first_aid_permission', 'slug'); + } + + public function efzStatus() + { + return $this->belongsTo(EfzStatus::class, 'efz_status', 'slug'); + } + + +} diff --git a/app/Repositories/CostUnitRepository.php b/app/Repositories/CostUnitRepository.php index 67bbb2d..0d59ca1 100644 --- a/app/Repositories/CostUnitRepository.php +++ b/app/Repositories/CostUnitRepository.php @@ -68,18 +68,22 @@ class CostUnitRepository { $canSeeAll = false; $user = Auth()->user(); - if ($tenant->slug !== 'lv') { - if ( - $user->user_role_main === UserRole::USER_ROLE_ADMIN || - in_array( $user->user_role_local_group, [UserRole::USER_ROLE_GROUP_LEADER, UserRole::USER_ROLE_ADMIN]) - ) { - $canSeeAll = true; - } + if ($disableAccessCheck) { + $canSeeAll = true; } else { - if ( - in_array( $user->user_role_main, [UserRole::USER_ROLE_GROUP_LEADER, UserRole::USER_ROLE_ADMIN]) - ) { - $canSeeAll = true; + if ($tenant->slug !== 'lv') { + if ( + $user->user_role_main === UserRole::USER_ROLE_ADMIN || + in_array($user->user_role_local_group, [UserRole::USER_ROLE_GROUP_LEADER, UserRole::USER_ROLE_ADMIN]) + ) { + $canSeeAll = true; + } + } else { + if ( + in_array($user->user_role_main, [UserRole::USER_ROLE_GROUP_LEADER, UserRole::USER_ROLE_ADMIN]) + ) { + $canSeeAll = true; + } } } diff --git a/app/Repositories/EventRepository.php b/app/Repositories/EventRepository.php index 7fd5acd..f0290d8 100644 --- a/app/Repositories/EventRepository.php +++ b/app/Repositories/EventRepository.php @@ -27,18 +27,22 @@ class EventRepository { $canSeeAll = false; $user = Auth()->user(); - if ($tenant->slug !== 'lv') { - if ( - $user->user_role_main === UserRole::USER_ROLE_ADMIN || - in_array( $user->user_role_local_group, [UserRole::USER_ROLE_GROUP_LEADER, UserRole::USER_ROLE_ADMIN]) - ) { - $canSeeAll = true; - } + if (!$accessCheck) { + $canSeeAll = true; } else { - if ( - in_array( $user->user_role_main, [UserRole::USER_ROLE_GROUP_LEADER, UserRole::USER_ROLE_ADMIN]) - ) { - $canSeeAll = true; + if ($tenant->slug !== 'lv') { + if ( + $user->user_role_main === UserRole::USER_ROLE_ADMIN || + in_array($user->user_role_local_group, [UserRole::USER_ROLE_GROUP_LEADER, UserRole::USER_ROLE_ADMIN]) + ) { + $canSeeAll = true; + } + } else { + if ( + in_array($user->user_role_main, [UserRole::USER_ROLE_GROUP_LEADER, UserRole::USER_ROLE_ADMIN]) + ) { + $canSeeAll = true; + } } } diff --git a/database/migrations/2026_01_30_140002_create_users_table.php b/database/migrations/2026_01_30_140002_create_users_table.php index 8921fc0..bd6afd9 100644 --- a/database/migrations/2026_01_30_140002_create_users_table.php +++ b/database/migrations/2026_01_30_140002_create_users_table.php @@ -67,12 +67,12 @@ return new class extends Migration $table->dateTime('activation_token_expires_at')->nullable()->default(date('Y-m-d H:i:s', strtotime('+3 days'))); $table->boolean('active')->default(false); - $table->foreign('local_group')->references('slug')->on('tenants')->cascadeOnDelete()->cascadeOnUpdate(); - $table->foreign('user_role_main')->references('slug')->on('user_roles')->cascadeOnDelete()->cascadeOnUpdate(); - $table->foreign('user_role_local_group')->references('slug')->on('user_roles')->cascadeOnDelete()->cascadeOnUpdate(); - $table->foreign('swimming_permission')->references('slug')->on('swimming_permissions')->cascadeOnDelete()->cascadeOnUpdate(); - $table->foreign('eating_habits')->references('slug')->on('eating_habits')->cascadeOnDelete()->cascadeOnUpdate(); - $table->foreign('first_aid_permission')->references('slug')->on('first_aid_permissions')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreign('local_group')->references('slug')->on('tenants')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('user_role_main')->references('slug')->on('user_roles')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('user_role_local_group')->references('slug')->on('user_roles')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('swimming_permission')->references('slug')->on('swimming_permissions')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('eating_habits')->references('slug')->on('eating_habits')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('first_aid_permission')->references('slug')->on('first_aid_permissions')->restrictOnDelete()->cascadeOnUpdate(); $table->rememberToken(); $table->timestamps(); diff --git a/database/migrations/2026_01_30_140010_create_cost_units.php b/database/migrations/2026_01_30_140010_create_cost_units.php index 923219e..f47535c 100644 --- a/database/migrations/2026_01_30_140010_create_cost_units.php +++ b/database/migrations/2026_01_30_140010_create_cost_units.php @@ -26,15 +26,15 @@ return new class extends Migration { $table->boolean('allow_new')->default(true); $table->boolean('archived')->default(false); - $table->foreign('tenant')->references('slug')->on('tenants')->cascadeOnDelete()->cascadeOnUpdate(); - $table->foreign('type')->references('slug')->on('cost_unit_types')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreign('tenant')->references('slug')->on('tenants')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('type')->references('slug')->on('cost_unit_types')->restrictOnDelete()->cascadeOnUpdate(); $table->timestamps(); }); Schema::create('cost_unit_treasurers', function (Blueprint $table) { $table->id(); - $table->foreignId('cost_unit_id')->constrained('cost_units', 'id')->cascadeOnDelete()->cascadeOnUpdate(); - $table->foreignId('user_id')->constrained('users', 'id')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreignId('cost_unit_id')->constrained('cost_units', 'id')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreignId('user_id')->constrained('users', 'id')->restrictOnDelete()->cascadeOnUpdate(); $table->timestamps(); }); } diff --git a/database/migrations/2026_01_30_140010_create_invoices.php b/database/migrations/2026_01_30_140010_create_invoices.php index 8611ff9..dabe3a0 100644 --- a/database/migrations/2026_01_30_140010_create_invoices.php +++ b/database/migrations/2026_01_30_140010_create_invoices.php @@ -23,13 +23,13 @@ return new class extends Migration { Schema::create('invoices', function (Blueprint $table) { $table->id(); $table->string('tenant'); - $table->foreignId('cost_unit_id')->constrained('cost_units', 'id')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreignId('cost_unit_id')->constrained('cost_units', 'id')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreignId('user_id')->nullable()->constrained('users', 'id')->restrictOnDelete()->cascadeOnUpdate(); $table->string('invoice_number'); $table->string('status'); $table->string('type'); $table->string('type_other')->nullable(); $table->boolean('donation')->default(false); - $table->foreignId('user_id')->nullable()->constrained('users', 'id')->cascadeOnDelete()->cascadeOnUpdate(); $table->string('contact_name'); $table->string('contact_email')->nullable(); $table->string('contact_phone')->nullable(); @@ -43,16 +43,16 @@ return new class extends Migration { $table->boolean('passengers')->nullable(); $table->boolean('transportation')->nullable(); $table->string('document_filename')->nullable(); - $table->foreignId('approved_by')->nullable()->constrained('users', 'id')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreignId('approved_by')->nullable()->constrained('users', 'id')->restrictOnDelete()->cascadeOnUpdate(); $table->dateTime('approved_at')->nullable(); $table->boolean('upload_required')->default(false); - $table->foreignId('denied_by')->nullable()->constrained('users', 'id')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreignId('denied_by')->nullable()->constrained('users', 'id')->restrictOnDelete()->cascadeOnUpdate(); $table->dateTime('denied_at')->nullable(); $table->string('denied_reason')->nullable(); - $table->foreign('tenant')->references('slug')->on('tenants')->cascadeOnDelete()->cascadeOnUpdate(); - $table->foreign('type')->references('slug')->on('invoice_types')->cascadeOnDelete()->cascadeOnUpdate(); - $table->foreign('status')->references('slug')->on('invoice_status')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreign('tenant')->references('slug')->on('tenants')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('type')->references('slug')->on('invoice_types')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('status')->references('slug')->on('invoice_status')->restrictOnDelete()->cascadeOnUpdate(); $table->timestamps(); }); diff --git a/database/migrations/2026_02_01_140010_create_cron_tasks.php b/database/migrations/2026_02_01_140010_create_cron_tasks.php index ce76fc1..c9e6727 100644 --- a/database/migrations/2026_02_01_140010_create_cron_tasks.php +++ b/database/migrations/2026_02_01_140010_create_cron_tasks.php @@ -11,6 +11,7 @@ return new class extends Migration { { Schema::create('cron_task_types', function (Blueprint $table) { $table->string('slug')->primary(); + $table->timestamps(); }); diff --git a/database/migrations/2026_02_14_140010_create_events.php b/database/migrations/2026_02_14_140010_create_events.php index 6051615..7ae0fbe 100644 --- a/database/migrations/2026_02_14_140010_create_events.php +++ b/database/migrations/2026_02_14_140010_create_events.php @@ -30,14 +30,14 @@ return new class extends Migration { $table->float('amount',2); $table->timestamps(); - $table->foreign('type')->references('slug')->on('participation_types')->cascadeOnDelete()->cascadeOnUpdate(); - $table->foreign('tenant')->references('slug')->on('tenants')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreign('type')->references('slug')->on('participation_types')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('tenant')->references('slug')->on('tenants')->restrictOnDelete()->cascadeOnUpdate(); }); Schema::create('events', function (Blueprint $table) { $table->id(); $table->string('tenant'); - $table->foreignId('cost_unit_id')->nullable()->constrained('cost_units', 'id')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreignId('cost_unit_id')->nullable()->constrained('cost_units', 'id')->restrictOnDelete()->cascadeOnUpdate(); $table->string('name'); $table->string('location'); @@ -67,21 +67,21 @@ return new class extends Migration { $table->boolean('archived')->default(false); $table->timestamps(); - $table->foreign('tenant')->references('slug')->on('tenants')->cascadeOnDelete()->cascadeOnUpdate(); - $table->foreign('participation_fee_type')->references('slug')->on('participation_fee_types')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreign('tenant')->references('slug')->on('tenants')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('participation_fee_type')->references('slug')->on('participation_fee_types')->restrictOnDelete()->cascadeOnUpdate(); }); Schema::create('event_allowed_eating_habits', function (Blueprint $table) { $table->id(); - $table->foreignId('event_id')->constrained('events', 'id')->cascadeOnDelete()->cascadeOnUpdate(); - $table->foreignId('eating_habit_id')->constrained('eating_habits', 'id')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreignId('event_id')->constrained('events', 'id')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreignId('eating_habit_id')->constrained('eating_habits', 'id')->restrictOnDelete()->cascadeOnUpdate(); $table->timestamps(); }); Schema::create('event_managers', function (Blueprint $table) { $table->id(); - $table->foreignId('event_id')->constrained('events', 'id')->cascadeOnDelete()->cascadeOnUpdate(); - $table->string('user_id')->constrained('users', 'id')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreignId('event_id')->constrained('events', 'id')->restrictOnDelete()->cascadeOnUpdate(); + $table->string('user_id')->constrained('users', 'id')->restrictOnDelete()->cascadeOnUpdate(); $table->timestamps(); }); diff --git a/database/migrations/2026_02_14_140011_create_event_localgroups.php b/database/migrations/2026_02_14_140011_create_event_localgroups.php index 6490185..13edf5d 100644 --- a/database/migrations/2026_02_14_140011_create_event_localgroups.php +++ b/database/migrations/2026_02_14_140011_create_event_localgroups.php @@ -11,8 +11,8 @@ return new class extends Migration { { Schema::create('event_local_groups', function (Blueprint $table) { $table->id(); - $table->foreignId('event_id')->constrained('events', 'id')->cascadeOnDelete()->cascadeOnUpdate(); - $table->foreignId('local_group_id')->constrained('tenants', 'id')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreignId('event_id')->constrained('events', 'id')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreignId('local_group_id')->constrained('tenants', 'id')->restrictOnDelete()->cascadeOnUpdate(); $table->timestamps(); }); } diff --git a/database/migrations/2026_02_15_140010_create_event_particpants.php b/database/migrations/2026_02_15_140010_create_event_particpants.php new file mode 100644 index 0000000..0c3942a --- /dev/null +++ b/database/migrations/2026_02_15_140010_create_event_particpants.php @@ -0,0 +1,86 @@ +string('slug')->primary(); + $table->string('name'); + $table->timestamps(); + }); + + + Schema::create('event_participants', function (Blueprint $table) { + $table->id(); + $table->string('tenant'); + + $table->foreignId('event_id')->constrained('events', 'id')->cascadeOnDelete()->cascadeOnUpdate(); + $table->foreignId('user_id')->nullable()->constrained('users', 'id')->cascadeOnDelete()->cascadeOnUpdate(); + + + $table->string('firstname'); + $table->string('lastname'); + $table->string('nickname')->nullable(); + $table->string('participation_type'); + $table->string('local_group'); + $table->dateTime('birthday'); + $table->string('address_1'); + $table->string('address_2'); + $table->string('postcode'); + $table->string('city'); + $table->string('email_1'); + $table->string('phone_1'); + $table->string('email_2')->nullable(); + $table->string('phone_2')->nullable(); + $table->string('contact_person')->nullable(); + $table->string('allergies')->nullable(); + $table->string('intolerances')->nullable(); + $table->string('eating_habits')->nullable(); + $table->string('swimming_permission')->nullable(); + $table->string('first_aid_permission')->nullable(); + $table->boolean('foto_socialmedia')->default(false); + $table->boolean('foto_print')->default(false); + $table->boolean('foto_webseite')->default(false); + $table->boolean('foto_partner')->default(false); + $table->boolean('foto_intern')->default(false); + $table->dateTime('arrival_date'); + $table->dateTime('departure_date'); + $table->integer('arrival_eating'); + $table->integer('departure_eating'); + $table->longText('notes')->nullable(); + $table->float('amount', 2); + $table->float('amount_paid',0)->default(0); + $table->string('efz_status'); + $table->timestamps(); + $table->dateTime('unregistered_at')->nullable(); + + $table->foreign('swimming_permission')->references('slug')->on('swimming_permissions')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('eating_habits')->references('slug')->on('eating_habits')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('first_aid_permission')->references('slug')->on('first_aid_permissions')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('tenant')->references('slug')->on('tenants')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('local_group')->references('slug')->on('tenants')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('participation_type')->references('slug')->on('participation_types')->restrictOnDelete()->cascadeOnUpdate(); + $table->foreign('efz_status')->references('slug')->on('efz_status')->restrictOnDelete()->cascadeOnUpdate(); + + }); + + } + + + + + + + + public function down(): void + { + Schema::dropIfExists('event_participants'); + Schema::dropIfExists('efz_status'); + } +};