Scope of this issue

  1. Provide a Fixed Off offer for orders
  2. Provide a Fixed Off offer for order items

Original summary

Hi

I think that we need add the following offers into commerce core
1. fexed off for order
2. fexed off for order item

Also we need the following conditions in core.
1. Product Is
2. Product Variation Is
3. Product Field Is Equal To
4. Product Variation Field Is Equal To
5. We need modify OrderTotalPrice condition to support order items (developers can create order item promo with condition to order total) or add order item equivalet for it.

Comments

niko- created an issue. See original summary.

niko-’s picture

niko-’s picture

Issue summary: View changes
niko-’s picture

StatusFileSize
new22.5 KB
joshmiller’s picture

Status: Active » Needs work
  1. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductEqual.php
    @@ -0,0 +1,69 @@
    + * Provides an 'Order: Total amount comparison' condition.
    

    This description appears to be inaccurate, maybe copy/pasted?

  2. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductEqual.php
    @@ -0,0 +1,69 @@
    + *   label = @Translation("Product is"),
    

    I think the object name "ProductEqual" is better ... I'd rather the label be "Product equals"

  3. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductFieldEqual.php
    @@ -0,0 +1,185 @@
    + * Provides an 'Order: Total amount comparison' condition.
    ...
    + *   label = @Translation("Product field is"),
    

    Again, it appears the description is a copy/paste hold over.

  4. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductFieldEqual.php
    @@ -0,0 +1,185 @@
    + *   label = @Translation("Product field is"),
    ...
    +class ProductFieldEqual extends PromotionConditionBase {
    

    Shouldn't this be "Product variation field equals"? "Product field is" appears to be way too generic.

  5. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductFieldEqual.php
    @@ -0,0 +1,185 @@
    +class ProductFieldEqual extends PromotionConditionBase {
    

    I would change the class name to "ProductVariationFieldEqual"

  6. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductFieldEqual.php
    @@ -0,0 +1,185 @@
    +    $fields = \Drupal::service("entity_field.manager")->getFieldDefinitions('commerce_product', $selected_bundle);
    

    This should be a dependency injected call.

  7. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductFieldEqual.php
    @@ -0,0 +1,185 @@
    +    //Create an empty representative entity
    

    Formatting. Needs a space and a terminator.

  8. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductFieldEqual.php
    @@ -0,0 +1,185 @@
    +    //Get the EntityFormDisplay (i.e. the default Form Display) of this content type
    ...
    +    //Get the body field widget and add it to the form
    

    Formatting. Needs a space and wrapped to 2 lines at the 80 character mark.

  9. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductFieldEqual.php
    @@ -0,0 +1,185 @@
    +    return $this->t('Compares the product entity.');
    

    Summary could be more specific. Perhaps "Compares the product variation field type."

  10. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductVariationEqual.php
    @@ -0,0 +1,70 @@
    + * Provides an 'Order: Total amount comparison' condition.
    

    Copy/paste error.

  11. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductVariationEqual.php
    @@ -0,0 +1,70 @@
    + *   label = @Translation("Product Variation is"),
    

    "Product variation equals"?

  12. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductVariationFieldEqual.php
    @@ -0,0 +1,188 @@
    + * Provides an 'Order: Total amount comparison' condition.
    

    Copy/Paste error.

  13. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductVariationFieldEqual.php
    @@ -0,0 +1,188 @@
    +//    $entity_id = isset($this->configuration['entity']) ? $this->configuration['entity'] : NULL;
    

    Remove commented code.

  14. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductVariationFieldEqual.php
    @@ -0,0 +1,188 @@
    +    $fields = \Drupal::service("entity_field.manager")->getFieldDefinitions('commerce_product_variation', $selected_bundle);
    

    Should be dependency injected.

  15. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductVariationFieldEqual.php
    @@ -0,0 +1,188 @@
    +    //Create an empty representative entity
    ...
    +    //Get the EntityFormDisplay (i.e. the default Form Display) of this content type
    ...
    +    //Get the body field widget and add it to the form
    

    Formatting.

  16. +++ b/modules/promotion/src/Plugin/Commerce/PromotionCondition/ProductVariationFieldEqual.php
    @@ -0,0 +1,188 @@
    +        $term = \Drupal::service('entity_type.manager')
    +          ->getStorage("taxonomy_term")->load($this->configuration[$field_id][0]['target_id']);
    +        $tree = \Drupal::service('entity_type.manager')
    +          ->getStorage("taxonomy_term")
    +          ->loadTree($term->getVocabularyId(), $term->id());
    

    Should be dependency injected.

mglaman’s picture

Assigned: Unassigned » mglaman

We also should have any product based promotions provided by the Product module, since we cannot guarantee it'll be enabled.

mglaman’s picture

Discussed with bojanz: one major change is the Product equals should allow you to select the product and default to All variations, then allowing specific variation choices. This simplifies UX and options by combining two conditions. If All variations is not selected let's limit by attributes to start (only Black is on sale, or only XXL)

EDIT: If the product variation type has no attributes, show a #multiple enabled select of all the titles. Or checkboxes.

mglaman’s picture

Title: Need additional conditions and offers for promotions » Improve and expand Promotion plugins

My work expanded quite a bit.

I need to update the order summary.

mglaman’s picture

Issue summary: View changes
StatusFileSize
new56.19 KB

Okay, I went a little deep on this. Here's a patch to mark progress and concepts. I tried to simplify offer plugins to not need to specify target entity type. But I blew the scope.

Scope of this issue should stick to (for my own benefit)

  1. Product Equals condition: auto complete to pick product via purchased entity relationship on order item. Allows you to pick variations, defaults to "All." If there are attributes on the variation type, provide checkboxes to filter available product variations by that. If no attributes, show checkboxes for each variant (extension of original patch condition, removal of separate variant one)
  2. Product has field condition: Check product field value via purchased entity relationship on order item (in original patch.)
  3. Variation has field condition: Check variation field value via purchased entity relationship on order item (in original patch.)
  4. Provide a Fixed Off offer for orders
  5. Provide a Fixed Off offer for order items

This current patch attempted 1 and consolidate 4 & 5 into a single plugin, making it easier to provide shipping promotions. However, I should tackle that in a follow-up. Given that this issue will add a lot more test coverage, which also needs a huge bump.

mglaman’s picture

Issue summary: View changes
Related issues: +#2842924: Add a product condition
mglaman’s picture

Title: Improve and expand Promotion plugins » Provide FixedOff offers for order and order items
Issue summary: View changes

We'll do product conditions in #2842924: Add a product condition and fixed off offers here.

mglaman’s picture

Issue tags: +MidCamp2017
josephdpurcell’s picture

Assigned: mglaman » josephdpurcell

Taking a look at this now.

josephdpurcell’s picture

Per conversation with Matt, ignore previous history in this ticket.

The goal here is to create "fixed off" promotion, where you take an amount and subtract an amount. Look at modules/promotion/src/Plugin/Commerce/PromotionOffer/OrderPercentageOff.php as an example, it should be more or a less a copy-paste, rename, and refactor execute to subtract.

Ensure there are tests.

manojapare’s picture

Status: Needs work » Needs review
StatusFileSize
new4.82 KB

Added `Fixed offer` and test for the same.

niko-’s picture

Hi @manojapare

You can't create adjustment
with amount more then order\order item total but in your implementation it is possible

niko-’s picture

Status: Needs review » Needs work
mglaman’s picture

  1. +++ b/modules/promotion/src/Plugin/Commerce/PromotionOffer/FixedOffBase.php
    @@ -0,0 +1,69 @@
    +      '#title' => $this->t('Fixed'),
    

    We can just say "Amount" here, since it is a static/fixed amount off each time.

  2. +++ b/modules/promotion/src/Plugin/Commerce/PromotionOffer/OrderFixedOff.php
    @@ -0,0 +1,30 @@
    + *   target_entity_type = "commerce_order",
    

    Offers no longer need to use `target_entity_type`.

  3. +++ b/modules/promotion/src/Plugin/Commerce/PromotionOffer/OrderFixedOff.php
    @@ -0,0 +1,30 @@
    +    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    +    $order = $this->getTargetEntity();
    

    Offers are always passed an order object, now. So getTargetEntity is only on conditions. Use

    $this->getOrder()

You can't create adjustment with amount more then order\order item total but in your implementation it is possible

Technically nothing prevents promotions from doing this. I don't think it should be a concern of the offer plugin, but something Commerce itself guarantees. When calculating order total it never goes negative. Also, it might be a sign of improper promotion conditions not limiting your promotions.

niko-’s picture

>Also, it might be a sign of improper promotion conditions not limiting your promotions.

But let's check the following:

we have $100 fixed discount for $90 order total
the code above will apply $100 ajustment with zero order total - thats ok until adjust total is hidden.

so order total will be the following
subtotal - $90
fixed discount - $100
total - $0.00

Isn't it ?

manojapare’s picture

Status: Needs work » Needs review
StatusFileSize
new5.15 KB
new2.49 KB

@niko @mglaman

Thanks for the guidance and help.

Had made the changes as per the review comments.

If fixed discount price is greater than order total price, I had made discount price same to order total price. So final total price won't be negative.

Doing like this will result in, say if order total price is 90 and fixed discount price is 100 then in order summary it will be displaying like:
subtotal - $90
discount - $90 // instead of $100
total - $0.00

josephdpurcell’s picture

Assigned: josephdpurcell » Unassigned
StatusFileSize
new5.23 KB
new8.29 KB

Nice work @manojapare.

It would seem I've wasted my time here--I didn't realize others were working on this. Nonetheless I'll contribute back the change of renaming "FixedOff" to "FixedAmountOff" if that is still desired.

Unassigning myself to indicate I'm not working on this.

imyaro’s picture

StatusFileSize
new5.24 KB
new1.27 KB

Thanks for your work! This patch is - pretty helpful for me. But regarding the last fix - I have faced an issue:
Price constructor expects first param to be a numeric value, not the Price object.

Changed patch a little, see in the attachments

manojapare’s picture

Status: Needs review » Reviewed & tested by the community

@zvse thanks. Patch is working fine. Marking as RTBC.

mglaman’s picture

  1. +++ b/modules/promotion/src/Plugin/Commerce/PromotionOffer/FixedAmountOffBase.php
    @@ -0,0 +1,69 @@
    +      'amount' => 0,
    

    Must be a string.

  2. +++ b/modules/promotion/src/Plugin/Commerce/PromotionOffer/OrderFixedAmountOff.php
    @@ -0,0 +1,38 @@
    +    $orderTotalPrice = $order->getTotalPrice();
    ...
    +    if ($orderTotalPrice < $this->getAmount()) {
    

    No camel case

  3. +++ b/modules/promotion/src/Plugin/Commerce/PromotionOffer/OrderFixedAmountOff.php
    @@ -0,0 +1,38 @@
    +      $discount_price = new Price($orderTotalPrice->getNumber(), $currency_code);
    

    Wouldn't this just be $order->getTotalPrice();

mglaman’s picture

Status: Reviewed & tested by the community » Needs work
bojanz’s picture

Assigned: Unassigned » bojanz

Taking over.

  • bojanz committed cbacafa on 8.x-2.x authored by manojapare
    Issue #2854313 by manojapare, niko-, zvse, josephdpurcell, mglaman,...
bojanz’s picture

Status: Needs work » Fixed

The fixed amount needed to be a commerce_price form element.
But that caused me to run into #2885575: Switching plugins can crash if both share a configuration element of the same name, but not the same type, now fixed.

Committed, thanks everyone!

bojanz’s picture

Title: Provide FixedOff offers for order and order items » Provide a fixed amount off offer for orders

Clarifying title, since this issue didn't add a per-order-item offer.

Status: Fixed » Closed (fixed)

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