[ 'driver' => 'sqlite', 'database' => ':memory:', 'prefix' => '', ], 'upstream_mirrors.connection' => 'business_mirror', ]); DB::purge('business_mirror'); (require database_path('migrations/2026_11_07_120000_create_vipshop_jx_opening_balance_snapshots.php'))->up(); (require database_path('migrations/2026_11_07_180000_create_vipshop_jx_bank_payments.php'))->up(); } public function test_opening_balance_rolls_from_june_ending_by_settlement_period(): void { $companyId = (int) DB::table('companies')->value('id'); DB::connection('business_mirror')->table(VipshopJxOpeningBalanceRepository::TABLE)->insert([ 'period_end' => '2026-06-30', 'balance' => '491948.53', 'source' => '唯品会结算平台历史账单累计', 'imported_at' => now(), 'created_at' => now(), 'updated_at' => now(), ]); $this->bill($companyId, 'JUL-A', '2026-07', '300', '50'); $this->bill($companyId, 'AUG-A', '2026-08', '100', '20'); $this->payment(1, 'BILL-2026-06', '2026-06', '491948.53'); $this->payment(2, 'BILL-2026-07', '2026-07', '100'); $this->payment(3, 'BILL-2026-08', '2026-08', '30'); $repository = app(VipshopJxOpeningBalanceRepository::class); $july = $repository->openingBalance('2026-07-01', '2026-07-31'); $august = $repository->openingBalance('2026-08-01', '2026-08-31'); $september = $repository->openingBalance('2026-09-01', '2026-09-30'); $this->assertSame(0.0, $july['balance']); $this->assertSame('2026-06-30', $july['date']); $this->assertSame('bank_settled', $july['source']); $this->assertSame(100.0, $july['withdrawal_amount']); $this->assertSame(150.0, $august['balance']); $this->assertSame('2026-07-31', $august['date']); $this->assertSame('previous_period', $august['source']); $this->assertSame(30.0, $august['withdrawal_amount']); $this->assertSame(200.0, $september['balance']); } public function test_it_returns_no_opening_balance_before_the_june_baseline(): void { $result = app(VipshopJxOpeningBalanceRepository::class) ->openingBalance('2026-06-01', '2026-06-30'); $this->assertSame(0.0, $result['balance']); $this->assertNull($result['date']); $this->assertSame('none', $result['source']); } private function bill( int $companyId, string $recordCode, string $period, string $income, string $expense, ): void { DB::table('ec_account_bills')->insert([ 'company_id' => $companyId, 'bill_type' => 'vipshop-jx', 'record_code' => $recordCode, 'store_name' => '唯品会JITX_亿家达', 'order_no' => 'ORDER-' . $recordCode, 'bill_item' => '销售明细', 'occurred_at' => $period . '-15 10:00:00', 'income' => $income, 'expense' => $expense, 'amount' => bcsub($income, $expense, 2), 'balance' => 0, 'payload' => json_encode(['settle_period' => $period], JSON_THROW_ON_ERROR), 'created_at' => now(), 'updated_at' => now(), ]); } private function payment( int $sourcePaymentId, string $billNumber, string $billPeriod, string $amount, ): void { DB::connection('business_mirror')->table(VipshopJxBankPaymentRepository::TABLE)->insert([ 'source_payment_id' => $sourcePaymentId, 'source_bill_number' => $billNumber, 'bill_period' => $billPeriod, 'pay_date' => $billPeriod . '-15', 'batch_number' => 'BATCH-' . $sourcePaymentId, 'vendor_account_num' => '1105055609100026936', 'amount' => $amount, 'currency_code' => 'CNY', 'pay_status' => 'SUCCESS', 'source_hash' => str_repeat('a', 64), 'imported_at' => now(), 'created_at' => now(), 'updated_at' => now(), ]); } }