Skip to content
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

Custom price calculation step #237

Closed
oncode opened this issue Dec 29, 2019 · 14 comments
Closed

Custom price calculation step #237

oncode opened this issue Dec 29, 2019 · 14 comments
Assignees
Milestone

Comments

@oncode
Copy link
Contributor

oncode commented Dec 29, 2019

Is your feature request related to a problem? Please describe.
I need to change the price according to whether a custom field is set to true or false.

Describe the solution you'd like
A custom price calculation step where you can increase the product / order line price depending on a custom field or custom requirement.

Describe alternatives you've considered
None

Additional context
I want to sell rackets amongst other things. Usually the pro rackets come without a string and I want to offer a stringing service with the product. I can add the required informations into custom fields of the OrderLine, but I don't see a possibility to increase the price. Another use case would be when you offer gift wrapping for the product and want to increase the price.

@michaelbromley
Copy link
Member

I thought about this and in your case, would it not make more sense to have the "stringing service" as a separate product which can be added to the order? I think this is the way many businesses track such add-on items, gift-wrapping too.

So there could be 2 ways to implement this:

  1. Create a Racket Product with 2 variants. The first variant is just a Racket. The second variant is a Stringed Racket. Set the prices accordingly. In your storefront app you handle the logic to add the correct variant depending on how the customer configures the racket.
  2. You could have an independent "Stringing Service" Product (in case it can be applied to multiple Racket products). Again, you storefront logic would need to add this to the Order according to the customer's selection.

Would this approach work in your case?

@oncode
Copy link
Contributor Author

oncode commented Dec 30, 2019

Hi @michaelbromley, thanks for your ideas!

  1. I thought shortly about this, but there is a lot of repetitive content work that could be avoided with a global solution. For every racket and future one I would need to add a separate product variant. It also seems hacky, because there will be a new SKU unit, even though it is the same unit.
  2. For this solution there would be much less content work, but It would require work in the storefront. With gift wrapping it would be no problem I think, but for the stringing order you have to connect it somehow to the racket order or else I won't know which stringing service configuration belongs to which racket. Or when you add the same racket to the cart but with different stringing service options. But I guess I could connect them with a custom field in the OrderLine of the stringing product and display it accordingly in the cart, this should work.

@michaelbromley
Copy link
Member

The solution you describe in 2 sounds workable.

I think there probably will end up being a custom calculator step, but as it has some rather complex implications, it may not be an immediate prospect.

I will leave this issue open and perhaps others may add their use-cases which can inform the design of such a feature.

@Tyratox
Copy link
Contributor

Tyratox commented Apr 13, 2020

I would also be interested in a hook for the price calculation since I would like to implement two discount systems:

  1. Bulk discount e.g. $10 standard, $7 if you order 100 or more and so on
  2. Reseller discount where specific product groups are discounted for specific customers

The data structures are easy to implement using the existing plugin architecture but as discounts affect the price a feature like this would be necessary.

I'm new to vendure and don't have much experience with the architecture yet but it seems a method similar to the lifecycle methods described in https://www.vendure.io/docs/typescript-api/plugin/plugin-lifecycle-methods/.
I worked a lot with wordpress and there the core has a lot of filter/action calls with a given name where plugins can then intercept and modify results.
It seems that the mentioned event bus might also be a good fit for such extensions.

I might also be able to contribute to such a feature if needed but as I said I'm not familiar with the whole architecture yet and maybe some things mentioned by me don't fit it.

@michaelbromley
Copy link
Member

Hi @Tyratox

  1. Have you looked into the Promotions system? There's not much documentation yet I'm afraid, but it allows you to define conditions which trigger the promotion (e.g. "order at least 100") and actions (e.g. "$3 off"). Seems like it would accomodate this need.
  2. We have the concept of CustomerGroups, but as yet it is not fully implemented. When it is, it can be used as a condition for a promotion (i.e. "if customer is member of group 'reseller'") to satisfy this requirement.

@Tyratox
Copy link
Contributor

Tyratox commented Apr 13, 2020

Wow that was a quick response!

No I didn't come across the Promotions system yet but it sounds very promising. Now I'll definitely take a closer look at it, thank you!

@Tyratox
Copy link
Contributor

Tyratox commented Apr 13, 2020

Yes you were right the promotions system seems to work for these requirements, thank you!
Is it planned that plugins can also inject PromotionUtils because I think the promotions system would be even more powerful with direct access to the connection object such as in

hasFacetValues: async (orderLine: OrderLine, facetValueIds: ID[]): Promise<boolean> => {
for the hasFacetValues method.

That way promotion actions could handle more complex discounts as otherwise one has to create additional promotion rules for all individual products. (i.e. one action instead of multiple copies of condition: order contains >= of product id x => action reduce price of order depending on quantity of the same product)

@michaelbromley
Copy link
Member

@Tyratox I agree, I actually think all of the configurable classes should be able to inject dependencies. I recently came up with a pattern to do that which I implemented in the new JobQueueStrategy interface. It has an init() method which can be used to inject any provider from anywhere in the app. So you could even define new services in a plugin and then inject them into e.g. you PromotionConditions etc.

I'll create an issue to track this tomorrow.

@Tyratox
Copy link
Contributor

Tyratox commented Apr 14, 2020

@michaelbromley That would be even better of course. Impressing work!

@maku
Copy link
Contributor

maku commented May 13, 2020

@michaelbromley What would the approach to handle a shop with a product configurator? e.g. for configurable furnitures (means the furniture is specially made for the customer) .

In this case the customer would select e.g. a product like a table. Based on this selection you have to select different parameters (variabel input width, height, depth etc - selection like decor, material property) -> The price should be (of course) dynamicaly calculated...

Is this use case feasible?

@michaelbromley
Copy link
Member

@maku I guess in this case, having a matrix of possible ProductVariants does not make sense.

This would indeed be the archetypal use-case for a custom price calculation step. I'm going to add this to the next minor release milestone and have a go at an implementation. The basic idea would be to allow you to define a PriceCalculationStrategy in which you will add your specific configurator-based pricing logic.

@michaelbromley michaelbromley added this to the v0.13.0 milestone May 13, 2020
@maku
Copy link
Contributor

maku commented May 13, 2020

@michaelbromley Great, thank you. In general, appart from the price calculation, what would be the approach to bring such a system into the vendure architecture. Is this a plugin?

@michaelbromley
Copy link
Member

@maku yes, plugins are where all your custom functionality should reside. In this case, the plugin would define whatever custom fields required to store your configurator params, as well as (eventually) your custom PriceCalculationStrategy.

@michaelbromley
Copy link
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants