<?php
/*
* This file is part of Customize of EC-CUBE by Kenji Nakanishi
*
* Copyright(c) 2021 Kenji Nakanishi. All Rights Reserved.
*
* https://www.facebook.com/web.kenji.nakanishi
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Plugin\SheebRental42;
use Doctrine\ORM\EntityManagerInterface;
use Eccube\Common\EccubeConfig;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Eccube\Event\TemplateEvent;
use Eccube\Service\PurchaseFlow\Processor\StockReduceProcessor;
use Eccube\Service\PurchaseFlow\PurchaseContext;
use Plugin\SheebRental42\Entity\Config;
use Plugin\SheebRental42\Entity\Holiday;
use Plugin\SheebRental42\Repository\ConfigRepository;
use Plugin\SheebRental42\Repository\HolidayRepository;
use Plugin\SheebRental42\Service\StockService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Workflow\Event\Event as WorkflowEvent;
class Event implements EventSubscriberInterface
{
/**
* @return array
*/
public static function getSubscribedEvents()
{
return [
'@admin/index.twig' => ['onRenderAdminHome', 10],
'@admin/Product/product_class.twig' => ['onRenderProductClassEdit', 10],
'@admin/Order/index.twig' => ['onRenderOrderArchive', 10],
'@admin/Order/edit.twig' => ['onRenderOrderEdit', 10],
'@admin/Order/shipping.twig' => ['onRenderOrderShipping', 10],
'Product/detail.twig' => ['onRenderProductDetail', 10],
'Shopping/index.twig' => ['onRenderShoppingIndex', 10],
'Shopping/confirm.twig' => ['onRenderShoppingConfirm', 10],
'Mypage/index.twig' => ['onRenderMypageHistoryArchive', 10],
'Mypage/history.twig' => ['onRenderMypageHistory', 10],
// 管理画面 Order登録・更新
EccubeEvents::ADMIN_ORDER_EDIT_INDEX_PROGRESS => ['updateOrder', 10],
// StateMachine 打ち消し
'workflow.order.transition.back_to_in_progress' => ['rollbackStock', 10],
'workflow.order.transition.cancel' => ['commitStock', 10],
];
}
/**
* @var EccubeConfig
*/
private $eccubeConfig;
/**
* @var FormFactoryInterface
*/
private $factory;
/**
* @var EntityManagerInterface
*/
private $em;
/**
* @var ConfigRepository
*/
private $RentalConfigReposigory;
/**
* @var HolidayRepository
*/
private $RentalHolidayRepository;
/**
* @var StockService
*/
private $stockService;
/**
* @var StockReduceProcessor
*/
private $stockReduceProcessor;
public function __construct(
EccubeConfig $eccubeConfig,
FormFactoryInterface $factory,
EntityManagerInterface $em,
StockService $stockService,
StockReduceProcessor $stockReduceProcessor
) {
$this->eccubeConfig = $eccubeConfig;
$this->factory = $factory;
$this->em = $em;
$this->RentalConfigReposigory = $this->em->getRepository(Config::class);
$this->RentalHolidayRepository = $this->em->getRepository(Holiday::class);
$this->stockService = $stockService;
$this->stockReduceProcessor = $stockReduceProcessor;
}
public function updateOrder(EventArgs $event)
{
/** @var \Eccube\Entity\Order */
$OriginOrder = $event->getArgument('OriginOrder');
/** @var \Eccube\Entity\Order */
$TargetOrder = $event->getArgument('TargetOrder');
/** @var \Eccube\Entity\Master\OrderStatus */
$OriginStatus = $OriginOrder->getOrderStatus();
/** @var \Eccube\Entity\Master\OrderStatus */
$TargetStatus = $TargetOrder->getOrderStatus();
if (!PluginManager::inPluginPurchase($TargetOrder, $this->em)) {
// レンタルプラグインの受注でなければ処理しない
return;
}
// レンタルステータスが null になっているものは 出荷準備中にする
foreach ($TargetOrder->getShippings() as $Shipping) {
if ($Shipping->getRentalStatus() !== PluginManager::ORDER_STATUS_PREPARE) continue;
$Shipping->setRentalStatus(PluginManager::ORDER_STATUS_PREPARE);
}
if (empty($OriginStatus)) {
// 新規登録時には終了
return;
}
if ($OriginStatus->getId() === $TargetStatus->getId()) {
// Statusに変更がなければ終了
return;
}
// OrderStatusに連動してレンタル状況を変更
foreach ($TargetOrder->getShippings() as $Shipping) {
$this->stockService->interlockStatus($Shipping, $TargetStatus);
}
}
/**
* 在庫を戻す. StateMachineの打ち消し
*
* @param Event $event
*/
public function rollbackStock(WorkflowEvent $event)
{
/* @var Order $Order */
$Order = $event->getSubject()->getOrder();
if (PluginManager::inPluginPurchase($Order, $this->em)) {
$this->stockReduceProcessor->rollback($Order, new PurchaseContext());
}
}
/**
* 在庫を減らす. StateMachineの打ち消し
*
* @param Event $event
*
* @throws PurchaseFlow\PurchaseException
*/
public function commitStock(WorkflowEvent $event)
{
/* @var Order $Order */
$Order = $event->getSubject()->getOrder();
if (PluginManager::inPluginPurchase($Order, $this->em)) {
$this->stockReduceProcessor->prepare($Order, new PurchaseContext());
}
}
/**
* 管理画面 HOME画面
* ・異常値チェック
*/
public function onRenderAdminHome(TemplateEvent $templateEvent)
{
$this->stockService->updateAlert();
// $templateEvent->addSnippet('@SheebRental42/Admin/index.twig');
$templateEvent->addSnippet('@SheebRental42/Admin/alert.twig');
}
/**
* 管理画面 商品管理 規格設定画面
* ・レンタル設定要素追加
*/
public function onRenderProductClassEdit(TemplateEvent $templateEvent)
{
$templateEvent->addSnippet('@SheebRental42/Admin/Product/product_class.twig');
}
/**
* 管理画面 HOME画面
* ・異常値チェック
*/
public function onRenderOrderArchive(TemplateEvent $templateEvent)
{
$this->stockService->updateAlert();
$templateEvent->addSnippet('@SheebRental42/Admin/alert.twig');
$templateEvent->addSnippet('@SheebRental42/Admin/Order/index.twig');
}
/**
* 管理画面 受注管理 詳細画面
* ・受注要素追加
*/
public function onRenderOrderEdit(TemplateEvent $templateEvent)
{
$templateEvent->addSnippet('@SheebRental42/Parts/datepick_snippet.twig');
$templateEvent->addAsset('@SheebRental42/Parts/datepick_asset.twig');
$templateEvent->addSnippet('@SheebRental42/Admin/Order/edit.twig');
}
/**
* 管理画面 受注管理 複数配送時 配送先編集画面
* ・受注要素追加
*/
public function onRenderOrderShipping(TemplateEvent $templateEvent)
{
$templateEvent->addSnippet('@SheebRental42/Parts/datepick_snippet.twig');
$templateEvent->addAsset('@SheebRental42/Parts/datepick_asset.twig');
$templateEvent->addSnippet('@SheebRental42/Admin/Order/shipping.twig');
}
/**
* フロント画面 商品詳細
*/
public function onRenderProductDetail(TemplateEvent $templateEvent)
{
$templateEvent->addSnippet('@SheebRental42/Product/detail.twig');
$templateEvent->addAsset('@SheebRental42/Product/detail_assets.twig');
}
/**
* フロント画面 注文手続き画面
*/
public function onRenderShoppingIndex(TemplateEvent $templateEvent)
{
if (defined('EXIST_SHEEB_RENTAL')) {
$Order = $templateEvent->getParameter('Order');
$Config = $this->RentalConfigReposigory->get();
$fnValidDate = function (\DateTime $datetime, \DateTime $min_date, \DateTime $max_date) {
if ($datetime < $min_date) {
return null;
}
if ($datetime > $max_date) {
return null;
}
return $datetime->format('Y-m-d');
};
$params = [];
/* @var $Shipping Shipping */
foreach ($Order->getShippings() as $idx => $Shipping) {
// --- カレンダー選択可能範囲 ---
[$min_start_days, $max_end_days] = $this->stockService->getSelectableDateRangeByOrderItems(
$Shipping->getOrderItems()
);
$params[$idx]['min_date'] = $min_start_days;
$params[$idx]['max_date'] = $max_end_days;
$start_date = (new \DateTime())->modify("+{$min_start_days} days");
$start_date->setTime(0, 0);
$end_date = (new \DateTime())->modify("+{$max_end_days} days");
$end_date->setTime(23, 59);
$period = StockService::createPeriod($start_date, $end_date);
// --- 営業日管理 ---
[$start_disable_days, $end_disable_days] = $this->stockService->getHolidays($period, $Config);
// --- 在庫管理 ---
[$calendar, $settings] = $this->stockService->getMergedStockCalendar($Shipping, $period);
$params[$idx]['start_calendar'] = $this->stockService->mergeDisableCalendar($calendar, $start_disable_days);
$params[$idx]['end_calendar'] = $this->stockService->mergeDisableCalendar($calendar, $end_disable_days);
$params[$idx]['period_start'] = $fnValidDate($Shipping->getPeriodStart(), $start_date, $end_date);
$params[$idx]['period_end'] = $fnValidDate($Shipping->getPeriodEnd(), $start_date, $end_date);
$params[$idx]['minRentalDays'] = $settings['minRentalDays'];
$params[$idx]['maxRentalDays'] = $settings['maxRentalDays'];
}
// 最短利用開始可能日数をセット
$templateEvent->setParameter('args', json_encode(['params' => $params], JSON_UNESCAPED_UNICODE));
$templateEvent->addSnippet('@SheebRental42/Shopping/index.twig');
$templateEvent->addAsset('@SheebRental42/Shopping/index_assets.twig');
} else {
$templateEvent->addSnippet('@SheebRental42/Shopping/index_not_rental.twig');
}
}
/**
* フロント画面 注文確認画面
*/
public function onRenderShoppingConfirm(TemplateEvent $templateEvent)
{
if (defined('EXIST_SHEEB_RENTAL')) {
// --- 送料や手数料計算の条件が、プラグインから他の明細を追加するとズレるのを修正 ---
$source = $templateEvent->getSource();
// 送料
$source = str_replace(
'{% for item in shipping.order_items if item.isDeliveryFee %}',
'{% for item in shipping.order_items if item.processor_name == "Eccube\\\\Service\\\\PurchaseFlow\\\\Processor\\\\DeliveryFeePreprocessor" %}',
$source
);
// 手数料
$source = str_replace(
'{% for item in Order.order_items if item.isCharge %}',
'{% for item in Order.order_items if item.processor_name == "Eccube\\\\Service\\\\PurchaseFlow\\\\Processor\\\\PaymentChargePreprocessor" %}',
$source
);
$templateEvent->setSource($source);
// --- テンプレート追加 ---
$templateEvent->addSnippet('@SheebRental42/Shopping/confirm.twig');
}
}
/**
* マイページ購入履歴一覧
* ・レンタル状況追加
*/
public function onRenderMypageHistoryArchive(TemplateEvent $templateEvent)
{
$templateEvent->addSnippet('@SheebRental42/Mypage/index.twig');
}
/**
* マイページ購入履歴詳細
* ・レンタル要素追加
*/
public function onRenderMypageHistory(TemplateEvent $templateEvent)
{
if (PluginManager::inPluginPurchase($templateEvent->getParameter('Order'), $this->em)) {
$templateEvent->addSnippet('@SheebRental42/Mypage/history.twig');
}
}
}