-
-
Notifications
You must be signed in to change notification settings - Fork 725
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
[City OFN Voucher] A shopper can use a VINE voucher #12949
[City OFN Voucher] A shopper can use a VINE voucher #12949
Conversation
84c1dfd
to
0a0ae42
Compare
render cable_ready: cable_car.replace( | ||
selector: "#checkout-payment-methods", |
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 didn't replace this by turbo, as it will be done in this PR #12896
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.
Partial review, up to and including "Add VineVoucherValidatorService and spec"
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.
Forgot to include a couple of thoughts on the data model:
...e/20241008053852_add_external_voucher_id_external_voucher_set_id_voucher_type_to_vouchers.rb
Show resolved
Hide resolved
...e/20241008053852_add_external_voucher_id_external_voucher_set_id_voucher_type_to_vouchers.rb
Show resolved
Hide resolved
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.
Also reviewed "Handle adding a VINE voucher to an order".
I will pause until we can discuss next week.
572271e
to
544dcfc
Compare
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.
Big effort! 💪
I have lots of comments sorry. I think because my brain is averse to complexity and tries to find simpler ways. I think you put it well when you said:
we are trying to shoehorn VINE voucher into a model that wasn't really design for that, on top of voucher already been shoehorned into adjustments
So I'm cautious about creating tech debt that we will have to pay for in the future.
fill_in "Enter voucher code", with: "KM1891" | ||
click_button("Apply") | ||
|
||
expect(page).to have_content("There was an error while adding the voucher") |
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.
Are we able to say why there was an error? Does the invalid_voucher
or not_found_voucher
message appear here?
flash[:error] = if vine_voucher_redeemer.errors.keys.include?(:redeeming_failed) | ||
vine_voucher_redeemer.errors[:redeeming_failed] | ||
else | ||
I18n.t('checkout.errors.voucher_redeeming_error') | ||
end |
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.
Can't we rely on vine_voucher_redeemer
to give us the error we need to know about? IE:
flash[:error] = if vine_voucher_redeemer.errors.keys.include?(:redeeming_failed) | |
vine_voucher_redeemer.errors[:redeeming_failed] | |
else | |
I18n.t('checkout.errors.voucher_redeeming_error') | |
end | |
flash[:error] = vine_voucher_redeemer.errors.first |
Or if not, maybe we can use optional chaining like so:
flash[:error] = if vine_voucher_redeemer.errors.keys.include?(:redeeming_failed) | |
vine_voucher_redeemer.errors[:redeeming_failed] | |
else | |
I18n.t('checkout.errors.voucher_redeeming_error') | |
end | |
flash[:error] = vine_voucher_redeemer.errors&[:redeeming_failed] || | |
I18n.t('checkout.errors.voucher_redeeming_error') |
9907b82
to
d1be702
Compare
I am yet to address all the review comments, but I had to do a bit more work to handle this requirement:
I ended up creating @dacook I started looking into handling API error with exception, and you are right it should be a bit cleaner than the current solution. Moving back into code review because I think it's worth Maikel having a look even if it's not totally finished |
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.
Great, thanks for trying that, I think it looks simpler now. What do you think?
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.
Great work, @rioug!
And sorry that it took me so long to review. There are some minor style issues we could address but I don't really want to add to this epic pull request. We can work on it in follow-up pull requests.
The only big questions for me now are:
- Is the data model right?
- Are we doing the correct validations?
Adding the external vine attributes is definitely not ideal. And I think that we could get around it by calling the validation API before redemption. That's maybe how it was intended. But those fields are also not in the way of anything. We could get rid of them quite easily in the future. So no need to act right now.
Those fields are also used in a find method. And just for my own clarification, this is how I read the code:
- User enters code.
- We can't find it locally and ask Vine.
- We get the set id etc and store the voucher locally.
- This info is used for redemption at checkout.
- The same voucher could be used again.
- Again, we don't find it locally and ask Vine.
- We get the same ids back and find it locally to update.
- Now the voucher value changed. If we ran reports about redemptions in OFN, we would only see the last remaining value of the voucher and not its initial value. Potential issue later?
Just thinking about alternatives:
- We don't need to store the short code because we never use it for redemption, just to display to the user.
- We could use
"#{voucher_set_id}/#{voucher_id}"
as local voucher id which would always be unique per enterprise. We wouldn't need to soften the validations. - Is the short code part of the long id? Can we derive it or do we need to store it separately?
Downside of the above would be that we need to change all the views to not display a really long voucher id.
- Should we always create a new voucher instead of finding a previous use of the same code?
That could avoid race conditions if the same code is used by two people. But that's unlikely. We would be able to track the value at the time of each redemption though.
What do you think?
voucher = Voucher.find_by(code: voucher_params[:voucher_code], | ||
enterprise: @order.distributor) | ||
return voucher unless voucher.nil? || voucher.is_a?(Vouchers::Vine) | ||
|
||
vine_voucher |
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.
No need to change now but generally I find this pattern more flexible:
local_voucher || vine_voucher
Then you can implement the parts on their own and test them independently.
063ff57
to
5852708
Compare
It is used to validate a voucher using the given short code
A Vine voucher is really a specific type of FlatRate voucher but because a Vine voucher can be used by mutiple enterprise, it can be considered different enough to warrant it's own class. It still share a lot of the behaviour of a FlatRate voucher, so to avoid duplication, all the shared functionality have been moved to a Vouchers::FlatRatable concern.
Plus optimise code with `find_or_initialize_by` as suggested in review
Paranoia doesn't support unique validation including deleted records: rubysherpas/paranoia#333 We use a custom validator, ScopedUniquenessValidator to avoid the issue
Log Client and Server error, and re raise exception for the caller to handle
5852708
to
f5b9ca3
Compare
@rioug thanks for the detailed testing notes, it's really helpfull! Main testing scenario passed successfully 💪 A few screenshots I might reuse later: however for the reports sections, only one report mentioned displayed vouchers
Is this list still accurate? I'm surprised to see the revenues by hub here given it's a report that is only accessible to super admins. I'm ok to merge this as is and focus on reports in another issue, what do you think @rioug ? there are failing check also to consider before merging. I also noticed something I've missed in my preview testing: the sentence above the link should not appear once the API key is settled. Also the link does not redirect to VINE. I've opened this issue about it: #13006 |
@rioug I also have a question about the test scenario: why do we need to "Set your team in VINE to "OFN test - merchant 2" ? I know staying login as OFN - test service will throw an error at checkout, but staying logout of VINE works as well (and that's correct as the shopper won't have a VINE account). |
That could be an issue indeed, that said I would expect VINE related report to be handled in VINE itself, or metabase. We need to update the value here as we need it in OFN to calculate the voucher adjustment amount ie : If we keep the original value, we could potentially try to redeem more than what's available and the customer won't be able to place the order.
I still think it's good to store it, it might be useful for debugging purposes I'd assume customer will only have access to the short code.
I am not sure how the short code is generated, as far as I can tell it's not part of the long id. We could have a look at the VINE implementation, but I don't think it's a good idea to copy the functionality. It's true we don't actually need the short code from a technical stand point, but we need it for customer feedback, ie we need to be able to display the code used to the customer on the checkout screen and order confirmation email.
I guess we could but wouldn't we have the same issue you raised above if we were to run reports about redemption in OFN ? We also would not have a unique voucher_set_id/voucher_id per enterprise any more. My understanding is for VINE to cover functionalities originally included in phase 2 of vouchers, so I am not expecting to see redemption report in OFN. But still it's good to keep this in mind. @mkllnk hopefully this answers your questions. I don't think we need to action anything for now. |
This to test a voucher can actually be redeemed by multiple enterprise. The test note don't exactly reflect a real life scenario, in reality each enterprise would be using their own set of credentials and would be linked to their own team in VINE. To make testing easier and not having to set up another set of credentials, you can just switch your team to a different Merchant to simulate that. |
@rioug yes that was my understanding as well for reports, I was confused by the reports section of the testing section of the PR. I think we can remove it? In that case and if Maikel's comments are all addressed, it looks like we can merge? I won't be at delivery circle tomorrow (that's the time slot I can't make) but feel free to merge if we are all aligned. Kudos :) |
What? Why?
It lets a customer use a VINE voucher on their order. OFN will communicate with the VINE Api :
VINE voucher are managed on the VINE platform : https://vine-staging.openfoodnetwork.org.au/login , as such they won't show on the voucher admin page.
What should we test?
Set up:
!! Make sure "connected_apps" feature is turned on
Logged as an enterprise to VINE, in the backoffice as an enterprise manager :
Log into VINE https://vine-staging.openfoodnetwork.org.au/ :
Normal checkout
Make sure you have an order cycle set up with the enterprise you connected to VINE set as a distributor, set your team in VINE to "OFN test - merchant"
--> you should see a voucher input
--> you should get a not found error
--> the 1$ voucher should be added to the order
--> you should get There was an error while adding the voucher
--> you should see the voucher applied to the order in the right hand side
--> you should see the voucher on the order confirmation page
--> you should see the voucher in the confirmation email
--> you should see "0$ Remaining value" and " 1 # Redemptions"
Same voucher used by multiple enterprise
Same as above, but this time use a $50 voucher from the first voucher set and place order under $50 so we can use the voucher with another enterprise.
--> you should see the voucher on the order confirmation page
--> you should see the voucher in the confirmation email
--> you should see " 2 # Redemptions" and under the "Voucher Redemptions" section, you should see a redemption for each "OFN test - merchant" and OFN test - mechant 2"
Failed redemption :
--> you should get "Redeeming the voucher failed" error
Admin - capture a payment
--> you should see the voucher as an "Order Adjustments"
--> The payment status should be "Complete" and order status on the right hand side should also be "Compete"
Failed redemption:
--> you should get "Redeeming the voucher failed" error
Admin - create a payment
--> you should get redirected to the payment page and the new payment should be listed, order status should be "complete"
Failed redemption:
--> should get redirected to the payment page and get "Redeeming the voucher failed" error
Report
Report will be available via Metabase and/or VINE.
Check the voucher are showing up correctly on the following reports:- Order Cycle Customer Totals- Enterprise Fees With Tax Report By Order- Revenues By Hub- Sales Tax Totals By OrderRelease notes
Changelog Category (reviewers may add a label for the release notes):
The title of the pull request will be included in the release notes.