CaiWuXiTong/tests/Feature/Business/ProductCostPendingDetailsTest.php
chenxi 630630b144 商品成本:待核验明细增加筛选与导出
待核验弹框增加筛选区和按当前条件导出全部明细的 CSV 按钮。
2026-10-25 22:11:42 +08:00

167 lines
6.9 KiB
PHP

<?php
namespace Tests\Feature\Business;
use Illuminate\Support\Facades\DB;
use Tests\Feature\FeatureTestCase;
class ProductCostPendingDetailsTest extends FeatureTestCase
{
public function test_pending_details_use_current_filters_and_include_both_unresolved_reasons(): void
{
$mirror = DB::connection('business_mirror');
$mirror->table('store_receipt_product_cost_rows')->insert([
$this->row('pending-both', 'HX-A', null, null, 2, null),
$this->row('pending-price', 'HX-B', '崔桥工厂仓', null, 3, null),
$this->row('pending-warehouse', 'HX-C', '', 10, 1, 10),
$this->row('valid', 'HX-D', '崔桥工厂仓', 10, 1, 10),
$this->row('df-normal', 'HX-E', null, 10, 1, 10, productCode: 'DF-ACCESSORY-1'),
$this->row('df-price', 'HX-F', null, null, 1, null, productCode: 'df-ACCESSORY-2'),
$this->row('other-store', 'OTHER', null, null, 1, null, '其他店铺'),
$this->row('other-month', 'OLD', null, null, 1, null, '京东-HX旗舰店104', '2026-08-01'),
]);
$response = $this->loginAs()->getJson(route(
'business.financial-operations.product-costs.pending-details',
[
'month' => '2026-09',
'store_name' => 'HX',
],
));
$response
->assertOk()
->assertJsonPath('summary.pending_rows', 4)
->assertJsonPath('summary.pending_cost_rows', 3)
->assertJsonPath('summary.pending_cost_quantity', 6)
->assertJsonPath('summary.missing_warehouse_rows', 2)
->assertJsonPath('pagination.total', 4)
->assertJsonPath('pagination.page', 1);
$cacheControl = (string) $response->headers->get('Cache-Control');
$this->assertStringContainsString('private', $cacheControl);
$this->assertStringContainsString('no-store', $cacheControl);
$rows = collect($response->json('rows'))->keyBy('online_order_no');
$this->assertCount(4, $rows);
$this->assertSame(['商品单价缺失', '仓库简称未匹配'], $rows['HX-A']['reasons']);
$this->assertTrue($rows['HX-A']['warehouse_missing']);
$this->assertSame(['商品单价缺失'], $rows['HX-B']['reasons']);
$this->assertSame(['仓库简称未匹配'], $rows['HX-C']['reasons']);
$this->assertTrue($rows['HX-C']['warehouse_missing']);
$this->assertSame(['商品单价缺失'], $rows['HX-F']['reasons']);
$this->assertFalse($rows['HX-F']['warehouse_missing']);
$this->assertFalse($rows->has('HX-D'));
$this->assertFalse($rows->has('HX-E'));
}
public function test_repaired_row_disappears_when_modal_data_is_reloaded(): void
{
$mirror = DB::connection('business_mirror');
$mirror->table('store_receipt_product_cost_rows')->insert(
$this->row('repair-me', 'REPAIR-1', null, null, 1, null)
);
$this->loginAs();
$url = route('business.financial-operations.product-costs.pending-details', [
'month' => '2026-09',
]);
$this->getJson($url)
->assertOk()
->assertJsonPath('pagination.total', 1)
->assertJsonPath('rows.0.online_order_no', 'REPAIR-1');
$mirror->table('store_receipt_product_cost_rows')
->where('row_key', 'repair-me')
->update([
'warehouse_short_name' => '崔桥工厂仓',
'unit_price' => 10,
'product_cost' => 10,
]);
$this->getJson($url)
->assertOk()
->assertJsonPath('summary.pending_rows', 0)
->assertJsonPath('summary.pending_cost_rows', 0)
->assertJsonPath('summary.missing_warehouse_rows', 0)
->assertJsonPath('pagination.total', 0)
->assertJsonCount(0, 'rows');
}
public function test_pending_type_filter_and_csv_export_use_modal_filters(): void
{
DB::connection('business_mirror')->table('store_receipt_product_cost_rows')->insert([
$this->row('both', 'FILTER-A', null, null, 2, null),
$this->row('price', 'FILTER-B', '崔桥工厂仓', null, 3, null),
$this->row('warehouse', 'FILTER-C', '', 10, 1, 10),
$this->row('valid', 'FILTER-D', '崔桥工厂仓', 10, 1, 10),
]);
$this->loginAs();
$this->getJson(route('business.financial-operations.product-costs.pending-details', [
'month' => '2026-09',
'store_name' => 'HX',
'pending_type' => 'missing_warehouse',
]))
->assertOk()
->assertJsonPath('pagination.total', 2)
->assertJsonPath('rows.0.online_order_no', 'FILTER-A')
->assertJsonPath('rows.1.online_order_no', 'FILTER-C');
$this->getJson(route('business.financial-operations.product-costs.pending-details', [
'month' => '2026-09',
'store_name' => 'HX',
'pending_type' => 'both',
]))
->assertOk()
->assertJsonPath('pagination.total', 1)
->assertJsonPath('rows.0.online_order_no', 'FILTER-A');
$response = $this->get(route('business.financial-operations.product-costs.pending-details.export', [
'month' => '2026-09',
'store_name' => 'HX',
'pending_type' => 'missing_price',
]));
$response
->assertOk()
->assertDownload('product-cost-pending-details_2026-09.csv');
$csv = $response->streamedContent();
$this->assertStringStartsWith("\xEF\xBB\xBF", $csv);
$this->assertStringContainsString('线上单号', $csv);
$this->assertStringContainsString('FILTER-A', $csv);
$this->assertStringContainsString('FILTER-B', $csv);
$this->assertStringNotContainsString('FILTER-C', $csv);
$this->assertStringNotContainsString('FILTER-D', $csv);
}
private function row(
string $rowKey,
string $onlineOrderNo,
?string $warehouseShortName,
int|float|null $unitPrice,
int|float $quantity,
int|float|null $productCost,
string $storeName = '京东-HX旗舰店104',
string $reportMonth = '2026-09-01',
?string $productCode = null
): array {
return [
'report_month' => $reportMonth,
'row_key' => $rowKey,
'platform' => '京东账单',
'occurred_date' => $reportMonth,
'store_name' => $storeName,
'online_order_no' => $onlineOrderNo,
'warehouse' => '简尚-崔桥工厂仓',
'warehouse_short_name' => $warehouseShortName,
'product_code' => $productCode ?? 'SKU-' . $rowKey,
'product_quantity' => $quantity,
'unit_price' => $unitPrice,
'product_cost' => $productCost,
'remark' => null,
'imported_at' => now(),
];
}
}