領収証発行サービス
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.

250 lines
6.6KB

  1. <?php
  2. namespace App\Logic\ReceiptIssuingOrder;
  3. use App\Exceptions\AppCommonException;
  4. use App\Exceptions\ExclusiveException;
  5. use App\Features\InstanceAble;
  6. use App\Features\LoginUser;
  7. use App\Models\ReceiptIssuingOrder;
  8. use App\Util\DateUtil;
  9. use Illuminate\Support\Carbon;
  10. use Illuminate\Support\Str;
  11. use LogicException;
  12. abstract class ReceiptIssuingOrderManager
  13. {
  14. use LoginUser, InstanceAble;
  15. protected bool $initialized = false;
  16. public function __construct(
  17. protected ReceiptIssuingOrder $order,
  18. ) {
  19. }
  20. public function initByToken(string $token)
  21. {
  22. $ret = $this->checkToken($token);
  23. if (!$ret) {
  24. throw new AppCommonException("トークン不正");
  25. }
  26. $this->initialized = true;
  27. return $this;
  28. }
  29. public function initById(string $id)
  30. {
  31. $this->fetch($id);
  32. $this->initialized = true;
  33. return $this;
  34. }
  35. public function getOrder(): array
  36. {
  37. if (!$this->initialized) {
  38. throw new LogicException("初期化ミス");
  39. }
  40. return $this->order->toArray();
  41. }
  42. public function isConfirmed(): bool
  43. {
  44. if (!$this->initialized) {
  45. throw new LogicException("初期化ミス");
  46. }
  47. return $this->order->status_receipt_confirm_datetime !== null;
  48. }
  49. public function checkTimestamp(Carbon $timestamp): static
  50. {
  51. if (!$this->initialized) {
  52. throw new LogicException("初期化ミス");
  53. }
  54. if ($this->order->updated_at->notEqualTo($timestamp)) {
  55. logger([
  56. 'request' => $timestamp,
  57. 'current' => $this->order->updated_at,
  58. ]);
  59. throw new ExclusiveException();
  60. }
  61. return $this;
  62. }
  63. protected function fetch(string $receiptIssuingOrderId)
  64. {
  65. $order = ReceiptIssuingOrder::findOrFail($receiptIssuingOrderId);
  66. if (!$this->loginUser()->checkAuthorization($order)) {
  67. throw new AppCommonException("認可不良");
  68. }
  69. $this->order = $order;
  70. }
  71. protected function refreshToken()
  72. {
  73. $order = $this->order;
  74. $order->access_token = base64_encode(Str::uuid());
  75. $order->access_token_expires_at = DateUtil::now()->adddays(7);
  76. return $this;
  77. }
  78. protected function checkToken(string $token): bool
  79. {
  80. $order = ReceiptIssuingOrder::whereAccessToken($token)
  81. ->first();
  82. if (!($order instanceof ReceiptIssuingOrder)) {
  83. return false;
  84. }
  85. if ($order->access_token_expires_at === null) {
  86. return false;
  87. }
  88. if ($order->access_token !== $token) {
  89. logger("TOKEN 期限切れ");
  90. return false;
  91. }
  92. $now = DateUtil::now();
  93. $ret = $now->lt($this->order->access_token_expires_at);
  94. if (!$ret) {
  95. logger("TOKEN 期限切れ");
  96. return false;
  97. }
  98. $this->order = $order;
  99. $this->initialized = true;
  100. return true;
  101. }
  102. protected function setStatus(): static
  103. {
  104. $order = $this->order;
  105. $order->status_done = false;
  106. // 郵送関連
  107. if ($order->status_mail_post_date !== null) {
  108. $order->status_name = "投函済み";
  109. $order->status_done = true;
  110. return $this;
  111. }
  112. if ($order->status_order_mail_datetime !== null) {
  113. $order->status_name = "郵送依頼中";
  114. return $this;
  115. }
  116. // メール配信
  117. if ($order->status_receipt_email_send_datetime !== null) {
  118. $order->status_name = "領収証メール配信済み";
  119. $order->status_done = true;
  120. return $this;
  121. }
  122. if ($order->status_mail_post_date !== null) {
  123. $order->status_name = "領収証メール配信依頼中";
  124. return $this;
  125. }
  126. // ダウンロード
  127. if ($order->status_receipt_download_datetime !== null) {
  128. $order->status_name = "ダウンロード済み";
  129. $order->status_done = true;
  130. return $this;
  131. }
  132. // 申請段階
  133. if ($order->status_receipt_confirm_datetime !== null) {
  134. $order->status_name = "確定済み";
  135. return $this;
  136. }
  137. if ($order->status_first_access_datetime !== null) {
  138. $order->status_name = "アクセス済み";
  139. return $this;
  140. }
  141. if ($order->status_sms_send_datetime !== null) {
  142. $order->status_name = "SMS配信済み";
  143. return $this;
  144. }
  145. if ($order->sms_send_success === false) {
  146. $order->status_name = "SMS送信失敗";
  147. return $this;
  148. }
  149. $order->status_name = "新規登録";
  150. return $this;
  151. }
  152. protected function save(): static
  153. {
  154. $this->setStatus()
  155. ->updateCheck();
  156. $this->order->save();
  157. return $this;
  158. }
  159. public function setConfirm(): static
  160. {
  161. if ($this->order->receipt_no !== null) {
  162. throw new LogicException("領収証確定済み変更検知");
  163. }
  164. $this->order->receipt_no = $this->generateReceiptnNo();
  165. $this->order->status_receipt_confirm_datetime = DateUtil::now();
  166. return $this;
  167. }
  168. private function generateReceiptnNo(): string
  169. {
  170. $count = 0;
  171. while (true) {
  172. $now = DateUtil::now();
  173. $receiptNo = sprintf("%04d%02d%02d-%06d", $now->year, $now->month, $now->day, random_int(0, 999999));
  174. if (!ReceiptIssuingOrder::whereReceiptNo($receiptNo)->exists()) {
  175. return $receiptNo;
  176. }
  177. $count++;
  178. if (1000 < $count) {
  179. throw new AppCommonException("領収証番号取得不正エラー");
  180. }
  181. }
  182. }
  183. private function updateCheck(): static
  184. {
  185. // 確定済みデータの変更確認
  186. if ($this->order->getOriginal(ReceiptIssuingOrder::COL_NAME_STATUS_RECEIPT_CONFIRM_DATETIME) !== null) {
  187. if ($this->order->isDirty([
  188. ReceiptIssuingOrder::COL_NAME_RECEIPT_USE_DATE,
  189. ReceiptIssuingOrder::COL_NAME_RECEIPT_SHOP_NAME,
  190. ReceiptIssuingOrder::COL_NAME_RECEIPT_ISSUER,
  191. ReceiptIssuingOrder::COL_NAME_RECEIPT_PURPOSE,
  192. ReceiptIssuingOrder::COL_NAME_RECEIPT_NAME,
  193. ReceiptIssuingOrder::COL_NAME_RECEIPT_INVOICE_NO,
  194. ReceiptIssuingOrder::COL_NAME_RECEIPT_AMOUNT,
  195. ])) {
  196. throw new LogicException("確定済みデータの変更を検知");
  197. }
  198. }
  199. return $this;
  200. }
  201. }