EC-CUBE4で特定の都道府県のみ送料無料条件の適用を外す方法

EC-CUBE4で特定の都道府県のみ送料無料条件の適用を外す方法です。

沖縄県のみ送料無料条件を外す場合

以下のDeliveryFeeFreeByShippingPreprocessor.phpをCustomize/Service/PurchaseFlow/Processorディレクトリに設定して下さい。

<?php

/*
 * Copyright (C) 2019 Akira Kurozumi <info@a-zumi.net>.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301  USA
 */

namespace Customize\Service\PurchaseFlow\Processor;

use Eccube\Annotation\ShoppingFlow;
use Eccube\Entity\BaseInfo;
use Eccube\Entity\ItemHolderInterface;
use Eccube\Entity\Order;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Repository\Master\PrefRepository;
use Eccube\Service\PurchaseFlow\ItemHolderPreprocessor;
use Eccube\Service\PurchaseFlow\Processor\DeliveryFeePreprocessor;
use Eccube\Service\PurchaseFlow\PurchaseContext;

/**
 * 送料無料条件を適用する.
 * お届け先ごとに条件判定を行う.
 *
 * @ShoppingFlow()
 */
class DeliveryFeeFreeByShippingPreprocessor implements ItemHolderPreprocessor
{
    /**
     * @var BaseInfo
     */
    protected $BaseInfo;

    /**
     * @var PrefRepository
     */
    private $prefRepository;

    public function __construct(
        BaseInfoRepository $baseInfoRepository,
        PrefRepository $prefRepository
    ) {
        $this->BaseInfo = $baseInfoRepository->get();
        $this->prefRepository = $prefRepository;
    }

    /**
     * @param ItemHolderInterface $itemHolder
     * @param PurchaseContext $context
     */
    public function process(ItemHolderInterface $itemHolder, PurchaseContext $context)
    {
        if (!($this->BaseInfo->getDeliveryFreeAmount() || $this->BaseInfo->getDeliveryFreeQuantity())) {
            return;
        }

        // Orderの場合はお届け先ごとに判定する.
        if ($itemHolder instanceof Order) {
            // 送料無料条件適用を除外する都道府県を指定
            $noFreePref = '沖縄県';

            /** @var Order $Order */
            $Order = $itemHolder;
            foreach ($Order->getShippings() as $Shipping) {
                $isFree = false;
                $total = 0;
                $quantity = 0;
                foreach ($Shipping->getProductOrderItems() as $Item) {
                    $total += $Item->getPriceIncTax() * $Item->getQuantity();
                    $quantity += $Item->getQuantity();
                }
                // 送料無料(金額)を超えている
                if ($this->BaseInfo->getDeliveryFreeAmount()) {
                    if ($total >= $this->BaseInfo->getDeliveryFreeAmount()) {
                        $isFree = true;
                    }
                }
                // 送料無料(個数)を超えている
                if ($this->BaseInfo->getDeliveryFreeQuantity()) {
                    if ($quantity >= $this->BaseInfo->getDeliveryFreeQuantity()) {
                        $isFree = true;
                    }
                }
                // 送料無料条件を超えている場合
                if ($isFree) {
                    foreach ($Shipping->getOrderItems() as $Item) {
                        if ($Item->getProcessorName() == DeliveryFeePreprocessor::class) {
                            // 送料無料条件適用を除外する都道府県とマッチしたら送料明細の数量を1とする
                            if ($Shipping->getPref() == $this->prefRepository->findOneBy(['name' => $noFreePref])) {
                                $Item->setQuantity(1);
                                // 都道府県別送料設定で設定した送料と別の送料にしたい場合はこちらを追加
                                // $Item->setPrice(500);
                            }
                        }
                    }
                }
            }
        }
    }
}

複数の都道府県で送料無料条件を外す場合

<?php


namespace Customize\Service\PurchaseFlow\Processor;


