<?php
namespace Plugin\EccubePaymentLite42\Controller\Admin\Regular;
use Eccube\Controller\AbstractController;
use Eccube\Repository\Master\PageMaxRepository;
use Eccube\Util\FormUtil;
use Knp\Component\Pager\PaginatorInterface;
use Plugin\EccubePaymentLite42\Form\Type\Admin\SearchRegularOrderType;
use Plugin\EccubePaymentLite42\Repository\RegularOrderRepository;
use Plugin\EccubePaymentLite42\Service\IsActiveRegularService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Plugin\EccubePaymentLite42\Entity\Config;
use Plugin\EccubePaymentLite42\Repository\ConfigRepository;
use Plugin\EccubePaymentLite42\Entity\RegularStatus;
//----------
//代理店名の取得はカスタムリポジトリを使用
//----------
use Customize\Repository\CustomizeCustomerRepository;
class OrderController extends AbstractController
{
/**
* @var PageMaxRepository
*/
private $pageMaxRepository;
/**
* @var RegularOrderRepository
*/
private $regularOrderRepository;
/**
* @var IsActiveRegularService
*/
private $isActiveRegularService;
/**
* @var ConfigRepository
*/
private $configRepository;
//----代理店カスタマイズ------
//代理店名の取得はカスタムリポジトリを使用
//----------
private $customizeCustomerRepository;
public function __construct(
PageMaxRepository $pageMaxRepository,
RegularOrderRepository $regularOrderRepository,
IsActiveRegularService $isActiveRegularService,
CustomizeCustomerRepository $customizeCustomerRepository,
ConfigRepository $configRepository
) {
$this->pageMaxRepository = $pageMaxRepository;
$this->regularOrderRepository = $regularOrderRepository;
$this->isActiveRegularService = $isActiveRegularService;
$this->customizeCustomerRepository = $customizeCustomerRepository;
$this->configRepository = $configRepository;
}
/**
* @Route(
* "/%eccube_admin_route%/eccube_payment_lite/regular/index",
* name="eccube_payment_lite42_admin_regular_index", methods={"GET", "POST"}
* )
* @Route(
* "/%eccube_admin_route%/eccube_payment_lite/regular/index/page/{page_no}", requirements={"page_no" = "\d+"},
* name="eccube_payment_lite42_admin_regular_index_page" , methods={"GET", "POST"}
* )
* @Template("@EccubePaymentLite42/admin/Regular/Order/index.twig")
*/
public function index(Request $request, PaginatorInterface $paginator, $page_no = null)
{
if (!$this->isActiveRegularService->isActive()) {
throw new NotFoundHttpException();
}
/** @var Config $Config */
$Config = $this->configRepository->find(1);
$createdAt = $Config->getCreatedAt();
$searchForm = $this->createForm(SearchRegularOrderType::class);
$page_count = $this->session->get(
'eccube.admin.regular.order.search.page_count',
$this->eccubeConfig->get('eccube_default_page_count')
);
$page_count_param = (int) $request->get('page_count');
$pageMaxis = $this->pageMaxRepository->findAll();
if ($page_count_param) {
foreach ($pageMaxis as $pageMax) {
if ($page_count_param == $pageMax->getName()) {
$page_count = $pageMax->getName();
$this->session->set('eccube.admin.regular.order.search.page_count', $page_count);
break;
}
}
}
if ('POST' === $request->getMethod()) {
$searchForm->handleRequest($request);
if ($searchForm->isValid()) {
$page_no = 1;
$searchData = $searchForm->getData();
// 検索条件, ページ番号をセッションに保持.
$this->session->set('eccube.admin.regular.order.search', FormUtil::getViewData($searchForm));
$this->session->set('eccube.admin.regular.order.search.page_no', $page_no);
} else {
// 検索エラーの際は, 詳細検索枠を開いてエラー表示する.
return [
'searchForm' => $searchForm->createView(),
'pagination' => [],
'pageMaxis' => $pageMaxis,
'page_no' => $page_no,
'page_count' => $page_count,
'has_errors' => true,
'createdAt' => $createdAt,
'missingOrderCreationCount' => 0,
];
}
} else {
if (null !== $page_no || $request->get('resume')) {
if ($page_no) {
$this->session->set('eccube.admin.regular.order.search.page_no', (int) $page_no);
} else {
$page_no = $this->session->get('eccube.admin.regular.order.search.page_no', 1);
}
$viewData = $this->session->get('eccube.admin.regular.order.search', []);
$searchData = FormUtil::submitAndGetData($searchForm, $viewData);
} else {
$page_no = 1;
$viewData = [];
if ($statusId = (int) $request->get('order_status_id')) {
$viewData = ['status' => $statusId];
}
$searchData = FormUtil::submitAndGetData($searchForm, $viewData);
// セッション中の検索条件, ページ番号を初期化.
$this->session->set('eccube.admin.regular.order.search', $viewData);
$this->session->set('eccube.admin.regular.order.search.page_no', $page_no);
}
}
$qb = $this->regularOrderRepository->getQueryBuilderBySearchDataForAdmin($searchData);
$pagination = $paginator->paginate(
$qb,
$page_no,
$page_count
);
// 受注一括作成漏れチェックを実施
$missingOrderCreationIds = $this->getMissingOrderCreationIds();
// メール送信漏れチェックを実施
$missingMailSendIds = $this->getMissingMailSendIds();
// 各顧客に代理店名を追加
foreach ($pagination as $RegularOrder) {
$customer = $RegularOrder->getCustomer();
if ($customer !== null) {
$agencyName = $this->customizeCustomerRepository->findAgencyNameByCustomerId($customer->getId());
$agencyId = $this->customizeCustomerRepository->findAgencyIdByCustomerId($customer->getId());
$RegularOrder->agencyName = $agencyName;
$RegularOrder->agencyId = $agencyId;
} else {
$RegularOrder->agencyName = "";
$RegularOrder->agencyId = null;
}
// 受注一括作成漏れフラグ
$RegularOrder->hasMissingOrderCreation = in_array($RegularOrder->getId(), $missingOrderCreationIds);
// メール送信漏れフラグを追加 ← 追加
$RegularOrder->hasMissingMailSend = in_array($RegularOrder->getId(), $missingMailSendIds);
}
// 現在のユーザーを取得(ログインユーザー)
$member = $this->getUser();
$authority = $member->getAuthority();
return [
'authority' => $authority,
'searchForm' => $searchForm->createView(),
'pagination' => $pagination,
'pageMaxis' => $pageMaxis,
'page_no' => $page_no,
'page_count' => $page_count,
'has_errors' => false,
'createdAt' => $createdAt,
'missingOrderCreationCount' => count($missingOrderCreationIds),
'missingMailSendCount' => count($missingMailSendIds),
];
}
/**
* 受注一括作成が漏れている定期便IDの配列を取得
*
* @return array
*/
private function getMissingOrderCreationIds(): array
{
$today = new \DateTime('today');
$batchExecutionTime = new \DateTime('today 12:20:00');
$now = new \DateTime();
//本日の受注一括作成対象を含めるかどうか
$todayInclude = false;
//12時20分を過ぎている場合、本日の受注一括作成対象を含める
if ($now >= $batchExecutionTime) {
$todayInclude = true;
}
// 対象定期便を取得
$targetRegularOrders = $this->getTargetRegularOrders($todayInclude);
$missingIds = [];
foreach ($targetRegularOrders as $regularOrder) {
$validationResult = $this->validateSingleRegularOrder($regularOrder, $todayInclude);
if (!$validationResult['is_valid']) {
$missingIds[] = $regularOrder->getId();
}
}
return $missingIds;
}
/**
* 個別の定期受注の検証
*
* @param \Plugin\EccubePaymentLite42\Entity\RegularOrder $regularOrder
* @param \DateTime $targetDate
* @return array
*/
private function validateSingleRegularOrder($regularOrder, $todayInclude): array
{
$regularStatus = $regularOrder->getRegularStatus();
$regularStopDate = $regularOrder->getRegularStopDate();
$RegularShipping = $regularOrder->getRegularShippings()->first();
// エラー判定用の配列
$errors = [];
switch ($regularStatus->getId()) {
// 継続の場合
case RegularStatus::CONTINUE:
// 再開した場合、次回配送お届け日が8日後になるため、次回配送日が7日後のものは昨日に再開した定期便となる
$targetDaysLater = new \DateTime('today');
if ($todayInclude) {
$targetDaysLater->modify('+ 8 day');
} else {
$targetDaysLater->modify('+ 7 day');
}
// 再開判定(停止日あり)
if ($regularStopDate && $RegularShipping) {
// 再開かつ8日以内 → エラー
if ($RegularShipping->getNextDeliveryDate() < $targetDaysLater) {
$errors[] = '再開後の受注一括作成処理が実施されていません。(継続[再開])';
}
} else {
// 通常の継続の場合は、受注一括作成漏れの為エラー
$errors[] = '受注一括作成処理が実施されていません。(継続)';
}
break;
// 決済エラーの場合
case RegularStatus::PAYMENT_ERROR:
$errors[] = '受注一括作成処理が実施されていません(決済エラー)。';
break;
// 再決済待ちの場合
case RegularStatus::WAITING_RE_PAYMENT:
$errors[] = '受注一括作成処理が実施されていません(再決済待ち)。';
break;
default:
// それ以外のステータスはクエリ上ありえないが、例外処理としてエラーを出力
$errors[] = sprintf(
'定期受注ID %d のステータスが想定外です(%s)',
$regularOrder->getId(),
$regularStatus->getName()
);
}
return [
'is_valid' => empty($errors),
'errors' => $errors,
];
}
/**
* 対象の定期便を取得
*
* @return array
*/
private function getTargetRegularOrders($todayInclude): array
{
/** @var \Plugin\EccubePaymentLite42\Entity\Config $Config */
$Config = $this->entityManager
->getRepository(\Plugin\EccubePaymentLite42\Entity\Config::class)
->find(1);
if (!$Config) {
return [];
}
// 対象の定期便の日付を計算
$deadLineStartDate = new \DateTime('today');
$deadLineStartDate->modify('- 14 day'); // 過去2週間分をチェック
//本日日付を含める場合(12:20分以降)
if ($todayInclude) {
$deadLineEndDate = new \DateTime('tomorrow');
$deadLineEndDate->modify('+' . $Config->getRegularOrderDeadline() . ' day');
} else {
//本日日付を含めない場合(12:20分より前)
$deadLineEndDate = new \DateTime('tomorrow');
$deadLineEndDate->modify('+' . $Config->getRegularOrderDeadline() - 1 . ' day');
}
// 定期便データの受け取り
/** @var RegularOrder[] $RegularOrders */
$RegularOrders = $this
->regularOrderRepository
->getRegularOrdersForCommand(clone $deadLineStartDate, clone $deadLineEndDate);
return $RegularOrders;
}
/**
* メール送信が漏れている定期便IDの配列を取得
*
* @return array
*/
private function getMissingMailSendIds(): array
{
$mailExecutionTime = new \DateTime('today 13:00:00');
$now = new \DateTime();
$missingOrders = [];
// 過去14日分をチェック
$checkDays = 14;
for ($i = 0; $i < $checkDays; $i++) {
$targetDate = new \DateTime('today');
$targetDate->modify('-' . $i . ' day');
// 13時より前で本日の場合はスキップ
if ($now < $mailExecutionTime && $i === 0) {
continue;
}
// リポジトリから該当日の定期便を取得
/** @var RegularOrder[] $regularOrders */
$regularOrders = $this
->regularOrderRepository
->getRegularOrdersForErrorNotification($targetDate);
foreach ($regularOrders as $regularOrder) {
// 重複チェック(IDをキーにして保存)
if (!isset($missingOrders[$regularOrder->getId()])) {
$missingOrders[$regularOrder->getId()] = $regularOrder;
}
}
}
// 各定期便のメール送信状況を検証
$missingIds = [];
foreach ($missingOrders as $regularOrder) {
$validationResult = $this->validateSingleRegularOrderForMail($regularOrder);
if (!$validationResult['is_valid']) {
$missingIds[] = $regularOrder->getId();
}
}
return $missingIds;
}
/**
* 個別の定期受注のメール送信検証
*
* @param \Plugin\EccubePaymentLite42\Entity\RegularOrder $regularOrder
* @return array
*/
private function validateSingleRegularOrderForMail($regularOrder): array
{
$regularStatus = $regularOrder->getRegularStatus();
$bulkOrderCreatedAt = $regularOrder->getBulkOrderCreatedAt();
// エラー判定用の配列
$errors = [];
// bulk_order_created_at がnullでない = メール送信漏れ
if ($bulkOrderCreatedAt !== null) {
switch ($regularStatus->getId()) {
// 休止(再開からの再休止)の場合
case RegularStatus::SUSPEND:
$errors[] = '再休止通知メールが送信されていません。';
break;
// 決済エラーの場合
case RegularStatus::PAYMENT_ERROR:
$currentPaymentErrorCount = $regularOrder->getPaymentErrorCount();
if ($currentPaymentErrorCount == 1) {
$errors[] = '初回決済エラー通知メールが送信されていません。';
} elseif ($currentPaymentErrorCount == 2) {
$errors[] = '2回目の決済エラー、スキップ通知メールが送信されていません。';
} else {
$errors[] = sprintf(
'予期しないエラーカウント値です(PaymentErrorCount: %d)',
$currentPaymentErrorCount
);
}
break;
// 解約の場合
case RegularStatus::CANCELLATION:
case RegularStatus::CANCELLATION_EXPIRED_RESUMPTION:
$currentPaymentErrorCount = $regularOrder->getPaymentErrorCount();
if ($currentPaymentErrorCount == 3) {
$errors[] = '自動解約通知メールが送信されていません。';
} else {
// エラーカウントが3でない解約は通常のフロー(メール送信漏れではない)
// エラーとして扱わない
}
break;
default:
// その他のステータスは対象外
break;
}
}
return [
'is_valid' => empty($errors),
'errors' => $errors,
];
}
}