feat: Phase 8.3 회사 추가 API 구현
- 사업자등록번호 유효성 검사 API (바로빌 연동) - 회사 추가 신청/승인/반려 워크플로우 - 신청 승인 시 테넌트 자동 생성 및 사용자 연결 - 관리자용 신청 목록/상세 조회 - 사용자용 내 신청 목록 조회 - Swagger 문서 및 i18n 메시지 추가
This commit is contained in:
237
app/Models/CompanyRequest.php
Normal file
237
app/Models/CompanyRequest.php
Normal file
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Members\User;
|
||||
use App\Models\Tenants\Tenant;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* 회사 추가 신청 모델
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $user_id 신청자 ID
|
||||
* @property string $business_number 사업자등록번호
|
||||
* @property string $company_name 회사명
|
||||
* @property string|null $ceo_name 대표자명
|
||||
* @property string|null $address 주소
|
||||
* @property string|null $phone 전화번호
|
||||
* @property string|null $email 이메일
|
||||
* @property string $status 상태 (pending, approved, rejected)
|
||||
* @property string|null $message 신청 메시지
|
||||
* @property string|null $reject_reason 반려 사유
|
||||
* @property array|null $barobill_response 바로빌 검증 응답
|
||||
* @property int|null $approved_by 승인/반려 처리자
|
||||
* @property int|null $created_tenant_id 생성된 테넌트 ID
|
||||
* @property \Carbon\Carbon|null $processed_at 처리일시
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
*/
|
||||
class CompanyRequest extends Model
|
||||
{
|
||||
// =========================================================================
|
||||
// 상수 정의
|
||||
// =========================================================================
|
||||
|
||||
/** 상태 */
|
||||
public const STATUS_PENDING = 'pending';
|
||||
|
||||
public const STATUS_APPROVED = 'approved';
|
||||
|
||||
public const STATUS_REJECTED = 'rejected';
|
||||
|
||||
public const STATUSES = [
|
||||
self::STATUS_PENDING,
|
||||
self::STATUS_APPROVED,
|
||||
self::STATUS_REJECTED,
|
||||
];
|
||||
|
||||
/** 상태 라벨 */
|
||||
public const STATUS_LABELS = [
|
||||
self::STATUS_PENDING => '대기중',
|
||||
self::STATUS_APPROVED => '승인',
|
||||
self::STATUS_REJECTED => '반려',
|
||||
];
|
||||
|
||||
// =========================================================================
|
||||
// 모델 설정
|
||||
// =========================================================================
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'business_number',
|
||||
'company_name',
|
||||
'ceo_name',
|
||||
'address',
|
||||
'phone',
|
||||
'email',
|
||||
'status',
|
||||
'message',
|
||||
'reject_reason',
|
||||
'barobill_response',
|
||||
'approved_by',
|
||||
'created_tenant_id',
|
||||
'processed_at',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'barobill_response' => 'array',
|
||||
'processed_at' => 'datetime',
|
||||
];
|
||||
|
||||
protected $attributes = [
|
||||
'status' => self::STATUS_PENDING,
|
||||
];
|
||||
|
||||
// =========================================================================
|
||||
// 관계
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 신청자
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 처리자 (승인/반려)
|
||||
*/
|
||||
public function approver(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'approved_by');
|
||||
}
|
||||
|
||||
/**
|
||||
* 생성된 테넌트
|
||||
*/
|
||||
public function createdTenant(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Tenant::class, 'created_tenant_id');
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 스코프
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 대기중인 신청만
|
||||
*/
|
||||
public function scopePending($query)
|
||||
{
|
||||
return $query->where('status', self::STATUS_PENDING);
|
||||
}
|
||||
|
||||
/**
|
||||
* 승인된 신청만
|
||||
*/
|
||||
public function scopeApproved($query)
|
||||
{
|
||||
return $query->where('status', self::STATUS_APPROVED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 반려된 신청만
|
||||
*/
|
||||
public function scopeRejected($query)
|
||||
{
|
||||
return $query->where('status', self::STATUS_REJECTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 상태 필터
|
||||
*/
|
||||
public function scopeOfStatus($query, string $status)
|
||||
{
|
||||
return $query->where('status', $status);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 접근자
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 상태 라벨
|
||||
*/
|
||||
public function getStatusLabelAttribute(): string
|
||||
{
|
||||
return self::STATUS_LABELS[$this->status] ?? $this->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 대기중 여부
|
||||
*/
|
||||
public function getIsPendingAttribute(): bool
|
||||
{
|
||||
return $this->status === self::STATUS_PENDING;
|
||||
}
|
||||
|
||||
/**
|
||||
* 승인됨 여부
|
||||
*/
|
||||
public function getIsApprovedAttribute(): bool
|
||||
{
|
||||
return $this->status === self::STATUS_APPROVED;
|
||||
}
|
||||
|
||||
/**
|
||||
* 반려됨 여부
|
||||
*/
|
||||
public function getIsRejectedAttribute(): bool
|
||||
{
|
||||
return $this->status === self::STATUS_REJECTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* 사업자등록번호 포맷 (하이픈 포함)
|
||||
*/
|
||||
public function getFormattedBusinessNumberAttribute(): string
|
||||
{
|
||||
$num = preg_replace('/[^0-9]/', '', $this->business_number);
|
||||
if (strlen($num) === 10) {
|
||||
return substr($num, 0, 3).'-'.substr($num, 3, 2).'-'.substr($num, 5, 5);
|
||||
}
|
||||
|
||||
return $this->business_number;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 헬퍼 메서드
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 승인 처리
|
||||
*/
|
||||
public function approve(int $approverId, int $tenantId): bool
|
||||
{
|
||||
if (! $this->is_pending) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->status = self::STATUS_APPROVED;
|
||||
$this->approved_by = $approverId;
|
||||
$this->created_tenant_id = $tenantId;
|
||||
$this->processed_at = now();
|
||||
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* 반려 처리
|
||||
*/
|
||||
public function reject(int $approverId, ?string $reason = null): bool
|
||||
{
|
||||
if (! $this->is_pending) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->status = self::STATUS_REJECTED;
|
||||
$this->approved_by = $approverId;
|
||||
$this->reject_reason = $reason;
|
||||
$this->processed_at = now();
|
||||
|
||||
return $this->save();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user