cyclecad 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BILLING-IMPLEMENTATION-SUMMARY.md +425 -0
- package/BILLING-INDEX.md +293 -0
- package/BILLING-INTEGRATION-GUIDE.md +414 -0
- package/COLLABORATION-INDEX.md +440 -0
- package/COLLABORATION-SYSTEM-SUMMARY.md +548 -0
- package/DOCKER-BUILD-MANIFEST.txt +483 -0
- package/DOCKER-FILES-REFERENCE.md +440 -0
- package/DOCKER-INFRASTRUCTURE.md +475 -0
- package/DOCKER-README.md +435 -0
- package/Dockerfile +33 -55
- package/PWA-FILES-CREATED.txt +350 -0
- package/QUICK-START-TESTING.md +126 -0
- package/STEP-IMPORT-QUICKSTART.md +347 -0
- package/STEP-IMPORT-SYSTEM-SUMMARY.md +502 -0
- package/app/css/mobile.css +1074 -0
- package/app/icons/generate-icons.js +203 -0
- package/app/js/billing-ui.js +990 -0
- package/app/js/brep-kernel.js +933 -981
- package/app/js/collab-client.js +750 -0
- package/app/js/mobile-nav.js +623 -0
- package/app/js/mobile-toolbar.js +476 -0
- package/app/js/modules/billing-module.js +724 -0
- package/app/js/modules/step-module-enhanced.js +938 -0
- package/app/js/offline-manager.js +705 -0
- package/app/js/responsive-init.js +360 -0
- package/app/js/touch-handler.js +429 -0
- package/app/manifest.json +211 -0
- package/app/offline.html +508 -0
- package/app/sw.js +571 -0
- package/app/tests/billing-tests.html +779 -0
- package/app/tests/brep-tests.html +980 -0
- package/app/tests/collab-tests.html +743 -0
- package/app/tests/mobile-tests.html +1299 -0
- package/app/tests/pwa-tests.html +1134 -0
- package/app/tests/step-tests.html +1042 -0
- package/app/tests/test-agent-v3.html +719 -0
- package/docker-compose.yml +225 -0
- package/docs/BILLING-HELP.json +260 -0
- package/docs/BILLING-README.md +639 -0
- package/docs/BILLING-TUTORIAL.md +736 -0
- package/docs/BREP-HELP.json +326 -0
- package/docs/BREP-TUTORIAL.md +802 -0
- package/docs/COLLABORATION-HELP.json +228 -0
- package/docs/COLLABORATION-TUTORIAL.md +818 -0
- package/docs/DOCKER-HELP.json +224 -0
- package/docs/DOCKER-TUTORIAL.md +974 -0
- package/docs/MOBILE-HELP.json +243 -0
- package/docs/MOBILE-RESPONSIVE-README.md +378 -0
- package/docs/MOBILE-TUTORIAL.md +747 -0
- package/docs/PWA-HELP.json +228 -0
- package/docs/PWA-README.md +662 -0
- package/docs/PWA-TUTORIAL.md +757 -0
- package/docs/STEP-HELP.json +481 -0
- package/docs/STEP-IMPORT-TUTORIAL.md +824 -0
- package/docs/TESTING-GUIDE.md +528 -0
- package/docs/TESTING-HELP.json +182 -0
- package/fusion-vs-cyclecad.html +1771 -0
- package/nginx.conf +237 -0
- package/package.json +1 -1
- package/server/Dockerfile.converter +51 -0
- package/server/Dockerfile.signaling +28 -0
- package/server/billing-server.js +487 -0
- package/server/converter-enhanced.py +528 -0
- package/server/requirements-converter.txt +29 -0
- package/server/signaling-server.js +801 -0
- package/tests/docker-tests.sh +389 -0
|
@@ -0,0 +1,639 @@
|
|
|
1
|
+
# cycleCAD Billing Integration - Complete Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
A complete Stripe-based billing system for cycleCAD with three pricing tiers (Free, Pro, Enterprise), usage tracking, feature gates, trial periods, and comprehensive test coverage.
|
|
6
|
+
|
|
7
|
+
## Files Created
|
|
8
|
+
|
|
9
|
+
### Core Modules
|
|
10
|
+
|
|
11
|
+
1. **`app/js/modules/billing-module.js`** (800+ lines)
|
|
12
|
+
- Main billing logic module
|
|
13
|
+
- Tier management and limit checking
|
|
14
|
+
- Usage tracking
|
|
15
|
+
- Trial period handling
|
|
16
|
+
- Stripe integration
|
|
17
|
+
- Promo code validation
|
|
18
|
+
- Webhook handling
|
|
19
|
+
- Offline caching
|
|
20
|
+
|
|
21
|
+
2. **`app/js/billing-ui.js`** (500+ lines)
|
|
22
|
+
- User interface components
|
|
23
|
+
- Pricing page (3-tier comparison)
|
|
24
|
+
- Upgrade modals
|
|
25
|
+
- Usage dashboard
|
|
26
|
+
- Subscription status display
|
|
27
|
+
- Trial countdown banner
|
|
28
|
+
- Feature gate overlays
|
|
29
|
+
- Payment method forms
|
|
30
|
+
- Promo code input
|
|
31
|
+
|
|
32
|
+
### Server Components
|
|
33
|
+
|
|
34
|
+
3. **`server/billing-server.js`** (400+ lines)
|
|
35
|
+
- Express.js API server
|
|
36
|
+
- Stripe Checkout session creation
|
|
37
|
+
- Customer Portal integration
|
|
38
|
+
- Webhook handling (subscription lifecycle)
|
|
39
|
+
- Usage tracking endpoint
|
|
40
|
+
- Invoice retrieval
|
|
41
|
+
- Promo code validation
|
|
42
|
+
|
|
43
|
+
### Documentation
|
|
44
|
+
|
|
45
|
+
4. **`docs/BILLING-TUTORIAL.md`** (600+ lines)
|
|
46
|
+
- Comprehensive user guide
|
|
47
|
+
- Pricing overview
|
|
48
|
+
- Step-by-step upgrade instructions
|
|
49
|
+
- Usage limit explanations
|
|
50
|
+
- Trial period details
|
|
51
|
+
- Billing & invoices
|
|
52
|
+
- Payment methods
|
|
53
|
+
- Self-hosting guide
|
|
54
|
+
- 40+ FAQ entries
|
|
55
|
+
|
|
56
|
+
5. **`docs/BILLING-HELP.json`** (30+ entries)
|
|
57
|
+
- Searchable help entries
|
|
58
|
+
- Categorized by billing topics
|
|
59
|
+
- Links to detailed documentation
|
|
60
|
+
- Keywords for quick search
|
|
61
|
+
|
|
62
|
+
### Testing
|
|
63
|
+
|
|
64
|
+
6. **`app/tests/billing-tests.html`** (1,400+ lines)
|
|
65
|
+
- Interactive test suite
|
|
66
|
+
- 38 test cases across 9 categories:
|
|
67
|
+
- Tier detection (5 tests)
|
|
68
|
+
- Limit checking (8 tests)
|
|
69
|
+
- Usage tracking (6 tests)
|
|
70
|
+
- Trial period (4 tests)
|
|
71
|
+
- Promo codes (3 tests)
|
|
72
|
+
- Grace period (2 tests)
|
|
73
|
+
- Feature gates (4 tests)
|
|
74
|
+
- Export/CSV (2 tests)
|
|
75
|
+
- Offline mode (2 tests)
|
|
76
|
+
- Live console output
|
|
77
|
+
- Results export (JSON/HTML)
|
|
78
|
+
- Progress tracking
|
|
79
|
+
|
|
80
|
+
## Quick Start
|
|
81
|
+
|
|
82
|
+
### 1. Installation
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Copy files to your cycleCAD project
|
|
86
|
+
cp app/js/modules/billing-module.js ~/cyclecad/app/js/modules/
|
|
87
|
+
cp app/js/billing-ui.js ~/cyclecad/app/js/
|
|
88
|
+
cp server/billing-server.js ~/cyclecad/server/
|
|
89
|
+
cp docs/BILLING-TUTORIAL.md ~/cyclecad/docs/
|
|
90
|
+
cp docs/BILLING-HELP.json ~/cyclecad/docs/
|
|
91
|
+
cp app/tests/billing-tests.html ~/cyclecad/app/tests/
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 2. Wire into App
|
|
95
|
+
|
|
96
|
+
**In `app/index.html`:**
|
|
97
|
+
|
|
98
|
+
```html
|
|
99
|
+
<!-- Load billing module -->
|
|
100
|
+
<script src="js/modules/billing-module.js"></script>
|
|
101
|
+
<script src="js/billing-ui.js"></script>
|
|
102
|
+
|
|
103
|
+
<script>
|
|
104
|
+
// Initialize billing after app loads
|
|
105
|
+
window.addEventListener('app-ready', () => {
|
|
106
|
+
window.BillingModule.init().then(() => {
|
|
107
|
+
console.log('Billing system ready');
|
|
108
|
+
|
|
109
|
+
// Register billing UI panels
|
|
110
|
+
window.cycleCAD.registerPanel('billing', BillingModule.getUI());
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
</script>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**In server `app.js`:**
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
const billingRouter = require('./billing-server');
|
|
120
|
+
|
|
121
|
+
// Mount billing routes
|
|
122
|
+
app.use('/billing', billingRouter);
|
|
123
|
+
|
|
124
|
+
// Configure Stripe webhook
|
|
125
|
+
app.post('/billing/webhook', express.raw({type: 'application/json'}),
|
|
126
|
+
billingRouter);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 3. Environment Variables
|
|
130
|
+
|
|
131
|
+
**`.env`:**
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
# Stripe Keys
|
|
135
|
+
STRIPE_PUBLIC_KEY=pk_live_51234567890
|
|
136
|
+
STRIPE_SECRET_KEY=sk_live_1234567890
|
|
137
|
+
STRIPE_WEBHOOK_SECRET=whsec_1234567890
|
|
138
|
+
|
|
139
|
+
# App Configuration
|
|
140
|
+
APP_URL=https://cyclecad.com
|
|
141
|
+
BILLING_SERVER_URL=https://api.cyclecad.com
|
|
142
|
+
|
|
143
|
+
# Pricing (in cents)
|
|
144
|
+
STRIPE_PRICE_PRO_MONTHLY=price_1234_pro_monthly
|
|
145
|
+
STRIPE_PRICE_PRO_YEARLY=price_1234_pro_yearly
|
|
146
|
+
STRIPE_PRICE_ENTERPRISE_MONTHLY=price_1234_ent_monthly
|
|
147
|
+
STRIPE_PRICE_ENTERPRISE_YEARLY=price_1234_ent_yearly
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 4. Stripe Setup
|
|
151
|
+
|
|
152
|
+
1. Create Stripe account at [stripe.com](https://stripe.com)
|
|
153
|
+
2. Create products and prices:
|
|
154
|
+
- Pro (€49/month, €468/year)
|
|
155
|
+
- Enterprise (€299/month, €2,868/year)
|
|
156
|
+
3. Get API keys from Dashboard
|
|
157
|
+
4. Create webhook endpoint: `/billing/webhook`
|
|
158
|
+
5. Subscribe to events:
|
|
159
|
+
- `customer.subscription.created`
|
|
160
|
+
- `customer.subscription.updated`
|
|
161
|
+
- `customer.subscription.deleted`
|
|
162
|
+
- `invoice.payment_succeeded`
|
|
163
|
+
- `invoice.payment_failed`
|
|
164
|
+
|
|
165
|
+
## API Reference
|
|
166
|
+
|
|
167
|
+
### BillingModule
|
|
168
|
+
|
|
169
|
+
#### Core Methods
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
// Initialize billing system
|
|
173
|
+
await window.BillingModule.init();
|
|
174
|
+
|
|
175
|
+
// Get current tier info
|
|
176
|
+
const tier = window.BillingModule.getCurrentTier();
|
|
177
|
+
// Returns: {tier, name, features, limits, usage, status, ...}
|
|
178
|
+
|
|
179
|
+
// Check if feature is allowed
|
|
180
|
+
const check = window.BillingModule.checkLimit('ai-requests');
|
|
181
|
+
// Returns: {allowed, current, limit, message, upgradeRequired, percentUsed}
|
|
182
|
+
|
|
183
|
+
// Check if user has a feature
|
|
184
|
+
const hasFeature = window.BillingModule.hasFeature('api-access');
|
|
185
|
+
|
|
186
|
+
// Get remaining quota before hitting limit
|
|
187
|
+
const remaining = window.BillingModule.getRemainingQuota('storage');
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### Subscription Management
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
// Start checkout for tier
|
|
194
|
+
await window.BillingModule.startCheckout('pro', 'monthly');
|
|
195
|
+
|
|
196
|
+
// Open Stripe Customer Portal
|
|
197
|
+
await window.BillingModule.openCustomerPortal();
|
|
198
|
+
|
|
199
|
+
// Cancel subscription
|
|
200
|
+
await window.BillingModule.cancelSubscription();
|
|
201
|
+
|
|
202
|
+
// Change billing cycle (monthly ↔ yearly)
|
|
203
|
+
await window.BillingModule.changeBillingCycle('yearly');
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
#### Promo Codes
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
// Apply promo code
|
|
210
|
+
const result = await window.BillingModule.applyPromoCode('STUDENT20');
|
|
211
|
+
// Returns: {valid, discount, message}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### Usage Tracking
|
|
215
|
+
|
|
216
|
+
```javascript
|
|
217
|
+
// Track feature usage
|
|
218
|
+
window.BillingModule.trackUsage('ai-request');
|
|
219
|
+
window.BillingModule.trackUsage('project-created');
|
|
220
|
+
window.BillingModule.trackUsage('storage-added', 0.5); // 0.5 GB
|
|
221
|
+
|
|
222
|
+
// Get all usage stats
|
|
223
|
+
const usage = window.BillingModule.getUsage();
|
|
224
|
+
|
|
225
|
+
// Export usage as CSV
|
|
226
|
+
window.BillingModule.exportUsageCSV();
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
#### Invoices
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
// Get past invoices
|
|
233
|
+
const invoices = await window.BillingModule.getInvoices();
|
|
234
|
+
// Returns: [{id, number, amount, date, status, pdfUrl}, ...]
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### BillingUI
|
|
238
|
+
|
|
239
|
+
#### Display Components
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
// Get pricing page component
|
|
243
|
+
const pricing = BillingUI.showPricingPage();
|
|
244
|
+
|
|
245
|
+
// Show upgrade modal when hitting limit
|
|
246
|
+
BillingUI.showUpgradeModal('storage', 'Your storage is full');
|
|
247
|
+
|
|
248
|
+
// Get usage dashboard
|
|
249
|
+
const dashboard = BillingUI.getUsageDashboard();
|
|
250
|
+
|
|
251
|
+
// Get subscription status card
|
|
252
|
+
const status = BillingUI.getSubscriptionStatus();
|
|
253
|
+
|
|
254
|
+
// Get trial countdown banner
|
|
255
|
+
const banner = BillingUI.getTrialBanner();
|
|
256
|
+
|
|
257
|
+
// Get feature gate overlay
|
|
258
|
+
const overlay = BillingUI.getFeatureGateOverlay('sso');
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Server API
|
|
262
|
+
|
|
263
|
+
#### Stripe Integration
|
|
264
|
+
|
|
265
|
+
```
|
|
266
|
+
POST /billing/create-checkout
|
|
267
|
+
Body: {priceId, tier, billingCycle, trialDays}
|
|
268
|
+
Returns: {sessionId}
|
|
269
|
+
|
|
270
|
+
POST /billing/create-portal
|
|
271
|
+
Returns: {url}
|
|
272
|
+
|
|
273
|
+
POST /billing/webhook
|
|
274
|
+
(Stripe webhook handler)
|
|
275
|
+
|
|
276
|
+
GET /billing/user
|
|
277
|
+
Returns: {userId, tier, status, usage, ...}
|
|
278
|
+
|
|
279
|
+
GET /billing/usage/:userId
|
|
280
|
+
Returns: {projects, storage, aiRequests, ...}
|
|
281
|
+
|
|
282
|
+
POST /billing/track-usage
|
|
283
|
+
Body: {feature, amount}
|
|
284
|
+
Returns: {success, usage}
|
|
285
|
+
|
|
286
|
+
POST /billing/apply-promo
|
|
287
|
+
Body: {code}
|
|
288
|
+
Returns: {valid, discount, message}
|
|
289
|
+
|
|
290
|
+
GET /billing/invoices
|
|
291
|
+
Returns: [{id, number, amount, date, ...}, ...]
|
|
292
|
+
|
|
293
|
+
POST /billing/change-billing-cycle
|
|
294
|
+
Body: {cycle}
|
|
295
|
+
Returns: {success, billingCycle}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Tier Comparison
|
|
299
|
+
|
|
300
|
+
| Feature | Free | Pro | Enterprise |
|
|
301
|
+
|---------|------|-----|------------|
|
|
302
|
+
| Price | €0 | €49/mo | €299/mo |
|
|
303
|
+
| Projects | 3 | ∞ | ∞ |
|
|
304
|
+
| Parts | 100 | ∞ | ∞ |
|
|
305
|
+
| Storage | 1 GB | 50 GB | 500 GB |
|
|
306
|
+
| STEP Import | 30 MB | 500 MB | ∞ |
|
|
307
|
+
| AI Requests/Day | 20 | 500 | ∞ |
|
|
308
|
+
| Collaborators | 0 | 10 | ∞ |
|
|
309
|
+
| CAM Operations | No | Yes | Yes |
|
|
310
|
+
| Custom Materials | No | Yes | Yes |
|
|
311
|
+
| API Access | No | Yes | Yes |
|
|
312
|
+
| Custom Branding | No | No | Yes |
|
|
313
|
+
| SSO | No | No | Yes |
|
|
314
|
+
| Self-Hosting | No | No | Yes |
|
|
315
|
+
| 99.9% SLA | No | No | Yes |
|
|
316
|
+
|
|
317
|
+
## Limit Checking
|
|
318
|
+
|
|
319
|
+
Limits are checked before operations. When user hits a limit:
|
|
320
|
+
|
|
321
|
+
1. **Soft limit (70%)**: Yellow warning in dashboard
|
|
322
|
+
2. **Hard limit (90%)**: Red warning + upgrade prompt
|
|
323
|
+
3. **At limit (100%)**: Operation blocked + "Upgrade Now" modal
|
|
324
|
+
|
|
325
|
+
Example flow:
|
|
326
|
+
|
|
327
|
+
```javascript
|
|
328
|
+
// User tries to create 4th project on Free tier (limit: 3)
|
|
329
|
+
const check = window.BillingModule.checkLimit('projects');
|
|
330
|
+
// check.allowed = false
|
|
331
|
+
// check.current = 3
|
|
332
|
+
// check.limit = 3
|
|
333
|
+
// check.message = "Upgrade to Pro to increase projects limit"
|
|
334
|
+
|
|
335
|
+
// Show upgrade prompt
|
|
336
|
+
if (!check.allowed) {
|
|
337
|
+
BillingUI.showUpgradeModal('projects', 'Free users can only create 3 projects');
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Trial Period
|
|
342
|
+
|
|
343
|
+
- **Duration**: 14 days
|
|
344
|
+
- **Cost**: Free (no charge during trial)
|
|
345
|
+
- **Access**: Full Pro features
|
|
346
|
+
- **Auto-upgrade**: On day 15, first payment charged
|
|
347
|
+
- **Cancellation**: Anytime before day 15, zero charges
|
|
348
|
+
|
|
349
|
+
Trial countdown banner shows remaining days:
|
|
350
|
+
|
|
351
|
+
```javascript
|
|
352
|
+
// In trial
|
|
353
|
+
state.status = 'trialing'
|
|
354
|
+
state.trialEndsAt = timestamp
|
|
355
|
+
|
|
356
|
+
// Banner shows: "Trial expires in 5 days"
|
|
357
|
+
const daysLeft = Math.ceil((state.trialEndsAt - Date.now()) / (1000 * 60 * 60 * 24));
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Grace Period
|
|
361
|
+
|
|
362
|
+
When payment fails:
|
|
363
|
+
|
|
364
|
+
1. **Day 1-7**: 7-day grace period, full access maintained
|
|
365
|
+
2. **Reminder emails**: Days 1, 3, 5, 7
|
|
366
|
+
3. **Update payment**: User can retry anytime
|
|
367
|
+
4. **After 7 days**: If not resolved, subscription canceled
|
|
368
|
+
|
|
369
|
+
```javascript
|
|
370
|
+
state.status = 'payment_failed'
|
|
371
|
+
state.gracePeriodEndsAt = Date.now() + (7 * 24 * 60 * 60 * 1000)
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## Usage Tracking
|
|
375
|
+
|
|
376
|
+
Track usage throughout the app:
|
|
377
|
+
|
|
378
|
+
```javascript
|
|
379
|
+
// When user creates a project
|
|
380
|
+
window.BillingModule.trackUsage('project-created');
|
|
381
|
+
|
|
382
|
+
// When user uploads a file (500 KB)
|
|
383
|
+
window.BillingModule.trackUsage('storage-added', 0.5);
|
|
384
|
+
|
|
385
|
+
// When user makes an AI request
|
|
386
|
+
window.BillingModule.trackUsage('ai-request');
|
|
387
|
+
|
|
388
|
+
// When user imports STEP file (50 MB)
|
|
389
|
+
window.BillingModule.trackUsage('step-import', 50 * 1024 * 1024);
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Daily/monthly counters reset automatically:
|
|
393
|
+
|
|
394
|
+
- **AI requests**: Reset at midnight UTC daily
|
|
395
|
+
- **STEP imports**: Reset on 1st of month
|
|
396
|
+
- Storage/projects: Continuous accumulation
|
|
397
|
+
|
|
398
|
+
## Feature Gates
|
|
399
|
+
|
|
400
|
+
Restrict features by tier:
|
|
401
|
+
|
|
402
|
+
```javascript
|
|
403
|
+
// Check if feature is available
|
|
404
|
+
if (!window.BillingModule.hasFeature('api-access')) {
|
|
405
|
+
// Show lock overlay
|
|
406
|
+
element.appendChild(BillingUI.getFeatureGateOverlay('api-access'));
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Disable CAM button for Free users
|
|
410
|
+
if (!window.BillingModule.hasFeature('cam-operations')) {
|
|
411
|
+
camButton.disabled = true;
|
|
412
|
+
camButton.title = 'CAM operations available in Pro tier';
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
## Promo Codes
|
|
417
|
+
|
|
418
|
+
Pre-configured codes:
|
|
419
|
+
|
|
420
|
+
- **STUDENT20**: 20% off Pro (with .edu verification)
|
|
421
|
+
- **NONPROFIT30**: 30% off Pro (with 501(c)(3) verification)
|
|
422
|
+
- **ANNUAL20**: 20% off yearly (auto-applied)
|
|
423
|
+
- **REFERRAL25**: €12 credit per referral
|
|
424
|
+
|
|
425
|
+
Apply at checkout:
|
|
426
|
+
|
|
427
|
+
```javascript
|
|
428
|
+
// User enters code "STUDENT20"
|
|
429
|
+
const result = await window.BillingModule.applyPromoCode('STUDENT20');
|
|
430
|
+
|
|
431
|
+
if (result.valid) {
|
|
432
|
+
// Display: "20% discount applied"
|
|
433
|
+
// Final price updates
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
## Testing
|
|
438
|
+
|
|
439
|
+
Run the comprehensive test suite:
|
|
440
|
+
|
|
441
|
+
```
|
|
442
|
+
Open: app/tests/billing-tests.html
|
|
443
|
+
Browser: Any modern browser (Chrome, Firefox, Safari, Edge)
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### Test Categories
|
|
447
|
+
|
|
448
|
+
1. **Tier Detection** (5 tests)
|
|
449
|
+
- Default tier is Free
|
|
450
|
+
- Pro/Enterprise limits correct
|
|
451
|
+
- Tier switching works
|
|
452
|
+
- Invalid tier fallback
|
|
453
|
+
|
|
454
|
+
2. **Limit Checking** (8 tests)
|
|
455
|
+
- Under/at/over limit detection
|
|
456
|
+
- Unlimited tier allows anything
|
|
457
|
+
- Storage warning at 80%
|
|
458
|
+
- AI request daily reset
|
|
459
|
+
- Percentage calculations
|
|
460
|
+
|
|
461
|
+
3. **Usage Tracking** (6 tests)
|
|
462
|
+
- Project creation tracking
|
|
463
|
+
- Storage tracking
|
|
464
|
+
- AI request tracking
|
|
465
|
+
- All metrics returned
|
|
466
|
+
- Concurrent overflow handling
|
|
467
|
+
- Persistence after save
|
|
468
|
+
|
|
469
|
+
4. **Trial Period** (4 tests)
|
|
470
|
+
- Countdown calculation
|
|
471
|
+
- Expiration detection
|
|
472
|
+
- Auto-conversion to paid
|
|
473
|
+
- Cancellation before expiry
|
|
474
|
+
|
|
475
|
+
5. **Promo Codes** (3 tests)
|
|
476
|
+
- Valid code acceptance
|
|
477
|
+
- Invalid code rejection
|
|
478
|
+
- Discount application math
|
|
479
|
+
|
|
480
|
+
6. **Grace Period** (2 tests)
|
|
481
|
+
- Grace period start on failure
|
|
482
|
+
- Access maintained during grace
|
|
483
|
+
|
|
484
|
+
7. **Feature Gates** (4 tests)
|
|
485
|
+
- Free tier blocks features
|
|
486
|
+
- Pro tier unlocks features
|
|
487
|
+
- Enforcement across tiers
|
|
488
|
+
- Enterprise unlocks everything
|
|
489
|
+
|
|
490
|
+
8. **Export/CSV** (2 tests)
|
|
491
|
+
- CSV format generation
|
|
492
|
+
- All metrics included
|
|
493
|
+
|
|
494
|
+
9. **Offline Mode** (2 tests)
|
|
495
|
+
- Cached data usage
|
|
496
|
+
- Sync on reconnect
|
|
497
|
+
|
|
498
|
+
### Running Tests
|
|
499
|
+
|
|
500
|
+
1. Click "Run All Tests" to execute all 38 tests
|
|
501
|
+
2. View results in real-time with pass/fail status
|
|
502
|
+
3. Check console output for detailed logs
|
|
503
|
+
4. Export results as JSON or HTML report
|
|
504
|
+
|
|
505
|
+
```javascript
|
|
506
|
+
// Programmatic test run
|
|
507
|
+
await suite.run();
|
|
508
|
+
// Returns array of test results with status and errors
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
## Error Handling
|
|
512
|
+
|
|
513
|
+
### Checkout Errors
|
|
514
|
+
|
|
515
|
+
```javascript
|
|
516
|
+
try {
|
|
517
|
+
await window.BillingModule.startCheckout('pro', 'monthly');
|
|
518
|
+
} catch (e) {
|
|
519
|
+
console.error('Checkout failed:', e.message);
|
|
520
|
+
// Show user-friendly error message
|
|
521
|
+
}
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
### Payment Failures
|
|
525
|
+
|
|
526
|
+
On webhook:
|
|
527
|
+
|
|
528
|
+
```javascript
|
|
529
|
+
case 'invoice.payment_failed':
|
|
530
|
+
// Send notification email to user
|
|
531
|
+
// Update subscription status to 'payment_failed'
|
|
532
|
+
// Start 7-day grace period
|
|
533
|
+
// Continue showing access (don't downgrade immediately)
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### Network Errors
|
|
537
|
+
|
|
538
|
+
Billing module gracefully handles offline:
|
|
539
|
+
|
|
540
|
+
```javascript
|
|
541
|
+
state.offlineMode = true;
|
|
542
|
+
// Use cached data from localStorage
|
|
543
|
+
// Sync when connection restored
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
## Database Considerations
|
|
547
|
+
|
|
548
|
+
Production deployment requires:
|
|
549
|
+
|
|
550
|
+
1. **User Subscriptions Table**
|
|
551
|
+
- userId (PK)
|
|
552
|
+
- tier (free/pro/enterprise)
|
|
553
|
+
- status (active/trialing/canceled/payment_failed)
|
|
554
|
+
- stripeCustomerId
|
|
555
|
+
- subscriptionId
|
|
556
|
+
- currentPeriodStart
|
|
557
|
+
- currentPeriodEnd
|
|
558
|
+
- trialEndsAt
|
|
559
|
+
- billingCycle (monthly/yearly)
|
|
560
|
+
- cancelAtPeriodEnd
|
|
561
|
+
|
|
562
|
+
2. **User Usage Table**
|
|
563
|
+
- userId (PK)
|
|
564
|
+
- projects
|
|
565
|
+
- totalParts
|
|
566
|
+
- storageGB
|
|
567
|
+
- aiRequests
|
|
568
|
+
- aiRequestsToday
|
|
569
|
+
- stepImportsThisMonth
|
|
570
|
+
- lastResetDate
|
|
571
|
+
|
|
572
|
+
3. **Invoices Table**
|
|
573
|
+
- invoiceId (PK)
|
|
574
|
+
- userId (FK)
|
|
575
|
+
- amount
|
|
576
|
+
- currency
|
|
577
|
+
- date
|
|
578
|
+
- status
|
|
579
|
+
- pdfUrl
|
|
580
|
+
|
|
581
|
+
## Deployment Checklist
|
|
582
|
+
|
|
583
|
+
- [ ] Set Stripe API keys in environment
|
|
584
|
+
- [ ] Create Stripe products and prices
|
|
585
|
+
- [ ] Configure webhook endpoint and secret
|
|
586
|
+
- [ ] Test checkout flow end-to-end
|
|
587
|
+
- [ ] Test subscription management in portal
|
|
588
|
+
- [ ] Test invoice generation
|
|
589
|
+
- [ ] Run complete test suite
|
|
590
|
+
- [ ] Deploy to staging environment
|
|
591
|
+
- [ ] User acceptance testing
|
|
592
|
+
- [ ] Deploy to production
|
|
593
|
+
- [ ] Monitor webhook deliveries
|
|
594
|
+
- [ ] Set up billing alerts
|
|
595
|
+
|
|
596
|
+
## Support & Troubleshooting
|
|
597
|
+
|
|
598
|
+
### Common Issues
|
|
599
|
+
|
|
600
|
+
**Q: Stripe keys not working**
|
|
601
|
+
A: Verify environment variables are set. Use `console.log` to debug.
|
|
602
|
+
|
|
603
|
+
**Q: Checkout redirects to error page**
|
|
604
|
+
A: Check webhook configuration. Ensure endpoint is accessible.
|
|
605
|
+
|
|
606
|
+
**Q: Usage not persisting**
|
|
607
|
+
A: Check localStorage is enabled. Verify `saveState()` is called.
|
|
608
|
+
|
|
609
|
+
**Q: Trial not counting down**
|
|
610
|
+
A: Verify system time is correct. Trial date calculation depends on `Date.now()`.
|
|
611
|
+
|
|
612
|
+
### Debugging
|
|
613
|
+
|
|
614
|
+
Enable verbose logging:
|
|
615
|
+
|
|
616
|
+
```javascript
|
|
617
|
+
// In billing-module.js
|
|
618
|
+
console.log('[Billing] ...message');
|
|
619
|
+
|
|
620
|
+
// In browser console
|
|
621
|
+
localStorage.setItem('billing_debug', 'true');
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
## Future Enhancements
|
|
625
|
+
|
|
626
|
+
1. **Multi-currency support** (USD, GBP, JPY, etc.)
|
|
627
|
+
2. **Team billing** (shared subscriptions)
|
|
628
|
+
3. **Usage-based pricing** (overage charges)
|
|
629
|
+
4. **Seat-based pricing** (per collaborator)
|
|
630
|
+
5. **Annual commitment discount** (additional 10%)
|
|
631
|
+
6. **Dunning management** (retry failed payments)
|
|
632
|
+
7. **Revenue recognition** (for accounting)
|
|
633
|
+
8. **Affiliate program** (partner commissions)
|
|
634
|
+
9. **Coupon management UI** (create/manage codes)
|
|
635
|
+
10. **Billing analytics** (MRR, churn, LTV)
|
|
636
|
+
|
|
637
|
+
## License
|
|
638
|
+
|
|
639
|
+
Copyright © 2026 cycleWASH. All rights reserved.
|