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

253 lines
6.6KB

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