CaiWuXiTong/modules/EcommerceFinance/Http/Controllers/StoreReceivingBalanceOverview.php
qiuxiang b1e4eb3c72 perf: cache period balance reconciliation
Cache summary and trend responses for five minutes by company and date.
2026-11-11 20:41:12 +08:00

187 lines
6.3 KiB
PHP

<?php
namespace Modules\EcommerceFinance\Http\Controllers;
use App\Utilities\SidebarPermissions;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Cache;
use Modules\EcommerceFinance\Services\PeriodBalanceReconciliationService;
use Modules\EcommerceFinance\Services\StoreReceivingBalanceOverviewService;
use Throwable;
class StoreReceivingBalanceOverview extends Controller
{
public function index(Request $request, StoreReceivingBalanceOverviewService $service)
{
$this->authorizeStoreReceivingBills();
try {
return response()->json($service->overview(...$this->requestedPeriod($request)));
} catch (Throwable $exception) {
report($exception);
return response()->json([
'message' => '账户余额总览暂时无法读取,请稍后重试。',
], 503);
}
}
public function incomeDetail(Request $request, StoreReceivingBalanceOverviewService $service)
{
$this->authorizeStoreReceivingBills();
try {
return response()->json($service->incomeDetail(...$this->requestedPeriod($request)));
} catch (Throwable $exception) {
report($exception);
return response()->json([
'message' => '收入明细暂时无法读取,请稍后重试。',
], 503);
}
}
public function expenseDetail(Request $request, StoreReceivingBalanceOverviewService $service)
{
$this->authorizeStoreReceivingBills();
try {
return response()->json($service->expenseDetail(...$this->requestedPeriod($request)));
} catch (Throwable $exception) {
report($exception);
return response()->json([
'message' => '支出明细暂时无法读取,请稍后重试。',
], 503);
}
}
public function reconciliation(Request $request, PeriodBalanceReconciliationService $service)
{
$this->authorizePeriodBalanceReconciliation();
try {
$period = $this->requestedPeriod($request);
$cacheKey = $this->reconciliationCacheKey('summary', $period);
return response()->json(Cache::remember(
$cacheKey,
now()->addMinutes(5),
static fn (): array => $service->build(...$period),
));
} catch (Throwable $exception) {
report($exception);
return response()->json([
'message' => '期末余额双源核对数据暂时无法读取,请稍后重试。',
], 503);
}
}
public function reconciliationTrend(Request $request, PeriodBalanceReconciliationService $service)
{
$this->authorizePeriodBalanceReconciliation();
try {
$period = $this->requestedPeriod($request);
$cacheKey = $this->reconciliationCacheKey('trend', $period);
return response()->json(Cache::remember(
$cacheKey,
now()->addMinutes(5),
static fn (): array => $service->buildTrend(...$period),
));
} catch (Throwable $exception) {
report($exception);
return response()->json([
'message' => '期末余额双源趋势暂时无法读取,请稍后重试。',
], 503);
}
}
public function balanceDetail(Request $request, StoreReceivingBalanceOverviewService $service)
{
$this->authorizeStoreReceivingBills();
try {
return response()->json($service->balanceDetail(...$this->requestedPeriod($request)));
} catch (Throwable $exception) {
report($exception);
return response()->json([
'message' => '期末余额明细暂时无法读取,请稍后重试。',
], 503);
}
}
public function balanceStoreDetail(Request $request, StoreReceivingBalanceOverviewService $service)
{
$this->authorizeStoreReceivingBills();
try {
return response()->json($service->balanceStoreDetail(...$this->requestedPeriod($request)));
} catch (Throwable $exception) {
report($exception);
return response()->json([
'message' => '店铺期末余额明细暂时无法读取,请稍后重试。',
], 503);
}
}
/** @return array{0:string,1?:string} */
private function requestedPeriod(Request $request): array
{
$validated = $request->validate([
'month' => ['nullable', 'date_format:Y-m'],
'start' => ['nullable', 'date_format:Y-m-d', 'required_with:end'],
'end' => ['nullable', 'date_format:Y-m-d', 'required_with:start', 'after_or_equal:start'],
]);
if (! empty($validated['start']) && ! empty($validated['end'])) {
return [(string) $validated['start'], (string) $validated['end']];
}
return [(string) ($validated['month'] ?? now('Asia/Shanghai')->format('Y-m'))];
}
private function authorizeStoreReceivingBills(): void
{
$section = collect(SidebarPermissions::navigationFor(user()))
->firstWhere('slug', 'billing-transactions');
$page = collect($section['pages'] ?? [])
->firstWhere('slug', 'store-receiving-bills');
abort_if(empty($page), 403, '当前账号没有店铺收款账户账单权限。');
}
private function authorizePeriodBalanceReconciliation(): void
{
$section = collect(SidebarPermissions::navigationFor(user()))
->firstWhere('slug', 'billing-transactions');
$pages = collect($section['pages'] ?? []);
$authorized = $pages->whereIn('slug', [
'store-receiving-bills',
'period-balance-reconciliation',
])->isNotEmpty();
abort_if(! $authorized, 403, '当前账号没有期末余额双源核对权限。');
}
/** @param array{0:string,1?:string} $period */
private function reconciliationCacheKey(string $kind, array $period): string
{
return implode(':', [
'ecommerce-finance',
'period-balance-reconciliation',
'v2',
$kind,
(string) company_id(),
$period[0],
$period[1] ?? '',
]);
}
}