0

I'm trying to create a module which adds 2 fields in bundle option. I've already managed to add 2 field: enter image description here However, it doesn't save the values in my database. The columns are created, but they are not populated with the correct values.

Here is my code:

Plugin\Ui\DataProvider\Product\Form\Modifier\Composite.php

<?php
declare(strict_types=1);

namespace Es100\ManageBundleMaxMin\Plugin\Ui\DataProvider\Product\Form\Modifier;

use Magento\Bundle\Ui\DataProvider\Product\Form\Modifier\Composite as BundleComposite;
use Magento\Catalog\Model\Locator\LocatorInterface;
use Magento\Bundle\Model\Product\Type;
use Magento\Bundle\Ui\DataProvider\Product\Form\Modifier\BundlePanel;
use Magento\Bundle\Model\Selection;

class Composite
{
protected $locator;
protected $selection;

/**
 * @param LocatorInterface $locator
 * @param Selection $selection
 */
public function __construct(
    LocatorInterface $locator,
    Selection $selection
) {
    $this->locator = $locator;
    $this->selection = $selection;
}

public function afterModifyData(BundleComposite $subject, array $data)
{
    $product = $this->locator->getProduct();
    $modelId = $product->getId();
    $isBundleProduct = $product->getTypeId() === Type::TYPE_CODE;
    if ($isBundleProduct && $modelId) {
        foreach ($data[$modelId][BundlePanel::CODE_BUNDLE_OPTIONS][BundlePanel::CODE_BUNDLE_OPTIONS] as &$option) {
            foreach ($option['bundle_selections'] as &$selection) {
                $this->selection->load($selection['selection_id']);
                $selection['min_qty'] = $this->selection->getMinQty();
                $selection['max_qty'] = $this->selection->getMaxQty();
            }
        }
    }

    return $data;
}
}

Model\LinkManagement.php

<?php
declare(strict_types=1);

namespace Es100\ManageBundleMaxMin\Model;

use Magento\Bundle\Api\Data\LinkInterface;
use Magento\Bundle\Api\Data\LinkInterfaceFactory;
use Magento\Bundle\Model\ResourceModel\Bundle;
use Magento\Bundle\Model\ResourceModel\BundleFactory;
use Magento\Bundle\Model\ResourceModel\Option\CollectionFactory;
use Magento\Bundle\Model\Selection;
use Magento\Bundle\Model\SelectionFactory;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\Api\DataObjectHelper;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Exception\InputException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Store\Model\StoreManagerInterface;

class LinkManagement extends \Magento\Bundle\Model\LinkManagement
{
/**
 * @var StoreManagerInterface
 */
private $storeManager;

/**
 * @var MetadataPool
 */
private $metadataPool;

public function __construct(
    ProductRepositoryInterface $productRepository,
    LinkInterfaceFactory $linkFactory,
    SelectionFactory $bundleSelection,
    BundleFactory $bundleFactory,
    CollectionFactory $optionCollection,
    StoreManagerInterface $storeManager,
    DataObjectHelper $dataObjectHelper,
    MetadataPool $metadataPool
) {
    parent::__construct(
        $productRepository,
        $linkFactory,
        $bundleSelection,
        $bundleFactory,
        $optionCollection,
        $storeManager,
        $dataObjectHelper,
        $metadataPool
    );
    $this->storeManager = $storeManager;
    $this->metadataPool = $metadataPool;
}

/**
 * {@inheritdoc}
 *
 * Mappa i campi min_qty e max_qty durante il salvataggio.
 */
protected function mapProductLinkToSelectionModel(
    Selection $selectionModel,
    LinkInterface $productLink,
    $linkedProductId,
    $parentProductId
): Selection {
    $selectionModel = parent::mapProductLinkToSelectionModel($selectionModel, $productLink, $linkedProductId, $parentProductId);

        $selectionModel->setData('min_qty', $productLink->getMinQty());
        $selectionModel->setData('max_qty', $productLink->getMaxQty());

    return $selectionModel;
  }
}

