|
|
@@ -0,0 +1,126 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace Tests\Integration;
|
|
|
+
|
|
|
+use App\Http\Controllers\admin\CompanyReport;
|
|
|
+use App\Http\Controllers\agent\CompanyReportController;
|
|
|
+use App\Models\Agent\Agent;
|
|
|
+use App\Services\CompanyMonthlyReportService;
|
|
|
+use Carbon\Carbon;
|
|
|
+use Illuminate\Database\Schema\Blueprint;
|
|
|
+use Illuminate\Filesystem\FilesystemManager;
|
|
|
+use Illuminate\Http\Request;
|
|
|
+use Illuminate\Http\UploadedFile;
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
+use Illuminate\Support\Facades\Schema;
|
|
|
+use PHPUnit\Framework\TestCase;
|
|
|
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
|
|
+use Tests\Support\AgentTestEnvironment;
|
|
|
+
|
|
|
+/** 公司营业报表:总后台按月上传 / 重新上传,入股代理查看和下载。 */
|
|
|
+class CompanyMonthlyReportTest extends TestCase
|
|
|
+{
|
|
|
+ use AgentTestEnvironment { setUp as environmentSetUp; tearDown as environmentTearDown; }
|
|
|
+
|
|
|
+ private string $root;
|
|
|
+ private array $temp = [];
|
|
|
+
|
|
|
+ protected function setUp(): void
|
|
|
+ {
|
|
|
+ $this->environmentSetUp();
|
|
|
+ Carbon::setTestNow('2026-11-12 10:00:00');
|
|
|
+ (require dirname(__DIR__, 2) . '/database/migrations/2026_11_12_120000_create_company_monthly_reports.php')->up();
|
|
|
+ Schema::create('admin', function (Blueprint $t) { $t->id(); $t->string('username'); });
|
|
|
+ DB::table('admin')->insert([['id' => 1, 'username' => 'root'], ['id' => 2, 'username' => 'finance']]);
|
|
|
+ $this->root = sys_get_temp_dir() . '/company-report-' . bin2hex(random_bytes(4));
|
|
|
+ config(['filesystems.disks.local' => ['driver' => 'local', 'root' => $this->root]]);
|
|
|
+ $this->app->instance('filesystem', new FilesystemManager($this->app));
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function tearDown(): void
|
|
|
+ {
|
|
|
+ Carbon::setTestNow();
|
|
|
+ foreach ($this->temp as $file) @unlink($file);
|
|
|
+ if (is_dir($this->root)) { array_map('unlink', glob($this->root . '/company-reports/*') ?: []); @rmdir($this->root . '/company-reports'); @rmdir($this->root); }
|
|
|
+ $this->environmentTearDown();
|
|
|
+ }
|
|
|
+
|
|
|
+ private function excel(string $name, string $head = "PK\x03\x04"): UploadedFile
|
|
|
+ {
|
|
|
+ $path = tempnam(sys_get_temp_dir(), 'xls');
|
|
|
+ file_put_contents($path, $head . random_bytes(32));
|
|
|
+ $this->temp[] = $path;
|
|
|
+ return new UploadedFile($path, $name, null, null, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ private function admin(string $action, array $params = [], array $files = [], int $adminId = 1)
|
|
|
+ {
|
|
|
+ $request = Request::create('/admin/companyReport/' . $action, $files ? 'POST' : 'GET', $params, [], $files);
|
|
|
+ $request->user = (object) ['id' => $adminId];
|
|
|
+ $this->app->instance('request', $request);
|
|
|
+ $response = (new CompanyReport())->{$action === '' ? 'index' : $action}($request, new CompanyMonthlyReportService());
|
|
|
+ return $response instanceof BinaryFileResponse ? $response : $response->getData(true);
|
|
|
+ }
|
|
|
+
|
|
|
+ private function agentCall(Agent $agent, string $action, array $params = [])
|
|
|
+ {
|
|
|
+ $request = Request::create('/agent/company-reports', 'GET', $params);
|
|
|
+ $request->attributes->set('agent', $agent);
|
|
|
+ $this->app->instance('request', $request);
|
|
|
+ $response = (new CompanyReportController())->{$action}($request, new CompanyMonthlyReportService());
|
|
|
+ return $response instanceof BinaryFileResponse ? $response : $response->getData(true);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_admin_uploads_last_month_once_and_reuploads_through_edit(): void
|
|
|
+ {
|
|
|
+ $this->assertSame('2026-10', CompanyMonthlyReportService::allowedMonth());
|
|
|
+ $wrong = $this->admin('create', ['month' => '2026-11'], ['file' => $this->excel('11月.xlsx')]);
|
|
|
+ $this->assertSame('只能上传已结束月份的报表(2026-10 及以前)', $wrong['msg']);
|
|
|
+ $this->assertSame('请上传 Excel 文件(.xlsx 或 .xls)', $this->admin('create', ['month' => '2026-10'], ['file' => $this->excel('a.pdf')])['msg']);
|
|
|
+ $this->assertSame('请上传 Excel 文件(.xlsx 或 .xls)', $this->admin('create', ['month' => '2026-10'], ['file' => $this->excel('fake.xlsx', 'abcd')])['msg'], 'content must be excel');
|
|
|
+
|
|
|
+ $encrypted = $this->admin('create', ['month' => '2026-08'], ['file' => $this->excel('8月-加密.xlsx', "\xD0\xCF\x11\xE0")]);
|
|
|
+ $this->assertSame([0, '2026-08'], [$encrypted['code'], $encrypted['data']['month'] ?? null], 'a missed earlier month can be added; password-protected xlsx is OLE');
|
|
|
+ $created = $this->admin('create', ['month' => '2026-10'], ['file' => $this->excel('10月营业报表.xlsx')]);
|
|
|
+ $this->assertSame(0, $created['code'], $created['msg']);
|
|
|
+ $this->assertSame(['2026-10', '10月营业报表.xlsx'], [$created['data']['month'], $created['data']['file_name']]);
|
|
|
+ $this->assertArrayNotHasKey('file_path', $created['data']);
|
|
|
+ $this->assertSame('2026-10 的报表已存在,请在列表中编辑重新上传', $this->admin('create', ['month' => '2026-10'], ['file' => $this->excel('again.xlsx')])['msg']);
|
|
|
+ $oldPath = DB::table('company_monthly_reports')->where('month', '2026-10')->value('file_path');
|
|
|
+ $this->assertFileExists($this->root . '/' . $oldPath);
|
|
|
+
|
|
|
+ $updated = $this->admin('update', ['id' => $created['data']['id']], ['file' => $this->excel('10月营业报表-修正.xls', "\xD0\xCF\x11\xE0")], 2);
|
|
|
+ $this->assertSame(0, $updated['code'], $updated['msg']);
|
|
|
+ $this->assertSame(['2026-10', '10月营业报表-修正.xls'], [$updated['data']['month'], $updated['data']['file_name']]);
|
|
|
+ $this->assertFileDoesNotExist($this->root . '/' . $oldPath, 'old file is removed after re-upload');
|
|
|
+
|
|
|
+ $list = $this->admin('', [])['data'];
|
|
|
+ $this->assertSame([2, '2026-10'], [$list['total'], $list['allowed_month']]);
|
|
|
+ $this->assertSame(['2026-10', '2026-08'], array_column($list['list'], 'month'));
|
|
|
+ $this->assertSame(['root', 'finance'], [$list['list'][0]['created_by_name'], $list['list'][0]['updated_by_name']]);
|
|
|
+ $file = $this->admin('download', ['id' => $created['data']['id']]);
|
|
|
+ $this->assertInstanceOf(BinaryFileResponse::class, $file);
|
|
|
+ $this->assertStringContainsString('attachment', (string) $file->headers->get('content-disposition'));
|
|
|
+ $this->assertSame('数据不存在', $this->admin('download', ['id' => 999])['msg']);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_only_equity_agents_can_list_and_download(): void
|
|
|
+ {
|
|
|
+ Carbon::setTestNow('2026-10-05 10:00:00');
|
|
|
+ $this->admin('create', ['month' => '2026-09'], ['file' => $this->excel('9月.xlsx')]);
|
|
|
+ Carbon::setTestNow('2026-11-12 10:00:00');
|
|
|
+ $id = $this->admin('create', ['month' => '2026-10'], ['file' => $this->excel('10月.xlsx')])['data']['id'];
|
|
|
+
|
|
|
+ $equity = $this->agent(Agent::TYPE_EQUITY);
|
|
|
+ $list = $this->agentCall($equity, 'index');
|
|
|
+ $this->assertSame(0, $list['code'], $list['msg']);
|
|
|
+ $this->assertSame(['2026-10', '2026-09'], array_column($list['data']['list'], 'month'), 'newest month first');
|
|
|
+ $this->assertArrayNotHasKey('created_by', $list['data']['list'][0], 'admin info stays in the admin');
|
|
|
+ $this->assertSame(['2026-09'], array_column($this->agentCall($equity, 'index', ['end_month' => '2026-09'])['data']['list'], 'month'));
|
|
|
+ $this->assertInstanceOf(BinaryFileResponse::class, $this->agentCall($equity, 'download', ['id' => $id]));
|
|
|
+
|
|
|
+ $joint = $this->agent();
|
|
|
+ $this->assertSame('仅入股代理可查看公司营业报表', $this->agentCall($joint, 'index')['msg']);
|
|
|
+ $this->assertSame('仅入股代理可查看公司营业报表', $this->agentCall($joint, 'download', ['id' => $id])['msg']);
|
|
|
+ }
|
|
|
+}
|