AAIVA Daily Updates pushed to production อัปเดตขึ้นโปรดักชัน
Open dashboard →เปิดแดชบอร์ด →
Six operator-safety and ops-reliability features shipped today: every backend request is now traceable to a single log line, operators can freeze a member's withdrawals with a hold flag, a duplicate-account detector surfaces shared phone numbers across the player list, a risk-score queue ranks members needing review, a full audit-log search with CSV export goes live under Settings, and both deposit and withdrawal queues gain bulk approve / reject with per-item auditing.วันนี้ส่งฟีเจอร์ความปลอดภัยและความน่าเชื่อถือของระบบสำหรับผู้ดำเนินการ 6 ฟีเจอร์: คำขอทุกรายการในระบบหลังบ้านตอนนี้ตรวจสอบได้จากบรรทัดล็อกเดียว ผู้ดำเนินการสามารถอายัดการถอนเงินของสมาชิกด้วยแฟล็ก Hold ตัวตรวจจับบัญชีซ้ำแสดงหมายเลขโทรศัพท์ที่ใช้ร่วมกันในรายการผู้เล่น คิวคะแนนความเสี่ยงจัดอันดับสมาชิกที่ต้องตรวจสอบ การค้นหา Audit Log พร้อมส่งออก CSV เปิดใช้งานในหน้าตั้งค่าแล้ว และคิวฝากและถอนเงินรองรับอนุมัติ/ปฏิเสธแบบกลุ่มพร้อมบันทึกรายการทีละรายการ
Ops & reliability การดำเนินงานและความน่าเชื่อถือ

Structured request logging — every backend call leaves a searchable trace

ล็อกคำขออย่างมีโครงสร้าง — ทุกการเรียกระบบหลังบ้านทิ้งร่องรอยที่ค้นหาได้

  • Every HTTP request now writes one structured log line containing the request ID, path, status code, and response time in milliseconds — so a single grep is enough to pull the full context of any incident.
  • Request IDs are consistent end-to-end, making it straightforward to correlate a user-reported error with the exact server entry without sifting through unstructured output.
  • ทุกคำขอ HTTP ตอนนี้เขียนบรรทัดล็อกมีโครงสร้างหนึ่งบรรทัด ที่มี ID คำขอ path รหัสสถานะ และเวลาตอบสนองเป็นมิลลิวินาที — ค้นหาครั้งเดียวก็ดึงบริบทเต็มของเหตุการณ์ใด ๆ ได้
  • ID คำขอสอดคล้องกันตลอดเส้นทาง ทำให้เชื่อมข้อผิดพลาดที่สมาชิกรายงานกับรายการเซิร์ฟเวอร์ที่แน่ชัดได้โดยไม่ต้องคัดกรองเอาต์พุตที่ไม่มีโครงสร้าง
Fraud containment การควบคุมการฉ้อโกง

Member hold / freeze — block withdrawals and record the reason

อายัด/ระงับสมาชิก — บล็อกการถอนและบันทึกเหตุผล

  • Any member can be placed on hold from their player profile. A red "On hold" badge appears on the profile and a Hold / Release toggle lets you flip the status with a required reason — kept in the audit trail.
  • Held members cannot have withdrawals approved — pending withdrawal requests for a held member are blocked at the approval step until the hold is explicitly released by an operator.
  • The hold reason is recorded and visible on the profile so any operator picking up the case can see why the freeze was applied without chasing history.
  • สมาชิกสามารถถูกอายัดได้จากโปรไฟล์ผู้เล่น · ป้าย "On hold" สีแดงปรากฏบนโปรไฟล์ และปุ่มสลับ Hold / Release ให้เปลี่ยนสถานะพร้อมบังคับระบุเหตุผล ซึ่งถูกเก็บไว้ใน Audit Trail
  • สมาชิกที่ถูกอายัดไม่สามารถอนุมัติการถอนได้ — คำขอถอนที่รอดำเนินการของสมาชิกที่ถูกอายัดจะถูกบล็อกที่ขั้นตอนอนุมัติจนกว่าผู้ดำเนินการจะปลดอายัดอย่างชัดเจน
  • เหตุผลการอายัดถูกบันทึกและมองเห็นได้บนโปรไฟล์ ผู้ดำเนินการคนใดที่รับช่วงต่อก็ทราบทันทีว่าทำไมจึงมีการระงับ โดยไม่ต้องค้นหาประวัติ
Duplicate-account detector ตรวจจับบัญชีซ้ำ

Spot shared phone numbers and hold an entire cluster in one click

ตรวจพบหมายเลขโทรศัพท์ที่ใช้ร่วมกันและอายัดทั้งกลุ่มในคลิกเดียว

  • A new "Duplicate accounts" view under Players clusters members who share the same phone number — a common signal for multi-accounting — so the pattern is visible at a glance rather than buried in individual profiles.
  • Each cluster has a one-click "Hold all" that places every member in the group on hold simultaneously, with the reason applied to each account in the audit log.
  • มุมมอง "Duplicate accounts" ใหม่ใต้เมนู Players จัดกลุ่มสมาชิกที่ใช้หมายเลขโทรศัพท์เดียวกัน — สัญญาณทั่วไปของการสร้างหลายบัญชี — เพื่อให้เห็นรูปแบบได้ทันทีแทนที่จะฝังอยู่ในโปรไฟล์แต่ละราย
  • แต่ละกลุ่มมีปุ่ม "Hold all" คลิกเดียว ที่อายัดสมาชิกทุกคนในกลุ่มพร้อมกัน โดยบันทึกเหตุผลลงใน Audit Log ในแต่ละบัญชี
Risk review queue คิวตรวจสอบความเสี่ยง

A ranked list of members to review, scored 0–100

รายการสมาชิกที่ต้องตรวจสอบ เรียงตามคะแนน 0–100

  • A new "Risk queue" under Players ranks every member by a 0–100 risk score combining four signals: shared phone number, high bonus-to-deposit ratio, high withdrawal-to-deposit ratio, and an active hold flag.
  • Each row has an inline Hold toggle so you can act on a flagged member without leaving the queue — no need to open their profile first.
  • The queue is designed to be worked top-down: highest-risk members first so the most urgent cases are never buried under lower-priority rows.
  • "Risk queue" ใหม่ใต้เมนู Players จัดอันดับสมาชิกทุกคนด้วยคะแนนความเสี่ยง 0–100 ผสมสี่สัญญาณ: หมายเลขโทรศัพท์ซ้ำ อัตราโบนัสต่อยอดฝากสูง อัตราการถอนต่อยอดฝากสูง และแฟล็ก Hold ที่ยังใช้งาน
  • แต่ละแถวมีปุ่มสลับ Hold ในบรรทัด เพื่อให้ดำเนินการกับสมาชิกที่ถูกแจ้งเตือนได้โดยไม่ต้องออกจากคิว ไม่จำเป็นต้องเปิดโปรไฟล์ก่อน
  • คิวออกแบบให้ทำงานจากบนลงล่าง: สมาชิกความเสี่ยงสูงสุดอยู่ก่อน ทำให้กรณีเร่งด่วนที่สุดไม่ถูกฝังใต้แถวที่มีลำดับความสำคัญต่ำกว่า
Audit-log search ค้นหา Audit Log

Search the full audit trail and export to CSV

ค้นหา Audit Trail ทั้งหมดและส่งออกเป็น CSV

  • A new "Audit log" page under Settings exposes the full event history — every operator action recorded since the system started — with filters for event type, operator, member, and date range.
  • Results can be exported to CSV for external review, compliance reporting, or sharing with another team without granting them dashboard access.
  • หน้า "Audit log" ใหม่ใต้เมนู Settings แสดงประวัติเหตุการณ์ทั้งหมด — ทุกการกระทำของผู้ดำเนินการที่บันทึกตั้งแต่ระบบเริ่มทำงาน — พร้อมตัวกรองตามประเภทเหตุการณ์ ผู้ดำเนินการ สมาชิก และช่วงวันที่
  • ผลลัพธ์สามารถส่งออกเป็น CSV สำหรับการตรวจสอบภายนอก รายงานการปฏิบัติตามข้อกำหนด หรือแบ่งปันกับทีมอื่นโดยไม่ต้องให้สิทธิ์เข้าถึงแดชบอร์ด
Bulk approve / reject อนุมัติ/ปฏิเสธแบบกลุ่ม

Check multiple items and act on all of them at once

เลือกหลายรายการและดำเนินการทั้งหมดพร้อมกัน

  • The Deposit and Withdrawal queues now have a checkbox on every row and a select-all in the header. Once you have a selection, a floating toolbar appears with Approve all and Reject all buttons.
  • Each item is still individually audited — bulk actions write one audit entry per transaction, not a single group entry, so the record is as clean as if each had been handled one at a time.
  • Held members are skipped on bulk approve automatically: if a selected withdrawal belongs to a member on hold, it is passed over (and counted in a skip summary) so the hold is never accidentally bypassed.
  • คิวฝากและถอนตอนนี้มีช่องทำเครื่องหมายทุกแถวและ "เลือกทั้งหมด" ในส่วนหัว · เมื่อเลือกแล้ว แถบเครื่องมือลอยปรากฏพร้อมปุ่ม "อนุมัติทั้งหมด" และ "ปฏิเสธทั้งหมด"
  • แต่ละรายการยังถูกบันทึกทีละรายการ — การดำเนินการกลุ่มเขียนรายการ Audit หนึ่งรายการต่อธุรกรรม ไม่ใช่รายการกลุ่มเดียว เพื่อให้บันทึกสะอาดเหมือนจัดการทีละรายการ
  • สมาชิกที่ถูกอายัดจะถูกข้ามโดยอัตโนมัติเมื่ออนุมัติแบบกลุ่ม: หากการถอนที่เลือกเป็นของสมาชิกที่อยู่ใน Hold ระบบจะข้ามรายการนั้น (และนับในสรุปรายการที่ถูกข้าม) เพื่อไม่ให้ Hold ถูกยกเลิกโดยไม่ตั้งใจ
Under the hood · reliability เบื้องหลัง · ความเสถียร

Steadier automated checks behind every release

ชุดทดสอบอัตโนมัติที่นิ่งขึ้นเบื้องหลังทุกการปล่อยอัปเดต

  • The automated test suite that guards the backoffice now runs deterministically. Two page-render checks occasionally failed only when the whole suite ran at once — a timing quirk, never a real bug; they now wait for the page to actually finish rendering instead of a fixed delay. Nothing you see in the app changes — this just keeps the pre-release safety gate trustworthy.
  • ชุดทดสอบอัตโนมัติที่คอยตรวจระบบหลังบ้านตอนนี้ทำงานได้ผลคงที่ · การตรวจการแสดงผลสองรายการเคยล้มเหลวเป็นครั้งคราวเฉพาะตอนรันทั้งชุดพร้อมกัน — เป็นเรื่องจังหวะเวลา ไม่ใช่บั๊กจริง · ตอนนี้รอให้หน้าแสดงผลเสร็จจริงแทนการหน่วงเวลาคงที่ · ไม่มีอะไรเปลี่ยนในสิ่งที่คุณเห็นในแอป เพียงทำให้ขั้นตอนตรวจก่อนปล่อยอัปเดตน่าเชื่อถือ
Saved filter views มุมมองตัวกรองที่บันทึกไว้

Name a filter combo once, recall it in one click

ตั้งชื่อชุดตัวกรองครั้งเดียว เรียกใช้ได้ในคลิกเดียว

  • The Deposit, Withdrawal and Member lists now have a "Save view" button above the filter bar. Name your current filters (e.g. "Pending THB today") and they appear as one-click pills next to the bar — no more re-entering the same filters every shift. Saved in your browser; remove a view with its ×.
  • หน้ารายการฝาก ถอน และสมาชิก มีปุ่ม "บันทึกมุมมอง" เหนือแถบตัวกรองแล้ว · ตั้งชื่อชุดตัวกรองปัจจุบัน (เช่น "รอตรวจ THB วันนี้") แล้วมันจะปรากฏเป็นป้ายคลิกเดียวข้างแถบ — ไม่ต้องกรอกตัวกรองเดิมซ้ำทุกกะ · บันทึกในเบราว์เซอร์ ลบได้ด้วยปุ่ม ×
Keyboard-driven queues เคลียร์คิวด้วยคีย์บอร์ด

Clear the deposit/withdrawal queues without the mouse

เคลียร์คิวฝาก/ถอนได้โดยไม่ต้องใช้เมาส์

  • On the Deposit and Withdrawal queues, j/k (or ↑/↓) move a highlighted row, "a" opens approve and "r" opens reject on it, Esc clears. The confirm popover still opens for each action — this just removes the click-hunting for high-volume operators clearing dozens of rows in a row.
  • ในคิวฝากและถอน ปุ่ม j/k (หรือ ↑/↓) เลื่อนแถวที่ไฮไลต์ · "a" เปิดอนุมัติ และ "r" เปิดปฏิเสธของแถวนั้น · Esc ยกเลิกการเลือก · ป๊อปอัปยืนยันยังเปิดทุกครั้งเช่นเดิม — แค่ตัดการไล่คลิกสำหรับผู้ดูแลที่เคลียร์หลายสิบแถวรวด
Rapid-deposit risk flag ป้ายความเสี่ยงฝากถี่

The risk queue now flags deposit bursts

คิวความเสี่ยงจับรูปแบบฝากถี่แล้ว

  • A member who deposits many times in a short window now carries a "Rapid deposits" flag and a higher risk score — the chip-dumping / structuring pattern the existing duplicate-phone and bonus-ratio signals miss. Surfaces in the Risk queue alongside the other flags.
  • สมาชิกที่ฝากหลายครั้งในช่วงเวลาสั้นจะมีป้าย "ฝากถี่" และคะแนนความเสี่ยงสูงขึ้น — เป็นรูปแบบที่สัญญาณเบอร์ซ้ำและอัตราโบนัสเดิมจับไม่ได้ · แสดงในคิวความเสี่ยงพร้อมป้ายอื่น ๆ
Large-withdrawal review note บันทึกการตรวจสอบยอดถอนสูง

Optional sign-off note on high-value payouts

บันทึกการอนุมัติยอดสูงแบบเปิดใช้ได้

  • An opt-in control: when enabled, approving a withdrawal above a configurable value (measured in THB-equivalent across currencies) requires a short review note first. The note is stored on the withdrawal and in the audit trail — a documented rationale on the highest-value money action. Off by default; turn it on per deployment when you want the control.
  • ตัวควบคุมแบบเปิดใช้ได้: เมื่อเปิด การอนุมัติการถอนที่เกินค่าที่กำหนด (วัดเป็นมูลค่าเทียบเท่า THB ข้ามสกุลเงิน) ต้องใส่บันทึกการตรวจสอบสั้น ๆ ก่อน · บันทึกถูกเก็บไว้บนรายการถอนและในร่องรอยการตรวจสอบ — เหตุผลที่มีหลักฐานสำหรับการเคลื่อนเงินมูลค่าสูงสุด · ปิดไว้โดยค่าเริ่มต้น เปิดเมื่อต้องการ
Under the hood · access control เบื้องหลัง · การควบคุมการเข้าถึง

Tighter role checks on the risk + audit reads

ตรวจสิทธิ์เข้มขึ้นบนข้อมูลความเสี่ยงและการตรวจสอบ

  • The risk views and the audit log now carry an explicit role check (alongside the existing login gate) — defense-in-depth so that, once per-operator logins are switched on, only recognised roles can read member financials. No change to today's shared-password experience.
  • มุมมองความเสี่ยงและบันทึกการตรวจสอบมีการตรวจสิทธิ์ตามบทบาทอย่างชัดเจนแล้ว (เพิ่มเติมจากการล็อกอินเดิม) — เป็นการป้องกันหลายชั้น เพื่อให้เมื่อเปิดล็อกอินรายผู้ดูแล เฉพาะบทบาทที่รับรองเท่านั้นที่อ่านข้อมูลการเงินสมาชิกได้ · ไม่กระทบประสบการณ์รหัสผ่านร่วมในวันนี้
Accessibility การเข้าถึง

The dashboard now honors your system "reduce motion" setting

แดชบอร์ดเคารพการตั้งค่า "ลดการเคลื่อนไหว" ของระบบแล้ว

  • If you turn on "Reduce motion" in your operating system's accessibility settings, the dashboard now quiets its animations and transitions automatically — skeleton shimmers, sliding panels, hover and toggle transitions all settle instead of animating. No setting to find inside the app; it follows the same OS switch every other accessible app respects.
  • Easier on the eyes for motion-sensitive operators and long night shifts. Nothing moves, nothing is hidden, and no workflow changes — the same screens, just calmer. Leave the OS setting off and everything animates exactly as before.
  • หากคุณเปิด "ลดการเคลื่อนไหว" ในการตั้งค่าการเข้าถึงของระบบปฏิบัติการ แดชบอร์ดจะลดแอนิเมชันและทรานซิชันให้อัตโนมัติ — เอฟเฟกต์ skeleton ที่กะพริบ แผงที่เลื่อน ทรานซิชันตอนชี้เมาส์และสลับสถานะ จะนิ่งแทนการเคลื่อนไหว · ไม่ต้องหาการตั้งค่าในแอป มันทำตามสวิตช์เดียวกันของระบบที่แอปซึ่งเข้าถึงได้ทุกตัวเคารพ
  • สบายตาขึ้นสำหรับผู้ดูแลที่ไวต่อการเคลื่อนไหวและกะดึกที่ทำงานยาว · ไม่มีอะไรเคลื่อนไหว ไม่มีอะไรถูกซ่อน และไม่มีขั้นตอนใดเปลี่ยน — หน้าจอเดิม เพียงนิ่งขึ้น · หากปิดการตั้งค่าระบบไว้ ทุกอย่างจะเคลื่อนไหวเหมือนเดิมทุกประการ
The AIVA assistant grew from three tabs into a six-tab mini-dashboard — a new Overview home that opens to at-a-glance cards and charts, two new outreach worklists (At-Risk members and New Depositors), a conversion funnel and channel breakdown in Insights, an "awaiting outcome" filter on Suggestions, and every AIVA list now pages through 50 rows at a time.ผู้ช่วย AIVA ขยายจากสามแท็บเป็นมินิแดชบอร์ดหกแท็บ — มีหน้า Overview ใหม่ที่เปิดมาเจอการ์ดสรุปและกราฟ, เพิ่มสองรายการงานติดต่อลูกค้า (สมาชิกเสี่ยงหลุด และนักฝากใหม่), funnel การแปลงและการแยกตามช่องทางในหน้า Insights, ตัวกรอง "รอผลลัพธ์" บนหน้าคำแนะนำ และทุกรายการของ AIVA แบ่งหน้าทีละ 50 รายการแล้ว
New AIVA home หน้าหลัก AIVA ใหม่

An Overview tab that opens to your whole panel at a glance