Plugin\Ui\DataProvider\Product\Form\Modifier\BundleCustomOptions.php

<?php
declare(strict_types=1);

namespace Es100\ManageBundleMaxMin\Plugin\Ui\DataProvider\Product\Form\Modifier;

 use Magento\Ui\Component\Form\Field;
 use Magento\Ui\Component\Form\Element\Input;
 use Magento\Ui\Component\Form\Element\DataType\Number;
 use Magento\Bundle\Ui\DataProvider\Product\Form\Modifier\BundleCustomOptions as MagentoBundleCustomOptions;

class BundleCustomOptions
{
const FIELD_MIN_QTY = 'min_qty';
const FIELD_MAX_QTY = 'max_qty';

public function afterModifyMeta(MagentoBundleCustomOptions $subject, array $meta)
{
    if (isset($meta['bundle-items']['children']['bundle_options']['children']['record']['children']['product_bundle_container']['children']['bundle_selections']['children']['record']['children'])) {
        $meta['bundle-items']['children']['bundle_options']['children']['record']['children']['product_bundle_container']['children']['bundle_selections']['children']['record']['children'][static::FIELD_MIN_QTY] = $this->getMinQtyFieldConfig(125);
        $meta['bundle-items']['children']['bundle_options']['children']['record']['children']['product_bundle_container']['children']['bundle_selections']['children']['record']['children'][static::FIELD_MAX_QTY] = $this->getMaxQtyFieldConfig(126);

        // Reorder table headings
        $actionDelete = $meta['bundle-items']['children']['bundle_options']['children']['record']['children']['product_bundle_container']['children']['bundle_selections']['children']['record']['children']['action_delete'];
        unset($meta['bundle-items']['children']['bundle_options']['children']['record']['children']['product_bundle_container']['children']['bundle_selections']['children']['record']['children']['action_delete']);
        $meta['bundle-items']['children']['bundle_options']['children']['record']['children']['product_bundle_container']['children']['bundle_selections']['children']['record']['children']['action_delete'] = $actionDelete;
    }

    return $meta;
}

protected function getMinQtyFieldConfig($sortOrder)
{
    return [
        'arguments' => [
            'data' => [
                'config' => [
                    'label' => __('Quantità Minima'),
                    'componentType' => Field::NAME,
                    'formElement' => Input::NAME,
                    'dataScope' => static::FIELD_MIN_QTY,
                    'dataType' => Number::NAME,
                    'sortOrder' => $sortOrder,
                    'validation' => [
                        'validate-number' => true,
                        'validate-zero-or-greater' => true
                    ],
                    'default' => 1,
                ],
            ],
        ],
    ];
}

protected function getMaxQtyFieldConfig($sortOrder)
{
    return [
        'arguments' => [
            'data' => [
                'config' => [
                    'label' => __('Quantità Massima'),
                    'componentType' => Field::NAME,
                    'formElement' => Input::NAME,
                    'dataScope' => static::FIELD_MAX_QTY,
                    'dataType' => Number::NAME,
                    'sortOrder' => $sortOrder,
                    'validation' => [
                        'validate-number' => true,
                        'validate-zero-or-greater' => true
                    ],
                    'default' => 1,
                ],
            ],
        ],
    ];
  }
}

Setup\UpgradeSchema.php

<?php
declare(strict_types=1);

namespace Es100\ManageBundleMaxMin\Setup;

use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\DB\Ddl\Table;

