diff --git a/server/src/external/stripe/handleStripeWebhookEvent.ts b/server/src/external/stripe/handleStripeWebhookEvent.ts index 056a479ef..830430bf7 100644 --- a/server/src/external/stripe/handleStripeWebhookEvent.ts +++ b/server/src/external/stripe/handleStripeWebhookEvent.ts @@ -251,6 +251,14 @@ export const handleStripeWebhookEvent = async ({ } } + if ( + process.env.NODE_ENV === "development" && + error instanceof Error && + error.message.includes("No stripe account linked to organization") + ) { + return; + } + logger.error(`Stripe webhook, error: ${error}`, { error }); throw error; } diff --git a/server/src/internal/customers/add-product/initCusEnt.ts b/server/src/internal/customers/add-product/initCusEnt.ts index 42498dff2..ba5c8a412 100644 --- a/server/src/internal/customers/add-product/initCusEnt.ts +++ b/server/src/internal/customers/add-product/initCusEnt.ts @@ -39,9 +39,7 @@ export const initCusEntEntities = ({ : null; for (const entity of entities) { - if (!entitlementLinkedToEntity({ entitlement, entity })) { - continue; - } + if (!entitlementLinkedToEntity({ entitlement, entity })) continue; if ( existingCusEnt && diff --git a/server/src/internal/customers/cusProducts/insertCusProduct/initCusEnt/initNextResetAt.ts b/server/src/internal/customers/cusProducts/insertCusProduct/initCusEnt/initNextResetAt.ts index 768ac0a2b..7260106b1 100644 --- a/server/src/internal/customers/cusProducts/insertCusProduct/initCusEnt/initNextResetAt.ts +++ b/server/src/internal/customers/cusProducts/insertCusProduct/initCusEnt/initNextResetAt.ts @@ -1,16 +1,17 @@ -import { applyTrialToEntitlement } from "@/internal/products/entitlements/entitlementUtils.js"; -import { freeTrialToStripeTimestamp } from "@/internal/products/free-trials/freeTrialUtils.js"; -import { subtractFromUnixTillAligned } from "@/internal/products/prices/billingIntervalUtils.js"; -import { formatUnixToDate } from "@/utils/genUtils.js"; -import { getNextEntitlementReset } from "@/utils/timeUtils.js"; import { - EntInterval, AllowanceType, - EntitlementWithFeature, + BillingInterval, + EntInterval, + type EntitlementWithFeature, FeatureType, - FreeTrial, + type FreeTrial, } from "@autumn/shared"; import { UTCDate } from "@date-fns/utc"; +import { applyTrialToEntitlement } from "@/internal/products/entitlements/entitlementUtils.js"; +import { freeTrialToStripeTimestamp } from "@/internal/products/free-trials/freeTrialUtils.js"; +import { getNextEntitlementReset } from "@/utils/timeUtils.js"; +import { formatUnixToDateTime } from "../../../../../utils/genUtils.js"; +import { getAlignedUnix } from "../../../../products/prices/billingIntervalUtils2.js"; export const initNextResetAt = ({ entitlement, @@ -31,19 +32,17 @@ export const initNextResetAt = ({ if ( entitlement.feature.type === FeatureType.Boolean || entitlement.allowance_type === AllowanceType.Unlimited || - entitlement.interval == EntInterval.Lifetime + entitlement.interval === EntInterval.Lifetime ) { return null; } // 2. If nextResetAt is provided, return it... - if (nextResetAt) { - return nextResetAt; - } + if (nextResetAt) return nextResetAt; // 3. Calculate next reset at... let nextResetAtCalculated = null; - let trialEndTimestamp = trialEndsAt + const trialEndTimestamp = trialEndsAt ? Math.round(trialEndsAt / 1000) : freeTrial ? freeTrialToStripeTimestamp({ freeTrial, now }) @@ -57,7 +56,7 @@ export const initNextResetAt = ({ nextResetAtCalculated = new UTCDate(trialEndTimestamp! * 1000); } - let resetInterval = entitlement.interval as EntInterval; + const resetInterval = entitlement.interval as EntInterval; nextResetAtCalculated = getNextEntitlementReset( nextResetAtCalculated || new UTCDate(now), @@ -65,11 +64,28 @@ export const initNextResetAt = ({ entitlement.interval_count || 1, ).getTime(); + console.log(`--------------------------------`); + console.log(`Interval: `, entitlement.interval); + console.log(`Interval count: `, entitlement.interval_count); + console.log(`Now: `, formatUnixToDateTime(now)); + console.log(`Next reset at: `, formatUnixToDateTime(nextResetAtCalculated)); + console.log(`Anchor to unix: `, formatUnixToDateTime(anchorToUnix)); + // If anchorToUnix, align next reset at to anchorToUnix... - if (anchorToUnix && nextResetAtCalculated) { - nextResetAtCalculated = subtractFromUnixTillAligned({ - targetUnix: anchorToUnix, - originalUnix: nextResetAtCalculated, + if ( + anchorToUnix && + nextResetAtCalculated && + Object.values(BillingInterval).includes( + entitlement.interval as unknown as BillingInterval, + ) + ) { + nextResetAtCalculated = getAlignedUnix({ + anchor: anchorToUnix, + intervalConfig: { + interval: entitlement.interval as unknown as BillingInterval, + intervalCount: entitlement.interval_count || 1, + }, + now, }); } diff --git a/server/tests/utils/stripeUtils/completeInvoiceCheckout.ts b/server/tests/utils/stripeUtils/completeInvoiceCheckout.ts index 7f100bd9d..761eca0c6 100644 --- a/server/tests/utils/stripeUtils/completeInvoiceCheckout.ts +++ b/server/tests/utils/stripeUtils/completeInvoiceCheckout.ts @@ -148,7 +148,7 @@ export const completeInvoiceCheckout = async ({ ); if (postalInput) { await postalInput.click(); - await postalInput.type("123123"); + await postalInput.type("SW59SX"); } } catch (error) { console.log("Could not find postal code input:", error); diff --git a/vite/src/views/products/plan/components/SelectFeatureSheet.tsx b/vite/src/views/products/plan/components/SelectFeatureSheet.tsx index 54166b223..bb7df4b05 100644 --- a/vite/src/views/products/plan/components/SelectFeatureSheet.tsx +++ b/vite/src/views/products/plan/components/SelectFeatureSheet.tsx @@ -30,15 +30,15 @@ export function SelectFeatureSheet({ const setProduct = useProductStore((s) => s.setProduct); const setSheet = useSheetStore((s) => s.setSheet); - // Get feature IDs that are already added to the plan - const addedFeatureIds = new Set( - product.items?.map((item) => item.feature_id).filter(Boolean) || [] - ); + // // Get feature IDs that are already added to the plan + // const addedFeatureIds = new Set( + // product.items?.map((item) => item.feature_id).filter(Boolean) || [] + // ); - // Filter out archived features and features already on the plan - const filteredFeatures = features.filter( - (f: Feature) => !f.archived && !addedFeatureIds.has(f.id) - ); + // // Filter out archived features and features already on the plan + // const filteredFeatures = features.filter( + // (f: Feature) => !f.archived && !addedFeatureIds.has(f.id) + // ); useEffect(() => { // If we're switching from another sheet, open immediately @@ -100,7 +100,7 @@ export function SelectFeatureSheet({
- {filteredFeatures.map((feature: Feature) => ( + {features.map((feature: Feature) => (