73 lines
3.5 KiB
PHP
73 lines
3.5 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\EcommerceFinance;
|
|
|
|
use Carbon\CarbonImmutable;
|
|
use Mockery;
|
|
use Modules\EcommerceFinance\Repositories\BusinessInformationMirrorRepository;
|
|
use Modules\EcommerceFinance\Repositories\StoreReportRepository;
|
|
use Modules\EcommerceFinance\Services\InternalFlowProjection;
|
|
use Tests\TestCase;
|
|
|
|
class InternalFlowProjectionTest extends TestCase
|
|
{
|
|
public function testForecastUsesPreviousMonthIncomeAggregatedByEntity(): void
|
|
{
|
|
$stores = [
|
|
['erp_store_name' => '店铺A', 'company_name' => '原主体'],
|
|
['erp_store_name' => '店铺B', 'company_name' => '原主体'],
|
|
];
|
|
$reportStores = array_map(
|
|
static fn (array $store): array => $store + ['system_company_name' => $store['company_name']],
|
|
$stores,
|
|
);
|
|
$businessInformation = Mockery::mock(BusinessInformationMirrorRepository::class);
|
|
$businessInformation->shouldReceive('receivingAccountStores')->once()->andReturn($stores);
|
|
$storeReports = Mockery::mock(StoreReportRepository::class);
|
|
$storeReports->shouldReceive('rows')
|
|
->once()
|
|
->with($reportStores, 2026, [])
|
|
->andReturn([
|
|
['entity' => '示例甲有限公司', 'income_10' => 1000000],
|
|
['entity' => '示例甲有限公司', 'income_10' => 250000.5],
|
|
['entity' => '示例乙有限公司', 'income_10' => 0],
|
|
['entity' => '示例丙有限公司', 'income_10' => null],
|
|
['entity' => '', 'income_10' => 999999],
|
|
]);
|
|
|
|
$projection = new InternalFlowProjection($businessInformation, $storeReports);
|
|
$result = $projection->forMonth(CarbonImmutable::create(2026, 11, 9, 10, 0, 0, 'Asia/Shanghai'));
|
|
|
|
$this->assertSame('2026-11', $result['forecast_month']);
|
|
$this->assertSame('11月', $result['forecast_month_label']);
|
|
$this->assertSame('2026-10', $result['source_month']);
|
|
$this->assertSame('10月', $result['source_month_label']);
|
|
$this->assertEqualsWithDelta(1250000.5, $result['sales_by_company']['示例甲有限公司'], 0.000001);
|
|
$this->assertSame(0.0, $result['sales_by_company']['示例乙有限公司']);
|
|
$this->assertNull($result['sales_by_company']['示例丙有限公司']);
|
|
$this->assertArrayNotHasKey('', $result['sales_by_company']);
|
|
}
|
|
|
|
public function testJanuaryForecastReadsDecemberOfPreviousYear(): void
|
|
{
|
|
$stores = [['erp_store_name' => '店铺A', 'company_name' => '示例甲有限公司']];
|
|
$reportStores = [
|
|
$stores[0] + ['system_company_name' => $stores[0]['company_name']],
|
|
];
|
|
$businessInformation = Mockery::mock(BusinessInformationMirrorRepository::class);
|
|
$businessInformation->shouldReceive('receivingAccountStores')->once()->andReturn($stores);
|
|
$storeReports = Mockery::mock(StoreReportRepository::class);
|
|
$storeReports->shouldReceive('rows')
|
|
->once()
|
|
->with($reportStores, 2025, [])
|
|
->andReturn([['entity' => '示例甲有限公司', 'income_12' => 880000]]);
|
|
|
|
$projection = new InternalFlowProjection($businessInformation, $storeReports);
|
|
$result = $projection->forMonth(CarbonImmutable::create(2026, 1, 5, 12, 0, 0, 'Asia/Shanghai'));
|
|
|
|
$this->assertSame('2026-01', $result['forecast_month']);
|
|
$this->assertSame('2025-12', $result['source_month']);
|
|
$this->assertEqualsWithDelta(880000.0, $result['sales_by_company']['示例甲有限公司'], 0.000001);
|
|
}
|
|
}
|