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:
54
backend/src/services/pricing.service.js
Normal file
54
backend/src/services/pricing.service.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import { getDb } from '../db/client.js'
|
||||
|
||||
const sql = getDb()
|
||||
|
||||
// Mock price tiers (will come from Control Center config later)
|
||||
const PRICE_TIERS = [
|
||||
{ duration_minutes: 15, price: 30000, label: '15 Menit' },
|
||||
{ duration_minutes: 30, price: 60000, label: '30 Menit' },
|
||||
{ duration_minutes: 45, price: 100000, label: '45 Menit' },
|
||||
{ duration_minutes: 60, price: 150000, label: '60 Menit' },
|
||||
{ duration_minutes: 1440, price: 250000, label: '24 Jam' },
|
||||
]
|
||||
|
||||
export const getPriceTiers = () => PRICE_TIERS
|
||||
|
||||
export const isValidTier = (durationMinutes, price) => {
|
||||
return PRICE_TIERS.some(
|
||||
(t) => t.duration_minutes === durationMinutes && t.price === price
|
||||
)
|
||||
}
|
||||
|
||||
export const getFreeTrial = async () => {
|
||||
const [enabledRow] = await sql`SELECT value FROM app_config WHERE key = 'free_trial_enabled'`
|
||||
const [durationRow] = await sql`SELECT value FROM app_config WHERE key = 'free_trial_duration_minutes'`
|
||||
return {
|
||||
enabled: enabledRow?.value?.value ?? false,
|
||||
duration_minutes: durationRow?.value?.value ?? 5,
|
||||
}
|
||||
}
|
||||
|
||||
export const isCustomerEligibleForFreeTrial = async (customerId) => {
|
||||
const freeTrial = await getFreeTrial()
|
||||
if (!freeTrial.enabled) return false
|
||||
|
||||
const [tx] = await sql`
|
||||
SELECT id FROM customer_transactions
|
||||
WHERE customer_id = ${customerId}
|
||||
LIMIT 1
|
||||
`
|
||||
return !tx // Eligible only if no transactions at all
|
||||
}
|
||||
|
||||
export const getPricingForCustomer = async (customerId) => {
|
||||
const tiers = getPriceTiers()
|
||||
const freeTrialEligible = await isCustomerEligibleForFreeTrial(customerId)
|
||||
const freeTrial = await getFreeTrial()
|
||||
|
||||
return {
|
||||
tiers,
|
||||
free_trial: freeTrialEligible
|
||||
? { eligible: true, duration_minutes: freeTrial.duration_minutes }
|
||||
: { eligible: false },
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user