diff --git a/admin/index.php b/admin/index.php index 5eaf697..aa15eea 100644 --- a/admin/index.php +++ b/admin/index.php @@ -1228,7 +1228,7 @@ function purchaseCard(p, showActions=true) { '' : (p.admin_note ? '
๐Ÿ“ '+escHtmlA(p.admin_note)+'
' : ''); - return '
'+ + return '
'+ '
'+ '
'+ '
'+ @@ -3173,22 +3173,37 @@ async function loadCreditEntries() { list.innerHTML = ` - + + - ${d.credits.map(c=>` - - - - - - `).join('')} + ${d.credits.map(c=>{ + const isDebit = c.type === 'debit'; + const amtColor = isDebit ? 'var(--red)' : 'var(--cyan)'; + const amtPrefix = isDebit ? 'โˆ’' : '+'; + const rowBg = isDebit ? 'background:rgba(255,68,68,.03)' : ''; + const typeBadge = isDebit + ? 'DEBIT' + : 'CREDIT'; + const refLink = (isDebit && c.purchase_ref_id) + ? `` + : ''; + const editDel = !isDebit + ? ` + ` + : ''; + return ` + + + + + + + `; + }).join('')}
DATECREDITSTYPEAMOUNT METHOD NOTES
${escHtmlA(c.credit_date)}${parseFloat(c.credits_purchased).toLocaleString(undefined,{minimumFractionDigits:2,maximumFractionDigits:2})}${escHtmlA(c.payment_method||'โ€”')}${escHtmlA(c.notes||'')} - - -
${escHtmlA(c.credit_date)}${typeBadge}${amtPrefix}${parseFloat(c.credits_purchased).toLocaleString(undefined,{minimumFractionDigits:2,maximumFractionDigits:2})}${escHtmlA(c.payment_method||'โ€”')}${escHtmlA(c.notes||'')}${refLink}${editDel}
`; } @@ -3249,6 +3264,22 @@ async function deleteCreditEntry(id) { else toast(d.error||'Error','err'); } +async function jumpToPurchase(purchaseId) { + closeCreditModal(); + showSec('purchases'); + document.querySelectorAll('#section-purchases .ftab').forEach(b=>b.classList.remove('active')); + const allTab = document.querySelector('#section-purchases .ftab[onclick*="\'all\'"]'); + if (allTab) allTab.classList.add('active'); + await loadPurchases('all'); + const el = document.getElementById('pr-' + purchaseId); + if (el) { + el.scrollIntoView({behavior:'smooth', block:'center'}); + el.style.outline = '2px solid var(--gold)'; + el.style.borderRadius = '12px'; + setTimeout(() => { el.style.outline = ''; el.style.borderRadius = ''; }, 2500); + } +} + // Sync hex input with color picker document.addEventListener('DOMContentLoaded', function() { const picker = document.getElementById('gf-color'); diff --git a/api/admin.php b/api/admin.php index ed843e4..33369df 100644 --- a/api/admin.php +++ b/api/admin.php @@ -104,17 +104,33 @@ switch ($action) { db()->beginTransaction(); try { if ($status === 'completed') { - // Credit tokens to user - logAdminAction('TOKENS_ADJUSTED', $adminId, 'user', isset($targetId)?(int)$targetId:0, 'Manual token adjustment: '.($data['tokens']??0).' tokens', '', ($data['tokens']??''), 'critical'); db()->prepare("UPDATE users SET tokens=tokens+? WHERE id=?")->execute([$purchase['tokens'], $purchase['user_id']]); } db()->prepare("UPDATE token_purchases SET status=?,admin_note=? WHERE id=?")->execute([$status, $note, $id]); db()->commit(); - echo json_encode($sent ? ['success'=>true] : ['success'=>false,'error'=>'Failed to send reset email. Please try again.']); } catch (Exception $e) { db()->rollBack(); - echo json_encode(['success'=>false,'error'=>'DB error']); + echo json_encode(['success'=>false,'error'=>'DB error']); exit; } + + // Insert debit entry into platform_credits when approved + if ($status === 'completed' && !empty($purchase['platform_id'])) { + $platRow = db()->prepare("SELECT id FROM platforms WHERE slug=?"); + $platRow->execute([$purchase['platform_id']]); + $platNumId = (int)$platRow->fetchColumn(); + if ($platNumId) { + $userRow = db()->prepare("SELECT username FROM users WHERE id=?"); + $userRow->execute([$purchase['user_id']]); + $username = $userRow->fetchColumn() ?: 'User#'.$purchase['user_id']; + $amtDollars = number_format($purchase['amount_cents'] / 100, 2); + $playerLabel = trim($purchase['player_name'] ?: $purchase['game_alias'] ?: $username); + $debitNotes = "Purchase #{$id} ยท {$playerLabel} ({$username}) ยท {$purchase['tokens']} tokens ยท \${$amtDollars} via {$purchase['payment_method']}"; + db()->prepare("INSERT INTO platform_credits (platform_id, credits_purchased, credit_date, payment_method, notes, type, purchase_ref_id) VALUES (?,?,CURDATE(),?,?,?,?)") + ->execute([$platNumId, $purchase['tokens'], $purchase['payment_method'], $debitNotes, 'debit', $id]); + } + } + + echo json_encode(['success'=>true]); break; // โ”€โ”€โ”€ CASHOUTS โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ diff --git a/api/platforms.php b/api/platforms.php index 8ccb59c..72935c0 100644 --- a/api/platforms.php +++ b/api/platforms.php @@ -120,7 +120,7 @@ switch ($action) { $rows = db()->prepare("SELECT * FROM platform_credits WHERE platform_id=? ORDER BY credit_date DESC, id DESC"); $rows->execute([$pid]); $credits = $rows->fetchAll(); - $total = db()->prepare("SELECT COALESCE(SUM(credits_purchased),0) FROM platform_credits WHERE platform_id=?"); + $total = db()->prepare("SELECT COALESCE(SUM(CASE WHEN type='debit' THEN -credits_purchased ELSE credits_purchased END),0) FROM platform_credits WHERE platform_id=?"); $total->execute([$pid]); echo json_encode(['success'=>true,'credits'=>$credits,'total'=>(float)$total->fetchColumn()]); break; diff --git a/db/schema.sql b/db/schema.sql index 82cf691..846cc74 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -282,6 +282,27 @@ CREATE TABLE `platforms` ( UNIQUE KEY `slug` (`slug`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; +DROP TABLE IF EXISTS `platform_credits`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `platform_credits` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `platform_id` int(11) NOT NULL, + `credits_purchased` decimal(12,2) NOT NULL DEFAULT 0.00, + `credit_date` date NOT NULL, + `payment_method` varchar(100) DEFAULT NULL, + `notes` text DEFAULT NULL, + `type` enum('credit','debit') NOT NULL DEFAULT 'credit', + `purchase_ref_id` int(11) DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + KEY `platform_id` (`platform_id`), + KEY `credit_date` (`credit_date`), + KEY `idx_pc_type` (`type`), + KEY `idx_pc_ref` (`purchase_ref_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `referral_social_shares`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8mb4 */;