-
-
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
Remove currency from line items #1507
Remove currency from line items #1507
Conversation
5c0c145
to
f2d2dde
Compare
There's no need to compare currency on all line items since they all have the same currency, same as their order.
f4dc323
to
571b3d7
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.
This is really, really good work. I have a couple of more nits, but I think the general direction is great. 👍
end | ||
|
||
def currency | ||
order.currency if order | ||
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 can be written shorter as a delegate:
delegate :currency, to: :order
# | ||
# @param [Spree::Money] money - the money object to obtain price and currency from | ||
# @param [Spree::Money] money - the money object to obtain price from | ||
def money_price=(money) |
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 think this should have a Safeguard: It should raise a good error when trying to assign a price with a currency different to the order currency. Otherwise the information would just be lost. So something along these lines:
class CurrencyMismatch < StandardError; end
def money_price=(money)
return unless money
raise CurrencyMismatch, "Line item price currency must match order currency!" if money.currency.iso_code != currency
self.price = money.to_d
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.
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.
Yes, this is good. I have a feeling one could golf around in this method a bit more, but I'm fine leaving it as is because it does the right things.
end | ||
end | ||
|
||
def pricing_options |
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 like removing things from the public interface, but I'm not sure about moving this method to the private section.
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 reverted this change for now. I'm probably missing something but at the moment I cannot see any scenario when something else then the line item itself could need to be aware of these specific line item pricing options. That's why I'd move it to the private section, but I'm ok leaving it in the public one as well.
self.cost_price ||= variant.cost_price | ||
self.money_price = variant.price_for(pricing_options) if price.nil? | ||
self.money_price = price_from_options if price.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.
Is there a reason for extracting this method? I wouldn't do that. :)
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.
reading the code again, I think you are right. There's no reason to extract this method. Going to revert this change.
@@ -33,7 +33,7 @@ def self.default_price_attributes | |||
def self.from_line_item(line_item) | |||
tax_address = line_item.order.try!(:tax_address) | |||
new( | |||
currency: line_item.order.try(:currency) || line_item.currency || Spree::Config.currency, | |||
currency: line_item.order.try(:currency) || Spree::Config.currency, |
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.
With the delegate, this can actually be written shorter as line_item.currency
:)
it needs `allow_nil` set to true because the variant pricing options should work even when the line item has no order associated.
Previously if a price with a currency different from the order currency was set on a line item, it was just taking the wrong price amount without explictily rasing an error.
571b3d7
to
d47b62c
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.
@mamhoff thanks a lot for the hints! Please let me know if you see anything else that can be improved.
end | ||
end | ||
|
||
def pricing_options |
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 reverted this change for now. I'm probably missing something but at the moment I cannot see any scenario when something else then the line item itself could need to be aware of these specific line item pricing options. That's why I'd move it to the private section, but I'm ok leaving it in the public one as well.
It's no more allowed to have line item with a currency different from the order currency. The line item currency will be taken from the order directly so this field is no more needed.
@mamhoff please check again when you have time, thanks a lot! |
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.
Excellent, @kennyadsl - I think this is good to go now!
# | ||
# @param [Spree::Money] money - the money object to obtain price and currency from | ||
# @param [Spree::Money] money - the money object to obtain price from | ||
def money_price=(money) |
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.
Yes, this is good. I have a feeling one could golf around in this method a bit more, but I'm fine leaving it as is because it does the right things.
# When price is part of the options we are not going to fetch | ||
# it from the variant. Please note that this always allows to set | ||
# a price for this line item, even if there is no existing price | ||
# for the associated line item in the order currency. |
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.
Really good documentation. I wish I'd had that when first reading this method :)
self.price = nil | ||
return | ||
end | ||
raise CurrencyMismatch, "Line item price currency must match order currency!" if money.currency.iso_code != currency | ||
self.price = money.to_d |
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 a little tough to parse with the early return inside the unless (which has me thinking about the rest of the method like the double negative unless...else).
I think it would read better as an if/elseif/else
if !money
self.price = nil
elsif money.currency.iso_code != currency
raise CurrencyMismatch, "Line item price currency must match order currency!"
else
self.price = money.to_d
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.
@jhawthorn thanks for your review. Agree on the better readability of suggested version. Changed!
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.
Other than one suggestion this is great.
Thank you @kennyadsl
This prevents to keep storing the old price (valid) when passing a new nil money object (invalid) to the `money_price` setter method. Previously: line_item.price => #<BigDecimal: 33.22> line_item.money_price = nil line_item.price => #<BigDecimal: 33.22> Now: line_item.price => #<BigDecimal: 33.22> line_item.money_price = nil line_item.price => nil
73660fa
to
1d92f39
Compare
This PR removes currency from line items. That field is no more useful since all order contents will have the same currency (the order one).
ref: #1399
TODO:
spree_line_items
database table. I'm a bit concerned about this. What happens if there are users that rely on this field has custom logic related to line item currency (like statistics)? They could loose them. Can we proceed anyway or it's better to leave the field in the database and mark it for a future removal?