回筐导出

This commit is contained in:
liu
2026-08-15 00:14:19 +08:00
parent 7c3f6147ac
commit cd35213ae6
7 changed files with 459 additions and 3 deletions
+140
View File
@@ -2,6 +2,7 @@
namespace Tests\Feature;
use App\Exports\ContainerReturnExport;
use App\Models\BillModel;
use App\Models\ContainerReturnModel;
use App\Models\CustomerLevelModel;
@@ -12,6 +13,7 @@ use App\Models\StoreModel;
use App\Models\StoreOrderModel;
use App\Models\UserModel;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;
use Modules\SystemTool\Services\SysSiteConfigService;
/**
@@ -182,4 +184,142 @@ class ContainerReturnTest extends ProcurementTestCase
])->assertJsonPath('success', false);
$this->deleteJson('/recon/container-return/1')->assertJsonPath('success', false);
}
/** 造一条压回筐记录(直接入库并指定记录时间,用于导出区间/合并断言) */
private function makeRecord(StoreModel $store, string $amount, string $createdAt): void
{
DB::table('container_return')->insert([
'store_id' => $store->id,
'bill_id' => 0,
'box_num' => 0,
'tray_num' => 0,
'box_price' => '5.00',
'tray_price' => '20.00',
'amount' => $amount,
'operator_id' => 0,
'created_at' => $createdAt,
'updated_at' => $createdAt,
]);
}
/** 汇总导出:行=日期(区间内逐日),列=门店,同日记录合并,无记录填 0,含行/列合计 */
public function test_export_matrix_merges_same_day_and_zero_fills(): void
{
$storeA = StoreModel::factory()->create();
$storeB = StoreModel::factory()->create();
// 08-01:A 两条同日记录合并(+55 压筐、-10 回筐 = 45),B 一条 -20
$this->makeRecord($storeA, '55.00', '2026-08-01 09:00:00');
$this->makeRecord($storeA, '-10.00', '2026-08-01 15:30:00');
$this->makeRecord($storeB, '-20.00', '2026-08-01 10:00:00');
// 08-02:仅 A +5B 无记录填 0
$this->makeRecord($storeA, '5.00', '2026-08-02 08:00:00');
// 区间外记录不参与
$this->makeRecord($storeB, '30.00', '2026-08-04 08:00:00');
$this->actingAsSysUser();
Excel::fake();
$this->get('/recon/container-return/export?start_date=2026-08-01&end_date=2026-08-03')->assertOk();
Excel::assertDownloaded(
'回筐记录_2026-08-01_2026-08-03.xlsx',
static function (ContainerReturnExport $export) use ($storeA, $storeB): bool {
$rows = $export->collection()->values();
// 标题1 + 范围1 + 空行1 + 列头1 + 日期3 + 合计1 = 8 行
if ($rows->count() !== 8) {
return false;
}
// 列头:日期 + 门店(未选门店时取区间内有记录的门店,ID 升序)+ 合计
if ($rows[3] !== ['日期', $storeA->name, $storeB->name, '合计']) {
return false;
}
// 08-01:同日合并 55-10=45B -20,行合计 25
if ($rows[4] !== ['2026-08-01', 45.0, -20.0, 25.0]) {
return false;
}
// 08-02A 5、B 无记录填 0,行合计 5
if ($rows[5] !== ['2026-08-02', 5.0, 0.0, 5.0]) {
return false;
}
// 08-03:当日全部无记录,整行填 0
if ($rows[6] !== ['2026-08-03', 0.0, 0.0, 0.0]) {
return false;
}
// 合计行:A 列 50、B 列 -20、总计 30
return $rows[7] === ['合计', 50.0, -20.0, 30.0];
}
);
}
/** 指定门店导出:仅所选门店成列,未选门店记录忽略;所选门店无记录整列填 0 */
public function test_export_filters_by_selected_stores(): void
{
$storeA = StoreModel::factory()->create();
$storeB = StoreModel::factory()->create();
$storeC = StoreModel::factory()->create();
$this->makeRecord($storeA, '55.00', '2026-08-01 09:00:00');
$this->makeRecord($storeB, '-20.00', '2026-08-01 10:00:00');
// C 区间内无记录,但被选中 → 整列填 0
$this->actingAsSysUser();
Excel::fake();
$this->get('/recon/container-return/export?start_date=2026-08-01&end_date=2026-08-02&store_ids=' . $storeA->id . ',' . $storeC->id)
->assertOk();
Excel::assertDownloaded(
'回筐记录_2026-08-01_2026-08-02.xlsx',
static function (ContainerReturnExport $export) use ($storeA, $storeC): bool {
$rows = $export->collection()->values();
// 列头仅含所选门店(B 的记录被忽略)
if ($rows[3] !== ['日期', $storeA->name, $storeC->name, '合计']) {
return false;
}
// 08-01A 55、C 填 008-02 全 0
if ($rows[4] !== ['2026-08-01', 55.0, 0.0, 55.0]) {
return false;
}
if ($rows[5] !== ['2026-08-02', 0.0, 0.0, 0.0]) {
return false;
}
return $rows[6] === ['合计', 55.0, 0.0, 55.0];
}
);
}
/** 参数校验:缺少日期 / 结束早于开始 / 区间超 366 天 → 拒绝 */
public function test_export_invalid_params_rejected(): void
{
$this->actingAsSysUser();
$this->get('/recon/container-return/export')
->assertJsonPath('success', false);
$this->get('/recon/container-return/export?start_date=2026-08-10&end_date=2026-08-01')
->assertJsonPath('success', false);
$this->get('/recon/container-return/export?start_date=2026-01-01&end_date=2027-06-30')
->assertJsonPath('success', false);
}
/** 区间内无记录且未选门店 → 拒绝 */
public function test_export_empty_range_rejected(): void
{
$this->actingAsSysUser();
$this->get('/recon/container-return/export?start_date=2026-08-01&end_date=2026-08-03')
->assertJsonPath('success', false);
}
/** 无 recon.containerReturn.export 权限点 → 拦截 */
public function test_export_requires_export_permission(): void
{
// 先建一个占位用户:每个测试方法内首个系统用户自增 id=1,
// SysAccessToken::can() 对 tokenable_id==1(超管)放行全部权限,会绕过 abilities 校验
$this->actingAsSysUser();
// 仅持有查询权限的用户
$this->actingAsSysUser(['recon.containerReturn.query']);
$response = $this->get('/recon/container-return/export?start_date=2026-08-01&end_date=2026-08-03');
$this->assertFalse($response->json('success'), '缺少权限点应被拦截');
}
}