#StackBounty: #magento2 #quote #product-weight Prevent custom weight from being overwritten

Bounty: 50

in my magento 2 extension I do calculate the product weight when the user adds the item to the cart.

My problem is that the weight I set gets overwritten at the checkout.
Cause is the setProduct() function of MagentoQuoteModelQuoteItem.php.

To prevent this I created a plugin:

VendorModulePluginItemModelPlugin.php

namespace VendorModulePlugin;

use MagentoQuoteModelQuoteItem as QuoteItem;

class ItemModelPlugin
{

    public function aroundSetProduct(QuoteItem $subject, Closure $proceed, $product)
    {

        if($product->getData('isCalcWeight') == true)
        {
            $weight = $subject->getWeight();
            $result =  $proceed($product);
            $subject->setWeight($weight);
            $subject->save();

        }else {

            $result =  $proceed($product);

        }

        return $result;

    }
}

But two things don’t work here.

$product->getData('isCalcWeight') and $subject->getWeight() always return NULL.

Note: The attribute “isCalcWeight” is a bool that is set to true/false depending on the fact if a custom weight is used or not.

Can someone help me out here?

UPDATE
Something to add is that I need to calculate my weight beforehand, because it is calculated with an ajax request which takes the choosen product options and returns the calculated price and weight for the product. Calculating this every time the product is set would makes things slow, unnecessarily complicated and possibly prone to bugs.


Get this bounty!!!

#StackBounty: #magento2 #layered-navigation #grouped-products Grouped Products: Filter based on simple products

Bounty: 100

The problem

I’m currently building a Magento 2 store which sells items in boxes and as singles (eg. a single item or a sealed box of 12). The product page has a grid which lets you add any number of boxes and any number of singles to your basket in one go.

I’ve currently got this set up with grouped/simple products – one product called FOO-GROUP which is placed into the relevant categories (but not given any attributes such as colour, size, etc) then individual products called FOO-L-ONE, FOO-L-BOX, FOO-M-ONE and so on which have the attributes set on them.

Grouped products are set to show up in Catalog and Search, while the simple products are set not to show up individually.

The problem is that on the category listing page, there are no filters for colour, size, price etc. because the grouped products don’t have those attributes – the simple products do, but those simple products are set not to show in the catalog listing.


The planned solution

I’m trying to find where the layered navigation gets its products from, then iterate over those products to check if each one is a grouped product. If so, I’d like to inject its child products instead of the group.

I’ve found a Magento.SE post which seems to be doing the same thing for Magento 1, but can’t find anything on how to do this in Magento 2. I’ve looked through the Layered Navigation module, the Catalog module and the Grouped Product module but not been able to figure out what I need to change where.


Help

There are two ways this could go (that I can think of).

I might be trying to do this the correct way and not being able to find the right bit of code – if so, any suggestions on where I should be looking are much appreciated.

It’s also entirely possible that I’m doing something fundamentally wrong, and perhaps shouldn’t be using grouped products or shouldn’t be doing something else that I am. If that’s the case, please suggest how you’d set up the same situation and I can try that.


Get this bounty!!!

#StackBounty: #magento2 #error #compilation Incompatible argument type error in Magento 2.2.2

Bounty: 50

I have installed Magento 2.2.2.

Running php bin/magento setup:di:compile result in this error:

MagentoBackendModelViewLayoutGeneratorPool
Incompatible argument type: Required type: MagentoFrameworkViewLayoutConditionConditionFactory.

Actual type: MagentoFrameworkAppConfigScopeConfigInterface; File: 
vendor/magento/module-backend/Model/View/Layout/GeneratorPool.php

In

vendor/magento/framework/View/Layout/Condition/ConditionFactory.php:

<?php

namespace MagentoFrameworkViewLayoutCondition;

use MagentoFrameworkObjectManagerInterface;

/**
 * Factory for composite.
 */
class ConditionFactory
{
    /**
     * @var ObjectManagerInterface
     */
    private $objectManager;

