From d42cee55af25cd06d69803e3f24ef3d4cf9c0e1d Mon Sep 17 00:00:00 2001
From: philipp lang <philipp@aweos.de>
Date: Thu, 18 Nov 2021 01:54:27 +0100
Subject: [PATCH] Add: Sync courses

---
 app/Course.php                                | 14 +++++++
 app/Initialize/InitializeCourses.php          | 26 ++++++++++++
 app/Initialize/InitializeJob.php              |  1 +
 app/Initialize/InitializeMembers.php          | 10 +++++
 app/Member/Member.php                         |  7 ++++
 database/factories/CourseFactory.php          | 20 ++++++++++
 ...2021_11_18_001427_create_courses_table.php | 40 +++++++++++++++++++
 tests/Feature/Initialize/InitializeTest.php   | 36 ++++++++++++++++-
 8 files changed, 152 insertions(+), 2 deletions(-)
 create mode 100644 app/Course.php
 create mode 100644 app/Initialize/InitializeCourses.php
 create mode 100644 database/factories/CourseFactory.php
 create mode 100644 database/migrations/2021_11_18_001427_create_courses_table.php

diff --git a/app/Course.php b/app/Course.php
new file mode 100644
index 00000000..17aa1a7a
--- /dev/null
+++ b/app/Course.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class Course extends Model
+{
+    use HasFactory;
+
+    public $timestamps = false;
+    public $guarded = [];
+}
diff --git a/app/Initialize/InitializeCourses.php b/app/Initialize/InitializeCourses.php
new file mode 100644
index 00000000..8f051547
--- /dev/null
+++ b/app/Initialize/InitializeCourses.php
@@ -0,0 +1,26 @@
+<?php 
+
+namespace App\Initialize;
+
+use App\Course;
+use Aweos\Agnoster\Progress\Progress;
+use Zoomyboy\LaravelNami\Api;
+use Zoomyboy\LaravelNami\NamiUser;
+
+class InitializeCourses {
+
+    private Progress $bar;
+    private Api $api;
+
+    public function __construct(Progress $bar, Api $api) {
+        $this->bar = $bar;
+        $this->api = $api;
+    }
+
+    public function handle(NamiUser $user): void
+    {
+        $this->api->courses()->each(function($course) {
+            Course::create(['nami_id' => $course->id, 'name' => $course->name]);
+        });
+    }
+}
diff --git a/app/Initialize/InitializeJob.php b/app/Initialize/InitializeJob.php
index 16dc5ff6..9128d8a0 100644
--- a/app/Initialize/InitializeJob.php
+++ b/app/Initialize/InitializeJob.php
@@ -25,6 +25,7 @@ class InitializeJob implements ShouldQueue
         InitializeGenders::class,
         InitializeRegions::class,
         InitializeActivities::class,
+        InitializeCourses::class,
         InitializeMembers::class,
     ];
 
diff --git a/app/Initialize/InitializeMembers.php b/app/Initialize/InitializeMembers.php
index b4ee361a..bcb2fb87 100644
--- a/app/Initialize/InitializeMembers.php
+++ b/app/Initialize/InitializeMembers.php
@@ -5,6 +5,7 @@ namespace App\Initialize;
 use App\Activity;
 use App\Confession;
 use App\Country;
+use App\Course;
 use App\Fee;
 use App\Gender;
 use App\Group;
@@ -72,6 +73,15 @@ class InitializeMembers {
                         'nationality_id' => Nationality::where('nami_id', $member->nationality_id)->firstOrFail()->id,
                         'version' => $member->version,
                     ]);
+
+                    foreach ($this->api->coursesFor($member->id) as $course) {
+                        $m->courses()->attach(Course::where('nami_id', $course->course_id)->firstOrFail(), [
+                            'organizer' => $course->organizer,
+                            'event_name' => $course->event_name,
+                            'completed_at' => $course->completed_at,
+                            'nami_id' => $course->id,
+                        ]);
+                    }
                 } catch (ModelNotFoundException $e) {
                     dd($e->getMessage(), $member);
                 }
diff --git a/app/Member/Member.php b/app/Member/Member.php
index 862a1995..8ce5930b 100644
--- a/app/Member/Member.php
+++ b/app/Member/Member.php
@@ -6,6 +6,7 @@ use App\Activity;
 use App\Bill\BillKind;
 use App\Confession;
 use App\Country;
+use App\Course;
 use App\Group;
 use App\Nationality;
 use App\Payment\Payment;
@@ -16,6 +17,7 @@ use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
 use Illuminate\Database\Eloquent\Relations\HasMany;
 use Illuminate\Notifications\Notifiable;
 use Zoomyboy\LaravelNami\Api;
