-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Payment methods display on boolean #1540
Payment methods display on boolean #1540
Conversation
38ce73d
to
5ac4ba6
Compare
<%= label_tag nil, Spree::PaymentMethod.human_attribute_name(:available_to_users) %> | ||
<ul> | ||
<li> | ||
<%= radio_button :payment_method, :available_to_users, true %> |
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.
A checkbox might be simpler than a radio button
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.
agreed - will change
store.payment_methods | ||
else | ||
Spree::PaymentMethod | ||
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.
This is not ideal because the order is holding knowledge about what payments are available to what stores. This logic would be better in either the Payment or Store class.
I'd recommend adding a Payment.available_to_store(store)
scope.
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.
sounds good, I'll add that scope
(store.nil? || store.payment_methods.empty? || store.payment_methods.include?(p)) | ||
Spree::Deprecation.warn "Spree::PaymentMethod.available is deprecated."\ | ||
"Please use .active, .available_to_users, and .available_to_admin scopes instead."\ | ||
"For payment methods associated with a specific store, use your_store.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.
This isn't a precise replacement ,your_store.payment_methods
won't return payments if none are associated (it should return all payments in this case). Payment.available_to_store(store)
which I suggest above would solve this.
@@ -0,0 +1,28 @@ | |||
class AddAvailableToColumnsAndRemoveDisplayOnFromPaymentMethods < ActiveRecord::Migration[5.0] | |||
def up | |||
add_column(:spree_payment_methods, :available_to_users, :boolean, default: nil) |
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 meaning does the default, nil
, have?
I would prefer that the default to both be true
(matching the old default behaviour) and that the column was null: false
to avoid any tri-value logic.
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 agree. Originally it was meant to be default: true
and avoid tri-value logic, however the edge case of nil
valued display_on
s make tri-value logic necessary.
"WHERE (display_on='front_end' OR display_on='' OR display_on='both')") | ||
execute("UPDATE spree_payment_methods "\ | ||
"SET available_to_admin='true' "\ | ||
"WHERE (display_on='back_end' OR display_on='' OR display_on='both')") |
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.
👍 Thank you for using plain SQL in the migration
when 'back_end' | ||
active.available_to_admin | ||
else | ||
active.available_to_users.available_to_admin + active.nil_available_to_users.nil_available_to_admin |
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 don't follow this line. I don't think it replicates the existing functionality.
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.
In the existing core/spec/models/spree/payment_method_spec.rb
file's describe .available
specs, there are four payment methods created, with display_on
values of 'front_end'
, 'back_end'
, 'both'
, and nil
.
The existing functionality filters with (p.display_on == display_on.to_s || p.display_on.blank?)
. This behaviour of .blank?
makes the live above (and the three value logic) necessary; the existing specs assert that there are two methods available for both. This should mean that there would be three each available for frontend and backend, as there are two for both and one each for those particular locations, however the specs show that this is not the case.
add_column(:spree_payment_methods, :available_to_admin, :boolean, default: nil) | ||
execute("UPDATE spree_payment_methods "\ | ||
"SET available_to_users='true' "\ | ||
"WHERE (display_on='front_end' OR display_on='' OR display_on='both')") |
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.
'both' should not be included here.
5ac4ba6
to
aeb6857
Compare
"WHERE NOT (display_on='front_end' OR display_on='' OR display_on IS NULL)") | ||
execute("UPDATE spree_payment_methods "\ | ||
"SET available_to_admin='false' "\ | ||
"WHERE NOT (display_on='back_end' OR display_on='' OR display_on IS NULL)") |
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'm not 100% sure thats safe, I'd prefer something like:
"SET available_to_admin=#{ActiveRecord::Base.connection.quote(true)}"
aeb6857
to
eb57967
Compare
@gevann this needs a rebase with master. |
LGTM! 👍 |
eb57967
to
eb4b1d7
Compare
PaymentMethod.display_on column is split in to two boolean columns available_to_users, and available_to_admin. Each value is set based on the value in the display_on column. Finally, the display_on column is removed.
Adjust Spree::Payment method creation in specs to use new boolean columns (available_to_users, available_to_admin) rather than string column 'display_on' Update specs and factories to use new columns
eb4b1d7
to
fa94154
Compare
This allows any existing code which used display_on to continue working. It's likely that specs will be using this.
The original implementation of `Spree::PaymentMethod.available` used `.select` which would turn the ActiveRecord::Relation into an array and meant we had to use `sort_by`. In solidusio#1540 `available` was deprecated in favour of `available_to_users` and `available_to_admin`, each of which returns an ActiveRecord::Relation object. That means we can use `order` to do the sorting in SQL, which also allows users to chain more scopes onto the return value if they wish.
Payment methods available on the backend used to be scope to active methods only. Unfortunately that functionality was lost in solidusio#1540 because the `available_to_admin` scope isn't limited to active payment methods.
This was the original behaviour in Solidus < 2.1, but the active scope got lost in solidusio#1540. Payment methods used to use the `available` filter which was scoped to active payment methods only. The `available_to_admin` scope isn't limited active payment methods, so we need to add it here.
I noticed that inactive payment methods were not being filtered out on the frontend. This used to happen in `Spree::PaymentMethod.available`, but in solidusio#1540 this filter was lost.
We use `Spree::Order#available_payment_methods` to determine which payment methods should be displayed on the payment page in checkout. The changes in solidusio#1540 accidentally dropped the scoping for active payment methods, causing inactive payment methods to show up on the frontend. This also required fixing the `available_to_store` scope, which behaved incorrectly. Calling `self` from inside the scope returns the `Spree::PaymentMethod` class itself and not the current scoping as the code implied. This scope will now raise an error if the store parameter is `nil`, return all payment methods in the current scope if the store has no payment methods, and return the payment methods for the store if it does have some.
Payment methods available on the backend used to be scope to active methods only. Unfortunately that functionality was lost in solidusio#1540 because the `available_to_admin` scope isn't limited to active payment methods.
This was the original behaviour in Solidus < 2.1, but the active scope got lost in solidusio#1540. Payment methods used to use the `available` filter which was scoped to active payment methods only. The `available_to_admin` scope isn't limited active payment methods, so we need to add it here.
This PR changes the
display_on
column of Spree::PaymentMethods to two boolean columns,available_to_users
andavailable_to_admin
. This allows clearer selection than the string-baseddisplay_on
column, enabling usage of scopes on the model, and improving readability and intention of the affected code.Closes #1532
This PR will be reworked into two-value logic after the merge of PR #1541, which fixes invalid specs for payment methods.