File manager - Edit - /home/webapp69.cm.in.th/u69319090028/Shop/app/Controllers/AdminFinanceController.php
Back
<?php /** * AdminFinanceController * Platform-wide financial overview: GMV, commission, refunds, settlements * Requires finance.view / finance.settle permission */ require_once __DIR__ . '/../Core/Controller.php'; require_once __DIR__ . '/../Models/Settlement.php'; require_once __DIR__ . '/../Models/Store.php'; require_once __DIR__ . '/../Models/AdminAuditLog.php'; require_once __DIR__ . '/../Services/AdminOrderService.php'; require_once __DIR__ . '/../Middleware/AdminMiddleware.php'; require_once __DIR__ . '/../Helpers/Auth.php'; require_once __DIR__ . '/../Helpers/Session.php'; require_once __DIR__ . '/../Helpers/Security.php'; class AdminFinanceController extends Controller { private AdminOrderService $orderService; private Settlement $settlementModel; private Store $storeModel; private AdminAuditLog $auditLog; public function __construct() { $this->orderService = new AdminOrderService(); $this->settlementModel = new Settlement(); $this->storeModel = new Store(); $this->auditLog = new AdminAuditLog(); } /** * Financial Reports Dashboard * GET /admin/finance */ public function index(): void { AdminMiddleware::requirePermission('finance.view'); $db = \Database::getInstance(); $filters = [ 'date_from' => $_GET['date_from'] ?? '', 'date_to' => $_GET['date_to'] ?? '', 'store_id' => $_GET['store_id'] ?? 'all', ]; $where = "o.deleted_at IS NULL"; $params = []; if (!empty($filters['date_from'])) { $where .= " AND o.created_at >= :date_from"; $params[':date_from'] = $filters['date_from'] . ' 00:00:00'; } if (!empty($filters['date_to'])) { $where .= " AND o.created_at <= :date_to"; $params[':date_to'] = $filters['date_to'] . ' 23:59:59'; } if (!empty($filters['store_id']) && $filters['store_id'] !== 'all') { $where .= " AND o.store_id = :store_id"; $params[':store_id'] = (int)$filters['store_id']; } // Summary Aggregates $sqlSummary = "SELECT COUNT(o.id) as total_orders, SUM(CASE WHEN o.order_status = 'completed' THEN o.total_amount ELSE 0 END) as gmv, SUM(CASE WHEN o.order_status = 'completed' THEN o.commission_amount ELSE 0 END) as total_commission, SUM(CASE WHEN o.order_status = 'completed' THEN o.net_revenue ELSE 0 END) as net_seller_revenue, SUM(CASE WHEN o.order_status = 'completed' THEN 1 ELSE 0 END) as completed_orders, SUM(CASE WHEN o.payment_status = 'confirmed' THEN o.total_amount ELSE 0 END) as total_collected, SUM(CASE WHEN o.payment_status = 'refunded' OR o.order_status = 'refunded' THEN o.total_amount ELSE 0 END) as total_refunded, SUM(CASE WHEN DATE(o.created_at) = CURDATE() AND o.order_status = 'completed' THEN o.total_amount ELSE 0 END) as today_gmv, SUM(CASE WHEN DATE(o.created_at) = CURDATE() AND o.order_status = 'completed' THEN o.commission_amount ELSE 0 END) as today_commission FROM `orders` o WHERE {$where}"; $stmtSummary = $db->prepare($sqlSummary); foreach ($params as $k => $v) { $stmtSummary->bindValue($k, $v); } $stmtSummary->execute(); $stats = $stmtSummary->fetch() ?: []; // Monthly breakdown (last 6 months) $sqlMonthly = "SELECT DATE_FORMAT(o.created_at, '%Y-%m') as month, COUNT(*) as order_count, SUM(CASE WHEN o.order_status = 'completed' THEN o.total_amount ELSE 0 END) as gmv, SUM(CASE WHEN o.order_status = 'completed' THEN o.commission_amount ELSE 0 END) as commission, SUM(CASE WHEN o.order_status = 'completed' THEN o.net_revenue ELSE 0 END) as net_revenue FROM `orders` o WHERE o.deleted_at IS NULL AND o.created_at >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH) GROUP BY DATE_FORMAT(o.created_at, '%Y-%m') ORDER BY month DESC"; $stmtMonthly = $db->prepare($sqlMonthly); $stmtMonthly->execute(); $monthly = $stmtMonthly->fetchAll(); // Top Store Revenue Performance Breakdown $sqlStores = "SELECT s.id, s.store_name, s.store_slug, COUNT(o.id) as completed_orders, SUM(o.total_amount) as store_gmv, SUM(o.commission_amount) as store_commission, SUM(o.net_revenue) as store_net_revenue FROM `stores` s JOIN `orders` o ON o.store_id = s.id WHERE o.order_status = 'completed' AND o.deleted_at IS NULL GROUP BY s.id ORDER BY store_gmv DESC LIMIT 10"; $topStores = $db->query($sqlStores)->fetchAll(); $allStores = $db->query("SELECT id, store_name FROM `stores` WHERE deleted_at IS NULL ORDER BY store_name ASC")->fetchAll(); $this->render('admin/finance/index', [ 'stats' => $stats, 'monthly' => $monthly, 'topStores' => $topStores, 'allStores' => $allStores, 'filters' => $filters, 'pageTitle' => 'รายงานการเงิน — CARGOO Admin', 'activeNav' => 'finance', ], 'admin'); } /** * Vendor Settlements List & Management * GET /admin/finance/settlements */ public function settlements(): void { AdminMiddleware::requirePermission('finance.view'); $filters = [ 'status' => $_GET['status'] ?? 'all', 'store_id' => $_GET['store_id'] ?? '', 'q' => trim($_GET['q'] ?? ''), 'date_from' => $_GET['date_from'] ?? '', 'date_to' => $_GET['date_to'] ?? '', ]; $page = max(1, (int)($_GET['page'] ?? 1)); $perPage = 20; $offset = ($page - 1) * $perPage; $settlements = $this->settlementModel->getAdminSettlements($filters, $perPage, $offset); $total = $this->settlementModel->countAdminSettlements($filters); $stats = $this->settlementModel->getSettlementStats(); $unsettled = $this->settlementModel->getUnsettledStoreBalances(); $db = \Database::getInstance(); $allStores = $db->query("SELECT id, store_name FROM `stores` WHERE deleted_at IS NULL ORDER BY store_name ASC")->fetchAll(); $this->render('admin/finance/settlements', [ 'settlements' => $settlements, 'total' => $total, 'stats' => $stats, 'unsettled' => $unsettled, 'allStores' => $allStores, 'filters' => $filters, 'page' => $page, 'perPage' => $perPage, 'totalPages' => (int)ceil($total / $perPage), 'pageTitle' => 'รายการตัดรอบโอนเงิน — CARGOO Admin', 'activeNav' => 'finance', ], 'admin'); } /** * Process Settlement Payout * POST /admin/finance/settlements/{id}/process */ public function processSettlement(string $id): void { AdminMiddleware::requirePermission('finance.settle'); $settlementId = (int)$id; $settlement = $this->settlementModel->findWithStore($settlementId); if (!$settlement) { Session::setFlash('danger', 'ไม่พบรายการรอบโอนเงินนี้'); $this->redirect('/admin/finance/settlements'); } $status = trim($_POST['status'] ?? 'completed'); $reference = trim($_POST['payment_reference'] ?? ''); $note = trim($_POST['note'] ?? ''); $adminId = Auth::id(); if (!in_array($status, ['pending', 'processing', 'completed', 'failed', 'cancelled'], true)) { Session::setFlash('danger', 'สถานะการโอนไม่ถูกต้อง'); $this->redirect('/admin/finance/settlements'); } $ok = $this->settlementModel->process($settlementId, $status, $reference ?: null, $note ?: null); if ($ok) { $this->auditLog->record( $adminId, 'settlement.process', 'finance', 'settlement', $settlementId, "Updated settlement #{$settlementId} for {$settlement['store_name']} to {$status}" . ($reference ? " (Ref: {$reference})" : "") ); Session::setFlash('success', 'บันทึกสถานะการโอนเงินเรียบร้อยแล้ว'); } else { Session::setFlash('danger', 'ไม่สามารถบันทึกข้อมูลได้'); } $this->redirect('/admin/finance/settlements'); } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.23 |
proxy
|
phpinfo
|
Settings