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

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