<?php
namespace Plugin\npka421;
use Plugin\npka421\Entity\OrderResult;
use Plugin\npka421\Repository\ErrorInfoRepository;
use Plugin\npka421\Repository\NpKakebaraiPaymentRepository;
use Plugin\npka421\Repository\OrderResultRepository;
use Plugin\npka421\Service\RestAPI\BillingsRequestsService;
use Plugin\npka421\Service\RestAPI\TransactionsCancelRequestsService;
use Plugin\npka421\Service\RestAPI\TransactionsModificationsRequestsService;
use Plugin\npka421\Service\RestAPI\TransactionsRegistrationsRequestsService;
use Plugin\npka421\Service\OrderStatusService;
use Plugin\npka421\Service\UtilService;
use Eccube\Common\EccubeConfig;
use Eccube\Entity\Master\OrderStatus;
use Eccube\Entity\Order;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Eccube\Event\TemplateEvent;
use Eccube\Repository\OrderRepository;
use Eccube\Repository\ShippingRepository;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Workflow\Event\Event;
class NpKakebaraiEvent implements EventSubscriberInterface
{
/**
* @var EccubeConfig
*/
protected $eccubeConfig;
/**
* @var ErrorInfoRepository
*/
protected $errorInfoRepository;
/**
* @var NpKakebaraiPaymentRepository
*/
protected $npKakebaraiPaymentRepository;
/**
* @var OrderResultRepository
*/
protected $orderResultRepository;
/**
* @var OrderRepository
*/
protected $orderRepository;
/**
* @var ShippingRepository
*/
protected $shippingRepository;
/**
* @var BillingsRequestsService
*/
protected $billingsRequestsService;
/**
* @var TransactionsCancelRequestsService
*/
protected $transactionsCancelRequestsService;
/**
* @var TransactionsModificationsRequestsService
*/
protected $transactionsModificationsRequestsService;
/**
* @var TransactionsRegistrationsRequestsService
*/
protected $transactionsRegistrationsRequestsService;
/**
* @var OrderStatusService
*/
protected $orderStatusService;
/**
* @var UtilService
*/
protected $utilService;
/**
* NpKakebaraiEvent constructor.
*
* @param EccubeConfig $eccubeConfig
* @param ErrorInfoRepository $errorInfoRepository
* @param NpKakebaraiPaymentRepository $npKakebaraiPaymentRepository
* @param OrderResultRepository $orderResultRepository
* @param OrderRepository $orderRepository
* @param ShippingRepository $shippingRepository
* @param BillingsRequestsService $billingsRequestsService
* @param TransactionsCancelRequestsService $transactionsCancelRequestsService
* @param TransactionsModificationsRequestsService $transactionsModificationsRequestsService
* @param TransactionsRegistrationsRequestsService $transactionsRegistrationsRequestsService
* @param OrderStatusService $orderStatusService
* @param UtilService $utilService
*/
public function __construct(
EccubeConfig $eccubeConfig,
ErrorInfoRepository $errorInfoRepository,
NpKakebaraiPaymentRepository $npKakebaraiPaymentRepository,
OrderResultRepository $orderResultRepository,
OrderRepository $orderRepository,
ShippingRepository $shippingRepository,
BillingsRequestsService $billingsRequestsService,
TransactionsCancelRequestsService $transactionsCancelRequestsService,
TransactionsModificationsRequestsService $transactionsModificationsRequestsService,
TransactionsRegistrationsRequestsService $transactionsRegistrationsRequestsService,
OrderStatusService $orderStatusService,
UtilService $utilService
) {
$this->eccubeConfig = $eccubeConfig;
$this->errorInfoRepository = $errorInfoRepository;
$this->npKakebaraiPaymentRepository = $npKakebaraiPaymentRepository;
$this->orderResultRepository = $orderResultRepository;
$this->orderRepository = $orderRepository;
$this->shippingRepository = $shippingRepository;
$this->billingsRequestsService = $billingsRequestsService;
$this->transactionsCancelRequestsService = $transactionsCancelRequestsService;
$this->transactionsModificationsRequestsService = $transactionsModificationsRequestsService;
$this->transactionsRegistrationsRequestsService = $transactionsRegistrationsRequestsService;
$this->orderStatusService = $orderStatusService;
$this->utilService = $utilService;
}
/**
* @return array
*/
public static function getSubscribedEvents()
{
return [
// 受注一覧
'@admin/Order/index.twig' => 'onRenderAdminOrderIndex',
// 受注登録・編集画面表示
'@admin/Order/edit.twig' => 'onRenderAdminOrderEdit',
// 受注登録・編集処理前
EccubeEvents::ADMIN_ORDER_EDIT_INDEX_PROGRESS => 'onAdminOrderEditIndexProgress',
// 受注登録・編集処理完了
EccubeEvents::ADMIN_ORDER_EDIT_INDEX_COMPLETE => 'onAdminOrderEditIndexComplete',
// キャンセル処理
'workflow.order.transition.cancel' => 'onCancel',
];
}
/**
* 受注一覧
*
* @param TemplateEvent $event
*/
public function onRenderAdminOrderIndex(TemplateEvent $event)
{
// 表示対象の受注一覧を取得
$pagination = $event->getParameter('pagination');
// 支払方法の取得
$NpKakebaraiPayment = $this->npKakebaraiPaymentRepository
->findOneBy(['payment_type' => $this->eccubeConfig['np_payment_invoice']]);
// NP処理ステータス一覧
$npStatusList = $this->orderStatusService->getNpStatusList();
// 配送先ごとの注文ID・NP処理ステータス
$shippingInfoMap = $this->getShippingInfoMap($pagination);
// テンプレートにセット
$event->setParameter('npStatusList', $npStatusList);
$event->setParameter('shippingInfoMap', $shippingInfoMap);
$event->addSnippet('@npka421/admin/Order/index_order_result.twig');
}
/**
* 受注リストから注文ID・NP処理ステータスを取得
*
* @param array $Orders
* @return array
*/
private function getShippingInfoMap($Orders)
{
$shippingInfoMap = [];
$shippingIdList = [];
foreach ($Orders as $Order) {
foreach ($Order->getShippings() as $Shipping) {
$shippingIdList[] = $Shipping->getId();
}
}
if (empty($shippingIdList)) {
return $shippingInfoMap;
}
// 配送先IDをもとに注文IDと決済ステータスを取得
$qb = $this->shippingRepository->createQueryBuilder('s');
$qb
->select(
's.id AS shippingId',
'o.id AS orderId',
'r.order_status AS npStatus'
)
->leftJoin(OrderResult::class, 'r', 'WITH', 'r.id = s.Order')
->innerJoin(Order::class, 'o', 'WITH', 'o.id = s.Order')
->where(
$qb->expr()->in('s.id', $shippingIdList)
);
$result = $qb->getQuery()->getResult();
if (empty($result)) {
return $shippingInfoMap;
}
foreach ($result as $row) {
$Order = $this->orderRepository->find($row['orderId']);
$OrderResult = $this->orderResultRepository->find($Order->getId());
$shippingInfoMap[$row['shippingId']] = [
'orderId' => $row['orderId'],
'npStatus' => $row['npStatus'],
'can_billing' => ($this->orderStatusService->canBilling($Order, $OrderResult)) ? 1 : 0,
'can_reauthori' => ($this->orderStatusService->canReauthori($Order, $OrderResult)) ? 1 : 0,
];
}
return $shippingInfoMap;
}
/**
* 受注登録・編集画面表示
*
* @param TemplateEvent $event
*/
public function onRenderAdminOrderEdit(TemplateEvent $event)
{
$Order = $event->getParameter('Order');
if (empty($Order) || empty($Order->getId())) {
return;
}
$Payment = $Order->getPayment();
if (empty($Payment)) {
return;
}
// 支払方法の取得
$NpKakebaraiPayment = $this->npKakebaraiPaymentRepository->findOneBy([
'payment_type' => $this->eccubeConfig['np_payment_invoice']
]);
// 支払方法が対象外
if ($Payment->getId() != $NpKakebaraiPayment->getId()) {
return;
}
// 受注処理結果取得
$OrderResult = $this->orderResultRepository->find($Order->getId());
if (empty($OrderResult)) {
return;
}
// NP処理ステータス名取得
$np_status_name = $this->orderStatusService
->getNpStatusName($OrderResult->getOrderStatus());
// エラー情報
$ErrorInfos = $this->errorInfoRepository->findBy(
['order_id' => $Order->getId()],
['id' => 'ASC']
);
// テンプレートにセット
$event->setParameter('OrderResult', $OrderResult);
$event->setParameter('np_status_name', $np_status_name);
$event->setParameter('ErrorInfos', $ErrorInfos);
$event->setParameter('can_billing', $this->orderStatusService->canBilling($Order, $OrderResult));
$event->setParameter('can_reauthori', $this->orderStatusService->canReauthori($Order, $OrderResult));
// 表示領域追加
$snippet = 'npka421/Resource/template/admin/Order/edit_order_result.twig';
$event->addSnippet($snippet);
}
/**
* 受注登録・編集処理前
*
* @param EventArgs $event
*/
public function onAdminOrderEditIndexProgress(EventArgs $event)
{
$request = $event->getRequest();
$OriginOrder = $event->getArgument('OriginOrder');
$TargetOrder = $event->getArgument('TargetOrder');
$Payment = $TargetOrder->getPayment();
if (empty($Payment)) {
return;
}
// 支払方法の取得
$NpKakebaraiPayment = $this->npKakebaraiPaymentRepository->findOneBy([
'payment_type' => $this->eccubeConfig['np_payment_invoice']
]);
// 支払方法が対象外
if ($Payment->getId() != $NpKakebaraiPayment->getId()) {
return;
}
// 新規受注登録は対象外
if (empty($TargetOrder->getId())) {
return;
}
$OrderResult = $this->orderResultRepository->find($OriginOrder->getId());
$npStatusId = $OrderResult->getOrderStatus();
$fromStatus = $OriginOrder->getOrderStatus();
$toStatus = $TargetOrder->getOrderStatus();
// ステータスに変更があった場合のみチェックする.
if ($fromStatus->getId() != $toStatus->getId()) {
if (!$this->canTransition($toStatus->getId(), $npStatusId)) {
$this->utilService->addError(
trans('admin.order.failed_to_change_status__short_np', [
'%npStatus%' => $this->orderStatusService->getNpStatusName($npStatusId),
]), 'admin');
header('Location: ' . $this->utilService->generateUrl('admin_order_edit', ['id' => $OriginOrder->getId()]));
exit();
}
}
switch ($request->get('mode')) {
// 登録・編集処理
case 'register':
$operation = $this->checkOperation($TargetOrder, $OriginOrder);
break;
// 請求依頼処理
case 'billing':
$TargetOrder->setDiscount($OriginOrder->getDiscount());
$TargetOrder->setDeliveryFeeTotal($OriginOrder->getDeliveryFeeTotal());
$TargetOrder->setCharge($OriginOrder->getCharge());
$this->doBilling($TargetOrder);
break;
// 再審査依頼処理
case 'reauthori':
$this->doReauthori($TargetOrder);
break;
}
}
/**
* 受注登録・編集処理完了
*
* @param EventArgs $event
*/
public function onAdminOrderEditIndexComplete(EventArgs $event)
{
$OriginOrder = $event->getArgument('OriginOrder');
$TargetOrder = $event->getArgument('TargetOrder');
// 支払方法の取得
$NpKakebaraiPayment = $this->npKakebaraiPaymentRepository
->findOneBy(['payment_type' => $this->eccubeConfig['np_payment_invoice']]);
$Payment = $TargetOrder->getPayment();
if (empty($Payment)) {
return false;
}
// 支払方法が対象外
if ($Payment->getId() != $NpKakebaraiPayment->getId()) {
return false;
}
// 新規受注登録の場合
if (empty($OriginOrder->getId())) {
// 取引登録依頼
$this->transactionsRegistrationsRequestsService
->postRequest($TargetOrder);
return;
}
// 処理判定
$operation = $this->checkOperation($TargetOrder);
switch ($operation) {
// 取引登録依頼
case 1:
$this->transactionsRegistrationsRequestsService
->postRequest($TargetOrder);
break;
// 取引修正依頼
case 2:
// 登録前後での変更有無を確認
$originJson = $this->transactionsModificationsRequestsService
->createRequestJson($OriginOrder);
$targetJson = $this->transactionsModificationsRequestsService
->createRequestJson($TargetOrder);
if ($originJson == $targetJson) {
// 変更は無いので取引修正依頼は行わない
return;
}
$this->transactionsModificationsRequestsService
->postRequest($TargetOrder);
break;
// 取引キャンセル依頼
case 3:
$this->transactionsCancelRequestsService
->postRequest($TargetOrder);
break;
// 処理無し
default:
// nop
}
}
/**
* 指定ステータスに遷移できるかどうかを判定.
*
* @param $to 遷移先ステータス
* @param $npStatus NPステータス
*
* @return boolean 指定ステータスに遷移できる場合はtrue
*/
private function canTransition($to, $npStatus)
{
$ngNpStatuses = [
$this->eccubeConfig['np_status_transactions_registrations_ng'],
$this->eccubeConfig['np_status_transactions_authorizations_pd'],
$this->eccubeConfig['np_status_transactions_authorizations_ng'],
$this->eccubeConfig['np_status_transactions_modifications_ng'],
$this->eccubeConfig['np_status_transactions_cancel_ng'],
$this->eccubeConfig['np_status_billings_ng']
];
if (in_array($npStatus, $ngNpStatuses)) {
if ($to !== OrderStatus::CANCEL) {
return false;
}
}
return true;
}
/**
* 請求依頼処理
*
* @param Order $Order
*/
private function doBilling(Order $Order)
{
// 受注処理結果取得
$OrderResult = $this->orderResultRepository->find($Order->getId());
if (empty($OrderResult)) {
$this->utilService->addError('admin.common.save_error', 'admin');
return;
}
// 請求依頼使用可否判定
if ($this->orderStatusService->canBilling($Order, $OrderResult) === false) {
$this->utilService->addError('admin.order.billing.error', 'admin');
return;
}
// 請求依頼依頼
$result = $this->billingsRequestsService
->postRequest($Order);
if ($result) {
$this->utilService->addSuccess('admin.common.save_complete', 'admin');
// 受注ステータスの更新を画面に反映
header('Location: ' . $this->utilService->generateUrl('admin_order_edit', ['id' => $Order->getId()]));
exit();
}
}
/**
* 再審査依頼処理
*
* @param Order $Order
*/
private function doReauthori(Order $Order)
{
// 受注処理結果取得
$OrderResult = $this->orderResultRepository->find($Order->getId());
if (empty($OrderResult)) {
$this->utilService->addError('admin.common.save_error', 'admin');
return;
}
// 再審査依頼使用可否判定
if ($this->orderStatusService->canReauthori($Order, $OrderResult) === false) {
$this->utilService->addError('admin.order.reauthori.error', 'admin');
return;
}
// 取引登録依頼
$result = $this->transactionsRegistrationsRequestsService
->postRequest($Order);
if ($result) {
$this->utilService->addSuccess('admin.common.save_complete', 'admin');
// リダイレクトするとflushされないのでスルー
// header('Location: ' . $this->utilService->generateUrl('admin_order_edit', ['id' => $Order->getId()]));
// exit();
}
}
/**
* 処理判定
*
* @param Order $Order
* @param Order|null $OriginOrder
* @param boolean $errorView
* @return integer -1:エラーあり 0:処理無し 1:取引登録依頼 2:取引修正依頼 3:取引キャンセル依頼
*/
private function checkOperation(Order $Order, Order $OriginOrder = null, $errorView = true)
{
$operation = 0;
// 支払方法の取得
$NpKakebaraiPayment = $this->npKakebaraiPaymentRepository
->findOneBy(['payment_type' => $this->eccubeConfig['np_payment_invoice']]);
$Payment = $Order->getPayment();
if (empty($Payment)) {
return $operation;
}
// 支払方法をチェック
if (empty($OriginOrder)) {
if ($Payment->getId() != $NpKakebaraiPayment->getId()) {
return $operation;
}
} else {
$OriginPayment = $OriginOrder->getPayment();
if (empty($OriginPayment)) {
return $operation;
}
if ($OriginPayment->getId() != $NpKakebaraiPayment->getId()) {
return $operation;
}
}
// 受注結果取得
$OrderResult = $this->orderResultRepository->find($Order->getId());
if (empty($OrderResult)) {
$status = 0;
} else {
$status = $OrderResult->getOrderStatus();
}
// キャンセル以外
if ($Order->getOrderStatus()->getId() != OrderStatus::CANCEL) {
switch ($status) {
// 未登録
case 0:
// 取引登録NG
case $this->eccubeConfig['np_status_transactions_registrations_ng']:
// 取引キャンセルOK
case $this->eccubeConfig['np_status_transactions_cancel_ok']:
// 取引登録依頼処理
$operation = 1;
break;
// 取引審査OK
case $this->eccubeConfig['np_status_transactions_authorizations_ok']:
// 取引審査NG
case $this->eccubeConfig['np_status_transactions_authorizations_ng']:
// 請求依頼OK
case $this->eccubeConfig['np_status_billings_ok']:
// 取引修正NG
case $this->eccubeConfig['np_status_transactions_modifications_ng']:
// 取引審査保留
case $this->eccubeConfig['np_status_transactions_authorizations_pd']:
// 取引修正依頼処理
$operation = 2;
break;
// エラー
default:
if ($errorView) {
$this->utilService->addError('admin.order.modification.error', 'admin');
header('Location: ' . $this->utilService->generateUrl('admin_order_edit', ['id' => $Order->getId()]));
exit();
}
$operation = -1;
}
}
return $operation;
}
/**
* キャンセル処理.
*
* @param Event $event
*/
public function onCancel(Event $event)
{
/* @var Order $Order */
$Order = $event->getSubject()->getOrder();
// 支払方法の取得
$NpKakebaraiPayment = $this->npKakebaraiPaymentRepository
->findOneBy(['payment_type' => $this->eccubeConfig['np_payment_invoice']]);
$Payment = $Order->getPayment();
if (empty($Payment)) {
return;
}
// 支払方法をチェック
if ($Payment->getId() != $NpKakebaraiPayment->getId()) {
return;
}
// 受注結果取得
$OrderResult = $this->orderResultRepository->find($Order->getId());
if (empty($OrderResult)) {
$status = 0;
} else {
$status = $OrderResult->getOrderStatus();
}
switch ($status) {
// 取引審査OK
case $this->eccubeConfig['np_status_transactions_authorizations_ok']:
// 取引審査NG
case $this->eccubeConfig['np_status_transactions_authorizations_ng']:
// 請求依頼OK
case $this->eccubeConfig['np_status_billings_ok']:
// 取引修正NG
case $this->eccubeConfig['np_status_transactions_modifications_ng']:
// 取引審査保留
case $this->eccubeConfig['np_status_transactions_authorizations_pd']:
// 取引キャンセル依頼処理
$this->transactionsCancelRequestsService
->postRequest($Order);
break;
}
}
}