第67回EC-CUBE関西UGに参加したまとめ｜【開発者向け】購入フローをカスタマイズしてみよう！

2021-01-28（木）18:00～開催された第67回EC-CUBE関西UGをまとめてみました。

67回は前回（[第64回](https://qiita.com/dev_belltzel/items/b8bf262ca8615d382736)）に続く内容になっています。
今回もおかじ（@okazy）さんが約2時間ぶっ通しで、説明しながらライブコーディングを行ってくれました。

また僕なりに資料を残してみます。

#資料サイト
EC-CUBE 4.0 開発者向けドキュメント::購入フローのカスタマイズ
[https://doc4.ec-cube.net/customize_service#%E8%B3%BC%E5%85%A5%E3%83%95%E3%83%AD%E3%83%BC%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA-2424](https://doc4.ec-cube.net/customize_service#%E8%B3%BC%E5%85%A5%E3%83%95%E3%83%AD%E3%83%BC%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA-2424)

本日のソース
[github:okazy](https://github.com/okazy/ec-cube/compare/5286a8102fea2b64d8557c5b46e28c259c482414...okazy:kansai202101?expand=1)

- 互換性を保つためにisNoshiのnullを許可
- 熨斗ありの場合に500円の手数料を追加する

上記２点が今回の差分になります。

#環境
前回の続きになります。

前回のカスタマイズが終わった環境を作りたい場合は、**kansai202010**のブランチをお使いください。

**kansai202101**のブランチが今回追加カスタマイズされたソースになります。

#購入フローのカスタマイズ

今回は、熨斗ありで受注した時に「熨斗手数料」の明細を追加するカスタマイズになります。

**カート**から**ご注文手続き**へ移動し、**熨斗の項目を有り**に変更すると、ページがリロードされ設定した金額（今回は500円）が手数料にプラスされています。

無しに設定すれば、手数料に500円がプラスされません。

熨斗ありで受注後、管理画面の受注一覧から受注詳細へ移動して、**商品情報**を確認してください。
**熨斗手数料**の項目が追加されているのが分かります。

##互換性を保つためにisNoshiのnullを許可

[Customize/Entity/OrderTraitの修正](https://github.com/okazy/ec-cube/commit/2a066fc1c81f594aa124472e8cb8161f2b1f546f)

関数`isNoshi()`の**return**で、NULLを許可する修正を行ってます。

##熨斗ありの場合に500円の手数料を追加する
###NoshiProcessorの追加と説明

今回は**熨斗の明細を追加する処理**を追加する為に、[Eccube/Service/PurchaseFlow/ItemHolderPreprocessor](https://github.com/EC-CUBE/ec-cube/blob/4.0/src/Eccube/Service/PurchaseFlow/ItemHolderPreprocessor.php)を**implements**した[Customize/Service/PurchaseFlow/Processor/NoshiProcessor](https://github.com/okazy/ec-cube/commit/82fa247a3180124e98ca709ed0b8ca600ff725fa)を追加(作成)しています。

実装内容を細かく説明しようと思いましたが、どうやって説明したらいいのか悩んだ挙句、細かい解説は諦めました。
おおざっぱに解説します。

####実行のタイミング

```php
@ShoppingFlow
```
アノテーションで設定しています。

`@ShoppingFlow`は購入画面で実行されます。

他にも
`@CartFlow`はカート画面、~~カートブロック~~
`@OrderFlow`は管理画面の受注詳細画面
で動作するものがあり全３種になります。

カートブロックに打消し線入れてますが、[カートブロックでpurchaseFlowを実行しないように修正](https://github.com/EC-CUBE/ec-cube/commit/caff58b5dbc840357da03400dee6006247ebc5bb#diff-bb9062b8b836b92ea30cab83a3a41252f3f8400f378a4b1d51d042973221aeb5)されてますね。

####Cart では処理をしない

```php
if (!$itemHolder instanceof Order) {
    return;
}
```
`$itemHolder`が`Order（Eccube\Entity\Order）`でなければ、処理を行わないようにしています。

`PurchaseFlow`はカート画面でも実行されますので`Cart（Eccube\Entity\Cart）`の時もあります。
そういう時に実行されないようにする処理・・・だと思います。

####すでに設定した「熨斗手数料」があれば削除

```php
foreach ($itemHolder->getItems() as $item) {
    if ($item->getProcessorName() == NoshiProcessor::class) {
        $itemHolder->removeOrderItem($item);
        $this->entityManager->remove($item);

        break;
    }
}
```

`$itemHolder`は`Order（Eccube\Entity\Order）`です。
`getItems()`で`OrderItem（Eccube\Entity\OrderItem）`を取得して`ProcessorName`を比較し、`NoshiProcessor::class`だったら`Order`から`OrderItem（熨斗手数料の明細）`を削除します。

この処理が無い場合は、`OrderItem（熨斗手数料の明細）`がどんどん増えていきます。
（支払い方法を変更したり、熨斗の有無を変更した場合などに）

####熨斗が有効な場合に熨斗手数料の明細を追加

```php
if ($itemHolder->isNoshi()) {
    $this->addNoshiItem($itemHolder);
}
```

```php
private function addNoshiItem(ItemHolderInterface $itemHolder): void
{
    $OrderItemType = $this->orderItemTypeRepository->find(OrderItemType::CHARGE);
    $TaxDisplayType = $this->taxDisplayTypeRepository->find(TaxDisplayType::INCLUDED);
    $Taxation = $this->taxTypeRepository->find(TaxType::TAXATION);
    $TaxRule = $this->taxRuleRepository->getByRule();

    $item = new OrderItem();
    $item->setProductName('熨斗手数料')
        ->setQuantity(1)
        ->setPrice(500)
        ->setOrderItemType($OrderItemType)
        ->setOrder($itemHolder)
        ->setTaxDisplayType($TaxDisplayType)
        ->setTaxType($Taxation)
        ->setProcessorName(NoshiProcessor::class)
        ->setTaxRate($TaxRule->getTaxRate())
        ->setTaxAdjust($TaxRule->getTaxAdjust())
        ->setRoundingType($TaxRule->getRoundingType());

    $itemHolder->addItem($item);
}
```
熨斗の選択が有りだったら`Order`に`OrderItem（熨斗手数料の明細）`を追加する処理です。

`OrderItemType` `TaxDisplayType` `TaxType`は`Eccube/Entity/Master`フォルダ内のファイルを見れば、どんな設定をしているのか分かります。
探してみてください。

`$TaxRule`は管理画面の**設定**→**店舗設定**→**税率設定**で設定された有効な`Eccube/Entity/TaxRule`になります。
詳しくは[Eccube/Repository/TaxRuleRepository::getByRule()](https://github.com/EC-CUBE/ec-cube/blob/e20433c5645299d6f83b66f3e129d1c49dfda398/src/Eccube/Repository/TaxRuleRepository.php#L111)を見てください。

あとは`OrderItem`をnewして`$itemHolder->addItem($item)`で`Order`に`OrderItem（熨斗手数料の明細）`を追加しています。

####テンプレートの修正

３か所の修正があり、２か所はテキストの修正です。

残りの１箇所

```diff
- {{ form_widget(form.noshi) }}
+ {{ form_widget(form.noshi, { 'attr': { 'data-trigger': 'change' }}) }}
```

上記の変更は値が変更された時に、画面が更新されるようになります。
生成されたコードを見て、どのようになっているのかは、自身でお確かめください。

実際にはパラメーターを飛ばして、注文手続き画面へリダイレクトされる処理です。
javascriptのコードは[こちら](https://github.com/EC-CUBE/ec-cube/blob/e20433c5645299d6f83b66f3e129d1c49dfda398/src/Eccube/Resource/template/default/Shopping/index.twig#L18)です。

##PurchaseFlowの資料

2019/2/7 EC-CUBE東京UG勉強会の資料ですが、PurchaseFlowについての[スライド](https://www.slideshare.net/chihiroadachi3/201927-eccubeugpurchaseflow-130874190?fbclid=IwAR1VAYGVyPoFh8tTsTKbLt-p7zIIRrh2YeoB0TtyztygFf13cVPmzpMgG4s)があります。

EC-CUBEの中の人でありエバンジェリスト足立 智広（qiita:@chihiro-adachi twitter:[@chihiro_adachi](https://twitter.com/chihiro_adachi)）さんの資料ですね。
自分がPurchaseFlowを勉強してる時に、よくみた資料です。

参考になると思います。

#まとめ

すみませんが、今回はキャプシャーなしですOTL

~~前回の環境が無くなっていたので、準備するのが面倒・・・というのは心の中に隠しておきます。~~

私見ですが、PurchaseFlowを使った購入フローやカート画面、管理画面の受注詳細のフローに追加するProcessorの作成は、Order・CartのEntity周り、本体でどのようなProcessorがどんな順番で実行されていて、データがどのように変化しているのか、その辺の把握も大事だと思います。

カスタマイズ例を探すのもよいですが、本体のソースを読んでみるのも良いですよ。
使えそうな部分が結構あります。

以上、最後まで読んで頂き有り難う御座いました。