feat: implement comprehensive credits management system
- Database schema: * Extended user_credits table with daily_limit, API costs, last_reset_at * Created credit_transactions table for full audit trail * Added RLS policies for secure access control - Core services: * credit-service.ts - balance checking, deduction, addition, transaction history * admin-credit-service.ts - admin controls for managing users and credits - API integration: * Integrated credit checking into discover-whiskybase.ts * Credits deducted after successful API calls * Insufficient credits error handling - Admin interface: * /admin/users page with user management * Statistics dashboard (total users, credits in circulation, usage) * Interactive user table with search * Edit modal for credit adjustment and settings * Per-user daily limits and API cost configuration - Features: * Automatic credit initialization (100 credits for new users) * Credit transaction logging with balance_after tracking * Admin can add/remove credits with reason * Admin can set custom daily limits per user * Admin can set custom API costs per user * Low credit warnings (< 10 credits) * Full transaction history - User experience: * Credits checked before API calls * Clear error messages for insufficient credits * Graceful handling of credit deduction failures System is ready for future enhancements like credit packages, auto-recharge, and payment integration.
This commit is contained in:
@@ -290,3 +290,59 @@ CREATE POLICY "Users can view their own admin record" ON admin_users FOR SELECT
|
||||
|
||||
-- Note: To add robin as admin, run this after getting the user_id:
|
||||
-- INSERT INTO admin_users (user_id, role) VALUES ('<robin_user_id>', 'super_admin');
|
||||
|
||||
-- ============================================
|
||||
-- Credits Management System
|
||||
-- ============================================
|
||||
|
||||
-- Extend user_credits table with additional fields
|
||||
ALTER TABLE user_credits
|
||||
ADD COLUMN IF NOT EXISTS daily_limit INTEGER DEFAULT NULL,
|
||||
ADD COLUMN IF NOT EXISTS google_search_cost INTEGER DEFAULT 1,
|
||||
ADD COLUMN IF NOT EXISTS gemini_ai_cost INTEGER DEFAULT 1,
|
||||
ADD COLUMN IF NOT EXISTS last_reset_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('Europe/Berlin'::text, now());
|
||||
|
||||
-- Credit transactions table
|
||||
CREATE TABLE IF NOT EXISTS credit_transactions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
amount INTEGER NOT NULL,
|
||||
type TEXT NOT NULL CHECK (type IN ('deduction', 'addition', 'admin_adjustment')),
|
||||
reason TEXT,
|
||||
api_type TEXT CHECK (api_type IN ('google_search', 'gemini_ai')),
|
||||
admin_id UUID REFERENCES auth.users(id),
|
||||
balance_after INTEGER,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('Europe/Berlin'::text, now())
|
||||
);
|
||||
|
||||
CREATE INDEX idx_credit_transactions_user_id ON credit_transactions(user_id);
|
||||
CREATE INDEX idx_credit_transactions_created_at ON credit_transactions(created_at);
|
||||
CREATE INDEX idx_credit_transactions_type ON credit_transactions(type);
|
||||
|
||||
-- Enable RLS for credit_transactions
|
||||
ALTER TABLE credit_transactions ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Policies for credit_transactions
|
||||
CREATE POLICY "Users can view their own transactions" ON credit_transactions
|
||||
FOR SELECT USING (auth.uid() = user_id);
|
||||
|
||||
CREATE POLICY "Admins can view all transactions" ON credit_transactions
|
||||
FOR SELECT USING (
|
||||
auth.uid() IN (SELECT user_id FROM admin_users)
|
||||
);
|
||||
|
||||
CREATE POLICY "System can insert transactions" ON credit_transactions
|
||||
FOR INSERT WITH CHECK (true);
|
||||
|
||||
-- Update user_credits policies to allow admin updates
|
||||
CREATE POLICY "Admins can update credits" ON user_credits
|
||||
FOR UPDATE USING (
|
||||
auth.uid() IN (SELECT user_id FROM admin_users)
|
||||
);
|
||||
|
||||
-- Initialize credits for existing users (run manually if needed)
|
||||
-- INSERT INTO user_credits (user_id, balance)
|
||||
-- SELECT id, 100
|
||||
-- FROM auth.users
|
||||
-- ON CONFLICT (user_id) DO UPDATE SET balance = EXCLUDED.balance
|
||||
-- WHERE user_credits.balance = 0;
|
||||
|
||||
Reference in New Issue
Block a user