'蔬菜', 'parent_id' => 0, 'sort' => 0, 'status' => 1]); $meatRoot = ProductCategoryModel::create(['name' => '肉禽蛋', 'parent_id' => 0, 'sort' => 1, 'status' => 1]); $level = CustomerLevelModel::factory()->create(); $store = StoreModel::factory()->create(['level_id' => $level->id]); $veg = ProductModel::factory()->create(['status' => ProductModel::STATUS_ON, 'category_id' => $vegRoot->id, 'cost_price' => '5.00']); $meat = ProductModel::factory()->create(['status' => ProductModel::STATUS_ON, 'category_id' => $meatRoot->id, 'cost_price' => '20.00']); $this->actingAsMiniUser(UserModel::factory()->forStore($store->id)->create()); $this->postJson('/mini/order', ['items' => [ ['product_id' => $veg->id, 'quantity' => 2], ['product_id' => $meat->id, 'quantity' => 1], ]])->assertJsonPath('success', true); // 接单后生成采购单 StoreOrderModel::query()->update(['status' => StoreOrderModel::STATUS_SUMMARIZED]); $this->actingAsSysUser(); $this->postJson('/purchase/order/generate', ['purchase_date' => now()->toDateString()]) ->assertJsonPath('success', true); return PurchaseOrderModel::first(); } /** xlsx 导出:正确 Content-Type + 中文文件名 RFC 5987 编码 */ public function test_export_xlsx_with_encoded_chinese_filename(): void { $purchase = $this->buildPurchaseWithItems(); $this->actingAsSysUser(); $response = $this->get("/purchase/order/{$purchase->id}/export"); $response->assertOk(); $this->assertStringContainsString( 'spreadsheetml', (string) $response->headers->get('Content-Type'), 'xlsx 应返回电子表格 Content-Type' ); $disposition = (string) $response->headers->get('Content-Disposition'); // Symfony 输出小写 utf-8''(RFC 5987),大小写不敏感断言 $this->assertMatchesRegularExpression("/filename\*=utf-8''/i", $disposition, '中文文件名应走 RFC 5987 编码'); $this->assertStringContainsString(rawurlencode('采购单'), $disposition); } /** 采购单不存在 → 拒绝 */ public function test_export_missing_purchase_rejected(): void { $this->actingAsSysUser(); $this->get('/purchase/order/99999/export') ->assertJsonPath('success', false); } /** 无 purchase.order.export 权限点 → 拦截 */ public function test_export_requires_export_permission(): void { $purchase = $this->buildPurchaseWithItems(); // 仅持有查询权限的用户 $this->actingAsSysUser(['purchase.order.query']); $response = $this->get("/purchase/order/{$purchase->id}/export"); $this->assertFalse($response->json('success'), '缺少权限点应被拦截'); } }