    /**
     * @param ObjectManagerInterface $objectManager
     */
    public function __construct(ObjectManagerInterface $objectManager)
    {
        $this->objectManager = $objectManager;
    }

    /**
     * @param array $elementVisibilityConditions
     *
     * @return Condition
     */
    public function create(array $elementVisibilityConditions)
    {
        $conditions = [];
        foreach ($elementVisibilityConditions as $condition) {
            $conditions[] = $this->objectManager->create($condition['name']);
        }
        return $this->objectManager->create(Condition::class, ['conditions' => $conditions]);
    }
}

In

vendor/magento/module-backend/Model/View/Layout/GeneratorPool.php:

<?php
namespace MagentoBackendModelViewLayout;

use MagentoFrameworkViewLayoutScheduledStructure;
use MagentoFrameworkViewLayoutDataStructure;

/**
 * Pool of generators for structural elements
 */
class GeneratorPool extends MagentoFrameworkViewLayoutGeneratorPool
{
    /**
     * @var FilterAcl
     */
    protected $aclFilter;

    /**
     * @param ScheduledStructureHelper $helper
     * @param MagentoFrameworkAppConfigScopeConfigInterface $scopeConfig
     * @param MagentoFrameworkAppScopeResolverInterface $scopeResolver
     * @param PsrLogLoggerInterface $logger
     * @param FilterAcl $aclFilter
     * @param array $generators
     */
    public function __construct(
        ScheduledStructureHelper $helper,
        MagentoFrameworkAppConfigScopeConfigInterface $scopeConfig,
        MagentoFrameworkAppScopeResolverInterface $scopeResolver,
        PsrLogLoggerInterface $logger,
        FilterAcl $aclFilter,
        array $generators = null
    ) {
        $this->aclFilter = $aclFilter;
        parent::__construct(
            $helper,
            $scopeConfig,
            $scopeResolver,
            $logger,
            $generators
        );
    }

    /**
     * Build structure that is based on scheduled structure
     *
     * @param ScheduledStructure $scheduledStructure
     * @param Structure $structure
     * @return $this
     */
    protected function buildStructure(ScheduledStructure $scheduledStructure, Structure $structure)
    {
        parent::buildStructure($scheduledStructure, $structure);
        $this->aclFilter->filterAclElements($scheduledStructure, $structure);
        return $this;
    }
}

What is the fix?


Get this bounty!!!

#StackBounty: #magento2 #price #catalog #product-list #tierprice Magento2 – include possible tier price in getProductPrice() product list

Bounty: 50

Our customer would like to display lowest possible price in product list pages

This is the function which displays the price

MagentoCatalogBlockProductListProduct

public function getProductPrice(MagentoCatalogModelProduct $product)
{
    $priceRender = $this->getPriceRender();

    $price = '';
    if ($priceRender) {
        $price = $priceRender->render(
            MagentoCatalogPricingPriceFinalPrice::PRICE_CODE,
            $product,
            [
                'include_container' => true,
                'display_minimal_price' => true,
                'zone' => MagentoFrameworkPricingRender::ZONE_ITEM_LIST,
                'list_category_page' => true
            ]
        );
    }

    return $price;
}

The fast try (changing MagentoCatalogPricingPriceFinalPrice::PRICE_CODE to MagentoCatalogPricingPriceTierPrice::PRICE_CODE) obviously doesn’t work, as TierPrice should return an array or some complex data and not a price amount

How to achieve this? Any tips?


Get this bounty!!!

#StackBounty: #magento2 #discount #coupon #totals #checkout-page Working of discount coupons on the checkout page in Magento 2.2.2

Bounty: 50

I am trying to understand the working of discount coupon codes on the checkout page.

When we apply any coupon code, then the discount is added without reloading the page.

I checked and found some below points:

  • discount” totals segment is added by Magento_SalesRule module.

When we apply any coupon code then, using vendormagentomodule-sales-ruleviewfrontendwebjsactionset-coupon-code.js, an ajax request is send to rest/default/V1/carts/mine/coupons/:coupon.

