app/Plugin/EccubePaymentLite42/Controller/Admin/Regular/OrderController.php line 79

Open in your IDE?
  1. <?php
  2. namespace Plugin\EccubePaymentLite42\Controller\Admin\Regular;
  3. use Eccube\Controller\AbstractController;
  4. use Eccube\Repository\Master\PageMaxRepository;
  5. use Eccube\Util\FormUtil;
  6. use Knp\Component\Pager\PaginatorInterface;
  7. use Plugin\EccubePaymentLite42\Form\Type\Admin\SearchRegularOrderType;
  8. use Plugin\EccubePaymentLite42\Repository\RegularOrderRepository;
  9. use Plugin\EccubePaymentLite42\Service\IsActiveRegularService;
  10. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  13. use Symfony\Component\Routing\Annotation\Route;
  14. use Plugin\EccubePaymentLite42\Entity\Config;
  15. use Plugin\EccubePaymentLite42\Repository\ConfigRepository;
  16. use Plugin\EccubePaymentLite42\Entity\RegularStatus;
  17. //----------
  18. //代理店名の取得はカスタムリポジトリを使用
  19. //----------
  20. use Customize\Repository\CustomizeCustomerRepository;
  21. class OrderController extends AbstractController
  22. {
  23.     /**
  24.      * @var PageMaxRepository
  25.      */
  26.     private $pageMaxRepository;
  27.     /**
  28.      * @var RegularOrderRepository
  29.      */
  30.     private $regularOrderRepository;
  31.     /**
  32.      * @var IsActiveRegularService
  33.      */
  34.     private $isActiveRegularService;
  35.     /**
  36.      * @var ConfigRepository
  37.      */
  38.     private $configRepository;
  39.     //----代理店カスタマイズ------
  40.     //代理店名の取得はカスタムリポジトリを使用
  41.     //----------
  42.     private $customizeCustomerRepository;
  43.     public function __construct(
  44.         PageMaxRepository $pageMaxRepository,
  45.         RegularOrderRepository $regularOrderRepository,
  46.         IsActiveRegularService $isActiveRegularService,
  47.         CustomizeCustomerRepository $customizeCustomerRepository,
  48.         ConfigRepository $configRepository
  49.     ) {
  50.         $this->pageMaxRepository $pageMaxRepository;
  51.         $this->regularOrderRepository $regularOrderRepository;
  52.         $this->isActiveRegularService $isActiveRegularService;
  53.         $this->customizeCustomerRepository $customizeCustomerRepository;
  54.         $this->configRepository $configRepository;
  55.     }
  56.     /**
  57.      * @Route(
  58.      *     "/%eccube_admin_route%/eccube_payment_lite/regular/index",
  59.      *     name="eccube_payment_lite42_admin_regular_index", methods={"GET", "POST"}
  60.      * )
  61.      * @Route(
  62.      *     "/%eccube_admin_route%/eccube_payment_lite/regular/index/page/{page_no}", requirements={"page_no" = "\d+"},
  63.      *     name="eccube_payment_lite42_admin_regular_index_page" , methods={"GET", "POST"}
  64.      * )
  65.      * @Template("@EccubePaymentLite42/admin/Regular/Order/index.twig")
  66.      */
  67.     public function index(Request $requestPaginatorInterface $paginator$page_no null)
  68.     {
  69.         if (!$this->isActiveRegularService->isActive()) {
  70.             throw new NotFoundHttpException();
  71.         }
  72.         /** @var Config $Config */
  73.         $Config $this->configRepository->find(1);
  74.         $createdAt $Config->getCreatedAt();
  75.         $searchForm $this->createForm(SearchRegularOrderType::class);
  76.         $page_count $this->session->get(
  77.             'eccube.admin.regular.order.search.page_count',
  78.             $this->eccubeConfig->get('eccube_default_page_count')
  79.         );
  80.         $page_count_param = (int) $request->get('page_count');
  81.         $pageMaxis $this->pageMaxRepository->findAll();
  82.         if ($page_count_param) {
  83.             foreach ($pageMaxis as $pageMax) {
  84.                 if ($page_count_param == $pageMax->getName()) {
  85.                     $page_count $pageMax->getName();
  86.                     $this->session->set('eccube.admin.regular.order.search.page_count'$page_count);
  87.                     break;
  88.                 }
  89.             }
  90.         }
  91.         if ('POST' === $request->getMethod()) {
  92.             $searchForm->handleRequest($request);
  93.             if ($searchForm->isValid()) {
  94.                 $page_no 1;
  95.                 $searchData $searchForm->getData();
  96.                 // 検索条件, ページ番号をセッションに保持.
  97.                 $this->session->set('eccube.admin.regular.order.search'FormUtil::getViewData($searchForm));
  98.                 $this->session->set('eccube.admin.regular.order.search.page_no'$page_no);
  99.             } else {
  100.                 // 検索エラーの際は, 詳細検索枠を開いてエラー表示する.
  101.                 return [
  102.                     'searchForm' => $searchForm->createView(),
  103.                     'pagination' => [],
  104.                     'pageMaxis' => $pageMaxis,
  105.                     'page_no' => $page_no,
  106.                     'page_count' => $page_count,
  107.                     'has_errors' => true,
  108.                     'createdAt' => $createdAt,
  109.                     'missingOrderCreationCount' => 0,
  110.                 ];
  111.             }
  112.         } else {
  113.             if (null !== $page_no || $request->get('resume')) {
  114.                 if ($page_no) {
  115.                     $this->session->set('eccube.admin.regular.order.search.page_no', (int) $page_no);
  116.                 } else {
  117.                     $page_no $this->session->get('eccube.admin.regular.order.search.page_no'1);
  118.                 }
  119.                 $viewData $this->session->get('eccube.admin.regular.order.search', []);
  120.                 $searchData FormUtil::submitAndGetData($searchForm$viewData);
  121.             } else {
  122.                 $page_no 1;
  123.                 $viewData = [];
  124.                 if ($statusId = (int) $request->get('order_status_id')) {
  125.                     $viewData = ['status' => $statusId];
  126.                 }
  127.                 $searchData FormUtil::submitAndGetData($searchForm$viewData);
  128.                 // セッション中の検索条件, ページ番号を初期化.
  129.                 $this->session->set('eccube.admin.regular.order.search'$viewData);
  130.                 $this->session->set('eccube.admin.regular.order.search.page_no'$page_no);
  131.             }
  132.         }
  133.         $qb $this->regularOrderRepository->getQueryBuilderBySearchDataForAdmin($searchData);
  134.         $pagination $paginator->paginate(
  135.             $qb,
  136.             $page_no,
  137.             $page_count
  138.         );
  139.         // 受注一括作成漏れチェックを実施
  140.         $missingOrderCreationIds $this->getMissingOrderCreationIds();
  141.         // メール送信漏れチェックを実施
  142.         $missingMailSendIds $this->getMissingMailSendIds();
  143.         // 各顧客に代理店名を追加
  144.         foreach ($pagination as $RegularOrder) {
  145.             $customer $RegularOrder->getCustomer();
  146.             if ($customer !== null) {
  147.                 $agencyName $this->customizeCustomerRepository->findAgencyNameByCustomerId($customer->getId());
  148.                 $agencyId $this->customizeCustomerRepository->findAgencyIdByCustomerId($customer->getId());
  149.                 $RegularOrder->agencyName $agencyName;
  150.                 $RegularOrder->agencyId $agencyId;
  151.             } else {
  152.                 $RegularOrder->agencyName "";
  153.                 $RegularOrder->agencyId null;
  154.             }
  155.             // 受注一括作成漏れフラグ
  156.             $RegularOrder->hasMissingOrderCreation in_array($RegularOrder->getId(), $missingOrderCreationIds);
  157.             // メール送信漏れフラグを追加 ← 追加
  158.             $RegularOrder->hasMissingMailSend in_array($RegularOrder->getId(), $missingMailSendIds);
  159.         }
  160.         // 現在のユーザーを取得(ログインユーザー)
  161.         $member $this->getUser();
  162.         $authority $member->getAuthority();
  163.         return [
  164.             'authority' => $authority,
  165.             'searchForm' => $searchForm->createView(),
  166.             'pagination' => $pagination,
  167.             'pageMaxis' => $pageMaxis,
  168.             'page_no' => $page_no,
  169.             'page_count' => $page_count,
  170.             'has_errors' => false,
  171.             'createdAt' => $createdAt,
  172.             'missingOrderCreationCount' => count($missingOrderCreationIds),
  173.             'missingMailSendCount' => count($missingMailSendIds),
  174.         ];
  175.     }
  176.     /**
  177.      * 受注一括作成が漏れている定期便IDの配列を取得
  178.      * 
  179.      * @return array
  180.      */
  181.     private function getMissingOrderCreationIds(): array
  182.     {
  183.         $today = new \DateTime('today');
  184.         $batchExecutionTime = new \DateTime('today 12:20:00');
  185.         $now = new \DateTime();
  186.         //本日の受注一括作成対象を含めるかどうか
  187.         $todayInclude false;
  188.         //12時20分を過ぎている場合、本日の受注一括作成対象を含める
  189.         if ($now >= $batchExecutionTime) {
  190.             $todayInclude true;
  191.         }
  192.         // 対象定期便を取得
  193.         $targetRegularOrders $this->getTargetRegularOrders($todayInclude);
  194.         $missingIds = [];
  195.         foreach ($targetRegularOrders as $regularOrder) {
  196.             $validationResult $this->validateSingleRegularOrder($regularOrder$todayInclude);
  197.             if (!$validationResult['is_valid']) {
  198.                 $missingIds[] = $regularOrder->getId();
  199.             }
  200.         }
  201.         return $missingIds;
  202.     }
  203.     /**
  204.      * 個別の定期受注の検証
  205.      * 
  206.      * @param \Plugin\EccubePaymentLite42\Entity\RegularOrder $regularOrder
  207.      * @param \DateTime $targetDate
  208.      * @return array
  209.      */
  210.     private function validateSingleRegularOrder($regularOrder$todayInclude): array
  211.     {
  212.         $regularStatus $regularOrder->getRegularStatus();
  213.         $regularStopDate $regularOrder->getRegularStopDate();
  214.         $RegularShipping $regularOrder->getRegularShippings()->first();
  215.         // エラー判定用の配列
  216.         $errors = [];
  217.         switch ($regularStatus->getId()) {
  218.             // 継続の場合
  219.             case RegularStatus::CONTINUE:
  220.                 // 再開した場合、次回配送お届け日が8日後になるため、次回配送日が7日後のものは昨日に再開した定期便となる
  221.                 $targetDaysLater = new \DateTime('today');
  222.                 if ($todayInclude) {
  223.                     $targetDaysLater->modify('+ 8 day');
  224.                 } else {
  225.                     $targetDaysLater->modify('+ 7 day');
  226.                 }
  227.                 // 再開判定(停止日あり)
  228.                 if ($regularStopDate && $RegularShipping) {
  229.                     // 再開かつ8日以内 → エラー
  230.                     if ($RegularShipping->getNextDeliveryDate() < $targetDaysLater) {
  231.                         $errors[] = '再開後の受注一括作成処理が実施されていません。(継続[再開])';
  232.                     }
  233.                 } else {
  234.                     // 通常の継続の場合は、受注一括作成漏れの為エラー 
  235.                     $errors[] = '受注一括作成処理が実施されていません。(継続)';
  236.                 }
  237.                 break;
  238.             // 決済エラーの場合
  239.             case RegularStatus::PAYMENT_ERROR:
  240.                 $errors[] = '受注一括作成処理が実施されていません(決済エラー)。';
  241.                 break;
  242.             // 再決済待ちの場合
  243.             case RegularStatus::WAITING_RE_PAYMENT:
  244.                 $errors[] = '受注一括作成処理が実施されていません(再決済待ち)。';
  245.                 break;
  246.             default:
  247.                 // それ以外のステータスはクエリ上ありえないが、例外処理としてエラーを出力
  248.                 $errors[] = sprintf(
  249.                     '定期受注ID %d のステータスが想定外です(%s)',
  250.                     $regularOrder->getId(),
  251.                     $regularStatus->getName()
  252.                 );
  253.         }
  254.         return [
  255.             'is_valid' => empty($errors),
  256.             'errors' => $errors,
  257.         ];
  258.     }
  259.     /**
  260.      * 対象の定期便を取得
  261.      * 
  262.      * @return array
  263.      */
  264.     private function getTargetRegularOrders($todayInclude): array
  265.     {
  266.         /** @var \Plugin\EccubePaymentLite42\Entity\Config $Config */
  267.         $Config $this->entityManager
  268.             ->getRepository(\Plugin\EccubePaymentLite42\Entity\Config::class)
  269.             ->find(1);
  270.         if (!$Config) {
  271.             return [];
  272.         }
  273.         // 対象の定期便の日付を計算
  274.         $deadLineStartDate = new \DateTime('today');
  275.         $deadLineStartDate->modify('- 14 day'); // 過去2週間分をチェック
  276.         //本日日付を含める場合(12:20分以降)
  277.         if ($todayInclude) {
  278.             $deadLineEndDate = new \DateTime('tomorrow');
  279.             $deadLineEndDate->modify('+' $Config->getRegularOrderDeadline() . ' day');
  280.         } else {
  281.             //本日日付を含めない場合(12:20分より前)
  282.             $deadLineEndDate = new \DateTime('tomorrow');
  283.             $deadLineEndDate->modify('+' $Config->getRegularOrderDeadline() - ' day');
  284.         }
  285.         // 定期便データの受け取り
  286.         /** @var RegularOrder[] $RegularOrders */
  287.         $RegularOrders $this
  288.             ->regularOrderRepository
  289.             ->getRegularOrdersForCommand(clone $deadLineStartDate, clone $deadLineEndDate);
  290.         return $RegularOrders;
  291.     }
  292.     /**
  293.      * メール送信が漏れている定期便IDの配列を取得
  294.      * 
  295.      * @return array
  296.      */
  297.     private function getMissingMailSendIds(): array
  298.     {
  299.         $mailExecutionTime = new \DateTime('today 13:00:00');
  300.         $now = new \DateTime();
  301.         $missingOrders = [];
  302.         // 過去14日分をチェック
  303.         $checkDays 14;
  304.         for ($i 0$i $checkDays$i++) {
  305.             $targetDate = new \DateTime('today');
  306.             $targetDate->modify('-' $i ' day');
  307.             // 13時より前で本日の場合はスキップ
  308.             if ($now $mailExecutionTime && $i === 0) {
  309.                 continue;
  310.             }
  311.         
  312.         // リポジトリから該当日の定期便を取得
  313.             /** @var RegularOrder[] $regularOrders */
  314.             $regularOrders $this
  315.                 ->regularOrderRepository
  316.                 ->getRegularOrdersForErrorNotification($targetDate);
  317.             foreach ($regularOrders as $regularOrder) {
  318.                 // 重複チェック(IDをキーにして保存)
  319.                 if (!isset($missingOrders[$regularOrder->getId()])) {
  320.                     $missingOrders[$regularOrder->getId()] = $regularOrder;
  321.                 }
  322.             }
  323.         }
  324.         // 各定期便のメール送信状況を検証
  325.         $missingIds = [];
  326.         foreach ($missingOrders as $regularOrder) {
  327.             $validationResult $this->validateSingleRegularOrderForMail($regularOrder);
  328.             if (!$validationResult['is_valid']) {
  329.                 $missingIds[] = $regularOrder->getId();
  330.             }
  331.         }
  332.         return $missingIds;
  333.     }
  334.     /**
  335.      * 個別の定期受注のメール送信検証
  336.      * 
  337.      * @param \Plugin\EccubePaymentLite42\Entity\RegularOrder $regularOrder
  338.      * @return array
  339.      */
  340.     private function validateSingleRegularOrderForMail($regularOrder): array
  341.     {
  342.         $regularStatus $regularOrder->getRegularStatus();
  343.         $bulkOrderCreatedAt $regularOrder->getBulkOrderCreatedAt();
  344.         // エラー判定用の配列
  345.         $errors = [];
  346.         // bulk_order_created_at がnullでない = メール送信漏れ
  347.         if ($bulkOrderCreatedAt !== null) {
  348.             switch ($regularStatus->getId()) {
  349.                 // 休止(再開からの再休止)の場合
  350.                 case RegularStatus::SUSPEND:
  351.                     $errors[] = '再休止通知メールが送信されていません。';
  352.                     break;
  353.                 // 決済エラーの場合
  354.                 case RegularStatus::PAYMENT_ERROR:
  355.                     $currentPaymentErrorCount $regularOrder->getPaymentErrorCount();
  356.                     if ($currentPaymentErrorCount == 1) {
  357.                         $errors[] = '初回決済エラー通知メールが送信されていません。';
  358.                     } elseif ($currentPaymentErrorCount == 2) {
  359.                         $errors[] = '2回目の決済エラー、スキップ通知メールが送信されていません。';
  360.                     } else {
  361.                         $errors[] = sprintf(
  362.                             '予期しないエラーカウント値です(PaymentErrorCount: %d)',
  363.                             $currentPaymentErrorCount
  364.                         );
  365.                     }
  366.                     break;
  367.                 // 解約の場合
  368.                 case RegularStatus::CANCELLATION:
  369.                 case RegularStatus::CANCELLATION_EXPIRED_RESUMPTION:
  370.                     $currentPaymentErrorCount $regularOrder->getPaymentErrorCount();
  371.                     if ($currentPaymentErrorCount == 3) {
  372.                         $errors[] = '自動解約通知メールが送信されていません。';
  373.                     } else {
  374.                         // エラーカウントが3でない解約は通常のフロー(メール送信漏れではない)
  375.                         // エラーとして扱わない
  376.                     }
  377.                     break;
  378.                 default:
  379.                     // その他のステータスは対象外
  380.                     break;
  381.             }
  382.         }
  383.         return [
  384.             'is_valid' => empty($errors),
  385.             'errors' => $errors,
  386.         ];
  387.     }
  388. }