Porting is in progress.

With a stable Commerce 2.x Pricing API now in place, product pricing can now be resolved like this or this.

Status of this module

Done:

  • Basic entites are in place, Price lists and Price list items.

Todo:

Comments

Andreas Radloff’s picture

Issue summary: View changes
Andreas Radloff’s picture

Oh, and Feeds needs to stable too of course, a major part of this module is the importing-bit.

mykola dolynskyi’s picture

Still ?

Andreas Radloff’s picture

I have started working on it but it's on my spare time so it's not going fast. I can promise to have it out by the time Commerce hits 8.x-1.0, right now it's in alpha.

Some planned changes:
Price lists are fieldable
Price list selection is done on the (entity field) query level, rather than loading all of them and then do some arcane filtering magic.
Possibly breaking out parts into composer libraries since there doesn't seem to exist any price list libraries for PHP out there

I'll try to get a MVP out there asap so anyone can contribute patches.

Sorry to keep you waiting! :)

Andreas Radloff’s picture

Version: 7.x-1.x-dev » 8.x-2.x-dev
Status: Postponed » Needs work
Andreas Radloff’s picture

Issue summary: View changes
Andreas Radloff’s picture

Issue summary: View changes
Andreas Radloff’s picture

Status: Needs work » Active
Issue tags: +Plan
steveoliver’s picture

Issue summary: View changes

Updating current state of Commerce 2.x Pricing API in issue summary.

mykola dolynskyi’s picture

Andreas Radloff, thanks a lot for your work!

trigdog’s picture

Just checking in on the progress on this. Thanks!

Andreas Radloff’s picture

I'm sorry this has been delayed, I'm having hard to find time for this project at the moment. I'm counting on getting it done in June.

niko-’s picture

Hi guys

I have partly worked Commerce Pricelist D8 version.
I need a day or two to validate it against updated Price API
Url to github repo will be posted here

trigdog’s picture

Great, thanks for the update.

trigdog’s picture

@niko, any updates on this? I would like to help out if I knew where the current progress stands.

websiteworkspace’s picture

Tracking this module.

Submitting D8 Commerce 2.x software problem reports to help make DC 2.x the best it might be.

niko-’s picture

Andreas Radloff’s picture

Awesome work niko, sorry for being MIA here. I'm sending you a PM about co-maintaining and commit access.

niko-’s picture

Hi Andreas

Email replied, and your proposal approved :)

Andreas Radloff’s picture

Welcome to the project, niko! :)

niko-’s picture

Thanks

krystalcode’s picture

Hello,

There's a related module that I have developed called Price Rule at https://www.drupal.org/project/commerce_price_rule. The original concept can be viewed at https://www.drupal.org/node/2899158. The code can be browsed at https://github.com/krystalcode/drupal8-commerce-price-rule. It is a more generic version of the Price List module, allowing to define conditions (like in promotions), and it allows different methods for calculating product prices, such as taking a percentage off, getting prices from a list, or custom calculations.

I have created it as a separate module because I think it is more generic than price lists and to bring it here would be misleading. Since there is certainly an overlap though, and based on a discussion on the Drupal Commerce Slack channel, I thought I'd bring it here so that we can decide what's the best way moving forward. I see three options:

1. Maintain the Price Rule module as a more generic solution and add a note to the Price List module directing users to Price Rule.
2. Prefer not to change namespace, remove the Price Rule module and merge it with current efforts done here.
3. There may be some users that want to have a solution more optimised specifically to Price Lists, for example without using the Condition plugin so that there is better performance. In that case, we may want to keep both modules as separate solutions.

Let me know what you think!

niko-’s picture

Hi @krystalcode

Thanks for your great work on commerce_price_rule module

I had made quick review of your module and found that it partly implemented my plan about commerce_price 8.x. Of course we have to fix DatabaseConnection injection like this one https://github.com/krystalcode/drupal8-commerce-price-rule/blob/8.x-1.x/... and have to use entity storage instead to make some parts of your code more "D8 way".

