CaiWuXiTong/tests/Feature/Business/FundForecastPageTest.php

184 lines
7.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Tests\Feature\Business;
use App\Business\FundForecastWorkbookImporter;
use App\Models\Auth\Permission;
use App\Models\Business\FundForecast;
use Illuminate\Http\UploadedFile;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Tests\Feature\FeatureTestCase;
class FundForecastPageTest extends FeatureTestCase
{
protected function setUp(): void
{
parent::setUp();
$this->user->attachPermission(
Permission::where('name', 'read-admin-panel')->firstOrFail(),
);
}
public function testPageReplacesLegacyTableWithWorkbookGroupsAndFilters(): void
{
FundForecast::create([
'company_id' => $this->company->id,
'budget_month' => '2026-09',
'company_name' => '测试资金公司',
'region' => '华东',
'report_status' => '待审核',
'balance_bank' => 100,
'balance_jd' => 20,
'income_jd' => 80,
'income_other' => 20,
'expense_supplier_goods' => 40,
'expense_salary' => 10,
'previous_month_balance' => 30,
]);
$response = $this->loginAs()->get(route('business.pages.show', [
'section' => 'fund-management',
'page' => 'fund-forecast',
]));
$response
->assertOk()
->assertSeeText('公司总数')
->assertSeeText('预测月份')
->assertSeeText('所属区域')
->assertSeeText('填报状态')
->assertSeeText('测试资金公司')
->assertSeeText('淘系支付宝')
->assertSeeText('店铺花费(暂估10%)')
->assertSeeText('上月末总余额')
->assertSeeText('缺口/盈余')
->assertSee('data-group="balance"', false)
->assertSee('data-group="income"', false)
->assertSee('data-group="expense"', false)
->assertDontSeeText('店铺余额(预算)')
->assertDontSeeText('银行余额(实际)');
$row = FundForecast::firstOrFail();
$this->assertSame('120.00', $row->previous_month_balance);
$this->assertSame('100.00', $row->forecast_month_income);
$this->assertSame('50.00', $row->forecast_month_expense);
$this->assertSame('170.00', $row->gap_surplus);
$this->assertFalse($row->has_gap);
$this->assertSame($this->company->id, $row->company_id);
}
public function testCompanyFilterOnlyShowsMatchingForecast(): void
{
foreach (['目标公司', '其他公司'] as $companyName) {
FundForecast::create([
'company_id' => $this->company->id,
'budget_month' => '2026-09',
'company_name' => $companyName,
]);
}
$this->loginAs()->get(route('business.pages.show', [
'section' => 'fund-management',
'page' => 'fund-forecast',
'company_name' => '目标',
]))
->assertOk()
->assertSeeText('目标公司')
->assertDontSeeText('其他公司');
}
public function testImporterUnderstandsTwoRowWorkbookHeaders(): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->fromArray([
['预策月份', '公司名称', '余额', null, '收入', null, '支出', null, '汇总', null, null, null, null],
[null, null, '京东', '抖音', '京东', '其他收入', '供应商货款', '工资', '上月末总余额', '预策本月收入', '预策本月支付', '缺口/盈余', '是否有缺口'],
['2026年9月', '导入测试公司', 12, 3, 100, 20, 30, 10, 50, 999, 999, -999, '是'],
]);
$path = tempnam(sys_get_temp_dir(), 'fund-forecast-');
(new Xlsx($spreadsheet))->save($path);
try {
$result = app(FundForecastWorkbookImporter::class)->import(
new UploadedFile($path, '资金预测表.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', null, true),
(int) $this->company->id,
);
} finally {
@unlink($path);
}
$this->assertSame(['created' => 1, 'updated' => 0], $result);
$row = FundForecast::where('company_name', '导入测试公司')->firstOrFail();
$this->assertSame('2026-09', $row->budget_month);
$this->assertSame('12.00', $row->balance_jd);
$this->assertSame('100.00', $row->income_jd);
$this->assertSame('15.00', $row->previous_month_balance);
$this->assertSame('120.00', $row->forecast_month_income);
$this->assertSame('40.00', $row->forecast_month_expense);
$this->assertSame('95.00', $row->gap_surplus);
$this->assertFalse($row->has_gap);
$this->assertSame('待审核', $row->report_status);
}
public function testTemplateDownloadContainsImportableTwoRowHeaders(): void
{
$response = $this->loginAs()->get(route('business.fund-forecast.template'));
$response
->assertOk()
->assertHeader('content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
$path = tempnam(sys_get_temp_dir(), 'fund-forecast-template-');
file_put_contents($path, $response->streamedContent());
try {
$sheet = IOFactory::load($path)->getActiveSheet();
$this->assertSame('资金预测表', $sheet->getTitle());
$this->assertSame('预测月份', $sheet->getCell('A1')->getValue());
$this->assertSame('公司名称', $sheet->getCell('B1')->getValue());
$this->assertSame('余额', $sheet->getCell('C1')->getValue());
$this->assertSame('银行', $sheet->getCell('C2')->getValue());
$this->assertSame('汇总', $sheet->getCell('AA1')->getValue());
$this->assertSame('是否有缺口', $sheet->getCell('AE2')->getValue());
$this->assertSame('=SUM(C3:H3)', $sheet->getCell('AA3')->getValue());
$this->assertSame('=SUM(I3:N3)', $sheet->getCell('AB3')->getValue());
$this->assertSame('=SUM(O3:Z3)', $sheet->getCell('AC3')->getValue());
$this->assertSame('=AA3+AB3-AC3', $sheet->getCell('AD3')->getValue());
$this->assertSame('=IF(AD3<0,"是","否")', $sheet->getCell('AE3')->getValue());
$this->assertSame('C3', $sheet->getFreezePane());
} finally {
@unlink($path);
}
}
public function testSummaryFieldsAreRecalculatedAndNegativeGapIsMarked(): void
{
$row = FundForecast::create([
'company_id' => $this->company->id,
'budget_month' => '2026-09',
'company_name' => '缺口测试公司',
'balance_bank' => 10,
'balance_wechat' => 5,
'income_other' => 20,
'expense_supplier_goods' => 50,
'previous_month_balance' => 999,
'forecast_month_income' => 999,
'forecast_month_expense' => 999,
'gap_surplus' => 999,
'has_gap' => false,
]);
$this->assertSame('15.00', $row->previous_month_balance);
$this->assertSame('20.00', $row->forecast_month_income);
$this->assertSame('50.00', $row->forecast_month_expense);
$this->assertSame('-15.00', $row->gap_surplus);
$this->assertTrue($row->has_gap);
}
}