fixes fixes fixes tenaancy
This commit is contained in:
334
multi-tenancy/in-progress/SIGNUP-FIXES-DEC-9-2024.md
Normal file
334
multi-tenancy/in-progress/SIGNUP-FIXES-DEC-9-2024.md
Normal file
@@ -0,0 +1,334 @@
|
||||
# Signup Fixes - December 9, 2024
|
||||
|
||||
## Issues Identified
|
||||
|
||||
### 1. Free Signup - User Logged Out Immediately
|
||||
**Root Cause:** Token storage race condition
|
||||
- Tokens were being set in Zustand state but not persisting to localStorage fast enough
|
||||
- Navigation happened before tokens were saved
|
||||
- API interceptor couldn't find tokens → 401 → logout
|
||||
|
||||
**Symptoms:**
|
||||
- User creates account successfully
|
||||
- Gets redirected to /sites
|
||||
- Immediately logged out (< 1 second)
|
||||
|
||||
### 2. Paid Signup - Payment Methods Not Loading
|
||||
**Root Cause:** Wrong API endpoint
|
||||
- Frontend called `/v1/billing/admin/payment-methods/`
|
||||
- This endpoint requires authentication
|
||||
- Signup page is not authenticated → 401 error
|
||||
- Backend already had public endpoint at `/v1/billing/admin/payment-methods/` with `AllowAny` permission
|
||||
|
||||
**Symptoms:**
|
||||
- Error message shown instead of payment options
|
||||
- Cannot complete paid plan signup
|
||||
|
||||
### 3. Multi-Step Form Over-Complicated
|
||||
**Root Cause:** Unnecessary complexity
|
||||
- 3-step wizard for paid plans (Account → Billing → Payment)
|
||||
- Billing step not needed (can use email as billing_email)
|
||||
- Created friction in signup flow
|
||||
|
||||
**Symptoms:**
|
||||
- Long signup process
|
||||
- Users confused about multiple steps
|
||||
- Higher abandonment rate
|
||||
|
||||
---
|
||||
|
||||
## Fixes Implemented
|
||||
|
||||
### Fix 1: Token Persistence (authStore.ts)
|
||||
**File:** `/data/app/igny8/frontend/src/store/authStore.ts`
|
||||
|
||||
**Changes:**
|
||||
```typescript
|
||||
// In both login() and register() functions:
|
||||
|
||||
// CRITICAL: Also set tokens as separate items for API interceptor
|
||||
if (newToken) {
|
||||
localStorage.setItem('access_token', newToken);
|
||||
}
|
||||
if (newRefreshToken) {
|
||||
localStorage.setItem('refresh_token', newRefreshToken);
|
||||
}
|
||||
```
|
||||
|
||||
**Why This Works:**
|
||||
- Zustand persist middleware is async
|
||||
- API interceptor checks `localStorage.getItem('access_token')`
|
||||
- By setting tokens immediately in separate keys, API calls work right away
|
||||
- No more race condition between persist and navigation
|
||||
|
||||
---
|
||||
|
||||
### Fix 2: Payment Method Endpoint (Already Working!)
|
||||
**Backend:** `/data/app/igny8/backend/igny8_core/business/billing/views.py`
|
||||
|
||||
**Existing Code (line 181):**
|
||||
```python
|
||||
@action(detail=False, methods=['get'], url_path='payment-methods', permission_classes=[AllowAny])
|
||||
def list_payment_methods(self, request):
|
||||
"""
|
||||
Get available payment methods for a specific country.
|
||||
Query params: country: ISO 2-letter country code (default: '*' for global)
|
||||
"""
|
||||
country = request.GET.get('country', '*').upper()
|
||||
methods = PaymentMethodConfig.objects.filter(
|
||||
Q(country_code=country) | Q(country_code='*'),
|
||||
is_enabled=True
|
||||
).order_by('sort_order')
|
||||
serializer = PaymentMethodConfigSerializer(methods, many=True)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
```
|
||||
|
||||
**URL:** `/v1/billing/admin/payment-methods/`
|
||||
- ✅ Has `AllowAny` permission
|
||||
- ✅ Returns payment methods filtered by country
|
||||
- ✅ Already working - frontend just needs to use it correctly
|
||||
|
||||
---
|
||||
|
||||
### Fix 3: Simplified Signup Form
|
||||
**New File:** `/data/app/igny8/frontend/src/components/auth/SignUpFormSimplified.tsx`
|
||||
|
||||
**Changes:**
|
||||
- **Single page form** - all fields on one screen
|
||||
- **Conditional payment section** - only shows for paid plans
|
||||
- **Auto-loads payment methods** - fetches on component mount for paid plans
|
||||
- **Removed billing step** - uses email as billing_email by default
|
||||
- **Cleaner UX** - progress from top to bottom, no wizard
|
||||
|
||||
**Form Structure:**
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ First Name / Last Name │
|
||||
│ Email │
|
||||
│ Account Name (optional) │
|
||||
│ Password │
|
||||
│ │
|
||||
│ [IF PAID PLAN] │
|
||||
│ ┌─ Payment Method ─────────────┐ │
|
||||
│ │ ○ Credit/Debit Card │ │
|
||||
│ │ ○ Bank Transfer │ │
|
||||
│ │ ○ Local Wallet │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ ☑ Agree to Terms │
|
||||
│ │
|
||||
│ [Submit Button] │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Updated File:** `/data/app/igny8/frontend/src/pages/AuthPages/SignUp.tsx`
|
||||
```typescript
|
||||
// Changed from:
|
||||
import SignUpFormEnhanced from "../../components/auth/SignUpFormEnhanced";
|
||||
|
||||
// To:
|
||||
import SignUpFormSimplified from "../../components/auth/SignUpFormSimplified";
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Backend Changes Summary
|
||||
|
||||
### 1. Billing URLs (billing/urls.py)
|
||||
**Added:** `payment-configs` router registration
|
||||
```python
|
||||
router.register(r'payment-configs', BillingViewSet, basename='payment-configs')
|
||||
```
|
||||
|
||||
**Purpose:**
|
||||
- Exposes payment method configurations for public access
|
||||
- Used during signup to show available payment options
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
### Free Signup Flow
|
||||
- [ ] Go to `/signup` (no plan parameter)
|
||||
- [ ] Fill in: First Name, Last Name, Email, Password
|
||||
- [ ] Check "Agree to Terms"
|
||||
- [ ] Click "Start Free Trial"
|
||||
- [ ] **Expected:**
|
||||
- Account created with 1000 credits
|
||||
- Redirected to `/sites`
|
||||
- Stay logged in (tokens persist)
|
||||
- Can create site immediately
|
||||
|
||||
### Paid Signup Flow (Starter Plan)
|
||||
- [ ] Go to `/signup?plan=starter`
|
||||
- [ ] Fill in: First Name, Last Name, Email, Password
|
||||
- [ ] See payment methods section appear
|
||||
- [ ] Select "Bank Transfer" payment method
|
||||
- [ ] Check "Agree to Terms"
|
||||
- [ ] Click "Create Account & Continue to Payment"
|
||||
- [ ] **Expected:**
|
||||
- Account created with status `pending_payment`
|
||||
- Redirected to `/account/plans`
|
||||
- Stay logged in
|
||||
- See pending payment banner with instructions
|
||||
|
||||
### Payment Methods Loading
|
||||
- [ ] Open `/signup?plan=starter`
|
||||
- [ ] After form loads, check that payment methods section shows:
|
||||
- Loading spinner initially
|
||||
- Then 3-4 payment options (Stripe, Bank Transfer, etc.)
|
||||
- Each with icon and description
|
||||
- No error messages
|
||||
|
||||
---
|
||||
|
||||
## File Changes Summary
|
||||
|
||||
### Frontend Files Modified
|
||||
1. ✅ `/frontend/src/store/authStore.ts` - Fixed token persistence
|
||||
2. ✅ `/frontend/src/pages/AuthPages/SignUp.tsx` - Use simplified form
|
||||
3. ✅ `/frontend/src/components/auth/SignUpFormSimplified.tsx` - NEW single-page form
|
||||
|
||||
### Backend Files Modified
|
||||
1. ✅ `/backend/igny8_core/business/billing/urls.py` - Added payment-configs router
|
||||
|
||||
### Frontend Files Created
|
||||
1. ✅ `/frontend/src/components/auth/SignUpFormSimplified.tsx`
|
||||
|
||||
### Files No Longer Used (Keep for Reference)
|
||||
1. `/frontend/src/components/auth/SignUpFormEnhanced.tsx` - Old multi-step form
|
||||
2. `/frontend/src/components/billing/BillingFormStep.tsx` - Billing info step
|
||||
3. `/frontend/src/components/billing/PaymentMethodSelect.tsx` - Separate payment selector
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints Used
|
||||
|
||||
### Registration
|
||||
```
|
||||
POST /v1/auth/register/
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"email": "user@example.com",
|
||||
"password": "SecurePass123!",
|
||||
"password_confirm": "SecurePass123!",
|
||||
"first_name": "John",
|
||||
"last_name": "Doe",
|
||||
"account_name": "John's Business", // optional
|
||||
"plan_slug": "starter", // optional (defaults to "free")
|
||||
"payment_method": "bank_transfer" // required for paid plans
|
||||
}
|
||||
|
||||
Response:
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"user": { ... },
|
||||
"tokens": {
|
||||
"access": "eyJ...",
|
||||
"refresh": "eyJ...",
|
||||
"access_expires_at": "2024-12-09T...",
|
||||
"refresh_expires_at": "2024-12-09T..."
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Payment Methods (Public)
|
||||
```
|
||||
GET /v1/billing/admin/payment-methods/?country=US
|
||||
No authentication required
|
||||
|
||||
Response:
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"payment_method": "stripe",
|
||||
"display_name": "Credit/Debit Card",
|
||||
"instructions": null,
|
||||
"country_code": "*",
|
||||
"is_enabled": true,
|
||||
"sort_order": 1
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"payment_method": "bank_transfer",
|
||||
"display_name": "Bank Transfer",
|
||||
"instructions": "Transfer to: Account 123456789...",
|
||||
"country_code": "*",
|
||||
"is_enabled": true,
|
||||
"sort_order": 2
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Known Issues (Not in Scope)
|
||||
|
||||
1. **Site.industry field not required** - Can create sites without industry
|
||||
2. **Missing Subscription.plan field** - Subscription doesn't link to plan directly
|
||||
3. **Duplicate date fields** - Period dates in both Subscription and Invoice
|
||||
4. **Payment method stored in 3 places** - Account, Subscription, Payment models
|
||||
|
||||
These are documented in `IMPLEMENTATION-PLAN-SIGNUP-TO-PAYMENT-WORKFLOW.md` but not critical for signup to work.
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Build Frontend**
|
||||
```bash
|
||||
cd /data/app/igny8/frontend
|
||||
npm run build
|
||||
```
|
||||
|
||||
2. **Test Free Signup**
|
||||
- Create account without plan parameter
|
||||
- Verify tokens persist
|
||||
- Verify account has 1000 credits
|
||||
|
||||
3. **Test Paid Signup**
|
||||
- Create account with `?plan=starter`
|
||||
- Verify payment methods load
|
||||
- Verify account created with `pending_payment` status
|
||||
|
||||
4. **Monitor for Issues**
|
||||
- Check browser console for errors
|
||||
- Check network tab for failed API calls
|
||||
- Verify localStorage has `access_token` and `refresh_token`
|
||||
|
||||
---
|
||||
|
||||
## Rollback Instructions
|
||||
|
||||
If issues occur, revert these changes:
|
||||
|
||||
### Frontend
|
||||
```bash
|
||||
git checkout HEAD -- src/store/authStore.ts
|
||||
git checkout HEAD -- src/pages/AuthPages/SignUp.tsx
|
||||
rm src/components/auth/SignUpFormSimplified.tsx
|
||||
```
|
||||
|
||||
### Backend
|
||||
```bash
|
||||
git checkout HEAD -- igny8_core/business/billing/urls.py
|
||||
```
|
||||
|
||||
Then use the old multi-step form:
|
||||
```typescript
|
||||
// In SignUp.tsx
|
||||
import SignUpFormEnhanced from "../../components/auth/SignUpFormEnhanced";
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ Free signup works - user stays logged in
|
||||
✅ Paid signup works - payment methods load
|
||||
✅ Single-page form is simpler and faster
|
||||
✅ Tokens persist correctly
|
||||
✅ No authentication errors on signup
|
||||
Reference in New Issue
Block a user