diff --git a/server/src/internal/billing/v2/actions/createSchedule/setup/setupCreateScheduleBillingContext.ts b/server/src/internal/billing/v2/actions/createSchedule/setup/setupCreateScheduleBillingContext.ts
index aba87f078..13ba640be 100644
--- a/server/src/internal/billing/v2/actions/createSchedule/setup/setupCreateScheduleBillingContext.ts
+++ b/server/src/internal/billing/v2/actions/createSchedule/setup/setupCreateScheduleBillingContext.ts
@@ -7,9 +7,13 @@ import {
type MultiAttachParamsV0,
} from "@autumn/shared";
import type { AutumnContext } from "@/honoUtils/HonoEnv";
+import { setupAnchorResetRefund } from "@/internal/billing/v2/setup/setupAnchorResetRefund";
+import { setupBillingCycleAnchor } from "@/internal/billing/v2/setup/setupBillingCycleAnchor";
+import { setupResetCycleAnchor } from "@/internal/billing/v2/setup/setupResetCycleAnchor";
import { setupImmediateMultiProductBillingContext } from "../../common/immediateMultiProduct/setupImmediateMultiProductBillingContext";
import { normalizeCreateSchedulePhases } from "../errors/normalizeCreateSchedulePhases";
import { validateCreateSchedulePhasePlans } from "../errors/validateCreateSchedulePhasePlans";
+import { billingContextToRecurringAndScheduled } from "../utils/billingContextToRecurringAndScheduled";
import { setupScheduledProductsContext } from "./setupScheduledProductsContext";
type CreateScheduleCheckoutModeContext = Pick<
@@ -115,7 +119,7 @@ export const setupCreateScheduleBillingContext = async ({
),
);
- return {
+ const scheduleBillingContext: CreateScheduleBillingContext = {
...billingContext,
checkoutMode: setupCreateScheduleCheckoutMode({
billingContext,
@@ -133,8 +137,54 @@ export const setupCreateScheduleBillingContext = async ({
billingContext.isCustom ||
scheduledCustomPrices.length > 0 ||
scheduledCustomEntitlements.length > 0,
+ requestedProrationBehavior: params.billing_behavior,
+ requestedBillingCycleAnchor: params.billing_cycle_anchor,
immediatePhase,
futurePhases,
scheduledPhaseContexts,
};
+
+ const { recurringActive } = billingContextToRecurringAndScheduled({
+ billingContext: scheduleBillingContext,
+ });
+
+ // setupImmediateMultiProductBillingContext does not forward
+ // `billing_cycle_anchor`, so billingCycleAnchorMs still reflects the existing
+ // Stripe anchor. When the caller asks to reset the cycle we must recompute
+ // the anchor (and the reset-cycle anchor) so downstream proration math runs
+ // against the new `[now, now + interval]` period. Mirrors the attach /
+ // updateSubscription setups.
+ if (params.billing_cycle_anchor !== undefined) {
+ const firstProduct = billingContext.fullProducts[0];
+ if (firstProduct) {
+ let recomputedAnchor = setupBillingCycleAnchor({
+ stripeSubscription: billingContext.stripeSubscription,
+ customerProduct: recurringActive[0],
+ newFullProduct: firstProduct,
+ trialContext: billingContext.trialContext,
+ currentEpochMs: billingContext.currentEpochMs,
+ requestedBillingCycleAnchor: params.billing_cycle_anchor,
+ });
+ if (billingContext.trialContext?.trialEndsAt) {
+ recomputedAnchor = billingContext.trialContext.trialEndsAt;
+ }
+ scheduleBillingContext.billingCycleAnchorMs = recomputedAnchor;
+ scheduleBillingContext.resetCycleAnchorMs = setupResetCycleAnchor({
+ billingCycleAnchorMs: recomputedAnchor,
+ customerProduct: undefined,
+ newFullProduct: firstProduct,
+ });
+ }
+ }
+
+ // Keep forward-looking charges (e.g. prepaid renewals) when the caller asks
+ // to reset the cycle with proration off; without this, finalizeLineItems
+ // drops every line item and total due now collapses to 0.
+ scheduleBillingContext.anchorResetRefund = setupAnchorResetRefund({
+ billingCycleAnchor: params.billing_cycle_anchor,
+ prorationBehavior: params.billing_behavior,
+ outgoingCustomerProduct: recurringActive[0],
+ });
+
+ return scheduleBillingContext;
};
diff --git a/shared/api/billing/createSchedule/createScheduleParamsV0.ts b/shared/api/billing/createSchedule/createScheduleParamsV0.ts
index 51e9eabac..f9f15851a 100644
--- a/shared/api/billing/createSchedule/createScheduleParamsV0.ts
+++ b/shared/api/billing/createSchedule/createScheduleParamsV0.ts
@@ -4,6 +4,8 @@ import { RedirectModeSchema } from "@api/billing/common/redirectMode";
import { BasePriceParamsSchema } from "@api/products/components/basePrice/basePrice";
import { CreatePlanItemParamsV1Schema } from "@api/products/items/crud/createPlanItemParamsV1";
import { z } from "zod/v4";
+import { BillingBehaviorSchema } from "../common/billingBehavior";
+import { BillingCycleAnchorSchema } from "../common/billingCycleAnchor";
const CreateScheduleCustomizePlanSchema = z
.object({
@@ -81,6 +83,14 @@ export const CreateScheduleParamsV0Schema = z
description:
"Controls when to return a checkout URL for the immediate phase. 'always' forces a confirmation or checkout flow, 'if_required' only redirects when needed, and 'never' disables redirects.",
}),
+ billing_behavior: BillingBehaviorSchema.optional().meta({
+ description:
+ "Whether to prorate the immediate phase. 'none' skips proration charges and credits.",
+ }),
+ billing_cycle_anchor: BillingCycleAnchorSchema.optional().meta({
+ description:
+ "Pass 'now' to reset the billing cycle anchor of the immediate phase to the current time.",
+ }),
phases: z
.tuple([CreateSchedulePhaseSchema])
.rest(CreateSchedulePhaseSchema)
diff --git a/vite/src/components/forms/attach-v2/components/AttachProductSelection.tsx b/vite/src/components/forms/attach-v2/components/AttachProductSelection.tsx
index bebe1c673..59a228a1a 100644
--- a/vite/src/components/forms/attach-v2/components/AttachProductSelection.tsx
+++ b/vite/src/components/forms/attach-v2/components/AttachProductSelection.tsx
@@ -3,17 +3,15 @@ import {
isProductCurrentlyAttached,
} from "@autumn/shared";
import { useProductsQuery } from "@/hooks/queries/useProductsQuery";
-import { useEntity } from "@/hooks/stores/useSubscriptionStore";
import { useCusQuery } from "@/views/customers/customer/hooks/useCusQuery";
import { useAttachFormContext } from "../context/AttachFormProvider";
export function AttachProductSelection() {
- const { form, hasCustomizations } = useAttachFormContext();
+ const { form, hasCustomizations, entityId } = useAttachFormContext();
const { products } = useProductsQuery();
const availableProducts = products.filter((p) => !p.archived);
const { customer } = useCusQuery();
- const { entityId } = useEntity();
const productId = form.state.values.productId;
diff --git a/vite/src/components/forms/attach-v2/context/AttachFormProvider.tsx b/vite/src/components/forms/attach-v2/context/AttachFormProvider.tsx
index ca992b98c..c38491e8f 100644
--- a/vite/src/components/forms/attach-v2/context/AttachFormProvider.tsx
+++ b/vite/src/components/forms/attach-v2/context/AttachFormProvider.tsx
@@ -59,6 +59,9 @@ interface AttachFormContextValue {
formValues: AttachForm;
features: Feature[];
+ entityId: string | undefined;
+ onScopeChange?: (entityId: string | undefined) => void;
+
product: ProductV2 | undefined;
prepaidItems: PrepaidItemWithFeature[];
originalItems: ProductItem[] | undefined;
@@ -103,6 +106,7 @@ interface AttachFormProviderProps {
onPlanEditorClose?: () => void;
onCheckoutRedirect?: (checkoutUrl: string) => void;
onSuccess?: () => void;
+ onScopeChange?: (entityId: string | undefined) => void;
initialSchedulePlan?: SchedulePlan | null;
disablePreview?: boolean;
children: ReactNode;
@@ -135,6 +139,7 @@ export function AttachFormProvider({
onPlanEditorClose,
onCheckoutRedirect,
onSuccess,
+ onScopeChange,
initialSchedulePlan,
disablePreview,
children,
@@ -472,6 +477,8 @@ export function AttachFormProvider({
form,
formValues,
features,
+ entityId,
+ onScopeChange,
product: effectiveProduct,
prepaidItems,
originalItems,
@@ -496,6 +503,8 @@ export function AttachFormProvider({
form,
formValues,
features,
+ entityId,
+ onScopeChange,
effectiveProduct,
prepaidItems,
originalItems,
diff --git a/vite/src/components/forms/create-schedule/components/CreateScheduleAdvancedSection.tsx b/vite/src/components/forms/create-schedule/components/CreateScheduleAdvancedSection.tsx
new file mode 100644
index 000000000..241e554a4
--- /dev/null
+++ b/vite/src/components/forms/create-schedule/components/CreateScheduleAdvancedSection.tsx
@@ -0,0 +1,67 @@
+import type { ReactNode } from "react";
+import {
+ AdvancedSection,
+ ConfigRow,
+} from "@/components/forms/shared/advanced-section";
+import { Switch } from "@/components/ui/switch";
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/components/v2/tooltips/Tooltip";
+import { useCreateScheduleFormContext } from "../context/CreateScheduleFormProvider";
+
+export function CreateScheduleAdvancedSection() {
+ const { form, formValues } = useCreateScheduleFormContext();
+ const { billingBehavior, resetBillingCycle, phases } = formValues;
+
+ const isProrate = billingBehavior !== "none";
+ const hasMultipleImmediatePlans = (phases[0]?.plans.length ?? 0) > 1;
+ const disabledReason = hasMultipleImmediatePlans
+ ? "Not yet supported for multi attach"
+ : null;
+
+ const renderToggle = ({
+ checked,
+ onCheckedChange,
+ }: {
+ checked: boolean;
+ onCheckedChange: (checked: boolean) => void;
+ }): ReactNode => (
+
+
+
+
+
+
+ {disabledReason && {disabledReason}}
+
+ );
+
+ return (
+
+
+ form.setFieldValue("billingBehavior", checked ? null : "none"),
+ })}
+ />
+
+ form.setFieldValue("resetBillingCycle", !!checked),
+ })}
+ />
+
+ );
+}
diff --git a/vite/src/components/forms/create-schedule/components/CreateScheduleSheetContent.tsx b/vite/src/components/forms/create-schedule/components/CreateScheduleSheetContent.tsx
index 1083aa403..c4aee4977 100644
--- a/vite/src/components/forms/create-schedule/components/CreateScheduleSheetContent.tsx
+++ b/vite/src/components/forms/create-schedule/components/CreateScheduleSheetContent.tsx
@@ -18,6 +18,7 @@ import { cn } from "@/lib/utils";
import { useCusQuery } from "@/views/customers/customer/hooks/useCusQuery";
import { useCreateScheduleFormContext } from "../context/CreateScheduleFormProvider";
import { useHasSchedule } from "../hooks/useHasSchedule";
+import { CreateScheduleAdvancedSection } from "./CreateScheduleAdvancedSection";
import { SchedulePhaseCard } from "./SchedulePhaseCard";
import { SchedulePreview } from "./SchedulePreview";
@@ -182,6 +183,7 @@ export function CreateScheduleReviewContent() {
/>
+
diff --git a/vite/src/components/forms/create-schedule/context/CreateScheduleFormProvider.tsx b/vite/src/components/forms/create-schedule/context/CreateScheduleFormProvider.tsx
index 5a062d0e7..b55cfab96 100644
--- a/vite/src/components/forms/create-schedule/context/CreateScheduleFormProvider.tsx
+++ b/vite/src/components/forms/create-schedule/context/CreateScheduleFormProvider.tsx
@@ -140,6 +140,16 @@ export function CreateScheduleFormProvider({
[form.store],
);
+ const getBillingBehavior = useCallback(
+ () => form.store.state.values.billingBehavior ?? null,
+ [form.store],
+ );
+
+ const getResetBillingCycle = useCallback(
+ () => form.store.state.values.resetBillingCycle ?? false,
+ [form.store],
+ );
+
const buildRequestBody = useBuildCreateScheduleRequestBody({
customerId,
entityId,
@@ -147,6 +157,8 @@ export function CreateScheduleFormProvider({
features,
nowMs,
getPhases,
+ getBillingBehavior,
+ getResetBillingCycle,
});
const previewRequestBody = useCreateScheduleRequestBody({
@@ -156,6 +168,8 @@ export function CreateScheduleFormProvider({
products,
features,
nowMs,
+ billingBehavior: formValues.billingBehavior,
+ resetBillingCycle: formValues.resetBillingCycle,
});
const phaseTimingError = useMemo(
diff --git a/vite/src/components/forms/create-schedule/createScheduleFormSchema.ts b/vite/src/components/forms/create-schedule/createScheduleFormSchema.ts
index 971594220..ff4952834 100644
--- a/vite/src/components/forms/create-schedule/createScheduleFormSchema.ts
+++ b/vite/src/components/forms/create-schedule/createScheduleFormSchema.ts
@@ -1,4 +1,4 @@
-import type { ProductItem } from "@autumn/shared";
+import { BillingBehaviorSchema, type ProductItem } from "@autumn/shared";
import { z } from "zod/v4";
export const SchedulePlanSchema = z.object({
@@ -169,6 +169,8 @@ export function getPhaseTimingError({
export const CreateScheduleFormSchema = z
.object({
phases: z.array(SchedulePhaseSchema).min(1),
+ billingBehavior: BillingBehaviorSchema.nullable(),
+ resetBillingCycle: z.boolean(),
})
.refine(
(data) =>
diff --git a/vite/src/components/forms/create-schedule/hooks/useCreateScheduleForm.ts b/vite/src/components/forms/create-schedule/hooks/useCreateScheduleForm.ts
index fb1417898..a8d231b5d 100644
--- a/vite/src/components/forms/create-schedule/hooks/useCreateScheduleForm.ts
+++ b/vite/src/components/forms/create-schedule/hooks/useCreateScheduleForm.ts
@@ -13,6 +13,8 @@ export function useCreateScheduleForm({
} = {}) {
const defaultValues: CreateScheduleForm = initialValues ?? {
phases: [{ startsAt: null, plans: [{ ...EMPTY_SCHEDULE_PLAN }] }],
+ billingBehavior: null,
+ resetBillingCycle: false,
};
const initialValuesRef = useRef(defaultValues);
diff --git a/vite/src/components/forms/create-schedule/hooks/useCreateScheduleRequestBody.ts b/vite/src/components/forms/create-schedule/hooks/useCreateScheduleRequestBody.ts
index 3a96842f0..701b52b0e 100644
--- a/vite/src/components/forms/create-schedule/hooks/useCreateScheduleRequestBody.ts
+++ b/vite/src/components/forms/create-schedule/hooks/useCreateScheduleRequestBody.ts
@@ -1,5 +1,6 @@
import type {
ApiPlanItemV1,
+ BillingBehavior,
CreateScheduleParamsV0,
Feature,
ProductItem,
@@ -110,6 +111,8 @@ export function buildCreateScheduleRequestBody({
products,
features,
nowMs,
+ billingBehavior,
+ resetBillingCycle,
}: {
customerId: string | undefined;
entityId: string | undefined;
@@ -117,6 +120,8 @@ export function buildCreateScheduleRequestBody({
products: ProductV2[];
features: Feature[];
nowMs?: number;
+ billingBehavior?: BillingBehavior | null;
+ resetBillingCycle?: boolean;
}): CreateScheduleParamsV0 | null {
const now = nowMs ?? Date.now();
if (!customerId || phases.length === 0) return null;
@@ -164,6 +169,17 @@ export function buildCreateScheduleRequestBody({
phases: validPhases,
};
if (entityId) body.entity_id = entityId;
+
+ // `billing_behavior` / `billing_cycle_anchor` aren't supported when the
+ // immediate phase is a multi-attach. The review UI disables the toggles in
+ // that case; mirror the same guard here so stale values don't leak into the
+ // request if the user flips from single-plan to multi-plan after toggling.
+ const immediatePlanCount = validPhases[0]?.plans.length ?? 0;
+ const supportsBillingFlags = immediatePlanCount === 1;
+ if (supportsBillingFlags) {
+ if (billingBehavior) body.billing_behavior = billingBehavior;
+ if (resetBillingCycle) body.billing_cycle_anchor = "now";
+ }
return body as CreateScheduleParamsV0;
}
@@ -174,6 +190,8 @@ export function useCreateScheduleRequestBody({
products,
features,
nowMs,
+ billingBehavior,
+ resetBillingCycle,
}: {
customerId: string | undefined;
entityId: string | undefined;
@@ -181,6 +199,8 @@ export function useCreateScheduleRequestBody({
products: ProductV2[];
features: Feature[];
nowMs?: number;
+ billingBehavior?: BillingBehavior | null;
+ resetBillingCycle?: boolean;
}) {
return useMemo(
() =>
@@ -191,8 +211,19 @@ export function useCreateScheduleRequestBody({
products,
features,
nowMs,
+ billingBehavior,
+ resetBillingCycle,
}),
- [customerId, entityId, phases, products, features, nowMs],
+ [
+ customerId,
+ entityId,
+ phases,
+ products,
+ features,
+ nowMs,
+ billingBehavior,
+ resetBillingCycle,
+ ],
);
}
@@ -203,6 +234,8 @@ export function useBuildCreateScheduleRequestBody({
features,
nowMs,
getPhases,
+ getBillingBehavior,
+ getResetBillingCycle,
}: {
customerId: string | undefined;
entityId: string | undefined;
@@ -210,6 +243,8 @@ export function useBuildCreateScheduleRequestBody({
features: Feature[];
nowMs?: number;
getPhases: () => SchedulePhase[];
+ getBillingBehavior?: () => BillingBehavior | null;
+ getResetBillingCycle?: () => boolean;
}) {
return useMemo(
() =>
@@ -229,6 +264,8 @@ export function useBuildCreateScheduleRequestBody({
products,
features,
nowMs,
+ billingBehavior: getBillingBehavior?.() ?? null,
+ resetBillingCycle: getResetBillingCycle?.() ?? false,
});
if (!requestBody) return null;
@@ -246,6 +283,15 @@ export function useBuildCreateScheduleRequestBody({
return requestBody;
},
- [customerId, entityId, products, features, nowMs, getPhases],
+ [
+ customerId,
+ entityId,
+ products,
+ features,
+ nowMs,
+ getPhases,
+ getBillingBehavior,
+ getResetBillingCycle,
+ ],
);
}
diff --git a/vite/src/components/v2/inline-custom-plan-editor/PlanEditorContext.tsx b/vite/src/components/v2/inline-custom-plan-editor/PlanEditorContext.tsx
index 263ca5eb3..9e0a9a0aa 100644
--- a/vite/src/components/v2/inline-custom-plan-editor/PlanEditorContext.tsx
+++ b/vite/src/components/v2/inline-custom-plan-editor/PlanEditorContext.tsx
@@ -227,16 +227,12 @@ export function useHasItemChanges() {
item1: itemDraft.session.draftItem,
item2: itemDraft.session.initialItem,
features,
- logDifferences: true,
});
return !same;
}
if (!item || !initialItem) {
- console.log(
- "[useHasItemChanges] no item or initialItem, returning false",
- );
return false;
}
@@ -244,7 +240,6 @@ export function useHasItemChanges() {
item1: item,
item2: initialItem,
features,
- logDifferences: true,
});
return !same;
diff --git a/vite/src/hooks/useSheetScopeEntityId.ts b/vite/src/hooks/useSheetScopeEntityId.ts
new file mode 100644
index 000000000..573372414
--- /dev/null
+++ b/vite/src/hooks/useSheetScopeEntityId.ts
@@ -0,0 +1,34 @@
+import { CusProductStatus, type FullCustomer } from "@autumn/shared";
+import { useMemo, useState } from "react";
+
+// If the customer has no active customer-level plan but has at least one
+// active entity-level plan, default scope to that entity. Otherwise stay
+// customer-scoped.
+function pickDefaultScopeEntityId({
+ customer,
+}: {
+ customer: FullCustomer | undefined;
+}): string | undefined {
+ const activePlans =
+ customer?.customer_products?.filter(
+ (cp) => cp.status === CusProductStatus.Active && !cp.canceled_at,
+ ) ?? [];
+
+ if (activePlans.some((cp) => !cp.entity_id)) return undefined;
+ return activePlans.find((cp) => !!cp.entity_id)?.entity_id ?? undefined;
+}
+
+// Sheet-local scope state for Attach / Create Schedule flows. Seeds from the
+// `entity_id` URL param if present, otherwise applies the smart default based
+// on the customer's existing plans. Changes stay local to the sheet.
+export function useSheetScopeEntityId(customer: FullCustomer | undefined) {
+ const initialFromUrl = useMemo(
+ () =>
+ new URLSearchParams(window.location.search).get("entity_id") ?? undefined,
+ [],
+ );
+
+ return useState(
+ initialFromUrl ?? pickDefaultScopeEntityId({ customer }),
+ );
+}
diff --git a/vite/src/views/customers2/components/sheets/AttachProductSheet.tsx b/vite/src/views/customers2/components/sheets/AttachProductSheet.tsx
index 6c4c173af..e5474067a 100644
--- a/vite/src/views/customers2/components/sheets/AttachProductSheet.tsx
+++ b/vite/src/views/customers2/components/sheets/AttachProductSheet.tsx
@@ -35,7 +35,7 @@ import {
} from "@/components/v2/sheets/SharedSheetComponents";
import { useOrgStripeQuery } from "@/hooks/queries/useOrgStripeQuery";
import { useSheetStore } from "@/hooks/stores/useSheetStore";
-import { useEntity } from "@/hooks/stores/useSubscriptionStore";
+import { useSheetScopeEntityId } from "@/hooks/useSheetScopeEntityId";
import { useEnv } from "@/utils/envUtils";
import { getBackendErr } from "@/utils/genUtils";
import { useCusQuery } from "@/views/customers/customer/hooks/useCusQuery";
@@ -205,12 +205,11 @@ function PlanDiffSkeleton() {
}
function SelectContent() {
- const { formValues } = useAttachFormContext();
+ const { formValues, entityId, onScopeChange } = useAttachFormContext();
const { closeSheet, setSheet } = useSheetStore();
const itemId = useSheetStore((s) => s.itemId);
const hasProductSelected = !!formValues.productId;
- const { entityId, setEntityId } = useEntity();
const { customer } = useCusQuery();
const fullCustomer = customer as FullCustomer | null;
const entities = fullCustomer?.entities || [];
@@ -247,7 +246,9 @@ function SelectContent() {
value={entityId ?? CUSTOMER_LEVEL_VALUE}
onValueChange={(value) =>
- setEntityId(value === CUSTOMER_LEVEL_VALUE ? null : value)
+ onScopeChange?.(
+ value === CUSTOMER_LEVEL_VALUE ? undefined : value,
+ )
}
options={entityOptions}
getOptionValue={getEntityOptionValue}
@@ -460,12 +461,14 @@ export function AttachProductSheet() {
const { closeSheet } = useSheetStore();
const { customer } = useCusQuery();
const { setIsInlineEditorOpen } = useCustomerContext();
- const { entityId } = useEntity();
+ const [scopeEntityId, setScopeEntityId] = useSheetScopeEntityId(
+ customer as FullCustomer | undefined,
+ );
return (
setIsInlineEditorOpen(true)}
onPlanEditorClose={() => setIsInlineEditorOpen(false)}
@@ -474,6 +477,7 @@ export function AttachProductSheet() {
toast.success("Checkout URL copied to clipboard");
}}
onSuccess={closeSheet}
+ onScopeChange={setScopeEntityId}
>
diff --git a/vite/src/views/customers2/components/sheets/CreateScheduleSheet.tsx b/vite/src/views/customers2/components/sheets/CreateScheduleSheet.tsx
index 709c511b0..92f73cb9b 100644
--- a/vite/src/views/customers2/components/sheets/CreateScheduleSheet.tsx
+++ b/vite/src/views/customers2/components/sheets/CreateScheduleSheet.tsx
@@ -6,7 +6,7 @@ import type {
} from "@autumn/shared";
import { CusProductStatus, mapToProductItems } from "@autumn/shared";
import { motion } from "motion/react";
-import { useMemo, useRef, useState } from "react";
+import { useMemo, useRef } from "react";
import { toast } from "sonner";
import {
AttachFormProvider,
@@ -43,6 +43,7 @@ import {
import { useOrgStripeQuery } from "@/hooks/queries/useOrgStripeQuery";
import { useProductsQuery } from "@/hooks/queries/useProductsQuery";
import { useSheetStore } from "@/hooks/stores/useSheetStore";
+import { useSheetScopeEntityId } from "@/hooks/useSheetScopeEntityId";
import { backendToDisplayQuantity } from "@/utils/billing/prepaidQuantityUtils";
import { useEnv } from "@/utils/envUtils";
import { useCusQuery } from "@/views/customers/customer/hooks/useCusQuery";
@@ -142,6 +143,8 @@ export function buildInitialValues({
: { ...EMPTY_SCHEDULE_PLAN };
}),
})),
+ billingBehavior: null,
+ resetBillingCycle: false,
};
}
@@ -164,6 +167,8 @@ export function buildInitialValues({
activePlans.length > 0 ? activePlans : [{ ...EMPTY_SCHEDULE_PLAN }],
},
],
+ billingBehavior: null,
+ resetBillingCycle: false,
};
}
@@ -360,15 +365,10 @@ export function getScheduleForScope({
export function CreateScheduleSheet() {
const { closeSheet } = useSheetStore();
const { customer, testClockFrozenTimeMs } = useCusQuery({ schedule: true });
- const initialEntityId =
- new URLSearchParams(window.location.search).get("entity_id") ?? undefined;
- const [scopeEntityId, setScopeEntityId] = useState(
- initialEntityId,
- );
+ const fullCustomer = customer as FullCustomer | undefined;
+ const [scopeEntityId, setScopeEntityId] = useSheetScopeEntityId(fullCustomer);
const { products } = useProductsQuery();
-
- const fullCustomer = customer as FullCustomer | undefined;
const schedule = getScheduleForScope({
customer: fullCustomer,
entityId: scopeEntityId,