181 lines
7.2 KiB
PHP
181 lines
7.2 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\EcommerceFinance;
|
|
|
|
use Modules\EcommerceFinance\Repositories\PinduoduoSpreadBillRepository;
|
|
use Modules\EcommerceFinance\Repositories\MarketingAccountBillMirrorRepository;
|
|
use Modules\EcommerceFinance\Services\UpstreamReadOnlyQuery;
|
|
use Modules\EcommerceFinance\Services\UpstreamReadOnlyQueryFactory;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class PinduoduoSpreadBillRepositoryTest extends TestCase
|
|
{
|
|
public function test_income_and_expense_filters_are_applied_to_list_and_summary_queries(): void
|
|
{
|
|
$query = new class('jiansun') extends UpstreamReadOnlyQuery {
|
|
/** @var array<int,array{method:string,sql:string,bindings:array}> */
|
|
public array $calls = [];
|
|
|
|
public function scalar(string $sql, array $bindings = []): mixed
|
|
{
|
|
$this->calls[] = compact('sql', 'bindings') + ['method' => 'scalar'];
|
|
|
|
return 1;
|
|
}
|
|
|
|
public function select(string $sql, array $bindings = []): array
|
|
{
|
|
$this->calls[] = compact('sql', 'bindings') + ['method' => 'select'];
|
|
|
|
return [[
|
|
'shopName' => '测试店铺',
|
|
'amount' => 100,
|
|
'balance' => 200,
|
|
'summary' => '测试',
|
|
'flowType' => 1,
|
|
'toAdvertiserFundType' => 1,
|
|
'createTime' => '2026-07-23 12:00:00',
|
|
]];
|
|
}
|
|
|
|
public function first(string $sql, array $bindings = []): ?array
|
|
{
|
|
$this->calls[] = compact('sql', 'bindings') + ['method' => 'first'];
|
|
|
|
return [
|
|
'income_total' => 0,
|
|
'expense_total' => 100,
|
|
'cnt' => 1,
|
|
];
|
|
}
|
|
};
|
|
|
|
$factory = new class($query) extends UpstreamReadOnlyQueryFactory {
|
|
public function __construct(private readonly UpstreamReadOnlyQuery $query)
|
|
{
|
|
}
|
|
|
|
public function forSource(string $source): UpstreamReadOnlyQuery
|
|
{
|
|
TestCase::assertSame('jiansun', $source);
|
|
|
|
return $this->query;
|
|
}
|
|
};
|
|
|
|
$repository = new PinduoduoSpreadBillRepository($factory);
|
|
|
|
$page = $repository->paginate(null, null, null, 'income', 1, 25);
|
|
$summary = $repository->summary(null, null, null, 'expense');
|
|
|
|
$this->assertSame(1, $page['total']);
|
|
$this->assertSame('收入', $page['rows'][0]['income_expense_type']);
|
|
$this->assertSame(-100.0, $summary['net']);
|
|
$this->assertStringContainsString('flowType = 1', $query->calls[0]['sql']);
|
|
$this->assertStringContainsString('flowType = 1', $query->calls[1]['sql']);
|
|
$this->assertStringContainsString('flowType = 2', $query->calls[2]['sql']);
|
|
}
|
|
|
|
public function test_monthly_balances_follow_the_reconciliation_formula(): void
|
|
{
|
|
$query = new class('jiansun') extends UpstreamReadOnlyQuery {
|
|
public array $calls = [];
|
|
|
|
public function scalar(string $sql, array $bindings = []): mixed
|
|
{
|
|
$this->calls[] = compact('sql', 'bindings') + ['method' => 'scalar'];
|
|
|
|
return 1;
|
|
}
|
|
|
|
public function select(string $sql, array $bindings = []): array
|
|
{
|
|
$this->calls[] = compact('sql', 'bindings') + ['method' => 'select'];
|
|
|
|
return [[
|
|
'shopName' => '拼多多_测试店铺',
|
|
'balance_date' => '2026-06-30',
|
|
'opening_balance' => 1000,
|
|
'income_total' => 500,
|
|
'expense_total' => 200,
|
|
'system_closing_balance' => 1300,
|
|
]];
|
|
}
|
|
};
|
|
$factory = new class($query) extends UpstreamReadOnlyQueryFactory {
|
|
public function __construct(private readonly UpstreamReadOnlyQuery $query) {}
|
|
public function forSource(string $source): UpstreamReadOnlyQuery { return $this->query; }
|
|
};
|
|
|
|
$result = (new PinduoduoSpreadBillRepository($factory))->paginateMonthlyBalances(
|
|
'拼多多_测试店铺', '2026-06', 2, 25,
|
|
);
|
|
$row = $result['rows'][0];
|
|
|
|
$this->assertSame(1300.0, $row['closing_balance']);
|
|
$this->assertSame(0.0, $row['balance_difference']);
|
|
$this->assertSame('已核对', $row['verification_status']);
|
|
$this->assertStringContainsString('flowType = 1', $query->calls[1]['sql']);
|
|
$this->assertStringContainsString('flowType = 2', $query->calls[1]['sql']);
|
|
$this->assertStringContainsString('p.createTime < m.month_start', $query->calls[1]['sql']);
|
|
$this->assertSame(['拼多多_测试店铺', '2026-06-01', '2026-06-01', 26, 50], $query->calls[1]['bindings']);
|
|
}
|
|
|
|
public function test_export_rows_reads_every_filtered_mirror_batch(): void
|
|
{
|
|
$mirror = new class extends MarketingAccountBillMirrorRepository {
|
|
public array $calls = [];
|
|
|
|
public function __construct() {}
|
|
|
|
public function ready(string $datasetKey): bool
|
|
{
|
|
TestCase::assertSame(MarketingAccountBillMirrorRepository::PINDUODUO, $datasetKey);
|
|
|
|
return true;
|
|
}
|
|
|
|
public function paginatePinduoduo(
|
|
?string $storeName,
|
|
?string $fromDate,
|
|
?string $toDate,
|
|
?string $flowType,
|
|
int $page,
|
|
int $pageSize,
|
|
): array {
|
|
$this->calls[] = compact('storeName', 'fromDate', 'toDate', 'flowType', 'page', 'pageSize');
|
|
$row = static fn (int $id): array => [
|
|
'id' => $id,
|
|
'shopName' => '筛选店铺',
|
|
'amount' => $id * 10,
|
|
'balance' => 100,
|
|
'summary' => '测试导出',
|
|
'flowType' => 1,
|
|
'toAdvertiserFundType' => 1,
|
|
'createTime' => '2026-07-23 12:00:00',
|
|
];
|
|
|
|
return $page === 1
|
|
? ['rows' => [$row(1), $row(2)], 'total' => 3]
|
|
: ['rows' => [$row(3)], 'total' => 3];
|
|
}
|
|
};
|
|
$query = new UpstreamReadOnlyQuery('jiansun');
|
|
$factory = new class($query) extends UpstreamReadOnlyQueryFactory {
|
|
public function __construct(private readonly UpstreamReadOnlyQuery $query) {}
|
|
public function forSource(string $source): UpstreamReadOnlyQuery { return $this->query; }
|
|
};
|
|
$repository = new PinduoduoSpreadBillRepository($factory, $mirror);
|
|
|
|
$rows = iterator_to_array($repository->exportRows(
|
|
'筛选店铺', '2026-07-01', '2026-07-31', 'income', 2,
|
|
));
|
|
|
|
$this->assertCount(3, $rows);
|
|
$this->assertSame([10.0, 20.0, 30.0], array_column($rows, 'amount'));
|
|
$this->assertSame([1, 2], array_column($mirror->calls, 'page'));
|
|
$this->assertSame(['筛选店铺', '筛选店铺'], array_column($mirror->calls, 'storeName'));
|
|
$this->assertSame(['income', 'income'], array_column($mirror->calls, 'flowType'));
|
|
}
|
|
}
|