From 5f71f6e4bfccc0b3917fc5c61c8fa6523d5a7261 Mon Sep 17 00:00:00 2001
From: philipp lang <philipp@aweos.de>
Date: Mon, 3 Jan 2022 10:33:48 +0100
Subject: [PATCH] Fixed: Get membership

---
 app/Initialize/InitializeMembers.php          | 108 ++++++++++--------
 app/Member/Membership.php                     |   2 +-
 ..._01_18_205354_create_memberships_table.php |   5 +-
 tests/Feature/Initialize/InitializeTest.php   |  85 ++++++++++----
 4 files changed, 128 insertions(+), 72 deletions(-)

diff --git a/app/Initialize/InitializeMembers.php b/app/Initialize/InitializeMembers.php
index 31fd0e62..326b3b85 100644
--- a/app/Initialize/InitializeMembers.php
+++ b/app/Initialize/InitializeMembers.php
@@ -1,4 +1,4 @@
-<?php 
+<?php
 
 namespace App\Initialize;
 
@@ -22,7 +22,7 @@ use Zoomyboy\LaravelNami\NamiException;
 class InitializeMembers {
 
     private $api;
-    
+
     public function __construct($api) {
         $this->api = $api;
     }
@@ -85,58 +85,22 @@ class InitializeMembers {
                 }
 
                 foreach ($this->api->membershipsOf($member->id) as $membership) {
-                    if (Carbon::parse($membership['entries_aktivVon'])->addYears(200)->isPast()) {
-                        continue;
-                    }
                     if ($membership['entries_aktivBis'] !== '') {
                         continue;
                     }
-                    if (preg_match('/\(([0-9]+)\)/', $membership['entries_taetigkeit'], $activityMatches) !== 1) {
-                        throw new NamiException("ID in taetigkeit string not found: {$membership['entries_taetigkeit']}");
+                    try {
+                        [$activityId, $subactivityId, $groupId] = $this->fetchMembership($member, $membership);
+                    } catch (RightException $e) {
+                        continue;
                     }
-                    $group = Group::where('name', $membership['entries_gruppierung'])->first();
-                    if (!$group) {
-                        preg_match('/(.*?) ([0-9]+)$/', $membership['entries_gruppierung'], $groupMatches);
-                        [$groupAll, $groupName, $groupId] = $groupMatches;
-                        $group = Group::create(['name' => $groupName, 'nami_id' => $groupId]);
-                    }
-                    if ($membership['entries_untergliederung'] === '') {
-                        $subactivityId = null;
-                    } else if (!Subactivity::where('name', $membership['entries_untergliederung'])->exists()) {
-                        try {
-                            $singleMembership = $this->api->membership($member->id, $membership['id']);
-                        } catch (RightException $e) {
-                            continue;
-                        }
-                        app(ActivityCreator::class)->createFor($this->api, $singleMembership['gruppierungId']);
-                        $subactivity = Subactivity::where('nami_id', $singleMembership['untergliederungId'])->firstOrFail();
-                        $subactivityId = $subactivity->id;
-                        $group = Group::firstOrCreate(['nami_id' => $singleMembership['gruppierungId']], [
-                            'nami_id' => $singleMembership['gruppierungId'],
-                            'name' => $singleMembership['gruppierung'],
-                        ]);
-                    } else {
-                        $subactivityId = Subactivity::where('name', $membership['entries_untergliederung'])->first()->id;
-                    }
-                    $activity = Activity::where('nami_id', (int) $activityMatches[1])->first();
-                    if (!$activity) {
-                        try {
-                            $singleMembership = $this->api->membership($member->id, $membership['id']);
-                        } catch (RightException $e) {
-                            continue;
-                        }
-                        app(ActivityCreator::class)->createFor($this->api, $singleMembership['gruppierungId']);
-                        $activity = Activity::where('nami_id', $singleMembership['taetigkeitId'])->first();
-                        $group = Group::firstOrCreate(['nami_id' => $singleMembership['gruppierungId']], [
-                            'nami_id' => $singleMembership['gruppierungId'],
-                            'name' => $singleMembership['gruppierung'],
-                        ]);
+                    if (is_null($activityId)) {
+                        continue;
                     }
                     $m->memberships()->create([
                         'nami_id' => $membership['id'],
-                        'created_at' => $membership['entries_aktivVon'],
-                        'group_id' => $group->id,
-                        'activity_id' => $activity->id,
+                        'from' => $membership['entries_aktivVon'],
+                        'group_id' => $groupId,
+                        'activity_id' => $activityId,
                         'subactivity_id' => $subactivityId,
                     ]);
                 }
@@ -145,4 +109,54 @@ class InitializeMembers {
             }
         });
     }
