user->attachPermission( Permission::where('name', 'read-admin-panel')->firstOrFail() ); } public function testDeliveryUnpricedPageUsesItsOwnTwentyColumnTable() { $this->grantAdminPermission(); $response = $this->loginAs()->get(route('business.pages.show', [ 'section' => 'supplier-payables', 'page' => 'delivery-unpriced', ])); $response ->assertOk() ->assertSee('id="delivery-unpriced-app"', false) ->assertSee('来源单号') ->assertSee('单据编号(采购单号)') ->assertSee('负责人') ->assertSee('public/js/ecommerce-finance/delivery-unpriced.min.js', false) ->assertDontSee('class="business-blank-page"', false); $this->assertSame(20, substr_count($response->getContent(), 'grantAdminPermission(); $response = $this->loginAs()->get(route('business.pages.show', [ 'section' => 'supplier-payables', 'page' => 'return-unpriced', ])); $response ->assertOk() ->assertSee('id="return-unpriced-app"', false) ->assertSee('明细供应商') ->assertSee('供应商条码') ->assertSee('对账人') ->assertSee('public/js/ecommerce-finance/return-unpriced.min.js', false) ->assertDontSee('class="business-blank-page"', false); $this->assertSame(20, substr_count($response->getContent(), 'grantAdminPermission(); $response = $this->loginAs()->get(route('business.pages.show', [ 'section' => 'supplier-payables', 'page' => 'board-deductions', ])); $response ->assertOk() ->assertSee('class="supplier-board-table"', false) ->assertSee('入库日期') ->assertSee('出库备注') ->assertSee('送货单号') ->assertDontSee('class="business-blank-page"', false); preg_match_all('/)/', $response->getContent(), $headers); $this->assertCount(17, $headers[0]); } public function testSupplierPayablesReportPageUsesItsOwnThirtyFourColumnGroupedTable() { $this->grantAdminPermission(); $response = $this->loginAs()->get(route('business.pages.show', [ 'section' => 'supplier-payables', 'page' => 'supplier-payables-report', ])); $response ->assertOk() ->assertSee('class="supplier-payables-report-table"', false) ->assertSee('已销账供应商') ->assertSee('本月采购金额') ->assertSee('加', false) ->assertSee('单位:元', false) ->assertSee('供应商余额', false) ->assertSee('最晚出账单时间(新执行标准)') ->assertDontSee('class="business-blank-page"', false); preg_match_all('/)/', $response->getContent(), $columns); $this->assertCount(34, $columns[0]); } public function testProductPricesPageUsesOperationsReplicaPriceLimitFields(): void { $this->grantAdminPermission(); $repository = \Mockery::mock(ProductPriceMirrorRepository::class); $repository->shouldReceive('ready')->once()->andReturnTrue(); $repository->shouldReceive('initialized')->once()->andReturnTrue(); $repository->shouldReceive('paginate') ->once() ->withArgs(static function (array $filters, int $page, int $limit): bool { return $filters === [ 'barcode' => 'YMJ005203N1176V01', 'completed_from' => '2025-12-01', 'completed_to' => '2025-12-31', ] && $page === 1 && $limit > 0; }) ->andReturn(new LengthAwarePaginator([(object) [ 'barcode' => 'YMJ005203N1176V01', 'spu' => 'YMJ0052', 'product_name' => '款式二 36/36/176 胡桃木色 BY-008', 'category' => '住宅家具 - 衣帽架', 'production_status' => '销售', 'minimum_price' => 152.8, 'price_limit' => 152.6, 'purchase_price' => 91.11, 'shipping_fee' => 11.62, 'jingxi_limit_price' => 123.0, 'approval_status' => '已完成', 'approval_result' => '已同意', 'workflow_title' => '特殊限价需求申请', 'completed_at' => '2025-12-31 00:00:00', ] ], 1, 25, 1)); $this->app->instance(ProductPriceMirrorRepository::class, $repository); $response = $this->loginAs()->get(route('business.pages.show', [ 'section' => 'supplier-payables', 'page' => 'product-prices', 'barcode' => 'YMJ005203N1176V01', 'completed_from' => '2025-12-01', 'completed_to' => '2025-12-31', ])); $response ->assertOk() ->assertSee('商品编码') ->assertSee('最低售价') ->assertSee('计算限价') ->assertSee('采购价') ->assertSee('京喜限价') ->assertSee('YMJ005203N1176V01') ->assertSee('152.80') ->assertSee('已同意') ->assertDontSee('是否采购降本'); preg_match_all('/)/', $response->getContent(), $headers); $this->assertCount(15, $headers[0]); } public function testProductPricesPageDoesNotTreatUninitializedMirrorAsEmptyData(): void { $this->grantAdminPermission(); $repository = \Mockery::mock(ProductPriceMirrorRepository::class); $repository->shouldReceive('ready')->once()->andReturnTrue(); $repository->shouldReceive('initialized')->once()->andReturnFalse(); $repository->shouldNotReceive('paginate'); $this->app->instance(ProductPriceMirrorRepository::class, $repository); $url = route('business.pages.show', [ 'company_id' => $this->company->id, 'section' => 'supplier-payables', 'page' => 'product-prices', ]) . '?page=2'; $response = $this->loginAs()->get($url); $response ->assertOk() ->assertSee('商品价格正在执行首次全量同步') ->assertDontSee('没有符合当前筛选条件的商品价格数据'); } public function testCompensationPageUsesTheFiveColumnsFromTheReferenceSheet(): void { $this->grantAdminPermission(); $response = $this->loginAs()->get(route('business.pages.show', [ 'section' => 'supplier-payables', 'page' => 'compensation-details', ])); $response ->assertOk() ->assertSee('id="compensation-detail-app"', false) ->assertSee('赔付原因') ->assertSee('备注') ->assertSee('public/js/ecommerce-finance/compensation-details.min.js', false); $this->assertSame(5, substr_count($response->getContent(), 'grantAdminPermission(); $cache = \Mockery::mock(JianSunQueryCache::class); $cache->shouldReceive('remember')->times(10)->andReturnUsing( static fn (string $scope): array => [ 'data' => [['scope' => $scope]], 'total' => 1, ], ); $cache->shouldReceive('responseHeaders')->times(10)->andReturn([]); $this->app->instance(JianSunQueryCache::class, $cache); $routes = [ 'workspace-data.supplier-payables.payment-reconciliation.index', 'workspace-data.supplier-payables.return-reconciliation.index', 'workspace-data.supplier-payables.invoice-deductions.index', 'workspace-data.supplier-payables.compensation-details.index', 'workspace-data.supplier-payables.advance-details.index', 'workspace-data.supplier-payables.delivery-unpriced.index', 'workspace-data.supplier-payables.return-unpriced.index', 'workspace-data.supplier-payables.sample-deductions.index', 'workspace-data.supplier-payables.other-adjustments.index', 'workspace-data.supplier-payables.dropshipping-express.index', ]; foreach ($routes as $routeName) { $this->loginAs() ->withHeader('X-Requested-With', 'XMLHttpRequest') ->get(route($routeName)) ->assertOk() ->assertJsonPath('total', 1); } } public function testSupplierPayableDataRouteRejectsUsersWithoutTheMatchingSidebarPage(): void { $subject = 'user_' . $this->user->id; setting()->set('system.sidebar_permissions', json_encode([ 'configured' => [$subject], 'subjects' => [ $subject => ['supplier-payables/invoice-deductions'], ], ], JSON_UNESCAPED_UNICODE)); try { $this->loginAs() ->withHeader('X-Requested-With', 'XMLHttpRequest') ->get(route('workspace-data.supplier-payables.payment-reconciliation.index')); $this->fail('缺少页面权限的用户不应读取货款对账数据。'); } catch (HttpException $exception) { $this->assertSame(403, $exception->getStatusCode()); } } }