0

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 &quot;Tuesday&quot; for Weekdays dropdown.
 */
const TUESDAY = &quot;Tue&quot;;

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

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

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

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

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

/**
 * {@inheritdoc}
 */
public function toOptionArray()
{
    return [
        ['value' =&gt; self::MONDAY, 'label' =&gt; __('Mon')],
        ['value' =&gt; self::TUESDAY, 'label' =&gt; __('Tue')],
        ['value' =&gt; self::WEDNESDAY, 'label' =&gt; __('Wed')],
        ['value' =&gt; self::THURSDAY, 'label' =&gt; __('Thu')],
        ['value' =&gt; self::FRIDAY, 'label' =&gt; __('Fri')],
        ['value' =&gt; self::SATURDAY, 'label' =&gt; __('Sat')],
        ['value' =&gt; self::SUNDAY, 'label' =&gt; __('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-&gt;getRequest();

    $postData = $request-&gt;getPostValue();

    $apply_on_weekday = $postData['apply_on_weekday'];

    if($apply_on_weekday &amp;&amp; is_array($apply_on_weekday)) {
        $apply_on_weekday = implode(',', $apply_on_weekday);
    }

    $request-&gt;setPostValue('apply_on_weekday', $apply_on_weekday);

    $writer = new \Zend_Log_Writer_Stream(BP . '/var/log/custom.log');
    $logger = new \Zend_Log();
    $logger-&gt;addWriter($writer);
    $logger-&gt;info('Your text message');
    $logger-&gt;info(json_encode($request-&gt;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?

Harsh Patel
  • 219
  • 1
  • 10

1 Answers1

1

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-&gt;getApplyOnWeekday())) {
        $applyOnWeekday = implode(',', $rule-&gt;getApplyOnWeekday());
        $rule-&gt;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

Harsh Patel
  • 219
  • 1
  • 10
Tu Van
  • 6,868
  • 2
  • 11
  • 22
  • 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. – Harsh Patel Nov 08 '22 at 05:13
  • Glad to help you. Cheers. – Tu Van Nov 08 '22 at 05: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? – Harsh Patel Nov 08 '22 at 06:43
  • It is Magento\SalesRule\Model\Utility::canProcessRule located in file: vendor/magento/module-sales-rule/Model/Utility.php – Tu Van Nov 08 '22 at 08:56
  • you mean we can put to validate apply_on_weekday field using beforeCanProcessRule plugin method. am i right? – Harsh Patel Nov 08 '22 at 09:06
  • No, I mean it is where Magento validates the salesRule date is valid. That method leads you to Magento\Rule\Model\Condition\Combine::validate, try to add afterValidate plugin and validate the date and weekday here. If you spend much time but do not get it works, let's create a new question "How to validate a custom field in sale rule", that will help other has same issue. – Tu Van Nov 08 '22 at 09:24
  • In the afterValidate plugin, check if $result is true, then validate weekday because the date is already valid. – Tu Van Nov 08 '22 at 09:54
  • hey see I opened question related to validate this custom field before applying sales rule https://magento.stackexchange.com/q/361557/93504 – Harsh Patel Nov 08 '22 at 09:57
  • 1
    Let's try it yourself first, I'll come later if you spend much time but do not get it works. – Tu Van Nov 08 '22 at 10:50
  • hey i can't understand how can i validate weekdays before salesrule applies to cart. can you help me? – Harsh Patel Nov 09 '22 at 10:18
  • Sure, I'll take a look. – Tu Van Nov 09 '22 at 10:49
  • hey brother, I think that maybe you're forgetting to answer about how to validate weekdays before salesrule applies to the cart – Harsh Patel Nov 10 '22 at 04:25
  • hey Harsh Patel, no worries. As you know your issue needs time, but I've added your issue to my queue. I think I can give you the solution today. – Tu Van Nov 10 '22 at 04:47