แท็บ Overview ที่เปิดมาเห็นภาพรวมทั้งแผงในพริบตา

  • Clicking AIVA now lands on a new Overview screen instead of the suggestions list, organised into three labelled sections — Worklist, Performance and Trends.
  • Worklist shows four cards — pending suggestions, suggestions awaiting an outcome, at-risk members, and new depositors (with today's count). Click any card to jump straight to that tab.
  • Performance shows the conversion rate and call pickup rate, plus a conversion funnel that walks total → dispatched → converted.
  • Trends shows two charts — a doughnut of members per segment, and a combined bar-and-line of daily call volume with the pickup-rate percentage.
  • คลิก AIVA ตอนนี้เข้าหน้า Overview ใหม่ แทนที่จะเป็นรายการคำแนะนำ จัดเป็นสามส่วนมีป้ายกำกับ — คิวงาน ประสิทธิภาพ และแนวโน้ม
  • คิวงานแสดงสี่การ์ด — คำแนะนำที่รอ, คำแนะนำที่รอผลลัพธ์, สมาชิกเสี่ยงหลุด และนักฝากใหม่ (พร้อมจำนวนวันนี้) · คลิกการ์ดใดก็ได้เพื่อกระโดดไปแท็บนั้นทันที
  • ประสิทธิภาพแสดงอัตราการแปลงและอัตรารับสาย พร้อม funnel การแปลงที่ไล่จาก ทั้งหมด → ส่งแล้ว → สำเร็จ
  • แนวโน้มแสดงสองกราฟ — โดนัทสัดส่วนสมาชิกต่อเซกเมนต์ และกราฟแท่งคู่เส้นของจำนวนการโทรรายวันพร้อมเปอร์เซ็นต์อัตรารับสาย
Two new worklists สองรายการงานใหม่

See who's slipping away, and who just arrived

เห็นว่าใครกำลังจะหลุด และใครเพิ่งเข้ามา

  • At-Risk lists members in a risk segment — At Risk, Need Attention, About To Sleep, Hibernating — most valuable first, so you reach the biggest spenders before they lapse.
  • New Depositors lists members who just made their first deposit, newest first — a ready-made welcome-outreach list.
  • Both replace the short-lived Callbacks and Operators tabs from earlier in the day, and slot into the same in-page tab strip beside Suggestions, Insights and Call Log.
  • สมาชิกเสี่ยงหลุด แสดงสมาชิกในเซกเมนต์เสี่ยง — At Risk, Need Attention, About To Sleep, Hibernating — เรียงตามมูลค่ามากสุดก่อน เพื่อให้ติดต่อคนที่ฝากเยอะก่อนจะหลุดไป
  • นักฝากใหม่ แสดงสมาชิกที่เพิ่งฝากครั้งแรก เรียงใหม่สุดก่อน — เป็นรายการติดต่อต้อนรับพร้อมใช้
  • ทั้งสองมาแทนแท็บ Callbacks และ Operators ที่ลองช่วงต้นวัน และวางอยู่ในแถบแท็บในหน้าเดียวกันข้าง คำแนะนำ วิเคราะห์ และบันทึกการโทร
Insights & Suggestions วิเคราะห์และคำแนะนำ

See what's converting, and close the loop

เห็นว่าอะไรแปลงสำเร็จ และปิดงานให้ครบ

  • Insights gained a conversion funnel and an SMS-vs-call effectiveness breakdown — so you can see which channel actually converts, not just how many suggestions were generated.
  • Suggestions gained an "Awaiting outcome" filter with a live backlog count — surfacing suggestions you dispatched but never recorded a result for, so none sit forgotten in limbo.
  • หน้าวิเคราะห์เพิ่ม funnel การแปลงและการแยกประสิทธิภาพ SMS เทียบกับโทร — เพื่อให้เห็นว่าช่องทางไหนแปลงสำเร็จจริง ไม่ใช่แค่จำนวนคำแนะนำที่สร้าง
  • หน้าคำแนะนำเพิ่มตัวกรอง "รอผลลัพธ์" พร้อมตัวนับงานค้างสด — ดึงคำแนะนำที่ส่งออกไปแล้วแต่ยังไม่ได้บันทึกผลขึ้นมา เพื่อไม่ให้มีรายการค้างถูกลืม
Lists that scale รายการที่รองรับข้อมูลเยอะ

Pagination everywhere, sortable columns, and a tidier pager

แบ่งหน้าทุกที่ คอลัมน์เรียงได้ และแถบหน้าที่เป็นระเบียบ

  • Every AIVA list pages through 50 rows at a time — Suggestions, Call Log, At-Risk and New Depositors all get previous/next controls with a running count.
  • The At-Risk worklist sorts on any column — username, segment, deposits or P&L — and starts each sort from page one.
  • The page controls now sit clear of the floating AIVA chat button, which used to overlap the "next" arrow at the bottom-right of a full table.
  • ทุกรายการของ AIVA แบ่งหน้าทีละ 50 แถว — คำแนะนำ บันทึกการโทร สมาชิกเสี่ยงหลุด และนักฝากใหม่ มีปุ่มก่อนหน้า/ถัดไป พร้อมตัวนับ
  • รายการสมาชิกเสี่ยงหลุดเรียงได้ทุกคอลัมน์ — ยูสเซอร์เนม เซกเมนต์ ยอดฝาก หรือกำไร/ขาดทุน — และเริ่มเรียงจากหน้าแรกทุกครั้ง
  • ปุ่มแบ่งหน้าตอนนี้อยู่พ้นปุ่มแชต AIVA ที่ลอยอยู่ ซึ่งเคยทับปุ่ม "ถัดไป" ที่มุมขวาล่างของตารางเต็มหน้า
Quicker access เข้าถึงเร็วขึ้น

Left-click any player name to open their profile

คลิกซ้ายที่ชื่อผู้เล่นเพื่อเปิดโปรไฟล์

  • A single left-click on a player's name now opens that player's full profile — anywhere a name appears across the dashboard. No more right-click-then-choose.
  • The right-click menu still has the quick actions — Ask AIVA about this player, the 360 timeline, send an SMS and log a call — it just drops the now-redundant "Open profile" entry.
  • คลิกซ้ายครั้งเดียวที่ชื่อผู้เล่นจะเปิดโปรไฟล์เต็มของผู้เล่นคนนั้น — ทุกที่ที่มีชื่อปรากฏทั่วทั้งแดชบอร์ด ไม่ต้องคลิกขวาแล้วเลือกอีกต่อไป
  • เมนูคลิกขวายังมีทางลัดเหมือนเดิม — ถาม AIVA เกี่ยวกับผู้เล่นนี้ ไทม์ไลน์ 360 ส่ง SMS และบันทึกการโทร — เพียงเอารายการ "เปิดโปรไฟล์" ที่ซ้ำซ้อนออก
Time-aware Overview Overview ตามช่วงเวลา

Scope the Overview by period, and see what changed

เลือกช่วงเวลาของ Overview และดูว่าอะไรเปลี่ยนไป

  • The Overview now has a Today / 7 days / 30 days / All selector at the top that re-scopes its numbers and charts to that window (defaults to the last 30 days).
  • Each metric carries a small ▲/▼ change vs the previous equal period — pending, awaiting, new depositors, conversion rate and pickup rate — coloured green when the move is good for that metric (more conversions, fewer waiting) and red when it isn't.
  • The at-risk count and the segment doughnut stay a "right now" snapshot — they describe the current state rather than a window, so they're marked "Current".
  • Overview มีตัวเลือก วันนี้ / 7 วัน / 30 วัน / ทั้งหมด ที่ด้านบนแล้ว ซึ่งปรับขอบเขตตัวเลขและกราฟให้อยู่ในช่วงนั้น (ค่าเริ่มต้นคือ 30 วันล่าสุด)
  • แต่ละตัวเลขมีป้าย ▲/▼ เทียบกับช่วงก่อนหน้าที่เท่ากัน — คำแนะนำที่รอ รอผลลัพธ์ นักฝากใหม่ อัตราการแปลง และอัตรารับสาย — เป็นสีเขียวเมื่อการเปลี่ยนแปลงเป็นเรื่องดีสำหรับตัวเลขนั้น (แปลงสำเร็จมากขึ้น รอน้อยลง) และสีแดงเมื่อไม่ดี
  • จำนวนสมาชิกเสี่ยงหลุดและโดนัทเซกเมนต์ยังเป็นภาพ "ตอนนี้" — บอกสถานะปัจจุบันไม่ใช่ช่วงเวลา จึงกำกับว่า "ปัจจุบัน"
Accessibility polish ความเรียบร้อยด้านการเข้าถึง

Top-bar controls read correctly in English

ปุ่มแถบบนอ่านถูกต้องในโหมดอังกฤษ

  • The quick-actions (+), menu toggle and home logo carried bilingual "Thai / English" labels for screen readers and tooltips, so they stayed Thai-then-English in English mode. They now follow the language toggle like everything else — plain "Quick actions", "Toggle menu", "Home" in English. A whole-site English sweep now comes back completely clean.
  • ปุ่มทางลัด (+) ปุ่มสลับเมนู และโลโก้หน้าหลักเคยมีป้าย "ไทย / อังกฤษ" สองภาษา สำหรับ screen reader และ tooltip จึงค้างเป็นไทยปนอังกฤษในโหมดอังกฤษ · ตอนนี้ตามสวิตช์ภาษาเหมือนทุกอย่าง — เป็น "Quick actions", "Toggle menu", "Home" ล้วนในภาษาอังกฤษ และการกวาดทั้งเว็บในโหมดอังกฤษสะอาดหมดแล้ว
The dashboard got a top-to-bottom visual refresh — one emerald theme across every screen, a redesigned top bar with the logo and your own quick-actions button, a collapsible icon menu and smooth liquid-glass tabs — and the English page was swept in a real browser to fully English, closing the last few hundred untranslated strings — and you can now upload your own logoแดชบอร์ดได้รับการปรับโฉมตั้งแต่บนจรดล่าง — ธีมเขียวมรกตเดียวทุกหน้าจอ แถบบนดีไซน์ใหม่พร้อมโลโก้และปุ่มทางลัดของคุณเอง เมนูไอคอนพับได้ และแท็บลิควิดกลาสที่ลื่นไหล — และหน้าโหมดอังกฤษถูกกวาดด้วยเบราว์เซอร์จริงให้เป็นอังกฤษครบ ปิดข้อความที่ยังไม่แปลหลายร้อยรายการ — และตอนนี้อัปโหลดโลโก้ของคุณเองได้แล้ว
A fresh look โฉมใหม่

One consistent look across the whole dashboard

หน้าตาเดียวกันทั้งระบบ

  • Every screen now shares one emerald theme. The patchwork of dark-teal chrome, bright-yellow page headers and a separate dark-navy Customer Data Platform is gone — the sidebar, top bar, report headers, the CDP and every page band are now the same green, top to bottom.
  • Report and section headers all match. Reports that used to render onto yellow banners now use the same emerald header strip with a clean "LIVE" tag as everywhere else, and the Customer Data Platform was rebuilt to the same light theme — its tabs included.
  • A refreshed logo, now in the top bar. The brand logo moved out of the sidebar to the top-left of the bar; click it (or press Enter) to jump home from anywhere.
  • Rough edges cleaned up. Stray white separation lines under the top bar and behind the logo were removed, the menu search box was tidied away, and a redundant page-title band on Home was hidden.
  • ทุกหน้าจอใช้ธีมเขียวมรกตเดียวกันแล้ว · โครมสีเขียวเข้มปนหัวหน้าสีเหลืองและหน้า Customer Data Platform สีกรมท่าเข้มที่เคยปนกันหายไป — เมนูข้าง แถบบน หัวรายงาน CDP และทุกแถบของหน้าเป็นสีเขียวเดียวกันทั้งหมด
  • หัวรายงานและหัวส่วนต่าง ๆ เข้าชุดกันหมด · รายงานที่เคยขึ้นบนแบนเนอร์เหลืองตอนนี้ใช้แถบหัวสีเขียวมรกตพร้อมป้าย "LIVE" สะอาดตาเหมือนที่อื่น และ Customer Data Platform ถูกสร้างใหม่ให้เป็นธีมสว่างชุดเดียวกัน รวมถึงแท็บ
  • โลโก้โฉมใหม่ ย้ายขึ้นแถบบน · โลโก้แบรนด์ย้ายจากเมนูข้างมาอยู่มุมซ้ายบนของแถบ คลิก (หรือกด Enter) เพื่อกลับหน้าหลักได้จากทุกที่
  • เก็บรายละเอียดเล็ก ๆ ให้เรียบร้อย · เส้นแบ่งสีขาวใต้แถบบนและหลังโลโก้ถูกเอาออก ช่องค้นหาเมนูถูกซ่อนให้เรียบ และแถบชื่อหน้าซ้ำซ้อนบนหน้าหลักถูกซ่อน
Top bar & navigation แถบบนและการนำทาง

A redesigned top bar, a collapsible menu, and your own quick actions

แถบบนดีไซน์ใหม่ เมนูพับได้ และทางลัดของคุณเอง

  • The top bar was redesigned. It now carries the logo on the left and a tidy row on the right — clock, a notifications bell, a quick-actions button, language, the emergency lock, your account and logout.
  • A "+" quick-actions menu you control. The green + opens shortcuts to the pages you use most. Choose exactly which appear from System Settings — tick or untick any of nine destinations and the menu updates instantly (and it reads correctly in English now).
  • Collapse the menu for more room. The toggle at the top-left smoothly shrinks the left menu to a slim icon-only rail, so wide tables and dashboards get the full width; click again to bring the labels back.
  • Smoother tab navigation everywhere. The in-page tabs — and the Customer Data Platform tabs — now use a frosted "liquid-glass" selector that glides to the tab you pick and can even be dragged between options.
  • แถบบนถูกออกแบบใหม่ · ตอนนี้มีโลโก้อยู่ซ้าย และแถวขวาที่เป็นระเบียบ — นาฬิกา กระดิ่งแจ้งเตือน ปุ่มทางลัด ภาษา ปุ่มล็อกฉุกเฉิน บัญชีของคุณ และออกจากระบบ
  • เมนูทางลัด "+" ที่คุณกำหนดเอง · ปุ่ม + สีเขียวเปิดทางลัดไปหน้าที่คุณใช้บ่อย เลือกได้เลยว่าจะให้รายการใดแสดงจากหน้าตั้งค่าระบบ — ติ๊กหรือเอาออกจากเก้าปลายทาง แล้วเมนูอัปเดตทันที (และตอนนี้แสดงเป็นภาษาอังกฤษถูกต้องแล้ว)
  • พับเมนูเพื่อพื้นที่มากขึ้น · ปุ่มสลับมุมซ้ายบนย่อเมนูซ้ายให้เหลือแถบไอคอนล้วนแบบบางอย่างนุ่มนวล เพื่อให้ตารางกว้างและแดชบอร์ดได้พื้นที่เต็ม คลิกอีกครั้งเพื่อเอาป้ายกลับมา
  • การสลับแท็บลื่นขึ้นทุกที่ · แท็บในหน้า — รวมถึงแท็บ Customer Data Platform — ใช้ตัวเลือกแบบ "ลิควิดกลาส" ฝ้า ที่เลื่อนไปยังแท็บที่เลือก และลากระหว่างตัวเลือกได้ด้วย
Language & polish ภาษาและความเรียบร้อย

English mode, wall-to-wall

โหมดอังกฤษ ครบทั้งระบบ

  • Every remaining Thai string on the English page is translated. About 130 new dictionary entries cover the deep report pages, the currency-pool leaderboards (including every sortable column header per currency), the AIVA suggestion / insight / call tables, analytics funnels and heatmap weekday labels, confirmation dialogs, toasts and the page-size dropdowns. The operator sign-in overlay, which used to show bilingual "ชื่อผู้ใช้ / Username" labels, now reads as pure English in English mode.
  • Numbers and units finally translate together. Lines like "6 สกุล", "1,234 ผู้เล่น" or "ทศนิยม: .47" are built as one piece of text, which the word-for-word dictionary could never catch — those spots now translate their unit at the moment they draw, so English mode shows "6 currencies", "1,234 players", "Decimal: .47".
  • A one-character bug, fixed. The USDT reference-rate warning on the deposit + withdrawal report stayed Thai in English mode because its dictionary entry was missing a single tone mark — the lookup could never match. Found by the new sweep below.
  • Screen-reader labels translate too. Hidden accessibility labels (menu, logout, send message) now follow the language toggle, and well-known seeded values — bank-account names like "หลัก / สำรอง" and AIVA's starter suggestions — display as "Primary / Secondary" and English suggestions while anything an operator typed passes through untouched.
  • A standing quality gate. A new automated check boots the app against a throwaway database, opens a real browser in English mode, walks all 33 pages and reports any visible Thai — so future features can't quietly ship half-translated again.
  • ข้อความไทยที่เหลือทั้งหมดบนหน้าโหมดอังกฤษถูกแปลครบ · คำแปลใหม่ราว 130 รายการครอบคลุมหน้ารายงานชั้นใน, ตารางอันดับ currency pool (รวมหัวคอลัมน์เรียงได้ของทุกสกุล), ตารางคำแนะนำ / วิเคราะห์ / การโทรของ AIVA, funnel และป้ายวันบน heatmap, กล่องยืนยัน, toast และตัวเลือกจำนวนแถวต่อหน้า · หน้าล็อกอิน operator ที่เคยโชว์สองภาษา "ชื่อผู้ใช้ / Username" ตอนนี้เป็นอังกฤษล้วนในโหมดอังกฤษ
  • ตัวเลขกับหน่วยแปลไปด้วยกันแล้ว · ข้อความแบบ "6 สกุล", "1,234 ผู้เล่น" หรือ "ทศนิยม: .47" ถูกประกอบเป็นชิ้นเดียวซึ่งพจนานุกรมแบบเทียบคำต่อคำจับไม่ได้ — จุดเหล่านี้แปลหน่วยตอนวาดผลแล้ว โหมดอังกฤษจึงเห็น "6 currencies", "1,234 players", "Decimal: .47"
  • บั๊กหนึ่งตัวอักษร แก้แล้ว · คำเตือนอัตราอ้างอิง USDT บนรายงานฝาก+ถอนค้างเป็นภาษาไทยในโหมดอังกฤษ เพราะรายการในพจนานุกรมพิมพ์ขาดวรรณยุกต์ไปตัวเดียว ทำให้เทียบไม่เจอตลอด — เจอด้วยตัวกวาดอัตโนมัติด้านล่าง
  • ป้ายสำหรับ screen reader ก็แปลด้วย · ป้าย accessibility ที่ซ่อนอยู่ (เมนู ออกจากระบบ ส่งข้อความ) ตามสวิตช์ภาษาแล้ว และค่าตั้งต้นที่ระบบ seed ไว้ — ชื่อบัญชีธนาคารอย่าง "หลัก / สำรอง" และคำแนะนำเริ่มต้นของ AIVA — แสดงเป็น "Primary / Secondary" และคำแนะนำภาษาอังกฤษ ส่วนค่าที่ operator พิมพ์เองผ่านไปตามเดิมไม่ถูกแตะ
  • ด่านคุณภาพถาวร · ตัวตรวจอัตโนมัติใหม่บูตระบบกับฐานข้อมูลชั่วคราว เปิดเบราว์เซอร์จริงในโหมดอังกฤษ เดินครบทั้ง 33 หน้า และรายงานข้อความไทยที่ยังมองเห็น — ฟีเจอร์ใหม่ในอนาคตจะแอบขึ้นระบบแบบแปลครึ่ง ๆ กลาง ๆ ไม่ได้อีก
Easier navigation นำทางง่ายขึ้น

A simpler menu — 9 entries, tabs inside the page

เมนูเรียบง่ายขึ้น — 9 รายการ แท็บอยู่ในหน้า

  • The left menu is now a flat list of nine entries. No more expanding groups or nested sub-menus — around thirty entries were folded into one entry per area: Home, Dashboard, Transactions, AutoPeer, Members, Customer Data Platform, Reports, AIVA and Settings.
  • Screens switch with iPhone-style pill tabs at the top of the page. Each area shows its screens on a rounded track where the active screen is a raised white card — deposits / withdrawals under Transactions, all ten reports side by side under Reports, suggestions / insights / call log under AIVA. One click, without leaving the page, and the tab row always stays above the data tables in both languages.
  • Report tabs read as clean names — First deposit, Cashback, Commission… — with no numbers, so all ten fit in one row. The numbers still live on each report's page title and now count in order, 6.1 First deposit through 6.10 Hidden deposits (they used to start at 6.4 and jump around); the two welcome notifications that pointed at the old numbers were reworded to use report names.
  • Menu search still finds everything. ⌘K search knows about screens that moved behind tabs — typing "Cashback" and pressing Enter jumps straight to that report.
  • The logo is now a Home button. Click the tiamut logo (or press Enter on it) to get back to the home screen from anywhere.
  • Deposit and withdrawal report columns sort for real. Clicking a column header re-orders the entire dataset on the server — not just the rows on screen.
  • เมนูซ้ายเป็นรายการแบนเก้ารายการแล้ว · ไม่มีกลุ่มที่ต้องกดกางหรือเมนูย่อยซ้อนกันอีก — ราวสามสิบรายการถูกพับเหลือพื้นที่ละหนึ่งรายการ: หน้าหลัก แดชบอร์ด ธุรกรรม AutoPeer สมาชิก Customer Data Platform รายงาน AIVA และตั้งค่า
  • สลับหน้าจอด้วยแท็บทรงแคปซูลสไตล์ iPhone ที่ด้านบนของหน้า · แต่ละพื้นที่แสดงหน้าจอบนแถบโค้งมน โดยหน้าจอที่เปิดอยู่เป็นการ์ดขาวนูน — ฝาก / ถอน ใต้ธุรกรรม, รายงานทั้งสิบเรียงกันใต้รายงาน, คำแนะนำ / วิเคราะห์ / บันทึกการโทร ใต้ AIVA · คลิกเดียวโดยไม่ออกจากหน้า และแถวแท็บอยู่เหนือตารางข้อมูลเสมอ ทั้งโหมดไทยและอังกฤษ
  • แท็บรายงานเป็นชื่อล้วน อ่านง่าย — ฝากแรก, Cashback, Commission… — ไม่มีตัวเลข ทำให้ทั้งสิบแท็บพอดีแถวเดียว · ตัวเลขยังอยู่บนหัวข้อของแต่ละหน้ารายงานและตอนนี้เรียงตามลำดับ 6.1 ฝากแรก ถึง 6.10 ฝากซ่อน (เดิมเริ่มที่ 6.4 และกระโดดไปมา) · การแจ้งเตือนต้อนรับสองรายการที่อ้างเลขเดิมถูกเปลี่ยนเป็นชื่อรายงานแทน
  • ค้นหาเมนูยังเจอครบทุกหน้า · ค้นหา ⌘K รู้จักหน้าจอที่ย้ายไปอยู่หลังแท็บแล้ว — พิมพ์ "Cashback" แล้วกด Enter กระโดดตรงไปรายงานนั้นได้เลย
  • โลโก้เป็นปุ่มหน้าหลักแล้ว · คลิกโลโก้ tiamut (หรือกด Enter ที่โลโก้) เพื่อกลับหน้าหลักได้จากทุกที่
  • คอลัมน์รายงานฝาก-ถอนเรียงข้อมูลจริงทั้งชุด · คลิกหัวคอลัมน์แล้วระบบเรียงข้อมูลทั้งหมดใหม่ฝั่งเซิร์ฟเวอร์ — ไม่ใช่แค่แถวที่เห็นบนจอ
Branding & safeguards แบรนด์และการป้องกัน

Upload your own logo — plus live work queues and cost safeguards

อัปโหลดโลโก้ของคุณเอง — พร้อมคิวงานสดและการป้องกันค่าใช้จ่าย

  • Upload your own logo. System Settings has a new Logo control — upload a PNG, SVG or JPG and it replaces the brand mark in the top bar on a clean chip. Each prefix keeps its own, and "Remove" restores the default mark.
  • Live auto-refresh now covers the deposit and withdrawal work queues. The "Live" pill — already on Home and the Dashboard — now also keeps the pending deposit and withdrawal queues current every 30 seconds, refreshing silently and pausing while you have a confirm dialog open.
  • Cost safeguards on the AI and SMS paths. The chat assistant and SMS-send endpoints are now rate-limited per source, so a stuck script or repeated calls can't run up an AI or messaging bill — over the limit, the request is simply asked to retry shortly.
  • อัปโหลดโลโก้ของคุณเอง · หน้าตั้งค่าระบบมีช่องโลโก้ใหม่ — อัปโหลด PNG, SVG หรือ JPG แล้วระบบจะแทนที่โลโก้แบรนด์บนแถบบนในกรอบสะอาดตา แต่ละ prefix มีของตัวเอง และปุ่ม "ลบ" คืนค่าโลโก้เริ่มต้น
  • อัปเดตสดครอบคลุมคิวงานฝากและถอนแล้ว · ปุ่ม "Live" ที่มีอยู่บนหน้าหลักและแดชบอร์ด ตอนนี้คอยอัปเดตคิวฝากและถอนที่รอดำเนินการทุก 30 วินาทีด้วย รีเฟรชแบบเงียบ ๆ และหยุดพักระหว่างที่เปิดกล่องยืนยัน
  • การป้องกันค่าใช้จ่ายบนช่อง AI และ SMS · ผู้ช่วยแชตและเส้นทางส่ง SMS ถูกจำกัดอัตราตามต้นทางแล้ว สคริปต์ที่ค้างหรือการเรียกซ้ำ ๆ จึงไม่ทำให้ค่า AI หรือค่าส่งข้อความบานปลาย — เมื่อเกินลิมิต ระบบจะให้ลองใหม่อีกครั้งในอีกสักครู่
A ten-improvement hardening round — nightly database backups, an audited undo for misclicked approvals, an oldest-first pending queue with overdue alerts, AIVA's suggestions and call log becoming a real working loop, and the chat assistant answering in production · then the backoffice got a whole new face (dark-teal sidebar, line icons, ⌘K quick search), the dashboard and reports learned date ranges with previous-period deltas and a queue mode, upgrades now ship with one password-guarded click, the AIVA dashboard gained slot 8.4 AI Calling — and a next-generation rebuild of the backoffice went live side-by-side at /aiva4/รอบปรับปรุงสิบรายการ — ฐานข้อมูลสำรองตัวเองทุกคืน กดอนุมัติพลาดย้อนกลับได้พร้อม audit คิวรอดำเนินการเรียงเก่าสุดก่อนพร้อมแจ้งเตือนรายการค้าง คำแนะนำและบันทึกการโทรของ AIVA กลายเป็นวงจรทำงานจริง และผู้ช่วยแชตตอบบน production แล้ว · จากนั้นหลังบ้านได้โฉมใหม่ทั้งระบบ (แถบเมนูเขียวเข้ม ไอคอนลายเส้น ค้นหาด่วน ⌘K) แดชบอร์ดและรายงานเข้าใจช่วงวันที่พร้อมเทียบช่วงก่อนหน้าและโหมดคิว อัปเกรดขึ้นระบบได้ในคลิกเดียวมีรหัสผ่านคุม แดชบอร์ด AIVA ได้ช่อง 8.4 AI Calling — และหลังบ้านเจเนอเรชันใหม่ขึ้นระบบเคียงข้างกันที่ /aiva4/
Safety & money integrity ความปลอดภัยและความถูกต้องของเงิน

The money data now protects itself

ข้อมูลเงินปกป้องตัวเองได้แล้ว

  • Nightly automatic backups. Every prefix's database gets an online snapshot each night — integrity-checked, kept for seven days, and runnable on demand. Until today there was no automated backup at all; the seeding tool also now refuses to touch a database that contains real data.
  • Un-settle: the undo button for money. A deposit or withdrawal approved or rejected by mistake can be reverted to Pending with a mandatory reason — admin-gated, fully audited, and the member's totals are restored to the exact pre-click values. Previously this required manual database surgery.
  • Cross-site request guard. Money-changing API calls now verify they genuinely come from the backoffice's own pages, not from another site or another app on the same domain.
  • สำรองข้อมูลอัตโนมัติทุกคืน · ฐานข้อมูลของทุก prefix ได้สแนปช็อตออนไลน์ทุกคืน — ตรวจความสมบูรณ์ เก็บไว้เจ็ดวัน และสั่งทำเองได้ทุกเมื่อ · ก่อนหน้านี้ไม่มีระบบสำรองอัตโนมัติเลย · เครื่องมือ seed ก็ปฏิเสธที่จะแตะฐานข้อมูลที่มีข้อมูลจริงแล้วด้วย
  • Un-settle: ปุ่มย้อนกลับของเงิน · รายการฝาก/ถอนที่กดอนุมัติหรือปฏิเสธพลาด ย้อนกลับเป็น Pending ได้พร้อมเหตุผลบังคับกรอก — จำกัดสิทธิ์แอดมิน บันทึก audit ครบ และยอดรวมของสมาชิกกลับเป็นค่าก่อนคลิกเป๊ะ ๆ · เมื่อก่อนต้องแก้ฐานข้อมูลด้วยมือ
  • การ์ดป้องกันคำขอข้ามไซต์ · API ที่เปลี่ยนแปลงเงินตรวจสอบแล้วว่าคำขอมาจากหน้าของระบบหลังบ้านเองจริง ๆ ไม่ใช่จากเว็บอื่นหรือแอปอื่นบนโดเมนเดียวกัน
Work queue & reports คิวงานและรายงาน

The pending queue thinks like an operator

คิวรอดำเนินการคิดแบบ operator

  • Oldest first, with wait-time badges. The Home pending queue now leads with the customer who has waited longest, each row carrying a wait badge that turns red past an hour — and a background sweep rings the notification bell for anything pending beyond the per-prefix threshold (default 30 minutes, adjustable in System Settings).
  • Report cards follow the filters. On the deposit and withdrawal reports the summary and per-bank cards now respect the filter bar — filter to yesterday and the totals are yesterday's, not all-time.
  • Find members by phone, tag, or any column. The member search matches phone numbers, a tag filter joined the filter bar, and sorting the money columns now sorts the entire dataset — exports match what's on screen.
  • No more 30-second flash. Auto-refresh updates content silently in place and politely waits while a confirm dialog is open — buttons no longer vanish mid-click.
  • เก่าสุดขึ้นก่อน พร้อมป้ายเวลารอ · คิวรอดำเนินการหน้า Home นำด้วยลูกค้าที่รอนานที่สุด แต่ละแถวมีป้ายเวลารอที่เปลี่ยนเป็นสีแดงเมื่อเกินหนึ่งชั่วโมง — และตัวกวาดเบื้องหลังสั่นกระดิ่งแจ้งเตือนทุกรายการที่ค้างเกินเกณฑ์ของ prefix นั้น (ค่าเริ่มต้น 30 นาที ปรับได้ใน System Settings)
  • การ์ดรายงานตามฟิลเตอร์แล้ว · บนรายงานฝากและถอน การ์ดสรุปและการ์ดรายธนาคารเคารพแถบฟิลเตอร์แล้ว — กรองเป็นเมื่อวาน ยอดรวมก็เป็นของเมื่อวาน ไม่ใช่ตลอดกาล
  • หาสมาชิกด้วยเบอร์โทร แท็ก หรือคอลัมน์ไหนก็ได้ · ช่องค้นหาสมาชิกจับเบอร์โทรด้วย เพิ่มฟิลเตอร์แท็กในแถบฟิลเตอร์ และการเรียงคอลัมน์เงินเรียงทั้งชุดข้อมูลแล้ว — ไฟล์ที่ export ตรงกับที่เห็นบนจอ
  • ไม่มีจอวาบทุก 30 วินาทีอีกต่อไป · รีเฟรชอัตโนมัติอัปเดตเนื้อหาเงียบ ๆ ตรงที่เดิม และรออย่างสุภาพระหว่างที่กล่องยืนยันเปิดอยู่ — ปุ่มไม่หายไปกลางคลิกอีกแล้ว
AIVA & platform AIVA และแพลตฟอร์ม

Smart suggestions become a working loop — and chat answers in production

คำแนะนำอัจฉริยะกลายเป็นวงจรทำงานจริง — และแชตตอบบน production แล้ว

  • Suggestions you can act on. Each AIVA smart suggestion now has Dispatch (SMS or call), Dismiss, and Record-outcome actions (converted / no response / declined) — the page reflects real state instead of a frozen demo feed, and every action is audited.
  • Log calls from the right-click menu. Right-click a member → 📞 บันทึกการโทร records pick-up/no-answer with optional duration and note; the Insights pickup rate is now computed from real calls.
  • The chat assistant works in production. AIVA chat now answers live on the production site; previously it only worked on the development machine.
  • One page to watch every prefix. A new platform-only 🏢 Prefix overview shows each prefix's members, pending deposits and withdrawals (count and amount), today's totals, and how long its oldest item has been waiting — no more switching into each prefix to check for stuck queues. The whole round shipped with the test suite grown from 509 to 617 (all green), browser-verified on production, with no new dependencies and no database migrations.
  • คำแนะนำที่ลงมือทำได้จริง · คำแนะนำอัจฉริยะของ AIVA แต่ละแถวมีปุ่ม ส่งหาลูกค้า (SMS หรือโทร) ปิดคำแนะนำ และบันทึกผล (สำเร็จ / ไม่ตอบกลับ / ปฏิเสธ) — หน้าแสดงสถานะจริงแทนฟีดเดโมที่แช่แข็ง และทุกการกระทำถูกบันทึก audit
  • บันทึกการโทรจากเมนูคลิกขวา · คลิกขวาที่สมาชิก → 📞 บันทึกการโทร เก็บผลรับสาย/ไม่รับสาย พร้อมระยะเวลาและโน้ตตามต้องการ · อัตรารับสายในหน้า Insights คำนวณจากการโทรจริงแล้ว
  • ผู้ช่วยแชตทำงานบน production แล้ว · แชต AIVA ตอบสดบนเว็บจริงแล้ว จากเดิมที่ทำงานได้เฉพาะบนเครื่องพัฒนา
  • หน้าเดียวเห็นทุก prefix · หน้าใหม่ 🏢 ภาพรวม Prefix (เฉพาะแพลตฟอร์ม) แสดงสมาชิก ยอดฝาก/ถอนรอดำเนินการ (จำนวนและยอดเงิน) ยอดวันนี้ และรายการเก่าสุดรอนานแค่ไหนของแต่ละ prefix — ไม่ต้องสลับเข้าทีละ prefix เพื่อหาคิวค้างอีกแล้ว · ทั้งรอบนี้ขึ้นพร้อมชุดเทสต์ที่โตจาก 509 เป็น 617 ตัว (เขียวทั้งหมด) ตรวจสอบผ่านเบราว์เซอร์บน production แล้ว ไม่มี dependency ใหม่ ไม่มี migration ฐานข้อมูล
A new look โฉมใหม่

The whole backoffice gets a new face — dark teal, line icons, ⌘K

หลังบ้านโฉมใหม่ทั้งระบบ — เขียวเข้ม ไอคอนลายเส้น และ ⌘K

  • A redesigned sidebar. A dark-teal rail with crisp line icons, navigation regrouped into six collapsible sections — all collapsed by default so the menu opens compact — topped by a dark brand strip with the wordmark in brand yellow.
  • ⌘K quick search. Press ⌘K (or Ctrl+K) anywhere and type to filter the menu — matching sections open by themselves, and deep links still land on the right group.
  • Copy a deposit reference in one click. Every reference number now carries a 📋 button — no more careful text-selecting on a busy table.
  • Confirmations, polished. The approve/reject popover can now be completed straight from the keyboard, and a stray empty popover that used to appear on non-money buttons is gone.
  • แถบเมนูข้างออกแบบใหม่ · รางสีเขียวเข้มพร้อมไอคอนลายเส้นคมชัด จัดกลุ่มเมนูใหม่เป็นหกหมวดพับได้ — เริ่มต้นพับทั้งหมดให้เมนูกระชับ — ด้านบนเป็นแถบแบรนด์สีเข้มกับโลโก้สีเหลือง
  • ค้นหาด่วน ⌘K · กด ⌘K (หรือ Ctrl+K) ที่ไหนก็ได้แล้วพิมพ์เพื่อกรองเมนู — หมวดที่ตรงจะกางออกเอง และลิงก์ลึกยังพาไปถูกหมวดเหมือนเดิม
  • คัดลอกเลขอ้างอิงฝากในคลิกเดียว · เลขอ้างอิงทุกตัวมีปุ่ม 📋 แล้ว — ไม่ต้องลากเลือกข้อความบนตารางที่ขยับตลอดอีกต่อไป
  • กล่องยืนยันเนี้ยบขึ้น · ป๊อปโอเวอร์อนุมัติ/ปฏิเสธกดจบได้จากคีย์บอร์ดล้วน ๆ และป๊อปโอเวอร์ว่างเปล่าที่เคยโผล่บนปุ่มที่ไม่ใช่เรื่องเงินหายไปแล้ว
Dashboard & reports แดชบอร์ดและรายงาน

The numbers learn about time — and the reports learn to triage

ตัวเลขเข้าใจช่วงเวลา — และรายงานช่วยจัดคิวได้

  • Date scoping with previous-period deltas. The dashboard KPI cards now follow a chosen date range, each carrying a delta chip against the period before — this week against last week at a glance.
  • One-tap period chips on reports. Ready-made date-range chips on the deposit and withdrawal filter bars set the period in a single tap instead of two date pickers.
  • Queue mode on the deposit & withdrawal reports. Flip a report into oldest-first queue order with the same wait-time badges as Home — SLA triage now works from the reports too.
  • Click a segment, meet its members. Every RFM segment card now opens the member list pre-filtered to exactly that segment.
  • The audit log exports. The full audit trail now downloads as a CSV — and every export the system produces neutralizes spreadsheet formula injection, closing a classic attack on money reports.
  • Reject reasons stop eating notes. A rejection reason now appends to the row's notes instead of replacing them — nothing an operator wrote ever vanishes.
  • เลือกช่วงวันที่พร้อมเทียบช่วงก่อนหน้า · การ์ด KPI บนแดชบอร์ดอิงช่วงวันที่ที่เลือกแล้ว แต่ละใบมีชิปเดลต้าเทียบกับช่วงก่อนหน้า — สัปดาห์นี้เทียบสัปดาห์ที่แล้วเห็นในแวบเดียว
  • ชิปช่วงเวลาแตะเดียวบนรายงาน · ชิปช่วงวันที่สำเร็จรูปบนแถบฟิลเตอร์รายงานฝากและถอน ตั้งช่วงได้ในแตะเดียวแทนการจิ้มปฏิทินสองช่อง
  • โหมดคิวบนรายงานฝาก-ถอน · สลับรายงานเป็นเรียงเก่าสุดก่อนพร้อมป้ายเวลารอแบบเดียวกับหน้า Home — จัดคิวตาม SLA จากหน้ารายงานได้เลย
  • คลิกการ์ดเซกเมนต์ เจอสมาชิกทันที · การ์ด RFM ทุกใบเปิดรายชื่อสมาชิกที่กรองเป็นเซกเมนต์นั้นให้แล้ว
  • บันทึก audit ส่งออกได้ · ประวัติ audit ทั้งหมดดาวน์โหลดเป็น CSV แล้ว — และไฟล์ส่งออกทุกไฟล์ของระบบกันสูตรฝัง (formula injection) ปิดช่องโจมตีคลาสสิกบนรายงานเงิน
  • เหตุผลการปฏิเสธไม่กลืนโน้ตอีกต่อไป · เหตุผลที่กรอกตอนปฏิเสธจะต่อท้ายโน้ตของแถวแทนการเขียนทับ — สิ่งที่ operator เขียนไว้ไม่หายอีกแล้ว
Upgrade pipeline ระบบอัปเกรด

New features now ship to production with one click

ฟีเจอร์ใหม่ขึ้น production ได้ในคลิกเดียว

  • One-click ship, password-guarded. The auto-upgrades queue's Ship button is now real: enter the ship password and the selected upgrades roll to production — no terminal session required.
  • Star ratings and an honest record. Queue cards display each proposal's star rating, and anything skipped at ship time is recorded so it's never proposed again.
  • A cleaner queue. Merge commits no longer show up as cards, and machine-generated trailers are stripped from descriptions.
  • ขึ้นระบบคลิกเดียว มีรหัสผ่านคุม · ปุ่ม Ship ของคิวอัปเกรดอัตโนมัติใช้งานจริงแล้ว: ใส่รหัสผ่านแล้วอัปเกรดที่เลือกขึ้น production เลย — ไม่ต้องเปิดเทอร์มินัล
  • ดาวให้คะแนนและบันทึกตรงไปตรงมา · การ์ดในคิวแสดงดาวของแต่ละข้อเสนอ และรายการที่ถูกข้ามตอน ship ถูกบันทึกไว้เพื่อไม่ให้ถูกเสนอซ้ำอีก
  • คิวสะอาดขึ้น · merge commit ไม่โผล่เป็นการ์ดอีกต่อไป และข้อความ trailer ที่เครื่องใส่มาถูกตัดออกจากคำอธิบาย
AIVA dashboard แดชบอร์ด AIVA

Slot 8.4 AI Calling — AI SMS gets a voice twin

ช่อง 8.4 AI Calling — ฝาแฝดสายเสียงของ AI SMS

  • A fourth slot joins the dashboard. AI Calling mirrors AI SMS end to end: a master toggle with the Off/Idle/On pill, a call-credit balance with its own billing kill-switch (2 credits = ฿26 per call), and the same audience-targeting filters.
  • Results at a glance. A date bar, three KPI cards, ROI and call-results charts, plus a paginated call history with duration and answered / no-answer / failed outcomes.
  • Watch it work. The live demo places a call every three seconds — each player called at most once per session — fully bilingual EN/TH.
  • ช่องที่สี่บนแดชบอร์ด · AI Calling สะท้อน AI SMS ครบทุกส่วน: สวิตช์หลักพร้อมพิล Off/Idle/On ยอดเครดิตโทรพร้อมสวิตช์ตัดการเรียกเก็บเงินของตัวเอง (2 เครดิต = ฿26 ต่อสาย) และฟิลเตอร์เลือกกลุ่มเป้าหมายชุดเดียวกัน
  • เห็นผลในแวบเดียว · แถบวันที่ การ์ด KPI สามใบ กราฟ ROI และผลการโทร พร้อมประวัติการโทรแบ่งหน้า มีคอลัมน์ระยะเวลาและผลลัพธ์ รับสาย / ไม่รับ / ล้มเหลว
  • ดูมันทำงาน · เดโมสดวางสายใหม่ทุกสามวินาที — ผู้เล่นแต่ละคนถูกโทรไม่เกินหนึ่งครั้งต่อเซสชัน — สองภาษา EN/TH ครบ
Next generation เจเนอเรชันถัดไป

A second build of the backoffice goes live at /aiva4/

หลังบ้านเวอร์ชันที่สองขึ้นระบบที่ /aiva4/

  • Side by side, zero risk. A ground-up rebuild of the backoffice on Nuxt 4 is now live at /aiva4/, running alongside the current backoffice against its own isolated snapshot of the data — same sign-in, single sign-on between the two, and daily operations untouched.
  • What's ported on day one. The new teal sidebar with ⌘K search, a live Dashboard with real KPIs and recent deposits, and the deposit report 6.1 with filters, paging, and CSV export (read-only for now). Everything not yet ported wears a "soon" badge in the menu.
  • It sets itself up. All fourteen database migrations travel inside the app, so a fresh install builds its own schema from nothing — the foundation for painless future deploys.
  • เคียงข้างกัน ความเสี่ยงเป็นศูนย์ · หลังบ้านที่สร้างใหม่หมดบน Nuxt 4 ขึ้นระบบแล้วที่ /aiva4/ รันคู่กับหลังบ้านปัจจุบันบนสำเนาข้อมูลแยกของตัวเอง — ล็อกอินชุดเดียวกัน ข้ามไปมาไม่ต้องใส่รหัสซ้ำ และงานประจำวันไม่กระทบเลย
  • วันแรกพอร์ตอะไรมาแล้วบ้าง · แถบเมนูเขียวเข้มโฉมใหม่พร้อมค้นหา ⌘K แดชบอร์ดสดด้วย KPI จริงและรายการฝากล่าสุด และรายงานฝาก 6.1 พร้อมฟิลเตอร์ แบ่งหน้า และส่งออก CSV (อ่านอย่างเดียวก่อน) · เมนูที่ยังไม่พอร์ตติดป้าย "soon" ไว้
  • ติดตั้งตัวเองได้ · migration ฐานข้อมูลทั้งสิบสี่ตัวเดินทางไปกับตัวแอป การติดตั้งใหม่จึงสร้าง schema ของตัวเองจากศูนย์ — รากฐานสำหรับการ deploy ที่ราบรื่นในอนาคต
The backoffice can now run multiple isolated prefixes — a new DEMO prefix ships as a clean, empty starting point for onboarding a new customer, switchable from a dropdown in the topbar · plus five operator upgrades: player tags & notes, inline money edits, full member-group management, live Home filters, and SMS straight from the right-click menuระบบหลังบ้านรองรับหลาย prefix แยกข้อมูลขาดจากกันแล้ว — เพิ่ม prefix ใหม่ DEMO เป็นจุดเริ่มต้นว่างเปล่าสะอาดสำหรับเริ่มงานลูกค้ารายใหม่ สลับได้จากเมนูดรอปดาวน์บนแถบบนสุด · พร้อมอัปเกรดสำหรับ operator อีกห้าอย่าง: แท็กและโน้ตผู้เล่น แก้ยอดเงินในตาราง จัดการกลุ่มสมาชิกครบวงจร ฟิลเตอร์หน้า Home แบบสด และส่ง SMS จากเมนูคลิกขวา
Cross-cutting ข้ามทุก slot

Prefix switcher — isolated instances of the whole backoffice

สลับ Prefix — อินสแตนซ์แยกของระบบหลังบ้านทั้งระบบ

  • The "Prefix: AIVA" chip in the topbar is now a dropdown. Pick a prefix and the page reloads into that prefix's own database — members, transactions, reports, settings, everything is fully isolated per prefix. The choice sticks per browser; colleagues on the same site are unaffected.
  • A fresh DEMO prefix is live. It starts completely clean — zero members, zero transactions — the intended starting point when onboarding a new customer. Adding another prefix later is a one-line config change; each one gets its own database file automatically, created and migrated at boot, never seeded.
  • AIVA's data is untouched. With no prefix selected the system behaves byte-for-byte as before; operator sessions and health checks stay on the main instance by design. Built with 20 new tests (suite now 389, all green), an adversarial review pass, and verified live: switching to DEMO shows an honest empty backoffice, switching back restores all 480 members instantly.
  • ชิป "Prefix: AIVA" บนแถบบนสุดกลายเป็นดรอปดาวน์แล้ว · เลือก prefix แล้วหน้าจะรีโหลดเข้าสู่ฐานข้อมูลของ prefix นั้นเอง — สมาชิก ธุรกรรม รายงาน การตั้งค่า ทุกอย่างแยกขาดจากกันต่อ prefix · ตัวเลือกจำต่อเบราว์เซอร์ เพื่อนร่วมงานบนเว็บเดียวกันไม่ได้รับผลกระทบ
  • Prefix ใหม่ DEMO เปิดใช้แล้ว · เริ่มต้นสะอาดทั้งหมด — ไม่มีสมาชิก ไม่มีธุรกรรม — เป็นจุดเริ่มต้นที่ตั้งใจไว้สำหรับเริ่มงานลูกค้ารายใหม่ · เพิ่ม prefix อื่นภายหลังแก้ config บรรทัดเดียว แต่ละอันได้ไฟล์ฐานข้อมูลของตัวเองอัตโนมัติ สร้างและ migrate ตอนบูต ไม่มีการ seed
  • ข้อมูลของ AIVA ไม่ถูกแตะ · ถ้าไม่ได้เลือก prefix ระบบทำงานเหมือนเดิมทุกบิต · session ของ operator และ health check ยังอยู่กับอินสแตนซ์หลักโดยตั้งใจ · สร้างพร้อมเทสต์ใหม่ 20 ตัว (ชุดเทสต์ตอนนี้ 389 ตัว เขียวทั้งหมด) ผ่านการรีวิวแบบ adversarial และตรวจสอบจริงบน production: สลับไป DEMO เห็นหลังบ้านว่างจริง สลับกลับเห็นสมาชิกทั้ง 480 คนทันที
Operator tools เครื่องมือ operator

Five everyday-workflow upgrades, shipped together

อัปเกรดเวิร์กโฟลว์ประจำวันห้าอย่าง ขึ้นพร้อมกัน

  • Player tags & notes are finally on the profile. Add/remove tags and write, edit or delete notes right on the player's Overview tab — every change lands in the audit trail.
  • Money figures are editable where you see them. An แก้ไข button on deposit/withdrawal rows opens an edit popover for the bonus or actual paid amount — changes feed the bonus-edit and withdrawal-edit reports (25.11/25.12) with full old→new history. Bad inputs are rejected at the API, and group colors are now locked to safe values.
  • Member groups are fully manageable. Create a group (optionally bulk-assigning members by username), rename or re-describe it inline on its card, and delete with a two-step confirm — the dead mockup form is gone.
  • The Home filters actually filter. The channel chips and currency selector now drive all four Home widgets live (verified against the real production channel list), with your choice remembered per session.
  • SMS without opening the chat. Right-click any player → ส่ง SMS opens the usual preview modal pre-filled with their number; sends are logged like every other outreach.
  • แท็กและโน้ตผู้เล่นมาอยู่บนโปรไฟล์แล้ว · เพิ่ม/ลบแท็ก และเขียน แก้ไข หรือลบโน้ตได้บนแท็บ Overview ของผู้เล่น — ทุกการเปลี่ยนแปลงถูกบันทึกใน audit
  • แก้ตัวเลขเงินได้ตรงจุดที่เห็น · ปุ่มแก้ไขบนแถวฝาก/ถอนเปิดป๊อปอัปแก้โบนัสหรือยอดจ่ายจริง — ป้อนเข้ารายงานแก้โบนัส/แก้ยอดถอน (25.11/25.12) พร้อมประวัติ เดิม→ใหม่ ครบ · ค่าที่ไม่ถูกต้องถูกปฏิเสธที่ API และสีของกลุ่มถูกล็อกให้เป็นค่าที่ปลอดภัยเท่านั้น
  • จัดการกลุ่มสมาชิกได้ครบวงจร · สร้างกลุ่ม (พร้อมย้ายสมาชิกเข้าเป็นชุดด้วยยูสเซอร์เนม) เปลี่ยนชื่อหรือคำอธิบายแบบ inline บนการ์ด และลบด้วยการยืนยันสองขั้น — ฟอร์ม mockup เดิมที่กดไม่ได้ถูกถอดออกแล้ว
  • ฟิลเตอร์หน้า Home ใช้งานได้จริง · ชิปช่องทางและตัวเลือกสกุลเงินขับเคลื่อนวิดเจ็ตทั้งสี่ของหน้า Home แบบสด (ตรวจสอบกับรายการช่องทางจริงบน production แล้ว) และจำตัวเลือกไว้ต่อ session
  • ส่ง SMS โดยไม่ต้องเปิดแชต · คลิกขวาที่ผู้เล่นคนไหนก็ได้ → ส่ง SMS เปิดหน้าต่างพรีวิวพร้อมเบอร์ของเขา · การส่งถูกบันทึกเหมือน outreach อื่นทุกครั้ง
Segments เซกเมนต์

Member segments now match AIVA v1's 11 RFM segments

เซกเมนต์สมาชิกตรงกับ 11 RFM segment ของ AIVA v1 แล้ว

  • One taxonomy across both generations. The member groups now use the same 11 segments as the original AIVA dashboard: Champions, Loyal Customers, Potential Loyalists, New Customers, Promising, Need Attention, About To Sleep, At Risk, Cant Loose, Hibernating, Unconverted Leads. Existing members kept their groups (two were renamed in place; three new ones start empty), and every fresh prefix starts with the same 11 out of the box.
  • อนุกรมวิธานเดียวกันทั้งสองรุ่น · กลุ่มสมาชิกใช้ 11 เซกเมนต์เดียวกับแดชบอร์ด AIVA รุ่นแรกแล้ว: Champions, Loyal Customers, Potential Loyalists, New Customers, Promising, Need Attention, About To Sleep, At Risk, Cant Loose, Hibernating, Unconverted Leads · สมาชิกเดิมยังอยู่กลุ่มเดิม (สองกลุ่มถูกเปลี่ยนชื่อในที่ สามกลุ่มใหม่เริ่มว่าง) และ prefix ใหม่ทุกอันเริ่มต้นด้วย 11 เซกเมนต์นี้ทันที
Customer-ready พร้อมส่งมอบลูกค้า

Bank Settings, a big honesty pass, and a friendlier front door

ตั้งค่าธนาคาร เก็บกวาดข้อมูลปลอมครั้งใหญ่ และหน้าแรกที่เป็นมิตรขึ้น

  • Banks are finally self-service. A new Bank Settings page (sidebar + a ⚙️ shortcut on Home) lets each prefix add and manage its own banks and receiving accounts — create, edit, activate/deactivate, every change audited. A fresh customer prefix can now go from empty to operational on its own.
  • No more leftover fake numbers. Every live page now fully retires its old mockup chrome: the fabricated ฿106M dashboard figures, fake bank cards with account numbers, fake currency pools, the fake Top-20 depositor list and the fake analytics revenue are gone. Empty screens now say honestly that the system is awaiting its first data — and point to the next setup step instead of blaming your filters.
  • A real first-run experience. The first screen on a fresh prefix is now a getting-started checklist with live progress (set up banks → add members → review segments → first deposit), the app opens on หน้าหลัก instead of the dashboard, analytics gained a live data panel with clearly watermarked samples, the Player Leaderboard tabs (Top Depositors / Winners / Most Active) went live, and notification badges show real counts instead of hardcoded ones.
  • Polish across the board. Live widgets now speak Thai-first like the rest of the app (with English a toggle away, including Thai display names for all 11 segments), the prefix switcher matches the language dropdown's look, and the AIVA chat bubble got a proper headset-with-sparkle icon. Built and verified across both a populated and a brand-new prefix — 463 automated tests plus a full screenshot walk of every page.
  • ธนาคารจัดการเองได้แล้ว · หน้าตั้งค่าธนาคารใหม่ (เมนูข้าง + ทางลัด ⚙️ บนหน้าหลัก) ให้แต่ละ prefix เพิ่มและจัดการธนาคารกับบัญชีรับเงินของตัวเอง — สร้าง แก้ไข เปิด/ปิดใช้งาน ทุกการเปลี่ยนแปลงถูกบันทึก audit · prefix ลูกค้าใหม่เริ่มจากว่างจนใช้งานได้ด้วยตัวเอง
  • ไม่มีตัวเลขปลอมหลงเหลือ · ทุกหน้าที่ใช้ข้อมูลจริงถอด mockup เดิมออกหมดแล้ว: ตัวเลขปลอม ฿106 ล้านบนแดชบอร์ด การ์ดธนาคารปลอมพร้อมเลขบัญชี พูลสกุลเงินปลอม ตาราง Top-20 ปลอม และรายได้ปลอมในหน้าวิเคราะห์ หายไปทั้งหมด · หน้าจอว่างบอกตรง ๆ ว่าระบบกำลังรอข้อมูลแรก พร้อมชี้ขั้นตอนถัดไป ไม่โทษฟิลเตอร์ของคุณ
  • ประสบการณ์เริ่มต้นใช้งานจริง · หน้าจอแรกของ prefix ใหม่เป็นเช็กลิสต์เริ่มต้นใช้งานพร้อมสถานะสด (ตั้งค่าธนาคาร → เพิ่มสมาชิก → ตรวจสอบเซกเมนต์ → รอฝากแรก) · แอปเปิดที่หน้าหลักแทนแดชบอร์ด · หน้าวิเคราะห์มีแผงข้อมูลจริงพร้อมตัวอย่างที่ติดลายน้ำชัดเจน · แท็บ Player Leaderboard ใช้ข้อมูลจริงแล้ว · ตัวเลขแจ้งเตือนเป็นค่าจริง ไม่ใช่เลขตายตัว
  • เก็บรายละเอียดทั่วทั้งแอป · วิดเจ็ตข้อมูลจริงพูดไทยเป็นหลักเหมือนส่วนอื่นของแอป (สลับอังกฤษได้ รวมชื่อไทยของทั้ง 11 เซกเมนต์) · ตัวสลับ prefix หน้าตาเดียวกับเมนูเลือกภาษา · ไอคอนแชต AIVA เป็นหูฟังพร้อมประกายดาวแบบมืออาชีพ · ทดสอบครบทั้ง prefix ที่มีข้อมูลและ prefix ใหม่เอี่ยม — เทสต์อัตโนมัติ 463 ตัว พร้อมเดินถ่ายภาพหน้าจอทุกหน้า
Prefix platform แพลตฟอร์ม Prefix

Instant new prefixes, per-prefix settings & branding, and cleaner navigation

สร้าง prefix ได้ทันที ตั้งค่าและแบรนด์ต่อ prefix และเมนูที่สะอาดขึ้น

  • New prefixes in seconds. A new System Settings page can provision a brand-new prefix on the spot — its database is created and ready immediately, no technical steps. Each prefix also gets its own settings: company name, default currency, timezone and contact.
  • Your brand on your backoffice. Set a company name and accent color and the prefix rebrands its topbar — the prefix switcher even shows each company's name. Nothing changes until you configure it.
  • Simpler menu, consistent numbering. Sidebar groups now start collapsed, the report numbers follow their tab (6.1–6.13 under tab 6, matching chips and page titles everywhere — even AIVA's chat answers cite the new numbers), and navigating from links now opens the right group with the item highlighted.
  • Quality pass under the hood. English mode no longer shows Thai number fragments, empty bank summaries say the honest thing (no transactions vs. no banks), closed banks can't quietly accept new accounts, and the topbar clock shows your real timezone. Suite now at 509 automated tests.
  • สร้าง prefix ใหม่ในไม่กี่วินาที · หน้าตั้งค่าระบบใหม่สร้าง prefix ได้ทันที — ฐานข้อมูลถูกสร้างและพร้อมใช้ทันที ไม่ต้องมีขั้นตอนเทคนิค · แต่ละ prefix มีการตั้งค่าของตัวเอง: ชื่อบริษัท สกุลเงินหลัก โซนเวลา และข้อมูลติดต่อ
  • แบรนด์ของคุณบนหลังบ้านของคุณ · ตั้งชื่อบริษัทและสีประจำแบรนด์แล้วแถบบนของ prefix นั้นเปลี่ยนตามทันที — เมนูสลับ prefix แสดงชื่อบริษัทของแต่ละราย · ไม่ตั้งค่าก็ไม่มีอะไรเปลี่ยน
  • เมนูเรียบง่าย เลขรายงานสอดคล้อง · กลุ่มเมนูข้างเริ่มต้นแบบพับเก็บ · เลขรายงานตามแท็บ (6.1–6.13 ใต้แท็บ 6 ตรงกันทั้งชิป หัวข้อหน้า และแม้แต่คำตอบของแชต AIVA) · กดลิงก์จากหน้าอื่นแล้วกลุ่มที่ถูกต้องเปิดพร้อมไฮไลต์รายการ
  • เก็บคุณภาพเบื้องหลัง · โหมดอังกฤษไม่มีเศษคำไทยปนตัวเลขแล้ว · สรุปธนาคารว่างบอกตามจริง (ไม่มีรายการ vs ไม่มีธนาคาร) · ธนาคารที่ปิดใช้งานรับบัญชีใหม่ไม่ได้ · นาฬิกาแถบบนแสดงโซนเวลาจริงของคุณ · ชุดเทสต์อัตโนมัติแตะ 509 ตัวแล้ว
Groundwork for per-operator logins shipped to production — behind a switch that's off for now, so today's login is unchanged · plus a reliability, security & speed pass under the hood, and two dashboard touches: a Live auto-refresh toggle and a one-click player 360 timelineขึ้นโครงสร้างพื้นฐานสำหรับล็อกอินรายคนบน production แล้ว — อยู่หลังสวิตช์ที่ยังปิดอยู่ การล็อกอินวันนี้จึงไม่เปลี่ยน · พร้อมการปรับปรุงด้านความเสถียร ความปลอดภัย และความเร็วเบื้องหลัง และสองจุดในแดชบอร์ด: ปุ่มอัปเดตสด และไทม์ไลน์ 360 ของผู้เล่นในคลิกเดียว
Cross-cutting ข้ามทุก slot

Per-operator logins are on the way

ล็อกอินรายคนกำลังจะมา

  • Each operator will get their own login. Today everyone shares one password (which also signs you into the sibling sites). The groundwork for individual operator accounts — with names, roles (admin / operator / viewer) and per-operator sessions — shipped to production today.
  • The audit trail will finally name names. Right now every approve / reject / edit / SMS is recorded as aiva-admin. Once operator login is switched on, each action is attributed to the person who did it — and the money actions (approve / reject / edit) become role-gated, so a "viewer" can look but not touch.
  • Shipped switched OFF — nothing changes yet. It sits behind an AUTH_MODE flag set to "gate", so today's shared-password login works exactly as before. The rollout is deliberate: run it alongside the old login for a soak, then cut over (we'll confirm first — the cutover is also when this app stops sharing a login with the other sites). Built safely: new tables, password hashing via Node's built-in scrypt (no new libraries), 10 new tests, and the full suite (276) stays green with production behaviour byte-for-byte identical until the switch is flipped.
  • ผู้ใช้แต่ละคนจะมีล็อกอินของตัวเอง · วันนี้ทุกคนใช้รหัสผ่านร่วมอันเดียว (ที่ล็อกอินเข้าเว็บพี่น้องด้วย) · วันนี้ขึ้นโครงสร้างพื้นฐานสำหรับบัญชี operator รายคน — มีชื่อ, บทบาท (admin / operator / viewer) และ session รายคน — บน production แล้ว
  • บันทึก audit จะระบุตัวคนได้ · ตอนนี้ทุกการอนุมัติ / ปฏิเสธ / แก้ไข / ส่ง SMS ถูกบันทึกเป็น aiva-admin · เมื่อเปิดล็อกอินรายคน แต่ละการกระทำจะระบุชื่อคนที่ทำ และการกระทำเกี่ยวกับเงิน (อนุมัติ / ปฏิเสธ / แก้ไข) จะถูกจำกัดตามบทบาท — "viewer" ดูได้แต่แก้ไม่ได้
  • ขึ้นแบบปิดสวิตช์ไว้ก่อน — ยังไม่มีอะไรเปลี่ยน · อยู่หลัง flag AUTH_MODE ที่ตั้งเป็น "gate" การล็อกอินด้วยรหัสร่วมเดิมจึงทำงานเหมือนเดิมทุกประการ · แผนเปิดใช้แบบค่อยเป็นค่อยไป: รันคู่กับของเดิมช่วงทดสอบ แล้วค่อยสลับ (จะยืนยันก่อน — จุดสลับยังเป็นตอนที่แอปนี้เลิกใช้ล็อกอินร่วมกับเว็บอื่น) · สร้างอย่างปลอดภัย: ตารางใหม่, แฮชรหัสด้วย scrypt ในตัวของ Node (ไม่เพิ่มไลบรารี), เทสต์ใหม่ 10 ตัว, ชุดเทสต์ทั้งหมด (276) ยังเขียว และพฤติกรรมบน production เหมือนเดิมทุกบิตจนกว่าจะสลับสวิตช์
Cross-cutting ข้ามทุก slot

Exports, faster loads, and a stronger test net

ส่งออกข้อมูล โหลดเร็วขึ้น และตาข่ายทดสอบที่แข็งแรงขึ้น

  • Export any report to CSV. The "ส่งออกไฟล์ / Export" button on the report pages now actually downloads the current view — with your filters applied — as a UTF-8 CSV (Thai-safe, opens in Excel). Covers deposits, withdrawals, members and the 25.x reports.
  • Faster loads. The dashboard's scripts and styles are now minified + content-hashed — about 30% smaller — and cache-busting is automatic, so you no longer get a half-updated page after a release.
  • A stronger safety net. The dashboard's rendering is now checked automatically on every code push — the same class of check that would have caught the recent faint table-header glitch before it ever reached you.
  • ส่งออกรายงานเป็น CSV ได้แล้ว · ปุ่ม "ส่งออกไฟล์" บนหน้ารายงานดาวน์โหลดมุมมองปัจจุบัน (ตามตัวกรองที่ตั้งไว้) เป็นไฟล์ CSV (UTF-8 รองรับภาษาไทย เปิดใน Excel ได้) · ใช้ได้กับ ฝาก ถอน สมาชิก และรายงาน 25.x
  • โหลดเร็วขึ้น · สคริปต์และสไตล์ของแดชบอร์ดถูกย่อขนาด (minify) และใส่ content-hash แล้ว — เล็กลงราว 30% — และจัดการแคชอัตโนมัติ จึงไม่เจอหน้าจออัปเดตไม่ครบหลังปล่อยเวอร์ชันอีก
  • ตาข่ายความปลอดภัยแข็งแรงขึ้น · การเรนเดอร์ของแดชบอร์ดถูกตรวจอัตโนมัติทุกครั้งที่ push โค้ด — แบบเดียวกับที่จะจับบั๊กหัวตารางจางที่เพิ่งเกิดได้ก่อนถึงมือคุณ
Cross-cutting ข้ามทุก slot

Under the hood: a more reliable, safer, faster backoffice

เบื้องหลัง: หลังบ้านที่เสถียร ปลอดภัย และเร็วขึ้น

  • A glitch on one screen no longer takes the whole backoffice down. If a single page hits an unexpected error, you now get a clean error on that page instead of the app going dark for everyone — and a new health check means we know instantly if it's ever unavailable.
  • Money actions and their history now save together. Every approve, reject and amount edit is written in the same step as its audit record, so they can never get out of sync — a change is never recorded without its history, and history is never recorded without the change.
  • Stronger protection on the login. The defense against password-guessing was hardened so it can't be tricked into resetting itself — the login is harder to brute-force.
  • Reports stay fast as the data grows. The Coupon, Cashback, Commission and Hidden-deposit reports were tuned so they keep loading quickly even with far more rows than today.
  • A guardrail on amount edits. Editing a bonus or payout now rejects an impossibly large or malformed value, so a slip of the keyboard can't quietly corrupt a figure.
  • ความผิดพลาดบนหน้าจอเดียวจะไม่ทำให้หลังบ้านล่มทั้งระบบ · ถ้าหน้าใดหน้าหนึ่งเจอข้อผิดพลาดที่ไม่คาดคิด ตอนนี้จะแสดงข้อผิดพลาดเฉพาะหน้านั้นแทนที่แอปจะดับทั้งหมด — และมีการตรวจสุขภาพระบบใหม่ที่ทำให้รู้ทันทีหากระบบใช้งานไม่ได้
  • การทำรายการเงินและประวัติถูกบันทึกพร้อมกัน · ทุกการอนุมัติ ปฏิเสธ และแก้ไขยอด ถูกเขียนในขั้นตอนเดียวกับบันทึก audit จึงไม่มีทางหลุดจากกัน — การเปลี่ยนแปลงจะไม่ถูกบันทึกโดยไม่มีประวัติ และไม่มีประวัติโดยไม่มีการเปลี่ยนแปลง
  • ป้องกันการล็อกอินแข็งแรงขึ้น · ระบบป้องกันการเดารหัสผ่านถูกทำให้แข็งแรงขึ้นจนหลอกให้รีเซ็ตตัวเองไม่ได้ — เดารหัสผ่านได้ยากขึ้น
  • รายงานยังเร็วแม้ข้อมูลโตขึ้น · รายงานคูปอง, Cashback, Commission และเงินฝากที่ถูกซ่อน ถูกปรับให้โหลดเร็วแม้มีจำนวนแถวมากกว่าตอนนี้มาก
  • กันพลาดตอนแก้ยอด · การแก้ไขโบนัสหรือยอดจ่ายจะปฏิเสธค่าที่ใหญ่เกินจริงหรือผิดรูปแบบ การพิมพ์พลาดจึงไม่ทำให้ตัวเลขเสียหายโดยไม่รู้ตัว
Cross-cutting ข้ามทุก slot

Two things you'll notice in the dashboard

สองสิ่งที่คุณจะสังเกตเห็นในแดชบอร์ด

  • A "Live" auto-refresh toggle on the pending queues. On the Home and Dashboard screens, flip the new อัปเดตสด / Live pill to have the pending deposit/withdrawal queues refresh themselves every 30 seconds — no more re-clicking the page to spot new items waiting for action. Your choice is remembered, and it pauses while the tab is in the background.
  • A player's full timeline in one click. Right-click any player's name and choose ดูไทม์ไลน์ 360 / View 360 Timeline to open their complete history — deposits, withdrawals, notes, tags and actions — in a single chronological view, without leaving the page you're on.
  • ปุ่ม "อัปเดตสด" บนคิวที่รอดำเนินการ · บนหน้าหลักและแดชบอร์ด เปิดปุ่ม อัปเดตสด / Live ใหม่ เพื่อให้คิวฝาก/ถอนที่รอดำเนินการรีเฟรชเองทุก 30 วินาที — ไม่ต้องคลิกหน้าซ้ำเพื่อดูรายการใหม่ที่รออยู่ · ระบบจำค่าที่เลือกไว้ และจะหยุดพักเมื่อแท็บอยู่เบื้องหลัง
  • ดูไทม์ไลน์ทั้งหมดของผู้เล่นในคลิกเดียว · คลิกขวาที่ชื่อผู้เล่นแล้วเลือก ดูไทม์ไลน์ 360 เพื่อเปิดประวัติทั้งหมด — ฝาก ถอน โน้ต แท็ก และการกระทำ — ในมุมมองเรียงตามเวลาเดียว โดยไม่ต้องออกจากหน้าที่กำลังดูอยู่

The last 3 mock pages go live — the report & analytics backlog is now 100% real data

3 หน้า mock สุดท้ายดึงข้อมูลจริงแล้ว — รายงานและวิเคราะห์ครบ 100%

  • Online Players + the activity heatmap. The "active recently" card is labeled honestly as a ~15-minute proxy — this app has no live presence signal yet, so it's not a true "online now" count; today's new-players / deposits / withdrawals are genuine counts; and the heatmap shows real transaction activity (deposits + withdrawals by hour), not logins, and says so.
  • Player Activity. The heatmap now supports the new / VIP / monitor / all segments (cohorts derived from registration date + member groups), over the same real transaction timestamps.
  • AutoPeer Settings persists. The config form (callback / deposit / withdraw toggles + limits) loads from and saves to a real settings store (admin-only save, audited). It stores the operator's configuration — there's no live AutoPeer engine reading it inside this dashboard yet.
  • With these, every page in the Reports and analytics sections now shows live data — no mock arrays left.
  • ผู้เล่นออนไลน์ + ฮีตแมปกิจกรรม · การ์ด "ใช้งานล่าสุด" ระบุตามตรงว่าเป็นค่าประมาณ ~15 นาที — แอปยังไม่มีสัญญาณ presence จริง จึงไม่ใช่ "ออนไลน์ตอนนี้" จริง ๆ · ตัวเลขผู้เล่นใหม่ / ฝาก / ถอน วันนี้เป็นค่าจริง · ฮีตแมปแสดงกิจกรรมธุรกรรมจริง (ฝาก+ถอน ตามชั่วโมง) ไม่ใช่การล็อกอิน และระบุไว้ชัดเจน
  • พฤติกรรมผู้เล่น · ฮีตแมปรองรับการแบ่งกลุ่ม ใหม่ / VIP / เฝ้าระวัง / ทั้งหมด (จัดกลุ่มจากวันสมัคร + member groups) บนเวลาธุรกรรมจริงเช่นกัน
  • ตั้งค่า AutoPeer บันทึกได้จริง · ฟอร์มตั้งค่า (callback / ฝาก / ถอน) โหลดและบันทึกลงที่เก็บค่าจริง (บันทึกได้เฉพาะ admin มี audit) · เก็บค่าตั้งของ operator — ยังไม่มีเอนจิน AutoPeer จริงในแดชบอร์ดนี้ที่อ่านค่าไปใช้
  • ด้วยสิ่งเหล่านี้ ทุกหน้าในส่วนรายงานและวิเคราะห์แสดงข้อมูลจริงทั้งหมดแล้ว — ไม่เหลือ mock array

No slot 8.2 changes today.

ไม่มีการเปลี่ยนแปลงใน slot 8.2 วันนี้

No slot 8.3 changes today.

ไม่มีการเปลี่ยนแปลงใน slot 8.3 วันนี้

Test + CI safety net · the entire Reports section now reads live data (25.4–25.13 + System Promotion) · bonus & withdrawal-amount edit history · UI polish (loading/empty states, accessibility, responsive) + a Content-Security-Policyตาข่ายความปลอดภัยด้วยเทสต์ + CI · หน้ารายงานทั้งหมดดึงข้อมูลจริงแล้ว (25.4–25.13 + สรุปโปรโมชันระบบ) · ประวัติการแก้ไขยอดโบนัส/ยอดถอน · ขัดเกลา UI (สถานะโหลด/ว่าง, การเข้าถึง, รองรับจอเล็ก) + Content-Security-Policy
Cross-cutting ข้ามทุก slot

The backoffice gets an automated safety net — 222 tests + CI

หลังบ้านได้ตาข่ายความปลอดภัยอัตโนมัติ — 222 เทสต์ + CI

  • Every API route now has automated tests — 222 in total. A new node:test suite covers all 18 backend route files plus an all-endpoints smoke test, a migration-idempotency check, and the shared-password gate's login/cookie behavior. The whole suite finishes in well under a second via npm test, and adds no new dependencies — it's built on Node's own test runner and node:sqlite.
  • Tests run against a throwaway database, never the live one. Each test file spins up its own temporary SQLite DB, migrates and seeds it, and exercises the real Express app (now importable for testing) — so the seeded demo data the dashboard reads is never touched by a test run.
  • The SMS and chat proxies are tested without ever firing for real. The Twilio, AIVA-chat and feedback routes are checked only through their validation and error paths (with the upstream pointed at a dead port), so a full test run never sends a real SMS or calls an external service.
  • Continuous integration on every push. A Forgejo Actions workflow runs npm ci && npm test on every push and pull request, so a change that breaks a route is caught automatically. It activates once a CI runner is registered on the repo host.
  • A more readable sidebar. The report-number badges in the left menu (25.1, 25.2, …) and the section arrows were a pale grey-green that was hard to read on the light background; they're now the same dark green as the menu labels, comfortably above the contrast threshold.
  • ทุก API route มีเทสต์อัตโนมัติแล้ว — รวม 222 เทสต์ · ชุดเทสต์ใหม่บน node:test ครอบคลุมไฟล์ route ทั้ง 18 ไฟล์ บวกเทสต์ smoke ที่ยิงทุก endpoint, เทสต์ migration แบบรันซ้ำได้ (idempotent) และพฤติกรรม login/cookie ของ gate รหัสผ่านรวม · ทั้งชุดรันเสร็จในไม่ถึงวินาทีด้วย npm test และ ไม่เพิ่ม dependency ใหม่เลย — ใช้ test runner ของ Node เองและ node:sqlite
  • เทสต์รันบนฐานข้อมูลชั่วคราว ไม่แตะตัวจริง · เทสต์แต่ละไฟล์สร้าง SQLite DB ชั่วคราวของตัวเอง แล้ว migrate + seed และเรียก Express app จริง (ตอนนี้ import มาเทสต์ได้แล้ว) — ข้อมูล demo ที่ dashboard อ่านจึงไม่ถูกแตะระหว่างรันเทสต์
  • proxy SMS และแชทถูกเทสต์โดยไม่ยิงจริง · route ของ Twilio, แชท AIVA และ feedback ถูกตรวจเฉพาะ path การ validate และ error (ชี้ upstream ไปยังพอร์ตที่ตายแล้ว) การรันเทสต์เต็มชุดจึงไม่เคยส่ง SMS จริงหรือเรียกบริการภายนอก
  • CI ทำงานทุกครั้งที่ push · workflow บน Forgejo Actions รัน npm ci && npm test ทุก push และ pull request ความเปลี่ยนแปลงที่ทำ route พังจึงถูกจับได้อัตโนมัติ · จะเริ่มทำงานเมื่อมี CI runner ลงทะเบียนบน repo host
  • เมนูด้านข้างอ่านง่ายขึ้น · ป้ายหมายเลขรายงานในเมนูซ้าย (25.1, 25.2, …) และลูกศรของแต่ละหมวดเคยเป็นสีเขียวอมเทาจาง ๆ ที่อ่านยากบนพื้นอ่อน · ตอนนี้เปลี่ยนเป็นสีเขียวเข้มเท่ากับชื่อเมนู ผ่านเกณฑ์ความคมชัดสบายตา
Cross-cutting ข้ามทุก slot

Polish + a hardened dashboard

ขัดเกลา + แดชบอร์ดที่แข็งแรงขึ้น

  • Snappier, clearer tables. While a report loads, tables now show a shimmer skeleton instead of bare "loading…"; and "no results" vs. "couldn't load" are now distinct states (the error one offers a retry), so an empty filter no longer looks like a failure.
  • Keyboard & screen-reader access. The sidebar, tabs and menus — previously mouse-only — are now keyboard-operable (Tab + Enter/Space) and announce themselves to screen readers; icon-only buttons gained labels.
  • Works on smaller screens. A responsive pass densifies the layout on laptops and slides the sidebar off-canvas on narrow widths, so report tables stop forcing left-right scrolling.
  • A hardened dashboard (Content-Security-Policy). The backoffice now ships a strict CSP that only allows scripts from itself and the known CDN — blocking injected external scripts, a real XSS safeguard on a money tool.
  • Automated tests now gate every push. The backend suite (now 266 tests) runs automatically on the server for every change, so a regression is caught before it reaches you.
  • ตารางลื่นขึ้นและสื่อสารชัดขึ้น · ระหว่างโหลดรายงาน ตารางแสดง skeleton shimmer แทนข้อความ "loading…" เปล่า ๆ · และสถานะ "ไม่พบข้อมูล" กับ "โหลดไม่สำเร็จ" แยกจากกันชัดเจน (อันหลังมีปุ่มลองใหม่) ตัวกรองที่ไม่เจอผลจึงไม่ดูเหมือนระบบล่ม
  • ใช้งานด้วยคีย์บอร์ดและ screen reader ได้ · เมนูด้านข้าง แท็บ และเมนูต่าง ๆ ที่เคยใช้ได้แต่เมาส์ ตอนนี้กดด้วยคีย์บอร์ดได้ (Tab + Enter/Space) และประกาศตัวเองต่อ screen reader · ปุ่มไอคอนล้วนได้ป้ายกำกับ
  • รองรับจอเล็กลง · ปรับ layout ให้แน่นขึ้นบนแล็ปท็อป และพับเมนูด้านข้างออกนอกจอเมื่อจอแคบ ตารางรายงานจึงไม่บังคับให้เลื่อนซ้าย–ขวา
  • แดชบอร์ดที่แข็งแรงขึ้น (Content-Security-Policy) · หลังบ้านส่ง CSP เข้มงวดที่อนุญาตสคริปต์เฉพาะจากตัวเองและ CDN ที่รู้จัก — บล็อกสคริปต์ภายนอกที่ถูกแทรก เป็นการป้องกัน XSS จริงบนเครื่องมือที่เกี่ยวกับเงิน
  • เทสต์อัตโนมัติรันทุกครั้งที่ push แล้ว · ชุดเทสต์ฝั่ง backend (ตอนนี้ 266 เทสต์) รันอัตโนมัติบนเซิร์ฟเวอร์ทุกการเปลี่ยนแปลง regression จึงถูกจับก่อนถึงมือคุณ

Five report pages wired to live data — no database change

5 หน้ารายงานเชื่อมข้อมูลจริง — ไม่แตะฐานข้อมูล

  • Reports 25.9 — Profit / Loss per currency. A new /api/reports/pnl-by-currency sums Success deposits, bonuses and withdrawals grouped by currency, converts each to USDT via its THB rate, and computes P&L = deposit + bonus − withdrawal. It always returns a row for all six active currencies. The one column with no backing data — "credit held" — honestly renders 0 (a known gap, flagged for a later schema decision).
  • Reports 25.10 — Decimal deposits. /api/deposits gained a decimal=1 filter (rows whose amount has a fractional part) that stacks cleanly with the existing status / currency / date / search filters and paging. Heads-up: the seeded demo data has no fractional amounts, so this table is empty on the demo DB until a genuine decimal deposit exists — that's correct, not a bug.
  • Player Type — RFM segments. The eight RFM cards (Champions, At Risk, … Hibernating) now show real member counts and total deposits per segment from the existing /api/member-groups, replacing the random placeholder numbers. The game / segment / rank sub-tabs stay on mock data — there's nothing behind them yet.
  • System Transaction. The "abnormal bonus — Top 10" table is now driven by a new /api/reports/top-bonus (the ten deposits with the highest bonus, joined to member and bank), and the daily deposit / withdrawal bar chart reads the live 14-day trend. Username masking stays client-side.
  • Player Report. A new /api/reports/player-report splits members into new vs. old by their registration date (a configurable window, default 30 days) and sums each group's real deposits, withdrawals and bonuses — retiring the old "old = new × 6.5" guess. The chart reuses the live trend series.
  • Each of the five pages now carries a LIVE chip and falls back to its original mock view if the live fetch fails.
  • รายงาน 25.9 — กำไรขาดทุนต่อสกุลเงิน · endpoint ใหม่ /api/reports/pnl-by-currency รวมยอดฝาก/โบนัส/ถอน (สถานะ Success) แยกตามสกุลเงิน, แปลงเป็น USDT ด้วยเรต THB ของแต่ละสกุล, และคำนวณกำไรขาดทุน = ฝาก + โบนัส − ถอน · คืนแถวครบทั้ง 6 สกุลเงินที่ใช้งานเสมอ · คอลัมน์เดียวที่ไม่มีข้อมูลรองรับ — "เครดิตที่ถือรับ" — แสดง 0 ตามตรง (เป็นช่องว่างที่รู้อยู่ รอการตัดสินใจเรื่อง schema ภายหลัง)
  • รายงาน 25.10 — ฝากทศนิยม · /api/deposits เพิ่มตัวกรอง decimal=1 (เฉพาะแถวที่ยอดมีเศษทศนิยม) ซึ่งซ้อนกับตัวกรองสถานะ/สกุลเงิน/วันที่/ค้นหา และการแบ่งหน้าเดิมได้สะอาด · หมายเหตุ: ข้อมูล demo ที่ seed ไม่มียอดทศนิยมเลย ตารางนี้บน demo DB จึงว่างจนกว่าจะมีรายการฝากทศนิยมจริง — ถูกต้องแล้ว ไม่ใช่บั๊ก
  • การจัดประเภทผู้เล่น — เซกเมนต์ RFM · การ์ด RFM ทั้ง 8 (Champions, At Risk, … Hibernating) แสดงจำนวนสมาชิกและยอดฝากรวมจริงต่อเซกเมนต์จาก /api/member-groups เดิม แทนตัวเลขสุ่ม · แท็บย่อย game / segment / rank ยังเป็น mock — ยังไม่มีข้อมูลรองรับ
  • Transaction (วิเคราะห์ระบบ) · ตาราง "โบนัสผิดปกติ — Top 10" ขับเคลื่อนด้วย endpoint ใหม่ /api/reports/top-bonus (รายการฝาก 10 อันดับที่โบนัสสูงสุด join สมาชิกและธนาคาร), และกราฟแท่งฝาก/ถอนรายวันอ่านจากเทรนด์ 14 วันตัวจริง · การปิดบังชื่อผู้ใช้ยังทำฝั่ง client
  • วิเคราะห์ผู้เล่น (Report) · endpoint ใหม่ /api/reports/player-report แยกสมาชิกเป็นใหม่/เก่าตามวันสมัคร (กำหนดช่วงได้ ค่าเริ่มต้น 30 วัน) แล้วรวมยอดฝาก/ถอน/โบนัสจริงของแต่ละกลุ่ม — เลิกใช้ค่าประมาณเดิม "เก่า = ใหม่ × 6.5" · กราฟใช้ชุดข้อมูลเทรนด์ตัวจริง
  • ทั้ง 5 หน้ามีป้าย LIVE และจะถอยกลับไปแสดง mock เดิมถ้าโหลดข้อมูลจริงไม่สำเร็จ

The rest of the Reports section goes live — 25.4–25.8, 25.13 + System Promotion

หน้ารายงานที่เหลือดึงข้อมูลจริงแล้ว — 25.4–25.8, 25.13 + สรุปโปรโมชันระบบ

  • One additive database migration backs all seven pages. A new migration adds only what these reports need — a promotions catalogue, cashback / commission / coupon tables, a hidden-deposit ledger, a first-deposit flag and a member-referrer link — without touching or dropping a single existing row. It was applied to production after a full database backup (with automatic rollback armed), and it backfills each member's first deposit from existing records, so 25.4 First Deposit lit up with real data immediately — 451 first deposits.
  • 25.4 First Deposit, 25.5 Cashback, 25.6 Commission, 25.7 Hidden Deposits, 25.8 Promo Summary, 25.13 Coupons and the System Promotion view all read from live endpoints now — each filterable, paginated and carrying a LIVE chip. 25.7 also gains an Approve button that matches a hidden bank credit to a member and writes an audit entry.
  • Honest about empty pages. Production is never re-seeded, so reports whose data has no historical source — cashback, commission, hidden deposits, coupons — start empty and fill as real activity happens. Promo Summary and System Promotion show the promotion catalogue at zero usage for the same reason: we deliberately did not invent promo labels for old deposits. On a fresh demo database every one of these is fully populated.
  • การย้ายฐานข้อมูลแบบเพิ่มอย่างเดียวรองรับทั้ง 7 หน้า · migration ใหม่เพิ่มเฉพาะสิ่งที่รายงานเหล่านี้ต้องใช้ — แคตตาล็อกโปรโมชัน, ตาราง cashback / commission / คูปอง, รายการฝากที่ถูกซ่อน, ธงฝากแรก และการเชื่อมผู้แนะนำ — โดยไม่แตะหรือลบข้อมูลเดิมแม้แต่แถวเดียว · ใช้กับ production หลังสำรองฐานข้อมูลเต็ม (พร้อม rollback อัตโนมัติ) และเติมข้อมูลฝากแรกของสมาชิกแต่ละรายจาก record เดิม หน้า 25.4 ฝากแรกจึงมีข้อมูลจริงทันที — ฝากแรก 451 รายการ
  • 25.4 ฝากแรก, 25.5 Cashback, 25.6 Commission, 25.7 ฝากที่ถูกซ่อน, 25.8 สรุปโปรโมชัน, 25.13 Coupon และหน้าโปรโมชันของวิเคราะห์ระบบ · ทุกหน้าดึงข้อมูลจาก endpoint จริงแล้ว — กรอง + แบ่งหน้าได้ และมีป้าย LIVE · 25.7 มีปุ่มอนุมัติที่จับคู่เงินเข้าธนาคารที่ถูกซ่อนกับสมาชิกและบันทึก audit
  • ตรงไปตรงมาเรื่องหน้าที่ยังว่าง · prod ไม่เคย seed ใหม่ หน้าที่ข้อมูลไม่มีแหล่งย้อนหลัง — cashback, commission, ฝากที่ถูกซ่อน, คูปอง — จึงเริ่มจากว่างและจะเติมเมื่อมีกิจกรรมจริง · สรุปโปรโมชันและโปรโมชันระบบแสดงแคตตาล็อกโปรโมชันที่ยอดใช้เป็น 0 ด้วยเหตุผลเดียวกัน เราตั้งใจไม่ใส่ชื่อโปรโมชันเดา ๆ ให้รายการฝากเก่า · บนฐานข้อมูล demo ใหม่ทุกหน้ามีข้อมูลครบ

Edit history — bonus and withdrawal-amount changes are now logged (25.11, 25.12)

ประวัติการแก้ไข — บันทึกการเปลี่ยนยอดโบนัสและยอดถอนแล้ว (25.11, 25.12)

  • Editing a deposit's bonus or a withdrawal's paid amount now writes an audit entry capturing the before → after value and who made the change. Two new endpoints back this, so every edit leaves a trail instead of silently overwriting the number.
  • 25.11 (bonus edits) and 25.12 (withdrawal-amount edits) read that trail from the audit log. 25.12 had been a "coming soon" placeholder and is now a real page. On production these fill as operators make edits; the withdrawal page already shows the existing approve / reject / edit history.
  • การแก้ไขโบนัสของรายการฝาก หรือยอดจ่ายของการถอน ตอนนี้เขียน audit บันทึกค่าก่อน → หลัง และผู้แก้ไข · มี endpoint ใหม่ 2 ตัวรองรับ ทุกการแก้ไขจึงทิ้งร่องรอยไว้แทนที่จะเขียนทับตัวเลขเงียบ ๆ
  • 25.11 (แก้ไขโบนัส) และ 25.12 (แก้ไขยอดถอน) · อ่านร่องรอยนี้จาก audit log · 25.12 เคยเป็นหน้า "เร็ว ๆ นี้" ตอนนี้เป็นหน้าจริงแล้ว · บน production จะเติมเมื่อ operator แก้ไข ส่วนหน้าถอนแสดงประวัติอนุมัติ / ปฏิเสธ / แก้ไขที่มีอยู่แล้ว

No slot 8.2 changes today.

ไม่มีการเปลี่ยนแปลงใน slot 8.2 วันนี้

No slot 8.3 changes today.

ไม่มีการเปลี่ยนแปลงใน slot 8.3 วันนี้

5 commits · b195a37 → 6f53dbc · The backoffice gets teeth: inline approve/reject with curated reason codes, filter + paging + sort on the live tables, and a member activity timeline with right-click drill-downหลังบ้านเริ่มลงมือได้จริง: อนุมัติ/ปฏิเสธในแถวพร้อมเหตุผลสำเร็จรูป, ตัวกรอง + แบ่งหน้า + เรียงลำดับบนตารางจริง, และไทม์ไลน์กิจกรรมของสมาชิกพร้อมคลิกขวาเปิดโปรไฟล์
Cross-cutting ข้ามทุก slot

Operator actions wired onto the live tables

การลงมือของ operator เชื่อมเข้ากับตารางจริง

  • Approve / Reject buttons on the live Deposit (25.1) and Withdrawal (25.2) tables. The dashboard's core verb finally has a trigger — the approve/reject endpoints existed but had no UI, so operators had to leave for the old panel. Every Pending/Processing row now carries Approve and Reject buttons; clicking opens a small confirm popover (no one-tap fire). A 409 stale-guard handles two operators racing the same row — if it was already actioned you get an "already processed" toast and the table refreshes instead of a silent double-action. Every action writes an audit_events row.
  • Reject reason codes. Reject opens six curated chips — duplicate slip / wrong amount / unverified account / suspected abuse / bank mismatch / other (free text) — and Confirm stays disabled until one is picked. The stable code is stored in the audit payload, so rejects are categorized and countable later instead of free-text guesswork.
  • Filter bar + paging + sort on the live Members (6.1), Deposit (25.1) and Withdrawal (25.2) tables. Status / currency / search / date-range filters (server-side — the API already honored the params, the frontend was throwing them away), « prev / next » paging with an "X–Y of N" count, and click-to-sort column headers. Filter + sort state is sticky per page via sessionStorage, so it survives navigating away and back within a shift.
  • ปุ่มอนุมัติ / ปฏิเสธ บนตารางฝาก (25.1) และถอน (25.2) ตัวจริง · กริยาหลักของ dashboard มีปุ่มกดสักที — endpoint อนุมัติ/ปฏิเสธมีอยู่แล้วแต่ไม่มี UI operator เลยต้องออกไปใช้แผงเก่า · ทุกแถวสถานะ Pending/Processing มีปุ่มอนุมัติและปฏิเสธ กดแล้วเปิด popover ยืนยันเล็ก ๆ (ไม่มี one-tap) · มี 409 stale-guard กันกรณี operator สองคนชนแถวเดียวกัน — ถ้าถูกดำเนินการไปแล้วจะขึ้น toast "รายการถูกดำเนินการไปแล้ว" และรีเฟรชตารางแทนที่จะ double-action เงียบ ๆ · ทุกการกระทำเขียนแถว audit_events
  • เหตุผลการปฏิเสธแบบสำเร็จรูป · กดปฏิเสธแล้วเปิด chip 6 ตัว — สลิปซ้ำ / ยอดไม่ตรง / บัญชีไม่ยืนยัน / สงสัยทุจริต / ธนาคารไม่ตรง / อื่น ๆ (พิมพ์เอง) — ปุ่มยืนยันยังกดไม่ได้จนกว่าจะเลือก · code ที่คงที่ถูกเก็บใน payload ของ audit รายการปฏิเสธจึงจัดหมวดและนับได้ภายหลัง ไม่ใช่ free-text เดา ๆ
  • แถบตัวกรอง + แบ่งหน้า + เรียงลำดับ บนตารางสมาชิก (6.1), ฝาก (25.1) และถอน (25.2) ตัวจริง · ตัวกรองสถานะ / สกุลเงิน / ค้นหา / ช่วงวันที่ (ฝั่ง server ซึ่ง API รองรับอยู่แล้ว แต่ frontend เคยทิ้งค่าไป), แบ่งหน้า « ก่อนหน้า / ถัดไป » พร้อมตัวนับ "X–Y / N", และหัวคอลัมน์กดเรียงได้ · สถานะตัวกรอง + การเรียงถูกจำต่อหน้าใน sessionStorage จึงอยู่ครบเมื่อสลับหน้าไปกลับภายในกะเดียว

Member profile: Activity timeline + right-click drill-down

โปรไฟล์สมาชิก: ไทม์ไลน์กิจกรรม + คลิกขวาเปิดโปรไฟล์

  • Open any player's profile by right-clicking their username → "Open profile". Until now the profile page was hardwired to a single demo member; the right-click menu (which already had "Ask AIVA") gains an Open-profile entry that loads that exact player.
  • New Activity tab on the profile — one timeline of everything that happened to a player. A new GET /api/members/:id/activity endpoint merges the member's deposits, withdrawals, notes, tags and outbound SMS into a single newest-first, paginated stream (each row icon-tagged: 💰 deposit / 💸 withdrawal / 📝 note / 🏷 tag / 📤 SMS). Deposit/withdrawal approve-reject audit is folded into the transaction rows rather than listed twice, and timestamps from the different sources are normalized so same-day events sort in true chronological order.
  • เปิดโปรไฟล์ผู้เล่นคนไหนก็ได้ด้วยการคลิกขวาที่ชื่อ → "เปิดโปรไฟล์" · ก่อนหน้านี้หน้าโปรไฟล์ถูกฮาร์ดโค้ดให้โชว์สมาชิกตัวอย่างคนเดียว · เมนูคลิกขวา (ที่มี "ถาม AIVA" อยู่แล้ว) เพิ่มรายการเปิดโปรไฟล์ที่โหลดผู้เล่นคนนั้นจริง ๆ
  • แท็บ Activity ใหม่บนโปรไฟล์ — ไทม์ไลน์เดียวรวมทุกอย่างที่เกิดกับผู้เล่น · endpoint ใหม่ GET /api/members/:id/activity รวมการฝาก ถอน โน้ต แท็ก และ SMS ขาออกของสมาชิกเป็น stream เดียวเรียงใหม่สุดก่อน แบ่งหน้าได้ (แต่ละแถวมีไอคอน: 💰 ฝาก / 💸 ถอน / 📝 โน้ต / 🏷 แท็ก / 📤 SMS) · audit อนุมัติ/ปฏิเสธของฝาก-ถอนถูกรวมเข้ากับแถวธุรกรรมแทนที่จะโชว์ซ้ำ · timestamp จากแต่ละแหล่งถูก normalize ให้เหตุการณ์วันเดียวกันเรียงตามเวลาจริง

No slot 8.2 changes today.

ไม่มีการเปลี่ยนแปลงใน slot 8.2 วันนี้

No slot 8.3 changes today.

ไม่มีการเปลี่ยนแปลงใน slot 8.3 วันนี้

4 commits · b9f3ff5 → 012c3bd · AIVA Chat: send SMS straight from the chat panel · two contextual follow-up prompts under every player replyแชท AIVA: ส่ง SMS ตรงจากแผงแชท · 2 prompt ต่อยอดที่เข้ากับบริบทใต้คำตอบทุกครั้งที่ผูกผู้เล่น
Cross-cutting ข้ามทุก slot

Changes that touch the whole site

การเปลี่ยนแปลงที่กระทบทั้งไซต์

  • Two contextual follow-up prompts under every player-bound reply — once AIVA finishes answering inside a member context, two dashed pill buttons (↳ …) appear under the reply suggesting the next deep-dive prompt. Click pre-fills the textarea and fires the next turn; the whole row vanishes the moment you pick one, because the alternatives are noise once you've committed to a direction. The model generates the two suggestions itself, wrapped in <followup>…</followup> tags it's instructed to append at the end of each reply — kept to ≤9 words, phrased as the operator would type it, in whichever language the operator is chatting in. A small streaming filter strips both completed and in-flight <followup> tags from the visible bubble so the operator never sees raw markup. The greeting message still shows the curated three quick-pick chips (💡 Next action / 🎯 Risk profile / 💬 Draft SMS) — those are the entry points, the follow-ups complement them.
  • Chat replies got ~3× faster — model swap to Groq + Llama 3.3 70B Versatile. The chat backend moved from gemini-2.5-flash-lite to groq('llama-3.3-70b-versatile') via the AI SDK's @ai-sdk/groq provider. Measured end-to-end time for a typical right-click → chip → reply dropped from ~2-4s to ~0.9-1.5s through HTTPS, Caddy, the AIVA chat proxy, and the upstream LPU. The trigger was the previous model hitting its daily free-tier cap mid-session and silently closing the stream on overflow; Groq's free quota is large enough that one operator team should never hit it. Same maxOutputTokens=400 cap and same "2-3 sentences, 80 words" system prompts; honest trade-off is that Llama's Thai phrasing is a small step more formal than Gemini's, but for short SMS-drafting and risk-summary replies it reads naturally. AIVA's /api/chat proxy didn't change — the upstream swap is invisible to the dashboard.
  • 2 prompt ต่อยอดเข้ากับบริบทใต้คำตอบทุกครั้งที่ผูกผู้เล่น — เมื่อ AIVA ตอบเสร็จในขณะที่ผูก member context อยู่ จะมีปุ่ม pill เส้นประ 2 ตัว (↳ …) ปรากฏใต้คำตอบ เสนอ prompt ขุดลึกขั้นถัดไป · กดแล้ว pre-fill ช่องพิมพ์และส่ง turn ถัดไป; แถวทั้งแถวจะหายไปทันทีที่เลือก เพราะตัวเลือกอื่นเป็นแค่ noise เมื่อตัดสินใจไปแล้ว · โมเดลสร้าง 2 prompt เอง โดยห่อในแท็ก <followup>…</followup> ที่ระบบสั่งให้เติมท้ายทุกคำตอบ — จำกัด ≤9 คำ, เขียนเหมือนที่ operator จะพิมพ์, ในภาษาที่ operator กำลังคุยอยู่ · filter ช่วง streaming ตัดทั้งแท็ก <followup> ที่สมบูรณ์และที่กำลังมาออกจาก bubble ที่มองเห็น operator จึงไม่เห็น markup ดิบ · ข้อความทักทายตอนเปิดแชทยังคงโชว์ chip prompt ด่วน 3 ตัวเดิม (💡 แนะนำขั้นถัดไป / 🎯 วิเคราะห์ความเสี่ยง / 💬 ร่างข้อความ SMS) — chip เป็นจุดเริ่ม, follow-up เสริมต่อจากนั้น
  • แชทตอบเร็วขึ้น ~3 เท่า — เปลี่ยน model เป็น Groq + Llama 3.3 70B Versatile · backend แชทย้ายจาก gemini-2.5-flash-lite ไปใช้ groq('llama-3.3-70b-versatile') ผ่าน provider @ai-sdk/groq ของ AI SDK · วัดเวลา end-to-end ของ right-click → chip → คำตอบ ลดจาก ~2-4 วินาที เหลือ ~0.9-1.5 วินาที ผ่าน HTTPS, Caddy, proxy ของ AIVA chat, และ LPU ต้นทาง · ที่กระตุ้นให้ย้ายคือ model เดิมชน cap free-tier รายวันกลาง session แล้วปิด stream เงียบ ๆ; quota ฟรีของ Groq ใหญ่พอที่ทีม operator ทีมเดียวจะไม่ชน · ใช้ maxOutputTokens=400 เดิมและ system prompt "2-3 ประโยค 80 คำ" เดิม · trade-off ตามจริงคือ ภาษาไทยของ Llama เป็นทางการกว่า Gemini เล็กน้อย แต่สำหรับการร่าง SMS สั้น ๆ และสรุปความเสี่ยงยังอ่านเป็นธรรมชาติ · proxy /api/chat ของ AIVA ไม่ต้องแก้ — การ swap ต้นทางไม่กระทบ dashboard

No slot 8.1 changes today.

ไม่มีการเปลี่ยนแปลงใน slot 8.1 วันนี้

No slot 8.2 changes today.

ไม่มีการเปลี่ยนแปลงใน slot 8.2 วันนี้

Send SMS straight from the AIVA chat panel

ส่ง SMS ตรงจากแผงแชท AIVA

  • 📤 Send SMS button appears under AIVA's reply when the operator picks the "Draft SMS" chip. The model is now asked to put the SMS body itself inside <sms>…</sms> tags at the end of its reply (Thai, ≤320 chars, no links, no all-caps); the tags are stripped from the visible bubble. Click the button and a confirmation modal opens — every dispatch is operator-confirmed, no one-tap fire. The modal shows the recipient (To: @username, Phone: … snapshotted from the member record), an editable preview textarea pre-filled with the extracted SMS body, and a live N / 480 char counter that turns red over the limit.
  • Confirm → posts to a new POST /api/twilio/sms route. The backend loads the member's phone from the DB, then either calls Twilio's REST API (when TWILIO_ACCOUNT_SID / AUTH_TOKEN / FROM are present in .env) or short-circuits in dry-run mode. Today ships in dry-run — no creds are wired yet, so every send is recorded but no actual Twilio call goes out. When the creds drop in, the route flips to live with no UI change. After a successful send (real or dry-run), the modal closes and the chat thread gets a confirmation message ✅ ส่ง SMS สำเร็จ (ทดสอบ) · #N with the log row id.
  • New outreach_log table records every attempt regardless of channel. Migration 003_outreach_log.sql adds id, member_id, channel (sms / voice), to_number (snapshot of the member's phone at send time), body, status (dry_run / sent / failed), twilio_sid (when live), error (when failed), sent_by, created_at. Indexed by member + recency. The table is the paper trail for AIVA's outbound contact with players — useful next for throttling (≤1 SMS per member per N days), templates, and the operator activity timeline.
  • GET /api/twilio/log exposes the trail with an optional ?member_id=N filter and a live flag in the payload indicating whether the route is in dry-run or real-dispatch mode.
  • ปุ่ม 📤 ส่ง SMS ปรากฏใต้คำตอบของ AIVA เมื่อ operator กด chip "ร่างข้อความ SMS" · โมเดลถูกสั่งให้ใส่ตัวเนื้อหา SMS ในแท็ก <sms>…</sms> ที่ท้ายคำตอบ (ภาษาไทย, ≤320 ตัวอักษร, ไม่มีลิงก์, ไม่ใช้ตัวพิมพ์ใหญ่ทั้งหมด); แท็กถูกตัดออกจาก bubble ที่มองเห็น · กดปุ่มแล้ว modal ยืนยันจะเปิดขึ้น — ทุกการส่งต้อง operator ยืนยัน ไม่มี one-tap · modal โชว์ผู้รับ (ถึง: @username, เบอร์ปลายทาง: … snapshot จาก record ของสมาชิก), textarea preview แก้ไขได้ pre-fill เนื้อหา SMS ที่ extract ออกมา, และตัวนับ N / 480 ที่เปลี่ยนเป็นสีแดงเมื่อเกินกำหนด
  • ยืนยัน → POST ไปที่ route ใหม่ POST /api/twilio/sms · backend ดึงเบอร์ของสมาชิกจาก DB แล้ว ถ้ามี TWILIO_ACCOUNT_SID / AUTH_TOKEN / FROM ใน .env จะเรียก Twilio REST API จริง ๆ ถ้าไม่มีก็ตกใน dry-run mode · วันนี้ขึ้นแบบ dry-run — ยังไม่ wire creds ทุกการส่งจึงถูกบันทึกแต่ไม่มีการเรียก Twilio จริง · เมื่อ creds มา route จะ flip เป็น live โดยไม่ต้องแก้ UI · หลังส่งสำเร็จ (จริงหรือ dry-run) modal ปิด และ thread แชทได้ข้อความยืนยัน ✅ ส่ง SMS สำเร็จ (ทดสอบ) · #N พร้อม id ของแถว log
  • ตาราง outreach_log ใหม่บันทึกทุกความพยายามไม่ว่าจะ channel ไหน · migration 003_outreach_log.sql เพิ่ม id, member_id, channel (sms / voice), to_number (snapshot เบอร์สมาชิก ณ เวลาส่ง), body, status (dry_run / sent / failed), twilio_sid (เมื่อ live), error (เมื่อ failed), sent_by, created_at · index ตามสมาชิก + ความใหม่ · ตารางนี้คือ paper trail ของการ outbound จาก AIVA ถึงผู้เล่น — ใช้ต่อกับ throttle (≤1 SMS ต่อสมาชิกต่อ N วัน), template, และ timeline กิจกรรม operator
  • GET /api/twilio/log เปิดให้อ่าน trail มีตัวกรอง ?member_id=N และ flag live ใน payload บอกว่า route อยู่ใน dry-run หรือ live
12 commits · 8caa5de → 3cd9a93 · AIVA v2 backoffice — fresh build · EN/TH toggle · right-click → Ask AIVA · 3 quick-pick prompts · chat ~2× fasterAIVA v2 backoffice — เริ่มใหม่ · สลับ EN/TH · คลิกขวา → ถาม AIVA · 3 prompt ด่วน · แชทเร็วขึ้น ~2 เท่า
Cross-cutting ข้ามทุก slot

Changes that touch the whole site

การเปลี่ยนแปลงที่กระทบทั้งไซต์

  • AIVA v2 backoffice shipped at /AIVA-v2/ — a from-scratch rebuild of the AIVA dashboard in the style of the AMBWIN backoffice mockup (Thai-first, green theme, Sarabun font, 6-currency tabs, bank cards). Different stack from v1: a real Node + Express server with node:sqlite behind Caddy, run by systemd as a dedicated aiva-v2 system user, on its own port (3100) at /opt/aiva-v2. v1 at /AIVA/ is untouched and keeps running — both dashboards live side-by-side, no cutover planned.
  • Real API powering 18 of ~30 pages — backed by a fresh SQLite DB seeded with 480 members, 3,073 deposits, 1,224 withdrawals, 200 AutoPeer transactions, 60 AIVA call logs, and 60 AI suggestions, all generated by a deterministic PRNG so re-running the seed is reproducible. Live now: Home (KPIs, bank cards, recent deposits), Dashboard (KPIs + 14-day inline-SVG trend chart + by-bank breakdown), Member list + Member groups, Agent Leaderboard, Player Leaderboard, AutoPeer Dashboard/Deposit/Withdraw/Credit, Reports 25.1 (deposit), 25.2 (withdrawal), 25.3 (deposit+withdrawal), Player Profile, AIVA Smart Suggestion, AIVA Auto Insight, AIVA Call Report. Remaining ~12 pages (Reports 25.4–25.13, Player Activity/Report/Type/Online, AutoPeer Settings) still render the mockup's hardcoded arrays — wiring is purely additive.
  • Notification bell in the topbar — same idea as the v1 bell on /AIVA/ but local-first on v2. Two tabs: Notifications (3 seeded entries + every submitted feedback echoed back) and Send Feedback (type pill, title, details, Telegram handle). The form posts through a v2 backend route that proxies to feedback.askmeaiva.com's public CORS bridge — same place v1 broadcasts route through — and writes a local notification regardless of upstream success, so the bell always reflects what was submitted. Unread badge polls every 60s; "อ่านทั้งหมด" clears all.
  • Floating AIVA chat bubble bottom-right — green gradient FAB with a 💬 speech bubble (started as a robot 🤖; iterated to a chat bubble for clarity). Opens a panel that streams replies token-by-token from the same backend Gemini 2.5 Flash service that powers the in-app launcher on v1's /AIVA/, reached via a v2 /api/chat proxy so the frontend talks to a single origin. If the upstream is offline the panel surfaces a clear 502 with a hint instead of hanging.
  • Sidebar logo says tiamut — top-left of the v2 sidebar reads tiamut with a gold "m" matching the existing logo-y accent, signalling this dashboard is for the Tiamut platform. The user chip in the topbar shows aiva-admin · Prefix: AIVA as a stand-in until real per-operator login is wired.
  • 27 API endpoints across 12 route files — currencies, banks, member-groups, members (+ detail), deposits (+ approve/reject), withdrawals (+ approve/reject), dashboard (kpis / trend / bank-summary), leaderboard (players + agents), reports (deposits / withdrawals / dep-wd), aiva (suggestions / calls / insights), autopeer (dashboard / transactions), notifications, feedback (proxy), chat (proxy). All list endpoints support ?limit, ?offset, currency / status / bank / channel filters, date ranges, and free-text search. Schema lives in one idempotent migration plus a notifications add-on.
  • Repo + deploy now match the tiamut-feedback pattern — code at git.askmeaiva.com/fargeiw/aiva-v2; deployed by SSHing into the VPS, git pull in /opt/aiva-v2, restart the systemd unit. The unit ships with the same hardening as tiamut-feedback (NoNewPrivileges, PrivateTmp, ProtectSystem=full, ProtectHome, ReadWritePaths scoped to the SQLite data dir). Caddyfile gained one handle_path /AIVA-v2/* line — every other route on the askmeaiva site block is unchanged.
  • Language dropdown + working EN translation — the static "🌐 ภาษาไทย" label in the topbar became a real chip-style dropdown with three options (🇹🇭 ไทย / 🇬🇧 English / 🇰🇭 ខ្មែរ); selection persists in localStorage. A new frontend/js/i18n.js ships a 75-entry TH→EN dictionary covering every sidebar item (top-level + Reports 25.1–25.13 + Members + AutoPeer), the topbar's 🔒 emergency-lock button, the notification bell panel (tabs / buttons / empty state / the 3 seeded entries), the Send Feedback form (all labels + every input placeholder + validation / sending / success / error states), the AIVA chat panel (header / status / input placeholder / greeting / runtime errors), and every LIVE overlay heading and KPI label on the wired pages. A TreeWalker scans text nodes on load and stashes the original Thai in a WeakMap so toggling back to ไทย restores it exactly; a MutationObserver catches dynamic content added later by the bell, the chat, and wire.js. Khmer 🇰🇭 currently falls back to Thai — it's a visual choice until a Khmer dictionary lands.
  • Right-click any player → "Ask AIVA about this player" — every username rendered by the live overlays (Members list, Deposit / Withdrawal reports, Player Leaderboard, AutoPeer Deposit / Withdraw / Credit, AIVA Smart Suggestion, AIVA Call Report, Player Profile, even Home's recent-deposits feed) is now wrapped in a tagged span. Right-click pops a small menu at the cursor with one action. Click it and the chat panel opens with an amber Context: @username · CURRENCY · Segment chip and the previous conversation cleared. The next POST /api/chat carries a custom system prompt containing the member's full profile + last 5 deposits + last 5 withdrawals fetched from /api/members/:id, so Gemini's reply is grounded in real data and can cite report numbers (25.1, 25.2, …) when relevant. The × on the context chip clears the binding and resets the chat. No backend changes — reuses the existing /api/members/:id and the system field already supported by the chat proxy.
  • Three quick-pick prompts when a player is selected — instead of a single pre-filled question, the chat panel now shows a row of three pill buttons under the amber context chip: 💡 Next action, 🎯 Risk profile, 💬 Draft SMS. Click any chip and the long-form prompt (e.g. "Draft a short Thai SMS to reach out to this player") sends immediately — the system context with the member's profile is already in place, so the reply is grounded. The chip row hides after the first send so the thread reads cleanly; clearing the context or right-clicking a different player brings them back. The Draft SMS preset reflects the project constraint that outbound to humans is SMS + voice calls only — no email anywhere.
  • Chat model swap: gemini-2.5-flashgemini-2.5-flash-lite — the free tier on gemini-2.5-flash caps at 20 generate-content requests per project per day, and the right-click → Ask AIVA testing blew through it within an hour, leaving the chat returning empty 200 responses (the SDK writes headers before calling Google, so the upstream 429 surfaces as a silently-closed stream). Switched the model in aiva-chat-demo to gemini-2.5-flash-lite on the same free tier and same API key, raising the daily ceiling to roughly 1,000 requests with comparable quality for short backoffice replies. Live test post-deploy: ~1.5s round-trip through the v2 proxy, no other code changes.
  • Chat response ~2× faster + Thai panel fully Thai — measured total time for a typical right-click → Ask AIVA round-trip dropped from ~10s to ~2-4s. Two compounding changes: aiva-chat-demo's streamText call now caps replies at maxOutputTokens=400, and both v2 system prompts (default + member-context) instruct the model to reply in 2-3 short sentences, 80 words max, no bullet lists unless asked. Total time on free-tier Gemini is streaming-dominated once TTFB clears, so capping output roughly halves it — TTFB itself stays at the usual ~1-3s with occasional 5-15s spikes (Google-side variance). Same pass also closed five English-leaking spots in the Thai version of the chat panel: header name was 'AIVA Assistant', greeting ended in '…backoffice บ้างครับ?', quick-pick #1 read 'แนะนำ next action' as label and prompt, and fetch-error messages prefixed with 'AIVA error:'. Defaults switched to pure Thai ('AIVA · ผู้ช่วย', 'ระบบหลังบ้าน', 'แนะนำขั้นถัดไป' / 'แนะนำขั้นตอนถัดไปที่ดีที่สุดสำหรับผู้เล่นคนนี้', 'ข้อผิดพลาด AIVA') with dictionary keys re-pointed so 🇬🇧 English still maps to the same English copy.
  • AIVA v2 backoffice ขึ้นจริงที่ /AIVA-v2/ — เริ่มต้นใหม่หมดในสไตล์ของ backoffice mockup ของ AMBWIN (ภาษาไทยเป็นหลัก, ธีมเขียว, ฟอนต์ Sarabun, แท็บ 6 สกุลเงิน, การ์ดธนาคาร) · stack ต่างจาก v1: Node + Express จริง ๆ พร้อม node:sqlite หลัง Caddy, รันด้วย systemd ในนามของ system user aiva-v2 โดยเฉพาะ, บนพอร์ตของตัวเอง (3100) ที่ /opt/aiva-v2 · v1 ที่ /AIVA/ ไม่ถูกแตะและยังรันอยู่ — ทั้งสอง dashboard อยู่คู่กัน ไม่มีแผน cutover
  • API จริงขับเคลื่อน 18 จาก ~30 หน้า — รองรับด้วย SQLite DB ใหม่ที่ seed ด้วยข้อมูล 480 ผู้เล่น, 3,073 รายการฝาก, 1,224 รายการถอน, 200 ธุรกรรม AutoPeer, 60 บันทึกการโทรของ AIVA และ 60 ข้อเสนอ AI ทั้งหมดมาจาก PRNG แบบ deterministic ดังนั้นการรัน seed ซ้ำให้ผลเหมือนเดิม · ที่ live แล้ว: หน้าหลัก (KPIs, การ์ดธนาคาร, รายการฝากล่าสุด), แดชบอร์ด (KPIs + กราฟ 14 วันแบบ inline SVG + แยกตามธนาคาร), รายชื่อสมาชิก + กลุ่มลูกค้า, Agent Leaderboard, Player Leaderboard, AutoPeer แดชบอร์ด/ฝาก/ถอน/เครดิต, รายงาน 25.1 (ฝาก), 25.2 (ถอน), 25.3 (ฝาก+ถอน), Player Profile, AIVA Smart Suggestion, AIVA Auto Insight, AIVA Call Report · ~12 หน้าที่เหลือ (รายงาน 25.4–25.13, Player Activity/Report/Type/Online, AutoPeer Settings) ยังใช้ข้อมูล hardcode จาก mockup — งานต่อเป็นแบบเสริมล้วน
  • ระฆังแจ้งเตือนบนแถบบน — แนวคิดเดียวกับระฆัง v1 ที่ /AIVA/ แต่บน v2 เก็บข้อมูลในเครื่องก่อน · มี 2 แท็บ: การแจ้งเตือน (3 รายการ seed + ทุก feedback ที่ส่งจะสะท้อนกลับมา) และ ส่ง Feedback (pill ประเภท, หัวข้อ, รายละเอียด, Telegram handle) · ฟอร์มส่งผ่าน route ใน v2 ที่ proxy ไปยัง CORS bridge สาธารณะของ feedback.askmeaiva.com — ที่เดียวกับที่ broadcast ของ v1 ไป — และเขียน notification ในเครื่องไม่ว่า upstream จะสำเร็จหรือไม่ ดังนั้นระฆังสะท้อนสิ่งที่ส่งเสมอ · badge ที่ยังไม่อ่าน poll ทุก 60 วินาที; "อ่านทั้งหมด" เคลียร์ทั้งหมด
  • ฟองสนทนา AIVA ลอยมุมขวาล่าง — ปุ่ม FAB ไล่เฉดเขียวพร้อม 💬 ฟองคำพูด (เริ่มต้นเป็น 🤖; ปรับเป็นฟองคำพูดเพื่อความชัดเจน) · กดเปิดแผงที่ stream คำตอบทีละ token จาก backend Gemini 2.5 Flash บริการเดียวกับที่ขับเคลื่อน launcher ในแอปบน /AIVA/ ของ v1, ถึงผ่าน proxy /api/chat ใน v2 เพื่อให้ frontend คุยกับ origin เดียว · ถ้า upstream ไม่ตอบ แผงจะแสดง 502 พร้อมคำใบ้แทนค้าง
  • โลโก้บน sidebar เป็น tiamut — มุมบนซ้ายของ sidebar v2 อ่านว่า tiamut โดย "m" สีทองให้เข้ากับ accent logo-y เดิม สื่อว่า dashboard นี้ใช้กับแพลตฟอร์ม Tiamut · ชิปผู้ใช้บนแถบบนเป็น aiva-admin · Prefix: AIVA เป็น placeholder จนกว่าจะเปิด login จริงต่อ operator
  • 27 API endpoints ใน 12 ไฟล์ route — currencies, banks, member-groups, members (+ detail), deposits (+ approve/reject), withdrawals (+ approve/reject), dashboard (kpis / trend / bank-summary), leaderboard (players + agents), reports (deposits / withdrawals / dep-wd), aiva (suggestions / calls / insights), autopeer (dashboard / transactions), notifications, feedback (proxy), chat (proxy) · ทุก list endpoint รองรับ ?limit, ?offset, ตัวกรองสกุลเงิน / สถานะ / ธนาคาร / channel, ช่วงวันที่, และค้นหาแบบ free-text · schema อยู่ใน migration แบบ idempotent ตัวเดียวบวก add-on สำหรับ notifications
  • repo + deploy เข้าแถวเดียวกับรูปแบบ tiamut-feedback — โค้ดอยู่ที่ git.askmeaiva.com/fargeiw/aiva-v2; deploy โดย SSH เข้า VPS, git pull ใน /opt/aiva-v2, restart systemd unit · unit ติดมาพร้อม hardening เดียวกับ tiamut-feedback (NoNewPrivileges, PrivateTmp, ProtectSystem=full, ProtectHome, ReadWritePaths ที่จำกัดเฉพาะโฟลเดอร์ข้อมูล SQLite) · Caddyfile เพิ่มแค่บรรทัด handle_path /AIVA-v2/* เดียว — route อื่น ๆ ใน site block ของ askmeaiva ไม่ถูกแตะ
  • Dropdown ภาษา + EN translation ใช้งานได้จริง — ป้ายข้อความ "🌐 ภาษาไทย" บนแถบบนกลายเป็น dropdown แบบ chip จริง 3 ตัวเลือก (🇹🇭 ไทย / 🇬🇧 English / 🇰🇭 ខ្មែរ); การเลือกถูกเก็บไว้ใน localStorage · มี frontend/js/i18n.js ใหม่ที่บรรจุ dictionary TH→EN 75 รายการ ครอบคลุม sidebar ทั้งหมด (top-level + รายงาน 25.1–25.13 + Members + AutoPeer), ปุ่ม 🔒 ล็อกฉุกเฉินบนแถบบน, แผงระฆัง (แท็บ / ปุ่ม / empty state / รายการ seed ทั้ง 3), ฟอร์ม Send Feedback (ทุก label + placeholder ทุกช่อง + ข้อความ validation / กำลังส่ง / สำเร็จ / ผิดพลาด), แผงแชท AIVA (header / สถานะ / placeholder ของช่องพิมพ์ / ข้อความทักทาย / error runtime), และทุกหัวเรื่อง + label KPI บนหน้า LIVE overlay ที่เชื่อม API แล้ว · TreeWalker scan text node ตอนโหลด เก็บ Thai ต้นฉบับใน WeakMap ดังนั้นสลับกลับเป็น ไทย คืนเหมือนเดิม; MutationObserver จับเนื้อหา dynamic ที่ระฆัง / แชท / wire.js เพิ่มเข้ามาทีหลัง · 🇰🇭 ខ្មែរ ตอนนี้ fallback ไปเป็นไทย — เป็นตัวเลือกแสดงผลจนกว่า Khmer dictionary จะมา
  • คลิกขวาที่ผู้เล่นใดก็ได้ → "ถาม AIVA เกี่ยวกับผู้เล่นนี้" — ทุก username ที่ render โดย LIVE overlay (รายชื่อสมาชิก, รายงานการฝาก / การถอน, Player Leaderboard, AutoPeer ฝาก / ถอน / เครดิต, AIVA Smart Suggestion, AIVA Call Report, Player Profile, รวมถึง feed รายการฝากล่าสุดบนหน้าหลัก) ตอนนี้ถูกห่อด้วย tagged span · คลิกขวาจะมีเมนูเล็กปรากฏที่ cursor พร้อมหนึ่ง action · กดแล้วแผงแชทจะเปิดขึ้นพร้อม chip สีอำพัน บริบท: @username · CURRENCY · Segment และ conversation เดิมถูก reset · POST /api/chat ถัดไปจะแนบ system prompt ที่มี profile ของสมาชิกเต็ม + รายการฝากล่าสุด 5 รายการ + รายการถอนล่าสุด 5 รายการ ที่ดึงจาก /api/members/:id, ดังนั้นคำตอบของ Gemini อิงข้อมูลจริงและอ้างเลขรายงานได้ (25.1, 25.2, …) เมื่อเหมาะสม · กด × บน chip บริบทเพื่อยกเลิกการผูกและ reset แชท · ไม่มีการแก้ backend — ใช้ /api/members/:id เดิมและ field system ที่ chat proxy รองรับอยู่แล้ว
  • 3 prompt ด่วนเมื่อเลือกผู้เล่น — แทนที่จะ pre-fill คำถามเดียวในช่องพิมพ์ แผงแชทตอนนี้แสดงปุ่ม pill 3 ตัวใต้ chip บริบทสีอำพัน: 💡 แนะนำ next action, 🎯 วิเคราะห์ความเสี่ยง, 💬 ร่างข้อความ SMS · กดปุ่มใดก็ได้แล้ว prompt ฉบับเต็ม (เช่น "ร่างข้อความ SMS เพื่อติดต่อผู้เล่นคนนี้ ภาษาไทย ความยาวสั้น") จะถูกส่งทันที — system context ที่มี profile ของสมาชิกแนบไปด้วยอยู่แล้ว คำตอบจึงอิงข้อมูลจริง · แถวปุ่มจะหายไปหลังส่งครั้งแรกเพื่อให้ thread อ่านสะอาด; ล้างบริบทหรือคลิกขวาผู้เล่นอื่นจะนำกลับมา · ปุ่ม ร่างข้อความ SMS สะท้อนข้อกำหนดของโปรเจกต์ว่าการ outbound ถึงคนใช้ได้แค่ SMS + โทรเสียง — ไม่มีอีเมลในที่ใด ๆ
  • เปลี่ยน chat model: gemini-2.5-flashgemini-2.5-flash-lite — free tier ของ gemini-2.5-flash จำกัด 20 generate-content requests ต่อ project ต่อวัน, และการทดสอบ คลิกขวา → ถาม AIVA วันนี้ใช้หมดภายในไม่ถึงชั่วโมง ทำให้แชทคืน response 200 เปล่า ๆ (SDK เขียน header ก่อนเรียก Google, upstream 429 จึงปรากฏเป็น stream ที่ปิดเงียบ) · เปลี่ยน model ใน aiva-chat-demo เป็น gemini-2.5-flash-lite บน free tier เดียวกันและ API key เดียวกัน เพิ่มเพดานต่อวันเป็นประมาณ 1,000 requests คุณภาพคำตอบสั้น ๆ ใน backoffice เทียบเคียงกัน · live test หลัง deploy: round-trip ~1.5 วินาทีผ่าน proxy v2, ไม่มีการแก้ code อื่น
  • แชทตอบเร็วขึ้น ~2 เท่า + แผงไทยเป็นภาษาไทยครบ — วัดเวลา round-trip รวมของ คลิกขวา → ถาม AIVA ลดจาก ~10 วินาที เหลือ ~2-4 วินาที · สองการเปลี่ยนแปลงที่ทำงานคู่กัน: streamText ใน aiva-chat-demo ตอนนี้คุมที่ maxOutputTokens=400, และ system prompt ทั้งสอง (default + member-context) ใน v2 สั่งโมเดลให้ตอบใน 2-3 ประโยคสั้น 80 คำสูงสุด ไม่ใช้ bullet list ถ้าไม่ได้ขอ · เวลารวมบน free-tier Gemini ถูกครอบงำโดย streaming เมื่อ TTFB ผ่าน, การจำกัด output จึงตัดได้ราวครึ่ง — TTFB เองยังราว ~1-3 วินาทีพร้อมโอกาสกระโดดไป 5-15 วินาทีบ้าง (variance ฝั่ง Google) · งานเดียวกันยังปิด 5 จุดที่ภาษาอังกฤษหลุดเข้ามาในแผงแชทเมื่อเลือก ไทย: ชื่อ header เป็น 'AIVA Assistant', คำทักทายลงท้าย '…backoffice บ้างครับ?', quick-pick #1 อ่านว่า 'แนะนำ next action' ทั้ง label และ prompt, และข้อความ error fetch ขึ้นต้นว่า 'AIVA error:' · เปลี่ยน default เป็นภาษาไทยทั้งหมด ('AIVA · ผู้ช่วย', 'ระบบหลังบ้าน', 'แนะนำขั้นถัดไป' / 'แนะนำขั้นตอนถัดไปที่ดีที่สุดสำหรับผู้เล่นคนนี้', 'ข้อผิดพลาด AIVA') และ re-point dictionary key ให้ 🇬🇧 English ยังคืน copy ภาษาอังกฤษเดิม

No slot-specific changes today — AIVA v2 is a whole new dashboard living next to /AIVA/ rather than a change to a slot.

ไม่มีการเปลี่ยนแปลงเฉพาะ slot วันนี้ — AIVA v2 เป็น dashboard ใหม่ทั้งตัวที่อยู่ข้าง /AIVA/ ไม่ใช่การแก้ไข slot

No changes in slot 8.2 today.

ไม่มีการเปลี่ยนแปลงใน slot 8.2 วันนี้

No changes in slot 8.3 today.

ไม่มีการเปลี่ยนแปลงใน slot 8.3 วันนี้

2 commits · 56ae8bd → 4cd21c9 · AIVA chat panel finally works · URL tidy-upsแผงแชท AIVA ใช้งานได้แล้ว · จัดระเบียบ URL
Cross-cutting ข้ามทุก slot

Changes that touch the whole site

การเปลี่ยนแปลงที่กระทบทั้งไซต์

  • AIVA chat panel actually responds now — the "Ask AIVA" launcher in the bottom-right has opened a chat UI since launch, but it was wired to /api/agent — a Vercel function endpoint that never resolved on the live Caddy-served site (no Vercel runtime on the VPS). Clicking Send returned the HTML index instead of JSON, so the panel was effectively a placeholder. Today it's connected to a new chat service running on the same VPS as a systemd-managed Node + Express process; replies stream back token-by-token straight into the assistant bubble.
  • Chat panel chrome refresh — header reads "AIVA · Assistant" (was "Data Analyst"), the empty-state message is honest about not having direct access to player or campaign data in this session, and the three suggestion buttons swap to general-purpose prompts: draft a Thai win-back SMS, explain RFM in three sentences, retention ideas. The original data-analyst persona with read-only tools over real player + campaign data is preserved in the repo but unwired — it'd need a real backing data layer on the VPS before it could be re-enabled.
  • URL tidy-ups — lowercase www.askmeaiva.com/aiva now 308-redirects to the dashboard (was previously a fall-through to the marketing landing page). The standalone chat page at /chat/ shipped earlier today was retired the same day — both /chat and /chat/ now bounce to the dashboard, so the in-app launcher is the single way in. The chat backend itself (/chat/api/*) keeps serving the dashboard's panel; backed by a free-tier LLM provider so demo traffic costs ฿0.
  • แผงแชท AIVA ตอบกลับได้แล้วจริง — ปุ่ม "Ask AIVA" มุมขวาล่างเปิดแผงแชทมาตั้งแต่เปิดตัว แต่ชี้ไปที่ /api/agent ซึ่งเป็น Vercel function endpoint ที่ไม่เคย resolve บนไซต์จริงที่ Caddy เสิร์ฟ (ไม่มี Vercel runtime บน VPS) · กด Send จะได้ HTML index คืนแทน JSON แผงจึงเป็นเหมือน placeholder · วันนี้เชื่อมเข้ากับ chat service ใหม่ที่รันบน VPS เดียวกันในรูปของ Node + Express จัดการด้วย systemd; การตอบกลับ stream แบบ token-by-token เข้าฟอง assistant ทันที
  • หน้าตาแผงแชทใหม่ — header เปลี่ยนเป็น "AIVA · Assistant" (เดิม "Data Analyst") · ข้อความ empty-state ซื่อสัตย์ว่าใน session นี้ไม่มีสิทธิ์เข้าถึงข้อมูลผู้เล่นหรือ campaign โดยตรง · ปุ่มแนะนำสามปุ่มเปลี่ยนเป็นคำถามทั่วไป: ร่าง SMS เรียกผู้เล่นกลับเป็นภาษาไทย, อธิบาย RFM ใน 3 ประโยค, ไอเดียการ retain ผู้เล่น · agent persona เดิม (Data Analyst ที่มี read-only tools ดู player + campaign จริง) ยังอยู่ใน repo แต่ไม่ได้เชื่อม — ต้องตั้ง data layer จริงบน VPS ก่อนถึงจะเปิดกลับมาได้
  • จัดระเบียบ URLwww.askmeaiva.com/aiva (ตัวพิมพ์เล็ก) 308-redirect เข้าหน้า dashboard แล้ว (ก่อนหน้านี้ตกไปที่หน้า marketing landing) · หน้าแชทเดี่ยวที่ /chat/ ที่ ship ไปต้น ๆ วันนี้ถูกปลดในวันเดียวกัน — ทั้ง /chat และ /chat/ ตอนนี้เด้งไปยัง dashboard, ให้ launcher ในแอปเป็นทางเดียวเข้าแชท · backend ของแชท (/chat/api/*) ยังเสิร์ฟแผงในหน้า dashboard อยู่; ใช้ผู้ให้บริการ LLM แบบ free tier ทำให้ traffic demo มีต้นทุน ฿0

No slot-specific changes today — the chat panel sits in the launcher and applies regardless of which slot you're on.

ไม่มีการเปลี่ยนแปลงเฉพาะ slot วันนี้ — แผงแชทอยู่ใน launcher และทำงานไม่ว่าจะอยู่ slot ใด

No changes in slot 8.2 today.

ไม่มีการเปลี่ยนแปลงใน slot 8.2 วันนี้

No changes in slot 8.3 today.

ไม่มีการเปลี่ยนแปลงใน slot 8.3 วันนี้

5 commits · 39ce7a9 → 9d6e968 · topbar 🔔 becomes alive · Tiamut feedback prompts · bilingual EN/TH🔔 บนแถบบนใช้งานได้แล้ว · รับข้อเสนอแนะ Tiamut · รองรับ EN/TH
Cross-cutting ข้ามทุก slot

Changes that touch the whole site

การเปลี่ยนแปลงที่กระทบทั้งไซต์

  • Topbar 🔔 is now a real notification dropdown — the placeholder bell with its hardcoded "10" badge is gone. Click the bell to open a panel anchored top-right; the badge is now a live unread count, "Mark all read" clears it, and click-outside / Esc closes the panel. The dropdown mixes locally-generated AIVA alerts (e.g. "3 new Cant Loose players this week", "Weekly Bonus fired · ฿82,400") with Tiamut feedback prompts the team broadcasts to your prefix.
  • Inline Tiamut feedback form — clicking a feedback prompt expands a form right inside the bell (no separate modal). Click the same prompt again to collapse it; opening a different prompt closes any other open one, so the panel stays tidy. Pick a type pill (🐛 Bug · ✨ Feature · 💡 Suggestion · ⚠ Complaint · 🔧 Improvement), write up to 2000 characters, hit Send. Your name + prefix (Nopparat.J · HHome) auto-attach, plus the broadcast id so the team sees which prompt drove your submission. After submit, the prompt collapses to "✓ Thanks!" and won't re-nag you in this browser.
  • Backend-driven broadcasts (new) — Tiamut admins can now fire a feedback request and every AIVA dashboard with the matching prefix picks it up automatically on next bell open. Each broadcast carries a title, body, optional prefix target, and expiry. 5 live now (all expire 2026-05-29): a general AIVA prompt ("Help shape Tiamut"), a Tiamut-platform prompt ("Tiamut overall — anything frustrating you?"), and three slot-specific cuts (Players (8.1), AIVA Rewards (8.2), AI SMS (8.3)). Read/submitted/dismissed state persists in pps75_notifs localStorage so handled prompts stay handled across reloads.
  • AGENT_PREFIX constant — added alongside AGENT_NAME at the top of the agent-notes module as the single source of truth for the signed-in operator's prefix. The bell, future-feature integrations, and anywhere else that needs "who is this dashboard for" can now read one constant instead of scraping the topbar DOM.
  • 📣 Admin broadcast UI on tiamut-feedback — a new 📣 Broadcasts button in the admin topbar opens a modal that composes new feedback prompts, lists every existing broadcast with its submission count, and toggles active state inline. No more SSH-into-VPS to fire a prompt. Every field is a dropdown: template (5 presets matching the slot cuts + Custom for free-text), target prefix (populated from the 27 real customer prefixes), expires in (7/14/30/60/90 days / Never). Modal auto-closes 700ms after a successful send.
  • Click-outside + Esc close on every admin modal — clicking the dimmed backdrop or hitting Esc now dismisses the open modal (broadcasts, edit-feedback, change-password). Single document-level listener in api.js so every admin page benefits without duplicate code.
  • Bell notifications now fully Thai-translated — completing today's bell story, the two demo alerts ("3 new Cant Loose players this week", "Weekly Bonus fired · 48 recipients · ฿82,400 paid · 67% claim rate so far"), the error toast prefix ("Couldn't send: …"), and the dynamic relative-time labels (5m ago / 2h ago / 3d ago) all flip to Thai when you toggle the language pill in the topbar. Strings live in LANG_TH so the existing MutationObserver picks them up — no separate render path.
  • Broadcasts are bilingual end-to-endfeedback_requests gained nullable title_th + body_th columns (idempotent migration runs on service restart). The public endpoint GET /api/feedback-requests/public returns both copies; the AIVA bell picks the TH copy when CURRENT_LANG==='th' and falls back to the EN copy when the broadcast is EN-only, so the 5 existing prompts keep rendering unchanged. The CLI gains --title-th="..." / --body-th="..." flags. Admin-typed text is tagged data-no-i18n so the LANG_TH dictionary doesn't try to translate it; local notifications strip the attribute so they still route through the dictionary. Toggling the language pill while the bell is open swaps copies immediately.
  • 🔔 บนแถบบนกลายเป็น dropdown แจ้งเตือนจริง — ไอคอนระฆัง placeholder ที่มี badge ตัวเลข "10" hardcode หายไปแล้ว · กดที่ระฆังจะเปิดแผงที่มุมบนขวา; badge เปลี่ยนเป็นจำนวนที่ยังไม่อ่านจริง, "Mark all read" ล้างทั้งหมด, คลิกนอก / ปุ่ม Esc ปิดแผง · แผงรวม alert จาก AIVA เอง (เช่น "3 new Cant Loose players this week", "Weekly Bonus fired · ฿82,400") กับ คำขอข้อเสนอแนะ Tiamut ที่ทีมส่งมายัง prefix ของคุณ
  • ฟอร์มข้อเสนอแนะ Tiamut ภายในระฆัง — กดที่คำขอข้อเสนอแนะ ฟอร์มจะกางออกในระฆังเลย (ไม่ใช่ modal แยก) · กดคำขอเดิมอีกครั้งเพื่อยุบ; เปิดคำขออื่นจะปิดอันที่เปิดอยู่ก่อน ฟอร์มจึงเปิดได้ทีละหนึ่งเท่านั้น · เลือก pill ประเภท (🐛 บั๊ก · ✨ ฟีเจอร์ · 💡 ข้อเสนอ · ⚠ ร้องเรียน · 🔧 ปรับปรุง), พิมพ์ได้สูงสุด 2000 ตัวอักษร, กด Send · ชื่อ + prefix ของคุณ (Nopparat.J · HHome) แนบให้อัตโนมัติ พร้อม id ของ broadcast ให้ทีมเห็นว่าคำขอไหนนำมาสู่ submission · หลังกดส่ง คำขอจะยุบเหลือ "✓ Thanks!" และจะไม่กวนใน browser นี้อีก
  • ระบบ broadcast จาก backend (ใหม่) — ผู้ดูแล Tiamut สามารถยิงคำขอข้อเสนอแนะ และทุก AIVA dashboard ที่มี prefix ตรงกันจะรับเข้ามาอัตโนมัติเมื่อเปิดระฆังครั้งถัดไป · แต่ละ broadcast มี title, body, target prefix (ถ้ามี), และวันหมดอายุ · ตอนนี้ live 5 รายการ (หมดอายุ 2026-05-29 ทั้งหมด): คำขอทั่วไปของ AIVA ("Help shape Tiamut"), คำขอสำหรับแพลตฟอร์ม Tiamut ("Tiamut overall — anything frustrating you?"), และเฉพาะ slot สามตัว (Players (8.1), AIVA Rewards (8.2), AI SMS (8.3)) · สถานะ อ่าน / ส่งแล้ว / ปิด ถูกบันทึกใน localStorage pps75_notifs เพื่อให้คำขอที่จัดการแล้วไม่กลับมาแสดงอีกข้ามการรีโหลด
  • ค่าคงที่ AGENT_PREFIX — เพิ่มข้าง AGENT_NAME ที่ต้นของโมดูล agent-notes เป็นแหล่งความจริงเดียวสำหรับ prefix ของ operator ที่ล็อกอินอยู่ · ระฆัง, ฟีเจอร์ในอนาคต, และทุกที่ที่ต้องรู้ว่า "dashboard นี้เป็นของใคร" อ่านค่าคงที่นี้ตัวเดียวแทนการขูด DOM ของแถบบน
  • 📣 UI ส่ง broadcast บน tiamut-feedback admin — ปุ่มใหม่ 📣 Broadcasts บนแถบบนของหน้า admin เปิด modal ที่ให้สร้างคำขอข้อเสนอแนะใหม่, แสดงรายการ broadcast ทั้งหมดพร้อมจำนวน submission, และสลับสถานะ active/inactive ได้ในที่เดียว · ไม่ต้อง SSH เข้า VPS เพื่อยิงคำขออีก · ทุกฟิลด์เป็น dropdown: template (5 preset ตรงกับ slot + Custom สำหรับเขียนเอง), target prefix (ดึงจาก 27 prefix ลูกค้าจริง), หมดอายุใน (7/14/30/60/90 วัน / ไม่หมดอายุ) · Modal ปิดเองหลังส่งสำเร็จ 700ms
  • คลิกนอก + ปุ่ม Esc ปิด modal ทุกตัวในหน้า admin — คลิก backdrop ที่หรี่หรือกด Esc จะปิด modal ที่เปิดอยู่ (broadcasts, edit-feedback, change-password) · listener เดียวระดับ document ใน api.js เพื่อให้ทุกหน้า admin ได้ประโยชน์โดยไม่ต้องเขียนโค้ดซ้ำ
  • Bell notification แปลไทยครบแล้ว — ต่อยอดงานระฆังของวันนี้ การแจ้งเตือนตัวอย่างทั้ง 2 รายการ ("3 new Cant Loose players this week", "Weekly Bonus fired · 48 recipients · ฿82,400 paid · 67% claim rate so far"), prefix ของ toast ข้อผิดพลาด ("Couldn't send: …"), และป้ายเวลาแบบ dynamic (5 น. ที่แล้ว / 2 ชม. ที่แล้ว / 3 วันที่แล้ว) เปลี่ยนเป็นภาษาไทยทั้งหมดเมื่อกดสลับภาษาบนแถบบน · ข้อความอยู่ใน LANG_TH ให้ MutationObserver เดิมหยิบไปแปลเอง — ไม่มี render path แยก
  • Broadcast รองรับสองภาษาทั้ง stack — ตาราง feedback_requests เพิ่มคอลัมน์ title_th + body_th แบบ nullable (migration idempotent ทำงานตอน restart service) · endpoint สาธารณะ GET /api/feedback-requests/public คืนทั้งสองชุด; ระฆัง AIVA หยิบคู่ TH เมื่อ CURRENT_LANG==='th' และ fallback ไปคู่ EN ถ้า broadcast เป็น EN อย่างเดียว ดังนั้น broadcast 5 รายการที่มีอยู่ยังทำงานต่อโดยไม่ต้องแก้ · CLI ได้ flag --title-th="..." / --body-th="..." · ข้อความที่ผู้ดูแลพิมพ์ติด data-no-i18n เพื่อไม่ให้ dictionary LANG_TH ไปแปล; การแจ้งเตือนภายในถอด attribute ออกเพื่อให้ใช้ dictionary ตามเดิม · สลับภาษาขณะระฆังเปิดอยู่ คู่ข้อความสลับทันที

No slot-specific changes today — the bell sits in the topbar and applies regardless of which slot you're on.

ไม่มีการเปลี่ยนแปลงเฉพาะ slot วันนี้ — ระฆังอยู่บนแถบบนและทำงานไม่ว่าจะอยู่ slot ใด

No changes in slot 8.2 today.

ไม่มีการเปลี่ยนแปลงใน slot 8.2 วันนี้

No changes in slot 8.3 today.

ไม่มีการเปลี่ยนแปลงใน slot 8.3 วันนี้

30 commits · 3e9cbf6 → 48b391d · custom RFM segments + multi-RFM membershipsRFM กำหนดเอง + ผู้เล่นอยู่หลายกลุ่ม
Cross-cutting ข้ามทุก slot

Changes that touch the whole site

การเปลี่ยนแปลงที่กระทบทั้งไซต์

  • Auto-reload on stale deploy — GitLab Pages forces Cache-Control: max-age=600 on every response and ignores <meta http-equiv> overrides, so operators were seeing cached HTML for up to 10 minutes after a deploy. The CI build now sed-injects $CI_COMMIT_SHA into a <meta name="build-version"> tag and writes a sibling public/version.txt. A small script at the top of <head> fetches that file with cache: 'no-store' on every page load; if the SHA differs, it location.replace()s with ?v=<sha> as a cache-buster so the browser fetches fresh HTML. sessionStorage guards against reload loops.
  • Roster row click resilience — wrapped the brittle inline onclick="loadPlayer(uid);switchView('profile')" in openPlayerFromRoster(uid) which switches the view first and wraps the load in try/catch. Previously if any earlier step in the loadPlayer pipeline threw, navigation silently failed and the row click looked dead.
  • Fix init crash on procedural players — the procedural-player IIFE was emitting p.games.mostPlayed and p.games.top: [], but renderPlayer reads p.games.mostType and p.games.top5.map(...). The undefined top5 threw and killed the entire init render chain, so the dashboard appeared blank until any tab click independently triggered a render via switchView. Only manifested when localStorage saved a procedural UID as the current player (default P-20481 is hand-crafted and unaffected). Two-sided fix: procedural IIFE now emits the canonical key names, and renderPlayer reads p.games defensively (mostType||mostPlayed, top5||top, fallbacks for missing fields).
  • Pre-load the segments view — reorder the init render chain so renderSegments + renderRoster fire BEFORE the heavier loadPlayer / renderPayouts work. Segments is the default landing tab (the only .view-content without a [hidden] attribute on load), so populating its grid + custom card first means operators see real content the moment the page paints instead of staring at empty cards while the hidden profile view fills.
  • โหลดอัตโนมัติเมื่อ deploy ใหม่ — GitLab Pages บังคับ Cache-Control: max-age=600 ทุก response และไม่สนใจ <meta http-equiv>, ทำให้ operator เห็น HTML ที่แคชไว้นานสุด 10 นาทีหลัง deploy · CI build ตอนนี้ใส่ $CI_COMMIT_SHA ลงใน meta tag build-version และเขียนไฟล์ public/version.txt คู่กัน · script เล็ก ๆ ใน <head> ดึงไฟล์นั้นแบบ cache: 'no-store' ทุกครั้งที่โหลดหน้า; ถ้า SHA ต่างกันจะ location.replace() ด้วย ?v=<sha> เป็น cache-buster เพื่อให้เบราว์เซอร์ดึง HTML ใหม่ · ใช้ sessionStorage ป้องกัน loop การ reload
  • คลิกแถว Roster ทนทาน — ห่อ inline onclick="loadPlayer(uid);switchView('profile')" เดิมไว้ใน openPlayerFromRoster(uid) ซึ่งสลับ view ก่อนแล้วห่อ load ใน try/catch · ก่อนหน้านี้ถ้า step ใน pipeline ของ loadPlayer โยน error การ navigate จะล้มเงียบ ๆ และคลิกแถวเหมือนไม่ทำงาน
  • แก้ init crash ของผู้เล่น procedural — IIFE ที่สร้างผู้เล่น procedural ส่งคีย์ p.games.mostPlayed และ p.games.top: [], แต่ renderPlayer อ่าน p.games.mostType และ p.games.top5.map(...) · top5 ที่เป็น undefined ทำให้ throw และหยุด chain การ render ทั้งหมดใน init · dashboard ดูเปล่า ๆ จนกว่าจะคลิก tab อะไรสักอย่างที่ trigger render ผ่าน switchView โดยอิสระ · เกิดเฉพาะเมื่อ localStorage บันทึก UID ของผู้เล่น procedural เป็น current (default P-20481 เป็น hand-crafted ไม่กระทบ) · แก้สองทาง: IIFE ส่งคีย์ตามมาตรฐาน และ renderPlayer อ่าน p.games แบบกันพลาด (mostType||mostPlayed, top5||top, fallback สำหรับฟิลด์ที่หาย)
  • โหลด segments ก่อน — เรียงใหม่ลำดับ render ใน init ให้ renderSegments + renderRoster ทำงานก่อน loadPlayer / renderPayouts ที่หนักกว่า · Segments เป็น tab landing เริ่มต้น (เป็น .view-content เดียวที่ไม่มี [hidden] ตอนโหลด), ดังนั้นการเติม grid + custom card ก่อนหมายความว่า operator เห็นเนื้อหาทันทีที่หน้า paint แทนที่จะมองการ์ดเปล่าระหว่างที่ view profile (ซ่อนอยู่) กำลังเติม
01

Custom RFM segments — operator-built groups beyond the 11 AIVA archetypes

RFM กำหนดเอง — กลุ่มที่ operator สร้างเอง นอกเหนือจาก 11 archetype ของ AIVA

A new dashed + Custom segment tile sits at the end of the Segmentation grid. Clicking opens a centered modal where the operator picks only two things: a name and ten threshold inputs that mirror the inputs to AIVA's player-ranking formula (aismsDesirability). The card's icon, colour, and recommended-action line are AIVA-generated at save time — operators don't choose them.

มี tile + Custom segment เส้นประที่ท้าย grid ของ Segmentation · กดเปิด modal จัดกลางที่ operator เลือก เพียงสองอย่าง: ชื่อและค่าขั้นต่ำ 10 ช่อง ที่สะท้อนอินพุตของสูตรจัดอันดับผู้เล่นของ AIVA (aismsDesirability) · ไอคอน, สี, และบรรทัด action บนการ์ดถูกสร้างอัตโนมัติโดย AIVA ตอนบันทึก — operator ไม่ต้องเลือก

The ten signals

สิบสัญญาณ

  • Min AIVA score (0–99) · Active within last N days · Min recent net loss (THB) · Min lifetime turnover (THB) · Min avg deposit size (THB) · Min frequency rating (%) · Min monetary rating (%) · Min loyalty rating (%) · Min engagement rating (%) · Max risk rating (%).
  • Nine floors and one ceiling (risk). Defaults match everyone (70 of 70 players); the live counter at the top updates as the operator tightens the criteria.
  • คะแนน AIVA ขั้นต่ำ (0–99) · ใช้งานภายใน N วันล่าสุด · ยอดเสียสุทธิล่าสุดขั้นต่ำ (บาท) · ยอดเล่นรวมต่ำสุด (บาท) · ขนาดฝากเฉลี่ยขั้นต่ำ (บาท) · คะแนนความถี่ขั้นต่ำ (%) · คะแนนการเงินขั้นต่ำ (%) · คะแนนความภักดีขั้นต่ำ (%) · คะแนนความผูกพันขั้นต่ำ (%) · คะแนนความเสี่ยงสูงสุด (%)
  • เป็นเกณฑ์ขั้นต่ำเก้าตัวและขั้นสูงสุดหนึ่งตัว (ความเสี่ยง) · ค่าเริ่มต้นจะตรงทุกคน (70 จาก 70 คน); ตัวนับล่าสุดบนหัวจะอัปเดตทันทีที่ operator เข้มงวดขึ้น

AIVA-generated chrome

หน้าตาที่ AIVA สร้างให้

  • autoGenIcon(name) — deterministic hash of the name picks from a curated emoji pool (🏆⭐💎🎯🚀💡🌟…).
  • autoGenColor(name) — same hash picks from the 8-colour palette RFM badges already use (pri / green / cyan / amber / red / purple / blue / gy).
  • autoGenAction(criteria) — compact summary of whichever criteria depart from defaults, e.g. score ≥ 70 · loss ≥ ฿20k · risk ≤ 50%. Capped at 80 chars with an ellipsis; falls back to "Custom RFM segment" when nothing is tightened.
  • All three are regenerated on every save so the card stays in sync with the current name + criteria.
  • autoGenIcon(name) — hash ของชื่อแบบ deterministic เลือกจาก pool emoji ที่คัดไว้ (🏆⭐💎🎯🚀💡🌟…)
  • autoGenColor(name) — hash เดียวกันเลือกจาก palette 8 สีที่ RFM badge ใช้อยู่แล้ว (pri / green / cyan / amber / red / purple / blue / gy)
  • autoGenAction(criteria) — สรุปย่อเกณฑ์ที่ไม่ใช่ค่าเริ่มต้น เช่น score ≥ 70 · loss ≥ ฿20k · risk ≤ 50% · ตัดที่ 80 ตัวอักษรด้วย ellipsis; ถ้าไม่ได้เข้มงวดเลยจะใช้ "Custom RFM segment"
  • ทั้งสามถูกสร้างใหม่ทุกครั้งที่บันทึก เพื่อให้การ์ดตรงกับชื่อ + เกณฑ์ปัจจุบัน

Persistence

การจัดเก็บ

  • localStorage key pps75_custom_segments. Shape: { id, name, createdAt, criteria, icon, color, action, manualIncludes, manualExcludes }.
  • Clicking a custom card filters the roster identically to an RFM card via state.rosterFilter = 'custom:<id>'; viewCustomSegment(id) sets the filter and switches view.
  • คีย์ใน localStorage: pps75_custom_segments · รูปร่าง: { id, name, createdAt, criteria, icon, color, action, manualIncludes, manualExcludes }
  • คลิก card กำหนดเองจะกรอง roster เหมือนคลิก RFM card ผ่าน state.rosterFilter = 'custom:<id>'; viewCustomSegment(id) ตั้งค่า filter และสลับ view
02

Multi-RFM memberships — players can sit in more than one archetype

สมาชิก RFM หลายกลุ่ม — ผู้เล่นอยู่ได้มากกว่าหนึ่ง archetype

AIVA's default is still one archetype per player. The operator can now extend membership: a player can belong to any number of RFM archetypes simultaneously (≥1 required). The primary stays in p.period30dBase.archetype — so the roster badge, profile head, and insight generation all keep their single-archetype display paths. Additional memberships go in p.extraArchetypes:[].

ค่าเริ่มต้นของ AIVA ยังเป็นหนึ่ง archetype ต่อผู้เล่น · ตอนนี้ operator ขยายสมาชิกได้: ผู้เล่นอยู่ใน RFM archetype ได้พร้อมกันหลายกลุ่ม (ต้องมีอย่างน้อย 1) · primary ยังอยู่ใน p.period30dBase.archetype — badge ใน roster, head ของ profile, การสร้าง insight ทุกอย่างยังใช้เส้นทาง archetype เดียวเหมือนเดิม · สมาชิกเพิ่มเติมอยู่ใน p.extraArchetypes:[]

  • playerArchetypes(p) returns [primary, ...extras]; playerInArchetype(p, arch) checks both. renderSegments, the roster filter, and aismsFilteredPlayers all walk the full membership set so a multi-tagged player counts in every segment they belong to (total segment population can exceed roster size).
  • Unchecking the primary while extras exist promotes the first extra to primary. Unchecking the last archetype is refused with a toast.
  • localStorage pps75_archetype_overrides. Legacy single-archetype string values are auto-promoted to single-element arrays on load. p.aivaArchetype is lazy-stored on the first override so the modal can tag AIVA's pick with a blue AIVA badge and the "revert to AIVA's pick" link collapses back to that single archetype.
  • playerArchetypes(p) คืน [primary, ...extras]; playerInArchetype(p, arch) ตรวจทั้งสอง · renderSegments, filter ของ roster, และ aismsFilteredPlayers เดินผ่านชุดสมาชิกทั้งหมด ผู้เล่นที่ถูกแท็กหลายกลุ่มจึงถูกนับในทุก segment ที่อยู่ (จำนวนรวมของทุก segment อาจมากกว่าจำนวนผู้เล่น)
  • ยกเลิกเช็ค primary ขณะมี extras จะเลื่อน extra แรกขึ้นเป็น primary · ยกเลิกเช็ค archetype สุดท้ายจะถูกปฏิเสธพร้อม toast
  • localStorage pps75_archetype_overrides · ค่า string archetype เดียวแบบเก่าจะถูกแปลงเป็น array หนึ่งสมาชิกตอนโหลด · p.aivaArchetype ถูกบันทึก lazy ตอนแก้ครั้งแรก เพื่อให้ modal ใส่ badge สีฟ้า AIVA ตรง archetype ที่ AIVA เลือก และลิงก์ "revert to AIVA's pick" คืนค่าเป็น archetype เดียวนั้นได้
03

Per-row + per-profile 🏷️ assignment modal

Modal มอบหมายด้วย 🏷️ ในแต่ละแถวและ profile

Every row in the Player Roster has a small 🏷️ button next to the username (with a count badge — e.g. 🏷️ 3 — when the player already belongs to N groups). The same icon appears in the player-profile action bar. Clicking either opens one centered modal with two checkbox sections:

ทุกแถวใน Player Roster มีปุ่ม 🏷️ เล็ก ๆ ติดอยู่ข้างชื่อผู้ใช้ (มี badge นับ — เช่น 🏷️ 3 — เมื่อผู้เล่นอยู่แล้ว N กลุ่ม) · ไอคอนเดียวกันมีบน action bar ของ profile · คลิกที่ไหนก็ได้จะเปิด modal จัดกลางเดียวที่มี checkbox สองส่วน:

  • RFM archetypes — all 11 archetypes as checkboxes (multi-membership, ≥1 required). The originally-assigned one carries a small blue AIVA badge; when you've checked extras, the current primary shows a primary tag.
  • Custom segments — one checkbox per custom RFM you've created, with a reason badge per row (criteria in blue when the player matches the thresholds; manual in amber when you added them by hand; excluded when they match but you removed them).
  • Round-trip from "+ New custom segment" — clicking that button inside the assign modal remembers the player's uid so saving (or cancelling) the segment editor pops you back into the assign modal with the new segment in the checkbox list.
  • RFM archetypes — ทั้ง 11 archetype เป็น checkbox (อยู่ได้หลายกลุ่ม, ต้องมีอย่างน้อย 1) · archetype ที่ AIVA เลือกแต่แรกมี badge สีฟ้า AIVA; เมื่อเช็ค extras แล้ว primary ปัจจุบันจะมี tag primary
  • Custom segments — checkbox ต่อ RFM กำหนดเองที่สร้างไว้ พร้อม reason badge แต่ละแถว (criteria สีฟ้า เมื่อผู้เล่นตรงเกณฑ์; manual สีเหลือง เมื่อเพิ่มเข้ามือ; excluded เมื่อตรงเกณฑ์แต่ถูกถอดออก)
  • วนกลับจาก "+ New custom segment" — กดปุ่มนั้นใน modal มอบหมายจะจดจำ uid ของผู้เล่น เมื่อบันทึก (หรือยกเลิก) editor segment จะกลับมา modal มอบหมายพร้อมเห็น segment ใหม่อยู่ใน list checkbox
04

Player Identity card lists every RFM segment + live-refreshes

การ์ด Player Identity แสดงทุก segment RFM + อัปเดตสด

A new RFM segments row at the top of the Player Identity card renders every archetype the player belongs to as a colour-coded badge — primary first, then extras. Custom RFM segments the player belongs to (whether they matched via criteria or were added manually) flow inline on the same row, each in its own palette colour with its auto-generated icon. The row pulls from playerArchetypes(p) + playerSegmentMemberships(p.uid) so it always reflects the current membership across both axes.

มีแถวใหม่ RFM segments ที่ด้านบนของการ์ด Player Identity แสดงทุก archetype ที่ผู้เล่นอยู่เป็น badge ตามสี — primary ก่อน, ต่อด้วย extras · ตามด้วย segment RFM กำหนดเองที่ผู้เล่นอยู่ (ไม่ว่าจะตรงเกณฑ์หรือถูกเพิ่มเข้ามือ) ในแถวเดียวกัน แต่ละตัวใช้สีจาก palette และไอคอนที่ AIVA สร้างให้ · แถวดึงข้อมูลจาก playerArchetypes(p) + playerSegmentMemberships(p.uid) จึงสะท้อนสมาชิกปัจจุบันทั้งสองแกนเสมอ

Live-refresh. A new refreshIfCurrent(uid) helper is called from togglePlayerArchetype, clearPlayerArchetype, and togglePlayerInSegment — when the uid matches state.player.uid, the profile re-renders, so the Identity row updates the moment you toggle a checkbox in the 🏷️ modal. saveCustomSegment, deleteCustomSegmentFromModal, and the reset flow all call renderPlayer() when a player is loaded so segment creation, edits, and deletions reflect immediately too.

อัปเดตสด · helper ใหม่ refreshIfCurrent(uid) ถูกเรียกจาก togglePlayerArchetype, clearPlayerArchetype, และ togglePlayerInSegment — เมื่อ uid ตรงกับ state.player.uid, profile จะ render ใหม่ทันที แถว Identity จึงอัปเดตทันทีที่กดเช็คใน modal 🏷️ · saveCustomSegment, deleteCustomSegmentFromModal, และ flow ของ reset ก็เรียก renderPlayer() เมื่อ profile เปิดอยู่ การสร้าง, แก้ไข, และลบ segment จึงสะท้อนผลทันทีเช่นกัน

05

↻ Reset to AIVA default — one click to undo everything

↻ คืนค่า AIVA — คลิกเดียวยกเลิกทุกอย่าง

A small button sits next to the Segment Overview card title. Clicking opens a centered confirm modal that previews the impact ("3 archetype changes + 2 extra archetypes will be cleared · 5 custom RFM segments will be deleted") and asks Cancel / Yes-reset. Confirming does two things:

ปุ่ม เล็ก ๆ ติดอยู่ข้างหัวการ์ด Segment Overview · กดเปิด modal ยืนยันจัดกลางที่แสดงผลกระทบ ("3 archetype changes + 2 extra archetypes will be cleared · 5 custom RFM segments will be deleted") และถาม Cancel / Yes-reset · ยืนยันแล้วจะทำสองอย่าง:

  • Every per-player archetype override is cleared — primary collapses back to p.aivaArchetype and p.extraArchetypes is dropped.
  • Every custom RFM segment is deleted — names, criteria, manual member assignments all gone (CUSTOM_SEGMENTS = [] + localStorage.removeItem(KEY_CUSTOM_SEGMENTS)). The roster filter clears if it was pointing at a now-deleted segment. The confirm modal warns the action can't be undone.
  • ทุกการ override archetype ของผู้เล่นถูกล้าง — primary คืนค่าเป็น p.aivaArchetype และ p.extraArchetypes ถูกลบ
  • ทุก segment RFM กำหนดเองถูกลบ — ชื่อ, เกณฑ์, สมาชิกที่กำหนดเอง หายหมด (CUSTOM_SEGMENTS = [] + localStorage.removeItem(KEY_CUSTOM_SEGMENTS)) · filter ของ roster จะถูกล้างถ้าชี้ไปยัง segment ที่เพิ่งถูกลบ · modal ยืนยันเตือนว่าทำแล้วยกเลิกไม่ได้
06

Layout split — custom RFM gets its own card + the detail table extends

แยก layout — RFM กำหนดเองมี card ของตัวเอง + ตารางรายละเอียดขยาย

Custom segments now render in their own card — Custom RFM Segments — directly below the canonical Segment Overview grid. The 11 AIVA-assigned cards stay in the original card untouched; the new card holds operator-built segments plus the + Custom segment entry tile. Header shows "N custom segments" or "No custom segments yet".

Segment กำหนดเองตอนนี้ render ในการ์ดของตัวเอง — Custom RFM Segments — อยู่ใต้ grid Segment Overview ของ AIVA โดยตรง · 11 archetype ที่ AIVA กำหนดยังอยู่ในการ์ดเดิมไม่เปลี่ยน · การ์ดใหม่เก็บ segment ที่ operator สร้าง พร้อม tile + Custom segment · หัวการ์ดแสดง "N custom segments" หรือ "No custom segments yet"

Per-Segment Detail table picks up the same separation — RFM rows first, then a divider row ("🏷️ Custom RFM Segments · N segment(s) · M total memberships"), then one row per custom segment with its own icon, palette colour, criteria-derived action line, and revenue stats, sorted by revenue inside the custom block.

ตาราง Per-Segment Detail ใช้การแยกเดียวกัน — แถว RFM ก่อน ตามด้วยแถวคั่น ("🏷️ Custom RFM Segments · N segment(s) · M total memberships") แล้วต่อด้วยแถวต่อ segment กำหนดเอง ใช้ไอคอน, สี palette, บรรทัด action ที่สร้างจากเกณฑ์, และสถิติรายได้ของตัวเอง เรียงตามรายได้ในกลุ่ม custom

Icon polish

ปรับไอคอน

Throughout the day the segment-assign affordance moved from 🛠 (wrench) to 🏷️ (tag) — fits the "label / classify a player" semantic better. Swapped in the roster row count badge, player-profile head action, assign modal title, custom-segment card icon (now AIVA-generated from the emoji pool, but 🏷️ remains the fallback), filter-chip label, and across the assign-modal segment rows.

ระหว่างวันเปลี่ยนไอคอนของการมอบหมาย segment จาก 🛠 (ประแจ) เป็น 🏷️ (แท็ก) — เข้ากับความหมาย "ติดป้าย / จัดกลุ่มผู้เล่น" มากกว่า · เปลี่ยนใน badge นับของแถว roster, action ของ profile head, หัว modal มอบหมาย, ไอคอนของการ์ด custom segment (ตอนนี้ AIVA สร้างจาก pool emoji แต่ 🏷️ ยังเป็น fallback), label ของ filter chip, และทุกแถว segment ใน modal มอบหมาย

07

🏷️ count on roster rows = total RFM segments

จำนวนข้าง 🏷️ บนแถว Roster = RFM segment ทั้งหมด

The 🏷️ badge next to each player's name used to count only custom segments — so every default player showed 🏷️ with no number. It now reflects the same union the Identity card row renders: playerArchetypes(p).length (primary + any extra RFM archetypes) + playerSegmentMemberships(p.uid).length (custom RFM segments via criteria or manual). Always ≥1 since every player carries an AIVA-assigned archetype. The highlighted .has style only kicks in when the count exceeds 1 — i.e. the operator has deliberately grouped the player beyond the default single archetype. Title attribute now reads "N RFM segments · click to manage".

Badge 🏷️ ข้างชื่อผู้เล่นเคยนับเฉพาะ custom segment — ผู้เล่นค่าเริ่มต้นจึงเห็น 🏷️ โดยไม่มีตัวเลข · ตอนนี้สะท้อน การรวมเดียวกับแถวของการ์ด Identity: playerArchetypes(p).length (primary + RFM archetype เพิ่มเติม) + playerSegmentMemberships(p.uid).length (custom RFM segment จากเกณฑ์หรือเพิ่มเข้ามือ) · เป็น ≥1 เสมอ เพราะผู้เล่นทุกคนมี archetype ที่ AIVA กำหนด · สไตล์เน้น .has ทำงานเฉพาะเมื่อจำนวนเกิน 1 — กล่าวคือ operator ได้จัดกลุ่มผู้เล่นเพิ่มจากค่าเริ่มต้น · Title อ่านว่า "N RFM segments · click to manage"

08

Player Roster — sortable by P&L and Lifetime turnover

Player Roster — จัดเรียงตาม P&L และเทิร์นโอเวอร์ตลอดชีพ

The 30d P&L and Lifetime turnover column headers are now clickable sort toggles. Same column flips direction; switching columns picks a sensible default — P&L asc (biggest loser first, matching the prior fixed behaviour) and turnover desc (biggest spender first). Active column header goes green with a / indicator. Sort state lives in state.rosterSort ({col, dir}) and defaults to P&L asc on first render.

หัวคอลัมน์ 30d P&L และ เทิร์นโอเวอร์ตลอดชีพ ตอนนี้กดเพื่อสลับการจัดเรียงได้ · กดที่เดิมจะกลับทิศทาง; เปลี่ยนคอลัมน์จะเลือกทิศทางเริ่มต้นที่เหมาะ — P&L asc (ผู้เสียมากที่สุดอยู่บน เหมือนพฤติกรรมเดิม) และเทิร์นโอเวอร์ desc (ผู้ใช้จ่ายสูงสุดอยู่บน) · หัวคอลัมน์ที่ active เป็นสีเขียวพร้อมตัวบ่งชี้ / · สถานะ sort อยู่ใน state.rosterSort ({col, dir}) ค่าเริ่มต้นคือ P&L asc

Implementation note: header text is split between a .label span (translatable, hits the LANG_TH exact-match) and a .sort-arrow span (data-no-i18n), so the TH translation of "Lifetime turnover" still resolves cleanly with the arrow appended.

หมายเหตุการ implement: ข้อความ header แยกเป็น span .label (แปลได้, ตรงกับ exact-match ใน LANG_TH) และ span .sort-arrow (data-no-i18n) ดังนั้นการแปล "Lifetime turnover" เป็นภาษาไทยยังทำงานปกติเมื่อมีลูกศรต่อท้าย

09

"across N segments" subline includes custom RFM count

บรรทัด "across N segments" รวม custom RFM ด้วย

The Total Players cell on the seg-stats qstrip and the seg-summary on the Segment Overview card header both used a hardcoded "11 segments." Both are now SEGMENT_LIST.length + CUSTOM_SEGMENTS.length, so saving a custom RFM segment bumps the visible total — 1 custom → "across 12 segments", 3 customs → "across 14 segments". Reset deletes customs and the number falls back to 11. The TH dictionary still hits exact-match in the common no-custom case ("across 11 segments" → "ใน 11 กลุ่ม"); once a custom exists, the number passes through untranslated.

เซลล์ Total Players บน qstrip ของ seg-stats และ seg-summary บนหัวการ์ด Segment Overview เคย hardcode เป็น "11 segments" · ตอนนี้ทั้งคู่ใช้ SEGMENT_LIST.length + CUSTOM_SEGMENTS.length · บันทึก custom RFM segment 1 อัน → "across 12 segments", 3 อัน → "across 14 segments" · Reset ลบ custom และตัวเลขกลับเป็น 11 · LANG_TH ยังตรงในกรณีไม่มี custom ("across 11 segments" → "ใน 11 กลุ่ม"); เมื่อมี custom ตัวเลขจะไม่ถูกแปล

No changes in slot 8.2 today — work focused on 8.1.

ไม่มีการเปลี่ยนแปลงใน slot 8.2 วันนี้ — โฟกัสที่ 8.1

No changes in slot 8.3 today — work focused on 8.1.

ไม่มีการเปลี่ยนแปลงใน slot 8.3 วันนี้ — โฟกัสที่ 8.1

15 commits · f9a3c71 → 8edcc58 · live at askmeaiva.comขึ้น askmeaiva.com แล้ว
Cross-cutting ข้ามทุก slot

Changes that touch every slot

การเปลี่ยนแปลงที่กระทบทุก slot

  • Cashback → Bonus rename — every customer-facing string that previously said "Cashback" now says "Bonus": campaign display names (Weekly / Monthly / Pre-Monthly / Post-Monthly Bonus), promo titles, AI-insight bodies, segment action lines, AISMS promo catalog, the 8.2 page subtitle, comm-log entries, and the matching LANG_TH entries. Internal IDs (weekly-cashback, monthly-cashback) kept as persistence keys; the boot IIFE backfills stale localStorage names.
  • Thai localization audit — translated the new AI-recommend popout body, every segment description in the Segment Guide popout, all SEGMENT_META action lines, the chip-label icon-prefixed forms (👑 Champions … 💤 Hibernating; 👑 Whale … 🥉 Bronze), the "Browsing" heatmap state, and a regex for the AI-recommend toast.
  • Default language → EN — every fresh page load now opens in English. The topbar pill still flips the session to ภาษาไทย, but the choice no longer persists across reloads (localStorage pps75_lang cleared on boot).
  • เปลี่ยนชื่อ Cashback → Bonus — ทุกข้อความที่ผู้ใช้เห็นซึ่งเคยใช้คำว่า "Cashback" เปลี่ยนเป็น "Bonus" แล้ว · ทั้งชื่อแคมเปญที่แสดง (Weekly / Monthly / Pre-Monthly / Post-Monthly Bonus), หัวข้อโปรโม, เนื้อหา AI insight, บรรทัด action ของ segment, แค็ตตาล็อก AISMS promo, subtitle หน้า 8.2, รายการ comm-log, และ LANG_TH ที่เกี่ยวข้อง · ID ภายใน (weekly-cashback, monthly-cashback) ยังคงไว้เป็น persistence key; boot IIFE จะแก้ชื่อใน localStorage ที่ค้างให้อัตโนมัติ
  • ตรวจสอบการแปลภาษาไทย — แปลเนื้อหา AI-recommend popout, ทุก segment description ในคู่มือ Segment, ทุกบรรทัด action ของ SEGMENT_META, รูปแบบ chip ที่มีไอคอนนำหน้า (👑 Champions … 💤 Hibernating; 👑 Whale … 🥉 Bronze), สถานะ "Browsing" ใน heatmap, และ regex สำหรับ toast ของ AI-recommend
  • ค่าเริ่มต้นภาษา → EN — ทุกครั้งที่โหลดหน้าใหม่จะเริ่มเป็นภาษาอังกฤษ · ปุ่ม pill ในแถบบนยังสามารถเปลี่ยนเป็น ภาษาไทย ได้ในรอบการใช้งานนั้น แต่จะไม่บันทึกข้ามการรีโหลด (ลบ localStorage pps75_lang ตอนบูต)
01

New RFM segment — Unconverted Leads

RFM Segment ใหม่ — Unconverted Leads

The 11th segment lives between New Customers and Promising. It captures registered accounts that haven't made a first deposit yet — the most conversion-sensitive cohort in any operator's roster. Action is direct: call + SMS within 24 hours to drive the first deposit.

Segment ตัวที่ 11 อยู่ระหว่าง New Customers และ Promising · เก็บผู้เล่นที่ลงทะเบียนแล้วแต่ยังไม่ฝากครั้งแรก — กลุ่มที่ไวต่อการ convert มากที่สุดในรายชื่อของ operator · action ตรงไปตรงมา: โทร + SMS ภายใน 24 ชั่วโมง เพื่อกระตุ้นการฝากครั้งแรก

📞
Unconverted LeadsRFM [5,1,1]
Unconverted LeadsRFM [5,1,1]
Registered but no first deposit yet. AI insight generator weight 90 (between At Risk 92 and About To Sleep 88). Action: "Follow-up — call + SMS to drive 1st deposit".
ลงทะเบียนแล้วแต่ยังไม่ฝากครั้งแรก · AI insight generator น้ำหนัก 90 (ระหว่าง At Risk 92 และ About To Sleep 88) · Action: "Follow-up — call + SMS to drive 1st deposit"

10 hand-crafted exemplars

ผู้เล่นตัวอย่างทำมือ 10 คน

Player UIDs P-77001 through P-77010 populate the segment with realistic variety — different lead sources (Facebook Ads, TikTok Ads, Google Ads, LINE OA, friend referral, affiliate, direct), days since registration (1–8), and follow-up states (hot leads online now, calls unanswered, follow-up overdue, email engaged). Roster total grows 60 → 70.

UID ผู้เล่น P-77001 ถึง P-77010 เติม segment ด้วยความหลากหลายจริง — แหล่งลีดต่างกัน (Facebook Ads, TikTok Ads, Google Ads, LINE OA, friend referral, affiliate, direct), จำนวนวันตั้งแต่ลงทะเบียน (1–8 วัน), และสถานะการติดตาม (hot lead ออนไลน์อยู่, โทรไม่รับ, ติดตามค้าง, อ่านอีเมลแล้ว) · รายชื่อรวมเพิ่มจาก 60 → 70 คน

  • SEGMENT_LIST, SEGMENT_META, RFM mapping, INSIGHT_GENERATORS, the procedural-gen TEMPLATES table, and LANG_TH all updated.
  • api/_lib/defaults.js MOCK_PLAYERS extended with the 10 new entries so the backend mirrors the frontend.
  • CLAUDE.md, README.md, USER_MANUAL.md all synced — segment table, hand-crafted player list, distribution note.
  • อัปเดต SEGMENT_LIST, SEGMENT_META, RFM mapping, INSIGHT_GENERATORS, ตาราง TEMPLATES สำหรับ procedural gen และ LANG_TH ครบทุกที่
  • api/_lib/defaults.js MOCK_PLAYERS เพิ่ม 10 entry ใหม่เพื่อให้ backend ตรงกับ frontend
  • CLAUDE.md, README.md, USER_MANUAL.md อัปเดตให้ตรง — ตาราง segment, รายชื่อผู้เล่นทำมือ, หมายเหตุการกระจาย
02

Segment Guide popout

ป๊อปอัปคู่มือ Segment

A small ⓘ button now sits next to the "Players" page title on slot 8.1. Click it to open a single-screen Segment Guide popout — every segment listed with its icon, plain-language description, recommended action, and live player count.

ตอนนี้มี ปุ่ม ⓘ เล็ก ๆ ติดอยู่ข้างหัวเรื่อง "Players" บน slot 8.1 · กดเปิดป๊อปอัปคู่มือ Segment ที่แสดงครบในหน้าเดียว — ทุก segment พร้อมไอคอน, คำอธิบายภาษาคนปกติ, action ที่แนะนำ, และจำนวนผู้เล่นล่าสุด

  • Two columns on desktop (≥720px), one column on phones — no internal scrolling needed.
  • Hidden on slots 8.2 / 8.3 (segments aren't relevant there); shown only when the title reads "Players".
  • Close via × button, Esc key, or click outside the popout.
  • The body of every segment row pulls from SEGMENT_DESCRIPTIONS; the new Unconverted Leads description is included and Thai-translated.
  • แสดงสองคอลัมน์บนเดสก์ท็อป (≥720px), หนึ่งคอลัมน์บนมือถือ — ไม่ต้องเลื่อนภายในป๊อปอัป
  • ซ่อนไว้บน slot 8.2 / 8.3 (segment ไม่เกี่ยว); แสดงเฉพาะเมื่อหัวเรื่องเป็น "Players"
  • ปิดด้วยปุ่ม × · ปุ่ม Esc · หรือคลิกนอกป๊อปอัป
  • แต่ละแถวดึงข้อมูลจาก SEGMENT_DESCRIPTIONS; รวมคำอธิบายของ Unconverted Leads และมีภาษาไทยแล้ว
01

Campaign display names → "Bonus"

ชื่อแคมเปญที่แสดง → "Bonus"

The four scheduled campaigns now read as Bonus across every surface they show up on:

ทั้ง 4 แคมเปญที่ตั้งเวลาไว้แสดงเป็น "Bonus" ในทุกที่ที่ปรากฏ:

  • Weekly Bonus — was "Weekly Cashback"
  • Pre-Monthly Bonus · Month-End Push — was "Pre-Monthly Cashback · …"
  • Monthly Bonus — was "Monthly Cashback" (the independent formula anchor)
  • Post-Monthly Bonus · Catch-Up — was "Post-Monthly Cashback · …"
  • Weekly Bonus — เดิม "Weekly Cashback"
  • Pre-Monthly Bonus · Month-End Push — เดิม "Pre-Monthly Cashback · …"
  • Monthly Bonus — เดิม "Monthly Cashback" (สูตรหลักของแคมเปญ)
  • Post-Monthly Bonus · Catch-Up — เดิม "Post-Monthly Cashback · …"

The 8.2 page subtitle also moves from "cashbacks, claims, and reconciliation" to "bonuses, claims, and reconciliation". The promo template title and body, the Bonus-aware AI insight strings, and the AISMS promo catalog all swap to the new wording in lock-step.

subtitle ของหน้า 8.2 ก็เปลี่ยนจาก "cashbacks, claims, and reconciliation" เป็น "bonuses, claims, and reconciliation" · ทั้งหัวข้อและเนื้อหา promo template, ข้อความ AI insight ที่เกี่ยวกับ Bonus, และแค็ตตาล็อก AISMS promo เปลี่ยนคำพร้อมกันทั้งหมด

Persistence keys untouched

Persistence key ไม่แตะ

Internal campaign IDs stay as weekly-cashback, monthly-cashback, etc. — they back localStorage pps75_campaigns and KV cron history, so renaming them would orphan saved state. Only the visible name field changes. The cashback formula (loss × 0.10 + wager × 0.0005) is also unchanged — the rename is display-layer only.

ID ภายในของแคมเปญยังคงเป็น weekly-cashback, monthly-cashback ฯลฯ — เป็น key ใน localStorage pps75_campaigns และ KV cron history · เปลี่ยนชื่อจะทำให้ข้อมูลที่บันทึกไว้ใช้ไม่ได้ · เปลี่ยนเฉพาะ field name ที่แสดง · สูตรการคิด cashback (loss × 0.10 + wager × 0.0005) ก็ไม่เปลี่ยน — เปลี่ยนเฉพาะการแสดงผลเท่านั้น

02

One-shot localStorage migration

Migration localStorage ครั้งเดียว

Users who loaded the dashboard before the rename had the old campaign names cached in pps75_campaigns. The boot IIFE's backfill() step now refreshes c.name from DEFAULT_CAMPAIGNS when the stored name still contains "Cashback" and the new default doesn't.

ผู้ใช้ที่โหลดแดชบอร์ดก่อนที่จะเปลี่ยนชื่อ จะมีชื่อแคมเปญเก่าเก็บไว้ใน pps75_campaigns · ขั้นตอน backfill() ใน boot IIFE จะอัปเดต c.name จาก DEFAULT_CAMPAIGNS เมื่อชื่อที่เก็บไว้ยังมีคำว่า "Cashback" แต่ default ใหม่ไม่มี

// CAMPAIGNS IIFE — refresh stale names
if(def
&&  typeof c.name === 'string'
&&  /cashback/i.test(c.name)
&&  !/cashback/i.test(def.name)) {
  c.name = def.name;
}

One-shot — quietly no-ops once everyone has loaded the dashboard once. Preserves user-renamed campaigns (e.g. "VIP Weekly Reload" won't match because the stored name lacks "Cashback").

ทำครั้งเดียว — จะไม่ทำอะไรอีกเมื่อทุกคนได้โหลดแดชบอร์ดผ่านแล้ว · ไม่กระทบแคมเปญที่ผู้ใช้ตั้งชื่อเอง (เช่น "VIP Weekly Reload" จะไม่เข้าเงื่อนไขเพราะไม่มีคำว่า "Cashback")

01

3-button AI-recommend selector

ตัวเลือก AI-recommend แบบ 3 ปุ่ม

The old "🤖 AI recommends top 10% players" single checkbox is now a three-button pill row inside the AISMS Filters popout. Click a bucket to engage; click the active bucket again to turn the recommendation off.

เช็คบ็อกซ์เดิม "🤖 AI recommends top 10% players" เปลี่ยนเป็นแถวปุ่ม pill 3 ปุ่มใน AISMS Filters popout · กดปุ่มเพื่อเปิดกลุ่มนั้น; กดปุ่มที่เปิดอยู่อีกครั้งเพื่อปิด

What changed underneath

มีอะไรเปลี่ยนใต้ฮูด

  • State carries the chosen percentage on aismsAIRecommendPct (10 / 25 / 50 / null).
  • The legacy aismsAIRecommend boolean stays in sync as !!aismsAIRecommendPct so any code path that only checks "is AI recommend on?" still works.
  • aismsTopSet(pct) builds the top-N set from the desirability score for any percentage. aismsTop10Set() remains as a back-compat shim returning aismsTopSet(10).
  • The toast on activation reports the actual count: "AI recommends top 25% · 17 players · intersected with chip filters."
  • state เก็บเปอร์เซ็นต์ที่เลือกไว้ใน aismsAIRecommendPct (10 / 25 / 50 / null)
  • boolean เดิม aismsAIRecommend ยัง sync เป็น !!aismsAIRecommendPct เพื่อให้โค้ดที่เช็คแค่ "AI recommend เปิดอยู่หรือไม่" ใช้ได้เหมือนเดิม
  • aismsTopSet(pct) สร้างชุด top-N จากคะแนน desirability สำหรับเปอร์เซ็นต์ใดก็ได้ · aismsTop10Set() ยังอยู่เป็น back-compat shim ที่ return aismsTopSet(10)
  • toast ตอนเปิดบอกจำนวนจริง: "AI recommends top 25% · 17 players · intersected with chip filters"
02

AI-recommend ⓘ info popout

ป๊อปอัปข้อมูล ⓘ ของ AI-recommend

The header line for the selector now carries an ⓘ button. Clicking it opens a nested popout that explains exactly how players are picked — formula, signal weights, and the on/off flow.

บรรทัดหัวของตัวเลือกตอนนี้มีปุ่ม ⓘ · กดเปิดป๊อปอัปซ้อนที่อธิบายวิธีคัดผู้เล่นแบบละเอียด — สูตร, น้ำหนักของสัญญาณ, และวิธีเปิด/ปิด

The score formula

สูตรคะแนน

desirability = AIVA-score             · 1.2
             + recency                · 35
             + log₁₀(recent loss)       · 8
             + log₁₀(lifetime turnover) · 4

Why each weight

ทำไมน้ำหนักแต่ละตัวถึงเป็นแบบนี้

AIVA score·1.2×
คะแนน AIVA·1.2×
Engagement-quality composite the model assigns each player (0–100).
คะแนนรวมคุณภาพการมีส่วนร่วม 0–100 ที่โมเดลกำหนดให้ผู้เล่นแต่ละคน
Recency·35×
ความใหม่·35×
How recently the player was active. Heaviest weight in the formula — recent players respond best.
ผู้เล่นแอคทีฟล่าสุดเมื่อใด · น้ำหนักสูงที่สุดในสูตร — ผู้เล่นที่เพิ่งแอคทีฟตอบสนองได้ดีที่สุด
📉
Recent loss·8× (log)
ขาดทุนล่าสุด·8× (log)
Net loss in the current period. Log-scaled so a Whale (฿100k loss) outranks a Bronze (฿1k loss) without dominating linearly.
ขาดทุนสุทธิช่วงเวลาปัจจุบัน · ใช้ log scale เพื่อให้ Whale (ขาดทุน ฿100k) อยู่เหนือ Bronze (ขาดทุน ฿1k) โดยไม่ครอบงำเชิงเส้น
💰
Lifetime turnover·4× (log)
เทิร์นโอเวอร์ตลอดชีพ·4× (log)
Cumulative wager since signup. Surfaces long-term high-value players even when the current period is quiet.
ยอดเดิมพันสะสมตั้งแต่สมัคร · ทำให้ผู้เล่นมูลค่าสูงระยะยาวขึ้นมาแม้ช่วงนี้จะเงียบ

The kept set is AND-intersected with the chip filters below — so a player only stays in the send queue if they pass the AI rank and every chip filter.

ชุดที่เก็บไว้จะถูก AND-intersect กับตัวกรอง chip ด้านล่าง — ผู้เล่นจะอยู่ในคิวส่งก็ต่อเมื่อผ่านอันดับ AI และ ผ่านตัวกรอง chip ทุกตัว

03

Nested ⓘ for Segments + VIP tiers

ป๊อปอัปข้อมูล ⓘ ซ้อนสำหรับ Segments + VIP tiers

Earlier today the AISMS Filters labels "Segments to include" and "VIP tiers" each got a small ⓘ that opens a nested popout above the AISMS Filters card. Both use the same viewport-fixed pattern so they aren't clipped by the parent card's transform.

ก่อนหน้านี้วันนี้ ป้าย "Segments to include" และ "VIP tiers" ใน AISMS Filters ทั้งคู่มี ⓘ เล็ก ๆ ที่กดเปิดป๊อปอัปซ้อนเหนือ AISMS Filters card · ใช้ pattern viewport-fixed เดียวกัน เพื่อไม่ให้โดน transform ของ card แม่ตัด

Segments popout

ป๊อปอัป Segments

Reuses SEGMENT_DESCRIPTIONS — every one of the 11 RFM segments listed with its plain-language description.

นำกลับมาใช้ SEGMENT_DESCRIPTIONS — ทุก 11 RFM segment พร้อมคำอธิบายภาษาคนปกติ

VIP tier popout

ป๊อปอัป VIP tier

Each tier paired with its Bonus multiplier (applied once at the source for derived campaigns via composition):

แต่ละ tier จับคู่กับตัวคูณ Bonus (ใช้ครั้งเดียวที่ต้นทางสำหรับแคมเปญที่ derive ผ่าน composition):

🥉
Bronze×1.0
Default tier — new or low-activity players.
ระดับเริ่มต้น — ผู้เล่นใหม่หรือกิจกรรมน้อย
🥈
VIP Silver×1.1
First step up — sustained low-to-mid volume.
ระดับถัดไป — กิจกรรมต่ำถึงปานกลางอย่างสม่ำเสมอ
🥇
VIP Gold×1.25
Active mid-volume regulars.
ผู้เล่นประจำระดับกลาง
💎
VIP Platinum×1.5
High-volume players · personal host eligible.
ผู้เล่นกิจกรรมสูง · มี VIP host เฉพาะ
👑
VIP Diamond×2.0
Top tier — whales / Champions.
ระดับสูงสุด — Whale / Champions

Closing behavior

พฤติกรรมการปิด

  • Click the × button or anywhere outside the popout to close.
  • Esc closes the nested popout first; only after both nested popouts are closed does Esc close the parent AISMS Filters card.
  • Closing the parent AISMS card calls closeAismsInfoPopouts() so the nested popouts don't get orphaned on screen.
  • กดปุ่ม × หรือคลิกนอกป๊อปอัปเพื่อปิด
  • Esc ปิดป๊อปอัปซ้อนก่อน · หลังจากป๊อปอัปซ้อนทั้งสองปิดแล้ว Esc จึงปิด AISMS Filters card หลัก
  • การปิด AISMS card หลักจะเรียก closeAismsInfoPopouts() เพื่อไม่ให้ป๊อปอัปซ้อนค้างหน้าจอ
04

Thai translations for AISMS Filters

การแปลภาษาไทยสำหรับ AISMS Filters

Chip labels (icon-prefixed forms)

ข้อความบน chip (แบบมีไอคอนนำหน้า)

The walker matches on trimmed text, so even though plain "Champions" and "Whale (≥฿100k)" were already in LANG_TH, the chip form "👑 Champions" / "👑 Whale (≥฿100k)" wasn't matching and the chip text fell back to English. Added every icon-prefixed combination.

walker เทียบจาก trimmed text · ดังนั้นแม้ "Champions" และ "Whale (≥฿100k)" จะอยู่ใน LANG_TH แล้ว · แต่รูปแบบบน chip "👑 Champions" / "👑 Whale (≥฿100k)" ไม่เข้าคู่ ทำให้ข้อความ chip ตกกลับเป็นภาษาอังกฤษ · เพิ่มทุกรูปแบบที่มีไอคอนนำหน้าครบแล้ว

EN
👑 Champions · ⭐ Loyal Customers · 🌿 Potential Loyalists · 🌱 New Customers · 📞 Unconverted Leads · ✨ Promising · 🔔 Need Attention · 😴 About To Sleep · ⚠ At Risk · 🔥 Cant Loose · 💤 Hibernating
TH
👑 แชมเปียน · ⭐ ลูกค้าประจำ · 🌿 ลูกค้าประจำที่กำลังจะมา · 🌱 ลูกค้าใหม่ · 📞 ลีดยังไม่ฝาก · ✨ มีแววดี · 🔔 ต้องการดูแล · 😴 กำลังจะหายไป · ⚠ มีความเสี่ยง · 🔥 เสียไม่ได้ · 💤 จำศีล

AI-recommend toast

Toast ของ AI-recommend

Added a regex pattern in LANG_TH_PATTERNS that catches the whole sentence including the dynamic count and percentage:

เพิ่ม regex pattern ใน LANG_TH_PATTERNS ที่จับทั้งประโยครวมตัวเลขและเปอร์เซ็นต์ที่เปลี่ยนแปลง:

EN
AI recommends top 25% · 17 players · intersected with chip filters
TH
AI แนะนำ 25% แรก · ผู้เล่น 17 คน · ตัดร่วมกับตัวกรอง

AI-recommend popout body

เนื้อหาในป๊อปอัป AI-recommend

The intro sentence, the "Score formula" eyebrow, all four signal name + description pairs, and the closing instruction line all translated. The formula text itself stays English (math + variable names are universal).

ประโยคบทนำ, eyebrow "Score formula", ทั้ง 4 คู่ของชื่อสัญญาณ + คำอธิบาย, และบรรทัดคำสั่งปิดท้าย แปลครบแล้ว · ตัวสูตรเองยังเป็นภาษาอังกฤษ (สัญลักษณ์คณิตศาสตร์และชื่อตัวแปรใช้สากล)

11 commits · 762602b → 38f46be · AISMS hardening dayวันเสริมความแข็งแกร่ง AISMS
Cross-cutting ข้ามทุก slot

Notes

หมายเหตุ

  • Almost the whole day went into hardening 8.3 AI SMS — pill state machine, Filters UX, History population, and behaviour at zero credits. CLAUDE.md, README.md, and USER_MANUAL.md all synced.
  • ใช้เวลาเกือบทั้งวันเสริมความแข็งแกร่งของ 8.3 AI SMS — state machine ของ pill, UX ของ Filters, การเติม History, และพฤติกรรมเมื่อเครดิตเป็น 0 · CLAUDE.md, README.md, USER_MANUAL.md อัปเดตครบ

No changes in slot 8.1 today — work focused on 8.3.

ไม่มีการเปลี่ยนแปลงใน slot 8.1 วันนี้ — โฟกัสที่ 8.3

No changes in slot 8.2 today — work focused on 8.3.

ไม่มีการเปลี่ยนแปลงใน slot 8.2 วันนี้ — โฟกัสที่ 8.3

01

Filters: collapsible card → centered popout

Filters: card แบบ collapsible → popout จัดกลาง

The AISMS Filters block used to be an inline collapsible card that pushed everything below it down when expanded. It's now a centered modal popout with a dimmed backdrop — opened via the 🎯 Filters button on the credit card, closed via × / Esc / backdrop click. Body scroll locks while open.

บล็อก AISMS Filters เคยเป็น card แบบ collapsible ที่ดันเนื้อหาด้านล่างเลื่อนลงเมื่อขยาย · ตอนนี้เป็น modal popout จัดกลางพร้อม backdrop ทึบ — เปิดด้วยปุ่ม 🎯 Filters บน card เครดิต, ปิดด้วย × / Esc / คลิก backdrop · scroll ของ body ถูกล็อกขณะเปิด

02

"AI recommends top 10% players" option

ตัวเลือก "AI แนะนำผู้เล่น 10% แรก"

First cut of the AI-recommend filter — a single checkbox at the top of the Filters popout. When on, AIVA ranks every player by a desirability score (AIVA score · 1.2 + recency · 35 + log10(recent loss) · 8 + log10(lifetime turnover) · 4) and keeps only the top 10%, then intersects with the chip filters below. (Superseded the next day by a 10 / 25 / 50 three-button selector.)

เวอร์ชันแรกของตัวกรอง AI-recommend — checkbox เดียวที่ด้านบนของ popout Filters · เมื่อเปิด AIVA จะจัดอันดับผู้เล่นทุกคนด้วยคะแนน desirability (AIVA score · 1.2 + recency · 35 + log10(recent loss) · 8 + log10(lifetime turnover) · 4) แล้วเก็บไว้แค่ 10% แรก ตัดร่วมกับ chip filter ด้านล่าง · (วันถัดมาถูกแทนด้วย selector 3 ปุ่ม 10 / 25 / 50)

03

AI SMS History: 120 generated entries + pagination + live updates

AI SMS History: 120 entry · แบ่งหน้า · อัปเดตสด

The History table now seeds with ~120 procedurally generated entries (varied promos, statuses, outcomes, dates) and paginates at 50 rows per page. While the AI Auto SMS ticker is sending, each tick prepends a new row with live:true; those rows render with a pulsing green left border for 4 seconds before reverting to standard styling. state.aismsHistoryPage persists across renders so the user keeps their place during live updates.

ตาราง History ตอนนี้มีข้อมูลเริ่มต้นประมาณ 120 entry (โปรโม, สถานะ, ผลลัพธ์, วันที่ หลากหลาย) และแบ่งหน้า 50 แถวต่อหน้า · ระหว่างที่ ticker AI Auto SMS กำลังส่ง แต่ละ tick จะเพิ่มแถวใหม่พร้อม live:true; แถวเหล่านั้นแสดงด้วยขอบซ้ายสีเขียวกระพริบ 4 วินาทีก่อนกลับเป็นสไตล์ปกติ · state.aismsHistoryPage รักษาไว้ข้ามการ render ผู้ใช้จึงยังอยู่ที่หน้าเดิมขณะมีการอัปเดตสด

Auto-start on Filters Confirm

เริ่มอัตโนมัติเมื่อกด Confirm บน Filters

Pressing Confirm in the Filters popout now closes the popout AND engages AI Auto SMS via toggleAISMS() if the master toggle was off — one-click "set filters and start sending".

การกดปุ่ม Confirm ใน popout Filters จะปิด popout และเปิด AI Auto SMS ผ่าน toggleAISMS() ถ้า master toggle ยังปิดอยู่ — "ตั้งค่าและเริ่มส่ง" ในคลิกเดียว

04

Pill state: Off / Idle / On with colour coding

สถานะ Pill: Off / Idle / On พร้อมรหัสสี

The AI Auto SMS card status pill is now three-state:

Pill สถานะของ card AI Auto SMS ตอนนี้มี 3 สถานะ:

  • Off (grey) — the master toggle is off.
  • On (green, --pri) — toggle on AND credit unlocked AND credits ≥ tick cost AND queue non-empty (= actually sending).
  • Idle (yellow, --amber) — toggle on AND anything else (queue drained, credit locked, or credits below tick cost).
  • Off (เทา) — master toggle ปิดอยู่
  • On (เขียว, --pri) — toggle เปิด, เครดิตปลดล็อก, เครดิต ≥ ราคา tick, queue ไม่ว่าง (= กำลังส่งจริง)
  • Idle (เหลือง, --amber) — toggle เปิด แต่กรณีอื่น (queue หมด, เครดิตล็อก, หรือเครดิตไม่พอ tick)

The yellow is driven by the .idle class on .autopilot-card, mirrored onto the SMS Credit pill so both pills move together. Slot 8.2 (AIVA Rewards autopilot) stays in the two-colour (off / on) model. The earlier "turn master toggle OFF when queue drains" approach was reverted in favour of staying engaged-but-idle — that way a chip toggle that brings a fresh untexted player into the set automatically resumes sending.

สีเหลืองมาจากคลาส .idle บน .autopilot-card, สะท้อนไปที่ pill เครดิต SMS เพื่อให้ทั้งสอง pill เคลื่อนไหวพร้อมกัน · Slot 8.2 (autopilot AIVA Rewards) ยังคงใช้แบบสองสี (off / on) · แนวคิดเดิม "ปิด master toggle เมื่อ queue หมด" ถูกย้อนกลับเป็นการรักษาสถานะ engaged-but-idle — แบบนั้นการเปิด chip ที่ดึงผู้เล่นใหม่เข้าสู่กลุ่มจะกลับมาส่งต่อเองโดยอัตโนมัติ

05

Credit balance starts at 0 + engage with zero credits

ยอดเครดิตเริ่มที่ 0 + เปิดได้แม้เครดิตเป็น 0

Initial SMS credit balance now starts at 0 (was 1,000). AI Auto SMS engages regardless of balance — the ticker just won't fire until credits cover the next tick; the pill stays Idle (yellow) with the description "credit balance is empty · top up". topUpCredit() calls syncAISMSTicker() so sending kicks in automatically the moment credits land.

ยอดเครดิต SMS เริ่มต้นที่ 0 แล้ว (เดิม 1,000) · AI Auto SMS เปิดได้แม้ไม่มียอด — ticker จะยังไม่ยิงจนกว่าเครดิตจะครอบคลุม tick ถัดไป; pill อยู่ Idle (เหลือง) พร้อมคำอธิบาย "เครดิตว่าง · เติม" · topUpCredit() เรียก syncAISMSTicker() เพื่อให้การส่งเริ่มเองทันทีที่เครดิตเข้า

4 commits · e35828e → 57bdd6f · bilingual launch + autopilot gatingเริ่มสองภาษา + ผูก autopilot
Cross-cutting ข้ามทุก slot

Bilingual EN / TH UI

UI สองภาษา EN / TH

First cut of the dashboard's Thai mode. A topbar pill (top-right) lets the operator flip between English and ภาษาไทย; a post-processor walks the DOM and substitutes labels from a LANG_TH dictionary on a MutationObserver, so dynamic content like newly-rendered cards and toasts pick up the translation too. Domain enum values (segment names, VIP tiers) stay English internally — only their display is translated.

เวอร์ชันแรกของโหมดภาษาไทยบนแดชบอร์ด · ปุ่ม pill บนแถบด้านขวาให้ผู้ดูแลสลับระหว่าง English และ ภาษาไทย; post-processor เดิน DOM แล้วแทนข้อความจาก dictionary LANG_TH ผ่าน MutationObserver จึงรองรับเนื้อหาที่ render ใหม่ทั้ง card และ toast · ค่า enum ของ domain (ชื่อ segment, ระดับ VIP) ยังคงเป็นภาษาอังกฤษภายใน — แปลเฉพาะการแสดงผล

01

Scheduled Campaigns card gated on AIVA Rewards

card Scheduled Campaigns ผูกกับ AIVA Rewards

The "Scheduled Campaigns" card in the right column of the player profile (slot 8.1) now hides when the master AIVA Rewards autopilot is off — gated via card.hidden = !state.aiAutopilot inside renderCampaigns(). toggleAutopilot() calls renderCampaigns() so flipping the master switch on slot 8.2 immediately updates the player profile too. Historical reward info (Bonus received lifetime, comm-log promo entries, AI insight recommendations) is intentionally NOT gated — it's data, not a description of the active rewards engine.

card "Scheduled Campaigns" ในคอลัมน์ขวาของ player profile (slot 8.1) ตอนนี้ซ่อนเมื่อ autopilot AIVA Rewards ปิด — ผูกผ่าน card.hidden = !state.aiAutopilot ใน renderCampaigns() · toggleAutopilot() เรียก renderCampaigns() เพื่อให้การสลับ master บน slot 8.2 อัปเดต player profile ทันที · ข้อมูล reward ในอดีต (Bonus ที่เคยรับ, รายการ promo ใน comm-log, AI insight) ตั้งใจไม่ผูก — เป็นข้อมูลย้อนหลัง ไม่ใช่คำอธิบายเอนจินที่ทำงานอยู่

No standalone changes in slot 8.2 today — see 8.1 for the cross-cutting gating change driven by the AIVA Rewards master toggle.

ไม่มีการเปลี่ยนแปลงเฉพาะ slot 8.2 วันนี้ — ดู 8.1 สำหรับการผูกแบบข้าม slot ที่ขับด้วย master toggle ของ AIVA Rewards

01

AISMS turns off when queue drains + TH coverage

AISMS ปิดเมื่อ queue หมด + เพิ่มเนื้อหาภาษาไทย

When the pending-queue empties (every targeted player has received their auto-SMS), the master toggle flips OFF and a toast confirms completion. Thai-language coverage expanded across AISMS components — toast prefixes, status descriptions, and the auto-SMS card's secondary lines were translated. (The toggle-off-on-drain behaviour was reverted the next day in favour of the Idle state that's live today.)

เมื่อ pending-queue หมด (ผู้เล่นเป้าหมายได้รับ auto-SMS หมดแล้ว), master toggle จะปิดและมี toast ยืนยัน · ภาษาไทยใน AISMS ครอบคลุมเพิ่ม — toast prefix, คำอธิบายสถานะ, และบรรทัดรองของ card auto-SMS ถูกแปล · (พฤติกรรม toggle-off-on-drain ถูกย้อนกลับในวันถัดไปเพื่อใช้สถานะ Idle ที่เห็นวันนี้)