user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail()); $repository = \Mockery::mock(SupplierBookkeepingWorkOrderRepository::class); $repository->shouldReceive('syncStatus')->andReturn(['code' => 'ready', 'last_succeeded_at' => null]); $repository->shouldReceive('rows')->andReturn([]); $this->app->instance(SupplierBookkeepingWorkOrderRepository::class, $repository); } private function url(string $name, array $params = []): string { return route($name, ['company_id' => $this->company->id] + $params); } private function configPage(array $query = []): string { return route('business.pages.show', ['company_id' => $this->company->id, 'section' => 'supplier-payables', 'page' => 'manufacturer-bookkeeping', 'bk_view' => 'config'] + $query); } private function xlsx(array $rows): UploadedFile { $book = new Spreadsheet(); $book->getActiveSheet()->fromArray($rows); $path = tempnam(sys_get_temp_dir(), 'sbc') . '.xlsx'; (new Xlsx($book))->save($path); return new UploadedFile($path, '厂家记账配置.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', null, true); } public function test_migration_imports_existing_finance_configs(): void { $this->assertSame(209, DB::table(Store::TABLE)->count()); $this->assertSame(4, DB::table(Store::TABLE)->where('mode', 'normal')->count()); $this->assertSame(48, DB::table(Store::TABLE)->where('mode', 'dropship_wrong')->count()); $row = DB::table(Store::TABLE)->where('supplier_name', '景瓴十方')->first(); $this->assertSame(['none', '2025-03-01', '2026-02-28'], [$row->mode, $row->effective_from, $row->effective_to]); $this->loginAs()->get($this->configPage(['supplier_name' => '曹县洪耀'])) ->assertOk() ->assertSee('厂家记账配置') ->assertSee('曹县洪耀') ->assertSee('代发仓发货错需记账,其他原因均不记账') ->assertSee('导入存量厂家记账配置:新增209条'); } public function test_create_update_delete_restore_with_audit_log(): void { $this->loginAs()->post($this->url('business.supplier-bookkeeping-configs.store'), ['supplier_name' => ' 新厂家 ', 'mode' => 'normal']) ->assertRedirect(); $id = DB::table(Store::TABLE)->where('supplier_name', '新厂家')->value('id'); $this->assertNotNull($id); $this->withExceptionHandling()->loginAs()->post($this->url('business.supplier-bookkeeping-configs.store'), ['supplier_name' => '新厂家', 'mode' => 'none']) ->assertSessionHasErrors('supplier_name'); $this->loginAs()->patch($this->url('business.supplier-bookkeeping-configs.update', ['configId' => $id]), [ 'supplier_name' => '新厂家', 'mode' => 'none', 'effective_from' => '2026-01-01', 'effective_to' => '2026-12-31', ])->assertRedirect(); $this->assertSame('none', DB::table(Store::TABLE)->where('id', $id)->value('mode')); $this->withExceptionHandling()->loginAs()->patch($this->url('business.supplier-bookkeeping-configs.update', ['configId' => $id]), [ 'supplier_name' => '新厂家', 'mode' => 'none', 'effective_from' => '2026-12-31', 'effective_to' => '2026-01-01', ])->assertSessionHasErrors('effective_to'); $this->loginAs()->delete($this->url('business.supplier-bookkeeping-configs.destroy', ['configId' => $id]))->assertRedirect(); $this->assertNotNull(DB::table(Store::TABLE)->where('id', $id)->value('deleted_at')); $this->loginAs()->post($this->url('business.supplier-bookkeeping-configs.restore', ['configId' => $id]))->assertRedirect(); $this->assertNull(DB::table(Store::TABLE)->where('id', $id)->value('deleted_at')); $this->assertSame(['import', 'create', 'update', 'delete', 'restore'], DB::table(Store::EVENTS)->orderBy('id')->pluck('action')->all()); } public function test_import_finance_sheet_adds_updates_and_skips(): void { $file = $this->xlsx([ ['供应商', '厂家是否记账'], ['鑫呈', '正常记账'], ['尊享', '代发仓发货错需记账,其他原因均不记账'], ['供应商', '厂家是否记账'], ['全新厂', '不记账(2025.3月-2027.12.30)'], ]); $this->loginAs()->post($this->url('business.supplier-bookkeeping-configs.import'), ['file' => $file]) ->assertRedirect() ->assertSessionHas('bookkeeping_config_message', '导入完成:新增1条,更新1条,未变化1条。'); $this->assertSame('dropship_wrong', DB::table(Store::TABLE)->where('supplier_name', '尊享')->value('mode')); $this->assertSame('2027-12-30', DB::table(Store::TABLE)->where('supplier_name', '全新厂')->value('effective_to')); $before = DB::table(Store::TABLE)->count(); $bad = $this->xlsx([['供应商', '厂家是否记账'], ['再一个厂', '正常记账'], ['坏行厂', '看情况']]); $this->withExceptionHandling()->loginAs()->post($this->url('business.supplier-bookkeeping-configs.import'), ['file' => $bad]) ->assertSessionHasErrors('file'); $this->assertSame($before, DB::table(Store::TABLE)->count()); } public function test_export_round_trips_through_import(): void { $response = $this->loginAs()->get($this->url('business.supplier-bookkeeping-configs.export', ['supplier_name' => '景瓴十方'])); $response->assertOk(); $path = tempnam(sys_get_temp_dir(), 'sbe') . '.xlsx'; file_put_contents($path, $response->streamedContent()); $rows = app(\Modules\EcommerceFinance\Services\SupplierBookkeepingConfigImporter::class)->read($path); $this->assertSame([['supplier_name' => '景瓴十方', 'mode' => 'none', 'effective_from' => '2025-03-01', 'effective_to' => '2026-02-28', 'source_text' => '不记账(2025.3月-2026.2月)']], $rows); } }