You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
5.6KB

  1. <?php
  2. namespace App\Logics\QRService;
  3. use App\Codes\DepositTransferReason;
  4. use App\Exceptions\AppCommonException;
  5. use App\Models\ColumnName;
  6. use App\Models\HtpmsCustomer\QRService\AcquisitionAvailableSetting;
  7. use App\Models\HtpmsCustomer\QRService\AcquisitionTicket;
  8. use App\Models\HtpmsCustomer\QRService\AcquisitionTicketToken;
  9. use App\Models\HtpmsCustomer\QRService\ServiceParkingGroupRelation;
  10. use App\Util\DateUtil;
  11. use Illuminate\Support\Carbon;
  12. use Str;
  13. class CreateLogic
  14. {
  15. use DepositCheck;
  16. /**
  17. * サービス券を作成する
  18. */
  19. public static function create(
  20. string $token,
  21. ) {
  22. // トークンから店舗ID検索
  23. $t = AcquisitionTicketToken::whereToken($token)->first();
  24. if ($t instanceof AcquisitionTicketToken === false) {
  25. throw new AppCommonException(sprintf("トークン不正 %s", $token));
  26. }
  27. $shopId = $t->shop_id;
  28. // 割引設定有無の確認
  29. $check = AcquisitionAvailableSetting::whereShopId($shopId)
  30. ->first();
  31. if ($check instanceof AcquisitionAvailableSetting === false) {
  32. throw new AppCommonException("取得できない割引");
  33. }
  34. // デポジットチェック
  35. if (!self::canCreate($shopId)) {
  36. throw new AppCommonException("認証不可 デポジット");
  37. }
  38. [$shop] = self::getData($shopId);
  39. // 設定値の検索
  40. $setting = AcquisitionAvailableSetting::whereShopId($shopId)
  41. ->first();
  42. if ($setting instanceof AcquisitionAvailableSetting === false) {
  43. throw new AppCommonException("QRサービス券取得可能設定 不正");
  44. }
  45. $qr = new AcquisitionTicket();
  46. $qr->qr_service_parking_group_id = $check->qr_service_parking_group_id;
  47. $qr->publishing_no = self::getNextSeqNo($setting->shop_no);
  48. $qr->shop_id = $shopId;
  49. $qr->shop_no = $setting->shop_no;
  50. $qr->discount_ticket_code = $setting->discount_ticket_code;
  51. $qr->qr_service_parking_group_id = $setting->qr_service_parking_group_id;
  52. // 有効期限設定
  53. $qr->expires_at = DateUtil::now()->addMinutes($shop->qr_service_expire_min);
  54. $qr->publishing_date = DateUtil::now();
  55. $qr->save();
  56. return $qr;
  57. }
  58. public static function getUsable(int $shopNo, Carbon $publishingDate, int $seqNo): AcquisitionTicket
  59. {
  60. $qr = AcquisitionTicket::query()
  61. ->whereShopNo($shopNo)
  62. ->wherePublishingDate($publishingDate)
  63. ->wherePublishingNo($seqNo)
  64. ->lockForUpdate()
  65. ->first();
  66. if ($qr instanceof AcquisitionTicket === false) {
  67. throw new AppCommonException("QR 認証なし");
  68. }
  69. if ($qr->iseExpired()) {
  70. throw new AppCommonException("QR 期限切れ");
  71. }
  72. if ($qr->isUsed()) {
  73. throw new AppCommonException("QR 使用済み");
  74. }
  75. return $qr;
  76. }
  77. /**
  78. * サービス券を使用する
  79. *
  80. * @param integer $shopNo
  81. * @param string $parkingManagementCode
  82. * @param Carbon $publishingDate
  83. * @param integer $seqNo
  84. * @param integer $discountTicketCode
  85. * @param Carbon $adjustDatetime
  86. * @param integer $discountAmount
  87. * @return void
  88. */
  89. public static function use(
  90. int $shopNo,
  91. string $parkingManagementCode,
  92. Carbon $publishingDate,
  93. int $seqNo,
  94. int $discountTicketCode,
  95. Carbon $adjustDatetime,
  96. int $discountAmount,
  97. ) {
  98. // QRコード情報の取得
  99. $qr = self::getUsable($shopNo, $publishingDate, $seqNo);
  100. // QRコードサービス券駐車場グループに含まれているかチェック
  101. self::checkQrParkingGroup($qr->qr_service_parking_group_id, $parkingManagementCode);
  102. // デポジット処理
  103. self::useDeposit($qr->shop_id, $discountAmount, DepositTransferReason::駐車料金割引_取得);
  104. $qr->discount_amount = $discountAmount;
  105. // 利用情報
  106. $qr->used_at = $adjustDatetime;
  107. $qr->discount_ticket_code = $discountTicketCode;
  108. $qr->parking_management_code = $parkingManagementCode;
  109. $qr->save();
  110. }
  111. public static function getToken(string $shopId, bool $refresh = false): AcquisitionTicketToken
  112. {
  113. $token = AcquisitionTicketToken::whereShopId($shopId)
  114. ->first();
  115. if ($refresh) {
  116. if ($token instanceof AcquisitionTicketToken === true) {
  117. $token->delete();
  118. $token = null;
  119. }
  120. }
  121. if ($token instanceof AcquisitionTicketToken) {
  122. return $token;
  123. }
  124. // トークン新規作成
  125. $token = new AcquisitionTicketToken();
  126. $token->token = Str::uuid()->toString();
  127. $token->shop_id = $shopId;
  128. $token->save();
  129. return $token;
  130. }
  131. private static function getNextSeqNo(int $shopNo)
  132. {
  133. $max = AcquisitionTicket::query()
  134. ->whereShopNo($shopNo)
  135. ->wherePublishingDate(DateUtil::now())
  136. ->max(ColumnName::PUBLISHING_NO);
  137. if ($max === null) return 1;
  138. return $max + 1;
  139. }
  140. private static function checkQrParkingGroup(string $groupId, string $parkingManagementCode)
  141. {
  142. $query = ServiceParkingGroupRelation::query()
  143. ->whereQrServiceParkingGroupId($groupId)
  144. ->whereParkingManagementCode($parkingManagementCode);
  145. if (!$query->exists()) {
  146. throw new AppCommonException("利用できない駐車場");
  147. }
  148. }
  149. }