82 lines
2.9 KiB
PHP
82 lines
2.9 KiB
PHP
<?php
|
|
|
|
namespace Modules\EcommerceFinance\Repositories;
|
|
|
|
use Carbon\CarbonImmutable;
|
|
use Illuminate\Database\ConnectionInterface;
|
|
use Illuminate\Database\DatabaseManager;
|
|
|
|
class VipshopJxOpeningBalanceRepository
|
|
{
|
|
public const TABLE = 'vipshop_jx_opening_balance_snapshots';
|
|
public const BASELINE_PERIOD_END = '2026-06-30';
|
|
|
|
private readonly ConnectionInterface $mirror;
|
|
private readonly ConnectionInterface $bills;
|
|
|
|
public function __construct(DatabaseManager $databases)
|
|
{
|
|
$this->mirror = $databases->connection(
|
|
(string) config('upstream_mirrors.connection', 'business_mirror'),
|
|
);
|
|
$this->bills = $databases->connection();
|
|
}
|
|
|
|
/** @return array{balance:float,date:?string,source:string} */
|
|
public function openingBalance(?string $startDate, ?string $endDate): array
|
|
{
|
|
$start = $this->monthStart($startDate) ?? $this->monthStart($endDate);
|
|
$baselineMonth = CarbonImmutable::create(2026, 7, 1)->startOfDay();
|
|
if ($start === null || $start->lt($baselineMonth)) {
|
|
return ['balance' => 0.0, 'date' => null, 'source' => 'none'];
|
|
}
|
|
if (! $this->mirror->getSchemaBuilder()->hasTable(self::TABLE)) {
|
|
return ['balance' => 0.0, 'date' => null, 'source' => 'none'];
|
|
}
|
|
|
|
$baseline = $this->mirror->table(self::TABLE)
|
|
->where('period_end', self::BASELINE_PERIOD_END)
|
|
->value('balance');
|
|
if ($baseline === null) {
|
|
return ['balance' => 0.0, 'date' => null, 'source' => 'none'];
|
|
}
|
|
|
|
$balance = (float) $baseline;
|
|
if ($start->gt($baselineMonth)) {
|
|
$movement = $this->bills->table('ec_account_bills')
|
|
->where('company_id', (int) (company_id() ?: 1))
|
|
->where('bill_type', 'vipshop-jx')
|
|
->whereNull('deleted_at')
|
|
->where('payload->settle_period', '>=', '2026-07')
|
|
->where('payload->settle_period', '<', $start->format('Y-m'))
|
|
->selectRaw('COALESCE(SUM(income), 0) AS income, COALESCE(SUM(expense), 0) AS expense')
|
|
->first();
|
|
$balance += (float) ($movement->income ?? 0) - (float) ($movement->expense ?? 0);
|
|
}
|
|
|
|
return [
|
|
'balance' => round($balance, 2),
|
|
'date' => $start->subDay()->format('Y-m-d'),
|
|
'source' => $start->equalTo($baselineMonth) ? 'june_ending' : 'previous_period',
|
|
];
|
|
}
|
|
|
|
private function monthStart(?string $value): ?CarbonImmutable
|
|
{
|
|
$date = trim((string) $value);
|
|
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $date) !== 1) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
$parsed = CarbonImmutable::createFromFormat('!Y-m-d', $date);
|
|
} catch (\Throwable) {
|
|
return null;
|
|
}
|
|
|
|
return $parsed instanceof CarbonImmutable && $parsed->format('Y-m-d') === $date
|
|
? $parsed->startOfMonth()
|
|
: null;
|
|
}
|
|
}
|