feat: Complete platform enhancement with multi-tenant architecture
Major additions: - Territory manager system with application workflow - Custom pricing and page builder with Craft.js - Enhanced Stripe Connect onboarding - CodeReadr QR scanning integration - Kiosk mode for venue sales - Super admin dashboard and analytics - MCP integration for AI-powered operations Infrastructure improvements: - Centralized API client and routing system - Enhanced authentication with organization context - Comprehensive theme management system - Advanced event management with custom tabs - Performance monitoring and accessibility features Database schema updates: - Territory management tables - Custom pages and pricing structures - Kiosk PIN system - Enhanced organization profiles - CodeReadr integration tables 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
216
src/pages/api/stripe/account-status.ts
Normal file
216
src/pages/api/stripe/account-status.ts
Normal file
@@ -0,0 +1,216 @@
|
||||
export const prerender = false;
|
||||
|
||||
import type { APIRoute } from 'astro';
|
||||
import { stripe } from '../../../lib/stripe';
|
||||
import { supabase, supabaseAdmin } from '../../../lib/supabase';
|
||||
import { verifyAuth } from '../../../lib/auth';
|
||||
import { logUserActivity } from '../../../lib/logger';
|
||||
|
||||
export const GET: APIRoute = async ({ request }) => {
|
||||
try {
|
||||
|
||||
// Verify authentication
|
||||
const authContext = await verifyAuth(request);
|
||||
if (!authContext) {
|
||||
console.error('Account status check failed: Unauthorized request');
|
||||
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
|
||||
status: 401,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
const { user } = authContext;
|
||||
|
||||
// Get user's organization ID first (using admin client to bypass RLS)
|
||||
const { data: userData, error: userError } = await (supabaseAdmin || supabase)
|
||||
.from('users')
|
||||
.select('organization_id')
|
||||
.eq('id', user.id)
|
||||
.single();
|
||||
|
||||
if (userError || !userData?.organization_id) {
|
||||
console.error('Account status check failed: Organization not found', {
|
||||
userId: user.id,
|
||||
userEmail: user.email,
|
||||
error: userError
|
||||
});
|
||||
return new Response(JSON.stringify({
|
||||
error: 'Organization not found',
|
||||
debug: {
|
||||
userId: user.id,
|
||||
userEmail: user.email,
|
||||
userData,
|
||||
userError
|
||||
}
|
||||
}), {
|
||||
status: 404,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// Now get the organization details
|
||||
const { data: organization, error: orgError } = await (supabaseAdmin || supabase)
|
||||
.from('organizations')
|
||||
.select(`
|
||||
id,
|
||||
name,
|
||||
stripe_account_id,
|
||||
account_status,
|
||||
stripe_onboarding_status,
|
||||
stripe_details_submitted,
|
||||
stripe_charges_enabled,
|
||||
stripe_payouts_enabled,
|
||||
onboarding_completed_at
|
||||
`)
|
||||
.eq('id', userData.organization_id)
|
||||
.single();
|
||||
|
||||
if (orgError || !organization) {
|
||||
console.error('Account status check failed: Organization details not found', {
|
||||
userId: user.id,
|
||||
organizationId: userData.organization_id,
|
||||
error: orgError
|
||||
});
|
||||
return new Response(JSON.stringify({
|
||||
error: 'Organization details not found',
|
||||
debug: {
|
||||
userId: user.id,
|
||||
userEmail: user.email,
|
||||
organizationId: userData.organization_id,
|
||||
orgError
|
||||
}
|
||||
}), {
|
||||
status: 404,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// If no Stripe account exists, return basic status
|
||||
if (!organization.stripe_account_id) {
|
||||
console.log('No Stripe account found for organization', {
|
||||
userId: user.id,
|
||||
organizationId: organization.id,
|
||||
organizationName: organization.name,
|
||||
accountStatus: organization.account_status
|
||||
});
|
||||
return new Response(JSON.stringify({
|
||||
account_status: organization.account_status,
|
||||
stripe_onboarding_status: 'not_started',
|
||||
can_start_onboarding: organization.account_status === 'approved',
|
||||
details_submitted: false,
|
||||
charges_enabled: false,
|
||||
payouts_enabled: false,
|
||||
requirements: {
|
||||
currently_due: [],
|
||||
eventually_due: [],
|
||||
past_due: []
|
||||
}
|
||||
}), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// Get detailed status from Stripe
|
||||
console.log('Retrieving Stripe account status', {
|
||||
userId: user.id,
|
||||
organizationId: organization.id,
|
||||
stripeAccountId: organization.stripe_account_id
|
||||
});
|
||||
|
||||
const account = await stripe.accounts.retrieve(organization.stripe_account_id);
|
||||
|
||||
// Determine overall onboarding status
|
||||
let onboarding_status = 'in_progress';
|
||||
if (account.details_submitted && account.charges_enabled) {
|
||||
onboarding_status = 'completed';
|
||||
} else if (account.details_submitted) {
|
||||
onboarding_status = 'pending_review';
|
||||
}
|
||||
|
||||
console.log('Stripe account status retrieved', {
|
||||
stripeAccountId: organization.stripe_account_id,
|
||||
detailsSubmitted: account.details_submitted,
|
||||
chargesEnabled: account.charges_enabled,
|
||||
payoutsEnabled: account.payouts_enabled,
|
||||
onboardingStatus: onboarding_status,
|
||||
requirementsCount: {
|
||||
currentlyDue: account.requirements?.currently_due?.length || 0,
|
||||
eventuallyDue: account.requirements?.eventually_due?.length || 0,
|
||||
pastDue: account.requirements?.past_due?.length || 0
|
||||
}
|
||||
});
|
||||
|
||||
// Update organization with latest Stripe status
|
||||
const { error: updateError } = await (supabaseAdmin || supabase)
|
||||
.from('organizations')
|
||||
.update({
|
||||
stripe_onboarding_status: onboarding_status,
|
||||
stripe_details_submitted: account.details_submitted,
|
||||
stripe_charges_enabled: account.charges_enabled,
|
||||
stripe_payouts_enabled: account.payouts_enabled,
|
||||
...(onboarding_status === 'completed' && !organization.onboarding_completed_at && {
|
||||
onboarding_completed_at: new Date().toISOString(),
|
||||
account_status: 'active'
|
||||
})
|
||||
})
|
||||
.eq('id', organization.id);
|
||||
|
||||
if (updateError) {
|
||||
console.error('Failed to update organization with latest Stripe status', {
|
||||
organizationId: organization.id,
|
||||
error: updateError
|
||||
});
|
||||
}
|
||||
|
||||
// Log status check if onboarding was completed
|
||||
if (onboarding_status === 'completed' && organization.stripe_onboarding_status !== 'completed') {
|
||||
await logUserActivity({
|
||||
userId: user.id,
|
||||
action: 'stripe_onboarding_completed',
|
||||
resourceType: 'organization',
|
||||
resourceId: organization.id,
|
||||
details: {
|
||||
stripe_account_id: organization.stripe_account_id,
|
||||
charges_enabled: account.charges_enabled,
|
||||
payouts_enabled: account.payouts_enabled
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
account_status: onboarding_status === 'completed' ? 'active' : organization.account_status,
|
||||
stripe_onboarding_status: onboarding_status,
|
||||
can_start_onboarding: organization.account_status === 'approved',
|
||||
details_submitted: account.details_submitted,
|
||||
charges_enabled: account.charges_enabled,
|
||||
payouts_enabled: account.payouts_enabled,
|
||||
requirements: {
|
||||
currently_due: account.requirements?.currently_due || [],
|
||||
eventually_due: account.requirements?.eventually_due || [],
|
||||
past_due: account.requirements?.past_due || []
|
||||
},
|
||||
stripe_account_id: organization.stripe_account_id,
|
||||
business_type: account.business_type,
|
||||
country: account.country,
|
||||
default_currency: account.default_currency,
|
||||
created: account.created
|
||||
}), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Account status check failed with unexpected error', {
|
||||
error: error instanceof Error ? error.message : error,
|
||||
stack: error instanceof Error ? error.stack : undefined
|
||||
});
|
||||
return new Response(JSON.stringify({
|
||||
error: 'Failed to check account status',
|
||||
details: error instanceof Error ? error.message : 'Unknown error'
|
||||
}), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user