Files
sam-manage/app/Models/Sales/SalesTenantManagement.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

204 lines
5.4 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;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
* 테넌트별 영업 관리 모델 (tenants 외래키 연결)
*
* @property int $id
* @property int $tenant_id
* @property int|null $sales_partner_id
* @property int|null $manager_user_id
* @property int $sales_scenario_step
* @property int $manager_scenario_step
* @property string $status
* @property \Carbon\Carbon|null $first_contact_at
* @property \Carbon\Carbon|null $contracted_at
* @property \Carbon\Carbon|null $onboarding_completed_at
* @property float|null $membership_fee
* @property \Carbon\Carbon|null $membership_paid_at
* @property string|null $membership_status
* @property float|null $sales_commission
* @property float|null $manager_commission
* @property \Carbon\Carbon|null $commission_paid_at
* @property string|null $commission_status
* @property int $sales_progress
* @property int $manager_progress
* @property string|null $notes
*/
class SalesTenantManagement extends Model
{
use SoftDeletes;
protected $table = 'sales_tenant_managements';
protected $fillable = [
'tenant_id',
'sales_partner_id',
'manager_user_id',
'sales_scenario_step',
'manager_scenario_step',
'status',
'first_contact_at',
'contracted_at',
'onboarding_completed_at',
'membership_fee',
'membership_paid_at',
'membership_status',
'sales_commission',
'manager_commission',
'commission_paid_at',
'commission_status',
'sales_progress',
'manager_progress',
'notes',
];
protected $casts = [
'sales_scenario_step' => 'integer',
'manager_scenario_step' => 'integer',
'membership_fee' => 'decimal:2',
'sales_commission' => 'decimal:2',
'manager_commission' => 'decimal:2',
'sales_progress' => 'integer',
'manager_progress' => 'integer',
'first_contact_at' => 'datetime',
'contracted_at' => 'datetime',
'onboarding_completed_at' => 'datetime',
'membership_paid_at' => 'datetime',
'commission_paid_at' => 'datetime',
];
/**
* 상태 상수
*/
const STATUS_PROSPECT = 'prospect';
const STATUS_APPROACH = 'approach';
const STATUS_NEGOTIATION = 'negotiation';
const STATUS_CONTRACTED = 'contracted';
const STATUS_ONBOARDING = 'onboarding';
const STATUS_ACTIVE = 'active';
const STATUS_CHURNED = 'churned';
/**
* 상태 라벨
*/
public static array $statusLabels = [
self::STATUS_PROSPECT => '잠재 고객',
self::STATUS_APPROACH => '접근 중',
self::STATUS_NEGOTIATION => '협상 중',
self::STATUS_CONTRACTED => '계약 완료',
self::STATUS_ONBOARDING => '온보딩 중',
self::STATUS_ACTIVE => '활성 고객',
self::STATUS_CHURNED => '이탈',
];
/**
* 테넌트 관계
*/
public function tenant(): BelongsTo
{
return $this->belongsTo(Tenant::class);
}
/**
* 영업 담당자 관계
*/
public function salesPartner(): BelongsTo
{
return $this->belongsTo(SalesPartner::class, 'sales_partner_id');
}
/**
* 관리 매니저 관계
*/
public function manager(): BelongsTo
{
return $this->belongsTo(User::class, 'manager_user_id');
}
/**
* 체크리스트 관계
*/
public function checklists(): HasMany
{
return $this->hasMany(SalesScenarioChecklist::class, 'tenant_id', 'tenant_id');
}
/**
* 상담 기록 관계
*/
public function consultations(): HasMany
{
return $this->hasMany(SalesConsultation::class, 'tenant_id', 'tenant_id');
}
/**
* 테넌트 ID로 조회 또는 생성
*/
public static function findOrCreateByTenant(int $tenantId): self
{
return self::firstOrCreate(
['tenant_id' => $tenantId],
[
'status' => self::STATUS_PROSPECT,
'sales_scenario_step' => 1,
'manager_scenario_step' => 1,
]
);
}
/**
* 진행률 업데이트
*/
public function updateProgress(string $scenarioType, int $progress): void
{
$field = $scenarioType === 'sales' ? 'sales_progress' : 'manager_progress';
$this->update([$field => $progress]);
}
/**
* 현재 단계 업데이트
*/
public function updateStep(string $scenarioType, int $step): void
{
$field = $scenarioType === 'sales' ? 'sales_scenario_step' : 'manager_scenario_step';
$this->update([$field => $step]);
}
/**
* 상태 라벨 Accessor
*/
public function getStatusLabelAttribute(): string
{
return self::$statusLabels[$this->status] ?? $this->status;
}
/**
* 특정 상태 스코프
*/
public function scopeByStatus($query, string $status)
{
return $query->where('status', $status);
}
/**
* 계약 완료 스코프
*/
public function scopeContracted($query)
{
return $query->whereIn('status', [
self::STATUS_CONTRACTED,
self::STATUS_ONBOARDING,
self::STATUS_ACTIVE,
]);
}
}