@@ -147,6 +149,11 @@ class Member extends Model
         return $this->belongsTo(Subactivity::class, 'first_subactivity_id');
     }
 
+    public function courses(): BelongsToMany
+    {
+        return $this->belongsToMany(Course::class)->withPivot(['organizer', 'completed_at', 'event_name']);
+    }
+
     public static function booted()
     {
         static::deleting(function(self $model): void {
diff --git a/database/factories/CourseFactory.php b/database/factories/CourseFactory.php
new file mode 100644
index 00000000..7c11880c
--- /dev/null
+++ b/database/factories/CourseFactory.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace Database\Factories;
+
+use Illuminate\Database\Eloquent\Factories\Factory;
+
+class CourseFactory extends Factory
+{
+    /**
+     * Define the model's default state.
+     *
+     * @return array
+     */
+    public function definition()
+    {
+        return [
+            //
+        ];
+    }
+}
diff --git a/database/migrations/2021_11_18_001427_create_courses_table.php b/database/migrations/2021_11_18_001427_create_courses_table.php
new file mode 100644
index 00000000..63a2dcd8
--- /dev/null
+++ b/database/migrations/2021_11_18_001427_create_courses_table.php
@@ -0,0 +1,40 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateCoursesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('courses', function (Blueprint $table) {
+            $table->id();
+            $table->unsignedInteger('nami_id');
+            $table->string('name');
+        });
+        Schema::create('course_member', function($table) {
+            $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');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('courses');
+    }
+}
diff --git a/tests/Feature/Initialize/InitializeTest.php b/tests/Feature/Initialize/InitializeTest.php
index 49520c5a..0e40f011 100644
--- a/tests/Feature/Initialize/InitializeTest.php
+++ b/tests/Feature/Initialize/InitializeTest.php
@@ -4,7 +4,9 @@ namespace Tests\Feature\Initialize;
 
 use App\Activity;
 use App\Country;
+use App\Course;
 use App\Gender;
+use App\Member\Member;
 use App\Nationality;
 use Illuminate\Foundation\Testing\RefreshDatabase;
 use Illuminate\Foundation\Testing\WithFaker;
@@ -28,6 +30,7 @@ class InitializeTest extends TestCase
             ->fakeCountries([['name' => 'Germany', 'id' => 302]])
             ->fakeGenders([['name' => 'Male', 'id' => 303]])
             ->fakeRegions([['name' => 'nrw', 'id' => 304]])
+            ->fakeCourses([['name' => '1a', 'id' => 506]])
             ->fakeActivities(1000, [['name' => 'leiter', 'id' => 305]]);
 
         if (!$callback) {
@@ -59,7 +62,7 @@ class InitializeTest extends TestCase
         ]);
     }
 
-    public function testItInitializesGenders(): void
+    public function testItInitializesAll(): void
     {
         $this->withoutExceptionHandling();
         $this->initializeProvider();
@@ -98,6 +101,10 @@ class InitializeTest extends TestCase
             'name' => 'Leiter',
             'nami_id' => 305
         ]);
+        $this->assertDatabaseHas('courses', [
+            'name' => '1a',
+            'nami_id' => 506
+        ]);
         $this->assertDatabaseHas('groups', ['nami_id' => 1000, 'name' => '::group::']);
         $this->assertDatabaseHas('members', [
             'nami_id' => 411,
@@ -112,7 +119,32 @@ class InitializeTest extends TestCase
         ]);
         $this->assertEquals([306], Activity::where('nami_id', 305)->firstOrFail()->subactivities()->pluck('nami_id')->toArray());
 
-        Http::assertSentCount(13);
+        Http::assertSentCount(15);
+    }
+
+    public function testSyncCoursesOfMember(): void
+    {
+        $this->withoutExceptionHandling();
+        $this->initializeProvider(function($backend) {
+            $backend->fakeMembers([
+                $this->member(['courses' => [ ['bausteinId' => 506, 'id' => 788, 'veranstalter' => 'KJA', 'vstgName' => 'eventname', 'vstgTag' => '2021-11-12 00:00:00'] ]])
+            ]);
+        });
+        $this->post('/login', [
+            'mglnr' => 123,
+            'password' => 'secret',
+        ]);
+
+        $this->post('/initialize');
+
+        $this->assertDatabaseHas('course_member', [
+            'member_id' => Member::where('firstname', '::firstname::')->firstOrFail()->id,
+            'course_id' => Course::where('name', '1a')->firstOrFail()->id,
+            'event_name' => 'eventname',
+            'completed_at' => '2021-11-12',
+            'organizer' => 'KJA',
+            'nami_id' => 788,
+        ]);
     }
 
     public function testItDoesntGetMembersWithNoJoinedAtDate(): void