feat: [approval] 결재관리 Phase 1 MVP 구현
- 모델 4개: Approval, ApprovalStep, ApprovalForm, ApprovalLine
- ApprovalService: 목록/CRUD/워크플로우(상신/승인/반려/회수) 비즈니스 로직
- ApprovalApiController: JSON API 엔드포인트 (기안함/결재함/완료함/참조함)
- ApprovalController: Blade 뷰 컨트롤러 (HX-Redirect 처리)
- 뷰 8개: drafts, pending, completed, references, create, edit, show
- partials: _status-badge, _step-progress, _approval-line-editor
- api.php/web.php 라우트 등록
2026-02-27 23:17:17 +09:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Models\Approvals;
|
|
|
|
|
|
|
|
|
|
use App\Models\User;
|
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
|
|
|
|
|
|
|
|
class ApprovalStep extends Model
|
|
|
|
|
{
|
|
|
|
|
protected $table = 'approval_steps';
|
|
|
|
|
|
|
|
|
|
protected $casts = [
|
|
|
|
|
'step_order' => 'integer',
|
2026-02-27 23:41:49 +09:00
|
|
|
'parallel_group' => 'integer',
|
feat: [approval] 결재관리 Phase 1 MVP 구현
- 모델 4개: Approval, ApprovalStep, ApprovalForm, ApprovalLine
- ApprovalService: 목록/CRUD/워크플로우(상신/승인/반려/회수) 비즈니스 로직
- ApprovalApiController: JSON API 엔드포인트 (기안함/결재함/완료함/참조함)
- ApprovalController: Blade 뷰 컨트롤러 (HX-Redirect 처리)
- 뷰 8개: drafts, pending, completed, references, create, edit, show
- partials: _status-badge, _step-progress, _approval-line-editor
- api.php/web.php 라우트 등록
2026-02-27 23:17:17 +09:00
|
|
|
'acted_at' => 'datetime',
|
|
|
|
|
'is_read' => 'boolean',
|
|
|
|
|
'read_at' => 'datetime',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
protected $fillable = [
|
|
|
|
|
'approval_id',
|
|
|
|
|
'step_order',
|
|
|
|
|
'step_type',
|
2026-02-27 23:41:49 +09:00
|
|
|
'parallel_group',
|
feat: [approval] 결재관리 Phase 1 MVP 구현
- 모델 4개: Approval, ApprovalStep, ApprovalForm, ApprovalLine
- ApprovalService: 목록/CRUD/워크플로우(상신/승인/반려/회수) 비즈니스 로직
- ApprovalApiController: JSON API 엔드포인트 (기안함/결재함/완료함/참조함)
- ApprovalController: Blade 뷰 컨트롤러 (HX-Redirect 처리)
- 뷰 8개: drafts, pending, completed, references, create, edit, show
- partials: _status-badge, _step-progress, _approval-line-editor
- api.php/web.php 라우트 등록
2026-02-27 23:17:17 +09:00
|
|
|
'approver_id',
|
2026-02-27 23:41:49 +09:00
|
|
|
'acted_by',
|
feat: [approval] 결재관리 Phase 1 MVP 구현
- 모델 4개: Approval, ApprovalStep, ApprovalForm, ApprovalLine
- ApprovalService: 목록/CRUD/워크플로우(상신/승인/반려/회수) 비즈니스 로직
- ApprovalApiController: JSON API 엔드포인트 (기안함/결재함/완료함/참조함)
- ApprovalController: Blade 뷰 컨트롤러 (HX-Redirect 처리)
- 뷰 8개: drafts, pending, completed, references, create, edit, show
- partials: _status-badge, _step-progress, _approval-line-editor
- api.php/web.php 라우트 등록
2026-02-27 23:17:17 +09:00
|
|
|
'approver_name',
|
|
|
|
|
'approver_department',
|
|
|
|
|
'approver_position',
|
|
|
|
|
'status',
|
2026-02-27 23:41:49 +09:00
|
|
|
'approval_type',
|
feat: [approval] 결재관리 Phase 1 MVP 구현
- 모델 4개: Approval, ApprovalStep, ApprovalForm, ApprovalLine
- ApprovalService: 목록/CRUD/워크플로우(상신/승인/반려/회수) 비즈니스 로직
- ApprovalApiController: JSON API 엔드포인트 (기안함/결재함/완료함/참조함)
- ApprovalController: Blade 뷰 컨트롤러 (HX-Redirect 처리)
- 뷰 8개: drafts, pending, completed, references, create, edit, show
- partials: _status-badge, _step-progress, _approval-line-editor
- api.php/web.php 라우트 등록
2026-02-27 23:17:17 +09:00
|
|
|
'comment',
|
|
|
|
|
'acted_at',
|
|
|
|
|
'is_read',
|
|
|
|
|
'read_at',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
protected $attributes = [
|
|
|
|
|
'status' => 'pending',
|
|
|
|
|
'is_read' => false,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// =========================================================================
|
|
|
|
|
// 상태 상수
|
|
|
|
|
// =========================================================================
|
|
|
|
|
|
|
|
|
|
public const STATUS_PENDING = 'pending';
|
|
|
|
|
|
|
|
|
|
public const STATUS_APPROVED = 'approved';
|
|
|
|
|
|
|
|
|
|
public const STATUS_REJECTED = 'rejected';
|
|
|
|
|
|
|
|
|
|
public const STATUS_SKIPPED = 'skipped';
|
|
|
|
|
|
2026-02-27 23:41:49 +09:00
|
|
|
public const STATUS_ON_HOLD = 'on_hold';
|
|
|
|
|
|
feat: [approval] 결재관리 Phase 1 MVP 구현
- 모델 4개: Approval, ApprovalStep, ApprovalForm, ApprovalLine
- ApprovalService: 목록/CRUD/워크플로우(상신/승인/반려/회수) 비즈니스 로직
- ApprovalApiController: JSON API 엔드포인트 (기안함/결재함/완료함/참조함)
- ApprovalController: Blade 뷰 컨트롤러 (HX-Redirect 처리)
- 뷰 8개: drafts, pending, completed, references, create, edit, show
- partials: _status-badge, _step-progress, _approval-line-editor
- api.php/web.php 라우트 등록
2026-02-27 23:17:17 +09:00
|
|
|
public const STATUSES = [
|
|
|
|
|
self::STATUS_PENDING,
|
|
|
|
|
self::STATUS_APPROVED,
|
|
|
|
|
self::STATUS_REJECTED,
|
|
|
|
|
self::STATUS_SKIPPED,
|
2026-02-27 23:41:49 +09:00
|
|
|
self::STATUS_ON_HOLD,
|
feat: [approval] 결재관리 Phase 1 MVP 구현
- 모델 4개: Approval, ApprovalStep, ApprovalForm, ApprovalLine
- ApprovalService: 목록/CRUD/워크플로우(상신/승인/반려/회수) 비즈니스 로직
- ApprovalApiController: JSON API 엔드포인트 (기안함/결재함/완료함/참조함)
- ApprovalController: Blade 뷰 컨트롤러 (HX-Redirect 처리)
- 뷰 8개: drafts, pending, completed, references, create, edit, show
- partials: _status-badge, _step-progress, _approval-line-editor
- api.php/web.php 라우트 등록
2026-02-27 23:17:17 +09:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// =========================================================================
|
|
|
|
|
// 관계 정의
|
|
|
|
|
// =========================================================================
|
|
|
|
|
|
|
|
|
|
public function approval(): BelongsTo
|
|
|
|
|
{
|
|
|
|
|
return $this->belongsTo(Approval::class, 'approval_id');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function approver(): BelongsTo
|
|
|
|
|
{
|
|
|
|
|
return $this->belongsTo(User::class, 'approver_id');
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-27 23:41:49 +09:00
|
|
|
public function actedBy(): BelongsTo
|
|
|
|
|
{
|
|
|
|
|
return $this->belongsTo(User::class, 'acted_by');
|
|
|
|
|
}
|
|
|
|
|
|
feat: [approval] 결재관리 Phase 1 MVP 구현
- 모델 4개: Approval, ApprovalStep, ApprovalForm, ApprovalLine
- ApprovalService: 목록/CRUD/워크플로우(상신/승인/반려/회수) 비즈니스 로직
- ApprovalApiController: JSON API 엔드포인트 (기안함/결재함/완료함/참조함)
- ApprovalController: Blade 뷰 컨트롤러 (HX-Redirect 처리)
- 뷰 8개: drafts, pending, completed, references, create, edit, show
- partials: _status-badge, _step-progress, _approval-line-editor
- api.php/web.php 라우트 등록
2026-02-27 23:17:17 +09:00
|
|
|
// =========================================================================
|
|
|
|
|
// 스코프
|
|
|
|
|
// =========================================================================
|
|
|
|
|
|
|
|
|
|
public function scopePending($query)
|
|
|
|
|
{
|
|
|
|
|
return $query->where('status', self::STATUS_PENDING);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function scopeApproved($query)
|
|
|
|
|
{
|
|
|
|
|
return $query->where('status', self::STATUS_APPROVED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function scopeByApprover($query, int $userId)
|
|
|
|
|
{
|
|
|
|
|
return $query->where('approver_id', $userId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function scopeApprovalOnly($query)
|
|
|
|
|
{
|
|
|
|
|
return $query->whereIn('step_type', [ApprovalLine::STEP_TYPE_APPROVAL, ApprovalLine::STEP_TYPE_AGREEMENT]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function scopeReferenceOnly($query)
|
|
|
|
|
{
|
|
|
|
|
return $query->where('step_type', ApprovalLine::STEP_TYPE_REFERENCE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// =========================================================================
|
|
|
|
|
// 헬퍼 메서드
|
|
|
|
|
// =========================================================================
|
|
|
|
|
|
|
|
|
|
public function isActionable(): bool
|
|
|
|
|
{
|
|
|
|
|
return $this->status === self::STATUS_PENDING
|
|
|
|
|
&& in_array($this->step_type, [ApprovalLine::STEP_TYPE_APPROVAL, ApprovalLine::STEP_TYPE_AGREEMENT]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function isReference(): bool
|
|
|
|
|
{
|
|
|
|
|
return $this->step_type === ApprovalLine::STEP_TYPE_REFERENCE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getStatusLabelAttribute(): string
|
|
|
|
|
{
|
|
|
|
|
return match ($this->status) {
|
|
|
|
|
self::STATUS_PENDING => '대기',
|
|
|
|
|
self::STATUS_APPROVED => '승인',
|
|
|
|
|
self::STATUS_REJECTED => '반려',
|
|
|
|
|
self::STATUS_SKIPPED => '건너뜀',
|
2026-02-27 23:41:49 +09:00
|
|
|
self::STATUS_ON_HOLD => '보류',
|
feat: [approval] 결재관리 Phase 1 MVP 구현
- 모델 4개: Approval, ApprovalStep, ApprovalForm, ApprovalLine
- ApprovalService: 목록/CRUD/워크플로우(상신/승인/반려/회수) 비즈니스 로직
- ApprovalApiController: JSON API 엔드포인트 (기안함/결재함/완료함/참조함)
- ApprovalController: Blade 뷰 컨트롤러 (HX-Redirect 처리)
- 뷰 8개: drafts, pending, completed, references, create, edit, show
- partials: _status-badge, _step-progress, _approval-line-editor
- api.php/web.php 라우트 등록
2026-02-27 23:17:17 +09:00
|
|
|
default => $this->status,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getStepTypeLabelAttribute(): string
|
|
|
|
|
{
|
|
|
|
|
return match ($this->step_type) {
|
|
|
|
|
ApprovalLine::STEP_TYPE_APPROVAL => '결재',
|
|
|
|
|
ApprovalLine::STEP_TYPE_AGREEMENT => '합의',
|
|
|
|
|
ApprovalLine::STEP_TYPE_REFERENCE => '참조',
|
|
|
|
|
default => $this->step_type,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|