1

I need to save custom multiselect field value in the apply_on_weekday column which is located in the salesrule Db table. I tried a lot but it doesn't save the data in the database.

Below is my code.

Vendor\Module\view\adminhtml\ui_component\sales_rule_form.xml

<?xml version="1.0" encoding="UTF-8"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="rule_information" sortOrder="10">
        <field name="apply_on_weekday" formElement="multiselect">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <!-- <item name="dataType" xsi:type="string">int</item> -->
                    <item name="source" xsi:type="string">sales_rule</item>
                    <item name="default" xsi:type="string">Mon</item>
                </item>
            </argument>
            <settings>
                <label translate="true">Apply for specific weekdays</label>
                <dataScope>apply_on_weekday</dataScope>
            </settings>
            <formElements>
                <multiselect>
                    <settings>
                        <options class="Vendor\Module\Model\Config\Source\Weekdays"/>
                    </settings>
                </multiselect>
            </formElements>
        </field>
    </fieldset>
</form>

Vendor\Module\Model\Config\Source\Weekdays.php file

<?php

namespace Vendor\Module\Model\Config\Source;

use Magento\Framework\Data\OptionSourceInterface;

class Weekdays implements OptionSourceInterface
{
    /**
     * Value which equal "Monday" for Weekdays dropdown.
     */
    const MONDAY = "Mon";

    /**
     * Value which equal "Tuesday" for Weekdays dropdown.
     */
    const TUESDAY = "Tue";

    /**
     * Value which equal "Wednesday" for Weekdays dropdown.
     */
    const WEDNESDAY = "Wed";

    /**
     * Value which equal "Thursday" for Weekdays dropdown.
     */
    const THURSDAY = "Thu";

    /**
     * Value which equal "Friday" for Weekdays dropdown.
     */
    const FRIDAY = "Fri";

    /**
     * Value which equal "Saturday" for Weekdays dropdown.
     */
    const SATURDAY = "Sat";

    /**
     * Value which equal "Sunday" for Weekdays dropdown.
     */
    const SUNDAY = "Sun";

    /**
     * {@inheritdoc}
     */
    public function toOptionArray()
    {
        return [
            ['value' => self::MONDAY, 'label' => __('Mon')],
            ['value' => self::TUESDAY, 'label' => __('Tue')],
            ['value' => self::WEDNESDAY, 'label' => __('Wed')],
            ['value' => self::THURSDAY, 'label' => __('Thu')],
            ['value' => self::FRIDAY, 'label' => __('Fri')],
            ['value' => self::SATURDAY, 'label' => __('Sat')],
            ['value' => self::SUNDAY, 'label' => __('Sun')],
        ];
    }
}

when we create select formComponent field then We need to declare field in UI_component the xml file only. but here we use multiselect formComponent, now when form submits it will give apply_on_weekday field value in terms of array format.

now we wants to save it in a single row column. So we need to convert apply_on_weekday field value array into comma seperated string to save it in a single column.

So, I use adminhtml_controller_salesrule_prepare_save event

Vendor\Module\etc\events.xml

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">    
    <event name="adminhtml_controller_salesrule_prepare_save">
        <observer name="vendor_module_adminhtml_controller_salesrule_prepare_save" instance="Vendor\Module\Observer\SalesrulePrepareSaveObserver"/>
    </event>
</config>

Vendor\Module\Observer\SalesrulePrepareSaveObserver.php

<?php

namespace Vendor\Module\Observer;

use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;

class SalesrulePrepareSaveObserver implements ObserverInterface {

    /**
     * @param \Magento\Framework\Event\Observer $observer
     * @return $this
     */
    public function execute(EventObserver $observer) {

        /** @var \Magento\Framework\App\RequestInterface */
        $request = $observer->getRequest();

        $postData = $request->getPostValue();

        $apply_on_weekday = $postData['apply_on_weekday'];

        if($apply_on_weekday && is_array($apply_on_weekday)) {
            $apply_on_weekday = implode(',', $apply_on_weekday);
        }
        
        $request->setPostValue('apply_on_weekday', $apply_on_weekday);
        
        $writer = new \Zend_Log_Writer_Stream(BP . '/var/log/custom.log');
        $logger = new \Zend_Log();
        $logger->addWriter($writer);
        $logger->info('Your text message');
        $logger->info(json_encode($request->getPostValue()));
        // return $this;
    }

}

when i debugging, I found that comma seperated value saved in the request. but after that event magento use old data array to store it in the database. see this controller here i found that magento doesn't take updated data to store it. So what can I do?

1 Answer 1

2

Because of adminhtml_controller_salesrule_prepare_save event does not return value to $data in Magento\SalesRule\Controller\Adminhtml\Promo\Quote\Save controller, you should use salesrule_rule_save_before event instead.

So, to convert your multiselect field value to string before saving Salesrule, take the following steps:

  1. Create app/code/Vendor/Module/etc/events.xml with the following code:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="salesrule_rule_save_before">
        <observer name="ConvertMultiSelectData" instance="Vendor\Module\Observer\ConvertMultiSelectData" />
    </event>
</config>

  1. Create Vendor/Module/Observer/ConvertMultiSelectData.php file:
<?php

namespace Vendor\Module\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

/**
 *  Convert multiSelect fields data before save.
 */
class ConvertMultiSelectData implements ObserverInterface
{
    /**
     * Convert multiSelect fields data before save.
     *
     * @param Observer $observer
     * @return $this
     */
    public function execute(Observer $observer)
    {
        /** @var \Magento\SalesRule\Model\Rule $rule */
        $rule = $observer->getEvent()->getRule();

        if (is_array($rule->getApplyOnWeekday())) {
            $applyOnWeekday = implode(',', $rule->getApplyOnWeekday());
            $rule->setApplyOnWeekday($applyOnWeekday);
        }

        return $this;
    }
}

Clear the cache. You're done.


How to save extension attribute in Salesrule Api magento 2.4

How to validate a custom field in sales rule before the discount applying to cart in magento 2.4

13
  • yeah, thats working perfectly. actually before opning this question, I was already tried that salesrule_rule_save_before model save before event. but unfortunately that custom field wasn't save in DB. then after I tried adminhtml_controller_salesrule_prepare_save event which is fired from Save Controller during admin form submits event. Thank you brother for your valuable time. Commented Nov 8, 2022 at 5:13
  • Glad to help you. Cheers.
    – Tu Van
    Commented Nov 8, 2022 at 5:23
  • brother I have one question, where magento validate the salesRule Date is valid or not before applying salesRule to cart. I check Magento SalesRule Module but I wasn't get any idea. Actually I need to validate date, then if date valid then i need to validate Day which one saved in apply_on_weekday column in salesrule Table. can you tell me this? Commented Nov 8, 2022 at 6:43
  • It is Magento\SalesRule\Model\Utility::canProcessRule located in file: vendor/magento/module-sales-rule/Model/Utility.php
    – Tu Van
    Commented Nov 8, 2022 at 8:56
  • 1
    Let's try it yourself first, I'll come later if you spend much time but do not get it works.
    – Tu Van
    Commented Nov 8, 2022 at 10:50

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.