diff --git a/app/Models/Member/Concerns/HasNoTimestamps.php b/app/Models/Member/Concerns/HasNoTimestamps.php new file mode 100644 index 0000000..0a0bb12 --- /dev/null +++ b/app/Models/Member/Concerns/HasNoTimestamps.php @@ -0,0 +1,8 @@ +belongsTo(MemInfo::class, 'mem_no', 'mem_no'); + } +} diff --git a/app/Models/Member/MemAuth.php b/app/Models/Member/MemAuth.php new file mode 100644 index 0000000..1db2e0d --- /dev/null +++ b/app/Models/Member/MemAuth.php @@ -0,0 +1,38 @@ +belongsTo(MemInfo::class, 'mem_no', 'mem_no'); + } +} diff --git a/app/Models/Member/MemAuthInfo.php b/app/Models/Member/MemAuthInfo.php new file mode 100644 index 0000000..acd8db9 --- /dev/null +++ b/app/Models/Member/MemAuthInfo.php @@ -0,0 +1,28 @@ + 'array', + ]; + + public function member(): BelongsTo + { + return $this->belongsTo(MemInfo::class, 'mem_no', 'mem_no'); + } +} diff --git a/app/Models/Member/MemAuthLog.php b/app/Models/Member/MemAuthLog.php new file mode 100644 index 0000000..bd452d9 --- /dev/null +++ b/app/Models/Member/MemAuthLog.php @@ -0,0 +1,32 @@ + 'array', + ]; + + public const STATE_S = 'S'; // success + public const STATE_F = 'F'; // fail + public const STATE_P = 'P'; // pass/processing + + public function member(): BelongsTo + { + return $this->belongsTo(MemInfo::class, 'mem_no', 'mem_no'); + } +} diff --git a/app/Models/Member/MemInfo.php b/app/Models/Member/MemInfo.php new file mode 100644 index 0000000..6979e9f --- /dev/null +++ b/app/Models/Member/MemInfo.php @@ -0,0 +1,87 @@ + 'array', + 'modify_log' => 'array', + ]; + + /* ===================== + * Relationships + * ===================== */ + + public function authInfo(): HasOne + { + return $this->hasOne(MemAuthInfo::class, 'mem_no', 'mem_no'); + } + + public function authRows(): HasMany + { + // mem_auth 복합키 테이블이지만 조회 관계는 문제 없음 + return $this->hasMany(MemAuth::class, 'mem_no', 'mem_no'); + } + + public function authLogs(): HasMany + { + return $this->hasMany(MemAuthLog::class, 'mem_no', 'mem_no'); + } + + public function addresses(): HasMany + { + return $this->hasMany(MemAddress::class, 'mem_no', 'mem_no'); + } + + public function joinLogs(): HasMany + { + return $this->hasMany(MemJoinLog::class, 'mem_no', 'mem_no'); + } + + public function stRing(): HasOne + { + return $this->hasOne(MemStRing::class, 'mem_no', 'mem_no'); + } + + public function loginRecents(): HasMany + { + return $this->hasMany(MemLoginRecent::class, 'mem_no', 'mem_no'); + } + + public function modLogs(): HasMany + { + return $this->hasMany(MemModLog::class, 'mem_no', 'mem_no'); + } + + /* ===================== + * Helpers (optional) + * ===================== */ + + public function isWithdrawn(): bool + { + // legacy: dt_out 기본값이 0000-00-00... 이므로 문자열 비교로 처리 + return isset($this->attributes['dt_out']) && $this->attributes['dt_out'] !== '0000-00-00 00:00:00'; + } + + public function hasEmail(): bool + { + return !empty($this->attributes['email']); + } +} diff --git a/app/Models/Member/MemJoinFilter.php b/app/Models/Member/MemJoinFilter.php new file mode 100644 index 0000000..52d5d94 --- /dev/null +++ b/app/Models/Member/MemJoinFilter.php @@ -0,0 +1,22 @@ + 'array', + ]; +} diff --git a/app/Models/Member/MemJoinLog.php b/app/Models/Member/MemJoinLog.php new file mode 100644 index 0000000..8f342a7 --- /dev/null +++ b/app/Models/Member/MemJoinLog.php @@ -0,0 +1,24 @@ +belongsTo(MemInfo::class, 'mem_no', 'mem_no'); + } +} diff --git a/app/Models/Member/MemLoginRecent.php b/app/Models/Member/MemLoginRecent.php new file mode 100644 index 0000000..7424c90 --- /dev/null +++ b/app/Models/Member/MemLoginRecent.php @@ -0,0 +1,24 @@ +belongsTo(MemInfo::class, 'mem_no', 'mem_no'); + } +} diff --git a/app/Models/Member/MemLoginYear.php b/app/Models/Member/MemLoginYear.php new file mode 100644 index 0000000..58be580 --- /dev/null +++ b/app/Models/Member/MemLoginYear.php @@ -0,0 +1,27 @@ +forYear(2026)->create([...]) + */ +class MemLoginYear extends Model +{ + use HasNoTimestamps; + + protected $primaryKey = 'seq'; + public $incrementing = true; + protected $keyType = 'int'; + + protected $guarded = []; + + public function forYear(int $year): self + { + $this->setTable('mem_login_' . $year); + return $this; + } +} diff --git a/app/Models/Member/MemModLog.php b/app/Models/Member/MemModLog.php new file mode 100644 index 0000000..8789310 --- /dev/null +++ b/app/Models/Member/MemModLog.php @@ -0,0 +1,18 @@ + 'array', + ]; +} diff --git a/app/Models/Member/MemStRing.php b/app/Models/Member/MemStRing.php new file mode 100644 index 0000000..29563d0 --- /dev/null +++ b/app/Models/Member/MemStRing.php @@ -0,0 +1,24 @@ +belongsTo(MemInfo::class, 'mem_no', 'mem_no'); + } +} diff --git a/app/Repositories/Member/MemberAuthRepository.php b/app/Repositories/Member/MemberAuthRepository.php new file mode 100644 index 0000000..dd334e4 --- /dev/null +++ b/app/Repositories/Member/MemberAuthRepository.php @@ -0,0 +1,110 @@ +toDateString(); + + DB::table('mem_auth')->updateOrInsert( + ['mem_no' => $memNo, 'auth_type' => $authType], + ['auth_state' => $authState, 'auth_date' => $authDate] + ); + } + + public function markRequested(int $memNo, string $authType, array $logInfo = []): void + { + $this->setStateWithLog($memNo, $authType, MemAuth::STATE_R, MemAuthLog::STATE_P, $logInfo); + } + + public function markProcessing(int $memNo, string $authType, array $logInfo = []): void + { + $this->setStateWithLog($memNo, $authType, MemAuth::STATE_P, MemAuthLog::STATE_P, $logInfo); + } + + public function markSuccess(int $memNo, string $authType, array $logInfo = []): void + { + $this->setStateWithLog($memNo, $authType, MemAuth::STATE_Y, MemAuthLog::STATE_S, $logInfo); + } + + public function markFail(int $memNo, string $authType, array $logInfo = []): void + { + $this->setStateWithLog($memNo, $authType, MemAuth::STATE_N, MemAuthLog::STATE_F, $logInfo); + } + + /** + * mem_auth_info.auth_info JSON에 타입별로 병합 저장 + * - 예: ["email" => [...], "cell" => [...]] + */ + public function mergeAuthInfo(int $memNo, string $authType, array $payload): void + { + DB::transaction(function () use ($memNo, $authType, $payload) { + /** @var MemAuthInfo $row */ + $row = MemAuthInfo::query()->find($memNo); + + if (!$row) { + $row = new MemAuthInfo(); + $row->mem_no = $memNo; + $row->auth_info = []; + } + + $data = $row->auth_info ?: []; + $data[$authType] = array_merge($data[$authType] ?? [], $payload); + + $row->auth_info = $data; + $row->save(); + }); + } + + /** + * mem_auth 상태 변경 + mem_auth_log 기록을 한 트랜잭션으로 + */ + private function setStateWithLog( + int $memNo, + string $authType, + string $authState, + string $logState, + array $logInfo + ): void { + DB::transaction(function () use ($memNo, $authType, $authState, $logState, $logInfo) { + $this->upsertState($memNo, $authType, $authState); + + MemAuthLog::query()->create([ + 'mem_no' => $memNo, + 'type' => $authType, + 'state' => $logState, + 'info' => $logInfo, + 'rgdate' => Carbon::now()->toDateTimeString(), + ]); + }); + } + + public function getState(int $memNo, string $authType): ?string + { + return DB::table('mem_auth') + ->where('mem_no', $memNo) + ->where('auth_type', $authType) + ->value('auth_state'); + } + + public function isVerified(int $memNo, string $authType): bool + { + return $this->getState($memNo, $authType) === MemAuth::STATE_Y; + } +}