+
+    private function fetchMembership($member, $membership) {
+        if ($this->shouldSyncMembership($membership)) {
+            $singleMembership = $this->api->membership($member->id, $membership['id']);
+            app(ActivityCreator::class)->createFor($this->api, $singleMembership['gruppierungId']);
+            $group = Group::firstOrCreate(['nami_id' => $singleMembership['gruppierungId']], [
+                'nami_id' => $singleMembership['gruppierungId'],
+                'name' => $singleMembership['gruppierung'],
+            ]);
+            try {
+                $activityId = Activity::where('nami_id', $singleMembership['taetigkeitId'])->firstOrFail()->id;
+                $subactivityId = $singleMembership['untergliederungId']
+                    ? Subactivity::where('nami_id', $singleMembership['untergliederungId'])->firstOrFail()->id
+                    : null;
+                return [$activityId, $subactivityId, $group->id];
+            } catch (ModelNotFoundException $e) {
+                return [null, null, null];
+            }
+        }
+
+        if ($membership['entries_untergliederung'] === '') {
+            $subactivityId = null;
+        } else {
+            $subactivityId = Subactivity::where('name', $membership['entries_untergliederung'])->firstOrFail()->id;
+        }
+        preg_match('/\(([0-9]+)\)$/', $membership['entries_taetigkeit'], $activityMatches);
+        $activityId = Activity::where('nami_id', $activityMatches[1])->firstOrFail()->id;
+        $groupId = Group::where('name', $membership['entries_gruppierung'])->firstOrFail()->id;
+
+        return [$activityId, $subactivityId, $groupId];
+    }
+
+    private function shouldSyncMembership($membership) {
+        if (!Group::where('name', $membership['entries_gruppierung'])->exists()) {
+            return true;
+        }
+        if (preg_match('/\(([0-9]+)\)/', $membership['entries_taetigkeit'], $activityMatches) !== 1) {
+            throw new NamiException("ID in taetigkeit string not found: {$membership['entries_taetigkeit']}");
+        }
+
+        if (!Activity::where('nami_id', (int) $activityMatches[1])->exists()) {
+            return true;
+        }
+
+        if ($membership['entries_untergliederung'] === '') {
+            return false;
+        }
+
+        return !Subactivity::where('name', $membership['entries_untergliederung'])->exists();
+    }
 }
