Follow-up to #2903713: Support negative promotions (fees)

Problem/Motivation

There needs to be a UI for configuring fees, which are the opposite of promotions: fixed amounts or percentages usually applied for specific payment gateways or shipping methods / addresses.

Proposed resolution

Add a commerce_fee submodule.

Issue fork commerce-2903716

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

heddn created an issue. See original summary.

bojanz’s picture

Title: [policy, no patch] How to handle fees vs promotions » [policy, no patch] How to handle fees

We discussed this on Slack and agreed that it doesn't make sense to (ab)use promotions for fees.
People expect a different UX (page title, listing), and the functionality is not completely the same (fees have no usage limits or coupons).
Furthermore, fees have different tax implications.

So, let's have fees be their own content entity, a copy of promotions without usage, compatibility, and coupons.
We can't reuse PromotionOffer plugins since they're not generic enough, so we'll need a fee specific plugin type.
Not sure what to name it though, FeeType would mean that it's used as a bundle, but it isn't. FeeAction?

Matt and I agreed that since the codebase would be close to promotions, it would make sense to have it in core, to prevent it from going out of sync. However, I have no clue when we'd have time to pursue such a thing.

heddn’s picture

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

Title: [policy, no patch] How to handle fees » Add a UI for fees
Component: Promotions » Other
Assigned: Unassigned » bojanz
Category: Task » Feature request
Issue summary: View changes
Status: Reviewed & tested by the community » Active

Let's use this issue for the implementation too.

Discussed it with Matt and Ryan, we agreed to go with a @CommerceFee plugin type.
I'll start work on this once we commit the display_title field to promotions. I can then copy commerce_promotion into commerce_fee and remove coupons, compatibility, usage.

s.messaris’s picture

Hello @bojanz, is this feature being worked on? I need this functionality and maybe I could work on it if you won't. Thanks!

mglaman’s picture

s.messaris it has not.

lisastreeter’s picture

lisastreeter’s picture

bojanz’s picture

Status: Active » Needs review
bojanz’s picture

Status: Needs review » Needs work

This will need to be updated to reflect #2980713: Switch order item adjustments from per-unit to per-line rounding and the new way of doing order offers (with the PriceSplitter splitting one amount betwen all order items).

lisastreeter’s picture

Status: Needs work » Needs review

I've made the updates at https://github.com/lisastreeter/commerce_fee to reflect #2980713: Switch order item adjustments from per-unit to per-line rounding.

Updates were applied to offer plugins:

  • src/Plugin/Commerce/Fee/OrderFixedAmount.php
  • src/Plugin/Commerce/Fee/OrderItemFixedAmount.php
  • src/Plugin/Commerce/Fee/OrderItemPercentage.php
  • src/Plugin/Commerce/Fee/OrderPercentage.php
  • src/Plugin/Commerce/Fee/PercentageBase.php

Corresponding test code also updated.

efpapado’s picture

I'm testing the module now.
At first, I created a pull request to make class FeeStorage constructor compatible with mother class CommerceContentEntityStorage
https://github.com/lisastreeter/commerce_fee/pull/1

efpapado’s picture

Status: Needs review » Reviewed & tested by the community

I tried the module and seems to work, with the same limitations as commerce_promotions. Note that it needs the patch #12.
I'll set it to RTBC, and hopefully it can be included in the roadmap.

bojanz’s picture

Status: Reviewed & tested by the community » Needs work

We also need to make Fee plugins work like offers in terms of base classes and traits, that was changed in commerce_promotion after #11 / June 26th.

Relevant promotion issues:
#2981944: Re-organize the base offer plugin classes
#2982202: Update promotion offer UX
#2980700: Introduce offer conditions

lisastreeter’s picture

Status: Needs work » Needs review

I've made the changes for comment #14. All tests are passing for me locally.

https://github.com/lisastreeter/commerce_fee

nickvanboven’s picture

Is there a reason that u dont use the eventsubscriber to alter the plugintypes that can be used?

mglaman’s picture

nickvanboven’s picture

@mglaman i was referring to the comment in the readme

"
Note: a modification is necessary in commerce file: commerce/src/Plugin/Field/FieldType/PluginItemDeriver.php

Modify method getDerivativeDefinitions()
add commerce_fee plugin to the $plugin_types array: 'commerce_fee' => $this->t('Commerce fee')
"

nickvanboven’s picture

Tested the new version works for me after adding a eventsubsciber to alter the list of plugin types in commerce core

lisastreeter’s picture

@nickvanboven My thinking with respect to altering the list of plugin types in commerce core was that since Fee would be a submodule in commerce core rather than a separate contrib module, we'd just alter core directly when it's added. So an EventSubscriber wouldn't be needed. But for testing purposes now, adding an eventsubscriber is certainly a good idea.

hockey2112’s picture

Is this feature close to being included in Commerce 2? If not, could you please provide me with a quick explanation on how to install the code listed in this thread? Thanks!

bojanz’s picture

This issue is on the roadmap and we hope to merge it in the next few months.

No guarantees are given regarding the GitHub code (no upgrade path, no bug fixes, no support). Use it only if you really know what you're doing.

hockey2112’s picture

Finally got around to giving this a try. Works great! My only snag (caused by my lack of attention) was installing it before making the changes to Commerce core's PluginItemDeriver.php as described in the readme. This omission resulted in database errors like this:

Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'mysite_drupal.commerce_fee' doesn't exist: SELECT COUNT(*) AS expression FROM (SELECT 1 AS expression FROM {commerce_fee} base_table GROUP BY base_table.fee_id) subquery; Array ( ) in Drupal\commerce_fee\FeeListBuilder->load() (line 23 of /home/mysite/public_html/modules/commerce_fee/src/FeeListBuilder.php).

I reverted my db, made the change to the PluginItemDeriver.php file, installed the module again, and everything ran smoothly. Hopefully my little snafu can help anyone else who runs into that self-inflicted issue, or help them to avoid it entirely.

Question/feature request: would it be possible for the cart/order to display the "Name" of the fee, instead of just "Fee"? For example, it could say "Wire Transfer Fee" or "Convenience Fee".