use Eccube\Annotation\ShoppingFlow;
use Eccube\Entity\BaseInfo;
use Eccube\Entity\ItemHolderInterface;
use Eccube\Entity\Order;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Repository\Master\PrefRepository;
use Eccube\Service\PurchaseFlow\ItemHolderPreprocessor;
use Eccube\Service\PurchaseFlow\Processor\DeliveryFeePreprocessor;
use Eccube\Service\PurchaseFlow\PurchaseContext;

/**
 * @ShoppingFlow()
 *
 * Class DeliveryFeeFreeByShippingPreprocessor
 * @package Customize\Service\PurchaseFlow\Processor
 */
class DeliveryFeeFreeByShippingPreprocessor implements ItemHolderPreprocessor
{

    /**
     * @var BaseInfo
     */
    protected $BaseInfo;

    /**
     * @var PrefRepository
     */
    private $prefRepository;

    public function __construct(
        BaseInfoRepository $baseInfoRepository,
        PrefRepository $prefRepository
    )
    {
        $this->BaseInfo = $baseInfoRepository->get();
        $this->prefRepository = $prefRepository;
    }

    /**
     * @param ItemHolderInterface $itemHolder
     * @param PurchaseContext $context
     */
    public function process(ItemHolderInterface $itemHolder, PurchaseContext $context)
    {
        if (!($this->BaseInfo->getDeliveryFreeAmount() || $this->BaseInfo->getDeliveryFreeQuantity())) {
            return;
        }

        // Orderの場合はお届け先ごとに判定する.
        if ($itemHolder instanceof Order) {
            /** @var Order $Order */
            $Order = $itemHolder;
            foreach ($Order->getShippings() as $Shipping) {
                $isFree = false;
                $total = 0;
                $quantity = 0;
                foreach ($Shipping->getProductOrderItems() as $Item) {
                    $total += $Item->getPriceIncTax() * $Item->getQuantity();
                    $quantity += $Item->getQuantity();
                }
                // 送料無料(金額)を超えている
                if ($this->BaseInfo->getDeliveryFreeAmount()) {
                    if ($total >= $this->BaseInfo->getDeliveryFreeAmount()) {
                        $isFree = true;
                    }
                }
                // 送料無料(個数)を超えている
                if ($this->BaseInfo->getDeliveryFreeQuantity()) {
                    if ($quantity >= $this->BaseInfo->getDeliveryFreeQuantity()) {
                        $isFree = true;
                    }
                }
                // 送料無料条件を超えている場合
                if ($isFree) {
                    foreach ($Shipping->getOrderItems() as $Item) {
                        if ($Item->getProcessorName() == DeliveryFeePreprocessor::class) {
                            // 送料無料条件適用を除外する都道府県とマッチしたら送料明細の数量を1とする
                            $Prefs = $this->prefRepository->findBy(['name' => ['沖縄県', '東京都']]);
                            foreach ($Prefs as $Pref) {
                                if ($Shipping->getPref() === $Pref) {
                                    $Item->setQuantity(1);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

一部の都道府県の送料無料条件を外して都道府県別送料設定した金額の半額にする場合

<?php


namespace Customize\Service\PurchaseFlow\Processor;


use Eccube\Annotation\ShoppingFlow;
use Eccube\Entity\BaseInfo;
use Eccube\Entity\ItemHolderInterface;
use Eccube\Entity\Order;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Repository\Master\PrefRepository;
use Eccube\Service\PurchaseFlow\ItemHolderPreprocessor;
use Eccube\Service\PurchaseFlow\Processor\DeliveryFeePreprocessor;
use Eccube\Service\PurchaseFlow\PurchaseContext;

/**
 * @ShoppingFlow()
 *
 * Class DeliveryFeeFreeByShippingPreprocessor
 * @package Customize\Service\PurchaseFlow\Processor
 */
class DeliveryFeeFreeByShippingPreprocessor implements ItemHolderPreprocessor
{

    /**
     * @var BaseInfo
     */
    protected $BaseInfo;

    /**
     * @var PrefRepository
     */
    private $prefRepository;

    public function __construct(
        BaseInfoRepository $baseInfoRepository,
        PrefRepository $prefRepository
    )
    {
        $this->BaseInfo = $baseInfoRepository->get();
        $this->prefRepository = $prefRepository;
    }

    /**
     * @param ItemHolderInterface $itemHolder
     * @param PurchaseContext $context
     */
    public function process(ItemHolderInterface $itemHolder, PurchaseContext $context)
    {
        if (!($this->BaseInfo->getDeliveryFreeAmount() || $this->BaseInfo->getDeliveryFreeQuantity())) {
            return;
        }

        // Orderの場合はお届け先ごとに判定する.
        if ($itemHolder instanceof Order) {
            /** @var Order $Order */
            $Order = $itemHolder;
            foreach ($Order->getShippings() as $Shipping) {
                $isFree = false;
                $total = 0;
                $quantity = 0;
                foreach ($Shipping->getProductOrderItems() as $Item) {
                    $total += $Item->getPriceIncTax() * $Item->getQuantity();
                    $quantity += $Item->getQuantity();
                }
                // 送料無料(金額)を超えている
                if ($this->BaseInfo->getDeliveryFreeAmount()) {
                    if ($total >= $this->BaseInfo->getDeliveryFreeAmount()) {
                        $isFree = true;
                    }
                }
                // 送料無料(個数)を超えている
                if ($this->BaseInfo->getDeliveryFreeQuantity()) {
                    if ($quantity >= $this->BaseInfo->getDeliveryFreeQuantity()) {
                        $isFree = true;
                    }
                }
                // 送料無料条件を超えている場合
                if ($isFree) {
                    foreach ($Shipping->getOrderItems() as $Item) {
                        if ($Item->getProcessorName() == DeliveryFeePreprocessor::class) {
                            // 送料無料条件適用を除外する都道府県とマッチしたら送料明細の数量を1とする
                            $Prefs = $this->prefRepository->findBy(['name' => ['沖縄県', '東京都']]);
                            foreach ($Prefs as $Pref) {
                                if ($Shipping->getPref() === $Pref) {
                                    $Item->setQuantity(1);
                                    // 都道府県別送料設定で設定した送料の半額にしたい場合はこちらを追加
                                    $Item->setPrice(round ($Item->getPrice()/2));
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

送料無料条件を32400円以上に設定し、注文金額が10800円以上32400円未満の場合送料半額とする場合

<?php


namespace Customize\Service\PurchaseFlow\Processor;


use Eccube\Annotation\ShoppingFlow;
use Eccube\Entity\BaseInfo;
use Eccube\Entity\ItemHolderInterface;
use Eccube\Entity\Order;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Repository\Master\PrefRepository;
use Eccube\Service\PurchaseFlow\ItemHolderPreprocessor;
use Eccube\Service\PurchaseFlow\Processor\DeliveryFeePreprocessor;
use Eccube\Service\PurchaseFlow\PurchaseContext;

/**
 * @ShoppingFlow()
 *
 * Class DeliveryFeeFreeByShippingPreprocessor
 * @package Customize\Service\PurchaseFlow\Processor
 */
class DeliveryFeeFreeByShippingPreprocessor implements ItemHolderPreprocessor
{

    /**
     * @var BaseInfo
     */
    protected $BaseInfo;

    /**
     * @var PrefRepository
     */
    private $prefRepository;

    public function __construct(
        BaseInfoRepository $baseInfoRepository,
        PrefRepository $prefRepository
    )
    {
        $this->BaseInfo = $baseInfoRepository->get();
        $this->prefRepository = $prefRepository;
    }

    /**
     * @param ItemHolderInterface $itemHolder
     * @param PurchaseContext $context
     */
    public function process(ItemHolderInterface $itemHolder, PurchaseContext $context)
    {
        if (!($this->BaseInfo->getDeliveryFreeAmount() || $this->BaseInfo->getDeliveryFreeQuantity())) {
            return;
        }

        // Orderの場合はお届け先ごとに判定する.
        if ($itemHolder instanceof Order) {
            /** @var Order $Order */
            $Order = $itemHolder;
            foreach ($Order->getShippings() as $Shipping) {
                $isFree = false;
                $total = 0;
                $quantity = 0;
                foreach ($Shipping->getProductOrderItems() as $Item) {
                    $total += $Item->getPriceIncTax() * $Item->getQuantity();
                    $quantity += $Item->getQuantity();
                }
                // 送料無料(金額)を超えている
                if ($this->BaseInfo->getDeliveryFreeAmount()) {
                    if ($total >= $this->BaseInfo->getDeliveryFreeAmount()) {
                        $isFree = true;
                    }
                }
                // 送料無料(個数)を超えている
                if ($this->BaseInfo->getDeliveryFreeQuantity()) {
                    if ($quantity >= $this->BaseInfo->getDeliveryFreeQuantity()) {
                        $isFree = true;
                    }
                }
                // 送料無料条件を超えていない場合
                if (!$isFree) {
                    foreach ($Shipping->getOrderItems() as $Item) {
                        if ($Item->getProcessorName() == DeliveryFeePreprocessor::class) {
                            // 合計金額が10,800円以上32,400円未満の場合送料半額とする
                            if ($total >= 10800 && $total < 32400) {
                                $Item->setPrice(round ($Item->getPrice()/2));
                            }
                        }
                    }
                }
            }
        }
    }
}

14件のコメント

  1. EC-cube4の配送方法設定で沖縄の送料1600円その他の地域は一律送料700円、1万円以上買い上げの場合は送料無料の設定で沖縄だけは1万円超えても無料ではなく800円の送料としたい場合は
    上記の $Item->setPrice(500);を$Item->setPrice(800);とすればよろしいでしょうか?

  2. そのとおりです。

  3. お世話になります。
    上記コードを試してみたのですが、うまくいかず試行錯誤しています。

    すみませんが、基本的な事をお尋ねします。
    コードファイルのアップ先ディレクトリは「app」内の
    app/Customize/Service/PurchaseFlow/Processor
    でよろしかったでしょうか。

    よろしくお願いいたします。

  4. ご返信ありがとうございました。大変助かります。

  5. 調べているうちにここにたどり着きました。
    いろいろ試していますが、phpを手探りで勉強中の為、なかなかうまくいきません。

    1.複数の県に適用したい場合、どのように記載したらよいでしょうか。
    2.また、都道府県別送料設定で設定した送料と別の送料にしたい場合、固定の600円ではなく半額等と計算させたい場合、どのようにすればよろしいでしょうか。

    宜しくお願い致します。

  6. とても迅速なご対応ありがとうございました!
    本当に助かりました!!

  7. 都道府県ではなく、例えば送料無料条件を金32,400円以上に設定し、注文金額が10,800円以上32,400円未満の場合送料半額とする場合はどうすればいいでしょうか?いろいろやってみたんですが、実現できずかなり困っております。

  8. 早速実装方法記載いただき感謝申し上げます!
    サイトの方に実装して問題なく稼働できました!
    ありがとうございました。ほんとに困っていたので、こんなに早く対応していただけて感激ですm(__)m

  9. いつも拝見させていただいております。
    とても参考になる記述内容で助かっています!

    一部離島(例えば八丈島や石垣島など)の場合送料を1,000円加算する場合はどうしたらいいでしょうか・・・
    プラグインも参考になる記述もなく途方に暮れております・・・。
    是非ご教示頂ければと思い、書き込ませていただきました。

  10. いつも拝見させていただいております。都道府県の一部地域別 配送不能にはどのようにすればよいのでしょうか?

    宜しくお願い致します。

  11. 以前、1万円以上買い上げの場合は送料無料の設定で沖縄だけは1万円超えても無料ではなく800円の送料とする件でお問い合わせをした福島です。
    現在EC-CUBE4.0.4を使用しているのですが、上記の設定が反映されず1万円超えても元の送料のままになります。どのように手直しをしたら良いのでしょうか

お気軽にコメントをどうぞ

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください