Implement Seller Dashboard Data Layer with Supabase
Description
Implement the data layer for StellarMarket's seller dashboard using Supabase. This includes setting up database tables, views, functions, and APIs to support seller analytics, order management, and performance tracking.
Acceptance Criteria
Database Schema Implementation
-
Stores Table
- Extend the existing stores table with:
revenue_total: decimal (calculated field)
active_product_count: integer (calculated field)
pending_order_count: integer (calculated field)
average_rating: decimal
rating_count: integer
monthly_sales_goal: decimal
customer_goal: integer
review_goal: integer
last_updated: timestamp
-
Store Analytics Table
- Create table with schema:
id: UUID primary key
store_id: FK to stores
date: date
revenue: decimal
order_count: integer
new_customers: integer
returning_customers: integer
average_order_value: decimal
conversion_rate: decimal
view_count: integer
-
Store Performance Goals
id: UUID primary key
store_id: FK to stores
goal_type: enum ('sales', 'customers', 'reviews', 'conversion', 'aov')
target_value: decimal
current_value: decimal
time_period: enum ('daily', 'weekly', 'monthly', 'quarterly', 'yearly')
start_date: date
end_date: date
created_at: timestamp
updated_at: timestamp
-
Order Status History
id: UUID primary key
order_id: FK to orders
status: enum ('created', 'processing', 'paid', 'shipped', 'delivered', 'cancelled', 'refunded')
changed_at: timestamp
changed_by: FK to auth.users
notes: text
Database Views
- Store Dashboard View
CREATE VIEW seller_dashboard_view AS
SELECT
s.id as store_id,
s.name as store_name,
s.owner_id,
COALESCE(SUM(o.total_amount), 0) as total_revenue,
COUNT(DISTINCT p.id) FILTER (WHERE p.active = true) as active_products,
COUNT(DISTINCT o.id) FILTER (WHERE o.status = 'processing') as pending_orders,
COALESCE(AVG(r.rating), 0) as average_rating,
COUNT(DISTINCT r.id) as rating_count,
COUNT(DISTINCT o.id) as total_orders
FROM stores s
LEFT JOIN products p ON s.id = p.store_id
LEFT JOIN orders o ON s.id = o.store_id
LEFT JOIN reviews r ON s.id = r.store_id
GROUP BY s.id;
- Recent Orders View
CREATE VIEW seller_recent_orders_view AS
SELECT
o.id as order_id,
o.store_id,
o.total_amount,
o.status,
o.created_at,
o.updated_at,
u.display_name as customer_name,
oi.product_id,
oi.quantity,
oi.price_at_purchase,
p.name as product_name,
p.variant as product_variant
FROM orders o
JOIN order_items oi ON o.id = oi.order_id
JOIN products p ON oi.product_id = p.id
JOIN auth.users u ON o.user_id = u.id
ORDER BY o.created_at DESC;
- Store Performance View
CREATE VIEW store_performance_view AS
SELECT
s.id as store_id,
g.goal_type,
g.target_value,
g.current_value,
CASE
WHEN g.target_value > 0 THEN
ROUND((g.current_value / g.target_value) * 100)
ELSE 0
END as percentage,
g.time_period,
g.start_date,
g.end_date
FROM stores s
JOIN store_performance_goals g ON s.id = g.store_id;
Database Functions
- Calculate Store Revenue
CREATE OR REPLACE FUNCTION calculate_store_revenue(store_id UUID)
RETURNS decimal AS $$
DECLARE
total decimal;
BEGIN
SELECT COALESCE(SUM(total_amount), 0)
INTO total
FROM orders
WHERE store_id = calculate_store_revenue.store_id
AND status NOT IN ('cancelled', 'refunded');
RETURN total;
END;
$$ LANGUAGE plpgsql;
- Update Store Metrics
CREATE OR REPLACE FUNCTION update_store_metrics()
RETURNS trigger AS $$
BEGIN
UPDATE stores
SET
revenue_total = calculate_store_revenue(NEW.store_id),
active_product_count = (
SELECT COUNT(*) FROM products
WHERE store_id = NEW.store_id AND active = true
),
pending_order_count = (
SELECT COUNT(*) FROM orders
WHERE store_id = NEW.store_id AND status = 'processing'
),
last_updated = NOW()
WHERE id = NEW.store_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
- Calculate Performance Percentage
CREATE OR REPLACE FUNCTION calculate_performance_percentage(
current_value decimal,
target_value decimal
) RETURNS integer AS $$
BEGIN
IF target_value IS NULL OR target_value = 0 THEN
RETURN 0;
END IF;
RETURN LEAST(ROUND((current_value / target_value) * 100), 100);
END;
$$ LANGUAGE plpgsql;
Row-Level Security Policies
- Stores Table Policies
-- Allow sellers to read their own store data
CREATE POLICY "Sellers can view their own store"
ON stores FOR SELECT
USING (auth.uid() = owner_id);
-- Allow sellers to update their own store
CREATE POLICY "Sellers can update their own store"
ON stores FOR UPDATE
USING (auth.uid() = owner_id);
- Analytics Table Policies
-- Only store owners can view their analytics
CREATE POLICY "Sellers can view their own analytics"
ON store_analytics FOR SELECT
USING (
auth.uid() IN (
SELECT owner_id FROM stores WHERE id = store_id
)
);
- Orders Policies for Sellers
-- Sellers can view orders for their store
CREATE POLICY "Sellers can view their store orders"
ON orders FOR SELECT
USING (
store_id IN (
SELECT id FROM stores WHERE owner_id = auth.uid()
)
);
-- Sellers can update order status
CREATE POLICY "Sellers can update order status"
ON orders FOR UPDATE
USING (
store_id IN (
SELECT id FROM stores WHERE owner_id = auth.uid()
)
)
WITH CHECK (
-- Only allow updating specific fields
(OLD.store_id = NEW.store_id) AND
(OLD.user_id = NEW.user_id) AND
(OLD.total_amount = NEW.total_amount)
);
API Implementation
-
Dashboard Overview API
- Get store dashboard summary
- Get revenue metrics
- Get product and order counts
- Get store rating
-
Recent Orders API
- Get paginated recent orders
- Get order details
- Update order status
- Filter orders by status
-
Store Performance API
- Get performance metrics
- Set performance goals
- Track goal progress
- Get historical performance data
-
Analytics API
- Get time-series revenue data
- Get customer growth metrics
- Get product performance stats
- Get conversion analytics
Security Considerations
-
Data Access Control
- Strict RLS policies to ensure sellers only access their data
- Audit logging for sensitive operations
- Prevent data leakage between sellers
-
Input Validation
- Validate all input parameters
- Sanitize order data
- Validate goal targets as positive values
-
Rate Limiting
- Implement rate limiting for analytics APIs
- Prevent abuse of dashboard refresh
Performance Optimization
-
Indexing Strategy
- Create indexes for:
orders(store_id, status, created_at)
products(store_id, active)
store_analytics(store_id, date)
store_performance_goals(store_id, goal_type, time_period)
-
Materialized Views
- Create materialized views for heavy dashboard queries
- Set up refresh schedule (every hour)
- Implement incremental view maintenance where possible
-
Caching Strategy
- Cache dashboard view data (5-minute TTL)
- Cache performance metrics (15-minute TTL)
- Use edge caching for static dashboard elements
Testing Requirements
-
Unit Tests
- Test all database functions
- Test RLS policy effectiveness
- Test calculation accuracy
-
Integration Tests
- Test API endpoints with various scenarios
- Test dashboard data consistency
- Test performance under load
-
Security Tests
- Verify RLS prevents cross-seller data access
- Test for SQL injection vulnerabilities
- Verify proper error handling
Definition of Done
- All database schemas implemented and migrated
- Functions and triggers tested and working
- APIs implemented and documented
- RLS policies verified for security
- Performance optimization applied
- Tests passing for all components
- Documentation updated
Implement Seller Dashboard Data Layer with Supabase
Description
Implement the data layer for StellarMarket's seller dashboard using Supabase. This includes setting up database tables, views, functions, and APIs to support seller analytics, order management, and performance tracking.
Acceptance Criteria
Database Schema Implementation
Stores Table
revenue_total: decimal (calculated field)active_product_count: integer (calculated field)pending_order_count: integer (calculated field)average_rating: decimalrating_count: integermonthly_sales_goal: decimalcustomer_goal: integerreview_goal: integerlast_updated: timestampStore Analytics Table
id: UUID primary keystore_id: FK to storesdate: daterevenue: decimalorder_count: integernew_customers: integerreturning_customers: integeraverage_order_value: decimalconversion_rate: decimalview_count: integerStore Performance Goals
id: UUID primary keystore_id: FK to storesgoal_type: enum ('sales', 'customers', 'reviews', 'conversion', 'aov')target_value: decimalcurrent_value: decimaltime_period: enum ('daily', 'weekly', 'monthly', 'quarterly', 'yearly')start_date: dateend_date: datecreated_at: timestampupdated_at: timestampOrder Status History
id: UUID primary keyorder_id: FK to ordersstatus: enum ('created', 'processing', 'paid', 'shipped', 'delivered', 'cancelled', 'refunded')changed_at: timestampchanged_by: FK to auth.usersnotes: textDatabase Views
Database Functions
Row-Level Security Policies
API Implementation
Dashboard Overview API
Recent Orders API
Store Performance API
Analytics API
Security Considerations
Data Access Control
Input Validation
Rate Limiting
Performance Optimization
Indexing Strategy
orders(store_id, status, created_at)products(store_id, active)store_analytics(store_id, date)store_performance_goals(store_id, goal_type, time_period)Materialized Views
Caching Strategy
Testing Requirements
Unit Tests
Integration Tests
Security Tests
Definition of Done