185 lines
7.7 KiB
PHP
185 lines
7.7 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\EcommerceFinance;
|
|
|
|
use App\Business\UpstreamBusinessInformation;
|
|
use Closure;
|
|
use Mockery;
|
|
use Modules\EcommerceFinance\Repositories\BusinessInformationMirrorRepository;
|
|
use Modules\EcommerceFinance\Repositories\InstallationDetailMirrorRepository;
|
|
use Modules\EcommerceFinance\Repositories\StoreAccountMirrorRepository;
|
|
use Modules\EcommerceFinance\Repositories\StoreReportRepository;
|
|
use Modules\EcommerceFinance\Services\UpstreamQueryCache;
|
|
use Modules\EcommerceFinance\Services\UpstreamQueryCacheFactory;
|
|
use Tests\TestCase;
|
|
|
|
class UpstreamBusinessInformationTest extends TestCase
|
|
{
|
|
/**
|
|
* @dataProvider businessInformationPages
|
|
*/
|
|
public function test_local_direct_page_resolver_passes_pagination_to_its_fixed_snapshot(
|
|
string $section,
|
|
string $page,
|
|
string $scope,
|
|
): void {
|
|
config(['upstreams.local_configuration.enabled' => true]);
|
|
$cache = new class extends UpstreamQueryCache {
|
|
public array $calls = [];
|
|
|
|
public function __construct()
|
|
{
|
|
}
|
|
|
|
public function remember(string $scope, array $parameters, Closure $resolver): mixed
|
|
{
|
|
$this->calls[] = compact('scope', 'parameters');
|
|
|
|
return $resolver();
|
|
}
|
|
};
|
|
|
|
$caches = new class($cache) extends UpstreamQueryCacheFactory {
|
|
public function __construct(private readonly UpstreamQueryCache $cache)
|
|
{
|
|
}
|
|
|
|
public function forSource(string $source): UpstreamQueryCache
|
|
{
|
|
return $this->cache;
|
|
}
|
|
};
|
|
|
|
$mirror = Mockery::mock(BusinessInformationMirrorRepository::class);
|
|
$mirror->shouldReceive('ready')->once()->with($scope)->andReturnFalse();
|
|
|
|
$information = new class($caches, $mirror, Mockery::mock(InstallationDetailMirrorRepository::class)) extends UpstreamBusinessInformation {
|
|
public array $snapshots = [];
|
|
|
|
public function snapshot(string $scope, array $parameters): array
|
|
{
|
|
$this->snapshots[] = compact('scope', 'parameters');
|
|
|
|
return ['data' => [], 'total' => 0];
|
|
}
|
|
};
|
|
|
|
$this->app['request']->merge(['page' => 3]);
|
|
|
|
$paginator = $information->paginate($section, $page, 25);
|
|
$expected = ['scope' => $scope, 'parameters' => ['page' => 3, 'perPage' => 25]];
|
|
|
|
$this->assertSame(3, $paginator->currentPage());
|
|
$this->assertSame($expected, $cache->calls[0]);
|
|
$this->assertSame($expected, $information->snapshots[0]);
|
|
}
|
|
|
|
/**
|
|
* @dataProvider businessInformationPages
|
|
*/
|
|
public function test_ready_business_mirror_is_used_without_registering_a_page_snapshot(
|
|
string $section,
|
|
string $page,
|
|
string $scope,
|
|
): void {
|
|
config(['operations_replica.enabled' => false, 'upstreams.stored_configuration.enabled' => false]);
|
|
$cache = new class extends UpstreamQueryCache {
|
|
public function __construct() {}
|
|
|
|
public function remember(string $scope, array $parameters, Closure $resolver): mixed
|
|
{
|
|
throw new \RuntimeException('镜像就绪后不应再读取分页快照。');
|
|
}
|
|
};
|
|
$caches = new class($cache) extends UpstreamQueryCacheFactory {
|
|
public function __construct(private readonly UpstreamQueryCache $cache) {}
|
|
|
|
public function forSource(string $source): UpstreamQueryCache { return $this->cache; }
|
|
};
|
|
$mirror = Mockery::mock(BusinessInformationMirrorRepository::class);
|
|
$mirror->shouldReceive('ready')->once()->with($scope)->andReturnTrue();
|
|
$mirror->shouldReceive('paginate')->once()->with($scope, 2, 25, [])->andReturn([
|
|
'data' => [['id' => 10]],
|
|
'total' => 51,
|
|
]);
|
|
|
|
$this->app['request']->merge(['page' => 2]);
|
|
$paginator = (new UpstreamBusinessInformation($caches, $mirror, Mockery::mock(InstallationDetailMirrorRepository::class)))
|
|
->paginate($section, $page, 25);
|
|
|
|
$this->assertSame(2, $paginator->currentPage());
|
|
$this->assertSame(51, $paginator->total());
|
|
$this->assertSame(10, $paginator->items()[0]->id);
|
|
}
|
|
|
|
public function test_bootstrap_without_mirror_explains_shared_connection_instead_of_requesting_upstream_credentials(): void
|
|
{
|
|
config(['system_database.mode' => 'bootstrap', 'upstreams.local_configuration.enabled' => false]);
|
|
$caches = Mockery::mock(UpstreamQueryCacheFactory::class);
|
|
$caches->shouldNotReceive('forSource');
|
|
$mirror = Mockery::mock(BusinessInformationMirrorRepository::class);
|
|
$mirror->shouldReceive('ready')->once()->with('store-information.read')->andReturnFalse();
|
|
$this->expectException(\Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException::class);
|
|
$this->expectExceptionMessage('无需另配上游 SQL Server');
|
|
(new UpstreamBusinessInformation($caches, $mirror, Mockery::mock(InstallationDetailMirrorRepository::class)))
|
|
->paginate('store-management', 'basic-information');
|
|
}
|
|
|
|
public function test_subject_operating_report_hides_income_months_without_data_by_default(): void
|
|
{
|
|
$mirror = Mockery::mock(BusinessInformationMirrorRepository::class);
|
|
$mirror->shouldReceive('ready')->with('store-information.read')->andReturnTrue();
|
|
$mirror->shouldReceive('allStores')->andReturn([['erp_store_name' => '测试店铺']]);
|
|
$mirror->shouldReceive('ready')->with('company-information.read')->andReturnTrue();
|
|
$mirror->shouldReceive('companiesByNames')->andReturn([]);
|
|
|
|
$storeReports = Mockery::mock(StoreReportRepository::class);
|
|
$storeReports->shouldReceive('rows')->andReturn([[
|
|
'entity' => '测试主体',
|
|
'company_type' => '店铺-普通公司',
|
|
'rolling_12m_income' => 188.5,
|
|
'income_01' => null,
|
|
'income_02' => 88.5,
|
|
'income_03' => 0.0,
|
|
'income_04' => null,
|
|
'income_05' => null,
|
|
'income_06' => null,
|
|
'income_07' => null,
|
|
'income_08' => null,
|
|
'income_09' => null,
|
|
'income_10' => null,
|
|
'income_11' => null,
|
|
'income_12' => null,
|
|
]]);
|
|
$storeAccounts = Mockery::mock(StoreAccountMirrorRepository::class);
|
|
$storeAccounts->shouldReceive('ownershipByStoreName')->andReturn([]);
|
|
|
|
$information = new UpstreamBusinessInformation(
|
|
Mockery::mock(UpstreamQueryCacheFactory::class),
|
|
$mirror,
|
|
Mockery::mock(InstallationDetailMirrorRepository::class),
|
|
$storeReports,
|
|
$storeAccounts,
|
|
);
|
|
|
|
$paginator = $information->paginate('company-management', 'subject-operating-report', 50);
|
|
|
|
// income_02 有金额、income_03 为 0 都算有数据,其余空月份默认隐藏。
|
|
$this->assertSame(
|
|
['income_01', 'income_04', 'income_05', 'income_06', 'income_07', 'income_08', 'income_09', 'income_10', 'income_11', 'income_12'],
|
|
$this->app['request']->attributes->get('subject-operating-report.default_hidden_columns'),
|
|
);
|
|
$this->assertSame(1, $paginator->total());
|
|
$this->assertSame('测试主体', $paginator->items()[0]->entity);
|
|
}
|
|
|
|
public static function businessInformationPages(): array
|
|
{
|
|
return [
|
|
'company' => ['company-management', 'basic-information', 'company-information.read'],
|
|
'store' => ['store-management', 'basic-information', 'store-information.read'],
|
|
'trademark' => ['trademark-management', 'information', 'trademark-information.read'],
|
|
];
|
|
}
|
|
}
|