-
-
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
Promotions remember their base code #1410
Promotions remember their base code #1410
Conversation
I personally think adding additional codes after a promotion is created is a great feature and this PR moves us in that direction. ❤️ |
@@ -28,7 +26,7 @@ def create | |||
|
|||
def load_bulk_code_information | |||
@promotion_builder = Spree::PromotionBuilder.new( | |||
base_code: @promotion.codes.first.try!(:value), | |||
base_code: @promotion.base_code || @promotion.codes.first.try!(:value), |
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.
If these two items are interchangeable, perhaps a migration to set that data on base_code
would be helpful?
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.
They aren't exactly interchangeable, but there's no good way to write a migration to set that data, because that data simply isn't there -- that's what this PR fixes.
I suppose you could write a migration that looked through all existing promotions, if they have promotion codes and if those codes all begin with the same prefix (assuming that prefix is always followed by an underscore, which the existing CodeBuilder does, but you could hypothetically have a custom CodeBuilder which does something else), then extract that prefix and set it as base_code?
That seemed far too error-prone and weird to try, to me.
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.
to be more clear: Prior to this PR, if you look at an existing Promotion, the first promotion code (if any) is shown on screen labelled (labelled incorrectly) "base code".
That's just a mess, but the actual base code was not stored anywhere to display instead. After this change, the actual base code is stored somewhere and can be displayed properly. But for backwards compatibility and with existing promotions that do not have a stored base code, it still falls through to the old behavior.
As I warn in the PR, this change leaves a lot of internal API (class/method) API being kind of confusing. A lot of existing design is... not the choices I would have made. But I intentionally made the smallest possible change to get a properly stored base_code.
If people would rather I change more to make the internal API more reasonable, I certainly can -- but it's very challenging to figure out how to do so in a way that is both backwards compatible and makes the code less rather than more confusing.
@jrochkind thanks for raising this issue! I've got a slightly different suggestion I'd like to offer on tackling this: What if we introduce a I very much agree with all of these points:
...
...
...
Along with those, here are a few additional points of pain I've had with the current system:
I think we might be able to help with all these issues if we added a PromotionCodeBatch model and update the admin API a bit. Specifics:
Thoughts? I know that's a much larger request, but personally I'd rather not cement the idea 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.
Other than a small nitpick I am strongly 👍 on merging this.
I like Jordan's proposal for a PromotionCodeBatch
model, but I think it is out of scope for what this proposes to fix. I think PromotionCodeBatch
would work well with a major rework of the code generation, as it implies some background processing, and begs for some other features too (pluggable code generation?).
I think this is a quick fix which should have always been included. If we ever get to creating PromotionCodeBatch
, it will be easy to move the stored base_code
over to the new model.
def initialize(attributes = {}, promotion_attributes = {}) | ||
if base_code = attributes[:base_code] | ||
promotion_attributes[:base_code] = base_code |
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 avoid modifying the hash passed in.
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.
good call. I guess the alternative is promotion_attributes = promotion_attributes.merge(base_code: base_code)
. Is that what makes sense?
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.
done
Yep, I agree with @jhawthorn, this is basically meant to fix what I think was an omission in the implementation of the multi-code feature, it should have included this to begin with. Just fixing it in the simplest way possible, entirely backwards compatible. I'll fix the mutation of the input parameter that @jhawthorn pointed out. If committers don't want to make this fix to the current architecture, insisting instead on a more major refactoring of the feature (perhaps backwards compat perhaps not), you can reject/close this PR. I can't commit to doing that major refactoring myself though, especially cause I've found that major refactorings are unlikely to be approved by committers who will disagree with each other about how it should look. :) If this does get accepted, I think the next step is some slight fixes to the admin UI, to deal with confusion several people have reported on the slack channel about how to create a promotion with just one code. With a base code stored, the UI can actually tell whether it's a multi-code promotion or a single-code promotion, and adjust labels accordingly to only say 'base code' if it really is a base code. Really, I think the original multi-code implementation was merged not really finished, just trying to finish it in a backwards compat way. |
builder.promotion.promotion_codes << | ||
Spree::PromotionCode.create( | ||
promotion: builder.promotion, | ||
value: "#{base_code}_abcdef") |
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.
Closing method call brace must be on the line after the last argument when opening brace is on a separate line from the first argument.
@vladstoick actually just implemented |
Do what you gotta do. My use case that inspired this was I want to be able to say "Add N more codes" (where N can == 1!), and get codes added, without the code making this request having to know through some out of band source what the correct 'base code' is. I'd put handling that use case in as a request for your alternate proposed refactoring, and additionally a clear path for making the admin UI less confusing than it is now, although I don't think that has to be in the PR improving the behind-the-scenes. (Multiple reports of people not understanding how to add a single-code promotion from current admin UI). |
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.
@vladstoick is working on upstreaming our work but I think we should be fine to merge this in the meantime. It's a good step forward and is a nice small set of changes.
Closing now that #1524 has been merged |
When multi-promotions were added to Solidus, they seem to have done so in a way that the base code is not stored on the promotion, it is purely a transitory property of the promotion creation process.
This makes it hard to later create more promotion codes using the same base code.
It also means when later looking at the Promotion in an admin edit screen, the first code from the db is shown on screen labelled as 'base code', rather than the base code itself. Which is kinda messy.
This PR: