From 2cd75fe5021f3292ffcdbbd7745659923dee2622 Mon Sep 17 00:00:00 2001 From: philipp lang Date: Sat, 20 Nov 2021 00:48:42 +0100 Subject: [PATCH] Add update member --- app/Course/Controllers/CourseController.php | 9 ++ app/Course/Models/CourseMember.php | 19 +++ app/Course/Requests/StoreRequest.php | 7 +- app/Course/Requests/UpdateRequest.php | 50 +++++++ app/Initialize/InitializeMembers.php | 3 +- app/Member/Member.php | 6 +- .../factories/Course/Models/CourseFactory.php | 1 + .../Course/Models/CourseMemberFactory.php | 32 +++++ ...2021_11_18_001427_create_courses_table.php | 4 +- packages/laravel-nami | 2 +- tests/Feature/Course/StoreTest.php | 4 +- tests/Feature/Course/UpdateTest.php | 125 ++++++++++++++++++ tests/Feature/Initialize/InitializeTest.php | 2 +- 13 files changed, 250 insertions(+), 14 deletions(-) create mode 100644 app/Course/Models/CourseMember.php create mode 100644 app/Course/Requests/UpdateRequest.php create mode 100644 database/factories/Course/Models/CourseMemberFactory.php create mode 100644 tests/Feature/Course/UpdateTest.php diff --git a/app/Course/Controllers/CourseController.php b/app/Course/Controllers/CourseController.php index 81e29149..c41bc381 100644 --- a/app/Course/Controllers/CourseController.php +++ b/app/Course/Controllers/CourseController.php @@ -2,7 +2,9 @@ namespace App\Course\Controllers; +use App\Course\Models\CourseMember; use App\Course\Requests\StoreRequest; +use App\Course\Requests\UpdateRequest; use App\Http\Controllers\Controller; use App\Member\Member; use Illuminate\Http\RedirectResponse; @@ -16,4 +18,11 @@ class CourseController extends Controller return redirect()->route('member.index'); } + + public function update(Member $member, CourseMember $course, UpdateRequest $request): RedirectResponse + { + $request->persist($member, $course); + + return redirect()->route('member.index'); + } } diff --git a/app/Course/Models/CourseMember.php b/app/Course/Models/CourseMember.php new file mode 100644 index 00000000..8200bdb7 --- /dev/null +++ b/app/Course/Models/CourseMember.php @@ -0,0 +1,19 @@ +belongsTo(Course::class); + } +} diff --git a/app/Course/Requests/StoreRequest.php b/app/Course/Requests/StoreRequest.php index 70597150..b28b4d9b 100644 --- a/app/Course/Requests/StoreRequest.php +++ b/app/Course/Requests/StoreRequest.php @@ -40,7 +40,7 @@ class StoreRequest extends FormRequest { $course = Course::where('id', $this->input('course_id'))->firstOrFail(); $payload = array_merge( - $this->only(['event_name', 'completed_at', 'course_id', 'organizer']), + $this->only(['event_name', 'completed_at', 'organizer']), ['course_id' => $course->nami_id], ); @@ -50,9 +50,6 @@ class StoreRequest extends FormRequest throw ValidationException::withMessages(['id' => 'Unbekannter Fehler']); } - $member->courses()->attach( - $course, - $this->safe()->collect()->put('nami_id', $namiId)->except(['course_id'])->toArray(), - ); + $member->courses()->create($this->safe()->collect()->put('nami_id', $namiId)->toArray()); } } diff --git a/app/Course/Requests/UpdateRequest.php b/app/Course/Requests/UpdateRequest.php new file mode 100644 index 00000000..05b0c268 --- /dev/null +++ b/app/Course/Requests/UpdateRequest.php @@ -0,0 +1,50 @@ + + */ + public function rules() + { + return [ + 'organizer' => 'required|max:255', + 'event_name' => 'required|max:255', + 'completed_at' => 'required|date', + 'course_id' => 'required|exists:courses,id', + ]; + } + + public function persist(Member $member, CourseMember $course): void + { + try { + auth()->user()->api()->updateCourse($member->nami_id, $course->nami_id, $this->safe()->merge(['course_id' => Course::find($this->input('course_id'))->nami_id])->toArray()); + } catch(NamiException $e) { + throw ValidationException::withMessages(['id' => 'Unbekannter Fehler']); + } + + $course->update($this->safe()->toArray()); + } +} diff --git a/app/Initialize/InitializeMembers.php b/app/Initialize/InitializeMembers.php index e34254ad..ef39e396 100644 --- a/app/Initialize/InitializeMembers.php +++ b/app/Initialize/InitializeMembers.php @@ -75,7 +75,8 @@ class InitializeMembers { ]); foreach ($this->api->coursesFor($member->id) as $course) { - $m->courses()->attach(Course::where('nami_id', $course->course_id)->firstOrFail(), [ + $m->courses()->create([ + 'course_id' => Course::where('nami_id', $course->course_id)->firstOrFail()->id, 'organizer' => $course->organizer, 'event_name' => $course->event_name, 'completed_at' => $course->completed_at, diff --git a/app/Member/Member.php b/app/Member/Member.php index 7a3ea32b..bb86027d 100644 --- a/app/Member/Member.php +++ b/app/Member/Member.php @@ -6,7 +6,7 @@ use App\Activity; use App\Bill\BillKind; use App\Confession; use App\Country; -use App\Course\Models\Course; +use App\Course\Models\CourseMember; use App\Group; use App\Nationality; use App\Payment\Payment; @@ -149,9 +149,9 @@ class Member extends Model return $this->belongsTo(Subactivity::class, 'first_subactivity_id'); } - public function courses(): BelongsToMany + public function courses(): HasMany { - return $this->belongsToMany(Course::class)->withPivot(['organizer', 'completed_at', 'event_name']); + return $this->hasMany(CourseMember::class); } public static function booted() diff --git a/database/factories/Course/Models/CourseFactory.php b/database/factories/Course/Models/CourseFactory.php index 2a269bbd..2d61a24a 100644 --- a/database/factories/Course/Models/CourseFactory.php +++ b/database/factories/Course/Models/CourseFactory.php @@ -27,6 +27,7 @@ class CourseFactory extends Factory { return [ 'name' => $this->faker->words(5, true), + 'nami_id' => $this->faker->numberBetween(1111, 9999), ]; } diff --git a/database/factories/Course/Models/CourseMemberFactory.php b/database/factories/Course/Models/CourseMemberFactory.php new file mode 100644 index 00000000..5e71013c --- /dev/null +++ b/database/factories/Course/Models/CourseMemberFactory.php @@ -0,0 +1,32 @@ + + */ + public function definition() + { + return [ + 'organizer' => $this->faker->words(5, true), + 'event_name' => $this->faker->words(5, true), + 'nami_id' => $this->faker->numberBetween(1111, 9999), + 'completed_at' => $this->faker->date(), + ]; + } + + public function inNami(int $namiId): self + { + return $this->state(['nami_id' => $namiId]); + } +} diff --git a/database/migrations/2021_11_18_001427_create_courses_table.php b/database/migrations/2021_11_18_001427_create_courses_table.php index 63a2dcd8..549d78f7 100644 --- a/database/migrations/2021_11_18_001427_create_courses_table.php +++ b/database/migrations/2021_11_18_001427_create_courses_table.php @@ -18,13 +18,15 @@ class CreateCoursesTable extends Migration $table->unsignedInteger('nami_id'); $table->string('name'); }); - Schema::create('course_member', function($table) { + Schema::create('course_members', function($table) { + $table->id(); $table->foreignId('member_id')->constrained(); $table->foreignId('course_id')->constrained(); $table->string('organizer'); $table->string('event_name'); $table->unsignedInteger('nami_id'); $table->date('completed_at'); + $table->timestamps(); }); } diff --git a/packages/laravel-nami b/packages/laravel-nami index 12383090..8614f81e 160000 --- a/packages/laravel-nami +++ b/packages/laravel-nami @@ -1 +1 @@ -Subproject commit 1238309006a18aa1de37bbaac74c3089c128c582 +Subproject commit 8614f81eca34143732a1618492c13e674ce7e224 diff --git a/tests/Feature/Course/StoreTest.php b/tests/Feature/Course/StoreTest.php index f7dbb980..7e69c6db 100644 --- a/tests/Feature/Course/StoreTest.php +++ b/tests/Feature/Course/StoreTest.php @@ -85,7 +85,7 @@ class StoreTest extends TestCase ]); $response->assertRedirect("/member"); - $this->assertDatabaseHas('course_member', [ + $this->assertDatabaseHas('course_members', [ 'member_id' => $member->id, 'course_id' => $course->id, 'completed_at' => '2021-01-02', @@ -116,7 +116,7 @@ class StoreTest extends TestCase ]); $response->assertSessionHasErrors(['id' => 'Unbekannter Fehler']); - $this->assertDatabaseCount('course_member', 0); + $this->assertDatabaseCount('course_members', 0); } } diff --git a/tests/Feature/Course/UpdateTest.php b/tests/Feature/Course/UpdateTest.php new file mode 100644 index 00000000..10eb12d6 --- /dev/null +++ b/tests/Feature/Course/UpdateTest.php @@ -0,0 +1,125 @@ +, errors: array}> + */ + public function validationDataProvider(): array + { + return [ + 'course_id_missing' => [ + 'payload' => ['course_id' => null], + 'errors' => ['course_id' => 'Baustein ist erforderlich.'], + ], + 'course_id_invalid' => [ + 'payload' => ['course_id' => 999], + 'errors' => ['course_id' => 'Baustein ist nicht vorhanden.'], + ], + 'completed_at_required' => [ + 'payload' => ['completed_at' => ''], + 'errors' => ['completed_at' => 'Datum ist erforderlich.'], + ], + 'completed_at_not_date' => [ + 'payload' => ['completed_at' => '123'], + 'errors' => ['completed_at' => 'Datum muss ein gültiges Datum sein.'], + ], + 'event_name_required' => [ + 'payload' => ['event_name' => ''], + 'errors' => ['event_name' => 'Veranstaltung ist erforderlich.'], + ], + 'organizer' => [ + 'payload' => ['organizer' => ''], + 'errors' => ['organizer' => 'Veranstalter ist erforderlich.'], + ], + ]; + } + + /** + * @param array $payload + * @param array $errors + * @dataProvider validationDataProvider + */ + public function testItValidatesInput(array $payload, array $errors): void + { + $this->login()->init(); + $member = Member::factory()->defaults()->inNami(123)->has(CourseMember::factory()->for(Course::factory()), 'courses')->createOne(); + $newCourse = Course::factory()->inNami(789)->create(); + + $response = $this->patch("/member/{$member->id}/course/{$member->courses->first()->id}", array_merge([ + 'course_id' => $newCourse->id, + 'completed_at' => '1999-02-03', + 'event_name' => '::newevent::', + 'organizer' => '::org::', + ], $payload)); + + $response->assertSessionHasErrors($errors); + } + + public function testItUpdatesACourse(): void + { + $this->withoutExceptionHandling(); + $this->login()->init(); + app(CourseFake::class)->updatesSuccessful(123, 999); + $member = Member::factory()->defaults()->inNami(123)->has(CourseMember::factory()->inNami(999)->for(Course::factory()), 'courses')->createOne(); + $newCourse = Course::factory()->inNami(789)->create(); + + $response = $this->patch("/member/{$member->id}/course/{$member->courses->first()->id}", array_merge([ + 'course_id' => $newCourse->id, + 'completed_at' => '1999-02-03', + 'event_name' => '::newevent::', + 'organizer' => '::neworg::', + ])); + + $response->assertRedirect("/member"); + $this->assertDatabaseHas('course_members', [ + 'member_id' => $member->id, + 'course_id' => $newCourse->id, + 'event_name' => '::newevent::', + 'organizer' => '::neworg::', + 'completed_at' => '1999-02-03', + 'nami_id' => 999, + ]); + app(CourseFake::class)->assertUpdated(123, 999, [ + 'bausteinId' => 789, + 'veranstalter' => '::neworg::', + 'vstgName' => '::newevent::', + 'vstgTag' => '1999-02-03T00:00:00', + ]); + } + + /* + public function testItReceivesUnknownErrors(): void + { + $this->login()->init(); + $member = Member::factory()->defaults()->inNami(123)->createOne(); + $course = Course::factory()->inNami(456)->createOne(); + app(CourseFake::class)->doesntCreateWithError(123); + + $response = $this->post("/member/{$member->id}/course", [ + 'course_id' => $course->id, + 'completed_at' => '2021-01-02', + 'event_name' => '::event::', + 'organizer' => '::org::', + ]); + + $response->assertSessionHasErrors(['id' => 'Unbekannter Fehler']); + $this->assertDatabaseCount('course_member', 0); + } + */ + +} diff --git a/tests/Feature/Initialize/InitializeTest.php b/tests/Feature/Initialize/InitializeTest.php index aa680ba7..8400d47c 100644 --- a/tests/Feature/Initialize/InitializeTest.php +++ b/tests/Feature/Initialize/InitializeTest.php @@ -136,7 +136,7 @@ class InitializeTest extends TestCase $this->post('/initialize'); - $this->assertDatabaseHas('course_member', [ + $this->assertDatabaseHas('course_members', [ 'member_id' => Member::where('firstname', '::firstname::')->firstOrFail()->id, 'course_id' => Course::where('name', '1a')->firstOrFail()->id, 'event_name' => 'eventname',