Also you have to know that here is not yet reviewed PR https://github.com/onatalushko/commerce_pricelist/pull/4/files with the similar fuctionality. Also we have to add multiple active pricelist support, improve price list edit form UX/UI, add contions also to price list entity and so on.

My main aim in D8 version is to siplify price management to speed up the work of real managers. In best case I want to make the interface the same as it is seen by managers.

I think that second option is the best way to go forward.

Let's wait for Andreas opinion and maybe someone else

bojanz’s picture

I was asked to review existing efforts in this area and provide a bit of direction. I think we (krystalcode, sumanthkumarc, niko, me) can collaborate in one project.

Every eCommerce system I've ever looked at distinguishes promotions from price lists.
Promotions modify a price (percentage/fixed amount off, etc), while price lists provide a different unit price.
Once #2805549: Expand the "Calculated price" formatter with the ability to show prices with promotions/taxes/fees gets committed to Commerce 2.x, we'll be able to show promotion-modified prices on the product catalog.
That removes most of the need for commerce_price_rule, which is currently mostly a copy of commerce_promotion modified to work with price resolvers.

I spoke to krystalcode and he raised the idea of using promotion entities to hold price list items, instead of using a PriceList entity.
With entity types being cheap, I don't think there are upsides to that approach. Price lists don't have usage limits or coupons, and they aren't constraint by order types or stores, making promotions ill fitting for this purpose.

So, let's focus on how commerce_pricelist should look and work. I've reviewed the D7 module and our best competition.

Use case: As a store admin, I need to be able to define per store/currency/quantity/customer group/etc prices for my products. These dimensions need to be extensible, and I might have more than one. I might not enter a price for each possible value (prices for some stores, but not all, since others would use the default price). Ideally I could manage these prices when editing a product, or for all products at once (a "Price lists" entry under admin/commerce).

Main question: Should price lists be defined on the variation or the product level? What is the more common use case?
The D7 and Oro approach is to do it for variations, which is more granular, and makes more sense at a glance.
However, if we imagine a price list with a dozen prices, it becomes potentially tedious to repeat them for each (of possibly many dozens) of the variations. A per-product price list could have an optional variation condition (defaulting to same prices for all variations, but allowing to be configured otherwise).
Related Commerce issue: #2901939: Move the variations form to its own tab next to (Product) Edit.

Code-wise we'd have commerce_price_list configuration entities that have a label, conditions (CommerceCondition API), start and end dates. Optionally they could also have a way to limit available currencies, and to limit product visibility (choose which product/variation types can see the price list).
Then we'd have commerce_price_list_item content entities which would have a product/variation ID, a price, quantity, and conditions. The UI would hide any conditions that are already set on the commerce_price_list. That way a "Wholesale price list" configured for the "special customer" role wouldn't show the role condition when adding price list items.
Finally, the price resolver would do an EntityQuery to load matching price list items, and evaluate their conditions, the quantities, and the price currency, in order to select the right price. This is a potentially expensive operation when showing 50 products at once, so we'd need to investigate optimizations. A single cache entry for all of the product/variation price list items might help. We could also cache which prices were selected using a cache-tag-like approach, but with per-user conditions that would lead to as many cache entries as there are users, which sounds non-ideal.

sumanthkumarc’s picture

Agree with bojan's thoughts above, afterall we are working towards same cause at the end of the day.

dr. gubó’s picture

Guys, thanks for trying to make this happen for D8.
To answer bojan's main question above, I think price lists should be defined on the product variation level. The way I understand Commerce 2, even for a product that has no variations (which actually means it has only one variation), price and SKU are both defined on the product variation level. No other way to go I think.
We're willing to put in some hours to make this happen, what would be the best way to go about this? (It's the first time we're contributing in writing/porting a module.)

trigdog’s picture

Should price lists be defined on the variation or the product level?

I like the idea of having it on the product level as long as there is a condition to select a variation when needed. This will save a lot of time entering prices if you have a lot of variations on a single product that all have the same price in the price list.

Once you figure out a firm direction for this module, I could help if needed ;)

krystalcode’s picture

