Sfoglia il codice sorgente

会员绑定合营上级改用代理账号

doge 21 ore fa
parent
commit
525a30cbb5

+ 10 - 3
app/Http/Controllers/admin/User.php

@@ -649,7 +649,7 @@ class User extends Controller
     }
     }
 
 
     /**
     /**
-     * 给无上级的会员补绑上级:type=agent 绑合营代理(superior_id 为代理 ID),type=member 绑上级会员(superior_id 为会员 ID)。
+     * 给无上级的会员补绑上级。合营代理填 agent_username,会员填 superior_id。
      */
      */
     function bindSuperior(\App\Services\MemberSuperiorService $service)
     function bindSuperior(\App\Services\MemberSuperiorService $service)
     {
     {
@@ -657,9 +657,16 @@ class User extends Controller
             $params = request()->validate([
             $params = request()->validate([
                 'member_id' => ['required', 'string', 'min:1'],
                 'member_id' => ['required', 'string', 'min:1'],
                 'type' => ['required', 'string', 'in:agent,member'],
                 'type' => ['required', 'string', 'in:agent,member'],
-                'superior_id' => ['required', 'string', 'min:1', 'max:64'],
+                'agent_username' => ['required_if:type,agent', 'missing_unless:type,agent', 'string', 'max:64'],
+                'superior_id' => ['required_if:type,member', 'missing_unless:type,member', 'string', 'max:64'],
+            ], [
+                'agent_username.required_if' => '请输入合营代理账号',
+                'agent_username.missing_unless' => '绑定会员时请填写上级会员 ID',
+                'superior_id.required_if' => '请输入上级会员 ID',
+                'superior_id.missing_unless' => '绑定合营代理时请填写代理账号',
             ]);
             ]);
-            $result = $service->bind($params['member_id'], $params['type'], trim($params['superior_id']));
+            $target = $params['agent_username'] ?? $params['superior_id'];
+            $result = $service->bind($params['member_id'], $params['type'], trim($target));
         } catch (ValidationException $e) {
         } catch (ValidationException $e) {
             return $this->error(HttpStatus::CUSTOM_ERROR, $e->validator->errors()->first());
             return $this->error(HttpStatus::CUSTOM_ERROR, $e->validator->errors()->first());
         } catch (Exception $e) {
         } catch (Exception $e) {

+ 5 - 5
app/Services/MemberSuperiorService.php

@@ -10,7 +10,7 @@ use Illuminate\Support\Facades\Schema;
 
 
 /**
 /**
  * 后台会员列表:给没有上级(无合营代理、无邀请人)的会员补绑上级。
  * 后台会员列表:给没有上级(无合营代理、无邀请人)的会员补绑上级。
- * type=agent:superior_id 为代理 ID(agents.id),写 users.agent_id;
+ * type=agent:agent_username 为代理账号(agents.username),写 users.agent_id;
  * type=member:superior_id 为上级会员的会员 ID(users.member_id),写 users.agent_user_code 并挂到分享关系树。
  * type=member:superior_id 为上级会员的会员 ID(users.member_id),写 users.agent_user_code 并挂到分享关系树。
  * 上级只有两种:会员邀请码,或合营代理(绑定域名注册)。入股代理不发展会员,不能当作上级。
  * 上级只有两种:会员邀请码,或合营代理(绑定域名注册)。入股代理不发展会员,不能当作上级。
  * 已有合营代理、能对上的邀请人,或分享关系树里已有上级的会员不能改绑。
  * 已有合营代理、能对上的邀请人,或分享关系树里已有上级的会员不能改绑。
@@ -20,9 +20,9 @@ class MemberSuperiorService
     public const TYPE_AGENT = 'agent';
     public const TYPE_AGENT = 'agent';
     public const TYPE_MEMBER = 'member';
     public const TYPE_MEMBER = 'member';
 
 
-    public function bind(string $memberId, string $type, string $superiorId): array
+    public function bind(string $memberId, string $type, string $target): array
     {
     {
-        return DB::transaction(function () use ($memberId, $type, $superiorId) {
+        return DB::transaction(function () use ($memberId, $type, $target) {
             // 与注册、分享关系绑定同一把锁,先锁关系再锁会员,避免死锁和并发重复绑定
             // 与注册、分享关系绑定同一把锁,先锁关系再锁会员,避免死锁和并发重复绑定
             ShareRelations::lock();
             ShareRelations::lock();
             $user = User::query()->where('member_id', $memberId)->lockForUpdate()->first();
             $user = User::query()->where('member_id', $memberId)->lockForUpdate()->first();
@@ -31,7 +31,7 @@ class MemberSuperiorService
             if ($this->hasSuperior($user)) throw new \RuntimeException('会员已有上级,不能修改');
             if ($this->hasSuperior($user)) throw new \RuntimeException('会员已有上级,不能修改');
 
 
             if ($type === self::TYPE_AGENT) {
             if ($type === self::TYPE_AGENT) {
-                $agent = ctype_digit($superiorId) ? Agent::query()->lockForUpdate()->find((int) $superiorId) : null;
+                $agent = Agent::query()->where('username', $target)->lockForUpdate()->first();
                 if (!$agent) throw new \RuntimeException('代理不存在');
                 if (!$agent) throw new \RuntimeException('代理不存在');
                 if (!$agent->isJoint()) throw new \RuntimeException('只能绑定合营代理');
                 if (!$agent->isJoint()) throw new \RuntimeException('只能绑定合营代理');
                 if ((int) $agent->status !== Agent::STATUS_ENABLED) throw new \RuntimeException('代理已禁用');
                 if ((int) $agent->status !== Agent::STATUS_ENABLED) throw new \RuntimeException('代理已禁用');
@@ -42,7 +42,7 @@ class MemberSuperiorService
             }
             }
 
 
             if ($type !== self::TYPE_MEMBER) throw new \RuntimeException('绑定类型错误');
             if ($type !== self::TYPE_MEMBER) throw new \RuntimeException('绑定类型错误');
-            $parent = User::query()->where('member_id', $superiorId)->first();
+            $parent = User::query()->where('member_id', $target)->first();
             if (!$parent) throw new \RuntimeException('上级会员不存在');
             if (!$parent) throw new \RuntimeException('上级会员不存在');
             if ((int) $parent->id === (int) $user->id) throw new \RuntimeException('不能绑定自己');
             if ((int) $parent->id === (int) $user->id) throw new \RuntimeException('不能绑定自己');
             if ((int) $parent->from === 2) throw new \RuntimeException('试玩会员不能作为上级');
             if ((int) $parent->from === 2) throw new \RuntimeException('试玩会员不能作为上级');

+ 2 - 1
docs/前端交付/README.md

@@ -10,7 +10,8 @@
 
 
 - [整站与游戏维护子类-总后台前端修改单](整站与游戏维护子类-总后台前端修改单.md):维护可以细到子类(三方平台、F1 彩种、F1 体育项);列表为树形(已包含《维护列表按层级返回》的内容);子类新增「支持内嵌」开关 `embeddable`;新增菜单「F1体育列表」(`GET /admin/config/sportList`,用 `setField` 的 `sport_list` 保存)。
 - [整站与游戏维护子类-总后台前端修改单](整站与游戏维护子类-总后台前端修改单.md):维护可以细到子类(三方平台、F1 彩种、F1 体育项);列表为树形(已包含《维护列表按层级返回》的内容);子类新增「支持内嵌」开关 `embeddable`;新增菜单「F1体育列表」(`GET /admin/config/sportList`,用 `setField` 的 `sport_list` 保存)。
 - [游戏支持内嵌-会员前台修改单](游戏支持内嵌-会员前台修改单.md):三方平台 / 游戏、F1 彩票、F1 体育列表项新增 `embeddable`(是否支持内嵌)。
 - [游戏支持内嵌-会员前台修改单](游戏支持内嵌-会员前台修改单.md):三方平台 / 游戏、F1 彩票、F1 体育列表项新增 `embeddable`(是否支持内嵌)。
-- [会员绑定上级-前端修改单](会员绑定上级-前端修改单.md):注册时代理域名和会员邀请码同时存在,**以会员邀请码为主**,会员前台不用改。总后台会员列表新增 `can_bind_superior`,无上级的会员可以通过 `POST /admin/user/bindSuperior` 绑定合营代理(代理 ID)或上级会员(会员 ID),绑定后不能修改。
+- [会员绑定上级-前端修改单](会员绑定上级-前端修改单.md):注册时代理域名和会员邀请码同时存在,**以会员邀请码为主**,会员前台不用改。总后台会员列表新增 `can_bind_superior`,无上级的会员可以通过 `POST /admin/user/bindSuperior` 绑定合营代理(代理账号)或上级会员(会员 ID),绑定后不能修改。
+- [会员绑定上级-目标字段调整](会员绑定上级-目标字段调整.md):合营代理提交 `agent_username`,会员提交 `superior_id`。
 
 
 ## 代理审核实时推送(2026-11-10)
 ## 代理审核实时推送(2026-11-10)
 
 

+ 10 - 8
docs/前端交付/会员绑定上级-前端修改单.md

@@ -27,7 +27,7 @@
 
 
 ## 二、总后台会员列表:给无上级的会员绑定上级
 ## 二、总后台会员列表:给无上级的会员绑定上级
 
 
-会员列表里 `can_bind_superior` 为 `true` 的会员,可以由管理员补绑一个上级。可以绑**合营代理**(填代理 ID),也可以绑**会员**(填会员 ID)。已经有上级的会员不能改绑。
+会员列表里 `can_bind_superior` 为 `true` 的会员,可以由管理员补绑一个上级。可以绑**合营代理**(填代理账号),也可以绑**会员**(填会员 ID)。已经有上级的会员不能改绑。
 
 
 ### 1. 列表新增字段
 ### 1. 列表新增字段
 
 
@@ -47,12 +47,15 @@
 |---|---|---|---|
 |---|---|---|---|
 | `member_id` | string | 是 | 要绑定上级的会员,也就是列表行的 `member_id` |
 | `member_id` | string | 是 | 要绑定上级的会员,也就是列表行的 `member_id` |
 | `type` | string | 是 | `agent` 绑合营代理;`member` 绑会员 |
 | `type` | string | 是 | `agent` 绑合营代理;`member` 绑会员 |
-| `superior_id` | string | 是 | `type=agent` 时填**代理 ID**(代理列表的 `id`);`type=member` 时填上级的**会员 ID**(会员列表的 `member_id`) |
+| `agent_username` | string | `type=agent` 时必填 | 合营代理账号,取代理列表的 `username` |
+| `superior_id` | string | `type=member` 时必填 | 上级会员 ID,取会员列表的 `member_id` |
+
+每次提交只带所选类型的目标字段。
 
 
 请求示例:
 请求示例:
 
 
 ```json
 ```json
-{"member_id":"92385294","type":"agent","superior_id":"6"}
+{"member_id":"92385294","type":"agent","agent_username":"agent06"}
 ```
 ```
 
 
 ```json
 ```json
@@ -78,7 +81,7 @@
 | 会员不存在 | `member_id` 有误 |
 | 会员不存在 | `member_id` 有误 |
 | 会员已有上级,不能修改 | 会员已经有代理或邀请人(例如列表数据过时了) |
 | 会员已有上级,不能修改 | 会员已经有代理或邀请人(例如列表数据过时了) |
 | 试玩会员不能绑定上级 | 要绑定的是试玩会员 |
 | 试玩会员不能绑定上级 | 要绑定的是试玩会员 |
-| 代理不存在 / 代理已禁用 / 只能绑定合营代理 | 代理 ID 有误、代理已停用,或填了入股代理 |
+| 代理不存在 / 代理已禁用 / 只能绑定合营代理 | 代理账号有误、代理已停用,或填了入股代理 |
 | 上级会员不存在 | 会员 ID 有误 |
 | 上级会员不存在 | 会员 ID 有误 |
 | 不能绑定自己 | 上级填了会员自己 |
 | 不能绑定自己 | 上级填了会员自己 |
 | 不能绑定自己或自己的下级 | 上级是这个会员的下级,绑定后会形成循环 |
 | 不能绑定自己或自己的下级 | 上级是这个会员的下级,绑定后会形成循环 |
@@ -90,16 +93,15 @@
 1. 会员列表操作列:`can_bind_superior` 为 `true` 时显示「绑定上级」按钮,否则不显示。
 1. 会员列表操作列:`can_bind_superior` 为 `true` 时显示「绑定上级」按钮,否则不显示。
 2. 点击后打开弹窗:
 2. 点击后打开弹窗:
    - **上级类型**:单选「合营代理」(`agent`)/「会员」(`member`),默认「合营代理」。
    - **上级类型**:单选「合营代理」(`agent`)/「会员」(`member`),默认「合营代理」。
-   - **上级 ID**:输入框。选「合营代理」时提示「请输入代理 ID」,选「会员」时提示「请输入会员 ID」。
+   - 选「合营代理」时显示「代理账号」,选「会员」时显示「上级会员 ID」。切换类型时清空输入框。
    - 会员信息只读显示(会员 ID、账号),方便确认。
    - 会员信息只读显示(会员 ID、账号),方便确认。
    - 确认前提示:**绑定后不能修改**。
    - 确认前提示:**绑定后不能修改**。
 3. 提交 `POST /admin/user/bindSuperior`。成功后提示「绑定成功」并刷新当前行或列表,这时「上级」列会显示「合营:agent06」或「邀请人:inviter01」,按钮也会消失;失败就提示 `msg`。
 3. 提交 `POST /admin/user/bindSuperior`。成功后提示「绑定成功」并刷新当前行或列表,这时「上级」列会显示「合营:agent06」或「邀请人:inviter01」,按钮也会消失;失败就提示 `msg`。
-4. (可选)上级类型为「合营代理」时,ID 输入框可以改成代理下拉,选项来自代理列表,提交的仍然是代理 `id`。
 
 
 ### 验收
 ### 验收
 
 
 1. 无上级的会员有「绑定上级」按钮;已有代理、已有邀请人的会员和试玩会员都没有这个按钮。
 1. 无上级的会员有「绑定上级」按钮;已有代理、已有邀请人的会员和试玩会员都没有这个按钮。
-2. 填合营代理 ID 绑定后,「上级」列显示「合营:代理账号」,这个会员也出现在该代理后台的「所有会员」里。填入股代理 ID 会提示「只能绑定合营代理」。
+2. 填合营代理账号绑定后,「上级」列显示「合营:代理账号」,这个会员也出现在该代理后台的「所有会员」里。填入股代理账号会提示「只能绑定合营代理」。
 3. 填会员 ID 绑定后,「上级」列显示「邀请人:账号」,上级会员的推广下级里能看到这个会员。
 3. 填会员 ID 绑定后,「上级」列显示「邀请人:账号」,上级会员的推广下级里能看到这个会员。
-4. 再次绑定,或者填自己、自己的下级、不存在的 ID、已停用的代理时,都会提示对应错误,数据不变。
+4. 再次绑定,或者填自己、自己的下级、不存在的会员 ID 或代理账号、已停用的代理时,都会提示对应错误,数据不变。
 5. 从代理域名进入并填写了会员邀请码注册的会员,「上级」显示「邀请人:账号」,不显示代理。
 5. 从代理域名进入并填写了会员邀请码注册的会员,「上级」显示「邀请人:账号」,不显示代理。

+ 18 - 0
docs/前端交付/会员绑定上级-目标字段调整.md

@@ -0,0 +1,18 @@
+# 会员绑定上级目标字段调整
+
+`POST /admin/user/bindSuperior` 按上级类型接收不同的目标字段。
+
+| 上级类型 | 输入框 | 提交字段 |
+|---|---|---|
+| 合营代理 `agent` | 代理账号,取代理列表的 `username` | `agent_username`(字符串) |
+| 会员 `member` | 上级会员 ID,取会员列表的 `member_id` | `superior_id`(字符串) |
+
+```json
+{"member_id":"92385294","type":"agent","agent_username":"agent06"}
+```
+
+```json
+{"member_id":"92385294","type":"member","superior_id":"92385001"}
+```
+
+切换类型时清空输入,只提交当前类型的目标字段。请求失败时显示接口返回的 `msg`。

+ 32 - 7
tests/Integration/AdminBindSuperiorTest.php

@@ -12,7 +12,7 @@ use Illuminate\Support\Facades\Schema;
 use PHPUnit\Framework\TestCase;
 use PHPUnit\Framework\TestCase;
 use Tests\Support\AgentTestEnvironment;
 use Tests\Support\AgentTestEnvironment;
 
 
-/** 后台会员列表:无上级的会员可补绑合营代理(代理 ID)或上级会员(会员 ID),已有上级不能改。 */
+/** 后台会员列表:无上级的会员可按账号补绑合营代理,或按会员 ID 补绑上级会员。 */
 class AdminBindSuperiorTest extends TestCase
 class AdminBindSuperiorTest extends TestCase
 {
 {
     use AgentTestEnvironment { setUp as private agentSetUp; }
     use AgentTestEnvironment { setUp as private agentSetUp; }
@@ -67,8 +67,9 @@ class AdminBindSuperiorTest extends TestCase
         $c = $this->member('1003');
         $c = $this->member('1003');
         $this->member('1004', ['from' => 2]);
         $this->member('1004', ['from' => 2]);
 
 
-        $data = $this->call(['member_id' => '1001', 'type' => 'agent', 'superior_id' => (string) $agent->id]);
+        $data = $this->call(['member_id' => '1001', 'type' => 'agent', 'agent_username' => ' ' . $agent->username . ' ']);
         $this->assertSame(0, $data['code'], (string) $data['msg']);
         $this->assertSame(0, $data['code'], (string) $data['msg']);
+        $this->assertSame($agent->id, $data['data']['agent_id']);
         $this->assertSame($agent->id, (int) DB::table('users')->where('member_id', '1001')->value('agent_id'));
         $this->assertSame($agent->id, (int) DB::table('users')->where('member_id', '1001')->value('agent_id'));
         $this->assertSame('会员已有上级,不能修改', $this->call(['member_id' => '1001', 'type' => 'member', 'superior_id' => '1002'])['msg']);
         $this->assertSame('会员已有上级,不能修改', $this->call(['member_id' => '1001', 'type' => 'member', 'superior_id' => '1002'])['msg']);
 
 
@@ -77,21 +78,21 @@ class AdminBindSuperiorTest extends TestCase
         $this->assertSame('C1002', DB::table('users')->where('id', $c)->value('agent_user_code'));
         $this->assertSame('C1002', DB::table('users')->where('id', $c)->value('agent_user_code'));
         $this->assertSame($b, (int) DB::table('share_members')->where('user_id', $c)->value('parent_user_id'));
         $this->assertSame($b, (int) DB::table('share_members')->where('user_id', $c)->value('parent_user_id'));
         $this->assertTrue(DB::table('share_tree')->where(['ancestor_user_id' => $b, 'descendant_user_id' => $c, 'depth' => 1])->exists());
         $this->assertTrue(DB::table('share_tree')->where(['ancestor_user_id' => $b, 'descendant_user_id' => $c, 'depth' => 1])->exists());
-        $this->assertSame('会员已有上级,不能修改', $this->call(['member_id' => '1003', 'type' => 'agent', 'superior_id' => (string) $agent->id])['msg']);
+        $this->assertSame('会员已有上级,不能修改', $this->call(['member_id' => '1003', 'type' => 'agent', 'agent_username' => $agent->username])['msg']);
 
 
         $this->assertSame('不能绑定自己或自己的下级', $this->call(['member_id' => '1002', 'type' => 'member', 'superior_id' => '1003'])['msg'], 'no cycle');
         $this->assertSame('不能绑定自己或自己的下级', $this->call(['member_id' => '1002', 'type' => 'member', 'superior_id' => '1003'])['msg'], 'no cycle');
         $this->assertSame('不能绑定自己', $this->call(['member_id' => '1002', 'type' => 'member', 'superior_id' => '1002'])['msg']);
         $this->assertSame('不能绑定自己', $this->call(['member_id' => '1002', 'type' => 'member', 'superior_id' => '1002'])['msg']);
         $this->assertSame('上级会员不存在', $this->call(['member_id' => '1002', 'type' => 'member', 'superior_id' => '9999'])['msg']);
         $this->assertSame('上级会员不存在', $this->call(['member_id' => '1002', 'type' => 'member', 'superior_id' => '9999'])['msg']);
-        $this->assertSame('代理不存在', $this->call(['member_id' => '1002', 'type' => 'agent', 'superior_id' => '9999'])['msg']);
+        $this->assertSame('代理不存在', $this->call(['member_id' => '1002', 'type' => 'agent', 'agent_username' => 'unknown-agent'])['msg']);
         $this->assertSame('试玩会员不能作为上级', $this->call(['member_id' => '1002', 'type' => 'member', 'superior_id' => '1004'])['msg']);
         $this->assertSame('试玩会员不能作为上级', $this->call(['member_id' => '1002', 'type' => 'member', 'superior_id' => '1004'])['msg']);
         $this->assertSame('试玩会员不能绑定上级', $this->call(['member_id' => '1004', 'type' => 'member', 'superior_id' => '1002'])['msg']);
         $this->assertSame('试玩会员不能绑定上级', $this->call(['member_id' => '1004', 'type' => 'member', 'superior_id' => '1002'])['msg']);
         $this->assertNotSame(0, $this->call(['member_id' => '1002', 'type' => 'other', 'superior_id' => '1'])['code']);
         $this->assertNotSame(0, $this->call(['member_id' => '1002', 'type' => 'other', 'superior_id' => '1'])['code']);
 
 
         $equity = $this->agent(Agent::TYPE_EQUITY);
         $equity = $this->agent(Agent::TYPE_EQUITY);
-        $this->assertSame('只能绑定合营代理', $this->call(['member_id' => '1002', 'type' => 'agent', 'superior_id' => (string) $equity->id])['msg']);
+        $this->assertSame('只能绑定合营代理', $this->call(['member_id' => '1002', 'type' => 'agent', 'agent_username' => $equity->username])['msg']);
         $this->member('1005', ['agent_id' => $equity->id]);
         $this->member('1005', ['agent_id' => $equity->id]);
         $this->member('1006', ['agent_id' => $equity->id, 'agent_user_code' => 'GONE']);
         $this->member('1006', ['agent_id' => $equity->id, 'agent_user_code' => 'GONE']);
-        $data = $this->call(['member_id' => '1005', 'type' => 'agent', 'superior_id' => (string) $agent->id]);
+        $data = $this->call(['member_id' => '1005', 'type' => 'agent', 'agent_username' => $agent->username]);
         $this->assertSame(0, $data['code'], (string) $data['msg']);
         $this->assertSame(0, $data['code'], (string) $data['msg']);
         $this->assertSame($agent->id, (int) DB::table('users')->where('member_id', '1005')->value('agent_id'));
         $this->assertSame($agent->id, (int) DB::table('users')->where('member_id', '1005')->value('agent_id'));
         $data = $this->call(['member_id' => '1006', 'type' => 'member', 'superior_id' => '1002']);
         $data = $this->call(['member_id' => '1006', 'type' => 'member', 'superior_id' => '1002']);
@@ -100,7 +101,31 @@ class AdminBindSuperiorTest extends TestCase
         $this->assertNull(DB::table('users')->where('member_id', '1006')->value('agent_id'));
         $this->assertNull(DB::table('users')->where('member_id', '1006')->value('agent_id'));
 
 
         Agent::query()->whereKey($agent->id)->update(['status' => Agent::STATUS_DISABLED]);
         Agent::query()->whereKey($agent->id)->update(['status' => Agent::STATUS_DISABLED]);
-        $this->assertSame('代理已禁用', $this->call(['member_id' => '1002', 'type' => 'agent', 'superior_id' => (string) $agent->id])['msg']);
+        $this->assertSame('代理已禁用', $this->call(['member_id' => '1002', 'type' => 'agent', 'agent_username' => $agent->username])['msg']);
         $this->assertNull(DB::table('users')->where('id', $b)->value('agent_id'));
         $this->assertNull(DB::table('users')->where('id', $b)->value('agent_id'));
     }
     }
+
+    public function test_rejects_mixed_target_fields_and_never_falls_back_to_other_identifiers(): void
+    {
+        $agent = $this->agent();
+        $member = $this->member('1001');
+        $this->member('1002', ['account' => 'inviter-account']);
+
+        foreach ([
+            ['type' => 'agent', 'superior_id' => (string) $agent->id],
+            ['type' => 'agent', 'agent_username' => $agent->username, 'superior_id' => '1002'],
+            ['type' => 'member', 'agent_username' => $agent->username],
+            ['type' => 'member', 'superior_id' => '1002', 'agent_username' => $agent->username],
+        ] as $params) {
+            $this->assertNotSame(0, $this->call($params + ['member_id' => '1001'])['code']);
+        }
+        $this->assertSame('代理不存在', $this->call([
+            'member_id' => '1001', 'type' => 'agent', 'agent_username' => (string) $agent->id,
+        ])['msg']);
+        $this->assertSame('上级会员不存在', $this->call([
+            'member_id' => '1001', 'type' => 'member', 'superior_id' => 'inviter-account',
+        ])['msg']);
+        $this->assertNull(DB::table('users')->where('id', $member)->value('agent_id'));
+        $this->assertNull(DB::table('share_members')->where('user_id', $member)->value('parent_user_id'));
+    }
 }
 }