user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail()); $this->createQuote(); $this->loginAs() ->get(route('business.pages.show', [ 'section' => 'courier-payables', 'page' => 'courier-surcharge', ])) ->assertOk() ->assertSeeText('附加费报价维护') ->assertSeeText('正式维护数据') ->assertSeeText('报价规则列表') ->assertSeeText('管理附加费类型') ->assertSeeText('类型列表') ->assertSeeText('进仓费') ->assertSeeText('新增报价规则') ->assertSeeText('结算方式') ->assertSeeText('计价标准') ->assertSeeText('生效条件') ->assertSeeText('快递归属') ->assertSeeText('自有快递') ->assertSeeText('代发仓') ->assertSeeText('对账人') ->assertSeeText('张会计') ->assertSeeText('附加费类型(可多选)') ->assertSeeText('列设置') ->assertSeeText('导出当前列') ->assertSeeText('导出全部字段') ->assertSeeText('规则编号与操作列固定显示') ->assertSee('data-column-storage-key="caiwu:table-columns:', false) ->assertSee('data-surcharge-table', false) ->assertSee('data-column-check', false) ->assertSee('data-surcharge-export-current', false) ->assertSee('data-surcharge-export-all', false) ->assertSee('data-column-reset', false) ->assertSee('name="types[]"', false) ->assertSeeInOrder(['data-column-key="courier"', 'data-column-key="scope"', 'data-column-key="reconciler"'], false) ->assertSeeText('曹县德邦') ->assertSeeText('超长费') ->assertSeeText('按尺寸/最长边') ->assertSeeText('8 元/单') ->assertSeeText('已启用') ->assertSeeText('后续结算页面将按启用中的规则计算'); } public function test_courier_surcharge_type_can_be_created_and_duplicate_is_rejected(): void { $this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail()); $this->loginAs(); $this->post(route('business.courier-surcharge.types.store'), ['name' => '偏远地区费']) ->assertRedirect(); $this->assertDatabaseHas('business_courier_surcharge_types', [ 'company_id' => company_id(), 'name' => '偏远地区费', 'status' => CourierSurchargeType::STATUS_ACTIVE, ]); $this->withExceptionHandling() ->from(route('business.pages.show', ['section' => 'courier-payables', 'page' => 'courier-surcharge'])) ->post(route('business.courier-surcharge.types.store'), ['name' => '偏远地区费']) ->assertRedirect() ->assertSessionHasErrors('name'); } public function test_inactive_type_is_rejected_for_new_quotes_but_keeps_historical_value(): void { $this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail()); $this->loginAs(); $type = app(CourierSurchargeTypeRepository::class)->all()->firstWhere('name', '超长费'); $this->assertNotNull($type); $quote = $this->createQuote(); $this->post(route('business.courier-surcharge.types.status', ['type' => $type->id]), [ 'status' => CourierSurchargeType::STATUS_INACTIVE, ])->assertRedirect(); $this->withExceptionHandling()->post(route('business.courier-surcharge.store'), [ 'courier' => '停用类型测试快递', 'scope' => '自有快递', 'reconciler' => '张会计', 'types' => ['超长费'], 'mode' => '固定单价', 'standard' => '1 元/单', 'condition' => '测试', 'effective_at' => '2026-09-02', ])->assertSessionHasErrors('types.0'); $this->get(route('business.pages.show', ['section' => 'courier-payables', 'page' => 'courier-surcharge'])) ->assertOk() ->assertSeeText($quote->courier) ->assertSeeText('超长费') ->assertSeeText('管理附加费类型'); $page = $this->get(route('business.pages.show', ['section' => 'courier-payables', 'page' => 'courier-surcharge'])) ->assertOk(); $this->assertStringNotContainsString('value="超长费">超长费', $page->getContent()); } public function test_type_status_endpoint_rejects_another_company_type(): void { $this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail()); $otherType = CourierSurchargeType::withoutGlobalScopes()->create([ 'company_id' => company_id() + 999, 'name' => '其他公司类型', 'status' => CourierSurchargeType::STATUS_ACTIVE, 'sort_order' => 99, ]); $this->loginAs(); $this->withExceptionHandling()->post(route('business.courier-surcharge.types.status', ['type' => $otherType->id]), [ 'status' => CourierSurchargeType::STATUS_INACTIVE, ])->assertNotFound(); } public function test_courier_surcharge_page_filters_persisted_rules(): void { $this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail()); $this->createQuote(); CourierSurchargeQuote::query()->create([ 'company_id' => company_id(), 'courier' => '常州松宇货运', 'scope' => '代发仓', 'reconciler' => '李会计', 'types' => ['送货费'], 'mode' => '按体积', 'standard' => '体积 ≤ 10 m³:50 元/单', 'condition' => '计费体积不超过 10 m³', 'effective_at' => '2026-09-02', 'status' => CourierSurchargeQuote::STATUS_ACTIVE, 'remark' => null, ]); $this->loginAs() ->get(route('business.pages.show', [ 'section' => 'courier-payables', 'page' => 'courier-surcharge', 'courier' => '常州松宇货运', 'scope' => '代发仓', 'reconciler' => '李会计', 'status' => '已启用', ])) ->assertOk() ->assertSeeText('常州松宇货运') ->assertSeeText('送货费') ->assertSeeText('代发仓') ->assertSeeText('李会计') ->assertSeeText('当前规则') ->assertDontSee('曹县德邦', false) ->assertDontSee('霸州百世快运-雅柏', false); } public function test_courier_surcharge_store_update_and_status_are_persistent(): void { $this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail()); $this->loginAs(); $payload = [ 'courier' => '测试快递', 'scope' => '代发仓', 'reconciler' => '李会计', 'types' => ['拦截费', '改地址'], 'mode' => '固定单价', 'standard' => '12 元/单', 'condition' => '拦截成功', 'effective_at' => '2026-09-02', 'remark' => '接口保存测试', ]; $this->post(route('business.courier-surcharge.store'), $payload) ->assertRedirect(route('business.pages.show', [ 'company_id' => company_id(), 'section' => 'courier-payables', 'page' => 'courier-surcharge', ])); $quote = CourierSurchargeQuote::query()->where('courier', '测试快递')->firstOrFail(); $this->assertSame(['拦截费', '改地址'], $quote->types); $this->assertSame(CourierSurchargeQuote::STATUS_ACTIVE, $quote->status); $this->assertSame((int) user_id(), (int) $quote->created_by); $this->assertSame((int) user_id(), (int) $quote->updated_by); $this->patch(route('business.courier-surcharge.update', ['quote' => $quote->id]), [ ...$payload, 'courier' => '测试快递(已修改)', 'types' => ['保费'], ])->assertRedirect(); $quote->refresh(); $this->assertSame('测试快递(已修改)', $quote->courier); $this->assertSame(['保费'], $quote->types); $this->post(route('business.courier-surcharge.status', ['quote' => $quote->id]), [ 'status' => CourierSurchargeQuote::STATUS_INACTIVE, ])->assertRedirect(); $this->assertSame(CourierSurchargeQuote::STATUS_INACTIVE, $quote->fresh()->status); } private function createQuote(): CourierSurchargeQuote { return CourierSurchargeQuote::query()->create([ 'company_id' => company_id(), 'courier' => '曹县德邦', 'scope' => '自有快递', 'reconciler' => '张会计', 'types' => ['超长费'], 'mode' => '按尺寸/最长边', 'standard' => '最长边 > 160 cm:8 元/单', 'condition' => '最长边超过 160 cm', 'effective_at' => '2026-09-01', 'status' => CourierSurchargeQuote::STATUS_ACTIVE, 'remark' => '大件渠道标准', ]); } }