| @@ -56,3 +56,9 @@ VITE_PUSHER_HOST="${PUSHER_HOST}" | |||||
| VITE_PUSHER_PORT="${PUSHER_PORT}" | VITE_PUSHER_PORT="${PUSHER_PORT}" | ||||
| VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" | VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" | ||||
| VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" | VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" | ||||
| SAIL_XDEBUG_MODE=debug,develop | |||||
| SMS_PROVIDER=log | |||||
| SMS_FOURS_MESSAGE_USER=null | |||||
| SMS_FOURS_MESSAGE_PASSWORD=null | |||||
| @@ -0,0 +1,64 @@ | |||||
| APP_NAME=Laravel | |||||
| APP_ENV=local | |||||
| APP_KEY=base64:7/KotwfYt4yVnc1Euu18lGSzo10TMPvW3JMv7LWdo8Y= | |||||
| APP_DEBUG=true | |||||
| APP_URL=http://localhost | |||||
| LOG_CHANNEL=web | |||||
| LOG_DEPRECATIONS_CHANNEL=null | |||||
| LOG_LEVEL=debug | |||||
| DB_CONNECTION=pgsql | |||||
| DB_HOST=pgsql | |||||
| DB_PORT=5432 | |||||
| DB_DATABASE=testing | |||||
| DB_USERNAME=sail | |||||
| DB_PASSWORD=password | |||||
| BROADCAST_DRIVER=log | |||||
| CACHE_DRIVER=file | |||||
| FILESYSTEM_DISK=local | |||||
| QUEUE_CONNECTION=sync | |||||
| SESSION_DRIVER=file | |||||
| SESSION_LIFETIME=120 | |||||
| MEMCACHED_HOST=127.0.0.1 | |||||
| REDIS_HOST=127.0.0.1 | |||||
| REDIS_PASSWORD=null | |||||
| REDIS_PORT=6379 | |||||
| MAIL_MAILER=smtp | |||||
| MAIL_HOST=mailpit | |||||
| MAIL_PORT=1025 | |||||
| MAIL_USERNAME=null | |||||
| MAIL_PASSWORD=null | |||||
| MAIL_ENCRYPTION=null | |||||
| MAIL_FROM_ADDRESS="hello@example.com" | |||||
| MAIL_FROM_NAME="${APP_NAME}" | |||||
| AWS_ACCESS_KEY_ID= | |||||
| AWS_SECRET_ACCESS_KEY= | |||||
| AWS_DEFAULT_REGION=us-east-1 | |||||
| AWS_BUCKET= | |||||
| AWS_USE_PATH_STYLE_ENDPOINT=false | |||||
| PUSHER_APP_ID= | |||||
| PUSHER_APP_KEY= | |||||
| PUSHER_APP_SECRET= | |||||
| PUSHER_HOST= | |||||
| PUSHER_PORT=443 | |||||
| PUSHER_SCHEME=https | |||||
| PUSHER_APP_CLUSTER=mt1 | |||||
| VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" | |||||
| VITE_PUSHER_HOST="${PUSHER_HOST}" | |||||
| VITE_PUSHER_PORT="${PUSHER_PORT}" | |||||
| VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" | |||||
| VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" | |||||
| SAIL_XDEBUG_MODE=debug,develop | |||||
| SMS_PROVIDER=log | |||||
| SMS_FOURS_MESSAGE_USER=T8VWXuqlV2Z6 | |||||
| SMS_FOURS_MESSAGE_PASSWORD=0Vjnak9FFPTH | |||||
| @@ -0,0 +1,40 @@ | |||||
| <?php | |||||
| namespace App\Codes\FourSMessage; | |||||
| enum APIErrorCode: string | |||||
| { | |||||
| case CODE_1001 = '1001'; // 認証失敗。 | |||||
| case CODE_1002 = '1002'; // 認証されたユーザーにはこの操作を行う権限が無い。 | |||||
| case CODE_2002 = '2002'; // 送信実行予定時刻範囲エラー。(現在〜31 日後の範囲外) | |||||
| case CODE_2003 = '2003'; // 日付範囲が 1 ヶ月を超えている。 | |||||
| case CODE_2004 = '2004'; // 指定された SMS 送信要求はキャンセルできない。(送信済み) | |||||
| case CODE_3002 = '3002'; // キャリアコードが指定されていない。 | |||||
| case CODE_3003 = '3003'; // キャリアコードの値が不正。 | |||||
| case CODE_3004 = '3004'; // 送信先電話番号が指定されていない。 | |||||
| case CODE_3005 = '3005'; // 送信先電話番号の形式が不正。 | |||||
| case CODE_3006 = '3006'; // メッセージが指定されていない。 | |||||
| case CODE_3007 = '3007'; // メッセージのデコードエラー。 | |||||
| case CODE_3011 = '3011'; // メッセージに「¦」文字が含まれている。 | |||||
| case CODE_3012 = '3012'; // 送信実行予定時刻の形式が不正。 | |||||
| case CODE_3013 = '3013'; // 範囲指定の日付時刻が指定されていない。(開始時刻) | |||||
| case CODE_3014 = '3014'; // 範囲指定の日付時刻が指定されていない。(終了時刻) | |||||
| case CODE_3015 = '3015'; // 範囲指定の日付形式が不正。(開始時刻) | |||||
| case CODE_3016 = '3016'; // 範囲指定の日付形式が不正。(終了時刻) | |||||
| case CODE_3017 = '3017'; // 日付範囲が不正。 | |||||
| case CODE_3018 = '3018'; // SMS 送信要求ID が指定されていない。 | |||||
| case CODE_3019 = '3019'; // 指定された SMS 送信要求ID が不正。 | |||||
| case CODE_3037 = '3037'; // パスワードが指定されていない。 | |||||
| case CODE_3038 = '3038'; // 指定されたパスワードが不正。(base64 エンコード) | |||||
| case CODE_3039 = '3039'; // 指定されたパスワードが不正。(使用文字) | |||||
| case CODE_3040 = '3040'; // 指定されたパスワードが不正。(セキュリティー要件) | |||||
| case CODE_3055 = '3055'; // 説明文字列を base64 でデコードできない。 | |||||
| case CODE_3067 = '3067'; // 送信オプションの形式が不正 | |||||
| case CODE_3068 = '3068'; // コールバックフラグの形式が不正 | |||||
| case CODE_3069 = '3069'; // コールバック URL が指定されていない | |||||
| case CODE_3070 = '3070'; // コールバック URL の形式が不正 | |||||
| case CODE_3073 = '3073'; // 送信除外時間extime_from の内容が正しくない | |||||
| case CODE_3074 = '3074'; // 送信除外時間extime_to の内容が正しくない | |||||
| case CODE_9001 = '9001'; // 各種エラー | |||||
| case CODE_1000 = '1000'; //1 送信要求時の各種エラー (エラー内容はレスポンス参照) | |||||
| } | |||||
| @@ -0,0 +1,14 @@ | |||||
| <?php | |||||
| namespace App\Codes\FourSMessage; | |||||
| /** | |||||
| * 受付状態 | |||||
| */ | |||||
| enum RequestStatus: string | |||||
| { | |||||
| case NONE = ''; | |||||
| case DONE = '00'; // 受付済 | |||||
| case CANCELED = '00'; // 受付取消 | |||||
| case FAILED = '00'; // 受付失敗 | |||||
| } | |||||
| @@ -0,0 +1,31 @@ | |||||
| <?php | |||||
| namespace App\Codes\FourSMessage; | |||||
| /** | |||||
| * 送達状態 | |||||
| */ | |||||
| enum ResultStatus: string | |||||
| { | |||||
| case NONE = ''; | |||||
| case SUCCESS_00 = '00'; // 正常 | |||||
| case OUT_OF_SERVIFCE_21 = '21'; // 圏外等 | |||||
| case NETWORK_ERROR_22 = '22'; // キャリア側NW 障害 | |||||
| case MOBILE_ERROR_23 = '23'; // 移動機起因エラー(SMS 拒否設定等) | |||||
| case OUT_OF_SERVIFCE_31 = '31'; // 圏外・電源オフ | |||||
| case MOBILE_ERROR_32 = '32'; // 移動機起因エラー | |||||
| case OTHER_ERROR_33 = '33'; // その他エラー | |||||
| case CARRIER_ERROR_33 = '33'; // キャリア側エラー | |||||
| case NOT_CARRIERS_USER_34 = '34'; // 自社キャリアのユーザではない | |||||
| case DONE_40 = '40'; // 送達済 | |||||
| case DELIVERD = 'DELIVERD'; // 正常 | |||||
| case FAILED = 'FAILED'; // 送信エラー | |||||
| case EXPIRED = 'EXPIRED'; // 圏外等 | |||||
| case DELETED = 'DELETED'; // 圏外等 | |||||
| case UNDELIV = 'UNDELIV'; // キャリア側NW 障害 | |||||
| case REJECTD = 'REJECTD'; // 移動機起因エラー(SMS 拒否設定等) | |||||
| case UNKNOWN = 'UNKNOWN'; // 想定外のエラー | |||||
| } | |||||
| @@ -0,0 +1,13 @@ | |||||
| <?php | |||||
| namespace App\Codes\FourSMessage; | |||||
| /** | |||||
| * 送信状態 | |||||
| */ | |||||
| enum SendingStatus: string | |||||
| { | |||||
| case NONE = ''; | |||||
| case SENDING = '10'; // 送信中 | |||||
| case DONE = '20'; // 送信済 | |||||
| } | |||||
| @@ -0,0 +1,11 @@ | |||||
| <?php | |||||
| namespace App\Codes; | |||||
| enum HTTPResultCode: int | |||||
| { | |||||
| case SECCESS = 0; | |||||
| case FAILED = 1; | |||||
| case UNAUTHORIZED = 2; | |||||
| case EXCLUSIVE_ERROR = 3; | |||||
| } | |||||
| @@ -0,0 +1,9 @@ | |||||
| <?php | |||||
| namespace App\Codes; | |||||
| enum QueueName: string | |||||
| { | |||||
| case EMAIL = 'email'; | |||||
| case SMS = 'sms'; | |||||
| } | |||||
| @@ -0,0 +1,27 @@ | |||||
| <?php | |||||
| namespace App\Codes; | |||||
| /** | |||||
| * 領収証発行依頼ステータス | |||||
| */ | |||||
| enum ReceiptIssuingOrderStatus: int | |||||
| { | |||||
| case NONE = 0; | |||||
| case CREATED = 100; // 新規作成 | |||||
| case SMS_SENDING = 200; // SMS送信中 | |||||
| case SMS_RECEIVED = 300; // SMS送信完了 | |||||
| case SMS_OPENED = 400; // SMS開封 | |||||
| // 郵送関連 | |||||
| case MAIL_REQUEST = 500; // 郵送依頼中 | |||||
| case PREPARING_FOR_MAIL = 510; // 郵送準備中 | |||||
| case MAIL_DONE = 520; // 郵送完了 | |||||
| // Email送信関連 | |||||
| case EMAIL_SENDING = 600; // Email送信中 | |||||
| case EMAIL_DONE = 610; // Email送信完了 | |||||
| // PDFダウンロード | |||||
| case DOWNLOAD_DONE = 700; // ダウンロード完了 | |||||
| } | |||||
| @@ -0,0 +1,9 @@ | |||||
| <?php | |||||
| namespace App\Codes; | |||||
| enum SMSProviderName: string | |||||
| { | |||||
| case FOUR_S_MESSAGE = 'FourSMessage'; | |||||
| case LOG = 'log'; | |||||
| } | |||||
| @@ -0,0 +1,8 @@ | |||||
| <?php | |||||
| namespace App\Codes; | |||||
| enum SMSSendPurpose: string | |||||
| { | |||||
| case SEND_RECEIPT_ISSUING_ORDER_FORM = 'SEND_RECEIPT_ISSUING_ORDER_FORM'; | |||||
| } | |||||
| @@ -0,0 +1,14 @@ | |||||
| <?php | |||||
| namespace App\Codes; | |||||
| /** | |||||
| * ユーザー権限 | |||||
| */ | |||||
| enum UserRole: int | |||||
| { | |||||
| case NONE = 0; | |||||
| case NORMAL_ADMIN = 100; | |||||
| case CONTRACT_ADMIN = 200; | |||||
| case SUPER_ADMIN = 900; | |||||
| } | |||||
| @@ -0,0 +1,105 @@ | |||||
| <?php | |||||
| namespace App\Console\Commands; | |||||
| use Exception; | |||||
| use Illuminate\Console\Command; | |||||
| use Illuminate\Support\Facades\Log; | |||||
| use Illuminate\Support\Str; | |||||
| abstract class BaseCommand extends Command | |||||
| { | |||||
| const RESULTCODE_SUCCESS = 0; | |||||
| const RESULTCODE_WARN = 1; | |||||
| const RESULTCODE_FAILED = 2; | |||||
| /** | |||||
| * Create a new command instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct() | |||||
| { | |||||
| parent::__construct(); | |||||
| } | |||||
| abstract protected function service(): int; | |||||
| protected bool $outputInfoForBase = true; | |||||
| /** | |||||
| * Execute the console command. | |||||
| * | |||||
| * @return int | |||||
| */ | |||||
| public function handle() | |||||
| { | |||||
| $ret = 0; | |||||
| $this->boot(); | |||||
| try { | |||||
| $ret = $this->service(); | |||||
| } catch (Exception $e) { | |||||
| $message = sprintf("例外発生:%s:%s:%d", $e->getMessage(), $e->getFile(), $e->getLine()); | |||||
| $this->outputError($message, $e->getTrace()); | |||||
| $ret = self::RESULTCODE_FAILED; | |||||
| } | |||||
| if ($ret === self::RESULTCODE_SUCCESS) { | |||||
| $this->outputInfoForBase("成功しました。"); | |||||
| } else if ($ret === self::RESULTCODE_WARN) { | |||||
| $this->outputWarn("一部失敗があります。"); | |||||
| } else if ($ret === self::RESULTCODE_FAILED) { | |||||
| $this->outputError("失敗しました"); | |||||
| } else { | |||||
| $this->outputError(sprintf("未定義のエラーコード:%d", $ret)); | |||||
| } | |||||
| return $ret; | |||||
| } | |||||
| private function boot() | |||||
| { | |||||
| Log::setDefaultDriver("batch"); | |||||
| Log::withContext([ | |||||
| '__scheduleId' => strval(Str::uuid()), | |||||
| ...$this->arguments(), | |||||
| ]); | |||||
| $this->outputInfoForBase(sprintf("バッチ起動 %s", $this->getCommandName())); | |||||
| } | |||||
| protected function outputInfo(string $message, array $context = []) | |||||
| { | |||||
| Log::info($message, $this->getContext($context)); | |||||
| $this->info($message); | |||||
| } | |||||
| private function outputInfoForBase(string $message, array $context = []) | |||||
| { | |||||
| if ($this->outputInfoForBase) { | |||||
| Log::info($message, $this->getContext($context)); | |||||
| } | |||||
| $this->info($message); | |||||
| } | |||||
| protected function outputWarn(string $message, array $context = []) | |||||
| { | |||||
| Log::warning($message, $this->getContext($context)); | |||||
| $this->warn($message); | |||||
| } | |||||
| protected function outputError(string $message, array $context = []) | |||||
| { | |||||
| Log::error($message, $this->getContext($context)); | |||||
| $this->error($message); | |||||
| } | |||||
| private function getContext(array $context = []) | |||||
| { | |||||
| return array_merge($context, ["context" => $this->arguments()]); | |||||
| } | |||||
| protected function getCommandName(): string | |||||
| { | |||||
| return ""; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,60 @@ | |||||
| <?php | |||||
| namespace App\Console\Commands; | |||||
| class HeartBeat extends BaseCommand | |||||
| { | |||||
| const COMMAND = "heartbeat {--maintenance}"; | |||||
| protected bool $outputInfoForBase = false; | |||||
| /** | |||||
| * The name and signature of the console command. | |||||
| * | |||||
| * @var string | |||||
| */ | |||||
| protected $signature = self::COMMAND; | |||||
| /** | |||||
| * The console command description. | |||||
| * | |||||
| * @var string | |||||
| */ | |||||
| protected $description = 'ハートビート'; | |||||
| static public function getCommand() | |||||
| { | |||||
| return self::COMMAND; | |||||
| } | |||||
| /** | |||||
| * Create a new command instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct() | |||||
| { | |||||
| parent::__construct(); | |||||
| } | |||||
| /** | |||||
| * Execute the console command. | |||||
| * | |||||
| * @return int | |||||
| */ | |||||
| public function service(): int | |||||
| { | |||||
| if ($this->option('maintenance')) { | |||||
| $isMaintenanceMode = app()->isDownForMaintenance(); | |||||
| if ($isMaintenanceMode) { | |||||
| $this->outputWarn("down for maintenance"); | |||||
| } | |||||
| } else { | |||||
| $this->outputInfo("heart beat"); | |||||
| } | |||||
| return self::RESULTCODE_SUCCESS; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,97 @@ | |||||
| <?php | |||||
| namespace App\Console\Commands; | |||||
| use App\Events\SMS\ConfirmEvent; | |||||
| use App\Exceptions\AppCommonException; | |||||
| use App\Logic\SMS\SMSManager; | |||||
| use App\Models\SMSSendOrder; | |||||
| class TestMail extends BaseCommand | |||||
| { | |||||
| const COMMAND = "sms:poll"; | |||||
| /** | |||||
| * The name and signature of the console command. | |||||
| * | |||||
| * @var string | |||||
| */ | |||||
| protected $signature = self::COMMAND; | |||||
| /** | |||||
| * The console command description. | |||||
| * | |||||
| * @var string | |||||
| */ | |||||
| protected $description = 'SMS配信状況を取得/反映する'; | |||||
| static public function getCommand() | |||||
| { | |||||
| return self::COMMAND; | |||||
| } | |||||
| /** | |||||
| * Create a new command instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct(private SMSManager $manager) | |||||
| { | |||||
| parent::__construct(); | |||||
| } | |||||
| /** | |||||
| * Execute the console command. | |||||
| * | |||||
| * @return int | |||||
| */ | |||||
| public function service(): int | |||||
| { | |||||
| $targets = $this->getTargets(); | |||||
| $this->outputInfo(sprintf("対象:%d件", $targets->count())); | |||||
| if ($targets->isEmpty()) { | |||||
| return self::RESULTCODE_SUCCESS; | |||||
| } else { | |||||
| } | |||||
| foreach ($targets as $order) { | |||||
| $this->handleOrder($order); | |||||
| } | |||||
| return self::RESULTCODE_SUCCESS; | |||||
| } | |||||
| public function getTargets() | |||||
| { | |||||
| return SMSSendOrder::whereDone(false) | |||||
| ->get(); | |||||
| } | |||||
| public function handleOrder(SMSSendOrder $order) | |||||
| { | |||||
| $ret = $this->manager->setOrder($order) | |||||
| ->poll(); | |||||
| if ($ret) { | |||||
| $order->save(); | |||||
| $this->outputInfo(sprintf( | |||||
| "ID:%s 電話番号:%s %s", | |||||
| $order->id, | |||||
| $order->phone_number, | |||||
| $order->done ? "完了" : "未" | |||||
| )); | |||||
| // イベント発行 | |||||
| if ($order->done) { | |||||
| ConfirmEvent::dispatch($order); | |||||
| } | |||||
| } else { | |||||
| $this->outputError(printf("失敗対象:%s", $order->toJson())); | |||||
| throw new AppCommonException("POLL 失敗"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,210 @@ | |||||
| <?php | |||||
| namespace App\Console\Commands; | |||||
| use App\Codes\UserRole; | |||||
| use App\Http\Controllers\Web\WebController; | |||||
| use Exception; | |||||
| use Illuminate\Routing\Route as RoutingRoute; | |||||
| use Illuminate\Support\Arr; | |||||
| use Illuminate\Support\Facades\Route; | |||||
| use Illuminate\Support\Str; | |||||
| use LogicException; | |||||
| class RouteListCsv extends BaseCommand | |||||
| { | |||||
| /** | |||||
| * コントローラー説明の個別定義 | |||||
| * 主にミドルウェア側のコントローラーに適用 | |||||
| */ | |||||
| const CONTROLLER_DESCRIPTION = [ | |||||
| \Laravel\Sanctum\Http\Controllers\CsrfCookieController::class => "csrf対策用", | |||||
| ]; | |||||
| /** | |||||
| * The name and signature of the console command. | |||||
| * | |||||
| * @var string | |||||
| */ | |||||
| protected $signature = 'route:csv {--tsv}'; | |||||
| /** | |||||
| * The console command description. | |||||
| * | |||||
| * @var string | |||||
| */ | |||||
| protected $description = 'ルート一覧をcsv標準出力する'; | |||||
| private Context $context; | |||||
| private $fp = null; | |||||
| private string $separator; | |||||
| private int $rowIndex = 0; | |||||
| /** | |||||
| * Create a new command instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct() | |||||
| { | |||||
| $this->outputInfoForBase = false; | |||||
| parent::__construct(); | |||||
| } | |||||
| /** | |||||
| * Execute the console command. | |||||
| * | |||||
| * @return int | |||||
| */ | |||||
| protected function service(): int | |||||
| { | |||||
| $routes = Route::getRoutes(); | |||||
| $routes->getRoutes(); | |||||
| $this->separator = $this->getSeparator(); | |||||
| try { | |||||
| $this->fp = fopen(base_path("routes.csv"), "w"); | |||||
| $this->putHeader(); | |||||
| foreach ($routes->getRoutes() as $r) { | |||||
| if (Str::startsWith($r->uri(), ["_", "clockwork"])) { | |||||
| continue; | |||||
| } | |||||
| $this->put($r); | |||||
| } | |||||
| } catch (Exception $e) { | |||||
| $this->outputError($e->getMessage()); | |||||
| if ($this->fp !== null) { | |||||
| fclose($this->fp); | |||||
| $this->fp = null; | |||||
| } | |||||
| return self::RESULTCODE_FAILED; | |||||
| } | |||||
| fclose($this->fp); | |||||
| return self::RESULTCODE_SUCCESS; | |||||
| } | |||||
| private function putHeader() | |||||
| { | |||||
| fputcsv($this->fp, [ | |||||
| "#", | |||||
| "NAME", | |||||
| "説明", | |||||
| "メソッド", | |||||
| "URI", | |||||
| "S", | |||||
| "C", | |||||
| "A", | |||||
| "L", | |||||
| "N", | |||||
| "コントローラー", | |||||
| ], $this->separator); | |||||
| } | |||||
| private function put(RoutingRoute $route) | |||||
| { | |||||
| if ($this->fp === null) { | |||||
| throw new LogicException("FP null"); | |||||
| } | |||||
| $controller = $route->getController(); | |||||
| fputcsv($this->fp, [ | |||||
| $this->rowIndex, | |||||
| $this->getControllerName($controller), | |||||
| $this->getControllerDescription($controller), | |||||
| $this->getMethods($route), | |||||
| $route->uri(), | |||||
| $this->getRoleAuth($controller, UserRole::NORMAL_ADMIN), | |||||
| $this->getRoleAuth($controller, UserRole::CONTRACT_ADMIN), | |||||
| $this->getRoleAuth($controller, UserRole::SUPER_ADMIN), | |||||
| $controller::class, | |||||
| ], $this->separator); | |||||
| $this->rowIndex++; | |||||
| } | |||||
| private function getMethods(RoutingRoute $route) | |||||
| { | |||||
| return implode('|', $route->methods()); | |||||
| } | |||||
| private function getRoleAuth($controller, UserRole $role): string | |||||
| { | |||||
| $ret = true; | |||||
| if ($controller instanceof WebController) { | |||||
| $ret = $controller->canAccess($role); | |||||
| } | |||||
| return $ret ? "〇" : "-"; | |||||
| } | |||||
| private function getControllerName($controller): string | |||||
| { | |||||
| if ($controller instanceof WebController) { | |||||
| return $controller->name(); | |||||
| } else if ( | |||||
| method_exists($controller, "name") && | |||||
| is_callable([$controller, "name"]) | |||||
| ) { | |||||
| $ret = $controller->name(); | |||||
| return is_string($ret) ? $ret : "-"; | |||||
| } else { | |||||
| // コントローラ名から名前空間、メソッド名、等を除去 | |||||
| return Str::of($controller::class) | |||||
| ->afterLast("\\") | |||||
| ->beforeLast("@") | |||||
| ->replace("Controller", ""); | |||||
| } | |||||
| } | |||||
| private function getControllerDescription($controller): string | |||||
| { | |||||
| if ($controller instanceof WebController) { | |||||
| return $controller->description(); | |||||
| } else if ( | |||||
| method_exists($controller, "description") && | |||||
| is_callable([$controller, "description"]) | |||||
| ) { | |||||
| $ret = $controller->description(); | |||||
| return is_string($ret) ? $ret : "-"; | |||||
| } else if (Arr::has(self::CONTROLLER_DESCRIPTION, $controller::class)) { | |||||
| return self::CONTROLLER_DESCRIPTION[$controller::class]; | |||||
| } else { | |||||
| return "-"; | |||||
| } | |||||
| } | |||||
| private function outputSjisFile() | |||||
| { | |||||
| $contents = file_get_contents(base_path("routes.csv")); | |||||
| file_put_contents( | |||||
| base_path("routes_sjis.csv"), | |||||
| mb_convert_encoding( | |||||
| $contents, | |||||
| "SJIS", | |||||
| "UTF8" | |||||
| ) | |||||
| ); | |||||
| } | |||||
| private function getSeparator(): string | |||||
| { | |||||
| return $this->option("tsv") ? "\t" : ","; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,61 @@ | |||||
| <?php | |||||
| namespace App\Console\Commands; | |||||
| use App\Events\Mail\ConfirmEvent; | |||||
| use App\Logic\EmailManager; | |||||
| use App\Mail\Test; | |||||
| class TestMail extends BaseCommand | |||||
| { | |||||
| const COMMAND = "test:mail {email}"; | |||||
| /** | |||||
| * The name and signature of the console command. | |||||
| * | |||||
| * @var string | |||||
| */ | |||||
| protected $signature = self::COMMAND; | |||||
| /** | |||||
| * The console command description. | |||||
| * | |||||
| * @var string | |||||
| */ | |||||
| protected $description = 'テストメールを送信する(キュー登録)'; | |||||
| static public function getCommand() | |||||
| { | |||||
| return self::COMMAND; | |||||
| } | |||||
| /** | |||||
| * Create a new command instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct() | |||||
| { | |||||
| parent::__construct(); | |||||
| } | |||||
| /** | |||||
| * Execute the console command. | |||||
| * | |||||
| * @return int | |||||
| */ | |||||
| public function service(): int | |||||
| { | |||||
| $email = $this->argument('email'); | |||||
| $mailer = new Test(); | |||||
| $mailer->setEmail($email); | |||||
| $manager = new EmailManager($mailer); | |||||
| $manager->confirm(); | |||||
| return self::RESULTCODE_SUCCESS; | |||||
| } | |||||
| } | |||||
| @@ -12,7 +12,9 @@ class Kernel extends ConsoleKernel | |||||
| */ | */ | ||||
| protected function schedule(Schedule $schedule): void | protected function schedule(Schedule $schedule): void | ||||
| { | { | ||||
| // $schedule->command('inspire')->hourly(); | |||||
| Schedules\HeartBeat::register($schedule); | |||||
| Schedules\MailSend::register($schedule); | |||||
| Schedules\SMSSend::register($schedule); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -20,7 +22,7 @@ class Kernel extends ConsoleKernel | |||||
| */ | */ | ||||
| protected function commands(): void | protected function commands(): void | ||||
| { | { | ||||
| $this->load(__DIR__.'/Commands'); | |||||
| $this->load(__DIR__ . '/Commands'); | |||||
| require base_path('routes/console.php'); | require base_path('routes/console.php'); | ||||
| } | } | ||||
| @@ -0,0 +1,10 @@ | |||||
| <?php | |||||
| namespace App\Console\Schedules; | |||||
| use Illuminate\Console\Scheduling\Schedule; | |||||
| abstract class BaseSchedule | |||||
| { | |||||
| abstract static public function register(Schedule $schedule); | |||||
| } | |||||
| @@ -0,0 +1,22 @@ | |||||
| <?php | |||||
| namespace App\Console\Schedules; | |||||
| use App\Console\Commands\HeartBeat as CommandsHeartBeat; | |||||
| use Illuminate\Console\Scheduling\Schedule; | |||||
| class HeartBeat extends BaseSchedule | |||||
| { | |||||
| static public function register(Schedule $schedule) | |||||
| { | |||||
| $schedule->command(CommandsHeartBeat::class) | |||||
| ->everyFiveMinutes() | |||||
| ->evenInMaintenanceMode() | |||||
| ->description("ハートビート"); | |||||
| $schedule->command(CommandsHeartBeat::class, ['--maintenance']) | |||||
| ->everyMinute() | |||||
| ->evenInMaintenanceMode() | |||||
| ->description("メンテナンスモード確認"); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,19 @@ | |||||
| <?php | |||||
| namespace App\Console\Schedules; | |||||
| use App\Codes\QueueName; | |||||
| use Illuminate\Console\Scheduling\Schedule; | |||||
| class MailSend extends BaseSchedule | |||||
| { | |||||
| static public function register(Schedule $schedule) | |||||
| { | |||||
| $schedule->command( | |||||
| sprintf('queue:work --queue=%s --max-time=55 ', QueueName::EMAIL->value) | |||||
| ) | |||||
| ->everyMinute() | |||||
| ->description("メールキュー処理"); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,19 @@ | |||||
| <?php | |||||
| namespace App\Console\Schedules; | |||||
| use App\Codes\QueueName; | |||||
| use Illuminate\Console\Scheduling\Schedule; | |||||
| class SMSSend extends BaseSchedule | |||||
| { | |||||
| static public function register(Schedule $schedule) | |||||
| { | |||||
| $schedule->command( | |||||
| sprintf('queue:work --queue=%s --max-time=55 ', QueueName::SMS->value) | |||||
| ) | |||||
| ->everyMinute() | |||||
| ->description("メールキュー処理"); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,31 @@ | |||||
| <?php | |||||
| namespace App\Events\Mail; | |||||
| use App\Mail\BaseMailer; | |||||
| use App\Models\Email; | |||||
| use Illuminate\Broadcasting\InteractsWithSockets; | |||||
| use Illuminate\Foundation\Events\Dispatchable; | |||||
| use Illuminate\Queue\SerializesModels; | |||||
| class ConfirmEvent | |||||
| { | |||||
| use Dispatchable, InteractsWithSockets, SerializesModels; | |||||
| public Email $email; | |||||
| /** | |||||
| * Create a new event instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct(Email|BaseMailer $email) | |||||
| { | |||||
| if ($email instanceof Email) { | |||||
| $this->email = $email; | |||||
| } else { | |||||
| $this->email = $email->makeModel(); | |||||
| $this->email->save(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,8 @@ | |||||
| <?php | |||||
| namespace App\Events\Model; | |||||
| class CreatedEvent extends ModelChangeEvent | |||||
| { | |||||
| } | |||||
| @@ -0,0 +1,8 @@ | |||||
| <?php | |||||
| namespace App\Events\Model; | |||||
| class DeletedEvent extends ModelChangeEvent | |||||
| { | |||||
| } | |||||
| @@ -0,0 +1,8 @@ | |||||
| <?php | |||||
| namespace App\Events\Model; | |||||
| class DeletingEvent extends ModelChangeEvent | |||||
| { | |||||
| } | |||||
| @@ -0,0 +1,36 @@ | |||||
| <?php | |||||
| namespace App\Events\Model; | |||||
| use App\Models\Feature\IModelFeature; | |||||
| use Illuminate\Broadcasting\InteractsWithSockets; | |||||
| use Illuminate\Broadcasting\PrivateChannel; | |||||
| use Illuminate\Foundation\Events\Dispatchable; | |||||
| use Illuminate\Queue\SerializesModels; | |||||
| abstract class ModelChangeEvent | |||||
| { | |||||
| use Dispatchable, InteractsWithSockets, SerializesModels; | |||||
| public IModelFeature $model; | |||||
| /** | |||||
| * Create a new event instance. | |||||
| */ | |||||
| public function __construct(IModelFeature $model) | |||||
| { | |||||
| $this->model = $model; | |||||
| } | |||||
| /** | |||||
| * Get the channels the event should broadcast on. | |||||
| * | |||||
| * @return array<int, \Illuminate\Broadcasting\Channel> | |||||
| */ | |||||
| public function broadcastOn(): array | |||||
| { | |||||
| return [ | |||||
| new PrivateChannel('channel-name'), | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,8 @@ | |||||
| <?php | |||||
| namespace App\Events\Model; | |||||
| class UpdatingEvent extends ModelChangeEvent | |||||
| { | |||||
| } | |||||
| @@ -0,0 +1,25 @@ | |||||
| <?php | |||||
| namespace App\Events\SMS; | |||||
| use App\Models\SMSSendOrder; | |||||
| use Illuminate\Broadcasting\InteractsWithSockets; | |||||
| use Illuminate\Foundation\Events\Dispatchable; | |||||
| use Illuminate\Queue\SerializesModels; | |||||
| /** | |||||
| * 送信状態の確定イベント | |||||
| */ | |||||
| class ConfirmEvent | |||||
| { | |||||
| use Dispatchable, InteractsWithSockets, SerializesModels; | |||||
| /** | |||||
| * Create a new event instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct(public SMSSendOrder $order) | |||||
| { | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,9 @@ | |||||
| <?php | |||||
| namespace App\Exceptions; | |||||
| use Exception; | |||||
| class AppCommonException extends Exception | |||||
| { | |||||
| } | |||||
| @@ -0,0 +1,9 @@ | |||||
| <?php | |||||
| namespace App\Exceptions; | |||||
| use Exception; | |||||
| class GeneralErrorMessageException extends Exception | |||||
| { | |||||
| } | |||||
| @@ -0,0 +1,13 @@ | |||||
| <?php | |||||
| namespace App\Features; | |||||
| use App\Models\Ex\LoginUser as ExLoginUser; | |||||
| trait LoginUser | |||||
| { | |||||
| protected function loginUser(): ExLoginUser | |||||
| { | |||||
| return app(ExLoginUser::class); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,61 @@ | |||||
| <?php | |||||
| namespace App\Http\Controllers\Web\Login; | |||||
| use App\Codes\UserRole; | |||||
| use App\Http\Controllers\Web\WebController; | |||||
| use App\Models\User; | |||||
| use App\Repositories\MeRepository; | |||||
| use Illuminate\Foundation\Auth\AuthenticatesUsers; | |||||
| use Illuminate\Http\JsonResponse; | |||||
| use Illuminate\Http\Request; | |||||
| use Illuminate\Support\Facades\Auth; | |||||
| class LoginController extends WebController | |||||
| { | |||||
| public function name(): string | |||||
| { | |||||
| return "ログイン"; | |||||
| } | |||||
| public function description(): string | |||||
| { | |||||
| return "ログインを行う"; | |||||
| } | |||||
| use AuthenticatesUsers; | |||||
| public function __construct(LoginParam $param) | |||||
| { | |||||
| $this->param = $param; | |||||
| } | |||||
| public function param(): LoginParam | |||||
| { | |||||
| return $this->param; | |||||
| } | |||||
| protected function run(Request $request): JsonResponse | |||||
| { | |||||
| // 取得したユーザ情報を登録しログインを行う | |||||
| $param = $this->param(); | |||||
| $user = User::whereEmail($param->email)->first(); | |||||
| if ($user === null) { | |||||
| return $this->failedResponse(); | |||||
| } | |||||
| if (Auth::attempt([ | |||||
| $this->username() => $param->email, | |||||
| 'password' => $param->password, | |||||
| ])) { | |||||
| $user = Auth::user(); | |||||
| return $this->successResponse(); | |||||
| } else { | |||||
| return $this->failedResponse([], '認証失敗'); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,20 @@ | |||||
| <?php | |||||
| namespace App\Http\Controllers\Web\Login; | |||||
| use App\Http\Controllers\Web\BaseParam; | |||||
| /** | |||||
| * @property string $email | |||||
| * @property string $password | |||||
| */ | |||||
| class LoginParam extends BaseParam | |||||
| { | |||||
| public function rules(): array | |||||
| { | |||||
| return [ | |||||
| 'email' => $this->str(), | |||||
| 'password' => $this->str(), | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -159,6 +159,15 @@ abstract class BaseParam implements IParam | |||||
| } | } | ||||
| protected function str(array|bool $condition = [], $nullable = false): array | protected function str(array|bool $condition = [], $nullable = false): array | ||||
| { | |||||
| $conditionEx = array_merge(is_array($condition) ? $condition : [], ['max:250']); | |||||
| return array_merge([ | |||||
| $this->isNullable($condition, $nullable) ? self::NULLABLE : self::REQUIRED, | |||||
| self::STR | |||||
| ], $conditionEx); | |||||
| } | |||||
| protected function text(array|bool $condition = [], $nullable = false): array | |||||
| { | { | ||||
| return array_merge([ | return array_merge([ | ||||
| $this->isNullable($condition, $nullable) ? self::NULLABLE : self::REQUIRED, | $this->isNullable($condition, $nullable) ? self::NULLABLE : self::REQUIRED, | ||||
| @@ -0,0 +1,48 @@ | |||||
| <?php | |||||
| namespace App\Http\Controllers\Web\ReceiptIssuingOrder; | |||||
| use App\Codes\UserRole; | |||||
| use App\Http\Controllers\Web\IParam; | |||||
| use App\Http\Controllers\Web\WebController; | |||||
| use App\Logic\ReceiptIssuingOrder\CreateManager; | |||||
| use Illuminate\Http\JsonResponse; | |||||
| use Illuminate\Http\Request; | |||||
| class CreateController extends WebController | |||||
| { | |||||
| public function name(): string | |||||
| { | |||||
| return "領収証発行依頼新規作成"; | |||||
| } | |||||
| public function description(): string | |||||
| { | |||||
| return "領収証発行依頼を新規作成する"; | |||||
| } | |||||
| public function __construct( | |||||
| protected CreateParam $param, | |||||
| private CreateManager $manager | |||||
| ) { | |||||
| $this->middleware('auth:sanctum'); | |||||
| $this->roleAllow(UserRole::NORMAL_ADMIN); | |||||
| } | |||||
| protected function getParam(): IParam | |||||
| { | |||||
| return $this->param; | |||||
| } | |||||
| protected function run(Request $request): JsonResponse | |||||
| { | |||||
| $param = $this->param; | |||||
| $this->manager->init() | |||||
| ->fill($param->toArray()) | |||||
| ->create(); | |||||
| return $this->successResponse(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,43 @@ | |||||
| <?php | |||||
| namespace App\Http\Controllers\Web\ReceiptIssuingOrder; | |||||
| use App\Http\Controllers\Web\BaseParam; | |||||
| use App\Models\ReceiptIssuingOrder; | |||||
| use App\Rules\PhoneNumber; | |||||
| use Carbon\Carbon; | |||||
| /** | |||||
| * @property ?string $handlerId | |||||
| * @property ?string $orderDatetime | |||||
| * @property ?string $sumamryKey1 | |||||
| * @property ?string $sumamryKey2 | |||||
| * @property ?string $smsPhoneNumber | |||||
| * @property ?string $receiptNo | |||||
| * @property ?Carbon $receiptUseDatetime | |||||
| * @property ?string $receiptShopName | |||||
| * @property ?string $receiptIssuer | |||||
| * @property ?string $receiptPurpose | |||||
| * @property string $receiptAmount | |||||
| * @property ?string $memo | |||||
| */ | |||||
| class CreateParam extends BaseParam | |||||
| { | |||||
| public function rules(): array | |||||
| { | |||||
| return [ | |||||
| ReceiptIssuingOrder::COL_NAME_SUMMARY_KEY1 => $this->str(true), | |||||
| ReceiptIssuingOrder::COL_NAME_SUMMARY_KEY2 => $this->str(true), | |||||
| ReceiptIssuingOrder::COL_NAME_SMS_PHONE_NUMBER => $this->str([new PhoneNumber()]), | |||||
| ReceiptIssuingOrder::COL_NAME_RECEIPT_NO => $this->str(true), | |||||
| ReceiptIssuingOrder::COL_NAME_RECEIPT_USE_DATETIME => $this->date(true), | |||||
| ReceiptIssuingOrder::COL_NAME_RECEIPT_SHOP_NAME => $this->str(true), | |||||
| ReceiptIssuingOrder::COL_NAME_RECEIPT_ISSUER => $this->str(true), | |||||
| ReceiptIssuingOrder::COL_NAME_RECEIPT_PURPOSE => $this->str(true), | |||||
| ReceiptIssuingOrder::COL_NAME_RECEIPT_AMOUNT => $this->numeric(['min:0', 'max:999999'], true), | |||||
| ReceiptIssuingOrder::COL_NAME_MEMO => $this->text(true), | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,363 @@ | |||||
| <?php | |||||
| namespace App\Http\Controllers\Web; | |||||
| use App\Codes\HTTPResultCode as ResultCode; | |||||
| use App\Codes\UserRole; | |||||
| use App\Exceptions\AppCommonException; | |||||
| use App\Exceptions\GeneralErrorMessageException; | |||||
| use Exception; | |||||
| use Illuminate\Foundation\Auth\Access\AuthorizesRequests; | |||||
| use Illuminate\Foundation\Bus\DispatchesJobs; | |||||
| use Illuminate\Foundation\Validation\ValidatesRequests; | |||||
| use Illuminate\Http\JsonResponse; | |||||
| use Illuminate\Http\Request; | |||||
| use Illuminate\Http\Response; | |||||
| use Illuminate\Routing\Controller as BaseController; | |||||
| use Illuminate\Support\Arr; | |||||
| use Illuminate\Support\Facades\Auth; | |||||
| use Illuminate\Support\Facades\Log; | |||||
| use Illuminate\Support\Facades\Validator; | |||||
| use Illuminate\Support\Str; | |||||
| use Illuminate\Validation\ValidationException; | |||||
| use LogicException; | |||||
| use Symfony\Component\HttpFoundation\BinaryFileResponse; | |||||
| use Symfony\Component\HttpKernel\Exception\HttpException; | |||||
| abstract class WebController extends BaseController | |||||
| { | |||||
| use AuthorizesRequests, DispatchesJobs, ValidatesRequests; | |||||
| const COL_NAME_CREATED_AT = 'created_at'; | |||||
| const COL_NAME_UPDATED_AT = 'updated_at'; | |||||
| const COL_NAME_RESULT_CODE = 'result'; | |||||
| const COL_NAME_DATA = 'data'; | |||||
| const COL_NAME_MESSAGES = 'messages'; | |||||
| const COL_NAME_GENERAL_MESSAGE = 'general'; | |||||
| const COL_NAME_EMAIL_ID = 'email_id'; | |||||
| const COL_NAME_ERRORS = 'errors'; | |||||
| /** | |||||
| * バリデートした結果を格納 | |||||
| * | |||||
| * @var array | |||||
| */ | |||||
| protected $validated = []; | |||||
| /** | |||||
| * 画面へ返却するメールID | |||||
| * | |||||
| * @var integer|null | |||||
| */ | |||||
| private int|null $emailId = null; | |||||
| /** | |||||
| * 返却するメッセージ | |||||
| * | |||||
| * @var array|null | |||||
| */ | |||||
| private array|null $messages = null; | |||||
| /** | |||||
| * 返却するメッセージ | |||||
| * | |||||
| * @var string|null | |||||
| */ | |||||
| private string|null $generalMessage = null; | |||||
| /** | |||||
| * 返却するデータ | |||||
| * | |||||
| * @var mixed|null | |||||
| */ | |||||
| private $data = null; | |||||
| /** | |||||
| * 返却する結果コード | |||||
| * | |||||
| * @var ResultCode|null | |||||
| */ | |||||
| private ResultCode|null $resultCode = ResultCode::SECCESS; | |||||
| /** | |||||
| * パラメータオブジェクト | |||||
| */ | |||||
| abstract protected function getParam(): IParam; | |||||
| /** | |||||
| * コントローラーの名前 | |||||
| * オーバーライドされることを想定 | |||||
| * 主に、Routeのドキュメント作成用 | |||||
| * | |||||
| * @return string | |||||
| */ | |||||
| public function name(): string | |||||
| { | |||||
| return "---未設定---"; | |||||
| } | |||||
| /** | |||||
| * コントローラーの説明 | |||||
| * オーバーライドされることを想定 | |||||
| * 主に、Routeのドキュメント作成用 | |||||
| * | |||||
| * @return string | |||||
| */ | |||||
| public function description(): string | |||||
| { | |||||
| return "---未設定---"; | |||||
| } | |||||
| /** | |||||
| * オーバーライド必要 | |||||
| * メインロジック | |||||
| * | |||||
| * @param Request $request | |||||
| * @return Response|JsonResponse|string | |||||
| */ | |||||
| protected function run(Request $request): Response|JsonResponse|BinaryFileResponse|string | |||||
| { | |||||
| return $this->successResponse(); | |||||
| } | |||||
| private function getRules() | |||||
| { | |||||
| return $this->getParam()->rules(); | |||||
| } | |||||
| public function entry(Request $request) | |||||
| { | |||||
| $this->setLogContext($request); | |||||
| try { | |||||
| $validator = Validator::make($request->all(), $this->getRules()); | |||||
| $validator->validate(); | |||||
| } catch (ValidationException $e) { | |||||
| logger("validate error", ['errors' => $e->errors(), 'request' => $request->all(), 'path' => $request->path()]); | |||||
| return $this->validateErrorResponse($e); | |||||
| } | |||||
| try { | |||||
| $this->validated = $validator->validated(); | |||||
| $this->getParam()->setData($this->validated); | |||||
| $this->authorize(); | |||||
| return $this->run($request); | |||||
| } catch (GeneralErrorMessageException $e) { | |||||
| return $this->failedResponse([], $e->getMessage()); | |||||
| } catch (AppCommonException $e) { | |||||
| logs()->error(sprintf("Appエラー:%s", $e->getMessage())); | |||||
| return $this->failedResponse(); | |||||
| } catch (LogicException $e) { | |||||
| logs()->error([ | |||||
| sprintf("実装エラー:%s", $e->getMessage()), | |||||
| get_class($e), | |||||
| $e->getFile(), | |||||
| $e->getLine(), | |||||
| $request->all(), | |||||
| ]); | |||||
| logger(array_filter($e->getTrace(), function ($val, $key) { | |||||
| return $key <= 5; | |||||
| }, ARRAY_FILTER_USE_BOTH)); | |||||
| return $this->failedResponse(); | |||||
| } catch (ValidationException $e) { | |||||
| return $this->validateErrorResponse($e); | |||||
| } catch (HttpException $e) { | |||||
| if ($e->getStatusCode() === 401) { | |||||
| return $this->unAuthorizedResponse(); | |||||
| } | |||||
| throw e; | |||||
| } catch (Exception $e) { | |||||
| logs()->error([ | |||||
| sprintf("例外エラー:%s", $e->getMessage()), | |||||
| get_class($e), | |||||
| $e->getFile(), | |||||
| $e->getLine(), | |||||
| $request->all(), | |||||
| ]); | |||||
| logger(array_filter($e->getTrace(), function ($val, $key) { | |||||
| return $key <= 5; | |||||
| }, ARRAY_FILTER_USE_BOTH)); | |||||
| return $this->failedResponse(); | |||||
| } | |||||
| } | |||||
| protected function successResponse(array|object $data = [], array|string $messages = []) | |||||
| { | |||||
| return $this->setData($data) | |||||
| ->setMessages($messages) | |||||
| ->setResultCode(ResultCode::SECCESS) | |||||
| ->makeResponse(); | |||||
| } | |||||
| protected function failedResponse(array|object $data = [], array|string $messages = []) | |||||
| { | |||||
| return $this->setData($data) | |||||
| ->setMessages($messages) | |||||
| ->setResultCode(ResultCode::FAILED) | |||||
| ->makeResponse(); | |||||
| } | |||||
| protected function unAuthorizedResponse(array|object $data = [], array|string $messages = []) | |||||
| { | |||||
| return $this->setData($data) | |||||
| ->setMessages($messages) | |||||
| ->setResultCode(ResultCode::UNAUTHORIZED) | |||||
| ->makeResponse(); | |||||
| } | |||||
| protected function exclusiveErrorResponse(array|object $data = [], array|string $messages = []) | |||||
| { | |||||
| return $this->setData($data) | |||||
| ->setMessages($messages) | |||||
| ->setResultCode(ResultCode::EXCLUSIVE_ERROR) | |||||
| ->makeResponse(); | |||||
| } | |||||
| protected function validateErrorResponse(ValidationException|array $exception, string|null $generalMessage = null) | |||||
| { | |||||
| $errorMessages = []; | |||||
| $general = null; | |||||
| if ($exception instanceof ValidationException) { | |||||
| foreach ($exception->errors() as $key => $m) { | |||||
| $errorMessages[$key] = $m[0]; | |||||
| } | |||||
| } | |||||
| if (is_array($exception)) { | |||||
| $errorMessages = $exception; | |||||
| } | |||||
| $general = $generalMessage ?? data_get($errorMessages, self::COL_NAME_GENERAL_MESSAGE); | |||||
| return $this->setData([]) | |||||
| ->setMessages($errorMessages) | |||||
| ->setGeneralMessage($general) | |||||
| ->setResultCode(ResultCode::FAILED) | |||||
| ->makeResponse(); | |||||
| } | |||||
| private function makeResponse() | |||||
| { | |||||
| if ($this->resultCode === null) { | |||||
| abort(403); | |||||
| } | |||||
| $ret = []; | |||||
| Arr::set($ret, self::COL_NAME_RESULT_CODE, $this->resultCode->value); | |||||
| if ($this->data !== null) { | |||||
| Arr::set($ret, self::COL_NAME_DATA, $this->data); | |||||
| } | |||||
| if ($this->messages !== null) { | |||||
| Arr::set($ret, self::COL_NAME_MESSAGES . "." . self::COL_NAME_ERRORS, $this->messages); | |||||
| } | |||||
| if ($this->generalMessage !== null) { | |||||
| Arr::set($ret, self::COL_NAME_MESSAGES . "." . self::COL_NAME_GENERAL_MESSAGE, $this->generalMessage); | |||||
| } | |||||
| if ($this->emailId !== null) { | |||||
| Arr::set($ret, self::COL_NAME_MESSAGES . "." . self::COL_NAME_EMAIL_ID, $this->emailId); | |||||
| } | |||||
| return response() | |||||
| ->json($ret) | |||||
| ->withHeaders($this->makeHeader()); | |||||
| } | |||||
| private function makeHeader(): array | |||||
| { | |||||
| $header = []; | |||||
| $user = Auth::user(); | |||||
| if ($user) { | |||||
| $header["App-User-Auth"] = sprintf("%d,%d", $user->id, $user->role->value); | |||||
| } else { | |||||
| $header["App-User-Auth"] = 'none'; | |||||
| } | |||||
| return $header; | |||||
| } | |||||
| // 以下 認可関係 | |||||
| protected array|null $roleAllow = null; | |||||
| protected array|null $roleDisallow = null; | |||||
| protected function roleAllow(UserRole $role) | |||||
| { | |||||
| $this->roleAllow = []; | |||||
| foreach (UserRole::cases() as $ele) { | |||||
| if ($role->value <= $ele->value) { | |||||
| $this->roleAllow[] = $ele; | |||||
| } | |||||
| } | |||||
| } | |||||
| private function authorize() | |||||
| { | |||||
| if (!Auth::check()) { | |||||
| return; | |||||
| } | |||||
| $role = Auth::user()->role; | |||||
| if (!$this->canAccess($role)) { | |||||
| abort(401); | |||||
| } | |||||
| } | |||||
| public function canAccess(UserRole $role) | |||||
| { | |||||
| if (is_array($this->roleAllow) && !in_array($role, $this->roleAllow)) { | |||||
| return false; | |||||
| } | |||||
| if (is_array($this->roleDisallow) && in_array($role, $this->roleDisallow)) { | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| // 返却用データの登録 | |||||
| protected function setEmailId(int $emailId) | |||||
| { | |||||
| $this->emailId = $emailId; | |||||
| return $this; | |||||
| } | |||||
| protected function setMessages(array|string $messages) | |||||
| { | |||||
| if (is_array($messages)) { | |||||
| $this->messages = $messages; | |||||
| } else { | |||||
| $this->setGeneralMessage($messages); | |||||
| } | |||||
| return $this; | |||||
| } | |||||
| protected function setGeneralMessage(string|null $generalMessage) | |||||
| { | |||||
| $this->generalMessage = $generalMessage; | |||||
| return $this; | |||||
| } | |||||
| protected function setData($data) | |||||
| { | |||||
| $this->data = $data; | |||||
| return $this; | |||||
| } | |||||
| protected function setResultCode(ResultCode $resultCode) | |||||
| { | |||||
| $this->resultCode = $resultCode; | |||||
| return $this; | |||||
| } | |||||
| protected function setLogContext(Request $request) | |||||
| { | |||||
| Log::withContext([ | |||||
| '__requestUuid__' => strval(Str::uuid()), | |||||
| '__userId__' => Auth::id(), | |||||
| '__path__' => $request->path(), | |||||
| ]); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,40 @@ | |||||
| <?php | |||||
| namespace App\Jobs\Mail; | |||||
| use App\Codes\QueueName; | |||||
| use App\Mail\Sender; | |||||
| use App\Models\Email; | |||||
| use Illuminate\Bus\Queueable; | |||||
| use Illuminate\Contracts\Queue\ShouldQueue; | |||||
| use Illuminate\Foundation\Bus\Dispatchable; | |||||
| use Illuminate\Queue\InteractsWithQueue; | |||||
| use Illuminate\Queue\SerializesModels; | |||||
| class SimpleMail implements ShouldQueue | |||||
| { | |||||
| use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; | |||||
| private string $emailId; | |||||
| /** | |||||
| * Create a new job instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct(Email $email) | |||||
| { | |||||
| $this->emailId = $email->id; | |||||
| $this->onQueue(QueueName::EMAIL->value); | |||||
| } | |||||
| /** | |||||
| * Execute the job. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function handle() | |||||
| { | |||||
| Sender::send($this->emailId); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,49 @@ | |||||
| <?php | |||||
| namespace App\Jobs\SMS; | |||||
| use App\Codes\QueueName; | |||||
| use App\Logic\SMS\SMSManager; | |||||
| use App\Models\SMSSendOrder; | |||||
| use Illuminate\Bus\Queueable; | |||||
| use Illuminate\Contracts\Queue\ShouldQueue; | |||||
| use Illuminate\Foundation\Bus\Dispatchable; | |||||
| use Illuminate\Queue\InteractsWithQueue; | |||||
| use Illuminate\Queue\SerializesModels; | |||||
| class SendSMS implements ShouldQueue | |||||
| { | |||||
| use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; | |||||
| /** | |||||
| * Create a new job instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct(private SMSSendOrder $order) | |||||
| { | |||||
| $this->onQueue(QueueName::SMS->value); | |||||
| } | |||||
| /** | |||||
| * Execute the job. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function handle(SMSManager $manager) | |||||
| { | |||||
| $ret = $manager->setOrder($this->order) | |||||
| ->send(); | |||||
| if ($ret) { | |||||
| info(sprintf( | |||||
| "SMS送信依頼成功 address:%s order_id:%s", | |||||
| $this->order->phone_number, | |||||
| $this->order->id, | |||||
| )); | |||||
| } else { | |||||
| $this->fail(sprintf("SMS送信依頼失敗 order_id:%s", $this->order->id)); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,36 @@ | |||||
| <?php | |||||
| namespace App\Listeners\Mail; | |||||
| use App\Events\Mail\ConfirmEvent; | |||||
| use App\Jobs\Mail\SimpleMail; | |||||
| use App\Util\DateUtil; | |||||
| class MailSendJobRegister | |||||
| { | |||||
| /** | |||||
| * Create the event listener. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct() | |||||
| { | |||||
| } | |||||
| /** | |||||
| * Handle the event. | |||||
| * | |||||
| * @param ConfirmEvent $event | |||||
| * @return void | |||||
| */ | |||||
| public function handle(ConfirmEvent $event) | |||||
| { | |||||
| $email = $event->email; | |||||
| if ($email->confirm_datetime === null && $email->send_datetime === null) { | |||||
| $email->confirm_datetime = DateUtil::now(); | |||||
| $email->save(); | |||||
| SimpleMail::dispatch($event->email); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,15 @@ | |||||
| <?php | |||||
| namespace App\Listeners\Model; | |||||
| use App\Events\Model\CreatedEvent; | |||||
| class CreatedListener extends ModelListener | |||||
| { | |||||
| protected const ACTION = '作成'; | |||||
| public function handle(CreatedEvent $event): void | |||||
| { | |||||
| $this->handleEvent($event->model); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,15 @@ | |||||
| <?php | |||||
| namespace App\Listeners\Model; | |||||
| use App\Events\Model\DeletedEvent; | |||||
| class DeletedListener extends ModelListener | |||||
| { | |||||
| protected const ACTION = '削除'; | |||||
| public function handle(DeletedEvent $event): void | |||||
| { | |||||
| $this->handleEvent($event->model); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,15 @@ | |||||
| <?php | |||||
| namespace App\Listeners\Model; | |||||
| use App\Events\Model\DeletingEvent; | |||||
| class DeletingListener extends ModelListener | |||||
| { | |||||
| protected const ACTION = '削除'; | |||||
| public function handle(DeletingEvent $event): void | |||||
| { | |||||
| $this->handleEvent($event->model); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,59 @@ | |||||
| <?php | |||||
| namespace App\Listeners\Model; | |||||
| use App\Models\ColumnName; | |||||
| use App\Models\Feature\IModelFeature; | |||||
| use Illuminate\Database\Eloquent\Model; | |||||
| use Illuminate\Support\Facades\Auth; | |||||
| use Illuminate\Support\Facades\Log; | |||||
| abstract class ModelListener | |||||
| { | |||||
| protected const ACTION = '-'; | |||||
| protected function handleEvent(IModelFeature $model): void | |||||
| { | |||||
| // 履歴作成処理 | |||||
| $this->createHistory($model); | |||||
| // 更新者作成者設定処理 | |||||
| $this->setHandlerIds(); | |||||
| } | |||||
| protected function createHistory(IModelFeature $model) | |||||
| { | |||||
| $history = $model->getHistory(); | |||||
| if ($history !== null) { | |||||
| $history->fillFromOrigin($model); | |||||
| $history->save(); | |||||
| $changeMessage = ""; | |||||
| if ($model instanceof Model) { | |||||
| $before = $model->getOriginal(); | |||||
| $after = $model; | |||||
| $message = $model->getChangeLogMessage($before, $after); | |||||
| if ($message !== null) { | |||||
| $changeMessage = sprintf("[%s]", $message); | |||||
| } | |||||
| } | |||||
| Log::info(sprintf( | |||||
| "モデル変更検知[%s][%s][ID:%s]%s", | |||||
| $model->getModelName(), | |||||
| static::ACTION, | |||||
| data_get($model, ColumnName::ID), | |||||
| $changeMessage | |||||
| )); | |||||
| } | |||||
| } | |||||
| protected function setHandlerIds() | |||||
| { | |||||
| if (Auth::check()) { | |||||
| $this->created_by = Auth::id(); | |||||
| $this->updated_by = Auth::id(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,15 @@ | |||||
| <?php | |||||
| namespace App\Listeners\Model; | |||||
| use App\Events\Model\UpdatingEvent; | |||||
| class UpdatingListener extends ModelListener | |||||
| { | |||||
| protected const ACTION = '更新'; | |||||
| public function handle(UpdatingEvent $event): void | |||||
| { | |||||
| $this->handleEvent($event->model); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,41 @@ | |||||
| <?php | |||||
| namespace App\Listeners\SMS; | |||||
| use App\Events\SMS\ConfirmEvent; | |||||
| /** | |||||
| * SMS送信依頼の確定イベントをキャッチ | |||||
| * 領収証発行依頼のSMS送信完了を設定する | |||||
| */ | |||||
| class ConfirmListener | |||||
| { | |||||
| /** | |||||
| * Create the event listener. | |||||
| */ | |||||
| public function __construct() | |||||
| { | |||||
| // | |||||
| } | |||||
| /** | |||||
| * Handle the event. | |||||
| */ | |||||
| public function handle(ConfirmEvent $event): void | |||||
| { | |||||
| $smsSendOrder = $event->order; | |||||
| $receiptIssuingOrder = $smsSendOrder->receiptIssuingOrder; | |||||
| if ($receiptIssuingOrder === null) { | |||||
| return; | |||||
| } | |||||
| $success = $smsSendOrder->send_datetime !== null; | |||||
| if ($success) { | |||||
| $receiptIssuingOrder->sms_send_success = true; | |||||
| $receiptIssuingOrder->save(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,101 @@ | |||||
| <?php | |||||
| namespace App\Logic; | |||||
| use App\Events\Mail\ConfirmEvent; | |||||
| use App\Exceptions\AppCommonException; | |||||
| use App\Mail\BaseMailer; | |||||
| use App\Models\Email; | |||||
| use Exception; | |||||
| use Illuminate\Support\Carbon; | |||||
| use Validator; | |||||
| class EmailManager | |||||
| { | |||||
| private Email $model; | |||||
| private bool $canSend = false; | |||||
| public function __construct(int|BaseMailer $param) | |||||
| { | |||||
| if (is_numeric($param)) { | |||||
| $this->model = Email::lockForUpdate()->findOrfail($param); | |||||
| $this->canSend = $this->model->send_datetime === null; | |||||
| if (!$this->checkAuth()) throw new AppCommonException("メール権限エラー"); | |||||
| } else if ($param instanceof BaseMailer) { | |||||
| $this->model = $param->makeModel(); | |||||
| } | |||||
| } | |||||
| public function checkAuth() | |||||
| { | |||||
| return true; | |||||
| } | |||||
| public function getEmailId() | |||||
| { | |||||
| return $this->model->id; | |||||
| } | |||||
| public function getTimestamp(): Carbon|null | |||||
| { | |||||
| return $this->model->updated_at; | |||||
| } | |||||
| public function create() | |||||
| { | |||||
| $this->model->save(); | |||||
| return []; | |||||
| } | |||||
| public function setSubject(string $subject) | |||||
| { | |||||
| if ($this->canSend()) { | |||||
| $this->model->subject = $subject; | |||||
| } else { | |||||
| throw new AppCommonException("送信済みメール編集エラー"); | |||||
| } | |||||
| return $this; | |||||
| } | |||||
| public function setContent(string $content) | |||||
| { | |||||
| if ($this->canSend()) { | |||||
| $this->model->content = $content; | |||||
| } else { | |||||
| throw new AppCommonException("送信済みメール編集エラー"); | |||||
| } | |||||
| return $this; | |||||
| } | |||||
| public function update() | |||||
| { | |||||
| $this->model->save(); | |||||
| return []; | |||||
| } | |||||
| public function confirm() | |||||
| { | |||||
| $validator = Validator::make(['email' => $this->model->email], [ | |||||
| 'email' => ['required', 'email:strict,dns'] | |||||
| ]); | |||||
| if ($validator->fails()) { | |||||
| throw new Exception(sprintf("%s [%s]", $validator->errors()->first(), $this->model->email)); | |||||
| } | |||||
| if ($this->canSend() !== null) { | |||||
| ConfirmEvent::dispatch($this->model); | |||||
| } else { | |||||
| throw new AppCommonException("送信済みエラー"); | |||||
| } | |||||
| } | |||||
| public function canSend() | |||||
| { | |||||
| return $this->canSend; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,79 @@ | |||||
| <?php | |||||
| namespace App\Logic\ReceiptIssuingOrder; | |||||
| use App\Codes\ReceiptIssuingOrderStatus; | |||||
| use App\Codes\SMSSendPurpose; | |||||
| use App\Logic\SMS\SMSManager; | |||||
| use App\Models\ReceiptIssuingOrder; | |||||
| use Illuminate\Support\Facades\View; | |||||
| use LogicException; | |||||
| class CreateManager extends ReceiptIssuingOrderManager | |||||
| { | |||||
| public function __construct( | |||||
| protected ReceiptIssuingOrder $order, | |||||
| protected SMSManager $smsManager | |||||
| ) { | |||||
| } | |||||
| public function init() | |||||
| { | |||||
| $order = $this->order; | |||||
| $this->initialized = true; | |||||
| return $this; | |||||
| } | |||||
| public function fill(array $attr) | |||||
| { | |||||
| $this->order->fill($attr); | |||||
| return $this; | |||||
| } | |||||
| public function create(): array | |||||
| { | |||||
| $order = $this->order; | |||||
| // パラメータチェック | |||||
| $messages = $this->paramCheck(); | |||||
| if (count($messages) !== 0) { | |||||
| return $messages; | |||||
| } | |||||
| // モデル更新 | |||||
| $order->status = ReceiptIssuingOrderStatus::CREATED; | |||||
| $this->refreshToken(); | |||||
| $contractId = $this->loginUser()->getContractId(); | |||||
| if ($contractId === null) { | |||||
| throw new LogicException("契約不良"); | |||||
| } | |||||
| $order->setContract($contractId) | |||||
| ->save(); | |||||
| // SMS配信 | |||||
| $smsSendOrder = $this->smsManager::makeSMSSendOrder($order, SMSSendPurpose::SEND_RECEIPT_ISSUING_ORDER_FORM, $this->makeSMSContents()); | |||||
| $smsSendOrder->send(); | |||||
| return []; | |||||
| } | |||||
| private function paramCheck(): array | |||||
| { | |||||
| $ret = []; | |||||
| $order = $this->order; | |||||
| return $ret; | |||||
| } | |||||
| private function makeSMSContents(): string | |||||
| { | |||||
| return View::make('sms.announce_receipt_issusing_order_form', [ | |||||
| 'url' => implode('/', [config('app.url'), 'receipt-issuing-order/create', $this->order->access_token]) | |||||
| ])->render(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,54 @@ | |||||
| <?php | |||||
| namespace App\Logic\ReceiptIssuingOrder; | |||||
| use App\Codes\ReceiptIssuingOrderStatus; | |||||
| use App\Exceptions\AppCommonException; | |||||
| use App\Logic\SMS\SMSManager; | |||||
| use App\Models\ReceiptIssuingOrder; | |||||
| use PDF; | |||||
| class UpdateManager extends ReceiptIssuingOrderManager | |||||
| { | |||||
| public function __construct( | |||||
| protected ReceiptIssuingOrder $order, | |||||
| protected SMSManager $smsManager | |||||
| ) { | |||||
| } | |||||
| public function initByToken(string $token) | |||||
| { | |||||
| $ret = $this->checkToken($token); | |||||
| if (!$ret) { | |||||
| throw new AppCommonException("トークン不正"); | |||||
| } | |||||
| $this->initialized = true; | |||||
| return $this; | |||||
| } | |||||
| public function initById(string $id) | |||||
| { | |||||
| $this->fetch($id); | |||||
| $this->initialized = true; | |||||
| return $this; | |||||
| } | |||||
| protected function service() | |||||
| { | |||||
| $order = $this->order; | |||||
| $pdf = PDF::loadView('pdf', $order); | |||||
| // はがきサイズを指定 | |||||
| $ret = $pdf->setOption('page-height', 148) | |||||
| ->setOption('page-width', 100) | |||||
| ->setOption('encoding', 'utf-8') | |||||
| ->inline(); | |||||
| $order->status = ReceiptIssuingOrderStatus::DOWNLOAD_DONE; | |||||
| return $ret; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,73 @@ | |||||
| <?php | |||||
| namespace App\Logic\ReceiptIssuingOrder; | |||||
| use App\Exceptions\AppCommonException; | |||||
| use App\Features\LoginUser; | |||||
| use App\Models\ReceiptIssuingOrder; | |||||
| use App\Util\DateUtil; | |||||
| use Illuminate\Support\Str; | |||||
| use LogicException; | |||||
| abstract class ReceiptIssuingOrderManager | |||||
| { | |||||
| use LoginUser; | |||||
| protected bool $initialized = false; | |||||
| protected function __construct(protected ReceiptIssuingOrder $order) | |||||
| { | |||||
| } | |||||
| protected function fetch(string $receiptIssuingOrderId) | |||||
| { | |||||
| $order = ReceiptIssuingOrder::findOrFail($receiptIssuingOrderId); | |||||
| if (!$this->loginUser()->checkAuthorization($order)) { | |||||
| throw new AppCommonException("認可不良"); | |||||
| } | |||||
| $this->order = $order; | |||||
| } | |||||
| protected function refreshToken() | |||||
| { | |||||
| $order = $this->order; | |||||
| $order->access_token = base64_encode(Str::uuid()); | |||||
| $order->access_token_expires_at = DateUtil::now()->adddays(7); | |||||
| } | |||||
| protected function checkToken(string $token): bool | |||||
| { | |||||
| if ($this->order->isNotSavedModel()) { | |||||
| throw new LogicException("初期化不良"); | |||||
| } | |||||
| $order = ReceiptIssuingOrder::whereAccessToken($token) | |||||
| ->first(); | |||||
| if (!($order instanceof ReceiptIssuingOrder)) { | |||||
| return false; | |||||
| } | |||||
| if ($order->access_token_expires_at === null) { | |||||
| return false; | |||||
| } | |||||
| if ($order->access_token !== $token) { | |||||
| return false; | |||||
| } | |||||
| $now = DateUtil::now(); | |||||
| $ret = $now->lt($this->order->access_token_expires_at); | |||||
| if (!$ret) { | |||||
| return false; | |||||
| } | |||||
| $this->order = $order; | |||||
| return true; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,66 @@ | |||||
| <?php | |||||
| namespace App\Logic\ReceiptIssuingOrder; | |||||
| use App\Exceptions\AppCommonException; | |||||
| use App\Logic\SMS\SMSManager; | |||||
| use App\Models\ReceiptIssuingOrder; | |||||
| class UpdateManager extends ReceiptIssuingOrderManager | |||||
| { | |||||
| public function __construct( | |||||
| protected ReceiptIssuingOrder $order, | |||||
| protected SMSManager $smsManager | |||||
| ) { | |||||
| } | |||||
| public function initByToken(string $token) | |||||
| { | |||||
| $ret = $this->checkToken($token); | |||||
| if (!$ret) { | |||||
| throw new AppCommonException("トークン不正"); | |||||
| } | |||||
| $this->initialized = true; | |||||
| return $this; | |||||
| } | |||||
| public function initById(string $id) | |||||
| { | |||||
| $this->fetch($id); | |||||
| $this->initialized = true; | |||||
| return $this; | |||||
| } | |||||
| public function fill(array $attr) | |||||
| { | |||||
| $this->order->fill($attr); | |||||
| return $this; | |||||
| } | |||||
| protected function service() | |||||
| { | |||||
| $order = $this->order; | |||||
| // パラメータチェック | |||||
| $messages = $this->paramCheck(); | |||||
| if (count($messages) !== 0) { | |||||
| return $messages; | |||||
| } | |||||
| // モデル更新 | |||||
| $order->save(); | |||||
| return []; | |||||
| } | |||||
| private function paramCheck(): array | |||||
| { | |||||
| $ret = []; | |||||
| $order = $this->order; | |||||
| return $ret; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,329 @@ | |||||
| <?php | |||||
| namespace App\Logic\SMS; | |||||
| use App\Codes\SMSProviderName; | |||||
| use App\Codes\SMSSendPurpose; | |||||
| use App\Models\ReceiptIssuingOrder; | |||||
| use App\Models\SMSProvider; | |||||
| use App\Models\SMSProviderFourSMessageCommunication; | |||||
| use App\Models\SMSSendOrder; | |||||
| use App\Util\DateUtil; | |||||
| use Exception; | |||||
| use Illuminate\Http\Client\Response; | |||||
| use Illuminate\Support\Collection; | |||||
| use Illuminate\Support\Facades\Http; | |||||
| use LogicException; | |||||
| class FourSMessageManager implements SMSManager | |||||
| { | |||||
| private const SEND_URL = ['POST', "https://4sm.jp/api/sms_send"]; | |||||
| private const CANCEL_URL = ['POST', "https://4sm.jp/api/sms_cancel"]; | |||||
| private const RESULT_URL = ['POST', "https://4sm.jp/api/get_send_result"]; | |||||
| private static function getUserId(): string | |||||
| { | |||||
| $ret = config("logic.sms.FourSMessage.userId"); | |||||
| if ($ret === null) { | |||||
| throw new LogicException("SMS FourSMessage UserID 未定義"); | |||||
| } | |||||
| return $ret; | |||||
| } | |||||
| private static function getPassword(): string | |||||
| { | |||||
| $ret = config("logic.sms.FourSMessage.password"); | |||||
| if ($ret === null) { | |||||
| throw new LogicException("SMS FourSMessage Password 未定義"); | |||||
| } | |||||
| return $ret; | |||||
| } | |||||
| public static function makeSMSSendOrder(ReceiptIssuingOrder $receiptIssuingOrder, SMSSendPurpose $purpose, string $contents): SMSSendOrder | |||||
| { | |||||
| $order = new SMSSendOrder(); | |||||
| $order->receipt_issuing_order_id = $receiptIssuingOrder->id; | |||||
| $order->contract_id = $receiptIssuingOrder->contract_id; | |||||
| $order->phone_number = $receiptIssuingOrder->sms_phone_number; | |||||
| $order->sumamry_key1 = $receiptIssuingOrder->sumamry_key1; | |||||
| $order->sumamry_key2 = $receiptIssuingOrder->sumamry_key2; | |||||
| $order->purpose = $purpose; | |||||
| $order->content = $contents; | |||||
| return $$order; | |||||
| } | |||||
| public function __construct( | |||||
| private SMSSendOrder $order, | |||||
| ) { | |||||
| } | |||||
| public function loadOrder(string $id): static | |||||
| { | |||||
| $this->order = SMSSendOrder::findOrFail($id); | |||||
| return $this; | |||||
| } | |||||
| public function setOrder(SMSSendOrder $order): static | |||||
| { | |||||
| $this->order = $order; | |||||
| return $this; | |||||
| } | |||||
| public function getOrder() | |||||
| { | |||||
| return $this->order; | |||||
| } | |||||
| public function send(): bool | |||||
| { | |||||
| $sendContents = [ | |||||
| 'cp_userid' => static::getUserId(), | |||||
| 'cp_password' => static::getPassword(), | |||||
| 'carrier_id' => '99', | |||||
| 'message' => $this->order->content, | |||||
| 'address' => $this->order->phone_number, | |||||
| 'urlshorterflg' => '1', | |||||
| 'send_date' => '202305120000', | |||||
| ]; | |||||
| $this->order->sms_provider_id = CommunicationData::getMst()->id; | |||||
| $res = $this->communication(self::SEND_URL, $sendContents); | |||||
| if ($res->isSuccess()) { | |||||
| // 送信依頼を作成 | |||||
| $this->order->save(); | |||||
| $comm = new SMSProviderFourSMessageCommunication(); | |||||
| $comm->sms_send_order_id = $this->order->id; | |||||
| $comm->contract_id = $this->order->contract_id; | |||||
| $comm->request_id = $res->requestId; | |||||
| $comm->request_date = $res->requestDate; | |||||
| $comm->save(); | |||||
| return true; | |||||
| } else { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| public function poll(): bool | |||||
| { | |||||
| $requestId = SMSProviderFourSMessageCommunication::whereSmsSendOrderId($this->order->id) | |||||
| ->firstOrFail() | |||||
| ->request_id; | |||||
| $sendContents = [ | |||||
| 'request_id' => $requestId, | |||||
| 'user_id' => static::getUserId(), | |||||
| 'password' => base64_encode(static::getPassword()), | |||||
| ]; | |||||
| $res = $this->communication(self::RESULT_URL, $sendContents); | |||||
| if ($res->isSuccess()) { | |||||
| $res->save(); | |||||
| } | |||||
| return $res->isSuccess(); | |||||
| } | |||||
| public function cancel(): bool | |||||
| { | |||||
| $requestId = SMSProviderFourSMessageCommunication::whereSmsSendOrderId($this->order->id) | |||||
| ->firstOrFail() | |||||
| ->request_id; | |||||
| $sendContents = [ | |||||
| 'request_id' => $requestId, | |||||
| 'cp_userid' => static::getUserId(), | |||||
| 'cp_password' => static::getPassword(), | |||||
| ]; | |||||
| $res = $this->communication(self::CANCEL_URL, $sendContents); | |||||
| return $res->isSuccess(); | |||||
| } | |||||
| private function communication(array $urlDef, array $sendData): CommunicationData | |||||
| { | |||||
| $method = $urlDef[0]; | |||||
| $form = Http::withHeaders([ | |||||
| 'Content-Type' => 'application/x-www-form-urlencoded', | |||||
| ]) | |||||
| ->asForm(); | |||||
| if ($method === 'GET') { | |||||
| $query = ""; | |||||
| foreach ($sendData as $key => $value) { | |||||
| if ($query !== "") { | |||||
| $query .= '&'; | |||||
| } | |||||
| $query .= $key . "=" . $value; | |||||
| } | |||||
| $url = $urlDef[1] . '?' . $query; | |||||
| $res = $form->get($url); | |||||
| } else { | |||||
| $url = $urlDef[1]; | |||||
| $res = $form->post($url, $sendData); | |||||
| } | |||||
| logger(['SMS-SendContet' => $sendData, 'URL' => $url]); | |||||
| if (!$res->ok()) { | |||||
| $res->throw(); | |||||
| } | |||||
| logger(['SMS-ReveiveContet' => $res->json()]); | |||||
| $ret = new CommunicationData($res, $this->order); | |||||
| return $ret; | |||||
| } | |||||
| } | |||||
| class CommunicationData | |||||
| { | |||||
| public string|null $result; | |||||
| public string|null $requestId; | |||||
| public string|null $requestDate; | |||||
| public string|null $errorCode; | |||||
| public string|null $errorMessage; | |||||
| /** | |||||
| * @var Collection<SMSProviderFourSMessageCommunication> | |||||
| */ | |||||
| public Collection $data; | |||||
| private SMSSendOrder $order; | |||||
| private const RESULT_SUCCESS = 'SUCCESS'; | |||||
| private const DATE_FORMAT = 'YmdHi'; | |||||
| public function __construct(Response $res, SMSSendOrder $order) | |||||
| { | |||||
| $this->order = $order; | |||||
| $data = $res->json(); | |||||
| $response = data_get($data, 'response'); | |||||
| if ($response !== null) { | |||||
| $data = $response; | |||||
| } | |||||
| $this->result = data_get($data, 'result'); | |||||
| $this->requestId = data_get($data, 'request_id'); | |||||
| $this->requestDate = data_get($data, 'request_date'); | |||||
| $this->errorCode = data_get($data, 'error_code'); | |||||
| $this->errorMessage = data_get($data, 'error_message'); | |||||
| $this->data = collect(); | |||||
| $records = data_get($data, 'records'); | |||||
| if (is_array($records)) { | |||||
| foreach ($records as $record) { | |||||
| $requestId = data_get($record, 'request_id'); | |||||
| // 空文字の場合があるので、数値にキャストする | |||||
| $record['success_count'] = intVal($record['success_count']); | |||||
| $ele = SMSProviderFourSMessageCommunication::whereRequestId($requestId) | |||||
| ->firstOrFail(); | |||||
| $ele->fill($record); | |||||
| $ele->sms_send_order_id = $order->id; | |||||
| $this->data->push($ele); | |||||
| } | |||||
| } | |||||
| } | |||||
| public function isSuccess(): bool | |||||
| { | |||||
| return $this->result === self::RESULT_SUCCESS; | |||||
| } | |||||
| public function save() | |||||
| { | |||||
| foreach ($this->data as $data) { | |||||
| $data->save(); | |||||
| if ($this->isFixRecord($data)) { | |||||
| $this->order->done = true; | |||||
| if ($data->deliv_rcpt_date !== null) { | |||||
| $this->order->send_datetime = DateUtil::parse($data->deliv_rcpt_date, self::DATE_FORMAT); | |||||
| } | |||||
| if ($data->success_count > 0) { | |||||
| $this->order->cost = $this->calcCost($data); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| public function isFixRecord(SMSProviderFourSMessageCommunication $comm): bool | |||||
| { | |||||
| // 以下のコードになれば「状態確定」のタイミングであると判断できます。 | |||||
| // ・受付状態 : 90受付取消、または99受付失敗 | |||||
| // ・送信エラー: 31~35送信エラー、または40送達済 | |||||
| if (in_array($comm->request_status, ['90', '99'])) { | |||||
| return true; | |||||
| } | |||||
| if (in_array($comm->sending_status, [ | |||||
| '31', | |||||
| '32', | |||||
| '33', | |||||
| '34', | |||||
| '35', | |||||
| '40', | |||||
| ])) { | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| private function calcCost(SMSProviderFourSMessageCommunication $comm): int | |||||
| { | |||||
| $provider = self::getMst(); | |||||
| return $comm->success_count * $provider->cost; | |||||
| } | |||||
| private static function getMst(): SMSProvider | |||||
| { | |||||
| static $provider = null; | |||||
| if ($provider === null) { | |||||
| $provider = SMSProvider::whereProviderName(SMSProviderName::FOUR_S_MESSAGE->value) | |||||
| ->firstOrFail(); | |||||
| } | |||||
| return $provider; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,91 @@ | |||||
| <?php | |||||
| namespace App\Logic\SMS; | |||||
| use App\Codes\SMSProviderName; | |||||
| use App\Codes\SMSSendPurpose; | |||||
| use App\Events\SMS\ConfirmEvent; | |||||
| use App\Models\ReceiptIssuingOrder; | |||||
| use App\Models\SMSProvider; | |||||
| use App\Models\SMSSendOrder; | |||||
| use App\Util\DateUtil; | |||||
| class LogManager implements SMSManager | |||||
| { | |||||
| public static function makeSMSSendOrder(ReceiptIssuingOrder $receiptIssuingOrder, SMSSendPurpose $purpose, string $contents): SMSSendOrder | |||||
| { | |||||
| $order = new SMSSendOrder(); | |||||
| $order->receipt_issuing_order_id = $receiptIssuingOrder->id; | |||||
| $order->contract_id = $receiptIssuingOrder->contract_id; | |||||
| $order->phone_number = $receiptIssuingOrder->sms_phone_number; | |||||
| $order->sumamry_key1 = $receiptIssuingOrder->sumamry_key1; | |||||
| $order->sumamry_key2 = $receiptIssuingOrder->sumamry_key2; | |||||
| $order->purpose = $purpose; | |||||
| $order->content = $contents; | |||||
| $order->sms_provider_id = static::getMst()->id; | |||||
| return $order; | |||||
| } | |||||
| public function __construct( | |||||
| private SMSSendOrder $order, | |||||
| ) { | |||||
| } | |||||
| public function loadOrder(string $id): static | |||||
| { | |||||
| $this->order = SMSSendOrder::findOrFail($id); | |||||
| return $this; | |||||
| } | |||||
| public function setOrder(SMSSendOrder $order): static | |||||
| { | |||||
| $this->order = $order; | |||||
| return $this; | |||||
| } | |||||
| public function getOrder() | |||||
| { | |||||
| return $this->order; | |||||
| } | |||||
| public function send(): bool | |||||
| { | |||||
| $this->order->send_datetime = DateUtil::now(); | |||||
| $this->order->done = true; | |||||
| $this->order->save(); | |||||
| info(sprintf("SMS送信ダミー:<<%s>>", $this->order->content)); | |||||
| return true; | |||||
| } | |||||
| public function poll(): bool | |||||
| { | |||||
| return true; | |||||
| } | |||||
| public function cancel(): bool | |||||
| { | |||||
| return true; | |||||
| } | |||||
| private static function getMst(): SMSProvider | |||||
| { | |||||
| static $provider = null; | |||||
| if ($provider === null) { | |||||
| $provider = SMSProvider::whereProviderName(SMSProviderName::LOG->value) | |||||
| ->firstOrFail(); | |||||
| } | |||||
| return $provider; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,21 @@ | |||||
| <?php | |||||
| namespace App\Logic\SMS; | |||||
| use App\Codes\SMSSendPurpose; | |||||
| use App\Models\ReceiptIssuingOrder; | |||||
| use App\Models\SMSSendOrder; | |||||
| interface SMSManager | |||||
| { | |||||
| public static function makeSMSSendOrder(ReceiptIssuingOrder $order, SMSSendPurpose $purpose, string $contents): SMSSendOrder; | |||||
| public function loadOrder(string $id): static; | |||||
| public function setOrder(SMSSendOrder $order): static; | |||||
| public function getOrder(); | |||||
| public function send(): bool; | |||||
| public function poll(): bool; | |||||
| public function cancel(): bool; | |||||
| } | |||||
| @@ -0,0 +1,15 @@ | |||||
| <?php | |||||
| namespace App\Mail\Admins; | |||||
| use App\Mail\BaseMailer; | |||||
| abstract class Admin extends BaseMailer | |||||
| { | |||||
| public function getParams(): array | |||||
| { | |||||
| return array_merge($this->getAdminParams(), []); | |||||
| } | |||||
| abstract public function getAdminParams(): array; | |||||
| } | |||||
| @@ -0,0 +1,92 @@ | |||||
| <?php | |||||
| namespace App\Mail\Admins; | |||||
| use App\Models\Parking; | |||||
| use App\Models\SeasonTicketContract; | |||||
| use App\Models\SeasonTicketContractSubscription; | |||||
| use App\Models\User; | |||||
| use App\Models\UserDetail; | |||||
| use Illuminate\Support\Carbon; | |||||
| class Ask extends Admin | |||||
| { | |||||
| protected string $askSubject; | |||||
| protected string $askContents; | |||||
| protected string|null $parkName = null; | |||||
| protected string|null $userName; | |||||
| protected string|null $userEmail; | |||||
| protected int|null $seasonTicketSeqNo = null; | |||||
| protected Carbon|null $subscribeDatetime = null; | |||||
| public function __construct( | |||||
| array $data, | |||||
| User|null $user = null, | |||||
| UserDetail|null $userDetail = null, | |||||
| SeasonTicketContract|null $seasonTicketContract = null, | |||||
| SeasonTicketContractSubscription|null $subscription = null, | |||||
| Parking|null $parking = null, | |||||
| ) { | |||||
| $this->setValues($data); | |||||
| if ($seasonTicketContract) { | |||||
| $this->seasonTicketSeqNo = $seasonTicketContract->season_ticket_seq_no; | |||||
| } | |||||
| if ($subscription) { | |||||
| $this->subscribeDatetime = $subscription->subscribe_datetime; | |||||
| } | |||||
| if ($user) { | |||||
| $this->userEmail = $user->email; | |||||
| } | |||||
| if ($userDetail) { | |||||
| $this->userName = sprintf( | |||||
| "%s %s", | |||||
| $userDetail->first_name, | |||||
| $userDetail->last_name | |||||
| ); | |||||
| } | |||||
| if ($parking) { | |||||
| $this->parkName = $parking->park_name; | |||||
| } | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.admins.ask'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return sprintf( | |||||
| '【スマートパーキングパス】【問い合わせ】【%s】%s', | |||||
| $this->userName, | |||||
| $this->askSubject | |||||
| ); | |||||
| } | |||||
| private function memberRegistration(): string | |||||
| { | |||||
| if ($this->seasonTicketSeqNo !== null || $this->subscribeDatetime !== null) { | |||||
| return "あり"; | |||||
| } | |||||
| return "なし"; | |||||
| } | |||||
| public function getAdminParams(): array | |||||
| { | |||||
| return [ | |||||
| 'askSubject' => $this->askSubject, | |||||
| 'askContents' => $this->askContents, | |||||
| 'parkName' => $this->parkName, | |||||
| 'userName' => $this->userName, | |||||
| 'userEmail' => $this->userEmail, | |||||
| 'seasonTicketSeqNo' => $this->seasonTicketSeqNo, | |||||
| 'subscribeDatetime' => $this->subscribeDatetime ? $this->subscribeDatetime->format('Y/m/d H:i:s') : null, | |||||
| 'memberRegistration' => $this->memberRegistration(), | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,177 @@ | |||||
| <?php | |||||
| namespace App\Mail; | |||||
| use App\Exceptions\AppCommonException; | |||||
| use App\Models\Email; | |||||
| use App\Models\User; | |||||
| use App\Util\DateUtil; | |||||
| use Illuminate\Bus\Queueable; | |||||
| use Illuminate\Mail\Mailable; | |||||
| use Illuminate\Queue\SerializesModels; | |||||
| use Illuminate\Support\Facades\Mail; | |||||
| use Illuminate\Support\Str; | |||||
| abstract class BaseMailer extends Mailable | |||||
| { | |||||
| use Queueable, SerializesModels; | |||||
| protected $configRoot = 'mail.mailers.smtp_ht.'; | |||||
| protected $casts = []; | |||||
| protected User|null $__user = null; | |||||
| protected string $__email = ""; | |||||
| protected string|null $__userId = null; | |||||
| protected string|null $__contractId = null; | |||||
| protected string|null $__receiptIssuingOrderId = null; | |||||
| public function sendEmail(string $email) | |||||
| { | |||||
| $this->__email = $email; | |||||
| Mail::to($email) | |||||
| ->send($this); | |||||
| } | |||||
| public function setUser(User $user) | |||||
| { | |||||
| $this->__userId = $user->id; | |||||
| $this->__email = $user->email; | |||||
| return $this; | |||||
| } | |||||
| public function setEmail(string $target) | |||||
| { | |||||
| $this->__email = $target; | |||||
| return $this; | |||||
| } | |||||
| public function setUserId(string $userId) | |||||
| { | |||||
| $this->__userId = $userId; | |||||
| return $this; | |||||
| } | |||||
| public function setContractId(string $contractId) | |||||
| { | |||||
| $this->__contractId = $contractId; | |||||
| return $this; | |||||
| } | |||||
| public function setReceiptIssuingOrderId(string $receiptIssuingOrderId) | |||||
| { | |||||
| $this->__receiptIssuingOrderId = $receiptIssuingOrderId; | |||||
| return $this; | |||||
| } | |||||
| public function build() | |||||
| { | |||||
| return $this->text($this->getTemplateName()) | |||||
| ->subject($this->getSubject()) | |||||
| ->with($this->getParams()); | |||||
| } | |||||
| public function setConfigDefault() | |||||
| { | |||||
| $root = $this->configRoot; | |||||
| config([ | |||||
| $root . "transport" => "smtp", | |||||
| $root . "host" => env('MAIL_HOST', 'smtp.mailgun.org'), | |||||
| $root . 'port' => env('MAIL_PORT', 587), | |||||
| $root . 'encryption' => env('MAIL_ENCRYPTION', 'tls'), | |||||
| $root . 'username' => env('MAIL_USERNAME'), | |||||
| $root . 'password' => env('MAIL_PASSWORD'), | |||||
| $root . 'timeout' => null, | |||||
| $root . 'auth_mode' => null, | |||||
| $root . 'verify_peer' => false, | |||||
| ]); | |||||
| } | |||||
| public function setConfig(array $config) | |||||
| { | |||||
| $root = $this->configRoot; | |||||
| $ret = []; | |||||
| foreach ($config as $key => $val) { | |||||
| $ret[$root . $key] = $val; | |||||
| } | |||||
| config($ret); | |||||
| } | |||||
| protected function setValues(\stdClass|array $data) | |||||
| { | |||||
| foreach ($data as $key => $val) { | |||||
| $this->setValue($key, $val); | |||||
| } | |||||
| } | |||||
| protected function setValue(string $key, $value) | |||||
| { | |||||
| $val = $value; | |||||
| $camel = Str::camel($key); | |||||
| $snake = Str::snake($key); | |||||
| $property = ""; | |||||
| if (property_exists($this, $camel)) { | |||||
| $property = $camel; | |||||
| } else if (property_exists($this, $snake)) { | |||||
| $property = $snake; | |||||
| } else { | |||||
| return; | |||||
| } | |||||
| if (data_get($this->casts, $property) === 'datetime') { | |||||
| $this->$property = DateUtil::parse($val); | |||||
| } else { | |||||
| $this->$property = $val; | |||||
| } | |||||
| } | |||||
| public function makeModel(): Email | |||||
| { | |||||
| if ($this->__email === "") { | |||||
| throw new AppCommonException("Email宛先不明"); | |||||
| } | |||||
| $model = new Email(); | |||||
| $model->subject = $this->getSubject(); | |||||
| $model->content = $this->render(); | |||||
| $model->type = get_class($this); | |||||
| $model->email = $this->__email; | |||||
| $model->contract_id = $this->__contractId; | |||||
| $model->user_id = $this->__userId; | |||||
| $model->receipt_issuing_order_id = $this->__receiptIssuingOrderId; | |||||
| return $model; | |||||
| } | |||||
| abstract public function getTemplateName(): string; | |||||
| abstract public function getSubject(): string; | |||||
| abstract public function getParams(): array; | |||||
| /** | |||||
| * 画面のURLを生成する | |||||
| * | |||||
| * @param array|string $path | |||||
| * @return string | |||||
| */ | |||||
| protected function getAppUrl(array|string $path): string | |||||
| { | |||||
| $elements = [config("app.url")]; | |||||
| if (is_array($path)) { | |||||
| $elements = array_merge($elements, $path); | |||||
| } else { | |||||
| $elements[] = $path; | |||||
| } | |||||
| return implode( | |||||
| "/", | |||||
| $elements, | |||||
| ); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,70 @@ | |||||
| <?php | |||||
| namespace App\Mail\Common; | |||||
| use App\Models\Parking; | |||||
| use App\Models\User; | |||||
| use App\Models\UserDetail; | |||||
| use Illuminate\Support\Carbon; | |||||
| trait AskConfirmation | |||||
| { | |||||
| protected string $askSubject; | |||||
| protected string $askContents; | |||||
| protected string|null $parkName = null; | |||||
| protected string|null $userName; | |||||
| protected string|null $userEmail; | |||||
| protected int|null $seasonTicketSeqNo = null; | |||||
| protected Carbon|null $subscribeDatetime = null; | |||||
| private bool $forMember = false; | |||||
| abstract protected function setValues(\stdClass|array $data); | |||||
| protected function setAskConfirmationData( | |||||
| array $data, | |||||
| User|null $user = null, | |||||
| UserDetail|null $userDetail = null, | |||||
| Parking|null $parking = null, | |||||
| ) { | |||||
| $this->setValues($data); | |||||
| if ($user) { | |||||
| $this->userEmail = $user->email; | |||||
| $this->forMember = true; | |||||
| } | |||||
| if ($userDetail) { | |||||
| $this->userName = sprintf( | |||||
| "%s %s", | |||||
| $userDetail->first_name, | |||||
| $userDetail->last_name | |||||
| ); | |||||
| $this->forMember = true; | |||||
| } | |||||
| if ($parking) { | |||||
| $this->parkName = $parking->park_name; | |||||
| } | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return $this->forMember ? 'mails.members.ask_confirmation' : 'mails.guests.ask_confirmation'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return '【スマートパーキングパス】お問い合わせ内容の確認'; | |||||
| } | |||||
| protected function getAskConfirmationParams(): array | |||||
| { | |||||
| return [ | |||||
| 'askSubject' => $this->askSubject, | |||||
| 'askContents' => $this->askContents, | |||||
| 'parkName' => $this->parkName, | |||||
| 'userName' => $this->userName, | |||||
| 'userEmail' => $this->userEmail, | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,27 @@ | |||||
| <?php | |||||
| namespace App\Mail\Guests; | |||||
| use App\Mail\Common\AskConfirmation as CommonAskConfirmation; | |||||
| use App\Models\Parking; | |||||
| use App\Models\User; | |||||
| use App\Models\UserDetail; | |||||
| class AskConfirmation extends Guest | |||||
| { | |||||
| use CommonAskConfirmation; | |||||
| public function __construct( | |||||
| array $data, | |||||
| User|null $user = null, | |||||
| UserDetail|null $userDetail = null, | |||||
| Parking|null $parking = null, | |||||
| ) { | |||||
| $this->setAskConfirmationData($data, $user, $userDetail, $parking); | |||||
| } | |||||
| public function getGuestParams(): array | |||||
| { | |||||
| return $this->getAskConfirmationParams(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,63 @@ | |||||
| <?php | |||||
| namespace App\Mail\Guests; | |||||
| use App\Models\ChangeEmail; | |||||
| use Exception; | |||||
| use Illuminate\Support\Carbon; | |||||
| class ChangeEmailStart extends Guest | |||||
| { | |||||
| protected string $token; | |||||
| protected Carbon $expiresAt; | |||||
| protected $casts = [ | |||||
| 'expiresAt' => 'datetime', | |||||
| ]; | |||||
| /** | |||||
| * Create a new message instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct(ChangeEmail $model) | |||||
| { | |||||
| logger($model->toArray()); | |||||
| $this->setValues($model->toArray()); | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.guests.change_email_start'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return '【スマートパーキングパス】Email変更手続きのご案内'; | |||||
| } | |||||
| public function getGuestParams(): array | |||||
| { | |||||
| return [ | |||||
| 'url' => $this->getUrl(), | |||||
| 'expiresAt' => $this->getExpiresAt(), | |||||
| ]; | |||||
| } | |||||
| private function getUrl() | |||||
| { | |||||
| return implode( | |||||
| "/", | |||||
| [ | |||||
| config("app.url"), | |||||
| 'change-email', | |||||
| $this->token | |||||
| ] | |||||
| ); | |||||
| } | |||||
| private function getExpiresAt() | |||||
| { | |||||
| return $this->expiresAt->format('Y/m/d H:i'); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,65 @@ | |||||
| <?php | |||||
| namespace App\Mail\Guests; | |||||
| use App\Models\EmailVerify as ModelsEmailVerify; | |||||
| use Exception; | |||||
| use Illuminate\Support\Carbon; | |||||
| class EmailVerify extends Guest | |||||
| { | |||||
| protected string $token; | |||||
| protected Carbon $expiresAt; | |||||
| protected $casts = [ | |||||
| 'expiresAt' => 'datetime', | |||||
| ]; | |||||
| /** | |||||
| * Create a new message instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct(ModelsEmailVerify $model) | |||||
| { | |||||
| $this->setValues($model->toArray()); | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.guests.email_verify'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return '【スマートパーキングパス】会員登録のご案内'; | |||||
| } | |||||
| public function getGuestParams(): array | |||||
| { | |||||
| return [ | |||||
| 'url' => $this->getUrl(), | |||||
| 'expiresAt' => $this->getExpiresAt(), | |||||
| ]; | |||||
| } | |||||
| private function getUrl() | |||||
| { | |||||
| return implode( | |||||
| "/", | |||||
| [ | |||||
| config("app.url"), | |||||
| 'register/user', | |||||
| $this->token | |||||
| ] | |||||
| ); | |||||
| } | |||||
| private function getExpiresAt() | |||||
| { | |||||
| $date = $this->expiresAt; | |||||
| if ($date !== null) { | |||||
| return $date->format('Y/m/d H:i'); | |||||
| } | |||||
| throw new Exception("有効期限日付不正"); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,15 @@ | |||||
| <?php | |||||
| namespace App\Mail\Guests; | |||||
| use App\Mail\BaseMailer; | |||||
| abstract class Guest extends BaseMailer | |||||
| { | |||||
| public function getParams(): array | |||||
| { | |||||
| return array_merge($this->getGuestParams(), []); | |||||
| } | |||||
| abstract public function getGuestParams(): array; | |||||
| } | |||||
| @@ -0,0 +1,27 @@ | |||||
| <?php | |||||
| namespace App\Mail\Members; | |||||
| use App\Mail\Common\AskConfirmation as CommonAskConfirmation; | |||||
| use App\Models\Parking; | |||||
| use App\Models\User; | |||||
| use App\Models\UserDetail; | |||||
| class AskConfirmation extends Member | |||||
| { | |||||
| use CommonAskConfirmation; | |||||
| public function __construct( | |||||
| array $data, | |||||
| User|null $user = null, | |||||
| UserDetail|null $userDetail = null, | |||||
| Parking|null $parking = null, | |||||
| ) { | |||||
| $this->setAskConfirmationData($data, $user, $userDetail, $parking); | |||||
| } | |||||
| public function getMemberParams(): array | |||||
| { | |||||
| return $this->getAskConfirmationParams(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,42 @@ | |||||
| <?php | |||||
| namespace App\Mail\Members; | |||||
| use App\Models\SeasonTicketContract; | |||||
| use App\Models\Parking; | |||||
| class AutoCancelSeasonTicketContract extends Member | |||||
| { | |||||
| protected string $parkName; | |||||
| protected int $seasonTicketSeqNo; | |||||
| /** | |||||
| * Create a new message instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct(Parking $parking, SeasonTicketContract $seasonTicketContract) | |||||
| { | |||||
| $this->setValues($parking->toArray()); | |||||
| $this->setValues($seasonTicketContract->toArray()); | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.members.auto_cancel_season_ticket_contract'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return '【スマートパーキングパス】駐車場利用停止のお知らせ'; | |||||
| } | |||||
| public function getMemberParams(): array | |||||
| { | |||||
| return [ | |||||
| 'parkName' => $this->parkName, | |||||
| 'seasonTicketSeqNo' => $this->seasonTicketSeqNo, | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,37 @@ | |||||
| <?php | |||||
| namespace App\Mail\Members; | |||||
| use Illuminate\Bus\Queueable; | |||||
| use Illuminate\Queue\SerializesModels; | |||||
| class Bulk extends Member | |||||
| { | |||||
| use Queueable, SerializesModels; | |||||
| private string $__subject; | |||||
| private string $__contents; | |||||
| public function __construct(string $subject, string $contents) | |||||
| { | |||||
| $this->__subject = $subject; | |||||
| $this->__contents = $contents; | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.members.bulk'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return $this->__subject; | |||||
| } | |||||
| public function getMemberParams(): array | |||||
| { | |||||
| return [ | |||||
| 'contents' => $this->__contents, | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,17 @@ | |||||
| <?php | |||||
| namespace App\Mail\Members; | |||||
| use App\Mail\BaseMailer; | |||||
| abstract class Member extends BaseMailer | |||||
| { | |||||
| public function getParams(): array | |||||
| { | |||||
| return array_merge($this->getMemberParams(), [ | |||||
| 'email' => $this->__email | |||||
| ]); | |||||
| } | |||||
| abstract public function getMemberParams(): array; | |||||
| } | |||||
| @@ -0,0 +1,42 @@ | |||||
| <?php | |||||
| namespace App\Mail\Members; | |||||
| use App\Exceptions\AppCommonException; | |||||
| class ResetIDm extends Member | |||||
| { | |||||
| private string $confirmationCode; | |||||
| private int $seasonTicketSeqNo; | |||||
| public function __construct() | |||||
| { | |||||
| $context = $this->context(); | |||||
| $seasonTicketContract = $context->getSeasonTicketContract(); | |||||
| if ($seasonTicketContract === null) { | |||||
| throw new AppCommonException("コンテキスト不正 定期契約情報"); | |||||
| } | |||||
| $this->confirmationCode = $seasonTicketContract->confirmation_code; | |||||
| $this->seasonTicketSeqNo = $seasonTicketContract->season_ticket_seq_no; | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.members.reset_idm'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return '【スマートパーキングパス】ICカードリセットのお知らせ'; | |||||
| } | |||||
| public function getMemberParams(): array | |||||
| { | |||||
| return [ | |||||
| 'confirmationCode' => $this->confirmationCode, | |||||
| 'seasonTicketSeqNo' => $this->seasonTicketSeqNo, | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,61 @@ | |||||
| <?php | |||||
| namespace App\Mail\Members; | |||||
| use App\Models\ResetPassword; | |||||
| use Illuminate\Support\Carbon; | |||||
| class ResetPasswordStart extends Member | |||||
| { | |||||
| protected string $token; | |||||
| protected Carbon $expiresAt; | |||||
| protected $casts = [ | |||||
| 'expiresAt' => 'datetime', | |||||
| ]; | |||||
| /** | |||||
| * Create a new message instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct(ResetPassword $model) | |||||
| { | |||||
| $this->setValues($model->toArray()); | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.members.reset_password_start'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return '【スマートパーキングパス】パスワードリセット手続きのご案内'; | |||||
| } | |||||
| public function getMemberParams(): array | |||||
| { | |||||
| return [ | |||||
| 'url' => $this->getUrl(), | |||||
| 'expiresAt' => $this->getExpiresAt(), | |||||
| ]; | |||||
| } | |||||
| private function getUrl() | |||||
| { | |||||
| return implode( | |||||
| "/", | |||||
| [ | |||||
| config("app.url"), | |||||
| 'password-reset', | |||||
| $this->token | |||||
| ] | |||||
| ); | |||||
| } | |||||
| private function getExpiresAt() | |||||
| { | |||||
| return $this->expiresAt->format('Y/m/d H:i'); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,45 @@ | |||||
| <?php | |||||
| namespace App\Mail\Members; | |||||
| use Illuminate\Support\Carbon; | |||||
| class SeasonTicketContractExpireRemind extends Member | |||||
| { | |||||
| protected string|null $parkName; | |||||
| protected int $seasonTicketSeqNo; | |||||
| protected Carbon $expirationEndDate; | |||||
| protected $casts = [ | |||||
| 'expirationEndDate' => 'datetime', | |||||
| ]; | |||||
| /** | |||||
| * Create a new message instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct(\stdClass $data) | |||||
| { | |||||
| $this->setValues($data); | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.members.season_ticket_contract_expires_remind'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return '【スマートパーキングパス】定期期限切れ予告通知'; | |||||
| } | |||||
| public function getMemberParams(): array | |||||
| { | |||||
| return [ | |||||
| 'parkName' => $this->parkName, | |||||
| 'seasonTicketSeqNo' => $this->seasonTicketSeqNo, | |||||
| 'expirationEndDate' => $this->expirationEndDate, | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,111 @@ | |||||
| <?php | |||||
| namespace App\Mail\Members\Subscription; | |||||
| use App\Codes\ParkingUseTypeCode; | |||||
| use App\Codes\VehicleTypeCode; | |||||
| use App\Mail\Members\Member; | |||||
| use App\Models\Parking; | |||||
| use App\Models\SeasonTicketContract; | |||||
| use App\Models\SeasonTicketContractSubscription; | |||||
| use App\Models\User; | |||||
| use Illuminate\Support\Carbon; | |||||
| use LogicException; | |||||
| class Approve extends Member | |||||
| { | |||||
| private string $email; | |||||
| private string $parkName; | |||||
| private Carbon|null $useStartRequestDate; | |||||
| private VehicleTypeCode $vehicleType; | |||||
| private string $contractorTypeName; | |||||
| private int $seasonTicketSeqNo; | |||||
| private int|null $confirmationCode; | |||||
| private ParkingUseTypeCode $parkingUseType; | |||||
| private string $customerCode; | |||||
| private string $parkingManagementCode; | |||||
| /** | |||||
| * Create a new message instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct( | |||||
| User $user, | |||||
| SeasonTicketContractSubscription|null $subscription, | |||||
| Parking $parking, | |||||
| SeasonTicketContract $seasonTicketContract, | |||||
| string $contractorTypeName | |||||
| ) { | |||||
| $this->email = $user->email; | |||||
| $this->parkName = $parking->park_name; | |||||
| $this->useStartRequestDate = $subscription ? $subscription->use_start_request_date : null; | |||||
| $this->vehicleType = $seasonTicketContract->vehicle_type; | |||||
| $this->contractorTypeName = $contractorTypeName; | |||||
| $this->seasonTicketSeqNo = $seasonTicketContract->season_ticket_seq_no; | |||||
| $this->confirmationCode = $seasonTicketContract->confirmation_code; | |||||
| $this->parkingUseType = $seasonTicketContract->parking_use_type; | |||||
| $this->customerCode = $seasonTicketContract->customer_code; | |||||
| $this->parkingManagementCode = $seasonTicketContract->parking_management_code; | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.members.subscription.approve'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return '【スマートパーキングパス】定期申し込み完了'; | |||||
| } | |||||
| public function getMemberParams(): array | |||||
| { | |||||
| return [ | |||||
| 'email' => $this->email, | |||||
| 'park_name' => $this->parkName, | |||||
| 'use_start_request_date' => $this->getUseStartRequestDate(), | |||||
| 'vehicle_type' => $this->getVehicleType(), | |||||
| 'contractor_type_name' => $this->contractorTypeName, | |||||
| 'how_to_use' => $this->getHowToUse(), | |||||
| 'season_ticket_seq_no' => $this->seasonTicketSeqNo, | |||||
| 'confirmation_code' => $this->confirmationCode, | |||||
| 'ic_card_rental_request' => $this->parkingUseType === ParkingUseTypeCode::IC_RENTAL, | |||||
| 'ic_self_card_request' => $this->parkingUseType === ParkingUseTypeCode::IC_SELF, | |||||
| 'ic_qr_code_request' => $this->parkingUseType === ParkingUseTypeCode::QR, | |||||
| 'my_qr_code_url' => $this->getMyQrCodeUrl(), | |||||
| ]; | |||||
| } | |||||
| private function getUseStartRequestDate() | |||||
| { | |||||
| if ($this->useStartRequestDate === null) return "-"; | |||||
| return $this->useStartRequestDate->format("Y年m月d日"); | |||||
| } | |||||
| private function getVehicleType() | |||||
| { | |||||
| return VehicleTypeCode::getName($this->vehicleType); | |||||
| } | |||||
| private function getHowToUse() | |||||
| { | |||||
| switch ($this->parkingUseType) { | |||||
| case ParkingUseTypeCode::IC_RENTAL: | |||||
| return "貸与ICカード"; | |||||
| case ParkingUseTypeCode::IC_SELF: | |||||
| return "個人ICカード"; | |||||
| case ParkingUseTypeCode::QR: | |||||
| return "QRコード"; | |||||
| } | |||||
| throw new LogicException(sprintf("不適切な駐車場利用方法 %d", $this->parkingUseType->value)); | |||||
| } | |||||
| private function getMyQrCodeUrl() | |||||
| { | |||||
| return $this->getAppUrl(['app', 'qrcode', 'detail', $this->customerCode, $this->parkingManagementCode]); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,45 @@ | |||||
| <?php | |||||
| namespace App\Mail\Members\Subscription; | |||||
| use App\Exceptions\AppCommonException; | |||||
| use App\Mail\Members\Member; | |||||
| class Cancel extends Member | |||||
| { | |||||
| private string $parkName; | |||||
| /** | |||||
| * Create a new message instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct() | |||||
| { | |||||
| $context = $this->context(); | |||||
| $parking = $context->getParking(); | |||||
| if ($parking === null) { | |||||
| throw new AppCommonException("コンテキスト不正 駐車場情報"); | |||||
| } | |||||
| $this->parkName = $parking->park_name; | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.members.subscription.cancel'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return '【スマートパーキングパス】申込キャンセルのお知らせ'; | |||||
| } | |||||
| public function getMemberParams(): array | |||||
| { | |||||
| return [ | |||||
| 'parkName' => $this->parkName, | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,70 @@ | |||||
| <?php | |||||
| namespace App\Mail\Members\Subscription; | |||||
| use App\Exceptions\AppCommonException; | |||||
| use App\Mail\Members\Member; | |||||
| use Illuminate\Support\Carbon; | |||||
| class Entry extends Member | |||||
| { | |||||
| private string $email; | |||||
| private string $parkName; | |||||
| private Carbon|null $useStartRequestDate; | |||||
| private string $memo; | |||||
| /** | |||||
| * Create a new message instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct() | |||||
| { | |||||
| $context = $this->context(); | |||||
| $user = $context->getUser(); | |||||
| $subscription = $context->getSeasonTicketContractSubscription(); | |||||
| $parking = $context->getParking(); | |||||
| if ($user === null) { | |||||
| throw new AppCommonException("コンテキスト不正 利用者情報"); | |||||
| } | |||||
| if ($subscription === null) { | |||||
| throw new AppCommonException("コンテキスト不正 申込情報"); | |||||
| } | |||||
| if ($parking === null) { | |||||
| throw new AppCommonException("コンテキスト不正 駐車場情報"); | |||||
| } | |||||
| $this->email = $user->email; | |||||
| $this->parkName = $parking->park_name; | |||||
| $this->useStartRequestDate = $subscription->use_start_request_date; | |||||
| $this->memo = $subscription->memo ?? ""; | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.members.subscription.entry'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return '【スマートパーキングパス】定期申し込み内容'; | |||||
| } | |||||
| public function getMemberParams(): array | |||||
| { | |||||
| return [ | |||||
| 'email' => $this->email, | |||||
| 'park_name' => $this->parkName, | |||||
| 'use_start_request_date' => $this->getUseStartRequestDate(), | |||||
| 'memo' => $this->memo | |||||
| ]; | |||||
| } | |||||
| public function getUseStartRequestDate() | |||||
| { | |||||
| if ($this->useStartRequestDate === null) return "-"; | |||||
| return $this->useStartRequestDate->format("Y年m月d日"); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,47 @@ | |||||
| <?php | |||||
| namespace App\Mail\Members\Subscription; | |||||
| use App\Mail\Members\Member; | |||||
| use App\Models\SeasonTicketContractSubscriptionMessage; | |||||
| class Hold extends Member | |||||
| { | |||||
| private string $parkName; | |||||
| private string|null $message; | |||||
| /** | |||||
| * Create a new message instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct(SeasonTicketContractSubscriptionMessage $message) | |||||
| { | |||||
| $context = $this->context(); | |||||
| $parking = $context->getParking(); | |||||
| if ($parking === null) { | |||||
| throw new AppCommonException("コンテキスト不正 駐車場情報"); | |||||
| } | |||||
| $this->parkName = $parking->park_name; | |||||
| $this->message = $message->message; | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.members.subscription.hold'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return '【スマートパーキングパス】申込確認のお知らせ'; | |||||
| } | |||||
| public function getMemberParams(): array | |||||
| { | |||||
| return [ | |||||
| 'parkName' => $this->parkName, | |||||
| 'memo' => $this->message, | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,47 @@ | |||||
| <?php | |||||
| namespace App\Mail\Members\Subscription; | |||||
| use App\Mail\Members\Member; | |||||
| use App\Models\SeasonTicketContractSubscriptionMessage; | |||||
| class Reject extends Member | |||||
| { | |||||
| private string $parkName; | |||||
| private string $message; | |||||
| /** | |||||
| * Create a new message instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct(SeasonTicketContractSubscriptionMessage $message) | |||||
| { | |||||
| $context = $this->context(); | |||||
| $parking = $context->getParking(); | |||||
| if ($parking === null) { | |||||
| throw new AppCommonException("コンテキスト不正 駐車場情報"); | |||||
| } | |||||
| $this->parkName = $parking->park_name; | |||||
| $this->message = $message->message ?? ""; | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.members.subscription.reject'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return '【スマートパーキングパス】申込却下のお知らせ'; | |||||
| } | |||||
| public function getMemberParams(): array | |||||
| { | |||||
| return [ | |||||
| 'parkName' => $this->parkName, | |||||
| 'memo' => $this->message, | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,48 @@ | |||||
| <?php | |||||
| namespace App\Mail\Members\Subscription; | |||||
| use App\Mail\Members\Member; | |||||
| use App\Models\SeasonTicketContractSubscriptionMessage; | |||||
| class Returned extends Member | |||||
| { | |||||
| private string $parkName; | |||||
| private string $message; | |||||
| /** | |||||
| * Create a new message instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct(SeasonTicketContractSubscriptionMessage $message) | |||||
| { | |||||
| $context = $this->context(); | |||||
| $parking = $context->getParking(); | |||||
| if ($parking === null) { | |||||
| throw new AppCommonException("コンテキスト不正 駐車場情報"); | |||||
| } | |||||
| $this->parkName = $parking->park_name; | |||||
| $this->message = $message->message ?? ""; | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.members.subscription.returned'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return '【スマートパーキングパス】申込差し戻しのお知らせ'; | |||||
| } | |||||
| public function getMemberParams(): array | |||||
| { | |||||
| return [ | |||||
| 'parkName' => $this->parkName, | |||||
| 'memo' => $this->message, | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,76 @@ | |||||
| <?php | |||||
| namespace App\Mail\Members; | |||||
| use App\Models\ResetPassword; | |||||
| use App\Models\User; | |||||
| use Illuminate\Support\Carbon; | |||||
| class UserRegisterComplete extends Member | |||||
| { | |||||
| private string $email; | |||||
| private bool $includePasswordReset = false; | |||||
| private Carbon|null $expiresAt = null; | |||||
| private string $token = ""; | |||||
| /** | |||||
| * Create a new message instance. | |||||
| * | |||||
| * @return void | |||||
| */ | |||||
| public function __construct(User $model, ResetPassword|null $password = null) | |||||
| { | |||||
| $this->email = $model->email; | |||||
| if ($password !== null) { | |||||
| $this->includePasswordReset = true; | |||||
| $this->expiresAt = $password->expires_at; | |||||
| $this->token = $password->token; | |||||
| } | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.members.user_register_complete'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return '【スマートパーキングパス】会員登録完了'; | |||||
| } | |||||
| public function getMemberParams(): array | |||||
| { | |||||
| return [ | |||||
| 'email' => $this->email, | |||||
| 'includePasswordReset' => $this->includePasswordReset, | |||||
| 'url' => $this->getUrl(), | |||||
| 'expiresAt' => $this->getExpiresAt(), | |||||
| ]; | |||||
| } | |||||
| private function getUrl() | |||||
| { | |||||
| return implode( | |||||
| "/", | |||||
| [ | |||||
| config("app.url"), | |||||
| 'password-reset', | |||||
| $this->token | |||||
| ] | |||||
| ); | |||||
| } | |||||
| private function getExpiresAt() | |||||
| { | |||||
| if ($this->expiresAt === null) { | |||||
| return ""; | |||||
| } else { | |||||
| return $this->expiresAt->format('Y/m/d H:i'); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,43 @@ | |||||
| <?php | |||||
| namespace App\Mail; | |||||
| use App\Middlewares\Now; | |||||
| use App\Models\Email; | |||||
| use App\Util\DateUtil; | |||||
| use Exception; | |||||
| use Illuminate\Support\Facades\Log; | |||||
| use Illuminate\Support\Facades\Mail; | |||||
| class Sender | |||||
| { | |||||
| public static function send(string $emailId) | |||||
| { | |||||
| $email = Email::findOrFail($emailId); | |||||
| info("メール送信", [ | |||||
| 'id' => $email->id, | |||||
| 'email' => $email->email, | |||||
| 'mailer' => $email->type, | |||||
| ]); | |||||
| try { | |||||
| Mail::to($email->email) | |||||
| ->send(new TextMail($email->subject, $email->content)); | |||||
| } catch (Exception $e) { | |||||
| Log::error("メール送信失敗", [ | |||||
| 'id' => $email->id, | |||||
| 'email' => $email->email, | |||||
| 'mailer' => $email->type, | |||||
| ]); | |||||
| $email->is_failed = true; | |||||
| $email->save(); | |||||
| throw $e; | |||||
| } | |||||
| $email->send_datetime = DateUtil::now(); | |||||
| $email->save(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,21 @@ | |||||
| <?php | |||||
| namespace App\Mail; | |||||
| class Test extends BaseMailer | |||||
| { | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.test'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return 'メールテスト'; | |||||
| } | |||||
| public function getParams(): array | |||||
| { | |||||
| return []; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,37 @@ | |||||
| <?php | |||||
| namespace App\Mail; | |||||
| use Illuminate\Bus\Queueable; | |||||
| use Illuminate\Queue\SerializesModels; | |||||
| class TextMail extends BaseMailer | |||||
| { | |||||
| use Queueable, SerializesModels; | |||||
| private string $__subject; | |||||
| private string $__contents; | |||||
| public function __construct(string $subject, string $contents) | |||||
| { | |||||
| $this->__subject = $subject; | |||||
| $this->__contents = $contents; | |||||
| } | |||||
| public function getTemplateName(): string | |||||
| { | |||||
| return 'mails.free_text'; | |||||
| } | |||||
| public function getSubject(): string | |||||
| { | |||||
| return $this->__subject; | |||||
| } | |||||
| public function getParams(): array | |||||
| { | |||||
| return [ | |||||
| 'contents' => $this->__contents, | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,22 @@ | |||||
| <?php | |||||
| namespace App\Models; | |||||
| use Illuminate\Database\Eloquent\Concerns\HasUuids; | |||||
| use Illuminate\Database\Eloquent\SoftDeletes; | |||||
| abstract class AppModel extends BaseModel | |||||
| { | |||||
| use SoftDeletes, HasUuids; | |||||
| public function getHistory(): ?HistoryModel | |||||
| { | |||||
| $historyName = static::class . 'History'; | |||||
| return new $historyName; | |||||
| } | |||||
| public function getChangeLogMessage($before, $after): ?string | |||||
| { | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,69 @@ | |||||
| <?php | |||||
| namespace App\Models; | |||||
| use App\Events\Model\CreatedEvent; | |||||
| use App\Events\Model\DeletedEvent; | |||||
| use App\Events\Model\UpdatingEvent; | |||||
| use App\Models\Feature\IModelFeature; | |||||
| use Illuminate\Database\Eloquent\Factories\HasFactory; | |||||
| use Illuminate\Database\Eloquent\Model; | |||||
| use Illuminate\Database\Query\Builder; | |||||
| use Illuminate\Support\Facades\DB; | |||||
| abstract class BaseModel extends Model implements IModelFeature | |||||
| { | |||||
| use HasFactory; | |||||
| const COL_NAME_ID = ColumnName::ID; | |||||
| const COL_NAME_CREATED_BY = ColumnName::CREATED_BY; | |||||
| const COL_NAME_UPDATED_BY = ColumnName::UPDATED_BY; | |||||
| const COL_NAME_CREATED_AT = ColumnName::CREATED_AT; | |||||
| const COL_NAME_UPDATED_AT = ColumnName::UPDATED_AT; | |||||
| const COL_NAME_DELETED_AT = ColumnName::DELETED_AT; | |||||
| protected $guarded = [ | |||||
| self::COL_NAME_ID, | |||||
| self::COL_NAME_CREATED_BY, | |||||
| self::COL_NAME_UPDATED_BY, | |||||
| self::COL_NAME_CREATED_AT, | |||||
| self::COL_NAME_UPDATED_AT, | |||||
| self::COL_NAME_DELETED_AT, | |||||
| ]; | |||||
| public static function getBuilder(string $name = 'main'): Builder | |||||
| { | |||||
| return DB::table(static::getTableName(), $name); | |||||
| } | |||||
| public static function getTableName(): string | |||||
| { | |||||
| return (new static)->getTable(); | |||||
| } | |||||
| public function copy(IModelFeature $from): static | |||||
| { | |||||
| $data = $from->getAttributeKeys(); | |||||
| foreach ($data as $key) { | |||||
| $this->$key = $from->$key; | |||||
| } | |||||
| return $this; | |||||
| } | |||||
| public function getAttributeKeys(): array | |||||
| { | |||||
| return array_values(array_unique(array_merge(array_keys($this->attributesToArray()), $this->hidden))); | |||||
| } | |||||
| public function isNotSavedModel(): bool | |||||
| { | |||||
| return data_get($this, ColumnName::ID) === null; | |||||
| } | |||||
| protected $dispatchesEvents = [ | |||||
| 'created' => CreatedEvent::class, | |||||
| 'updating' => UpdatingEvent::class, | |||||
| 'deleted' => DeletedEvent::class, | |||||
| ]; | |||||
| } | |||||
| @@ -0,0 +1,22 @@ | |||||
| <?php | |||||
| namespace App\Models; | |||||
| abstract class ColumnName | |||||
| { | |||||
| // 共通 | |||||
| const ID = 'id'; | |||||
| const UPDATED_AT = 'updated_at'; | |||||
| const UPDATED_BY = 'updated_by'; | |||||
| const CREATED_AT = 'created_at'; | |||||
| const CREATED_BY = 'created_by'; | |||||
| const DELETED_AT = 'deleted_at'; | |||||
| const HISTORY_ID = 'history_id'; | |||||
| // 業務 | |||||
| const CONTRACT_ID = 'contract_id'; | |||||
| const USER_ID = 'user_id'; | |||||
| const RECEIPT_ISSUING_ORDER_ID = "receipt_issuing_order_id"; | |||||
| const SMS_SEND_ORDER_ID = "sms_send_order_id"; | |||||
| const SMS_PROVIDER_ID = "sms_provider_id"; | |||||
| } | |||||
| @@ -0,0 +1,32 @@ | |||||
| <?php | |||||
| namespace App\Models; | |||||
| use Illuminate\Support\Str; | |||||
| class Contract extends AppModel | |||||
| { | |||||
| const COL_NAME_NAME = 'name'; | |||||
| const COL_NAME_CUSTOM = 'custom'; | |||||
| public function getModelName(): string | |||||
| { | |||||
| return "契約"; | |||||
| } | |||||
| public function includeCustom(string $target): bool | |||||
| { | |||||
| return in_array($target, $this->custom(), true); | |||||
| } | |||||
| public function custom(): array | |||||
| { | |||||
| $custom = data_get($this, self::COL_NAME_CUSTOM); | |||||
| if ($custom) { | |||||
| return explode(',', $custom); | |||||
| } else { | |||||
| return []; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,12 @@ | |||||
| <?php | |||||
| namespace App\Models; | |||||
| class ContractHistory extends HistoryModel | |||||
| { | |||||
| public function getModelName(): string | |||||
| { | |||||
| return "契約履歴"; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,12 @@ | |||||
| <?php | |||||
| namespace App\Models; | |||||
| class Email extends AppModel | |||||
| { | |||||
| public function getModelName(): string | |||||
| { | |||||
| return "Email"; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,12 @@ | |||||
| <?php | |||||
| namespace App\Models; | |||||
| class EmailHistory extends HistoryModel | |||||
| { | |||||
| public function getModelName(): string | |||||
| { | |||||
| return "Email履歴"; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,76 @@ | |||||
| <?php | |||||
| namespace App\Models\Ex; | |||||
| use App\Codes\UserRole; | |||||
| use App\Models\ColumnName; | |||||
| use App\Models\Contract; | |||||
| use App\Models\User; | |||||
| use Illuminate\Database\Eloquent\Model; | |||||
| use Illuminate\Support\Facades\Auth; | |||||
| use LogicException; | |||||
| class LoginUser | |||||
| { | |||||
| private const SESSION_KEY_SADMIN_CONTRACT_ID = 'SESSION_KEY_SADMIN_CONTRACT_ID'; | |||||
| public function __construct( | |||||
| private User $user, | |||||
| private Contract $contract | |||||
| ) { | |||||
| } | |||||
| public function user(): ?User | |||||
| { | |||||
| return Auth::user(); | |||||
| } | |||||
| public function contract(): ?Contract | |||||
| { | |||||
| if (!Auth::check()) { | |||||
| return null; | |||||
| } | |||||
| if ($this->contract->isNotSavedModel()) { | |||||
| $this->contract = $this->user()->contract; | |||||
| } | |||||
| return $this->contract; | |||||
| } | |||||
| public function checkAuthorization(array|Model $target): bool | |||||
| { | |||||
| if (!Auth::check()) { | |||||
| return false; | |||||
| } | |||||
| if ($this->user()->role === UserRole::SUPER_ADMIN) { | |||||
| return true; | |||||
| } | |||||
| $contractId = data_get($target, ColumnName::CONTRACT_ID); | |||||
| if ($contractId === null) { | |||||
| throw new LogicException("契約ID不正"); | |||||
| } | |||||
| return $contractId === $this->user()->contract_id; | |||||
| } | |||||
| public function getContractId(): ?string | |||||
| { | |||||
| if ($this->user()->role === UserRole::SUPER_ADMIN) { | |||||
| $session = request()->session(); | |||||
| if ($session->exists(self::SESSION_KEY_SADMIN_CONTRACT_ID)) { | |||||
| return $session->get(self::SESSION_KEY_SADMIN_CONTRACT_ID); | |||||
| } | |||||
| return $this->contract()->id; | |||||
| } | |||||
| return data_get($this->contract(), Contract::COL_NAME_ID); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,30 @@ | |||||
| <?php | |||||
| namespace App\Models\Feature; | |||||
| use App\Models\ColumnName; | |||||
| use App\Models\Contract; | |||||
| use Illuminate\Database\Eloquent\Model; | |||||
| use Illuminate\Database\Eloquent\Relations\BelongsTo; | |||||
| use LogicException; | |||||
| trait ContractFeature | |||||
| { | |||||
| const COL_NAME_CONTRACT_ID = ColumnName::CONTRACT_ID; | |||||
| public function setContract(Contract|string $contract): static | |||||
| { | |||||
| $id = is_string($contract) ? $contract : $contract->id; | |||||
| data_set($this, self::COL_NAME_CONTRACT_ID, $id); | |||||
| return $this; | |||||
| } | |||||
| public function contract(): BelongsTo | |||||
| { | |||||
| if ($this instanceof Model) { | |||||
| return $this->belongsTo(Contract::class); | |||||
| } else { | |||||
| throw new LogicException("不正"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,31 @@ | |||||
| <?php | |||||
| namespace App\Models\Feature; | |||||
| use App\Models\HistoryModel; | |||||
| use Illuminate\Database\Query\Builder; | |||||
| interface IModelFeature | |||||
| { | |||||
| public static function getBuilder(string $name = 'main'): Builder; | |||||
| public static function getTableName(): string; | |||||
| public function copy(IModelFeature $from): static; | |||||
| public function getAttributeKeys(): array; | |||||
| public function isNotSavedModel(): bool; | |||||
| public function getHistory(): HistoryModel|null; | |||||
| /** | |||||
| * モデルの和名を取得する | |||||
| * | |||||
| * @return string | |||||
| */ | |||||
| public function getModelName(): string; | |||||
| public function getChangeLogMessage($before, $after): string|null; | |||||
| } | |||||
| @@ -0,0 +1,30 @@ | |||||
| <?php | |||||
| namespace App\Models\Feature; | |||||
| use App\Models\ColumnName; | |||||
| use App\Models\ReceiptIssuingOrder; | |||||
| use Illuminate\Database\Eloquent\Model; | |||||
| use Illuminate\Database\Eloquent\Relations\BelongsTo; | |||||
| use LogicException; | |||||
| trait ReceiptIssuingOrderFeature | |||||
| { | |||||
| const COL_NAME_RECEIPT_ISSUING_ORDER_ID = ColumnName::RECEIPT_ISSUING_ORDER_ID; | |||||
| public function setReceiptIssuingOrder(ReceiptIssuingOrder|string $receiptIssuingOrder): static | |||||
| { | |||||
| $id = is_string($receiptIssuingOrder) ? $receiptIssuingOrder : $receiptIssuingOrder->id; | |||||
| data_set($this, self::COL_NAME_RECEIPT_ISSUING_ORDER_ID, $id); | |||||
| return $this; | |||||
| } | |||||
| public function receiptIssuingOrder(): BelongsTo | |||||
| { | |||||
| if ($this instanceof Model) { | |||||
| return $this->belongsTo(ReceiptIssuingOrder::class); | |||||
| } else { | |||||
| throw new LogicException("不正"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,30 @@ | |||||
| <?php | |||||
| namespace App\Models\Feature; | |||||
| use App\Models\ColumnName; | |||||
| use App\Models\SMSProvider; | |||||
| use Illuminate\Database\Eloquent\Model; | |||||
| use Illuminate\Database\Eloquent\Relations\BelongsTo; | |||||
| use LogicException; | |||||
| trait SMSProviderFeature | |||||
| { | |||||
| const COL_NAME_SMS_PROVIDER_ID = ColumnName::SMS_PROVIDER_ID; | |||||
| public function setSMSProvider(SMSProvider|string $smsProvider): static | |||||
| { | |||||
| $id = is_string($smsProvider) ? $smsProvider : $smsProvider->id; | |||||
| data_set($this, self::COL_NAME_SMS_PROVIDER_ID, $id); | |||||
| return $this; | |||||
| } | |||||
| public function smsProvider(): BelongsTo | |||||
| { | |||||
| if ($this instanceof Model) { | |||||
| return $this->belongsTo(SMSProvider::class); | |||||
| } else { | |||||
| throw new LogicException("不正"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,29 @@ | |||||
| <?php | |||||
| namespace App\Models\Feature; | |||||
| use App\Models\ColumnName; | |||||
| use App\Models\SMSSendOrder; | |||||
| use Illuminate\Database\Eloquent\Model; | |||||
| use Illuminate\Database\Eloquent\Relations\BelongsTo; | |||||
| use LogicException; | |||||
| trait SMSSendOrderFeature | |||||
| { | |||||
| const COL_NAME_SMS_SEND_ORDER_ID = ColumnName::SMS_SEND_ORDER_ID; | |||||
| public function setSMSSendOrder(SMSSendOrder|string $smsSendOrder) | |||||
| { | |||||
| $id = is_string($smsSendOrder) ? $smsSendOrder : $smsSendOrder->id; | |||||
| data_set($this, self::COL_NAME_SMS_SEND_ORDER_ID, $id); | |||||
| } | |||||
| public function smsSendOrder(): BelongsTo | |||||
| { | |||||
| if ($this instanceof Model) { | |||||
| return $this->belongsTo(SMSSendOrder::class); | |||||
| } else { | |||||
| throw new LogicException("不正"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,39 @@ | |||||
| <?php | |||||
| namespace App\Models; | |||||
| use App\Models\Feature\IModelFeature; | |||||
| use Illuminate\Database\Eloquent\Collection; | |||||
| abstract class HistoryModel extends BaseModel | |||||
| { | |||||
| const COL_NAME_HISTORY_ID = ColumnName::HISTORY_ID; | |||||
| protected $primaryKey = ColumnName::HISTORY_ID; | |||||
| /** | |||||
| * @param string $id | |||||
| * @return Collection<static> | |||||
| */ | |||||
| public static function findById(string $id) | |||||
| { | |||||
| return static::query()->where(ColumnName::ID, $id) | |||||
| ->orderBy(ColumnName::CREATED_AT) | |||||
| ->get(); | |||||
| } | |||||
| public function fillFromOrigin(IModelFeature $originModel) | |||||
| { | |||||
| return $this->copy($originModel); | |||||
| } | |||||
| public function getHistory(): ?HistoryModel | |||||
| { | |||||
| return null; | |||||
| } | |||||
| public function getChangeLogMessage($before, $after): ?string | |||||
| { | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,15 @@ | |||||
| <?php | |||||
| namespace App\Models; | |||||
| use App\Models\Feature\ReceiptIssuingOrderFeature; | |||||
| class ReceiptIssuingHTParkingCustomOrder extends AppModel | |||||
| { | |||||
| use ReceiptIssuingOrderFeature; | |||||
| public function getModelName(): string | |||||
| { | |||||
| return "領収証発行依頼(HT駐車場カスタム)"; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,12 @@ | |||||
| <?php | |||||
| namespace App\Models; | |||||
| class ReceiptIssuingHTParkingCustomOrderHistory extends HistoryModel | |||||
| { | |||||
| public function getModelName(): string | |||||
| { | |||||
| return "領収証発行依頼履歴(HT駐車場カスタム)"; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,47 @@ | |||||
| <?php | |||||
| namespace App\Models; | |||||
| use App\Codes\ReceiptIssuingOrderStatus; | |||||
| use App\Models\Feature\ContractFeature; | |||||
| class ReceiptIssuingOrder extends AppModel | |||||
| { | |||||
| use ContractFeature; | |||||
| const COL_NAME_HANDLER_ID = "handler_id"; | |||||
| const COL_NAME_ORDER_DATETIME = "order_datetime"; | |||||
| const COL_NAME_STATUS = "status"; | |||||
| const COL_NAME_SUMMARY_KEY1 = "sumamry_key1"; | |||||
| const COL_NAME_SUMMARY_KEY2 = "sumamry_key2"; | |||||
| const COL_NAME_ACCESS_TOKEN = "access_token"; | |||||
| const COL_NAME_ACCESS_TOKEN_EXPIRES_AT = "access_token_expires_at"; | |||||
| const COL_NAME_SMS_PHONE_NUMBER = "sms_phone_number"; | |||||
| const COL_NAME_SMS_SEND_SUCCESS = "sms_send_success"; | |||||
| const COL_NAME_RECEIPT_NO = "receipt_no"; | |||||
| const COL_NAME_RECEIPT_USE_DATETIME = "receipt_use_datetime"; | |||||
| const COL_NAME_RECEIPT_SHOP_NAME = "receipt_shop_name"; | |||||
| const COL_NAME_RECEIPT_ISSUER = "receipt_issuer"; | |||||
| const COL_NAME_RECEIPT_PURPOSE = "receipt_purpose"; | |||||
| const COL_NAME_RECEIPT_INVOICE_NO = "receipt_invoice_no"; | |||||
| const COL_NAME_RECEIPT_AMOUNT = "receipt_amount"; | |||||
| const COL_NAME_RECEIPT_HOW_TO_RECEIVE = "receipt_how_to_receive"; | |||||
| const COL_NAME_EMAIL = "email"; | |||||
| const COL_NAME_MAIL_PREF_CODE = "mail_pref_code"; | |||||
| const COL_NAME_MAIL_ZIP_CODE = "mail_zip_code"; | |||||
| const COL_NAME_MAIL_ADDRESS1 = "mail_address1"; | |||||
| const COL_NAME_MAIL_ADDRESS2 = "mail_address2"; | |||||
| const COL_NAME_MAIL_ADDRESS3 = "mail_address3"; | |||||
| const COL_NAME_MAIL_POST_DATE = "mail_post_date"; | |||||
| const COL_NAME_MEMO = "memo"; | |||||
| protected $casts = [ | |||||
| self::COL_NAME_STATUS => ReceiptIssuingOrderStatus::class, | |||||
| ]; | |||||
| public function getModelName(): string | |||||
| { | |||||
| return "領収証発行依頼"; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,12 @@ | |||||
| <?php | |||||
| namespace App\Models; | |||||
| class ReceiptIssuingOrderHistory extends HistoryModel | |||||
| { | |||||
| public function getModelName(): string | |||||
| { | |||||
| return "領収証発行依頼履歴"; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,15 @@ | |||||
| <?php | |||||
| namespace App\Models; | |||||
| class SMSProvider extends AppModel | |||||
| { | |||||
| const COL_NAME_PROVIDER_NAME = 'provider_name'; | |||||
| public function getModelName(): string | |||||
| { | |||||
| return "SMSプロバイダーマスタ"; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,23 @@ | |||||
| <?php | |||||
| namespace App\Models; | |||||
| use App\Codes\SMSProvicer; | |||||
| use App\Models\Feature\ContractFeature; | |||||
| use App\Models\Feature\SMSSendOrderFeature; | |||||
| use Illuminate\Database\Eloquent\Relations\BelongsTo; | |||||
| class SMSProviderFourSMessageCommunication extends AppModel | |||||
| { | |||||
| use ContractFeature, SMSSendOrderFeature; | |||||
| public function getModelName(): string | |||||
| { | |||||
| return "FourSMessage通信実績"; | |||||
| } | |||||
| public function getHistory(): ?HistoryModel | |||||
| { | |||||
| return null; | |||||
| } | |||||
| } | |||||