I've looked into this again, and I would like to make again the case for the Commerce Price Rule module (namespace not important, the architecture is). Apologies for redirecting the conversation a bit, but if we are to consolidate efforts we need to agree upon the direction first.

Promotions and proposed field formatter solution

The Commerce Price Rule module essentially provides functionality, including a UI, for managing price resolvers - that is, altering the base product price. This is fundamentally different than Promotions which are architected with applying discounts to an order in mind. The more both modules evolve the more the differences will be highlighted, including functionality and UI. One of the basic issues that leaves a gap that the Promotion module cannot fill is that promotions currently have a hard dependency on an order. Unless this dependency is removed, Promotions cannot replace Price Rules.

The issue regarding the field formatter mentioned by Bojanz might answer the original question "how much would this product cost if it was in my cart right now", but it is different than the requirement of changing the base price of a product everywhere on a site. The proposed solution via the field formatter currently is to calculate the price via resolvers, create an order, add an order item for the product, refresh the order, apply any adjustments such as taxes and promotions to the calculated price and use that final price.

All that is fine for the question that issue tries to address, but it is irrelevant and inefficient when all we want is the first part only: "calculate the price via resolvers". It would be bad enough from a performance perspective to do all that in a product display page, imagine doing this on a listings page where you might listing 50 products. Yes, I can pay a developer to write a price resolver and a field formatter, but I'm a store manager and that's what modules do, provide a UI so that I don't have to pay a developer and I don't have to reproduce the same work in multiple websites.

Bottom line is that, unless the Promotion module is changed at a fundamental level (likely won't happen nor should it) there will be space for the Price Rule module.

Comparison with other systems and proposed functionality

I've done no extensive search on how other systems work, but I had a quick look at the link Bojanz posted. Actually, that system is exactly an example of what the Price Rule module does or aspires to do. Apart from specifying a fixed replacement price (like D7 pricelist), it allows store managers to define "Price Calculation Rules", which are formulas that define the price of a product.

https://www.orocommerce.com/documentation/current/user-guide/pricing/pri...

Rule: (price formula), Condition: (product filtering expression)

You can define conditions and a formula for determining the product price. That's exactly what the Price Rule module does. Use case, calculate product prices based on desired profit margins - very common requirement and that's how most store owners calculate their price lists using spreadsheets. That could be simply implemented as a Price Rule calculation plugin and it would be more performant since a simple multiplication is much faster than fetching a record from the database.

Developing related functionality

One more thing I would like to point out is that by having a unified solution, we can implement related solutions such as caching and search API integration that cover all cases, instead of duplicating work. There is work under way for integrating Price Rules with search API allowing for price filtering based on customized prices, and while there's still a prototype to be built I believe there's a way to do this to cover most common cases. We don't have to do this separately for price lists and separately for other use cases.

Performance comparison

I haven't seen yet any disadvantage related to performance (or any other disadvantage) with developing a more generic solution. If Price Lists would be developed independently as full entities with conditions (which I think is the idea), performance would be the same.

Options available

So, to me, the question is whether we want to develop a unified solution that provides Price Lists but it also covers other use cases (i.e. Price Rule), or whether we want to focus specifically to Price Lists only. Module namespace aside, there's two ways forward:

1. Develop a unified solution continuing the work already done in the Price Rule module.
2. Develop a price list specific solution here, and the Price Rule module will try to provide integration with it.

Unfortunately, #2 mentioned integration might present issues if Price Lists is worked on independently and there is a risk that the solutions will diverge.

Product vs Product Variation level

At the database level, I believe this has to be resolved at the variation level. Both for providing flexibility, but also for performance which is very important. I have a purchasable entity, give me directly the price for it. We could accommodate other cases via UI manipulation e.g. allow entering a price for a product, but save that price per variation on the database.

In the Price Rule module way, there could be different Calculation plugins that would use the same PriceList entity and underlying database structure but would provide different UIs for different use cases. For example, set the prices at the product level, or set the prices at the variation level, or set the quantity restrictions globally at the list level so that they don't have to set min/max quantities for every single variation (if that's how some stores manage their prices). Even if we only choose to support one UI in the module, developers would be able to build their own UIs on top of it.

