-
Notifications
You must be signed in to change notification settings - Fork 210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(next): Update success page, add latest invoice to cart data #17850
base: main
Are you sure you want to change the base?
Conversation
@@ -1,8 +1,8 @@ | |||
next-payment-confirmation-thanks-heading = Thank you! | |||
next-payment-confirmation-thanks-heading = Thanks, now check your email! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can re-use the string below (just add the next-
prefix).
payment-confirmation-thanks-heading-account-exists = Thanks, now check your email!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be happy to update it! Does re-using the string with an added next-
prefix help improve translations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding the next-
prefix helps us keep track of which strings already have translations. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a bit of additional context to what Lisa mentioned. The intention is to reuse translations from SP2.0 in SP3.0, i.e. copy strings from payments.ftl
into payments-next.ftl
. The way the reusable strings are currently identified is by prefixing the id's with next-
.
# $email (String) - The user's email. | ||
# $product_name (String) - The name of the subscribed product. | ||
next-payment-confirmation-thanks-subheading = A confirmation email has been sent to { $email } with details on how to get started with { $product_name }. | ||
next-payment-confirmation-thanks-subheading = You'll receive an email at { $email } with instructions about your subscription, as well as your payment details. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can re-use this fluent ID with the next-
prefix as well:
# $email (string) - The user's email.
payment-confirmation-thanks-subheading-account-exists = You’ll receive an email at { $email } with instructions for setting up your account, as well as your payment details.
Also, just so you're aware, we use smart characters (at least that's what I think they're called?) in ftl strings, eg:
’
instead of'
…
instead of...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the note about the smart characters! I am not sure I understand about the fluent id re-use though, the two strings are similar, but not the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aah, I didn't catch that the sentence changed at the end! Apologies, this would require a new fluent id.
|
||
if (!paymentMethodId) return latestInvoiceDTO; | ||
|
||
const paymentMethod = await this.stripeClient.paymentMethodRetrieve( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Services" should not call "Clients" directly. Instead add a method to the PaymentMethod manager
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -78,7 +78,22 @@ export class InvoiceManager { | |||
requestObject | |||
); | |||
|
|||
return stripeInvoiceToFirstInvoicePreviewDTO(upcomingInvoice); | |||
let last4: string | undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the need for this change?
This method returns a preview of the invoice a customer might receive. At this point I wouldn't expect there to be a payment intent or payment method available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, thank you! You are correct - an upcoming invoice has none of this information, this is leftover from early debugging, but because of the undefined
case handling, it didn't impact the functionality of the method. Will remove.
/** | ||
* Fetch the invoice preview for the latest invoice associated with a cart | ||
*/ | ||
async previewLatestInvoice( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be moved to the InvoiceManager
Also note, that previewLatestInvoice
should only be responsible for fetching the latest invoice for a specific invoice Id.
Fetching the subscription, to get the latest invoice, is not the responsibility of the Invoice Manager.
Similarly returning the payment method data, should be part of the PaymentMethodManager
.
Put another way, Managers are responsible for interacting with data in their domain, Services are responsible for orchestrating all the data to complete a specific function. I've added some pseudo code below of what I'd expect the CartService.getCart
to change to
if (cart.stripeSubscriptionId) {
const sub = await this.subManager.retrieve(cart.stripeSubscriptionId);
const latestInvoice = await this.subManager.previewLatest(sub.latest_invoice)
const paymentMethod = await this.paymentMethodManager.retrieve(paymentMethod.id)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a nice way of doing this, will update
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
due to the way everything may-or-may-not-be undefined
, while trying to avoid a wildly nested if/else
block I've invented something equally bad! I present to you: ternary hell
const subscription = cart.stripeSubscriptionId
? await this.subscriptionManager.retrieve(cart.stripeSubscriptionId)
: undefined;
const latestInvoice = subscription?.latest_invoice
? await this.invoiceManager.retrieve(subscription.latest_invoice)
: undefined;
const paymentIntent = latestInvoice?.payment_intent
? await this.stripeClient.paymentIntentRetrieve(
latestInvoice.payment_intent
)
: undefined;
const paymentMethodId =
typeof paymentIntent?.payment_method === 'string'
? paymentIntent.payment_method
: paymentIntent?.payment_method?.id;
const paymentMethod = paymentMethodId
? await this.paymentMethodManager.retrieve(paymentMethodId)
: undefined;
const latestInvoicePreview = latestInvoice?.id
? await this.invoiceManager.previewInvoice(latestInvoice.id)
: undefined;
const last4 = paymentMethod?.card?.last4;
if (latestInvoicePreview) {
latestInvoicePreview.last4 = last4;
}
Not sure this is better, lets chat through options tomorrow
const paymentMethod = await this.stripeClient.paymentMethodRetrieve( | ||
paymentMethodId | ||
); | ||
const last4 = paymentMethod.card?.last4; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure this should be considered as part of the invoice preview
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should exist somewhere between the invoice
layer, and the cart
layer. It seemed like invoicePreview
was effectively an aggregate of fields related to invoices, rather than a method for surfacing the actual invoice itself.
In my brain, the specifics of payment details exist in relation to the payment event (here being on the completed invoice). Do you have a suggestion for where this should live?
a518391
to
6fd6a01
Compare
Because
This pull request
Issue that this pull request solves
Closes: FXA-7575
Checklist
Put an
x
in the boxes that applyScreenshots (Optional)