From ea57e1c55221f92f652edbf85556fa49ef774ace Mon Sep 17 00:00:00 2001
From: philipp lang <philipp@aweos.de>
Date: Mon, 6 Feb 2023 00:07:37 +0100
Subject: [PATCH] Fix member update

---
 src/Api.php                      |  58 +++++++++++-------
 src/Fakes/MemberFake.php         |  38 ++++++------
 tests/Unit/Api/PutMemberTest.php | 100 +++++++++++++++++++++++++++++++
 tests/Unit/PushMemberTest.php    |  50 ----------------
 4 files changed, 154 insertions(+), 92 deletions(-)
 create mode 100644 tests/Unit/Api/PutMemberTest.php
 delete mode 100644 tests/Unit/PushMemberTest.php

diff --git a/src/Api.php b/src/Api.php
index 5bba99f..cb14c9f 100644
--- a/src/Api.php
+++ b/src/Api.php
@@ -110,29 +110,33 @@ class Api
         );
     }
 
-    public function putMember(Member $member): int
+    public function putMember(Member $member, ?int $firstActivity = null, ?int $firstSubactivity = null): int
     {
         $this->assertLoggedIn();
         if ($member->id) {
-            $existing = $this->member($member->groupId, $member->id);
+            $existing = $this->rawMember($member->groupId, $member->id);
             $payload = array_merge($existing, $member->toNami());
             $payload['kontoverbindung'] = json_encode(data_get($payload, 'kontoverbindung', []));
-            $url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$member->group_id.'/'.$member->id;
+            $url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$member->groupId.'/'.$member->id;
             $response = $this->http()->put($url, $payload);
             if (true !== data_get($response->json(), 'success')) {
                 $this->exception('Update failed', $url, $response->json(), $member->toNami());
             }
+
+            return $response->json()['data']['id'];
         } else {
             $url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$member->groupId;
-            $response = $this->http()->post($url, $member->toNami());
+            $response = $this->http()->post($url, [
+                ...$member->toNami(),
+                'ersteTaetigkeitId' => $firstActivity,
+                'ersteUntergliederungId' => $firstSubactivity,
+            ]);
             if (true !== data_get($response->json(), 'success')) {
                 $this->exception('Update failed', $url, $response->json(), $member->toNami());
             }
 
             return $response->json()['data'];
         }
-
-        return $response->json()['data'];
     }
 
     public function putMembership(int $memberId, Membership $data): int
@@ -290,23 +294,7 @@ class Api
 
     public function member(int $groupId, int $memberId): Member
     {
-        $this->assertLoggedIn();
-        $url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/'.$memberId;
-        $response = $this->http()->get($url);
-
-        if (false === $response->json()['success'] && Str::startsWith($response['message'], 'Access denied')) {
-            return $this->singleMemberFallback($groupId, $memberId);
-        }
-
-        if (false === $response->json()['success'] && Str::startsWith($response['message'], 'Sicherheitsverletzung: Zugriff')) {
-            return $this->singleMemberFallback($groupId, $memberId);
-        }
-
-        if (true !== $response->json()['success']) {
-            $this->exception('Fetching member failed', $url, $response->json());
-        }
-
-        return Member::from($response->json()['data']);
+        return Member::from($this->rawMember($groupId, $memberId));
     }
 
     public function hasGroup(int $groupId): bool
@@ -504,4 +492,28 @@ class Api
             $this->exception($error, $url, $response->json());
         }
     }
+
+    /**
+     * @return array<string, mixed>
+     */
+    private function rawMember(int $groupId, int $memberId): array
+    {
+        $this->assertLoggedIn();
+        $url = $this->url.'/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/'.$memberId;
+        $response = $this->http()->get($url);
+
+        if (false === $response->json()['success'] && Str::startsWith($response['message'], 'Access denied')) {
+            return $this->singleMemberFallback($groupId, $memberId);
+        }
+
+        if (false === $response->json()['success'] && Str::startsWith($response['message'], 'Sicherheitsverletzung: Zugriff')) {
+            return $this->singleMemberFallback($groupId, $memberId);
+        }
+
+        if (true !== $response->json()['success']) {
+            $this->exception('Fetching member failed', $url, $response->json());
+        }
+
+        return $response->json()['data'];
+    }
 }
