OFFLINE-GmbH / oc-mall-plugin

:convenience_store: E-commerce solution for October CMS
https://offline-gmbh.github.io/oc-mall-plugin
MIT License
166 stars 112 forks source link

Shipping: pick up point can't validate #1148

Open adamo opened 2 weeks ago

adamo commented 2 weeks ago

I've created a plugin to add pickup point to shipping method. If a shipping method is a parcel pickup point.

Then in the shippingmethod.htm partial I've added a component that shows a pickup point with a hidden field.

{% if cart.shipping_method.is_inpost %}
<div class="parcel-point-select" style='min-height: 540px;display: flex;'>
    <inpost-geowidget style='width: 100%;' onpoint="onpointselect" token='' language='pl' config='parcelcollect'></inpost-geowidget>
</div>
<div class="form-group">
    <input name="pick_up_point_id" id="pick_up_point_id" value='' type='hidden'>
    <div data-validate-for='pick_up_point_id'>test</div>
</div>
{% endif %}

Now the fields should be validated conditionally, but first I've tried to extend the validation in my plugin boot() method this is a version of the extend method that has gone through every possible variant I could think of but non of them added a validation error in the front end.

  Order::extend(function ($model) {
            $model->rules['pick_up_point_id'] = 'required';
            $model->messages['pick_up_point_id.required'] = 'Please choose a pick up point.';

            $model->bindEvent('model.beforeValidate', function () use ($model) {
                $model->rules['pick_up_point_id'] = 'required';
            });
});

What am I missing? Should the validation be added somewhere else? I'm currently using the Quick Checkout component to test this.

UPDATE: I've added a field to the order model and I'm forcing the field to be required - problem that the validation id fired after the user is created so even if the customer chooses a point, he'll get an this email is taken error.

adamo commented 1 week ago

I've found a solution which feels hacky, in the quickcheckout component I've added a validation in the onSubmit method

public function onSubmit()
    {
        $data = post();

        if ($this->cart->shipping_method->is_inpost) {

            if ($data['pick_up_point_id'] == '') {
                $data = Request::validate([
                    'pick_up_point_id' => 'required',
                ]);
            }
        }
// rest of the method code
}

Not sure how to move this code to the Pugin.php files boot() method. Any help would be appreciated.

adamo commented 4 days ago

I've ended adding a event listen to the QuickCheckout component method onSubmit

 public function onSubmit()
    {
        $data = post();

        Event::fire('offline.mall.beforeOnSubmit', [$this->cart, $data]);

        // The user is not signed in. Let's create a new account.
        if (!$this->user) {
            $this->user = app(SignUpHandler::class)->handle($data, (bool)post('as_guest'));
            if (!$this->user) {
                throw new ValidationException(
                    [trans('offline.mall::lang.components.quickCheckout.errors.signup_failed')]
                );
            }
            $this->cart = $this->cart->refresh();
        }
...

Then in the plugin I could extend the logic

        Event::listen('offline.mall.beforeOnSubmit', function ($cart, $data) {
            if ($cart->shipping_method->is_inpost) {
                if ($data['pick_up_point_id'] == '') {
                    $data = \Request::validate([
                        'pick_up_point_id' => 'required',
                    ]);
                }
            }
        });

This got me thinking about implementing more if the same logic in other places like the backend order view where I'd had to use this trick to override the view to add another button with functionality.

        Orders::extend(function ($controller) {
            list($author, $plugin) = explode('\\', strtolower(get_class()));
            $partials_path = sprintf('$/%s/%s/partials/orders', $author, $plugin);
            $controller->addViewPath($partials_path);
        });