Thanks!

yonailo’s picture

Hello,

Two months have passed. Do you know when there will be a release of this ? I really need it and I hesitate to take the github code if the module is to be released in the short time ?

Do you have any fixed release date for it ? (other than "in the next few months" ?)

Thanks in advance.

hockey2112’s picture

@unknownguy, I can't comment on how close they are to release, but I can say that the github changes were very easy to apply, as long as you avoid the silly mistake I described above.

jmoruzi’s picture

Looking for this for an upcoming project as well.

cmcintosh’s picture

Also another quick note, instead of having to alter Commerce for files, you can create a field_type_info_alter hook.

You can define a new deriver class and insert the commerce_fee into it that way. I am a bit tight on a deadline, but will more than likely write something up for this if someone needs it.

Alternatively we could update the original deriver class to leverage some sort of Hook / way of extending the initial things.

cmcintosh’s picture

k.skarlatos’s picture

Hi, the module @lisastreeter created does not work after commit cc0a2fa3 of drupal commerce

k.skarlatos’s picture

Status: Needs review » Needs work
jacob.embree’s picture

Status: Needs work » Needs review

Try this pull request. I compared commerce_fee to commerce_promotion line by line, trying to bring in all the changes since commerce_fee was created.

I didn't touch the tests though.

mglaman’s picture

Assigned: bojanz » mglaman

I'll take a look at https://github.com/lisastreeter/commerce_fee/pull/3 and discuss with lisastreeter and bojanz.

jacob.embree’s picture

To address the instructions in the readme automatically you can add this patch to commerce in your composer.json or Drush make file.

hockey2112’s picture

I tied to implement the fees patch on Commerce 8.x-2.17, and I received this error message in the error_log, along with a Drupal WSOD:

[15-Apr-2020 18:32:38 America/Chicago] TypeError: Argument 7 passed to Drupal\commerce\CommerceContentEntityStorage::__construct() must implement interface Drupal\Core\Entity\EntityTypeBundleInfoInterface, instance of Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher given, called in /home2/mysite/public_html/modules/custom/commerce_fee/src/FeeStorage.php on line 50 in /home2/mysite/public_html/modules/contrib/commerce/src/CommerceContentEntityStorage.php on line 54 #0 /home2/mysite/public_html/modules/custom/commerce_fee/src/FeeStorage.php(50): Drupal\commerce\CommerceContentEntityStorage->__construct(Object(Drupal\Core\Entity\ContentEntityType), Object(Drupal\Core\Database\Driver\mysql\Connection), Object(Drupal\Core\Entity\EntityManager), Object(Drupal\Core\Cache\DatabaseBackend), Object(Drupal\Core\Language\LanguageManager), Object(Drupal\Core\Cache\MemoryCache\MemoryCache), Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))

What does this mean? How can I fix this issue? Thanks!

liquidcms’s picture

Status: Needs review » Needs work

yes, i get same result as @hockey2112. this doesn't work with 2.17 version of Commerce.

jacob.embree’s picture

Are you two testing https://github.com/lisastreeter/commerce_fee/pull/3 or one of the patches here?

hockey2112’s picture

@jacob.embree, i tried with both versions... the original lisa streeter version, and the version I downloaded from your link (https://github.com/lisastreeter/commerce_fee/tree/67192bb638dfbe9f1e546b...)

I was able to install your version of the module successfully in my localhost environment, but when I add a product to cart (and when I try to access /cart directly), I receive the error below. What might cause this issue? I did modify the commerce/src/Plugin/Field/FieldType/PluginItemDeriver.php file as outlined in the readme.

Error: Class 'Drupal\commerce_fee\DateTimeItemInterface' not found in Drupal\commerce_fee\FeeStorage->loadAvailable() (line 83 of C:\xampp\htdocs\mysite\public_html\modules\custom\commerce_fee\src\FeeStorage.php)

#0 C:\xampp\htdocs\mysite\public_html\modules\custom\commerce_fee\src\FeeOrderProcessor.php(35): Drupal\commerce_fee\FeeStorage->loadAvailable(Object(Drupal\commerce_order\Entity\Order))
#1 C:\xampp\htdocs\mysite\public_html\modules\contrib\commerce\modules\order\src\OrderRefresh.php(156): Drupal\commerce_fee\FeeOrderProcessor->process(Object(Drupal\commerce_order\Entity\Order))
#2 C:\xampp\htdocs\mysite\public_html\modules\contrib\commerce\modules\order\src\OrderStorage.php(127): Drupal\commerce_order\OrderRefresh->refresh(Object(Drupal\commerce_order\Entity\Order))
#3 C:\xampp\htdocs\mysite\public_html\modules\contrib\commerce\modules\order\src\OrderStorage.php(108): Drupal\commerce_order\OrderStorage->doOrderPreSave(Object(Drupal\commerce_order\Entity\Order))
#4 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\Entity\EntityStorageBase.php(500): Drupal\commerce_order\OrderStorage->invokeHook('presave', Object(Drupal\commerce_order\Entity\Order))
#5 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\Entity\ContentEntityStorageBase.php(700): Drupal\Core\Entity\EntityStorageBase->doPreSave(Object(Drupal\commerce_order\Entity\Order))
#6 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\Entity\EntityStorageBase.php(454): Drupal\Core\Entity\ContentEntityStorageBase->doPreSave(Object(Drupal\commerce_order\Entity\Order))
#7 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\Entity\Sql\SqlContentEntityStorage.php(837): Drupal\Core\Entity\EntityStorageBase->save(Object(Drupal\commerce_order\Entity\Order))
#8 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\Entity\EntityBase.php(395): Drupal\Core\Entity\Sql\SqlContentEntityStorage->save(Object(Drupal\commerce_order\Entity\Order))
#9 C:\xampp\htdocs\mysite\public_html\modules\contrib\commerce\modules\order\src\OrderStorage.php(160): Drupal\Core\Entity\EntityBase->save()
#10 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\Entity\EntityStorageBase.php(307): Drupal\commerce_order\OrderStorage->postLoad(Array)
#11 C:\xampp\htdocs\mysite\public_html\modules\contrib\commerce\modules\cart\src\CartProvider.php(225): Drupal\Core\Entity\EntityStorageBase->loadMultiple(Array)
#12 C:\xampp\htdocs\mysite\public_html\modules\contrib\commerce\modules\cart\src\CartProvider.php(177): Drupal\commerce_cart\CartProvider->loadCartData(Object(Drupal\Core\Session\AccountProxy))
#13 C:\xampp\htdocs\mysite\public_html\modules\contrib\commerce\modules\cart\src\CartProvider.php(165): Drupal\commerce_cart\CartProvider->getCartIds(NULL)
#14 C:\xampp\htdocs\mysite\public_html\modules\contrib\commerce\modules\cart\src\Controller\CartController.php(52): Drupal\commerce_cart\CartProvider->getCarts()
#15 [internal function]: Drupal\commerce_cart\Controller\CartController->cartPage()
#16 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array)
#17 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\Render\Renderer.php(573): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#18 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#19 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array)
#20 C:\xampp\htdocs\mysite\vendor\symfony\http-kernel\HttpKernel.php(151): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#21 C:\xampp\htdocs\mysite\vendor\symfony\http-kernel\HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#22 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\StackMiddleware\Session.php(57): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#23 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\StackMiddleware\KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#24 C:\xampp\htdocs\mysite\public_html\core\modules\page_cache\src\StackMiddleware\PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#25 C:\xampp\htdocs\mysite\public_html\core\modules\page_cache\src\StackMiddleware\PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#26 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\StackMiddleware\ReverseProxyMiddleware.php(47): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#27 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\StackMiddleware\NegotiationMiddleware.php(52): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#28 C:\xampp\htdocs\mysite\vendor\stack\builder\src\Stack\StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#29 C:\xampp\htdocs\mysite\public_html\core\lib\Drupal\Core\DrupalKernel.php(708): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#30 C:\xampp\htdocs\mysite\public_html\index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#31 {main}

liquidcms’s picture

sorry, no.. i was trying Lisa's master branch. Not sure how to use a PR.. will see if i can figure it out. Is it actually: https://github.com/jacobembree/commerce_fee/tree/fixes by any chance?

if yes, then i am now trying that but as D8 tends to do.. there is no clean way to remove a module.. so after trying master i can now no longer pmu the module. due to incompatibility of master with current version of commerce; the install of the module led to corrupted db. the only way i could recover the site was to remove the module folder. Now, adding the version from https://github.com/jacobembree/commerce_fee/tree/fixes when i try to en it simply says "already enabled"; when i try pmu, it says:

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'sia8.commerce_fee' doesn't exist

i tried just adding a dummy table and then it complains about columns missing.. D8 really sucks at this.

i'll see if i can go through my db and remove everything related to this module to try out your fixes.

thank-you for this work.. :)