class UpgradeSchema implements UpgradeSchemaInterface
{
public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
{
    $setup->startSetup();

    if (version_compare($context->getVersion(), '1.0.0', '<')) {
        $connection = $setup->getConnection();
        $tableName = $setup->getTable('catalog_product_bundle_selection');

        if ($connection->isTableExists($tableName)) {
            if (!$connection->tableColumnExists($tableName, 'min_qty')) {
                $connection->addColumn(
                    $tableName,
                    'min_qty',
                    [
                        'type' => Table::TYPE_INTEGER,
                        'nullable' => true,
                        'comment' => 'Quantità minima'
                    ]
                );
            }

            if (!$connection->tableColumnExists($tableName, 'max_qty')) {
                $connection->addColumn(
                    $tableName,
                    'max_qty',
                    [
                        'type' => Table::TYPE_INTEGER,
                        'nullable' => true,
                        'comment' => 'Quantità massima'
                    ]
                );
            }
        }
    }

    $setup->endSetup();
 }
}

1 Answer 1

0

This is the whole code which works perfectly !!!!

you need to setMinQty and setMaxQty in this function below

  1. di.xml

    <type name="Magento\Bundle\Ui\DataProvider\Product\Form\Modifier\BundleCustomOptions">
                <plugin name="aam_image_bundleCustomOptions" type="Aam\Image\Plugin\Ui\DataProvider\Product\Form\Modifier\BundleCustomOptions" sortOrder="1"/>
    
    </type> 
    <type name="Magento\Bundle\Ui\DataProvider\Product\Form\Modifier\Composite">
                <plugin name="aam_image_composite" type="Aam\Image\Plugin\Ui\DataProvider\Product\Form\Modifier\Composite" sortOrder="1"/>
    
    </type> 
        <preference for="Magento\Bundle\Model\LinkManagement" type="Aam\Image\Model\LinkManagement" />
    
  2. LinkManagement.php

