Checkout backend actions#56
Conversation
| async function getDefaultPriceId(stripeProductId: string) { | ||
| const product = await stripe.products.retrieve(stripeProductId); | ||
| const defaultPrice = product.default_price; | ||
| if (typeof defaultPrice === "string") return defaultPrice; | ||
| return (defaultPrice as Stripe.Price | null)?.id ?? null; | ||
| } | ||
|
|
There was a problem hiding this comment.
Should actions.ts only be for writes and maybe have a dedicated queries.ts for reads? also maybe we can use this instead?
| const service = await db.query.services.findFirst({ | ||
| where: eq(services.id, serviceId), | ||
| }); |
There was a problem hiding this comment.
| const service = await db.query.services.findFirst({ | ||
| where: eq(services.id, row.serviceId), | ||
| }); |
|
Honestly I would wait until this PR is merged #55, feels like life would be easier, then rebase onto dev |
cac31f8 to
06b0440
Compare
…is branch (services enum, title, description, price, isactive, stripe product id, status). Added relationship of coach id to profile (will discuss). added stripeorderid to servicebookings. stripeorderid to coaching services.
06b0440 to
777721d
Compare
martin0024
left a comment
There was a problem hiding this comment.
Good job thomas.
One concern:
Stripe retries checkout.session.completed regularly imagine if a later state (refund, cancellation) has already moved the row, a retry will re-flip it to confirmed or pending. Scope the update with and(eq(id,…), eq(status, 'awaiting_payment')) please.
| async function getDefaultPriceId(stripeProductId: string) { | ||
| const product = await stripe.products.retrieve(stripeProductId); | ||
| const defaultPrice = product.default_price; | ||
| if (typeof defaultPrice === "string") return defaultPrice; | ||
| return (defaultPrice as Stripe.Price | null)?.id ?? null; | ||
| } |
There was a problem hiding this comment.
| async function getDefaultPriceId(stripeProductId: string) { | |
| const product = await stripe.products.retrieve(stripeProductId); | |
| const defaultPrice = product.default_price; | |
| if (typeof defaultPrice === "string") return defaultPrice; | |
| return (defaultPrice as Stripe.Price | null)?.id ?? null; | |
| } | |
| async function getDefaultPriceId(stripeProductId: string): Promise<string> { | |
| const product = await stripe.products.retrieve(stripeProductId); | |
| const defaultPriceId = product.default_price; | |
| if (!defaultPriceId) { | |
| throw new Error(`Stripe product ${stripeProductId} has no default price`); | |
| } | |
| return defaultPriceId as string; | |
| } |
| params.userId, | ||
| params.email, | ||
| ); | ||
| const origin = (await headers()).get("origin") ?? ""; |
There was a problem hiding this comment.
| const origin = (await headers()).get("origin") ?? ""; | |
| const origin = getRequestOrigin(); |
function getRequestOrigin(): string {
const origin = headers().get("origin");
if (!origin) {
throw new Error("Missing request origin");
}
return origin;
}There was a problem hiding this comment.
A row is inserted with awaiting_payment before the Stripe call. Abandoned checkouts leave permanent orphan rows.
Why does checkoutServiceBooking deletes the booking row if Stripe fails but checkoutCoachingSession does not?
Closes #49
Overview
Implements the backend actions for checking out coaching sessions (private lessons) and service bookings (programs).
Testing
Manual
Checklist
Tip: You can make the issue and then check them after the fact or replace
[ ]with[x]to check it!Notes
{Any issues/suggestions relating to the ticket, repo, assignments, TL duties; please mention here!}