liquidcms’s picture

Not too bad cleaning things up. commerce_fee shows in numerous tables in a db scan but i opted to try only removing the one in the config table (be careful if you are attempting the same cleanup as this is a serialized data field so you need to adjust the array item count as well as removing the commerce_fee entry). After doing that and cache rebuild i was able to enable the module from here: https://github.com/jacobembree/commerce_fee/tree/fixes successfully. I can see the UI and will try it out now.

Thanks again.

liquidcms’s picture

Works great. A couple things:

1. when i edit a Fee i see 2 edit tabs: https://www.screencast.com/t/s0SOq2OgPEn my guess is this is due to the remnant of the earlier version of the module and D8 not being able to clean out the router entry when it fails installing a module.

2. as mentioned above, the checkout review pane shows the fee listed as simply "Fee" as opposed to the name given to the Fee (in my case, CC Processing Fee). This will need to be changed as the customer would have no idea why the fee was added; plus, i guess there could be more than 1 fee added. I can look at doing patch for this if no one else does.

3. This is less of a Fee issue and more of an overall Commerce issue. Commerce doesn't properly handle payments made by staff (i.e. taking a CC payment over the phone). Numerous pieces are missing in the payment process for this: payment methods are not available (recent patch for this), payment methods are not available unless also available to users, orders are not "placed" after payment is made and, in line with these other issues; Fees are not added to orders paid for by staff (i.e. through the admin interface).

Great work on this everyone.. much appreciated. :)

hockey2112’s picture

