151 lines
5.7 KiB
PHP
151 lines
5.7 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\TaobaoWechatOpeningBalanceRepository;
|
|
use Modules\EcommerceFinance\Support\TaobaoWechatBackofficeJuneEndingBalances;
|
|
use Tests\TestCase;
|
|
|
|
class TaobaoWechatOpeningBalanceRepositoryTest extends TestCase
|
|
{
|
|
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->createTables();
|
|
}
|
|
|
|
public function test_july_opening_uses_the_june_ending_balance(): void
|
|
{
|
|
$this->insertOpening('淘系微信一店', '669385.40');
|
|
|
|
$result = app(TaobaoWechatOpeningBalanceRepository::class)
|
|
->openingBalance('淘系微信一店', '2026-07-01');
|
|
|
|
$this->assertSame(669385.4, $result['balance']);
|
|
$this->assertSame('2026-06-30', $result['date']);
|
|
$this->assertSame(TaobaoWechatBackofficeJuneEndingBalances::SOURCE, $result['source']);
|
|
$this->assertSame(1, $result['store_count']);
|
|
}
|
|
|
|
public function test_later_periods_carry_the_opening_balance_forward(): void
|
|
{
|
|
$this->insertOpening('淘系微信一店', '100.00');
|
|
$this->insertBill('淘系微信一店', '2026-07-05 10:00:00', '50.00', '20.00');
|
|
$this->insertBill('淘系微信一店', '2026-08-02 10:00:00', '10.00', '5.00');
|
|
|
|
$result = app(TaobaoWechatOpeningBalanceRepository::class)
|
|
->openingBalance('淘系微信一店', '2026-08-01');
|
|
|
|
$this->assertSame(130.0, $result['balance']);
|
|
$this->assertSame('2026-07-31', $result['date']);
|
|
$this->assertSame(
|
|
TaobaoWechatBackofficeJuneEndingBalances::SOURCE . '_carried_forward',
|
|
$result['source'],
|
|
);
|
|
}
|
|
|
|
public function test_all_store_openings_are_summed_when_no_store_is_selected(): void
|
|
{
|
|
$this->insertOpening('淘系微信一店', '100.00');
|
|
$this->insertOpening('淘系微信二店', '200.25');
|
|
|
|
$result = app(TaobaoWechatOpeningBalanceRepository::class)
|
|
->openingBalance(null, '2026-07-01');
|
|
|
|
$this->assertSame(300.25, $result['balance']);
|
|
$this->assertSame(2, $result['store_count']);
|
|
}
|
|
|
|
public function test_backoffice_dataset_contains_the_twenty_one_confirmed_store_balances(): void
|
|
{
|
|
$balances = TaobaoWechatBackofficeJuneEndingBalances::balances();
|
|
$totalCents = array_sum(array_map(
|
|
static fn (string $balance): int => (int) round((float) $balance * 100),
|
|
array_values($balances),
|
|
));
|
|
|
|
$this->assertCount(21, $balances);
|
|
$this->assertSame(81463042, $totalCents);
|
|
$this->assertSame('27846.22', $balances['天猫-HX旗舰店101']);
|
|
$this->assertSame('290881.84', $balances['天猫-亿家达旗舰店']);
|
|
$this->assertSame('5155.88', $balances['天猫-亿家达宜彩专卖店']);
|
|
$this->assertSame('86802.00', $balances['淘宝-全颐家具工厂店']);
|
|
}
|
|
|
|
public function test_missing_opening_balance_is_unavailable(): void
|
|
{
|
|
$result = app(TaobaoWechatOpeningBalanceRepository::class)
|
|
->openingBalance('未录入店铺', '2026-07-01');
|
|
|
|
$this->assertNull($result['balance']);
|
|
$this->assertNull($result['date']);
|
|
$this->assertSame('unavailable', $result['source']);
|
|
$this->assertSame(0, $result['store_count']);
|
|
}
|
|
|
|
private function createTables(): void
|
|
{
|
|
$schema = Schema::connection('business_mirror');
|
|
$schema->create(TaobaoWechatOpeningBalanceRepository::TABLE, function (Blueprint $table): void {
|
|
$table->id();
|
|
$table->date('balance_date');
|
|
$table->string('store_name', 191);
|
|
$table->decimal('balance', 20, 2);
|
|
$table->string('source', 191);
|
|
$table->text('source_note')->nullable();
|
|
$table->timestamp('imported_at');
|
|
$table->timestamps();
|
|
$table->unique(['balance_date', 'store_name']);
|
|
});
|
|
$schema->create('taobao_wechat_bill_rows', function (Blueprint $table): void {
|
|
$table->string('record_code', 191)->primary();
|
|
$table->string('store_name')->nullable();
|
|
$table->dateTime('occurred_at');
|
|
$table->decimal('income_amount', 20, 2);
|
|
$table->decimal('expense_amount', 20, 2);
|
|
});
|
|
}
|
|
|
|
private function insertOpening(string $storeName, string $balance): void
|
|
{
|
|
DB::connection('business_mirror')->table(TaobaoWechatOpeningBalanceRepository::TABLE)->insert([
|
|
'balance_date' => '2026-06-30',
|
|
'store_name' => $storeName,
|
|
'balance' => $balance,
|
|
'source' => TaobaoWechatBackofficeJuneEndingBalances::SOURCE,
|
|
'source_note' => TaobaoWechatBackofficeJuneEndingBalances::SOURCE_NOTE,
|
|
'imported_at' => '2026-11-09 10:00:00',
|
|
]);
|
|
}
|
|
|
|
private function insertBill(
|
|
string $storeName,
|
|
string $occurredAt,
|
|
string $income,
|
|
string $expense,
|
|
): void {
|
|
static $sequence = 0;
|
|
$sequence++;
|
|
DB::connection('business_mirror')->table('taobao_wechat_bill_rows')->insert([
|
|
'record_code' => 'TEST-' . $sequence,
|
|
'store_name' => $storeName,
|
|
'occurred_at' => $occurredAt,
|
|
'income_amount' => $income,
|
|
'expense_amount' => $expense,
|
|
]);
|
|
}
|
|
}
|