bojanz’s picture

I stand by my recommendation in #24.
Feel free to experiment with commerce_price_rule, but commerce_pricelist should stay independent of it.

The issue regarding the field formatter mentioned by Bojanz might answer the original question "how much would this product cost if it was in my cart right now", but it is different than the requirement of changing the base price of a product everywhere on a site. The proposed solution via the field formatter currently is to calculate the price via resolvers, create an order, add an order item for the product, refresh the order, apply any adjustments such as taxes and promotions to the calculated price and use that final price.


All that is fine for the question that issue tries to address, but it is irrelevant and inefficient when all we want is the first part only: "calculate the price via resolvers". It would be bad enough from a performance perspective to do all that in a product display page, imagine doing this on a listings page where you might listing 50 products.

Do note that this is precisely how Commerce 1.x price calculation works. Even on listings with 50 products.
You create dummy order and order item entities once, then rerun the promotions for each product. Performance wise, you are doing the same loading and evaluating as you are for price rules.

krystalcode’s picture

Ok. I'm sorry that we wouldn't agree on this but that's ok; it happens. If it turns out that you are right I would be happy to deprecate Price Rule in the future. Honestly I haven't heard any arguments yet about the disadvantages of my approach and the most important features we're looking for are already implemented, including Price Lists, so I will continue with its development.

Other interested parties that are looking for a more generic solution can follow the work and contribute on the module's page and issue queue (https://www.drupal.org/project/commerce_price_rule), otherwise follow Bojanz's lead and contribute to development here.

rszrama’s picture

Honestly I haven't heard any arguments yet about the disadvantages of my approach and the most important features we're looking for are already implemented, including Price Lists, so I will continue with its development.

@krystalcode While this may be true for the particular feature at hand, the most important disadvantage is in standing up contributed modules that create replacements or alternative to core systems and patterns. For example, in Commerce 1.x, the Commerce Option suite created an alternative approach to a core problem - using line item fields to alter product prices. All of the effort that went into those modules could have been spent resolving the remaining UX issues in core, but we lost both that opportunity and created end user confusion for lack of cooperation.

It sounds to me like you're proposing something similar by duplicating the functionality of the Promotions system in such a way that it actually contradicts the core 2.x pricing logic. We specifically split static base price resolution out of price calculation to solve problems in the 1.x implementation. Your proposal would reverse that and require both your module to mimic core in other ways (for example, currency selection or accommodating tax edge cases, esp. around VAT that need careful ordering of pricing logic) and other modules that work with the core pricing system to make special integrations with your module to also accommodate calculation during resolution.

Perhaps there was some realtime communication in Slack that didn't get captured in here - so I may be missing longer architectural discussions you guys have had. I don't see enough in here to make me think this conversation needs to end, though. The main problem as I read it is that you think you want to "calculate the price via resolvers" when we made price resolution specifically separate from calculation in 2.x to address flaws in 1.x. I don't see in your post above an acknowledgment of that, nor do I understand yet how you believe Bojan's proposal for the development of this module would not address your own requirements.

We're actively trying to create less confusion / fragmentation in the Commerce 2.x contrib ecosystem and would really prefer to work this out and not end up with modules that we have to advise developers against using as in 1.x.

zfming’s picture

StatusFileSize
new32.22 KB

i write code follow commerce_pricelist drupal 8.x, add store selection and fix bug price_list_type in commerce config menu. https://github.com/zfuming/commerce_pricelist

Andreas Radloff’s picture

I have invited Bojanz as new maintainer to get the D8 version ready.

zfming’s picture

StatusFileSize
new22.62 KB

This patch follow commit `a5291f5b78fce600e3e38e90e31bd4880e675b78`, fixed price list type config and add store support

zfming’s picture

StatusFileSize
new67.42 KB

