feat: validate podcast cost estimation accuracy, document per-token costs, and fix subscription/plan enforcement
Issue #543 — Validate Estimated Cost Accuracy (UI vs Backend) Backend: - cost_estimator.py uses pricing catalog (APIProviderPricing) as single source of truth - All 7 cost components: analysis, research (search+LLM), script, TTS, voice clone, avatar, video - initialize_default_pricing() runs on every app startup for auto-sync Frontend cost estimation fixes: - Added missing analysisCost, scriptCost, voiceCloneCost to PodcastEstimate type - toPodcastEstimate() now extracts all 7 backend fields (was dropping 3) - headerCostEst maps analysisCost->Analyze, scriptCost->Write, voiceCloneCost->Produce - EstimateCard shows 5 chips: Analysis, Research, Script, Voice(TTS+clone), Visuals(avatar+video) - Chip sum now equals backend total for all configurations Subscription & plan fixes: - Removed Stripe re-verification from checkSubscription() (downgrade regression fix #539) - Added verifyCheckoutRef pattern for reliable mount-time checkout polling - One-time Stripe sync effect with pending_subscription_change flag for Customer Portal returns - Free plan limits: stability_calls 3->10, audio_calls 5->10 (supports 2 podcasts) - Image enforcement uses actual provider (GPT_PROVIDER), not hardcoded Stability - Billing/pricing pages bypass onboarding check in ProtectedRoute - Gradient buttons + loading spinner on plan chip in UserBadge - Added metadata-based Stripe lookup fallback (Issue #538) Documentation: - TESTING_GUIDE.md: comprehensive testing instructions for non-technical testers - Free plan limits, usage tracking, cost estimation formulas - 10 test cases for UI verification - Troubleshooting guide - Quick-reference cost formulas with all default rates Cleanup: removed legacy ToBeMigrated directory (70+ files, ~22K LOC) GSC Brainstorm: service, hook, modal, and UI components for blog topic brainstorming
This commit is contained in:
@@ -90,13 +90,21 @@ const PodcastDashboard: React.FC = () => {
|
||||
}
|
||||
|
||||
if (estimate) {
|
||||
const analyzeCost = breakdownMap.get("Analyze") || 0;
|
||||
const gatherCost = breakdownMap.get("Gather") || 0;
|
||||
const writeCost = breakdownMap.get("Write") || 0;
|
||||
const produceCost = breakdownMap.get("Produce") || 0;
|
||||
if (analyzeCost === 0 && estimate.analysisCost > 0) {
|
||||
breakdownMap.set("Analyze", estimate.analysisCost);
|
||||
}
|
||||
if (gatherCost === 0 && estimate.researchCost > 0) {
|
||||
breakdownMap.set("Gather", estimate.researchCost);
|
||||
}
|
||||
if (writeCost === 0 && estimate.scriptCost > 0) {
|
||||
breakdownMap.set("Write", estimate.scriptCost);
|
||||
}
|
||||
if (produceCost === 0) {
|
||||
breakdownMap.set("Produce", estimate.ttsCost + estimate.avatarCost + estimate.videoCost);
|
||||
breakdownMap.set("Produce", estimate.ttsCost + estimate.voiceCloneCost + estimate.avatarCost + estimate.videoCost);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user