184 lines
7.4 KiB
PHP
184 lines
7.4 KiB
PHP
<?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);
|
||
}
|
||
}
|