user->attachPermission( Permission::where('name', 'read-admin-panel')->firstOrFail() ); } public function test_final_table_page_keeps_the_maintenance_toolbar_and_starts_empty(): void { $this->loginAs() ->get(route('business.pages.show', [ 'section' => 'supplier-payables-final', 'page' => 'board-deductions', ])) ->assertOk() ->assertSeeText('导入') ->assertSeeText('导出') ->assertSeeText('查询') ->assertSeeText('重置') ->assertSeeText('编辑') ->assertSeeText('下载导入模板') ->assertSeeText('月份') ->assertSeeText('入库日期') ->assertSeeText('申领单号') ->assertSeeText('暂无数据,请点击“导入”上传本表数据。') ->assertSee('workspace/supplier-payables-final/actions/board-deductions/import', false) ->assertSee('workspace/supplier-payables-final/actions/board-deductions/template', false) // 导入/编辑弹窗的行内脚本必须随页面输出,局部替换导航才不会出现“点了没反应”。 ->assertSee('data-supplier-import-modal', false) ->assertSee('data-supplier-import-choose', false) ->assertSee('modal.dataset.ready', false) ->assertSee('data-supplier-maintenance-modal', false) // 页签是局部替换导航,弹窗脚本要带 replay 标记,替换后才会重新执行并绑定。 ->assertSee('data-caiwu-replay', false) ->assertDontSee('workspace/supplier-payables/actions/board-deductions/import', false); } public function test_final_template_downloads_the_same_columns(): void { $response = $this->loginAs() ->get(route('business.supplier-payables-final.board-deductions.template')) ->assertOk() ->assertHeader('content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); $path = tempnam(sys_get_temp_dir(), 'caiwu-template') . '.xlsx'; try { file_put_contents($path, $response->streamedContent()); $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($path); $header = $spreadsheet->getSheet(0)->rangeToArray('A1:C1')[0]; $notes = $spreadsheet->getSheet(1)->rangeToArray('A2:B2')[0]; $spreadsheet->disconnectWorksheets(); $this->assertSame(['记录标识', '月份', '入库日期'], $header); $this->assertSame('记录标识', $notes[0]); $this->assertStringContainsString('选填', (string) $notes[1]); } finally { @unlink($path); } } public function test_product_price_final_page_reuses_the_price_template_columns(): void { $this->loginAs() ->get(route('business.pages.show', [ 'section' => 'supplier-payables-final', 'page' => 'product-prices', ])) ->assertOk() ->assertSeeText('商品编码') ->assertSeeText('采购价') ->assertSeeText('京喜限价') ->assertSeeText('暂无数据,请点击“导入”上传本表数据。') ->assertSee('workspace/supplier-payables-final/actions/product-prices/template', false); $this->loginAs() ->get(route('business.supplier-payables-final.product-prices.template')) ->assertOk() ->assertHeader('content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); } public function test_import_writes_rows_into_the_final_dataset_only(): void { $file = UploadedFile::fake()->createWithContent( 'board-deductions.csv', "\xEF\xBB\xBF月份,入库日期,出库日期,家具厂,压贴厂,类型,规格,原料名称,实收数量,单价,金额,单位,批次日期,出库单号,出库备注,申领单号,单号类型,送货单号\n" . "2026-09,2026-09-01,2026-09-02,终版家具厂,终版压贴厂,类型A,规格A,原料A,3,12.5,37.5,张,2026-09-03,OUT-1,备注A,CLM-1,单号,DL-1\n", ); $this->loginAs() ->post(route('business.supplier-payables-final.board-deductions.import'), ['import' => $file]) ->assertStatus(302) ->assertSessionHas('success', '导入完成:新增 1 条,更新 0 条。'); $this->assertDatabaseHas('supplier_payable_overrides', [ 'company_id' => $this->company->id, 'dataset' => 'final:supplier:board-deductions', ]); $this->assertSame(0, DB::connection(config('database.supplier_payable_maintenance_connection')) ->table('supplier_payable_overrides') ->where('company_id', $this->company->id) ->where('dataset', 'board-deductions') ->count()); $this->loginAs() ->get(route('business.pages.show', [ 'section' => 'supplier-payables-final', 'page' => 'board-deductions', ])) ->assertOk() ->assertSeeText('2026-09') ->assertSeeText('终版家具厂') ->assertSeeText('CLM-1') ->assertDontSeeText('暂无数据,请点击“导入”上传本表数据。'); } public function test_final_export_and_edit_work_on_the_imported_rows(): void { $file = UploadedFile::fake()->createWithContent( 'board-deductions.csv', "入库日期,出库日期,家具厂,压贴厂,类型,规格,原料名称,实收数量,单价,金额,单位,批次日期,出库单号,出库备注,申领单号,单号类型,送货单号\n" . "2026-09-11,2026-09-12,导出家具厂,厂二,类型B,规格B,原料B,1,10,10,张,2026-09-13,OUT-2,备注B,CLM-2,单号,DL-2\n", ); $this->loginAs()->post(route('business.supplier-payables-final.board-deductions.import'), ['import' => $file]) ->assertStatus(302); $connection = DB::connection(config('database.supplier_payable_maintenance_connection')); $recordKey = (string) $connection->table('supplier_payable_overrides') ->where('company_id', $this->company->id) ->where('dataset', 'final:supplier:board-deductions') ->value('record_key'); $this->assertStringStartsWith('hash:', $recordKey); $export = $this->loginAs()->get(route('business.supplier-payables-final.board-deductions.export')); $export->assertOk(); $this->assertStringContainsString('导出家具厂', $export->streamedContent()); $this->loginAs() ->patch(route('business.supplier-payables-final.board-deductions.update', ['recordKey' => $recordKey]), [ 'values' => ['furniture_factory' => '编辑后的家具厂'], ]) ->assertStatus(302) ->assertSessionHas('success', '保存成功。'); $this->loginAs() ->get(route('business.pages.show', [ 'section' => 'supplier-payables-final', 'page' => 'board-deductions', ])) ->assertOk() ->assertSeeText('编辑后的家具厂'); } public function test_final_page_keyword_filter_narrows_the_rows(): void { $file = UploadedFile::fake()->createWithContent( 'board-deductions.csv', "入库日期,出库日期,家具厂,压贴厂,类型,规格,原料名称,实收数量,单价,金额,单位,批次日期,出库单号,出库备注,申领单号,单号类型,送货单号\n" . "2026-09-21,2026-09-22,筛选甲厂,厂二,类型C,规格C,原料C,1,1,1,张,2026-09-23,OUT-3,备注C,CLM-3,单号,DL-3\n" . "2026-09-21,2026-09-22,筛选乙厂,厂二,类型D,规格D,原料D,1,1,1,张,2026-09-23,OUT-4,备注D,CLM-4,单号,DL-4\n", ); $this->loginAs()->post(route('business.supplier-payables-final.board-deductions.import'), ['import' => $file]) ->assertStatus(302); $this->loginAs() ->get(route('business.pages.show', [ 'section' => 'supplier-payables-final', 'page' => 'board-deductions', 'keyword' => '筛选甲厂', ])) ->assertOk() ->assertSeeText('筛选甲厂') ->assertDontSeeText('筛选乙厂') ->assertSeeText('共 1 条'); } }