Code from vendormagentomodule-sales-ruleviewfrontendwebjsactionset-coupon-code.js :

 return storage.put(
            url,
            {},
            false
        ).done(function (response) {
            var deferred;

            if (response) {
                deferred = $.Deferred();

                isApplied(true);
                totals.isLoading(true);
                getPaymentInformationAction(deferred);
                $.when(deferred).done(function () 
                {
                    fullScreenLoader.stopLoader();
                    totals.isLoading(false);
                });
                messageContainer.addSuccessMessage({
                    'message': message
                });
            }
        }).fail(function (response) {
            fullScreenLoader.stopLoader();
            totals.isLoading(false);
            errorProcessor.process(response, messageContainer);
        });
  • After the above ajax call, Summary total section gets refresh and
    Discount appears in it [ Attached img ].

apply coupon

  • When we click on the cancel coupon button then code from
    vendormagentomodule-sales-ruleviewfrontendwebjsactioncancel-coupon.js
    runs and “Discount” disappears from the summary total section.

enter image description here

How does the total_segments add or remove “discount”?


Get this bounty!!!

#StackBounty: #magento2 #module #requirejs #dependency #magento2.2.3 Dependecy error bug? Magento 2.2.3

Bounty: 50

I’ve asked a similar question before, but because of some research, it would not have been relevant anymore. So here a more comprehensive explanation of my problem.

My scenario

I want the cart page to update without a refresh when the quantity has been changed of a product in the order list.

What I did

First of all, and most essential in this whole problem: I reinstalled Magento so there was a clean work environment I could test the module in.
Secondly, I created a module, named AjaxCart. This module consists of the following files:

Directory breakdown

module.xml has the following content:

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_AjaxCart" setup_version="2.0.0"/>
</config>

checkout_cart_index.xml has the following content:

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <link src="Vendor_AjaxCart/js/jquery.cartAjaxQty.js"/>
    </head>
</page>

requirejs-config.js has the following content:

var config = {
    map: {
        '*': {
            ajaxQty: 'Vendor_AjaxCart/js/jquery.cartAjaxQty'
        }
    }
};

and finally jquery.cartAjax.js has the following content:

    require(['jquery', 'Magento_Checkout/js/action/get-totals'], function () {
    jQuery(document).ready(function($, getTotalsAction){
        $(".cart-container .form-cart .action.update").remove();
        // On change handler
        jQuery(document).on('change', 'input[name$="[qty]"]', function(){
                    console.log("quantity changed");
                    var form = jQuery(jQuery(this).closest('form'));

                    $.ajax({
                        url: form.attr('action'),
                        data: form.serialize(),
                        showLoader: true,
                        context: this.changedInput,
                        success: function (res) {
                            var parsedResponse = $.parseHTML(res);
                            var result = $(parsedResponse).find("#form-validate");
                            $("#form-validate").replaceWith(result);
                            var deferred = $.Deferred();
                            getTotalsAction([], deferred);
                            console.log('Ajax succes function completed');
                        },
                        error: function (xhr, status, error) {
                            var err = eval("(" + xhr.responseText + ")");
                            console.log(err.Message);
                        }
                    });

                }
            );
    });
});

So, I also know where things go wrong: the requirements.
If the file only has the following requirement:

require([
    'jquery']

There is nothing wrong, and I can console.log the changes in quantities.

Problem

If I add the requirement I have in the file (which I need to update the cart summary block), I get the following error on the cart page:

sectionloadurl error

I don’t know if this is a Magento 2.2.x bug, or is it because of the file or directory structures I have made. Anyhow, it is something that has me in it’s grip for a long time and I am really thinking this is just a problem caused by Magento self and not my code.

I’m really curious if someone could try exactly what I did (except the clean install, a little bit too much to ask) and see if he/she gets the same problem or if someone knows an answer to this. I’ve also tried changing themes, but no luck.


Get this bounty!!!