CaiWuXiTong/tests/Feature/Business/CourierPayableSummaryPagesTest.php
苏木 79588e88f2 fix: 提升快递汇总导入上限至50万 (#214)
运费差与其他附加费汇总的单次导入上限统一提升至 500,000 条,并补充超过旧上限的回归验证。
Co-authored-by: 苏木 <594326199@qq.com>
Co-committed-by: 苏木 <594326199@qq.com>
2026-09-20 14:09:46 +08:00

396 lines
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Tests\Feature\Business;
use App\Business\CourierPayableSummaryStore;
use App\Models\Auth\Permission;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\IOFactory;
use Tests\Feature\FeatureTestCase;
class CourierPayableSummaryPagesTest extends FeatureTestCase
{
protected function setUp(): void
{
parent::setUp();
$this->user->attachPermission(
Permission::where('name', 'read-admin-panel')->firstOrFail()
);
Storage::fake('uploads');
}
public function test_final_workspace_places_both_summary_pages_after_courier_payables_report(): void
{
$response = $this->loginAs()->get(route('business.pages.show', [
'section' => 'courier-payables-final',
]));
$response->assertOk()->assertSeeInOrder([
route('business.pages.show', ['section' => 'courier-payables', 'page' => 'courier-payables-report']),
route('business.pages.show', ['section' => 'courier-payables', 'page' => 'freight-difference']),
route('business.pages.show', ['section' => 'courier-payables', 'page' => 'other-surcharge-summary']),
], false);
}
public function test_summary_pages_render_import_and_export_buttons(): void
{
foreach (CourierPayableSummaryStore::PAGES as $page => $title) {
$this->loginAs()->get(route('business.pages.show', [
'section' => 'courier-payables',
'page' => $page,
]))
->assertOk()
->assertSee("data-courier-payable-summary=\"{$page}\"", false)
->assertSeeText($title)
->assertSeeText('导入')
->assertSeeText('导出')
->assertSeeText('暂无数据,请先点击“导入”上传汇总表。');
}
}
public function test_freight_difference_import_dialog_downloads_the_supplied_xlsx_template(): void
{
$pageResponse = $this->loginAs()->get(route('business.pages.show', [
'section' => 'courier-payables',
'page' => 'freight-difference',
]));
$pageResponse
->assertOk()
->assertSee('data-courier-summary-import-dialog', false)
->assertSeeText('下载模板')
->assertSee(route('business.courier-payable-summaries.template', [
'summaryPage' => 'freight-difference',
]), false);
$templateResponse = $this->loginAs()->get(route('business.courier-payable-summaries.template', [
'summaryPage' => 'freight-difference',
]));
$templateResponse
->assertOk()
->assertDownload('freight_difference_import_template.xlsx')
->assertHeader('content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
$this->assertStringContainsString(
"filename*=utf-8''" . rawurlencode('运费差导入模板.xlsx'),
(string) $templateResponse->headers->get('Content-Disposition'),
);
$spreadsheet = IOFactory::load(resource_path('templates/courier-payables/freight-difference-import-template.xlsx'));
$worksheet = $spreadsheet->getActiveSheet();
$this->assertSame([
'日期',
'负责人',
'快递公司',
'快递单号',
'店铺',
'id',
'条码',
'交易单号',
'差异(结算运费-提供成本运费)',
'是否配件',
'配件成品条码',
], $worksheet->rangeToArray('A1:K1', null, false, false)[0]);
$this->assertSame('FFFFC000', $worksheet->getStyle('E1')->getFill()->getStartColor()->getARGB());
$this->assertSame('FFFFC000', $worksheet->getStyle('F1')->getFill()->getStartColor()->getARGB());
$this->assertSame('FFFFC000', $worksheet->getStyle('H1')->getFill()->getStartColor()->getARGB());
$this->assertSame('@', $worksheet->getStyle('A2')->getNumberFormat()->getFormatCode());
$this->assertSame('@', $worksheet->getStyle('F2')->getNumberFormat()->getFormatCode());
$this->assertSame('@', $worksheet->getStyle('H2')->getNumberFormat()->getFormatCode());
$this->assertSame('', (string) $worksheet->getCell('A2')->getValue());
$spreadsheet->disconnectWorksheets();
}
public function test_other_surcharge_import_dialog_downloads_the_supplied_xlsx_template(): void
{
$pageResponse = $this->loginAs()->get(route('business.pages.show', [
'section' => 'courier-payables',
'page' => 'other-surcharge-summary',
]));
$pageResponse
->assertOk()
->assertSee('data-courier-summary-import-dialog', false)
->assertSeeText('导入其他附加费汇总')
->assertSeeText('其他附加费导入模板')
->assertSeeText('.xlsx · 11 个字段')
->assertSeeText('下载模板')
->assertSee(route('business.courier-payable-summaries.template', [
'summaryPage' => 'other-surcharge-summary',
]), false);
$templateResponse = $this->loginAs()->get(route('business.courier-payable-summaries.template', [
'summaryPage' => 'other-surcharge-summary',
]));
$templateResponse
->assertOk()
->assertDownload('other_surcharge_import_template.xlsx')
->assertHeader('content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
$this->assertStringContainsString(
"filename*=utf-8''" . rawurlencode('其他附加费导入模板.xlsx'),
(string) $templateResponse->headers->get('Content-Disposition'),
);
$spreadsheet = IOFactory::load(resource_path('templates/courier-payables/other-surcharge-import-template.xlsx'));
$worksheet = $spreadsheet->getActiveSheet();
$this->assertSame([
'日期',
'负责人',
'快递公司',
'快递单号',
'商品ID',
'条码',
'店铺',
'交易单号',
'金额',
'备注',
'成品条码',
], $worksheet->rangeToArray('A1:K1', null, false, false)[0]);
$this->assertSame('@', $worksheet->getStyle('A2')->getNumberFormat()->getFormatCode());
$this->assertSame('@', $worksheet->getStyle('D2')->getNumberFormat()->getFormatCode());
$this->assertSame('@', $worksheet->getStyle('E2')->getNumberFormat()->getFormatCode());
$this->assertSame('@', $worksheet->getStyle('F2')->getNumberFormat()->getFormatCode());
$this->assertSame('@', $worksheet->getStyle('H2')->getNumberFormat()->getFormatCode());
$this->assertSame('0.00########', $worksheet->getStyle('I2')->getNumberFormat()->getFormatCode());
$this->assertSame('@', $worksheet->getStyle('K2')->getNumberFormat()->getFormatCode());
$this->assertSame('', (string) $worksheet->getCell('A2')->getValue());
$this->assertSame('', (string) $worksheet->getCell('K18')->getValue());
$spreadsheet->disconnectWorksheets();
}
public function test_completed_freight_difference_template_preserves_long_identifiers_on_import(): void
{
$spreadsheet = IOFactory::load(resource_path('templates/courier-payables/freight-difference-import-template.xlsx'));
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->fromArray([
'2026-07',
'苏木',
'测试快递',
'YT7632543323146',
'测试店铺',
'855226246304',
'DNZ0117123N1210V01',
'3312228147193110069',
0.1827,
'成品',
'',
], null, 'A2');
$worksheet->getCell('F2')->setValueExplicit('855226246304', DataType::TYPE_STRING);
$worksheet->getCell('H2')->setValueExplicit('3312228147193110069', DataType::TYPE_STRING);
$path = tempnam(sys_get_temp_dir(), 'freight-template-');
$this->assertNotFalse($path);
$xlsxPath = $path . '.xlsx';
try {
IOFactory::createWriter($spreadsheet, 'Xlsx')->save($xlsxPath);
$spreadsheet->disconnectWorksheets();
$file = new UploadedFile(
$xlsxPath,
'运费差导入模板.xlsx',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
null,
true,
);
$this->loginAs()->post(route('business.courier-payable-summaries.import', [
'summaryPage' => 'freight-difference',
]), ['import' => $file])
->assertRedirect(route('business.pages.show', [
'section' => 'courier-payables',
'page' => 'freight-difference',
]))
->assertSessionHas('success', '导入完成:1 条数据,11 个字段。');
$snapshot = app(CourierPayableSummaryStore::class)->snapshot(
(int) $this->company->id,
'freight-difference',
);
$this->assertSame('2026-07', $snapshot['rows'][0][0]);
$this->assertSame('855226246304', $snapshot['rows'][0][5]);
$this->assertSame('3312228147193110069', $snapshot['rows'][0][7]);
$this->assertSame('0.1827', $snapshot['rows'][0][8]);
} finally {
if (isset($spreadsheet)) {
$spreadsheet->disconnectWorksheets();
}
if ($path !== false && is_file($path)) {
unlink($path);
}
if (isset($xlsxPath) && is_file($xlsxPath)) {
unlink($xlsxPath);
}
}
}
public function test_completed_other_surcharge_template_preserves_long_identifiers_on_import(): void
{
$spreadsheet = IOFactory::load(resource_path('templates/courier-payables/other-surcharge-import-template.xlsx'));
$worksheet = $spreadsheet->getActiveSheet();
$worksheet->fromArray([
'2026-07',
'苏木',
'测试快递',
'SF5199125637478',
'6041543429417',
'SJ038017N1410V01',
'测试店铺',
'5110751415866048404',
-60,
'安装费',
'CP001',
], null, 'A2');
$worksheet->getCell('E2')->setValueExplicit('6041543429417', DataType::TYPE_STRING);
$worksheet->getCell('H2')->setValueExplicit('5110751415866048404', DataType::TYPE_STRING);
$path = tempnam(sys_get_temp_dir(), 'other-surcharge-template-');
$this->assertNotFalse($path);
$xlsxPath = $path . '.xlsx';
try {
IOFactory::createWriter($spreadsheet, 'Xlsx')->save($xlsxPath);
$spreadsheet->disconnectWorksheets();
$file = new UploadedFile(
$xlsxPath,
'其他附加费导入模板.xlsx',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
null,
true,
);
$this->loginAs()->post(route('business.courier-payable-summaries.import', [
'summaryPage' => 'other-surcharge-summary',
]), ['import' => $file])
->assertRedirect(route('business.pages.show', [
'section' => 'courier-payables',
'page' => 'other-surcharge-summary',
]))
->assertSessionHas('success', '导入完成:1 条数据,11 个字段。');
$snapshot = app(CourierPayableSummaryStore::class)->snapshot(
(int) $this->company->id,
'other-surcharge-summary',
);
$this->assertSame('2026-07', $snapshot['rows'][0][0]);
$this->assertSame('6041543429417', $snapshot['rows'][0][4]);
$this->assertSame('5110751415866048404', $snapshot['rows'][0][7]);
$this->assertSame('-60', $snapshot['rows'][0][8]);
$this->assertSame('安装费', $snapshot['rows'][0][9]);
} finally {
if (isset($spreadsheet)) {
$spreadsheet->disconnectWorksheets();
}
if ($path !== false && is_file($path)) {
unlink($path);
}
if (isset($xlsxPath) && is_file($xlsxPath)) {
unlink($xlsxPath);
}
}
}
public function test_import_replaces_the_page_snapshot_and_export_returns_all_rows(): void
{
$file = UploadedFile::fake()->createWithContent(
'运费差.csv',
"快递公司,结算月份,运费差,备注\n测试快递,2026-08,-18.50,复核\n第二快递,2026-08,20,=待确认\n",
);
$this->loginAs()->post(route('business.courier-payable-summaries.import', [
'summaryPage' => 'freight-difference',
]), ['import' => $file])
->assertRedirect(route('business.pages.show', [
'section' => 'courier-payables',
'page' => 'freight-difference',
]))
->assertSessionHas('success', '导入完成:2 条数据,4 个字段。');
Storage::disk('uploads')->assertExists(
app(CourierPayableSummaryStore::class)->path((int) $this->company->id, 'freight-difference')
);
$this->loginAs()->get(route('business.pages.show', [
'section' => 'courier-payables',
'page' => 'freight-difference',
]))
->assertOk()
->assertSeeText('导入完成:2 条数据,4 个字段。')
->assertSeeText('测试快递')
->assertSeeText('-18.50')
->assertSeeText('第二快递');
$response = $this->loginAs()->get(route('business.courier-payable-summaries.export', [
'summaryPage' => 'freight-difference',
]));
$content = $response->streamedContent();
$response->assertOk()->assertHeader('content-type', 'text/csv; charset=UTF-8');
$this->assertStringContainsString('快递公司,结算月份,运费差,备注', $content);
$this->assertStringContainsString('测试快递,2026-08,-18.50,复核', $content);
$this->assertStringContainsString("\t=待确认", $content);
}
public function test_summary_imports_accept_more_than_ten_thousand_rows(): void
{
$store = app(CourierPayableSummaryStore::class);
$this->assertSame(500000, $store->maxRows('freight-difference'));
$this->assertSame(500000, $store->maxRows('other-surcharge-summary'));
$rows = ["快递公司,结算月份\n"];
for ($index = 1; $index <= 10001; $index++) {
$rows[] = "测试快递,2026-08\n";
}
foreach (['freight-difference', 'other-surcharge-summary'] as $page) {
$file = UploadedFile::fake()->createWithContent($page . '.csv', implode('', $rows));
$this->loginAs()->post(route('business.courier-payable-summaries.import', [
'summaryPage' => $page,
]), ['import' => $file])
->assertRedirect(route('business.pages.show', [
'section' => 'courier-payables',
'page' => $page,
]))
->assertSessionHas('success', '导入完成:10001 条数据,2 个字段。')
->assertSessionDoesntHaveErrors('import');
$snapshot = $store->snapshot((int) $this->company->id, $page);
$this->assertCount(10001, $snapshot['rows']);
}
}
public function test_summary_actions_require_the_matching_page_permission(): void
{
$this->withExceptionHandling();
$this->user->roles()->sync([
\App\Models\Auth\Role::where('name', 'admin')->firstOrFail()->id,
]);
setting()->set('system.sidebar_permissions', [
'configured' => ['user_' . $this->user->id],
'subjects' => ['user_' . $this->user->id => ['courier-payables/courier-information']],
]);
$this->loginAs()->get(route('business.courier-payable-summaries.export', [
'summaryPage' => 'freight-difference',
]))->assertForbidden();
$this->loginAs()->get(route('business.courier-payable-summaries.template', [
'summaryPage' => 'freight-difference',
]))->assertForbidden();
$this->loginAs()->get(route('business.courier-payable-summaries.template', [
'summaryPage' => 'other-surcharge-summary',
]))->assertForbidden();
}
}