Files
sam-manage/app/Models/Sales/SalesScenarioChecklist.php
pro 329c58e63b refactor:영업관리 데이터를 DB 테이블로 변경
- 모델 추가: SalesPartner, SalesTenantManagement, SalesScenarioChecklist, SalesConsultation
- 모델 위치 이동: app/Models/ → app/Models/Sales/
- 컨트롤러 수정: 캐시 대신 DB 모델 사용
- 뷰 수정: Eloquent 모델 속성 사용

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 06:42:32 +09:00

169 lines
4.5 KiB
PHP

<?php
namespace App\Models\Sales;
use App\Models\Tenants\Tenant;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* 영업 시나리오 체크리스트 모델
*
* @property int $id
* @property int $tenant_id
* @property string $scenario_type (sales/manager)
* @property int $step_id
* @property string|null $checkpoint_id
* @property int|null $checkpoint_index
* @property bool $is_checked
* @property \Carbon\Carbon|null $checked_at
* @property int|null $checked_by
* @property string|null $memo
*/
class SalesScenarioChecklist extends Model
{
protected $table = 'sales_scenario_checklists';
protected $fillable = [
'tenant_id',
'scenario_type',
'step_id',
'checkpoint_id',
'checkpoint_index',
'is_checked',
'checked_at',
'checked_by',
'memo',
'user_id', // 하위 호환성
];
protected $casts = [
'step_id' => 'integer',
'checkpoint_index' => 'integer',
'is_checked' => 'boolean',
'checked_at' => 'datetime',
];
/**
* 테넌트 관계
*/
public function tenant(): BelongsTo
{
return $this->belongsTo(Tenant::class);
}
/**
* 체크한 사용자 관계
*/
public function checkedByUser(): BelongsTo
{
return $this->belongsTo(User::class, 'checked_by');
}
/**
* 사용자 관계 (하위 호환성)
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
/**
* 체크포인트 토글
*/
public static function toggle(int $tenantId, string $scenarioType, int $stepId, string $checkpointId, bool $checked, ?int $userId = null): self
{
$checklist = self::firstOrNew([
'tenant_id' => $tenantId,
'scenario_type' => $scenarioType,
'step_id' => $stepId,
'checkpoint_id' => $checkpointId,
]);
$checklist->is_checked = $checked;
$checklist->checked_at = $checked ? now() : null;
$checklist->checked_by = $checked ? ($userId ?? auth()->id()) : null;
$checklist->save();
return $checklist;
}
/**
* 특정 테넌트/시나리오의 체크리스트 조회
*/
public static function getChecklist(int $tenantId, string $scenarioType): array
{
$items = self::where('tenant_id', $tenantId)
->where('scenario_type', $scenarioType)
->where('is_checked', true)
->get();
$result = [];
foreach ($items as $item) {
$key = "{$item->step_id}_{$item->checkpoint_id}";
$result[$key] = [
'checked_at' => $item->checked_at?->toDateTimeString(),
'checked_by' => $item->checked_by,
];
}
return $result;
}
/**
* 진행률 계산
*/
public static function calculateProgress(int $tenantId, string $scenarioType, array $steps): array
{
$checklist = self::getChecklist($tenantId, $scenarioType);
$totalCheckpoints = 0;
$completedCheckpoints = 0;
$stepProgress = [];
foreach ($steps as $step) {
$stepCompleted = 0;
$stepTotal = count($step['checkpoints'] ?? []);
$totalCheckpoints += $stepTotal;
foreach ($step['checkpoints'] as $checkpoint) {
$key = "{$step['id']}_{$checkpoint['id']}";
if (isset($checklist[$key])) {
$completedCheckpoints++;
$stepCompleted++;
}
}
$stepProgress[$step['id']] = [
'total' => $stepTotal,
'completed' => $stepCompleted,
'percentage' => $stepTotal > 0 ? round(($stepCompleted / $stepTotal) * 100) : 0,
];
}
return [
'total' => $totalCheckpoints,
'completed' => $completedCheckpoints,
'percentage' => $totalCheckpoints > 0 ? round(($completedCheckpoints / $totalCheckpoints) * 100) : 0,
'steps' => $stepProgress,
];
}
/**
* 시나리오 타입 스코프
*/
public function scopeByScenarioType($query, string $type)
{
return $query->where('scenario_type', $type);
}
/**
* 체크된 항목만 스코프
*/
public function scopeChecked($query)
{
return $query->where('is_checked', true);
}
}