Fix consulting order processing and display
- Fix consulting history to show continuous time range (09:00 - 11:00) instead of listing individual slots - Add foreign key relationships for consulting_slots (order_id and user_id) - Fix handle-order-paid to query profiles(email, name) instead of full_name - Add completed consulting sessions with recordings to Member Access page - Add user_id foreign key constraint to consulting_slots table - Add orders foreign key constraint for consulting_slots relationship 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -24,17 +24,19 @@ serve(async (req: Request): Promise<Response> => {
|
||||
const { order_id } = body;
|
||||
|
||||
console.log("[HANDLE-PAID] Processing paid order:", order_id);
|
||||
console.log("[HANDLE-PAID] Request body:", JSON.stringify(body));
|
||||
|
||||
const supabaseUrl = Deno.env.get("SUPABASE_URL")!;
|
||||
const supabaseServiceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!;
|
||||
const supabase = createClient(supabaseUrl, supabaseServiceKey);
|
||||
|
||||
// Get full order details with items AND consulting slots
|
||||
// Use maybeSingle() in case there are no related records
|
||||
const { data: order, error: orderError } = await supabase
|
||||
.from("orders")
|
||||
.select(`
|
||||
*,
|
||||
profiles(email, full_name),
|
||||
profiles(email, name),
|
||||
order_items (
|
||||
product_id,
|
||||
product:products (title, type)
|
||||
@@ -48,12 +50,20 @@ serve(async (req: Request): Promise<Response> => {
|
||||
)
|
||||
`)
|
||||
.eq("id", order_id)
|
||||
.single();
|
||||
.maybeSingle();
|
||||
|
||||
if (orderError || !order) {
|
||||
console.error("[HANDLE-PAID] Order not found:", order_id, orderError);
|
||||
if (orderError) {
|
||||
console.error("[HANDLE-PAID] Database error:", orderError);
|
||||
return new Response(
|
||||
JSON.stringify({ success: false, error: "Order not found" }),
|
||||
JSON.stringify({ success: false, error: "Database error", details: orderError.message }),
|
||||
{ status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } }
|
||||
);
|
||||
}
|
||||
|
||||
if (!order) {
|
||||
console.error("[HANDLE-PAID] Order not found:", order_id);
|
||||
return new Response(
|
||||
JSON.stringify({ success: false, error: "Order not found", order_id }),
|
||||
{ status: 404, headers: { ...corsHeaders, "Content-Type": "application/json" } }
|
||||
);
|
||||
}
|
||||
@@ -67,7 +77,7 @@ serve(async (req: Request): Promise<Response> => {
|
||||
}));
|
||||
|
||||
const userEmail = order.profiles?.email || "";
|
||||
const userName = order.profiles?.full_name || "Pelanggan";
|
||||
const userName = order.profiles?.name || userEmail.split('@')[0] || "Pelanggan";
|
||||
const orderItems = order.order_items as Array<{
|
||||
product_id: string;
|
||||
product: { title: string; type: string };
|
||||
@@ -140,12 +150,13 @@ serve(async (req: Request): Promise<Response> => {
|
||||
// Don't fail the entire process
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send consulting notification with the consultingSlots data
|
||||
await sendNotification(supabase, "consulting_scheduled", {
|
||||
nama: userName,
|
||||
email: userEmail,
|
||||
order_id: order_id.substring(0, 8),
|
||||
order_id_short: order_id.substring(0, 8),
|
||||
tanggal_pesanan: new Date().toLocaleDateString("id-ID"),
|
||||
total: `Rp ${order.total_amount.toLocaleString("id-ID")}`,
|
||||
metode_pembayaran: order.payment_method || "Unknown",
|
||||
@@ -188,7 +199,7 @@ serve(async (req: Request): Promise<Response> => {
|
||||
await sendNotification(supabase, "payment_success", {
|
||||
nama: userName,
|
||||
email: userEmail,
|
||||
order_id: order_id.substring(0, 8),
|
||||
order_id_short: order_id.substring(0, 8),
|
||||
tanggal_pesanan: new Date().toLocaleDateString("id-ID"),
|
||||
total: `Rp ${order.total_amount.toLocaleString("id-ID")}`,
|
||||
metode_pembayaran: order.payment_method || "Unknown",
|
||||
|
||||
@@ -65,7 +65,7 @@ serve(async (req) => {
|
||||
// Find the order by payment_reference or id
|
||||
const { data: order, error: orderError } = await supabase
|
||||
.from("orders")
|
||||
.select("id, payment_status")
|
||||
.select("id, payment_status, user_id, total_amount")
|
||||
.or(`payment_reference.eq.${payload.order_id},id.eq.${payload.order_id}`)
|
||||
.single();
|
||||
|
||||
|
||||
16
supabase/migrations/20251226_configure_trigger_settings.sql
Normal file
16
supabase/migrations/20251226_configure_trigger_settings.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
-- Configure database settings for handle-order-paid trigger
|
||||
-- These settings are required for the payment trigger to work
|
||||
|
||||
-- Set base URL (change if different)
|
||||
DELETE FROM pg_settings WHERE name = 'app.base_url';
|
||||
ALTER DATABASE postgres SET "app.base_url" = 'https://lovable.backoffice.biz.id';
|
||||
|
||||
-- Set service role key (you need to replace this with your actual service role key)
|
||||
-- Get it from: Supabase Dashboard > Project Settings > API > service_role (confidential)
|
||||
-- Uncomment and set the actual key:
|
||||
-- ALTER DATABASE postgres SET "app.service_role_key" = 'YOUR_SERVICE_ROLE_KEY_HERE';
|
||||
|
||||
-- Verify settings
|
||||
SELECT
|
||||
current_setting('app.base_url', true) as base_url,
|
||||
current_setting('app.service_role_key', true) as service_role_key;
|
||||
@@ -0,0 +1,37 @@
|
||||
-- Add foreign key relationship between consulting_slots and profiles (user_id)
|
||||
-- This enables the relationship query in ConsultingHistory component
|
||||
|
||||
-- First, check if the foreign key already exists
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.table_constraints
|
||||
WHERE table_name = 'consulting_slots'
|
||||
AND constraint_name = 'consulting_slots_user_id_fkey'
|
||||
) THEN
|
||||
-- Add foreign key constraint if it doesn't exist
|
||||
ALTER TABLE consulting_slots
|
||||
ADD CONSTRAINT consulting_slots_user_id_fkey
|
||||
FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE;
|
||||
|
||||
RAISE NOTICE 'Foreign key constraint added for user_id';
|
||||
ELSE
|
||||
RAISE NOTICE 'Foreign key constraint for user_id already exists';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Verify the relationship
|
||||
SELECT
|
||||
tc.table_name,
|
||||
kcu.column_name,
|
||||
ccu.table_name AS foreign_table_name,
|
||||
ccu.column_name AS foreign_column_name
|
||||
FROM information_schema.table_constraints AS tc
|
||||
JOIN information_schema.key_column_usage AS kcu
|
||||
ON tc.constraint_name = kcu.constraint_name
|
||||
AND tc.table_schema = kcu.table_schema
|
||||
JOIN information_schema.constraint_column_usage AS ccu
|
||||
ON ccu.constraint_name = tc.constraint_name
|
||||
WHERE tc.constraint_type = 'FOREIGN KEY'
|
||||
AND tc.table_name = 'consulting_slots'
|
||||
AND kcu.column_name = 'user_id';
|
||||
36
supabase/migrations/20251227_add_orders_foreign_key.sql
Normal file
36
supabase/migrations/20251227_add_orders_foreign_key.sql
Normal file
@@ -0,0 +1,36 @@
|
||||
-- Add foreign key relationship between consulting_slots and orders
|
||||
-- This enables the relationship query in handle-order-paid edge function
|
||||
|
||||
-- First, check if the column exists
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.table_constraints
|
||||
WHERE table_name = 'consulting_slots'
|
||||
AND constraint_name = 'consulting_slots_order_id_fkey'
|
||||
) THEN
|
||||
-- Add foreign key constraint if it doesn't exist
|
||||
ALTER TABLE consulting_slots
|
||||
ADD CONSTRAINT consulting_slots_order_id_fkey
|
||||
FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE;
|
||||
|
||||
RAISE NOTICE 'Foreign key constraint added successfully';
|
||||
ELSE
|
||||
RAISE NOTICE 'Foreign key constraint already exists';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Verify the relationship
|
||||
SELECT
|
||||
tc.table_name,
|
||||
kcu.column_name,
|
||||
ccu.table_name AS foreign_table_name,
|
||||
ccu.column_name AS foreign_column_name
|
||||
FROM information_schema.table_constraints AS tc
|
||||
JOIN information_schema.key_column_usage AS kcu
|
||||
ON tc.constraint_name = kcu.constraint_name
|
||||
AND tc.table_schema = kcu.table_schema
|
||||
JOIN information_schema.constraint_column_usage AS ccu
|
||||
ON ccu.constraint_name = tc.constraint_name
|
||||
WHERE tc.constraint_type = 'FOREIGN KEY'
|
||||
AND tc.table_name = 'consulting_slots';
|
||||
Reference in New Issue
Block a user