CaiWuXiTong/tests/Feature/Business/CompanyPlanPageTest.php
DoDo 692d590509 feat: 公司盘点页面与未完结店铺关联
新增经营报表 › 公司盘点,支持导入预览、筛选、备注关键词搜索、编辑、导出及未完结店铺关联。

验证:公司盘点与导航相关测试 15 项通过(161 断言),目录表头测试 99 断言通过。
边界:原始 Excel 与本地 SQLite 数据不进入 Git;本次无数据库迁移。
2026-11-09 15:43:43 +08:00

275 lines
11 KiB
PHP

<?php
namespace Tests\Feature\Business;
use App\Business\CompanyPlan\CompanyPlanRepository;
use App\Business\CompanyPlan\CompanyPlanWorkbookImporter;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Tests\Feature\FeatureTestCase;
class CompanyPlanPageTest extends FeatureTestCase
{
private string $tempDirectory;
protected function setUp(): void
{
parent::setUp();
$this->tempDirectory = sys_get_temp_dir() . '/caiwu-company-plan-' . bin2hex(random_bytes(6));
File::ensureDirectoryExists($this->tempDirectory);
Storage::fake('local');
config([
'company_plan.database_path' => $this->tempDirectory . '/company-plan.sqlite',
'company_plan.preview_disk' => 'local',
]);
}
protected function tearDown(): void
{
File::deleteDirectory($this->tempDirectory);
parent::tearDown();
}
public function testPageRendersExactWorkbookHeadersClickableSummaryAndRemarkSearch(): void
{
$this->seedRows();
$response = $this->loginAs()->get(route('business.pages.show', [
'section' => 'company-management',
'page' => 'company-plan',
]));
$response
->assertOk()
->assertSee('data-company-plan-page', false)
->assertSee('data-company-plan-summary="all"', false)
->assertSee('data-company-plan-summary="plan:retained"', false)
->assertSee('data-company-plan-summary="status:cancelling"', false)
->assertSeeTextInOrder([
'序号',
'公司名称',
'类型',
'税务类型',
'注册时间',
'工商类型',
'统一社会信用代码',
'规划',
'公司状态',
'注销-税务',
'注销-工商',
'注销-银行',
'备注',
])
->assertSeeText('备注搜索')
->assertSee('placeholder="只搜索备注内容', false)
->assertSeeText('公司总数')
->assertSeeText('规划保留')
->assertSeeText('已注销')
->assertSeeText('注销中')
->assertSeeText('规划注销未发起')
->assertSeeText('未完结店铺');
}
public function testFiltersUseServerSideCompanyAndRemarkKeywords(): void
{
$this->seedRows();
$this->loginAs()
->get(route('business.pages.show', [
'section' => 'company-management',
'page' => 'company-plan',
'remark_keyword' => '银行卡',
'plan' => '注销',
'company_status' => '注销中',
]))
->assertOk()
->assertSeeText('上海测试注销主体')
->assertDontSeeText('常州测试保留主体')
->assertSeeText('备注含:银行卡');
$this->get(route('business.pages.show', [
'section' => 'company-management',
'page' => 'company-plan',
'keyword' => '常州测试',
]))
->assertOk()
->assertSeeText('常州测试保留主体')
->assertDontSeeText('上海测试注销主体');
$this->get(route('business.pages.show', [
'section' => 'company-management',
'page' => 'company-plan',
'remark_keyword' => '常州测试',
]))
->assertOk()
->assertDontSeeText('常州测试保留主体')
->assertDontSeeText('上海测试注销主体');
}
public function testEditUpdatesOneCompanyPlanRow(): void
{
$this->seedRows();
$repository = app(CompanyPlanRepository::class);
$row = $repository->paginate((int) company_id(), [], 1, 25)['rows'][0];
$this->loginAs()
->patch(route('business.company-plan.update', ['row' => $row['id']]), [
'sequence_no' => 9,
'company_name' => '常州测试保留主体',
'company_type' => '店铺-普通公司',
'taxpayer_type' => '小规模纳税人',
'registered_at' => '2024-03-02',
'business_registration_type' => '/',
'unified_social_credit_code' => 'TEST-CREDIT-001',
'plan' => '待定',
'company_status' => '正常',
'tax_cancellation' => '',
'business_cancellation' => '',
'bank_cancellation' => '',
'notes' => '已改为保留观察',
])
->assertRedirect();
$updated = $repository->findForCompany((int) company_id(), (int) $row['id']);
$this->assertSame('待定', $updated['plan']);
$this->assertSame('已改为保留观察', $updated['notes']);
$this->assertSame('2024-03-02', $updated['registered_at']);
}
public function testWorkbookPreviewAndConfirmImportsOnlyValidRows(): void
{
$path = $this->tempDirectory . '/subject-inventory.xlsx';
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setTitle('主体盘点');
$sheet->fromArray([
[
'序号', '公司名称', '类型', '税务类型', '注册时间', '工商类型',
'统一社会信用代码', '规划', '公司状态', '注销-税务', '注销-工商', '注销-银行', '备注',
],
[1, '新增测试主体', '店铺-普通公司', '一般纳税人', '2025-01-02', '/', 'TEST-NEW-001', '保留', '正常', '', '', '', '重点观察'],
[2, '', '店铺-普通公司', '小规模纳税人', '2025-01-03', '/', 'TEST-BAD-001', '注销', '注销中', '', '', '', ''],
[3, '新增测试主体', '店铺-普通公司', '一般纳税人', '2025-01-04', '/', 'TEST-DUP-001', '注销', '注销中', '', '', '', '文件内重复'],
], null, 'A1');
(new Xlsx($spreadsheet))->save($path);
$spreadsheet->disconnectWorksheets();
$previewResponse = $this->loginAs()
->post(route('business.company-plan.import.preview'), [
'import' => new UploadedFile(
$path,
'subject-inventory.xlsx',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
null,
true,
),
'duplicate_mode' => 'update',
])
->assertRedirect();
$token = session('company_plan_preview_token');
$this->assertIsString($token);
$this->assertSame(40, strlen($token));
$this->get(route('business.pages.show', [
'section' => 'company-management',
'page' => 'company-plan',
]))
->assertOk()
->assertSeeText('导入预览')
->assertSeeText('有效主体')
->assertSeeText('新增测试主体')
->assertSeeText('公司名称为空')
->assertSeeText('文件内公司名称重复')
->assertDontSeeText('缺少表头');
$this->post(route('business.company-plan.import.confirm'), [
'preview_token' => $token,
'duplicate_mode' => 'update',
])->assertRedirect();
$repository = app(CompanyPlanRepository::class);
$result = $repository->paginate((int) company_id(), ['keyword' => '新增测试主体'], 1, 25);
$this->assertSame(1, $result['total']);
$this->assertSame('重点观察', $result['rows'][0]['notes']);
$this->assertNull(session('company_plan_preview_token'));
}
public function testExportUsesCurrentFilterAndSelectedColumns(): void
{
$this->seedRows();
$response = $this->loginAs()->get(route('business.company-plan.export', [
'plan' => '保留',
'columns' => 'sequence_no,company_name,plan,notes',
]));
$response
->assertOk()
->assertHeader('content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
$content = $response->streamedContent();
$this->assertNotSame('', $content);
$this->assertStringContainsString(
'公司盘点_',
urldecode($response->headers->get('content-disposition', ''))
);
$path = $this->tempDirectory . '/company-plan-export.xlsx';
file_put_contents($path, $content);
$spreadsheet = IOFactory::load($path);
$sheet = $spreadsheet->getActiveSheet();
$this->assertSame(['序号', '公司名称', '规划', '备注'], [
$sheet->getCell('A1')->getValue(),
$sheet->getCell('B1')->getValue(),
$sheet->getCell('C1')->getValue(),
$sheet->getCell('D1')->getValue(),
]);
$this->assertSame(2, $sheet->getHighestDataRow());
$this->assertSame('常州测试保留主体', $sheet->getCell('B2')->getValue());
$spreadsheet->disconnectWorksheets();
}
private function seedRows(): void
{
app(CompanyPlanRepository::class)->importRows((int) company_id(), [
[
'sequence_no' => 1,
'company_name' => '常州测试保留主体',
'company_type' => '店铺-普通公司',
'taxpayer_type' => '小规模纳税人',
'registered_at' => '2024-03-01',
'business_registration_type' => '/',
'unified_social_credit_code' => 'TEST-CREDIT-001',
'plan' => '保留',
'company_status' => '正常',
'tax_cancellation' => null,
'business_cancellation' => null,
'bank_cancellation' => null,
'notes' => '先继续使用',
],
[
'sequence_no' => 2,
'company_name' => '上海测试注销主体',
'company_type' => '资产型',
'taxpayer_type' => '一般纳税人',
'registered_at' => '2023-04-05',
'business_registration_type' => '/',
'unified_social_credit_code' => 'TEST-CREDIT-002',
'plan' => '注销',
'company_status' => '注销中',
'tax_cancellation' => '✅',
'business_cancellation' => null,
'bank_cancellation' => null,
'notes' => '税务已注销,银行卡待注销',
],
], 'update', (int) auth()->id());
}
}