CaiWuXiTong/tests/Unit/EcommerceFinance/AlibabaAccountBalanceRepositoryTest.php

121 lines
4.9 KiB
PHP

<?php
namespace Tests\Unit\EcommerceFinance;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Modules\EcommerceFinance\Repositories\AlibabaAccountBalanceRepository;
use Modules\EcommerceFinance\Services\AlibabaAccountBalanceWorkbookImporter;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Tests\TestCase;
class AlibabaAccountBalanceRepositoryTest extends TestCase
{
private string $workbookPath;
protected function setUp(): void
{
parent::setUp();
config([
'database.connections.business_mirror' => [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
],
'upstream_mirrors.connection' => 'business_mirror',
]);
DB::purge('business_mirror');
$this->createTable();
$this->workbookPath = sys_get_temp_dir() . '/alibaba-account-balance-' . uniqid('', true) . '.xlsx';
}
protected function tearDown(): void
{
if (isset($this->workbookPath) && is_file($this->workbookPath)) {
unlink($this->workbookPath);
}
DB::purge('business_mirror');
parent::tearDown();
}
public function testItImportsUpdatesFiltersAndPaginatesBalanceSnapshots(): void
{
$this->writeWorkbook([
['2026-06-30', '阿里店甲', null, null, null, 4142.96, null, null, null, null, null],
['2026-06-30', '阿里店乙', 100, 50, 20, 130, 130, 0, '', '已核对', '测试'],
]);
$importer = app(AlibabaAccountBalanceWorkbookImporter::class);
$first = $importer->import($this->workbookPath, '阿里巴巴余额.xlsx');
$second = $importer->import($this->workbookPath, '阿里巴巴余额.xlsx');
$this->assertSame(['created' => 2, 'updated' => 0, 'skipped' => 0, 'total' => 2], $first);
$this->assertSame(['created' => 0, 'updated' => 2, 'skipped' => 0, 'total' => 2], $second);
$this->assertSame(2, DB::connection('business_mirror')->table(AlibabaAccountBalanceRepository::TABLE)->count());
$repository = app(AlibabaAccountBalanceRepository::class);
$result = $repository->paginateMonthlyBalances('阿里店甲', '2026-06', 1, 25);
$this->assertTrue($repository->usesBusinessMirror());
$this->assertSame(['阿里店乙', '阿里店甲'], $repository->storeOptions());
$this->assertSame(1, $result['total']);
$this->assertSame('2026-06-30', $result['rows'][0]['date']);
$this->assertSame('阿里店甲', $result['rows'][0]['store_name']);
$this->assertSame(4142.96, $result['rows'][0]['closing_balance']);
$this->assertNull($result['rows'][0]['opening_balance']);
}
public function testItRejectsNonMonthEndDatesBeforeWriting(): void
{
$this->writeWorkbook([
['2026-06-29', '阿里店甲', null, null, null, 10, null, null, null, null, null],
]);
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('必须是月末日期');
app(AlibabaAccountBalanceWorkbookImporter::class)->import($this->workbookPath);
}
/** @param array<int,array<int,mixed>> $rows */
private function writeWorkbook(array $rows): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$sheet->setTitle('阿里巴巴账户');
$sheet->fromArray([[
'日期', '店铺名称', '期初余额', '本期收入', '本期支出', '期末余额',
'系统期末余额', '余额差异', '差异原因', '核对状态', '备注',
], ...$rows]);
(new Xlsx($spreadsheet))->save($this->workbookPath);
$spreadsheet->disconnectWorksheets();
}
private function createTable(): void
{
Schema::connection('business_mirror')->create(AlibabaAccountBalanceRepository::TABLE, function (Blueprint $table): void {
$table->id();
$table->date('balance_date');
$table->string('store_name');
$table->decimal('opening_balance', 20, 6)->nullable();
$table->decimal('income_total', 20, 6)->nullable();
$table->decimal('expense_total', 20, 6)->nullable();
$table->decimal('closing_balance', 20, 6)->nullable();
$table->decimal('system_closing_balance', 20, 6)->nullable();
$table->decimal('balance_difference', 20, 6)->nullable();
$table->text('difference_reason')->nullable();
$table->string('verification_status')->nullable();
$table->text('notes')->nullable();
$table->string('source_file_name');
$table->char('source_sha256', 64);
$table->dateTime('imported_at');
$table->timestamps();
$table->unique(['balance_date', 'store_name']);
});
}
}