87 lines
3.3 KiB
PHP
87 lines
3.3 KiB
PHP
<?php
|
|
|
|
namespace Modules\EcommerceFinance\Repositories;
|
|
|
|
use Carbon\CarbonImmutable;
|
|
use Illuminate\Database\ConnectionInterface;
|
|
use Illuminate\Database\DatabaseManager;
|
|
use Modules\EcommerceFinance\Services\VipshopMpOpeningBalanceImporter;
|
|
|
|
class VipshopMpOpeningBalanceRepository
|
|
{
|
|
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 $storeName, ?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(VipshopMpOpeningBalanceImporter::TABLE)) {
|
|
return ['balance' => 0.0, 'date' => null, 'source' => 'none'];
|
|
}
|
|
|
|
$store = trim((string) $storeName);
|
|
$snapshot = $this->mirror->table(VipshopMpOpeningBalanceImporter::TABLE)
|
|
->where('period_end', '2026-06-30')
|
|
->when($store !== '', static fn ($query) => $query->where('store_name', $store));
|
|
if ((clone $snapshot)->doesntExist()) {
|
|
return ['balance' => 0.0, 'date' => null, 'source' => 'none'];
|
|
}
|
|
|
|
$balance = round((float) (clone $snapshot)->sum('balance'), 2);
|
|
if ($start->gt($baselineMonth)) {
|
|
$movement = $this->bills->table('ec_account_bills')
|
|
->where('company_id', (int) (company_id() ?: 1))
|
|
->where('bill_type', 'vipshop')
|
|
->whereNull('deleted_at')
|
|
->where('payload->settle_period', '>=', '2026-07')
|
|
->where('payload->settle_period', '<', $start->format('Y-m'))
|
|
->when($store !== '', static fn ($query) => $query->where('store_name', $store))
|
|
->selectRaw('COALESCE(SUM(income), 0) AS income, COALESCE(SUM(expense), 0) AS expense')
|
|
->first();
|
|
$balance = round(
|
|
$balance
|
|
+ (float) ($movement->income ?? 0)
|
|
- (float) ($movement->expense ?? 0),
|
|
2,
|
|
);
|
|
}
|
|
|
|
return [
|
|
'balance' => $balance,
|
|
'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;
|
|
}
|
|
}
|