CaiWuXiTong/tests/Unit/EcommerceFinance/JianSunSnapshotRefresherTest.php
WuYongJie 28a62434d2 整合并修正京东钱包账单 (#26)
接入京东充值与消耗账单,修复快照冷启动、刷新依赖、日期边界与标签局部切换。
2026-08-11 12:22:41 +08:00

400 lines
14 KiB
PHP

<?php
namespace Tests\Unit\EcommerceFinance;
use Closure;
use Modules\EcommerceFinance\Repositories\AlibabaBillRepository;
use Modules\EcommerceFinance\Repositories\EdgeBandingRepository;
use Modules\EcommerceFinance\Repositories\GoodsReconciliationRepository;
use Modules\EcommerceFinance\Repositories\InventoryRepository;
use Modules\EcommerceFinance\Repositories\JdWalletBillRepository;
use Modules\EcommerceFinance\Repositories\PinduoduoSpreadBillRepository;
use Modules\EcommerceFinance\Repositories\ProductPriceRepository;
use Modules\EcommerceFinance\Repositories\RawBoardPayablesRepository;
use Modules\EcommerceFinance\Repositories\SupplierPayableRepository;
use Modules\EcommerceFinance\Repositories\SupplierPayableReportRepository;
use Modules\EcommerceFinance\Repositories\TmallTaobaoSpreadBillRepository;
use Modules\EcommerceFinance\Services\JianSunQueryCache;
use Modules\EcommerceFinance\Services\JianSunSnapshotRefresher;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
class JianSunSnapshotRefresherTest extends TestCase
{
public function test_alibaba_filters_are_preserved_during_background_refresh(): void
{
$alibaba = new class extends AlibabaBillRepository {
public array $arguments = [];
public function __construct()
{
}
public function paginate(
?string $shopName = null,
?string $productType = null,
?string $fromDate = null,
?string $toDate = null,
int $page = 1,
int $pageSize = 25,
): array {
$this->arguments = func_get_args();
return ['rows' => [], 'total' => 0];
}
};
$refresher = $this->refresher(alibaba: $alibaba);
$status = $refresher->refresh([
'scope' => 'marketing-account-bills.alibaba.list',
'parameters' => [
'filters' => [
'shop_name' => '测试店铺',
'product_type' => '全站投放',
'from' => '2026-06-30',
'to' => '2026-07-01',
],
'page' => 3,
'limit' => 50,
],
]);
$this->assertSame('fresh', $status);
$this->assertSame(
['测试店铺', '全站投放', '2026-06-30', '2026-07-01', 3, 50],
$alibaba->arguments,
);
}
public function test_pinduoduo_flow_filter_is_preserved_during_background_refresh(): void
{
$pinduoduo = new class extends PinduoduoSpreadBillRepository {
public array $arguments = [];
public function __construct()
{
}
public function paginate(
?string $storeName = null,
?string $fromDate = null,
?string $toDate = null,
?string $flowType = null,
int $page = 1,
int $pageSize = 25
): array {
$this->arguments = func_get_args();
return ['rows' => [], 'total' => 0];
}
};
$refresher = $this->refresher(pinduoduo: $pinduoduo);
$status = $refresher->refresh([
'scope' => 'pinduoduo-bills.list',
'parameters' => [
'filters' => [
'store_name' => '测试店铺',
'from' => '2026-07-01',
'to' => '2026-07-23',
'flow_type' => 'expense',
],
'page' => 3,
'limit' => 50,
],
]);
$this->assertSame('fresh', $status);
$this->assertSame(
['测试店铺', '2026-07-01', '2026-07-23', 'expense', 3, 50],
$pinduoduo->arguments
);
}
public function test_taobao_alipay_filters_are_preserved_during_background_refresh(): void
{
$taobaoAlipay = new class extends TmallTaobaoSpreadBillRepository {
public array $arguments = [];
public function __construct()
{
}
public function paginate(
?string $storeName = null,
?string $fromDate = null,
?string $toDate = null,
?string $flowType = null,
int $page = 1,
int $pageSize = 25
): array {
$this->arguments = func_get_args();
return ['rows' => [], 'total' => 0];
}
};
$refresher = $this->refresher(taobaoAlipay: $taobaoAlipay);
$status = $refresher->refresh([
'scope' => 'taobao-alipay-bills.list',
'parameters' => [
'filters' => [
'store_name' => '测试店铺',
'from' => '2026-07-01',
'to' => '2026-07-23',
'flow_type' => 'income',
],
'page' => 2,
'limit' => 25,
],
]);
$this->assertSame('fresh', $status);
$this->assertSame(
['测试店铺', '2026-07-01', '2026-07-23', 'income', 2, 25],
$taobaoAlipay->arguments
);
}
public function test_inventory_scope_is_available_to_background_refresh(): void
{
$inventory = new class extends InventoryRepository {
public array $arguments = [];
public function __construct()
{
}
public function boardInventoryDetails(array $filters, int $page, int $limit): array
{
$this->arguments = func_get_args();
return ['data' => [], 'total' => 0, 'totals' => []];
}
};
$refresher = $this->refresher(inventory: $inventory);
$status = $refresher->refresh([
'scope' => 'inventory.board-details',
'parameters' => [
'filters' => ['manufacturer' => '测试厂'],
'page' => 2,
'limit' => 50,
],
]);
$this->assertSame('fresh', $status);
$this->assertSame([['manufacturer' => '测试厂'], 2, 50], $inventory->arguments);
}
public function test_raw_board_reconciliation_scope_is_available_to_background_refresh(): void
{
$rawBoardPayables = new class extends RawBoardPayablesRepository {
public array $arguments = [];
public function __construct()
{
}
public function reconciliations(array $filters, int $page, int $limit): array
{
$this->arguments = func_get_args();
return ['data' => [], 'total' => 0, 'totals' => []];
}
};
$refresher = $this->refresher(rawBoardPayables: $rawBoardPayables);
$status = $refresher->refresh([
'scope' => 'raw-board.reconciliations',
'parameters' => [
'filters' => ['supplier' => '测试厂'],
'page' => 2,
'limit' => 50,
],
]);
$this->assertSame('fresh', $status);
$this->assertSame([['supplier' => '测试厂'], 2, 50], $rawBoardPayables->arguments);
}
public function test_jd_wallet_scopes_are_available_to_background_refresh(): void
{
$jdWallet = new class extends JdWalletBillRepository {
public array $calls = [];
public function __construct()
{
}
public function paginateConsumption(
?string $shopName = null,
?string $fromDate = null,
?string $toDate = null,
int $page = 1,
int $pageSize = 25,
): array {
$this->calls['consumption.list'] = func_get_args();
return ['rows' => [], 'total' => 0];
}
public function paginateRecharge(
?string $shopName = null,
?string $fromDate = null,
?string $toDate = null,
int $page = 1,
int $pageSize = 25,
): array {
$this->calls['recharge.list'] = func_get_args();
return ['rows' => [], 'total' => 0];
}
public function summaryConsumption(
?string $shopName = null,
?string $fromDate = null,
?string $toDate = null,
): array {
$this->calls['consumption.summary'] = func_get_args();
return ['amount_total' => 0, 'balance_total' => 0, 'count' => 0];
}
public function summaryRecharge(
?string $shopName = null,
?string $fromDate = null,
?string $toDate = null,
): array {
$this->calls['recharge.summary'] = func_get_args();
return ['amount_total' => 0, 'balance_total' => 0, 'count' => 0];
}
public function shopOptions(): array
{
$this->calls['options'] = [];
return ['测试京东店铺'];
}
};
$refresher = $this->refresher(jdWallet: $jdWallet);
$rechargeStatus = $refresher->refresh([
'scope' => 'jd-wallet-bills.recharge.list',
'parameters' => [
'filters' => [
'store_name' => '测试京东店铺',
'from' => '2026-08-01',
'to' => '2026-08-10',
],
'page' => 2,
'limit' => 50,
],
]);
$consumptionSummaryStatus = $refresher->refresh([
'scope' => 'jd-wallet-bills.consumption.summary',
'parameters' => [
'filters' => [
'store_name' => '测试京东店铺',
'from' => '2026-08-01',
'to' => '2026-08-10',
],
],
]);
$rechargeSummaryStatus = $refresher->refresh([
'scope' => 'jd-wallet-bills.recharge.summary',
'parameters' => [
'filters' => [
'store_name' => '测试京东店铺',
'from' => '2026-08-01',
'to' => '2026-08-10',
],
],
]);
$consumptionListStatus = $refresher->refresh([
'scope' => 'jd-wallet-bills.consumption.list',
'parameters' => [
'filters' => [
'store_name' => '测试京东店铺',
'from' => '2026-08-01',
'to' => '2026-08-10',
],
'page' => 3,
'limit' => 25,
],
]);
$optionsStatus = $refresher->refresh([
'scope' => 'jd-wallet-bills.options',
'parameters' => [],
]);
$this->assertSame('fresh', $rechargeStatus);
$this->assertSame('fresh', $consumptionSummaryStatus);
$this->assertSame('fresh', $rechargeSummaryStatus);
$this->assertSame('fresh', $consumptionListStatus);
$this->assertSame('fresh', $optionsStatus);
$this->assertSame(
['测试京东店铺', '2026-08-01', '2026-08-10', 2, 50],
$jdWallet->calls['recharge.list'],
);
$this->assertSame(
['测试京东店铺', '2026-08-01', '2026-08-10'],
$jdWallet->calls['consumption.summary'],
);
$this->assertSame(
['测试京东店铺', '2026-08-01', '2026-08-10'],
$jdWallet->calls['recharge.summary'],
);
$this->assertSame(
['测试京东店铺', '2026-08-01', '2026-08-10', 3, 25],
$jdWallet->calls['consumption.list'],
);
$this->assertSame([], $jdWallet->calls['options']);
}
private function refresher(
?InventoryRepository $inventory = null,
?AlibabaBillRepository $alibaba = null,
?PinduoduoSpreadBillRepository $pinduoduo = null,
?ProductPriceRepository $productPrices = null,
?RawBoardPayablesRepository $rawBoardPayables = null,
?TmallTaobaoSpreadBillRepository $taobaoAlipay = null,
?SupplierPayableReportRepository $supplierPayableReports = null,
?JdWalletBillRepository $jdWallet = null,
): JianSunSnapshotRefresher {
return new JianSunSnapshotRefresher(
new class extends JianSunQueryCache {
public mixed $value = null;
public function __construct()
{
}
public function refresh(string $scope, array $parameters, Closure $resolver): string
{
$this->value = $resolver();
return 'fresh';
}
},
$this->placeholder(EdgeBandingRepository::class),
$this->placeholder(GoodsReconciliationRepository::class),
$inventory ?? $this->placeholder(InventoryRepository::class),
$alibaba ?? $this->placeholder(AlibabaBillRepository::class),
$pinduoduo ?? $this->placeholder(PinduoduoSpreadBillRepository::class),
$productPrices ?? $this->placeholder(ProductPriceRepository::class),
$rawBoardPayables ?? $this->placeholder(RawBoardPayablesRepository::class),
$taobaoAlipay ?? $this->placeholder(TmallTaobaoSpreadBillRepository::class),
$this->placeholder(SupplierPayableRepository::class),
$supplierPayableReports ?? $this->placeholder(SupplierPayableReportRepository::class),
$jdWallet ?? $this->placeholder(JdWalletBillRepository::class),
);
}
private function placeholder(string $class): object
{
return (new ReflectionClass($class))->newInstanceWithoutConstructor();
}
}