Phase 3 scaffold: chat engine (WebSocket, FCM, pricing, timer, extension, history)
- Backend: WebSocket plugin, chat/pricing/timer/extension/closure/notification services - Client app: ChatBloc, pricing dialog, chat screen with message status, extension/goodbye flow, history - Mitra app: MitraChatBloc, ExtensionBloc, chat screen, extension accept/reject, history - Control center: free trial, extension timeout, early end config toggles - DB migration: chat_messages, session_closures, session_extensions, customer_transactions tables Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,11 +6,12 @@ const sql = getDb()
|
||||
export const getActiveSessionByCustomer = async (customerId) => {
|
||||
const [session] = await sql`
|
||||
SELECT cs.id, cs.customer_id, cs.mitra_id, cs.status, cs.created_at, cs.paired_at,
|
||||
cs.duration_minutes, cs.price, cs.is_free_trial, cs.expires_at, cs.extended_minutes,
|
||||
m.display_name AS mitra_display_name
|
||||
FROM chat_sessions cs
|
||||
LEFT JOIN mitras m ON m.id = cs.mitra_id
|
||||
WHERE cs.customer_id = ${customerId}
|
||||
AND cs.status IN ('active', 'pending_payment')
|
||||
AND cs.status IN ('active', 'pending_payment', 'extending', 'closing')
|
||||
ORDER BY cs.created_at DESC LIMIT 1
|
||||
`
|
||||
return session
|
||||
@@ -19,11 +20,12 @@ export const getActiveSessionByCustomer = async (customerId) => {
|
||||
export const getActiveSessionsByMitra = async (mitraId) => {
|
||||
const sessions = await sql`
|
||||
SELECT cs.id, cs.customer_id, cs.status, cs.created_at, cs.paired_at,
|
||||
cs.duration_minutes, cs.expires_at, cs.extended_minutes,
|
||||
c.display_name AS customer_display_name
|
||||
FROM chat_sessions cs
|
||||
INNER JOIN customers c ON c.id = cs.customer_id
|
||||
WHERE cs.mitra_id = ${mitraId}
|
||||
AND cs.status IN ('active', 'pending_payment')
|
||||
AND cs.status IN ('active', 'pending_payment', 'extending', 'closing')
|
||||
ORDER BY cs.created_at DESC
|
||||
`
|
||||
return sessions
|
||||
@@ -138,6 +140,7 @@ export const listSessions = async ({ page = 1, limit = 20, status } = {}) => {
|
||||
export const getSessionById = async (sessionId) => {
|
||||
const [session] = await sql`
|
||||
SELECT cs.id, cs.customer_id, cs.mitra_id, cs.status, cs.created_at, cs.paired_at, cs.ended_at, cs.ended_by,
|
||||
cs.duration_minutes, cs.price, cs.is_free_trial, cs.expires_at, cs.extended_minutes,
|
||||
c.display_name AS customer_display_name,
|
||||
m.display_name AS mitra_display_name
|
||||
FROM chat_sessions cs
|
||||
@@ -147,3 +150,45 @@ export const getSessionById = async (sessionId) => {
|
||||
`
|
||||
return session
|
||||
}
|
||||
|
||||
export const getCustomerHistory = async (customerId, { page = 1, limit = 20 } = {}) => {
|
||||
const offset = (page - 1) * limit
|
||||
const items = await sql`
|
||||
SELECT cs.id, cs.mitra_id, cs.status, cs.created_at, cs.paired_at, cs.ended_at,
|
||||
cs.duration_minutes, cs.price, cs.is_free_trial, cs.extended_minutes,
|
||||
m.display_name AS mitra_display_name,
|
||||
(SELECT message FROM session_closures WHERE session_id = cs.id AND user_type = 'mitra' LIMIT 1) AS mitra_closure_message,
|
||||
(SELECT message FROM session_closures WHERE session_id = cs.id AND user_type = 'customer' LIMIT 1) AS customer_closure_message
|
||||
FROM chat_sessions cs
|
||||
LEFT JOIN mitras m ON m.id = cs.mitra_id
|
||||
WHERE cs.customer_id = ${customerId}
|
||||
AND cs.status = 'completed'
|
||||
ORDER BY cs.ended_at DESC
|
||||
LIMIT ${limit} OFFSET ${offset}
|
||||
`
|
||||
const [{ count }] = await sql`
|
||||
SELECT COUNT(*) FROM chat_sessions WHERE customer_id = ${customerId} AND status = 'completed'
|
||||
`
|
||||
return { items, total: Number(count), page, limit }
|
||||
}
|
||||
|
||||
export const getMitraHistory = async (mitraId, { page = 1, limit = 20 } = {}) => {
|
||||
const offset = (page - 1) * limit
|
||||
const items = await sql`
|
||||
SELECT cs.id, cs.customer_id, cs.status, cs.created_at, cs.paired_at, cs.ended_at,
|
||||
cs.duration_minutes, cs.price, cs.is_free_trial, cs.extended_minutes,
|
||||
c.display_name AS customer_display_name,
|
||||
(SELECT message FROM session_closures WHERE session_id = cs.id AND user_type = 'mitra' LIMIT 1) AS mitra_closure_message,
|
||||
(SELECT message FROM session_closures WHERE session_id = cs.id AND user_type = 'customer' LIMIT 1) AS customer_closure_message
|
||||
FROM chat_sessions cs
|
||||
INNER JOIN customers c ON c.id = cs.customer_id
|
||||
WHERE cs.mitra_id = ${mitraId}
|
||||
AND cs.status = 'completed'
|
||||
ORDER BY cs.ended_at DESC
|
||||
LIMIT ${limit} OFFSET ${offset}
|
||||
`
|
||||
const [{ count }] = await sql`
|
||||
SELECT COUNT(*) FROM chat_sessions WHERE mitra_id = ${mitraId} AND status = 'completed'
|
||||
`
|
||||
return { items, total: Number(count), page, limit }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user