From dd9d15d042d7771b662456ded80acfc8ca374388 Mon Sep 17 00:00:00 2001 From: m5r Date: Sat, 2 Oct 2021 00:19:06 +0200 Subject: [PATCH] always create new subscription --- app/api/debug/cancel-subscription.ts | 4 +- app/api/debug/get-payments.ts | 29 ++++ app/api/debug/get-subscription.ts | 18 +++ .../api/queue/subscription-created.ts | 65 +++----- .../components/billing/billing-history.tsx | 140 +++++++++--------- app/settings/pages/settings/billing.tsx | 47 +++--- app/settings/queries/get-subscription.ts | 9 +- 7 files changed, 169 insertions(+), 143 deletions(-) create mode 100644 app/api/debug/get-payments.ts create mode 100644 app/api/debug/get-subscription.ts diff --git a/app/api/debug/cancel-subscription.ts b/app/api/debug/cancel-subscription.ts index e2f683d..5c803d2 100644 --- a/app/api/debug/cancel-subscription.ts +++ b/app/api/debug/cancel-subscription.ts @@ -1,7 +1,7 @@ import type { BlitzApiHandler } from "blitz"; -import { cancelPaddleSubscription } from "../../../integrations/paddle"; -import appLogger from "../../../integrations/logger"; +import { cancelPaddleSubscription } from "integrations/paddle"; +import appLogger from "integrations/logger"; const logger = appLogger.child({ route: "/api/debug/cancel-subscription" }); diff --git a/app/api/debug/get-payments.ts b/app/api/debug/get-payments.ts new file mode 100644 index 0000000..35d28d0 --- /dev/null +++ b/app/api/debug/get-payments.ts @@ -0,0 +1,29 @@ +import type { BlitzApiHandler } from "blitz"; + +import { getPayments } from "integrations/paddle"; +import appLogger from "integrations/logger"; +import db from "db"; + +const logger = appLogger.child({ route: "/api/debug/cancel-subscription" }); + +const cancelSubscriptionHandler: BlitzApiHandler = async (req, res) => { + const { organizationId } = req.body; + + logger.debug(`fetching payments for organizationId="${organizationId}"`); + const subscriptions = await db.subscription.findMany({ where: { organizationId } }); + if (subscriptions.length === 0) { + res.status(200).send([]); + } + console.log("subscriptions", subscriptions); + + const paymentsBySubscription = await Promise.all( + subscriptions.map((subscription) => getPayments({ subscriptionId: subscription.paddleSubscriptionId })), + ); + const payments = paymentsBySubscription.flat(); + const result = Array.from(payments).sort((a, b) => b.payout_date.localeCompare(a.payout_date)); + logger.debug(result); + + res.status(200).send(result); +}; + +export default cancelSubscriptionHandler; diff --git a/app/api/debug/get-subscription.ts b/app/api/debug/get-subscription.ts new file mode 100644 index 0000000..d3c9652 --- /dev/null +++ b/app/api/debug/get-subscription.ts @@ -0,0 +1,18 @@ +import type { BlitzApiHandler } from "blitz"; + +import db from "db"; +import appLogger from "integrations/logger"; + +const logger = appLogger.child({ route: "/api/debug/get-subscription" }); + +const cancelSubscriptionHandler: BlitzApiHandler = async (req, res) => { + const { organizationId } = req.body; + + logger.debug(`fetching subscription for organizationId="${organizationId}"`); + const subscription = await db.subscription.findFirst({ where: { organizationId } }); + console.debug(subscription); + + res.status(200).send(subscription); +}; + +export default cancelSubscriptionHandler; diff --git a/app/settings/api/queue/subscription-created.ts b/app/settings/api/queue/subscription-created.ts index 5aab521..9fd76a8 100644 --- a/app/settings/api/queue/subscription-created.ts +++ b/app/settings/api/queue/subscription-created.ts @@ -30,34 +30,27 @@ export const subscriptionCreatedQueue = Queue("api/queue/subscription-c const orgOwner = organization.memberships.find((membership) => membership.role === MembershipRole.OWNER); const email = orgOwner!.user!.email; - const paddleCheckoutId = event.checkoutId; - const paddleSubscriptionId = event.subscriptionId; - const planId = event.productId; - const nextBillDate = event.nextPaymentDate; - const status = translateSubscriptionStatus(event.status); - const lastEventTime = event.eventTime; - const updateUrl = event.updateUrl; - const cancelUrl = event.cancelUrl; - const currency = event.currency; - const unitPrice = event.unitPrice; + await db.organization.update({ + where: { id: organizationId }, + data: { + subscription: { + create: { + paddleSubscriptionId: event.subscriptionId, + paddlePlanId: event.productId, + paddleCheckoutId: event.checkoutId, + nextBillDate: event.nextPaymentDate, + status: translateSubscriptionStatus(event.status), + lastEventTime: event.eventTime, + updateUrl: event.updateUrl, + cancelUrl: event.cancelUrl, + currency: event.currency, + unitPrice: event.unitPrice, + }, + }, + }, + }); if (!!organization.subscription) { - await db.subscription.update({ - where: { paddleSubscriptionId: organization.subscription.paddleSubscriptionId }, - data: { - paddleSubscriptionId, - paddlePlanId: planId, - paddleCheckoutId, - nextBillDate, - status, - lastEventTime, - updateUrl, - cancelUrl, - currency, - unitPrice, - }, - }); - sendEmail({ subject: "Welcome back to Shellphone", body: "Welcome back to Shellphone", @@ -66,26 +59,6 @@ export const subscriptionCreatedQueue = Queue("api/queue/subscription-c logger.error(error); }); } else { - await db.organization.update({ - where: { id: organizationId }, - data: { - subscription: { - create: { - paddleSubscriptionId, - paddlePlanId: planId, - paddleCheckoutId, - nextBillDate, - status, - lastEventTime, - updateUrl, - cancelUrl, - currency, - unitPrice, - }, - }, - }, - }); - sendEmail({ subject: "Welcome to Shellphone", body: `Welcome to Shellphone`, diff --git a/app/settings/components/billing/billing-history.tsx b/app/settings/components/billing/billing-history.tsx index 65087fc..956ea7b 100644 --- a/app/settings/components/billing/billing-history.tsx +++ b/app/settings/components/billing/billing-history.tsx @@ -3,76 +3,78 @@ import useSubscription from "../../hooks/use-subscription"; export default function BillingHistory() { const { payments } = useSubscription(); + if (payments.length === 0) { + return null; + } + return ( -
-
-
-

Billing history

-
-
-
-
-
- - - - - - - - - - - {typeof payments !== "undefined" - ? payments.map((payment) => ( - - - - - - - )) - : null} - -
- Date - - Amount - - Status - - View receipt -
- - - {payment.amount} {payment.currency} - - {payment.is_paid === 1 ? "Paid" : "Upcoming"} - - {typeof payment.receipt_url !== "undefined" ? ( - - View receipt - - ) : null} -
-
+
+
+

Billing history

+
+
+
+
+
+ + + + + + + + + + + {typeof payments !== "undefined" + ? payments.map((payment) => ( + + + + + + + )) + : null} + +
+ Date + + Amount + + Status + + View receipt +
+ + + {payment.amount} {payment.currency} + + {payment.is_paid === 1 ? "Paid" : "Upcoming"} + + {typeof payment.receipt_url !== "undefined" ? ( + + View receipt + + ) : null} +
diff --git a/app/settings/pages/settings/billing.tsx b/app/settings/pages/settings/billing.tsx index ceae33a..d2b3edd 100644 --- a/app/settings/pages/settings/billing.tsx +++ b/app/settings/pages/settings/billing.tsx @@ -31,37 +31,36 @@ const Billing: BlitzPage = (props) => { */ useRequireOnboarding(); - const { subscription, cancelSubscription, updatePaymentMethod } = useSubscription({ + const { subscription, cancelSubscription, updatePaymentMethod, payments } = useSubscription({ initialData: props.subscription, }); - if (!subscription) { - return ( - <> - -

Prices include all applicable sales taxes.

- - ); - } - return ( <> - - updatePaymentMethod({ updateUrl: subscription.updateUrl })} - text="Update payment method" - /> - cancelSubscription({ cancelUrl: subscription.cancelUrl })} - text="Cancel subscription" - /> - + {subscription ? ( + +

Current plan: {subscription.paddlePlanId}

- + updatePaymentMethod({ updateUrl: subscription.updateUrl })} + text="Update payment method" + /> + cancelSubscription({ cancelUrl: subscription.cancelUrl })} + text="Cancel subscription" + /> +
+ ) : null} -
- -
+ {payments.length > 0 ? ( + <> + + +
+ +
+ + ) : null}

Prices include all applicable sales taxes.

diff --git a/app/settings/queries/get-subscription.ts b/app/settings/queries/get-subscription.ts index b11d9bc..0fc9f39 100644 --- a/app/settings/queries/get-subscription.ts +++ b/app/settings/queries/get-subscription.ts @@ -1,9 +1,14 @@ import { resolver } from "blitz"; -import db from "db"; +import db, { SubscriptionStatus } from "db"; export default resolver.pipe(resolver.authorize(), async (_ = null, { session }) => { if (!session.orgId) return null; - return db.subscription.findFirst({ where: { organizationId: session.orgId } }); + return db.subscription.findFirst({ + where: { + organizationId: session.orgId, + status: { not: SubscriptionStatus.deleted }, + }, + }); });