diff --git a/app/Member/Membership.php b/app/Member/Membership.php
index fb3d6af2..c7af2608 100644
--- a/app/Member/Membership.php
+++ b/app/Member/Membership.php
@@ -12,7 +12,7 @@ class Membership extends Model
 {
     use HasFactory;
 
-    public $fillable = ['subactivity_id', 'activity_id', 'group_id', 'member_id', 'nami_id', 'created_at'];
+    public $fillable = ['subactivity_id', 'activity_id', 'group_id', 'member_id', 'nami_id', 'from'];
 
     public function activity(): BelongsTo
     {
diff --git a/database/migrations/2018_01_18_205354_create_memberships_table.php b/database/migrations/2018_01_18_205354_create_memberships_table.php
index 9f0848b7..577ed091 100644
--- a/database/migrations/2018_01_18_205354_create_memberships_table.php
+++ b/database/migrations/2018_01_18_205354_create_memberships_table.php
@@ -1,8 +1,8 @@
 <?php
 
-use Illuminate\Support\Facades\Schema;
-use Illuminate\Database\Schema\Blueprint;
 use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
 
 class CreateMembershipsTable extends Migration
 {
@@ -19,6 +19,7 @@ class CreateMembershipsTable extends Migration
             $table->integer('group_id')->nullable();
             $table->integer('member_id');
             $table->integer('nami_id')->nullable();
+            $table->datetime('from');
             $table->timestamps();
             $table->unique(['activity_id', 'group_id', 'member_id', 'nami_id']);
         });
diff --git a/tests/Feature/Initialize/InitializeTest.php b/tests/Feature/Initialize/InitializeTest.php
index f16f8f42..78e73d9c 100644
--- a/tests/Feature/Initialize/InitializeTest.php
+++ b/tests/Feature/Initialize/InitializeTest.php
@@ -164,6 +164,49 @@ class InitializeTest extends TestCase
 
     public function membershipDataProvider() {
         return [
+            'dont_fetch_activity_from_group' => [
+                [
+                    'gruppierung' => '::newgroup:: 22',
+                    'id' => 1077,
+                    'taetigkeit' => '::newtaetigkeit:: (9001)',
+                ],
+                function($db) {
+                    $db->assertDatabaseCount('memberships', 0);
+                },
+                function($backend) {
+                    return $backend->fakeSingleMembership(116, 1077, [
+                        'aktivVon' => '2021-08-22 00:00:00',
+                        'aktivBis' => '',
+                        'gruppierungId' => 9056,
+                        'gruppierung' => '::newgroup::',
+                        'id' => 1077,
+                        'taetigkeit' => '::newtaetigkeit::',
+                        'taetigkeitId' => 4000,
+                        'untergliederungId' => 306,
+                    ])
+                    ->fakeActivities(9056, []);
+                }
+            ],
+            'normal' => [
+                [
+                    'aktivVon' => '2021-08-22 00:00:00',
+                    'aktivBis' => '',
+                    'gruppierung' => '::group::',
+                    'id' => 1077,
+                    'taetigkeit' => '€ leiter (305)',
+                    'untergliederung' => 'wö',
+                ],
+                function($db) {
+                    $db->assertDatabaseHas('memberships', [
+                        'member_id' => Member::where('firstname', '::firstname::')->firstOrFail()->id,
+                        'activity_id' => Activity::where('nami_id', 305)->firstOrFail()->id,
+                        'subactivity_id' => Subactivity::where('nami_id', 306)->firstOrFail()->id,
+                        'nami_id' => 1077,
+                        'from' => '2021-08-22 00:00:00',
+                        'group_id' => Group::where('name', '::group::')->firstOrFail()->id,
+                    ]);
+                },
+            ],
             'fetch_subactivity_from_group' => [
                 [
                     'gruppierung' => '::newgroup:: 22',
@@ -240,26 +283,6 @@ class InitializeTest extends TestCase
                     ]);
                 }
             ],
-            'normal' => [
-                [
-                    'aktivVon' => '2021-08-22 00:00:00',
-                    'aktivBis' => '',
-                    'gruppierung' => '::group::',
-                    'id' => 1077,
-                    'taetigkeit' => '€ leiter (305)',
-                    'untergliederung' => 'wö',
-                ],
-                function($db) {
-                    $db->assertDatabaseHas('memberships', [
-                        'member_id' => Member::where('firstname', '::firstname::')->firstOrFail()->id,
-                        'activity_id' => Activity::where('nami_id', 305)->firstOrFail()->id,
-                        'subactivity_id' => Subactivity::where('nami_id', 306)->firstOrFail()->id,
-                        'nami_id' => 1077,
-                        'created_at' => '2021-08-22 00:00:00',
-                        'group_id' => Group::where('name', '::group::')->firstOrFail()->id,
-                    ]);
-                },
-            ],
             'new_group' => [
                 [
                     'gruppierung' => '::new group:: 5555',
@@ -267,6 +290,22 @@ class InitializeTest extends TestCase
                 function($db) {
                     $db->assertDatabaseHas('groups', ['name' => '::new group::', 'nami_id' => 5555]);
                 },
+                function($backend) {
+                    return $backend->fakeSingleMembership(116, 1077, [
+                        'aktivVon' => '2021-08-22 00:00:00',
+                        'aktivBis' => '',
+                        'gruppierungId' => 5555,
+                        'gruppierung' => '::new group::',
+                        'id' => 1077,
+                        'taetigkeitId' => 305,
+                        'untergliederungId' => 306,
+                    ])
+                    ->fakeActivities(5555, [['name' => 'mitglied', 'id' => 310]])
+                    ->fakeSubactivities([
+                        310 => [['name' => 'wö', 'id' => 306]]
+                    ]);
+                                    
+                }
             ],
             'no_subactivity' => [
                 [
@@ -276,12 +315,14 @@ class InitializeTest extends TestCase
                     $db->assertDatabaseHas('memberships', ['subactivity_id' => null]);
                 },
             ],
-            'no_wrong_dates' => [
+            'wrong_dates' => [
                 [
                     'aktivVon' => '1014-04-01 00:00:00',
                 ],
                 function($db) {
-                    $db->assertDatabaseCount('memberships', 0);
+                    $db->assertDatabaseHas('memberships', [
+                        'from' => '1014-04-01 00:00:00',
+                    ]);
                 },
             ],
             'not_inactive' => [