This patch added fields quantity/start-date/end-dat in price list item entity, added feild store in price_list entity , also added field price_list_item in product_varation entity. This follow commerce-8.x-2.x-dev and commerce-product-varations-tabs.patch (issue-link: https://www.drupal.org/project/commerce/issues/2901939). full commit log at https://github.com/zfuming/commerce_pricelist

skyredwang’s picture

Status: Active » Needs review

#35 hasn't touched price resolver part mentioned in #24; also, pricelist_item currently save product variant reference, this needs to be updated to store PurchaseableEntity reference just like order item

Status: Needs review » Needs work

The last submitted patch, 35: commerce_pricelist-8.x-2.x_update.patch, failed testing. View results

zfming’s picture

StatusFileSize
new67.49 KB

This patch fixed product form save error

zfming’s picture

StatusFileSize
new1.52 KB
new67.97 KB

This patch fixed product save but price list dosn't have item entity

zfming’s picture

StatusFileSize
new3.03 KB
new67.16 KB

This patch remove custom test code and remove mode change files

zfming’s picture

StatusFileSize
new2.59 KB
new88.16 KB

This patch change item product_variation to purchased_entity

zfming’s picture

StatusFileSize
new1.3 KB
new88.29 KB

This patch fixed price list item save error when purchased entity price is null

skyredwang’s picture

Status: Needs work » Needs review

Set this to be ready to review.

One known UX issue is: when commerce_bundle doesn't include a default price. The commerce_pricelist should be disable the price text box for editing. This would support the use case when commerce_bundle has dynamic price, pricelist is not able to override a specific price anymore. We can create a new issue to address this UX.

zfming’s picture

StatusFileSize
new11.2 KB
new95.16 KB

This patch add price disabled when commerce_bundle doesn't include a default price.

Status: Needs review » Needs work

The last submitted patch, 44: commerce_pricelist-8.x-2.x_update-7.patch, failed testing. View results

zfming’s picture

StatusFileSize
new95.27 KB

fixed Could not apply patch

zfming’s picture

skyredwang’s picture

The latest patch contains a lot of sample codes from http://dev.studiopresent.com/blog/back-end/drupal-commerce-2-and-sale-price, which obviously suggest it is work in progress.

zfming’s picture

StatusFileSize
new2.43 KB
new95.08 KB

This patch remove sample codes and change service getPrice to purchased entity getPrice

skyredwang’s picture

Status: Needs work » Needs review

I did functional test on #49, below is what I found:

1. When adding a Product / Bundle to the pricelist_item, the original of the price is not auto loaded to the pricelist_item as the default price. This can be an improvement for UX.
2. On /price_list/*/edit page, the table to display the pricelist_item includes a pricelist reference, which is unnecessary.
3. "Add new price list item" button depends on the type of purchaseable_entities that are activated by admin, this design copied from Commercec Order, it seems to be powerful, but I am not sure it is necessary.

More reviews are appreciated

zfming’s picture

StatusFileSize
new1.63 KB
new95.52 KB

This patch auto loaded to the pricelist_item as the default price and delete price list dispaly at price list item inline entity form

zfming’s picture

StatusFileSize
new3.24 KB
new97.28 KB

This patch used Dependency Injection in inline entity form

zfming’s picture

StatusFileSize
new38.93 KB
new112.61 KB

This patch run phpcs and fixed the error

skyredwang’s picture

I have discussed the work in this thread so far with @bojanz, hopefully, we can get the foundation work above committed, and created a follow up issue #2938881: Explore adding conditions to price list items

bojanz’s picture

Title: Drupal 8 version » Reboot the Drupal 8 port

Better title, since there's already a D8 branch.

  • bojanz committed defa924 on 8.x-2.x authored by zfming
    Issue #2368053 by zfming, skyredwang, bojanz: Reboot the Drupal 8 port
    
bojanz’s picture

Status: Needs review » Fixed

This is more than enough work for one patch. Thanks, everyone!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

bojanz’s picture

This week we rebuilt the 8.x-2.x branch again, and released the first beta: https://www.drupal.org/project/commerce_pricelist/releases/8.x-2.0-beta1

The data model has been improved for greater performance, there is a new UI and a CSV import form. Give it a shot!