namespace Aam\Image\Model;

    use Magento\Bundle\Api\Data\LinkInterface;
    use Magento\Bundle\Api\Data\LinkInterfaceFactory;
    use Magento\Bundle\Model\ResourceModel\Bundle;
    use Magento\Bundle\Model\ResourceModel\BundleFactory;
    use Magento\Bundle\Model\ResourceModel\Option\CollectionFactory;
    use Magento\Bundle\Model\Selection;
    use Magento\Bundle\Model\SelectionFactory;
    use Magento\Catalog\Api\Data\ProductInterface;
    use Magento\Catalog\Api\ProductRepositoryInterface;
    use Magento\Framework\Api\DataObjectHelper;
    use Magento\Framework\EntityManager\MetadataPool;
    use Magento\Framework\Exception\CouldNotSaveException;
    use Magento\Framework\Exception\InputException;
    use Magento\Framework\Exception\NoSuchEntityException;
    use Magento\Store\Model\StoreManagerInterface;
    
    class LinkManagement extends \Magento\Bundle\Model\LinkManagement
    {
    /**
     * @var StoreManagerInterface
     */
    private $storeManager;
    
    /**
     * @var MetadataPool
     */
    private $metadataPool;
    
    public function __construct(
    ProductRepositoryInterface $productRepository,
    LinkInterfaceFactory $linkFactory,
    SelectionFactory $bundleSelection,
    BundleFactory $bundleFactory,
    CollectionFactory $optionCollection,
    StoreManagerInterface $storeManager,
    DataObjectHelper $dataObjectHelper,
    MetadataPool $metadataPool
    ) {
    parent::__construct(
        $productRepository,
        $linkFactory,
        $bundleSelection,
        $bundleFactory,
        $optionCollection,
        $storeManager,
        $dataObjectHelper,
        $metadataPool
    );
    $this->storeManager = $storeManager;
    $this->metadataPool = $metadataPool;
    }
    
    
    
    public function saveChild(
    $sku,
    LinkInterface $linkedProduct
    ) {
    $product = $this->productRepository->get($sku, true);
    if ($product->getTypeId() != 'bundle') {
        throw new InputException(
            __('The product with the "%1" SKU isn\'t a bundle product.', [$product->getSku()])
        );
    }
    
    /** @var Product $linkProductModel */
    $linkProductModel = $this->productRepository->get($linkedProduct->getSku());
    if ($linkProductModel->isComposite()) {
        throw new InputException(__('The bundle product can\'t contain another composite product.'));
    }
    
    if (!$linkedProduct->getId()) {
        throw new InputException(__('The product link needs an ID field entered. Enter and try again.'));
    }
    
    /** @var Selection $selectionModel */
    $selectionModel = $this->bundleSelection->create();
    $selectionModel->load($linkedProduct->getId());
    if (!$selectionModel->getId()) {
        throw new InputException(
            __(
                'The product link with the "%1" ID field wasn\'t found. Verify the ID and try again.',
                [$linkedProduct->getId()]
            )
        );
    }
    $selectionModel = $this->mapProductLinkToBundleSelectionModel(
        $selectionModel,
        $linkedProduct,
        $product,
        (int)$linkProductModel->getId()
    );
    $selectionModel->setMinQty(1);
    $selectionModel->setMaxQty(43);
    try {
        $selectionModel->save();
    } catch (\Exception $e) {
        throw new CouldNotSaveException(__('Could not save child: "%1"', $e->getMessage()), $e);
    }
    
    return true;
    }
/**
     * Fill selection model with product link data.
     *
     * @param Selection $selectionModel
     * @param LinkInterface $productLink
     * @param ProductInterface $parentProduct
     * @param int $linkedProductId
     * @param string $linkField
     * @return Selection
     * @throws NoSuchEntityException
     */
    private function mapProductLinkToBundleSelectionModel(
        Selection $selectionModel,
        LinkInterface $productLink,
        ProductInterface $parentProduct,
        int $linkedProductId
    ): Selection {
        $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField();
        $selectionModel->setProductId($linkedProductId);
        $selectionModel->setParentProductId($parentProduct->getData($linkField));
        if ($productLink->getSelectionId() !== null) {
            $selectionModel->setSelectionId($productLink->getSelectionId());
        }
        if ($productLink->getOptionId() !== null) {
            $selectionModel->setOptionId($productLink->getOptionId());
        }
        if ($productLink->getPosition() !== null) {
            $selectionModel->setPosition($productLink->getPosition());
        }
        if ($productLink->getQty() !== null) {
            $selectionModel->setSelectionQty($productLink->getQty());
        }
        if ($productLink->getPriceType() !== null) {
            $selectionModel->setSelectionPriceType($productLink->getPriceType());
        }
        if ($productLink->getPrice() !== null) {
            $selectionModel->setSelectionPriceValue($productLink->getPrice());
        }
        if ($productLink->getCanChangeQuantity() !== null) {
            $selectionModel->setSelectionCanChangeQty($productLink->getCanChangeQuantity());
        }
        if ($productLink->getIsDefault() !== null) {
            $selectionModel->setIsDefault($productLink->getIsDefault());
        }
        $selectionModel->setWebsiteId((int)$this->storeManager->getStore($parentProduct->getStoreId())->getWebsiteId());

        return $selectionModel;
    }
    }

3.BundleCustomOptions (same as yours)

4.Composite (same as yours)

in database you can see its saving.

enter image description here

11
  • Thank you for your response. I've attempted to modify Linkmanagement.php with your code, but it still doesn't save neither.
    – Petacchi
    Commented Jul 2 at 8:02
  • just for testing purpose can you please add that code in core file to just confirm. if it works will override it, later
    – Kareem k
    Commented Jul 2 at 8:04
  • added 2 rows in core file (vendor/magento/module-bundle/Model/LinkManagement.php) but it doesn't save neighter
    – Petacchi
    Commented Jul 2 at 8:09
  • in this function mapProductLinkToBundleSelectionModel
    – Kareem k
    Commented Jul 2 at 8:11
  • yes,I'm 100% sure.
    – Petacchi
    Commented Jul 2 at 8:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.