回筐导出
This commit is contained in:
@@ -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 +5,B 无记录填 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=45,B -20,行合计 25
|
||||
if ($rows[4] !== ['2026-08-01', 45.0, -20.0, 25.0]) {
|
||||
return false;
|
||||
}
|
||||
// 08-02:A 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-01:A 55、C 填 0;08-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'), '缺少权限点应被拦截');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user