Thanks for that link (https://github.com/jacobembree/commerce_fee/tree/fixes). I was able to install that version successfully.

As before, I added commerce_fee plugin to the $plugin_types array in commerce/src/Plugin/Field/FieldType/PluginItemDeriver.php: 'commerce_fee' => $this->t('Commerce fee'), so that section of that file now looks like this:

public function getDerivativeDefinitions($base_plugin_definition) {
$plugin_types = [
'commerce_condition' => $this->t('Condition'),
'commerce_promotion_offer' => $this->t('Promotion offer'),
'commerce_fee' => $this->t('Fee'),
];

I created a new Fee in the UI. I added a product to cart, selected the payment gateway that the fee should be applied to, and proceeded through checkout. The fee was not displayed in the cart, and it was not reflected in the final order amount or shown in the admin view of the order.

I inspected the settings for the fee. Everything looked fine. On a whim, I changed the "Start date" to a month ago, instead of today. The fee now works! Not sure if this is a localhost issue or a servertime issue, but this is what fixed it for me.

hockey2112’s picture

@liquidcms...

2. as mentioned above, the checkout review pane shows the fee listed as simply "Fee" as opposed to the name given to the Fee (in my case, CC Processing Fee). This will need to be changed as the customer would have no idea why the fee was added; plus, i guess there could be more than 1 fee added. I can look at doing patch for this if no one else does.

I agree, this would be a great feature, and is leaning toward "necessary". Please let us know if you do create a patch to include that functionality, I will gladly test it.

liquidcms’s picture

@hockey2112, yes, i had same issue that the Start date defaults to a date in the future (later today). I set it to yesterday to get tings working. I also set the Fee to be limited to Payment Methods.

liquidcms’s picture

a few more issues/comments on this:

1. i am not sure why the complexity in using the Fee name on the checkout form rather than just "Fee". The spot in the code mentions this issue: #2770731: Add a display name to promotions which has been going on for a few years but looks like they finished for the Promotion module. Anyway, the fix for Fee module is trivial and just requires line 44 in OrderFixedAmount.php (and other places for the other Fee types) to be changed to this:

'label' => $fee->getName(),

2. there is an issue with where/how this gets added. The fee should get added on the Order Information page via ajax once the payment method is selected (assuming that method has a fee). It isn't added until the Review page. This is ok except that if you return to the Order Info page and switch to a method which doesn't have that fee; the fee remains. Even going all the way back to the cart page and the fee is still attached.

hockey2112’s picture

1. Works great, thanks!

2. I agree that it would be ideal for the fee to be added on the Order Information page via Ajax. However, I was unable to recreate the issue you described. I chose the gateway that has a fee, proceeded to Review, the fee was there. Then I returned to Order Information, changed to the gateway with no fee, proceeded to Review, and there was no fee. Unless you are referring only to the Order Information page, in which case the proposed Ajax functionality would indeed "fix" that issue, and I completely agree that it has the potential to be very confusing for customers who make that payment gateway change as described above.

liquidcms’s picture

2. ah, yes, it does go away (I think was picking a method i thought had no fee; but did). still a little confusing as you could leave the site altogether and come back to your cart days later to see you are being charged a CC fee when you haven't yet picked CC - but certainly workable as it is.

jacob.embree’s picture

Status: Needs work » Needs review

My work on this will not stray far from the design of the promotion Commerce sub module. I don't want to increase development overhead too much; better to get the first big step committed first.

I updated my fixes branch to pull more recent changes from promotion.

I hope the update hook isn't the hangup since January. It would be really easy to pull it out, but I want a decision maker to make the decision to pull it before I go ahead.

liquidcms’s picture

I agree that the commerce_fee module is a workable solution for customer checkout (although the comments i made above about using ajax to add/remove the fee would make a much less confusing interface). I also agree this is the main flow to consider (customer checkout).

As i am realizing more and more about Commerce in D8 (and supposedly for D7 as well); that the Admin UI (accepting a CC payment over the phone) does not follow the same flow as the customer checkout; and as a result is missing many pieces (some are work in progress, others have no current plan). This is true for Fees as well.

For Fee related issues i see the following:
- when an admin chooses a payment method (only recently available through this patch: #2912996: Support admin order payments); fees do not get attached to the order
- if an admin wanted to simply edit the order before making a payment; there is a UI to add a Fee; but it has no knowledge of the Fee entities made available through this module.

My guess/hope would be that those features will eventually reside in this module as well.

hockey2112’s picture

Came across a use-case issue today. The fee applies to the order subtotal, or to the individual product price. However, when you have a coupon applied, the fee does not take that into account when determining the percentage fee amount.

Subtotal $900.00
Discount -$500.00
Test Fee $27.00
Total $427.00

The fee in this instance is 3%. $27 is 3% of the product's original price ($900), but the correct percent amount to charge would be $12 (3% of $400, the post-discount price).

The issue occurs whether the fee is set to apply to the subtotal or to the individual product amount.

Any ideas on how to resolve this?

devnyc’s picture

Hi all - I got here thanks to hockey2112 and i've installed the module successfully, set to activate on Paypal payment gateway, but on selecting paypal as the payment method on the order and proceeding, I get the following error. I made sure to have a Display Name set for the fee. Any thoughts?

[php7:notice] [pid 5827] [client 75.67.141.19:51791] Error: Call to a member function getDisplayName() on null in /var/www/html/helpca/web/modules/contrib/commerce_fee/src/Plugin/Commerce/Fee/OrderPercentage.php on line 41 #0 /var/www/html/helpca/web/modules/contrib/commerce_fee/src/Entity/Fee.php(383): Drupal\\commerce_fee\\Plugin\\Commerce\\Fee\\OrderPercentage->apply(Object(Drupal\\commerce_order\\Entity\\Order), Object(Drupal\\commerce_fee\\Entity\\Fee))\n#1 /var/www/html/helpca/web/modules/contrib/commerce_fee/src/FeeOrderProcessor.php(38): Drupal\\commerce_fee\\Entity\\Fee->apply(Object(Drupal\\commerce_order\\Entity\\Order))\n#2 /var/www/html/helpca/web/modules/contrib/commerce/modules/order/src/OrderRefresh.php(156): Drupal\\commerce_fee\\FeeOrderProcessor->process(Object(Drupal\\commerce_order\\Entity\\Order))\n#3 /var/www/html/helpca/web/modules/contrib/commerce/modules/order/src/OrderStorage.php(127): Drupal\\commerce_order\\OrderRefresh->refresh(Object(Drupal\\commerce_order\\Entity\\Order))\n#4 /var/www/html/helpca/web/modules/contrib/commerce/modules/order/src/OrderStorage.php(108): Drupal\\commerce_order\\OrderStorage->doOrderPreSave(Object(Drupal\\commerce_order\\Entity\\Order))\n#5 /var/www/html/helpca/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(500): Drupal\\commerce_order\\OrderStorage->invokeHook('presave', Object(Drupal\\commerce_order\\Entity\\Order))\n#6 /var/www/html/helpca/web/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(700): Drupal\\Core\\Entity\\EntityStorageBase->doPreSave(Object(Drupal\\commerce_order\\Entity\\Order))\n#7 /var/www/html/helpca/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(454): Drupal\\Core\\Entity\\ContentEntityStorageBase->doPreSave(Object(Drupal\\commerce_order\\Entity\\Order))\n#8 /var/www/html/helpca/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(837): Drupal\\Core\\Entity\\EntityStorageBase->save(Object(Drupal\\commerce_order\\Entity\\Order))\n#9 /var/www/html/helpca/web/core/lib/Drupal/Core/Entity/EntityBase.php(395): Drupal\\Core\\Entity\\Sql\\SqlContentEntityStorage->save(Object(Drupal\\commerce_order\\Entity\\Order))\n#10 /var/www/html/helpca/web/modules/contrib/commerce/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowBase.php(335): Drupal\\Core\\Entity\\EntityBase->save()\n#11 /var/www/html/helpca/web/modules/contrib/commerce/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowWithPanesBase.php(615): Drupal\\commerce_checkout\\Plugin\\Commerce\\CheckoutFlow\\CheckoutFlowBase->submitForm(Array, Object(Drupal\\Core\\Form\\FormState))\n#12 [internal function]: Drupal\\commerce_checkout\\Plugin\\Commerce\\CheckoutFlow\\CheckoutFlowWithPanesBase->submitForm(Array, Object(Drupal\\Core\\Form\\FormState))\n#13 /var/www/html/helpca/web/core/lib/Drupal/Core/Form/FormSubmitter.php(114): call_user_func_array(Array, Array)\n#14 /var/www/html/helpca/web/core/lib/Drupal/Core/Form/FormSubmitter.php(52): Drupal\\Core\\Form\\FormSubmitter->executeSubmitHandlers(Array, Object(Drupal\\Core\\Form\\FormState))\n#15 /var/www/html/helpca/web/core/lib/Drupal/Core/Form/FormBuilder.php(591): Drupal\\Core\\Form\\FormSubmitter->doSubmitForm(Array, Object(Drupal\\Core\\Form\\FormState))\n#16 /var/www/html/helpca/web/core/lib/Drupal/Core/Form/FormBuilder.php(320): Drupal\\Core\\Form\\FormBuilder->processForm('commerce_checko...', Array, Object(Drupal\\Core\\Form\\FormState))\n#17 /var/www/html/helpca/web/core/lib/Drupal/Core/Form/FormBuilder.php(218): Drupal\\Core\\Form\\FormBuilder->buildForm(Object(Drupal\\commerce_checkout\\Plugin\\Commerce\\CheckoutFlow\\MultistepDefault), Object(Drupal\\Core\\Form\\FormState))\n#18 /var/www/html/helpca/web/modules/contrib/commerce/modules/checkout/src/Controller/CheckoutController.php(94): Drupal\\Core\\Form\\FormBuilder->getForm(Object(Drupal\\commerce_checkout\\Plugin\\Commerce\\CheckoutFlow\\MultistepDefault), 'order_informati...')\n#19 [internal function]: Drupal\\commerce_checkout\\Controller\\CheckoutController->formPage(Object(Drupal\\Core\\Routing\\RouteMatch))\n#20 /var/www/html/helpca/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array)\n#21 /var/www/html/helpca/web/core/lib/Drupal/Core/Render/Renderer.php(573): Drupal\\Core\\EventSubscriber\\EarlyRenderingControllerWrapperSubscriber->Drupal\\Core\\EventSubscriber\\{closure}()\n#22 /var/www/html/helpca/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\\Core\\Render\\Renderer->executeInRenderContext(Object(Drupal\\Core\\Render\\RenderContext), Object(Closure))\n#23 /var/www/html/helpca/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\\Core\\EventSubscriber\\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array)\n#24 /var/www/html/helpca/web/vendor/symfony/http-kernel/HttpKernel.php(151): Drupal\\Core\\EventSubscriber\\EarlyRenderingControllerWrapperSubscriber->Drupal\\Core\\EventSubscriber\\{closure}()\n#25 /var/www/html/helpca/web/vendor/symfony/http-kernel/HttpKernel.php(68): Symfony\\Component\\HttpKernel\\HttpKernel->handleRaw(Object(Symfony\\Component\\HttpFoundation\\Request), 1)\n#26 /var/www/html/helpca/web/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Symfony\\Component\\HttpKernel\\HttpKernel->handle(Object(Symfony\\Component\\HttpFoundation\\Request), 1, true)\n#27 /var/www/html/helpca/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\\Core\\StackMiddleware\\Session->handle(Object(Symfony\\Component\\HttpFoundation\\Request), 1, true)\n#28 /var/www/html/helpca/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\\Core\\StackMiddleware\\KernelPreHandle->handle(Object(Symfony\\Component\\HttpFoundation\\Request), 1, true)\n#29 /var/www/html/helpca/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\\page_cache\\StackMiddleware\\PageCache->pass(Object(Symfony\\Component\\HttpFoundation\\Request), 1, true)\n#30 /var/www/html/helpca/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\\page_cache\\StackMiddleware\\PageCache->handle(Object(Symfony\\Component\\HttpFoundation\\Request), 1, true)\n#31 /var/www/html/helpca/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(52): Drupal\\Core\\StackMiddleware\\ReverseProxyMiddleware->handle(Object(Symfony\\Component\\HttpFoundation\\Request), 1, true)\n#32 /var/www/html/helpca/web/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\\Core\\StackMiddleware\\NegotiationMiddleware->handle(Object(Symfony\\Component\\HttpFoundation\\Request), 1, true)\n#33 /var/www/html/helpca/web/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\\StackedHttpKernel->handle(Object(Symfony\\Component\\HttpFoundation\\Request), 1, true)\n#34 /var/www/html/helpca/web/index.php(19): Drupal\\Core\\DrupalKernel->handle(Object(Symfony\\Component\\HttpFoundation\\Request))\n#35 {main}

devnyc’s picture

I was able to get around the error above by manually giving a display name in the commerce_fee/src/Plugin/Commerce/Fee/OrderPercentage.php file, but now while the fee applies correctly on checkout, the paypal buttons just leading to spinning circles and the debug shows "commerce-paypal/checkout-create/paypal/506 400 (Bad Request)". If i disable the fee, no error at all and payment works as usual. Any thoughts?

devnyc’s picture

Also seeing this error message in drupal recent logs whenever attempting the checkout with the field activated:

Client error: `POST https://api.sandbox.paypal.com/v2/checkout/orders` resulted in a `422 Unprocessable Entity` response: {"name":"UNPROCESSABLE_ENTITY","details":[{"field":"/purchase_units/@reference_id=='default'/amount/value","value":"62.9 (truncated...)

devnyc’s picture

I'm wondering if this has something to do with the currency. I am running to currencies on the site but i make sure to switch to USD for paypal. Wish that log message weren't truncated. Does anyone have thoughts on what's going on or how to get the full log message?

Thanks!

devnyc’s picture

Confirmed this is not a currency issue. Tested on a brand new instance of the Kickstart Demo. Added Commerce Paypal. Confirmed it works as a payment gateway. Then added Commerce Fee from Jacob's git. Made the necessary code change. Set up new Commerce Fee tied to the Paypal payment gateway. The fee is calculated and displayed correctly but once I click on any of the Paypal payment buttons, i get spinning wheel and the debugger shows "Failed to load resource: the server responded with a status of 400 (Bad Request)".

liquidcms’s picture

I suspect little love will be given here to support the admin payment flow using these new Fee entities. To highlight this need and hopfully to work on the patch for this; i have added this issue: #3150718: Admin UI for adding Fees as a logical extension of this one.

xamount’s picture

Here is a patch that fixes the issue for #50.

$promotion does not exist (seems to be a copy/paste error when commerce_fee was ported over from Promotion). We should use $fee instead

xamount’s picture

I added a child issue #3151656: Adding a fee based on Percentage AND Fixed Amount (patch included) which adds a new fee type based on Percentage AND Fixed Amount.

Thanks for all the great work on this commerce_fee module. I am able to use it but I would love to see a stable release soon.

hockey2112’s picture

@xamount, thanks for those updates! Do you have any ideas on how the issue I outlined in #49 can be resolved? https://www.drupal.org/project/commerce/issues/2903716#comment-13603003

xamount’s picture

@hockey2112 I spent the good part of a day trying to solve #49. But still no solution at this point. It seems that when you apply the coupon/promo, $order->collectAdjustments() is still returning empty in OrderPercentage plugin (and other similar fee plugins depending on what type of promotion you use). If anyone finds a solution, please post back! Also, if you know of a solution but you do not have the time to write the code, at least write a description of what the solution can be.

hockey2112’s picture

@xamount, thanks for looking into it. I am pretty puzzled by it myself as well. Hopefully someone has an idea on how it can be accomplished.

ornagy’s picture

@devnyc Could you solve the paypal problem? I have the same issue.

ornagy’s picture

@devnyc Could you solve the paypal problem? I have the same issue.

devnyc’s picture

Hey @ornagy - No not yet. For now, I'm using the Paypal Legacy Express Checkout instead of the other options, as that one is able to process the payments without error.

ornagy’s picture

@devnyc Thank you, for the answer. I will try it.

amateescu’s picture

Title: Add a UI for fees » Implement the ability to add fees to an order
liquidcms’s picture

Can anyone point me to how in the code and the db; a fee is added to an order? I need to figure out how to programmatically add a fee to an order. Looking through the code and the db; all i see is definition of the fee entity; but not its use. I can see in the commerce_order table that the price has been adjusted to include the fee; but no luck tracking the where or how the fee is attached to the order.

Sorry, this should likely be a support question on its own.. but where? This module isn't under the the main commerce module and it isn't its own project.

liquidcms’s picture

Hmm, ok.. i think its an adjustment; for some reason my SQL browser (Navicat); doesn't show it.. although does find it in a search.

Still would be grateful if someone could suggest where in the code an adjustment gets added to an Order.

liquidcms’s picture

No hints? Will pay for someone to suggest how a fee can be added to an order (programmatically). In FeeOrderProcessor.php i can see something as simple as $fee->apply($order); but can't get this to do anything (no errors; just doesn't do anything).

in the payment add form i added a submit function which has this:

  $order = Order::load($order_id);
  $fee = current(Drupal\commerce_fee\Entity\Fee::loadMultiple());

  $price = $fee->getPlugin()->getConfiguration()['amount'];
  $splitter = \Drupal::getContainer()->get('commerce_order.price_splitter');
  $amounts = $splitter->split($order, new Price($price['number'], $price['currency_code']));

  foreach ($order->getItems() as $order_item) {
    $order_item->addAdjustment(new Adjustment([
      'type' => 'fee',
      'label' => $fee->getName(),
      'amount' => $amounts[$order_item->id()],
      'source_id' => $fee->id(),
    ]));
  }

  $fee->apply($order);
  $order->recalculateTotalPrice();
  $order->save();

not sure if the price splitting matters; but doesn't impact one way or the other.

liquidcms’s picture

also saw a post suggesting i have to set adjustments and then save each order item:

    $adjustments = $order_item->getAdjustments();
    $adjustments[] = new Adjustment([
      'type' => 'fee',
      'label' => $fee->getName(),
      'amount' => $amounts[$order_item->id()],
      'source_id' => $fee->id(),
    ]);
    $order_item->setAdjustments($adjustments);
    $order_item->save();

this also does not work.

liquidcms’s picture

I sorted out how to add fees within the admin payment flow. Ideally this would be included as part of this module; but i suspect not much interest.

https://www.drupal.org/project/commerce/issues/3150718#comment-13767634

mandus.cz’s picture

mhawwari’s picture

Uploading the modification on commerce/src/Plugin/Field/FieldType/PluginItemDeriver.php as a patch to be able to keep updating commerce until commerce_fees gets added to core.

kaipipek’s picture

Any update on getting this into production version? This feature would be highly appreciated.

mellowtothemax’s picture

There seems to be an issue with the added fee to a payment method when free delivery over a certain amount is applied.

For example if there is a free shipping promotion over 50 euros and the subtotal is 46 euros. If a 5 euro fee is applied on the order for a payment option then the subtotal goes over the 50 euros and the free delivery promotion as applied. This is unwanted as the fee should not be part of the order subtotal.

Anyone have any ideas as to how to deal with this?

Regards,

GiorgosK’s picture

I have tried the Centarro sponsored https://www.drupal.org/project/commerce_fee but I have had lots of problems with Drupal 9
I had better luck with this https://github.com/jacobembree/commerce_fee and had to patch it to make it work you can find the code here
https://github.com/GiorgosK/commerce_fee/tree/drupal9-fix

I have added instructions on how to patch commerce using composer.json so basically for Drupal 9 what I did was

- install and enable https://github.com/GiorgosK/commerce_fee/tree/drupal9-fix
- add the necessary code in composer.json so you should end up with something similar to this

    "extra": {
        ...
        "patches": {
            ....
            "drupal/commerce": {
                "Implement the ability to add fees to an order dgo.to/2903716": "https://www.drupal.org/files/issues/2020-11-18/add-plugin-type-2903716-72.patch"
            },
            ...

- run composer install
- you should be able to add fee from the drupal interface

Alternatively one can easily create a custom fee as seen here https://github.com/GiorgosK/commerce_custom_fees

inwebsol’s picture

First of all, thank you for this really useful initiative. I have manged to get it working on D8 pretty successfully so far.

I have one issue now however. I noticed that the fee applies the VAT (tax) rules when they should be independent of taxes. For instance, If I have one product at 6% and another at 21% VAT, the calculated rates (of the product net prices HTVA) become higher than they should be because they also take into account the fees' rules added in the case of fees applied to credit or debit card payments. They should not be included.

Any ideas how to mitigate this?

Once again, a big thank you to all.

benjarlett’s picture

Thanks for this! Looks just what I need.
@GiorgosK I'm trying tot get this to work on drupal 9 but it's crashing at the review stage

Error: Call to a member function getDisplayName() on null in Drupal\commerce_fee\Plugin\Commerce\Fee\OrderPercentage->apply() (line 41 of /home/mysite/sites/web/modules/commerce_fee-drupal9-fix/src/Plugin/Commerce/Fee/OrderPercentage.php)
#0 /home/mysite/sites/web/modules/commerce_fee-drupal9-fix/src/Entity/Fee.php(383): Drupal\commerce_fee\Plugin\Commerce\Fee\OrderPercentage->apply(Object(Drupal\commerce_order\Entity\Order), Object(Drupal\commerce_fee\Entity\Fee))
#1 /home/mysite/sites/web/modules/commerce_fee-drupal9-fix/src/FeeOrderProcessor.php(38): Drupal\commerce_fee\Entity\Fee->apply(Object(Drupal\commerce_order\Entity\Order))
#2 /home/mysite/sites/web/modules/contrib/commerce/modules/order/src/OrderRefresh.php(180): Drupal\commerce_fee\FeeOrderProcessor->process(Object(Drupal\commerce_order\Entity\Order))
#3 /home/mysite/sites/web/modules/contrib/commerce/modules/order/src/OrderStorage.php(131): Drupal\commerce_order\OrderRefresh->refresh(Object(Drupal\commerce_order\Entity\Order))
#4 /home/mysite/sites/web/modules/contrib/commerce/modules/order/src/OrderStorage.php(108): Drupal\commerce_order\OrderStorage->doOrderPreSave(Object(Drupal\commerce_order\Entity\Order))
#5 /home/mysite/sites/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(495): Drupal\commerce_order\OrderStorage->invokeHook('presave', Object(Drupal\commerce_order\Entity\Order))
#6 /home/mysite/sites/web/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(657): Drupal\Core\Entity\EntityStorageBase->doPreSave(Object(Drupal\commerce_order\Entity\Order))
#7 /home/mysite/sites/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(449): Drupal\Core\Entity\ContentEntityStorageBase->doPreSave(Object(Drupal\commerce_order\Entity\Order))
#8 /home/mysite/sites/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(801): Drupal\Core\Entity\EntityStorageBase->save(Object(Drupal\commerce_order\Entity\Order))
#9 /home/mysite/sites/web/core/lib/Drupal/Core/Entity/EntityBase.php(339): Drupal\Core\Entity\Sql\SqlContentEntityStorage->save(Object(Drupal\commerce_order\Entity\Order))
#10 /home/mysite/sites/web/modules/contrib/commerce/modules/order/src/OrderStorage.php(164): Drupal\Core\Entity\EntityBase->save()
#11 /home/mysite/sites/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(302): Drupal\commerce_order\OrderStorage->postLoad(Array)
#12 /home/mysite/sites/web/modules/contrib/commerce/modules/cart/src/CartProvider.php(231): Drupal\Core\Entity\EntityStorageBase->loadMultiple(Array)
#13 /home/mysite/sites/web/modules/contrib/commerce/modules/cart/src/CartProvider.php(180): Drupal\commerce_cart\CartProvider->loadCartData(Object(Drupal\Core\Session\AccountProxy))
#14 /home/mysite/sites/web/modules/contrib/commerce/modules/cart/src/CartProvider.php(167): Drupal\commerce_cart\CartProvider->getCartIds(NULL, NULL)
#15 /home/mysite/sites/web/modules/contrib/commerce_cart_blocks/src/Plugin/Block/CartBlockBase.php(321): Drupal\commerce_cart\CartProvider->getCarts()
#16 /home/mysite/sites/web/modules/contrib/commerce_cart_blocks/src/Plugin/Block/CartBlockBase.php(304): Drupal\commerce_cart_blocks\Plugin\Block\CartBlockBase->getCarts()
#17 /home/mysite/sites/web/modules/contrib/commerce_cart_blocks/src/Plugin/Block/CartBlockBase.php(332): Drupal\commerce_cart_blocks\Plugin\Block\CartBlockBase->getCartCount()
#18 /home/mysite/sites/web/modules/contrib/commerce_cart_blocks/src/Plugin/Block/CartBlock.php(79): Drupal\commerce_cart_blocks\Plugin\Block\CartBlockBase->shouldHide()
#19 /home/mysite/sites/web/core/modules/block/src/BlockViewBuilder.php(171): Drupal\commerce_cart_blocks\Plugin\Block\CartBlock->build()
#20 [internal function]: Drupal\block\BlockViewBuilder::preRender(Array)
#21 /home/mysite/sites/web/core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php(101): call_user_func_array(Array, Array)
#22 /home/mysite/sites/web/core/lib/Drupal/Core/Render/Renderer.php(781): Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_ren...', 'exception', 'Drupal\\Core\\Ren...')
#23 /home/mysite/sites/web/core/lib/Drupal/Core/Render/Renderer.php(372): Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array)
#24 /home/mysite/sites/web/core/lib/Drupal/Core/Render/Renderer.php(200): Drupal\Core\Render\Renderer->doRender(Array, true)
#25 /home/mysite/sites/web/core/lib/Drupal/Core/Render/Renderer.php(156): Drupal\Core\Render\Renderer->render(Array, true)
#26 /home/mysite/sites/web/core/lib/Drupal/Core/Render/Renderer.php(573): Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}()
#27 /home/mysite/sites/web/core/lib/Drupal/Core/Render/Renderer.php(157): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#28 /home/mysite/sites/web/core/lib/Drupal/Core/Render/Renderer.php(171): Drupal\Core\Render\Renderer->renderPlain(Array)
#29 /home/mysite/sites/web/core/modules/big_pipe/src/Render/BigPipe.php(693): Drupal\Core\Render\Renderer->renderPlaceholder('callback=Drupal...', Array)
#30 /home/mysite/sites/web/core/modules/big_pipe/src/Render/BigPipe.php(547): Drupal\big_pipe\Render\BigPipe->renderPlaceholder('callback=Drupal...', Array)
#31 /home/mysite/sites/web/core/modules/big_pipe/src/Render/BigPipe.php(305): Drupal\big_pipe\Render\BigPipe->sendPlaceholders(Array, Array, Object(Drupal\Core\Asset\AttachedAssets))
#32 /home/mysite/sites/web/core/modules/big_pipe/src/Render/BigPipeResponse.php(112): Drupal\big_pipe\Render\BigPipe->sendContent(Object(Drupal\big_pipe\Render\BigPipeResponse))
#33 /home/mysite/sites/vendor/symfony/http-foundation/Response.php(381): Drupal\big_pipe\Render\BigPipeResponse->sendContent()
#34 /home/mysite/sites/web/index.php(20): Symfony\Component\HttpFoundation\Response->send()
#35 {main}

pslcbs’s picture

It was working correctly with D8.9 and Commerce 2.27.

After updating to Commerce 2.28 I have crashes when accessing to https://yoursite/admin/commerce/fees and https://yoursite/fee/add
Error: Call to a member function dispatch() on null in Drupal\commerce\CommerceContentEntityStorage->postLoad() (line 48 of /public_html/modules/contrib/commerce/src/CommerceContentEntityStorage.php)

I provide a patch to update FeeStorage.php file on commerce_fee submodule, with changes based on PromotionStorage.php file.

It works for me.

fonant’s picture

Working in Drupal 9.2.10, Commerce 8.x-2.28.

  1. Downloaded https://github.com/GiorgosK/commerce_fee/tree/drupal9-fix
  2. Patched Drupal Commerce with https://www.drupal.org/files/issues/2020-11-18/add-plugin-type-2903716-7...
  3. Patched commerce_fee with https://www.drupal.org/files/issues/2021-11-16/Commerce2.28_eventDispatc...
  4. I also needed to change "ConfigurablePluginInterface" to "ConfigurableInterface" in src/Plugin/Commerce/Fee/FeeInterface.php
SocialNicheGuru’s picture

marciaibanez’s picture

Assigned: mglaman » marciaibanez

I'll review this.

marciaibanez’s picture

Assigned: marciaibanez » Unassigned
Status: Needs review » Reviewed & tested by the community

Hi! I reviewed this issue and the other mentioned by @SocialNicheGuru in comment #80 (https://www.drupal.org/project/commerce_fee/issues/3265672#comment-14419951) and here's what I did:
- Downloaded and enabled the modules;
- Tried to create a new Fee;
- Got the error;
- Applied the patch from this issue;
- Tried to add a Fee again, but got the other error, from the issue linked above;
- Applied the patch made by @SocialNicheGuru;
- Everything worked and I was able to create and edit the Fees.

hockey2112’s picture

I installed the module on a new D9 website using the steps outlined in 79, 80, and 82. My percentage based fees were throwing errors.

I had to manually change the label of the Percentage fee, on line 41 of src/Plugin/Commerce/Fee/OrderPercentage.php, like this:

'label' => $this->t('Processing Fee'),

This means that the admin form label will no longer be used for percentage discounts. This is problematic if you need multiple different percentage-based fees (probably a rare occurrence).

These are the two errors I was receiving when trying to access the checkout pages with the percentage fee enabled. Any ideas on how to properly fix without resorting to my "hack"?

Notice: Undefined variable: promotion in Drupal\commerce_fee\Plugin\Commerce\Fee\OrderPercentage->apply() (line 41 of /home1/mywebsite/public_html/modules/custom/commerce_fee/src/Plugin/Commerce/Fee/OrderPercentage.php)

Error: Call to a member function getDisplayName() on null in Drupal\commerce_fee\Plugin\Commerce\Fee\OrderPercentage->apply() (line 41 of /home1/mywebsite/public_html/modules/custom/commerce_fee/src/Plugin/Commerce/Fee/OrderPercentage.php)

jsacksick’s picture

Status: Reviewed & tested by the community » Closed (won't fix)

I'm not really sure what's "RTBC" here. Which patch? I see links to custom Github projects and links to the contrib commerce_fee plugin. I'm unclear on what we're trying to achieve here TBH.

Since we now have a "commerce_fee" contrib, all requests should be made against this module. Once the module is stable & functional, we'll evaluate moving it to core.

SocialNicheGuru’s picture

Commerce fee has been updated.
Here the patch to commit to commerce is #72, https://www.drupal.org/project/commerce/issues/2903716#comment-13906947

In order to get commerce_fee to work with commerce:
download the latest http://drupal.org/project/commerce_fee
apply patch in #72 to commerce, https://www.drupal.org/project/commerce/issues/2903716#comment-13906947

Nothing else is needed.

jsacksick’s picture

@SocialNicheGuru: For now this is issue has been closed, so there's no reason to update it (use the commerce_fee issue queue).

Additionally, there's no need for the change from the patch from #72, this is handled by Commerce Fee directly, there's no need to touch Commerce core.

This is done by the ReferenceablePluginTypesSubscriber.