diff --git a/src/Fakes/MemberFake.php b/src/Fakes/MemberFake.php
index 431f36d..c5990a8 100644
--- a/src/Fakes/MemberFake.php
+++ b/src/Fakes/MemberFake.php
@@ -60,24 +60,6 @@ class MemberFake extends Fake
         return $this;
     }
 
-    /**
-     * @param array<string, string|int|null> $data
-     */
-    public function updates(int $groupId, int $memberId, array $data): self
-    {
-        Http::fake(function ($request) use ($groupId, $memberId, $data) {
-            $url = 'https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/'.$memberId;
-            if ($request->url() === $url && 'PUT' === $request->method()) {
-                return $this->dataResponse([
-                    'id' => $memberId,
-                    ...$data,
-                ]);
-            }
-        });
-
-        return $this;
-    }
-
     public function deletes(int $memberId, Carbon $date): void
     {
         Http::fake(function ($request) use ($memberId, $date) {
@@ -103,6 +85,24 @@ class MemberFake extends Fake
         });
     }
 
+    /**
+     * @param array<string, string|int|null> $data
+     */
+    public function updatesSuccessfully(int $groupId, int $memberId, array $data = []): self
+    {
+        Http::fake(function ($request) use ($groupId, $memberId, $data) {
+            $url = 'https://nami.dpsg.de/ica/rest/nami/mitglied/filtered-for-navigation/gruppierung/gruppierung/'.$groupId.'/'.$memberId;
+            if ($request->url() === $url && 'PUT' === $request->method()) {
+                return $this->dataResponse([
+                    'id' => $memberId,
+                    ...$data,
+                ]);
+            }
+        });
+
+        return $this;
+    }
+
     public function createsSuccessfully(int $groupId, int $memberId): self
     {
         Http::fake(function ($request) use ($memberId, $groupId) {
@@ -159,7 +159,7 @@ class MemberFake extends Fake
             $requestBody = json_decode($request->body(), true);
 
             foreach ($body as $key => $value) {
-                if (!isset($requestBody[$key])) {
+                if (!array_key_exists($key, $requestBody)) {
                     return false;
                 }
 
diff --git a/tests/Unit/Api/PutMemberTest.php b/tests/Unit/Api/PutMemberTest.php
new file mode 100644
index 0000000..fa5ca05
--- /dev/null
+++ b/tests/Unit/Api/PutMemberTest.php
@@ -0,0 +1,100 @@
+<?php
+
+namespace Zoomyboy\LaravelNami\Tests\Unit\Api;
+
+use Zoomyboy\LaravelNami\Data\Member;
+use Zoomyboy\LaravelNami\Fakes\MemberFake;
+use Zoomyboy\LaravelNami\Tests\TestCase;
+
+class PutMemberTest extends TestCase
+{
+    public function testPushASingleMember(): void
+    {
+        app(MemberFake::class)->createsSuccessfully(103, 16);
+        $member = Member::from([
+            'firstname' => 'Max',
+            'lastname' => 'Nach1',
+            'nickname' => 'spitz1',
+            'groupId' => 103,
+            'genderId' => 17,
+            'confessionId' => 33,
+            'joinedAt' => '2021-02-02 00:00:00',
+            'birthday' => '2021-02-02 00:00:00',
+            'email' => 'aa@b.de',
+            'countryId' => 78,
+            'keepdata' => false,
+            'sendNewspaper' => false,
+            'regionId' => 11,
+            'nationalityId' => 12,
+            'beitragsartId' => null,
+        ]);
+        $response = $this->login()->putMember($member, 78, 79);
+
+        $this->assertEquals(16, $response);
+
+        app(MemberFake::class)->assertCreated(103, [
+            'spitzname' => 'spitz1',
+            'vorname' => 'Max',
+            'nachname' => 'Nach1',
+            'geschlechtId' => 17,
+            'email' => 'aa@b.de',
+            'beitragsartId' => null,
+            'geburtsDatum' => '2021-02-02 00:00:00',
+            'konfessionId' => 33,
+            'landId' => 78,
+            'wiederverwendenFlag' => false,
+            'zeitschriftenversand' => false,
+            'regionId' => 11,
+            'staatsangehoerigkeitId' => 12,
+            'ersteTaetigkeitId' => 78,
+            'ersteUntergliederungId' => 79,
+        ]);
+    }
+
+    public function testUpdateAMemberWithForeignAttributes(): void
+    {
+        app(MemberFake::class)
+            ->updatesSuccessfully(103, 16)
+            ->shows(103, 16, [
+                'foreign' => 'fff',
+            ]);
+        $member = Member::from([
+            'firstname' => 'Max',
+            'lastname' => 'Nach1',
+            'nickname' => 'spitz1',
+            'groupId' => 103,
+            'genderId' => 17,
+            'confessionId' => 33,
+            'joinedAt' => '2021-02-02 00:00:00',
+            'birthday' => '2021-02-02 00:00:00',
+            'email' => 'aa@b.de',
+            'countryId' => 78,
+            'keepdata' => false,
+            'sendNewspaper' => false,
+            'regionId' => 11,
+            'nationalityId' => 12,
+            'beitragsartId' => null,
+            'id' => 16,
+        ]);
+        $response = $this->login()->putMember($member);
+
+        $this->assertEquals(16, $response);
+
+        app(MemberFake::class)->assertUpdated(103, 16, [
+            'spitzname' => 'spitz1',
+            'vorname' => 'Max',
+            'nachname' => 'Nach1',
+            'geschlechtId' => 17,
+            'email' => 'aa@b.de',
+            'beitragsartId' => null,
+            'geburtsDatum' => '2021-02-02 00:00:00',
+            'konfessionId' => 33,
+            'landId' => 78,
+            'wiederverwendenFlag' => false,
+            'zeitschriftenversand' => false,
+            'regionId' => 11,
+            'staatsangehoerigkeitId' => 12,
+            'foreign' => 'fff',
+        ]);
+    }
+}
diff --git a/tests/Unit/PushMemberTest.php b/tests/Unit/PushMemberTest.php
deleted file mode 100644
index 1e272e4..0000000
--- a/tests/Unit/PushMemberTest.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-namespace Zoomyboy\LaravelNami\Tests\Unit;
-
-use Zoomyboy\LaravelNami\Data\Member;
-use Zoomyboy\LaravelNami\Fakes\MemberFake;
-use Zoomyboy\LaravelNami\Tests\TestCase;
-
-class PushMemberTest extends TestCase
-{
-    public function testPushASingleMember(): void
-    {
-        app(MemberFake::class)->createsSuccessfully(103, 16);
-        $response = $this->login()->putMember(Member::from([
-            'firstname' => 'Max',
-            'lastname' => 'Nach1',
-            'nickname' => 'spitz1',
-            'groupId' => 103,
-            'genderId' => 17,
-            'confessionId' => 33,
-            'joinedAt' => '2021-02-02 00:00:00',
-            'birthday' => '2021-02-02 00:00:00',
-            'email' => 'aa@b.de',
-            'countryId' => 78,
-            'keepdata' => false,
-            'sendNewspaper' => false,
-            'regionId' => 11,
-            'nationalityId' => 12,
-            'beitragsartId' => null,
-        ]));
-
-        $this->assertEquals(16, $response);
-
-        app(MemberFake::class)->assertCreated(103, [
-            'spitzname' => 'spitz1',
-            'vorname' => 'Max',
-            'nachname' => 'Nach1',
-            'geschlechtId' => 17,
-            'email' => 'aa@b.de',
-            'beitragsartId' => null,
-            'geburtsDatum' => '2021-02-02 00:00:00',
-            'konfessionId' => 33,
-            'landId' => 78,
-            'wiederverwendenFlag' => false,
-            'zeitschriftenversand' => false,
-            'regionId' => 11,
-            'staatsangehoerigkeitId' => 12,
-        ]);
-    }
-}