$courier) { $accessories[] = [ 'trade_no' => 'T001', 'express_no' => 'BF-TEST-' . $i, 'express_name1' => $courier, 'express_name2' => '', 'ship_time' => '2026-11-10', 'barcode' => 'SKU-1', 'freight' => '10.00', ]; } $original = [ 'trade_no' => 'T001', 'express_no' => 'FIRST001', 'express_name1' => '首发快递', 'ship_time' => '2026-10-01', 'barcode' => 'SKU', 'warehouse_name' => '成品仓', ]; $shipping = \Mockery::mock(ShippingOrderRepository::class); $shipping->shouldReceive('accessoryReshipBatches')->with('2026-11-01', '2026-12-01', '2026-09-01') ->andReturnUsing(static function () use ($accessories, $original) { yield ['accessories' => $accessories, 'originals' => [$original]]; }); $configs = \Mockery::mock(AccessoryReshipCourierStore::class); $configs->shouldReceive('activeRates')->andReturn(['首发快递' => ['courier_code' => 'TEST', 'rate_basis_points' => 5000]]); $selections = \Mockery::mock(AccessoryReshipSelectionStore::class); $selections->shouldReceive('forMonth')->andReturn([]); $this->app->instance(ShippingOrderRepository::class, $shipping); $this->app->instance(AccessoryReshipCourierStore::class, $configs); $this->app->instance(AccessoryReshipSelectionStore::class, $selections); $this->user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail()); } protected function pageUrl(array $filters = []): string { return route('business.pages.show', [ 'company_id' => $this->company->id, 'section' => 'courier-payables', 'page' => 'accessory-reship-deductions', 'month' => '2026-11', ] + $filters); } public function test_page_totals_and_export_exclude_both_couriers_from_deductions(): void { $this->mockShipments(); $this->loginAs()->get($this->pageUrl(['match_status' => 'all']))->assertOk() ->assertSee('BF-TEST-0')->assertSee('BF-TEST-1')->assertSee('BF-TEST-2') ->assertSee('补发快递为祥和中通,不参与扣款') ->assertSee('补发快递为柏卡顺丰干配配件,不参与扣款') ->assertSee('¥ 5.00'); $csv = $this->get(route('business.accessory-reship-deductions.export', [ 'company_id' => $this->company->id, 'month' => '2026-11', 'match_status' => 'all', ]))->assertOk()->streamedContent(); $records = array_map('str_getcsv', explode("\n", trim($csv))); $this->assertCount(4, $records); foreach ([1, 2] as $i) { $this->assertSame('不扣款', $records[$i][7]); $this->assertSame('0.00', $records[$i][12]); } $this->assertSame('可扣款', $records[3][7]); $this->assertSame('5.00', $records[3][12]); $this->get($this->pageUrl())->assertOk()->assertSee('BF-TEST-2') ->assertDontSee('BF-TEST-0')->assertDontSee('BF-TEST-1')->assertSee('¥ 5.00'); $readyCsv = $this->get(route('business.accessory-reship-deductions.export', [ 'company_id' => $this->company->id, 'month' => '2026-11', ]))->assertOk()->streamedContent(); $this->assertStringContainsString('BF-TEST-2', $readyCsv); $this->assertStringNotContainsString('BF-TEST-0', $readyCsv); $this->assertStringNotContainsString('BF-TEST-1', $readyCsv); $this->get($this->pageUrl(['match_status' => 'all', 'deduction_state' => 'excluded_courier'])) ->assertOk()->assertSee('BF-TEST-0')->assertSee('BF-TEST-1') ->assertDontSee('BF-TEST-2')->assertSee('¥ 0.00'); } }