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

247 lines
6.5KB

  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. throw new ExclusiveException();
  56. }
  57. return $this;
  58. }
  59. protected function fetch(string $receiptIssuingOrderId)
  60. {
  61. $order = ReceiptIssuingOrder::findOrFail($receiptIssuingOrderId);
  62. if (!$this->loginUser()->checkAuthorization($order)) {
  63. throw new AppCommonException("認可不良");
  64. }
  65. $this->order = $order;
  66. }
  67. protected function refreshToken()
  68. {
  69. $order = $this->order;
  70. $order->access_token = base64_encode(Str::uuid());
  71. $order->access_token_expires_at = DateUtil::now()->adddays(7);
  72. return $this;
  73. }
  74. protected function checkToken(string $token): bool
  75. {
  76. $order = ReceiptIssuingOrder::whereAccessToken($token)
  77. ->first();
  78. if (!($order instanceof ReceiptIssuingOrder)) {
  79. return false;
  80. }
  81. if ($order->access_token_expires_at === null) {
  82. return false;
  83. }
  84. if ($order->access_token !== $token) {
  85. logger("TOKEN 期限切れ");
  86. return false;
  87. }
  88. $now = DateUtil::now();
  89. $ret = $now->lt($this->order->access_token_expires_at);
  90. if (!$ret) {
  91. logger("TOKEN 期限切れ");
  92. return false;
  93. }
  94. $this->order = $order;
  95. $this->initialized = true;
  96. return true;
  97. }
  98. protected function setStatus(): static
  99. {
  100. $order = $this->order;
  101. $order->status_done = false;
  102. // 郵送関連
  103. if ($order->status_mail_post_date !== null) {
  104. $order->status_name = "投函済み";
  105. $order->status_done = true;
  106. return $this;
  107. }
  108. if ($order->status_order_mail_datetime !== null) {
  109. $order->status_name = "郵送依頼中";
  110. return $this;
  111. }
  112. // メール配信
  113. if ($order->status_receipt_email_send_datetime !== null) {
  114. $order->status_name = "領収証メール配信済み";
  115. $order->status_done = true;
  116. return $this;
  117. }
  118. if ($order->status_mail_post_date !== null) {
  119. $order->status_name = "領収証メール配信依頼中";
  120. return $this;
  121. }
  122. // ダウンロード
  123. if ($order->status_receipt_download_datetime !== null) {
  124. $order->status_name = "ダウンロード済み";
  125. $order->status_done = true;
  126. return $this;
  127. }
  128. // 申請段階
  129. if ($order->status_receipt_confirm_datetime !== null) {
  130. $order->status_name = "確定済み";
  131. return $this;
  132. }
  133. if ($order->status_first_access_datetime !== null) {
  134. $order->status_name = "アクセス済み";
  135. return $this;
  136. }
  137. if ($order->status_sms_send_datetime !== null) {
  138. $order->status_name = "SMS配信済み";
  139. return $this;
  140. }
  141. if ($order->sms_send_success === false) {
  142. $order->status_name = "SMS送信失敗";
  143. return $this;
  144. }
  145. $order->status_name = "新規登録";
  146. return $this;
  147. }
  148. protected function save(): static
  149. {
  150. $this->setStatus()
  151. ->updateCheck();
  152. $this->order->save();
  153. return $this;
  154. }
  155. public function setConfirm(): static
  156. {
  157. if ($this->order->receipt_no !== null) {
  158. throw new LogicException("領収証確定済み変更検知");
  159. }
  160. $this->order->receipt_no = $this->generateReceiptnNo();
  161. $this->order->status_receipt_confirm_datetime = DateUtil::now();
  162. return $this;
  163. }
  164. private function generateReceiptnNo(): string
  165. {
  166. $count = 0;
  167. while (true) {
  168. $now = DateUtil::now();
  169. $receiptNo = sprintf("%04d%02d%02d-%06d", $now->year, $now->month, $now->day, random_int(0, 999999));
  170. if (!ReceiptIssuingOrder::whereReceiptNo($receiptNo)->exists()) {
  171. return $receiptNo;
  172. }
  173. $count++;
  174. if (1000 < $count) {
  175. throw new AppCommonException("領収証番号取得不正エラー");
  176. }
  177. }
  178. }
  179. private function updateCheck(): static
  180. {
  181. // 確定済みデータの変更確認
  182. if ($this->order->getOriginal(ReceiptIssuingOrder::COL_NAME_STATUS_RECEIPT_CONFIRM_DATETIME) !== null) {
  183. if ($this->order->isDirty([
  184. ReceiptIssuingOrder::COL_NAME_RECEIPT_USE_DATE,
  185. ReceiptIssuingOrder::COL_NAME_RECEIPT_SHOP_NAME,
  186. ReceiptIssuingOrder::COL_NAME_RECEIPT_ISSUER,
  187. ReceiptIssuingOrder::COL_NAME_RECEIPT_PURPOSE,
  188. ReceiptIssuingOrder::COL_NAME_RECEIPT_NAME,
  189. ReceiptIssuingOrder::COL_NAME_RECEIPT_INVOICE_NO,
  190. ReceiptIssuingOrder::COL_NAME_RECEIPT_AMOUNT,
  191. ])) {
  192. throw new LogicException("確定済みデータの変更を検知");
  193. }
  194. }
  195. return $this;
  196. }
  197. }