661 lines
25 KiB
PHP
661 lines
25 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Sales;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Sales\SalesCommission;
|
|
use App\Models\Sales\SalesPartner;
|
|
use App\Models\Sales\SalesScenarioChecklist;
|
|
use App\Models\Sales\SalesTenantManagement;
|
|
use App\Models\Sales\TenantProspect;
|
|
use App\Models\User;
|
|
use App\Services\SalesCommissionService;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Http\Response;
|
|
use Illuminate\View\View;
|
|
|
|
/**
|
|
* 관리자용 전체 영업파트너 고객 관리 컨트롤러
|
|
* 관리자/슈퍼관리자만 접근 가능
|
|
*/
|
|
class AdminProspectController extends Controller
|
|
{
|
|
/**
|
|
* 관리자 권한 체크
|
|
*/
|
|
private function checkAdminAccess(): void
|
|
{
|
|
if (! auth()->user()->isAdmin() && ! auth()->user()->isSuperAdmin()) {
|
|
abort(403, '관리자만 접근할 수 있습니다.');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 필드명에 따라 payment_type 결정 (1차→deposit, 2차→balance)
|
|
*/
|
|
private function getPaymentTypeForField(string $field): string
|
|
{
|
|
return in_array($field, ['second_payment_at', 'second_partner_paid_at'])
|
|
? SalesCommission::PAYMENT_BALANCE
|
|
: SalesCommission::PAYMENT_DEPOSIT;
|
|
}
|
|
|
|
/**
|
|
* deposit/balance 커미션 레코드를 병합하여 뷰용 객체 반환
|
|
*/
|
|
private function loadMergedCommission(?SalesTenantManagement $management): ?object
|
|
{
|
|
if (! $management) {
|
|
return null;
|
|
}
|
|
|
|
$commissions = SalesCommission::where('management_id', $management->id)->get();
|
|
if ($commissions->isEmpty()) {
|
|
return null;
|
|
}
|
|
|
|
$deposit = $commissions->firstWhere('payment_type', SalesCommission::PAYMENT_DEPOSIT);
|
|
$balance = $commissions->firstWhere('payment_type', SalesCommission::PAYMENT_BALANCE);
|
|
|
|
// balance 레코드가 없으면 기존 단일 레코드 그대로 반환 (하위호환)
|
|
if (! $balance) {
|
|
return $deposit ?? $commissions->first();
|
|
}
|
|
|
|
// 1차 필드는 deposit, 2차 필드는 balance에서 가져옴
|
|
$merged = new \stdClass;
|
|
$merged->first_payment_at = $deposit?->first_payment_at;
|
|
$merged->first_partner_paid_at = $deposit?->first_partner_paid_at;
|
|
$merged->second_payment_at = $balance->second_payment_at;
|
|
$merged->second_partner_paid_at = $balance->second_partner_paid_at;
|
|
$merged->first_subscription_at = $deposit?->first_subscription_at;
|
|
$merged->manager_paid_at = $deposit?->manager_paid_at;
|
|
$merged->referrer_commission = ($deposit?->referrer_commission ?? 0) + ($balance?->referrer_commission ?? 0);
|
|
|
|
return $merged;
|
|
}
|
|
|
|
/**
|
|
* 전체 고객 목록 페이지
|
|
*/
|
|
public function index(Request $request): View|Response
|
|
{
|
|
$this->checkAdminAccess();
|
|
if ($request->header('HX-Request')) {
|
|
return response('', 200)->header('HX-Redirect', route('sales.admin-prospects.index'));
|
|
}
|
|
|
|
$data = $this->getIndexData($request);
|
|
|
|
return view('sales.admin-prospects.index', $data);
|
|
}
|
|
|
|
/**
|
|
* 고객 상세 모달
|
|
*/
|
|
public function modalShow(int $id): View
|
|
{
|
|
$this->checkAdminAccess();
|
|
|
|
$prospect = TenantProspect::with(['registeredBy', 'tenant'])->findOrFail($id);
|
|
|
|
// 진행률
|
|
$progress = SalesScenarioChecklist::getProspectProgress($prospect->id);
|
|
$prospect->sales_progress = $progress['sales']['percentage'];
|
|
$prospect->manager_progress = $progress['manager']['percentage'];
|
|
|
|
// management 정보
|
|
$management = SalesTenantManagement::findOrCreateByProspect($prospect->id);
|
|
$management->load(['contractProducts.product', 'contractProducts.category']);
|
|
|
|
// 수당 정보
|
|
$commission = $this->loadMergedCommission($management);
|
|
|
|
// 수당 정산 전체 레코드 (상세보기용)
|
|
$commissions = SalesCommission::where('management_id', $management->id)
|
|
->with(['partner.user', 'manager'])
|
|
->get();
|
|
|
|
// 파트너 타입
|
|
$partnerType = $management->salesPartner?->partner_type;
|
|
if (! $partnerType && $prospect->registered_by) {
|
|
$partnerType = SalesPartner::where('user_id', $prospect->registered_by)->value('partner_type');
|
|
}
|
|
$partnerType = $partnerType ?? 'individual';
|
|
|
|
return view('sales.admin-prospects.partials.show-modal', compact('prospect', 'management', 'progress', 'commission', 'commissions', 'partnerType'));
|
|
}
|
|
|
|
/**
|
|
* 콘텐츠 새로고침 (HTMX)
|
|
*/
|
|
public function refresh(Request $request): View
|
|
{
|
|
$this->checkAdminAccess();
|
|
|
|
$data = $this->getIndexData($request);
|
|
|
|
return view('sales.admin-prospects.partials.content', $data);
|
|
}
|
|
|
|
/**
|
|
* index 데이터 조회 (공통)
|
|
*/
|
|
private function getIndexData(Request $request): array
|
|
{
|
|
// 영업 역할을 가진 사용자 목록 (영업파트너)
|
|
$salesPartners = User::whereHas('userRoles', function ($q) {
|
|
$q->whereHas('role', function ($rq) {
|
|
$rq->whereIn('name', ['sales', 'manager']);
|
|
});
|
|
})->orderBy('name')->get();
|
|
|
|
// 필터
|
|
$filters = [
|
|
'search' => $request->get('search'),
|
|
'status' => $request->get('status'),
|
|
'registered_by' => $request->get('registered_by'),
|
|
];
|
|
|
|
// 쿼리 빌드
|
|
$query = TenantProspect::with(['registeredBy', 'tenant']);
|
|
|
|
// 검색
|
|
if (! empty($filters['search'])) {
|
|
$search = $filters['search'];
|
|
$query->where(function ($q) use ($search) {
|
|
$q->where('company_name', 'like', "%{$search}%")
|
|
->orWhere('business_number', 'like', "%{$search}%")
|
|
->orWhere('ceo_name', 'like', "%{$search}%")
|
|
->orWhere('contact_phone', 'like', "%{$search}%");
|
|
});
|
|
}
|
|
|
|
// 상태 필터
|
|
$isProgressCompleteFilter = ($filters['status'] === 'progress_complete');
|
|
$isHandoverFilter = ($filters['status'] === 'handover');
|
|
if (! empty($filters['status']) && ! $isProgressCompleteFilter && ! $isHandoverFilter) {
|
|
$query->where('status', $filters['status']);
|
|
}
|
|
|
|
// 인계완료 필터: hq_status가 handover인 prospect만
|
|
if ($isHandoverFilter) {
|
|
$handoverProspectIds = SalesTenantManagement::where('hq_status', 'handover')->pluck('tenant_prospect_id');
|
|
$query->whereIn('id', $handoverProspectIds);
|
|
}
|
|
|
|
// 영업파트너 필터
|
|
if (! empty($filters['registered_by'])) {
|
|
$query->where('registered_by', $filters['registered_by']);
|
|
}
|
|
|
|
// progress_complete 필터: 전체 조회 후 PHP에서 필터링
|
|
if ($isProgressCompleteFilter) {
|
|
$allProspects = $query->orderByDesc('created_at')->get();
|
|
|
|
// 진행률 계산 및 부가정보 세팅
|
|
foreach ($allProspects as $prospect) {
|
|
$progress = SalesScenarioChecklist::getProspectProgress($prospect->id);
|
|
$prospect->sales_progress = $progress['sales']['percentage'];
|
|
$prospect->manager_progress = $progress['manager']['percentage'];
|
|
|
|
if ($progress['sales']['percentage'] === 100 && $progress['manager']['percentage'] === 100) {
|
|
SalesScenarioChecklist::checkAndConvertProspectStatus($prospect->id);
|
|
$prospect->refresh();
|
|
}
|
|
|
|
$management = SalesTenantManagement::where('tenant_prospect_id', $prospect->id)->first();
|
|
$prospect->hq_status = $management?->hq_status ?? 'pending';
|
|
$prospect->hq_status_label = $management?->hq_status_label ?? '대기';
|
|
$prospect->manager_user = $management?->manager;
|
|
$prospect->contracted_at = $management?->contracted_at;
|
|
$prospect->handover_at = $management?->handover_at;
|
|
|
|
$prospect->commission = $this->loadMergedCommission($management);
|
|
|
|
// 파트너 타입: management → registered_by 순으로 조회
|
|
$partnerType = $management?->salesPartner?->partner_type;
|
|
if (! $partnerType && $prospect->registered_by) {
|
|
$partnerType = SalesPartner::where('user_id', $prospect->registered_by)->value('partner_type');
|
|
}
|
|
$prospect->partner_type = $partnerType ?? 'individual';
|
|
}
|
|
|
|
// 두 시나리오 모두 100%인 것만 필터링
|
|
$filtered = $allProspects->filter(function ($prospect) {
|
|
return $prospect->sales_progress === 100 && $prospect->manager_progress === 100;
|
|
});
|
|
|
|
// 수동 페이지네이션
|
|
$page = request()->get('page', 1);
|
|
$perPage = 20;
|
|
$prospects = new \Illuminate\Pagination\LengthAwarePaginator(
|
|
$filtered->forPage($page, $perPage)->values(),
|
|
$filtered->count(),
|
|
$perPage,
|
|
$page,
|
|
['path' => request()->url(), 'query' => request()->query()]
|
|
);
|
|
} else {
|
|
$prospects = $query->orderByDesc('created_at')->paginate(20);
|
|
|
|
// 각 가망고객의 진행률 계산 및 상태 자동 전환
|
|
foreach ($prospects as $prospect) {
|
|
$progress = SalesScenarioChecklist::getProspectProgress($prospect->id);
|
|
$prospect->sales_progress = $progress['sales']['percentage'];
|
|
$prospect->manager_progress = $progress['manager']['percentage'];
|
|
|
|
// 진행률 100% 시 상태 자동 전환 체크
|
|
if ($progress['sales']['percentage'] === 100 && $progress['manager']['percentage'] === 100) {
|
|
SalesScenarioChecklist::checkAndConvertProspectStatus($prospect->id);
|
|
$prospect->refresh();
|
|
}
|
|
|
|
// management 정보
|
|
$management = SalesTenantManagement::where('tenant_prospect_id', $prospect->id)->first();
|
|
$prospect->hq_status = $management?->hq_status ?? 'pending';
|
|
$prospect->hq_status_label = $management?->hq_status_label ?? '대기';
|
|
$prospect->manager_user = $management?->manager;
|
|
$prospect->contracted_at = $management?->contracted_at;
|
|
$prospect->handover_at = $management?->handover_at;
|
|
|
|
// 수당 정보 (management가 있는 경우)
|
|
$prospect->commission = $this->loadMergedCommission($management);
|
|
|
|
// 파트너 타입: management → registered_by 순으로 조회
|
|
$partnerType = $management?->salesPartner?->partner_type;
|
|
if (! $partnerType && $prospect->registered_by) {
|
|
$partnerType = SalesPartner::where('user_id', $prospect->registered_by)->value('partner_type');
|
|
}
|
|
$prospect->partner_type = $partnerType ?? 'individual';
|
|
}
|
|
}
|
|
|
|
// 진행완료 건수 계산 (전체 prospect 중 두 시나리오 모두 100%인 건수)
|
|
$progressCompleteCount = 0;
|
|
$allForStats = TenantProspect::all();
|
|
foreach ($allForStats as $p) {
|
|
$prog = SalesScenarioChecklist::getProspectProgress($p->id);
|
|
if ($prog['sales']['percentage'] === 100 && $prog['manager']['percentage'] === 100) {
|
|
$progressCompleteCount++;
|
|
}
|
|
}
|
|
|
|
// 전체 통계
|
|
$stats = [
|
|
'total' => TenantProspect::count(),
|
|
'active' => TenantProspect::where('status', TenantProspect::STATUS_ACTIVE)->count(),
|
|
'completed' => TenantProspect::where('status', TenantProspect::STATUS_COMPLETED)->count(),
|
|
'handover' => SalesTenantManagement::where('hq_status', 'handover')->count(),
|
|
];
|
|
|
|
// 영업파트너별 통계
|
|
$partnerStats = TenantProspect::selectRaw('registered_by, COUNT(*) as total')
|
|
->groupBy('registered_by')
|
|
->with('registeredBy')
|
|
->get()
|
|
->map(function ($item) {
|
|
return [
|
|
'user' => $item->registeredBy,
|
|
'total' => $item->total,
|
|
];
|
|
});
|
|
|
|
$isSuperAdmin = auth()->user()->isSuperAdmin();
|
|
|
|
return compact('prospects', 'stats', 'salesPartners', 'partnerStats', 'filters', 'isSuperAdmin');
|
|
}
|
|
|
|
/**
|
|
* 개발 진행 상태 변경
|
|
*/
|
|
public function updateHqStatus(int $id, Request $request)
|
|
{
|
|
$this->checkAdminAccess();
|
|
|
|
$request->validate([
|
|
'hq_status' => 'required|in:'.implode(',', array_keys(SalesTenantManagement::$hqStatusLabels)),
|
|
]);
|
|
|
|
$prospect = TenantProspect::findOrFail($id);
|
|
$management = SalesTenantManagement::findOrCreateByProspect($prospect->id);
|
|
|
|
$newStatus = $request->input('hq_status');
|
|
$updateData = ['hq_status' => $newStatus];
|
|
|
|
// 인계로 변경 시 오늘 날짜 자동 세팅, 다른 상태로 변경 시 초기화
|
|
if ($newStatus === SalesTenantManagement::HQ_STATUS_HANDOVER) {
|
|
$updateData['handover_at'] = now();
|
|
} else {
|
|
$updateData['handover_at'] = null;
|
|
}
|
|
|
|
$management->update($updateData);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'hq_status' => $management->hq_status,
|
|
'hq_status_label' => $management->hq_status_label,
|
|
'handover_at' => $management->handover_at?->format('Y-m-d'),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 계약일 변경
|
|
*/
|
|
public function updateContractedDate(int $id, Request $request)
|
|
{
|
|
$this->checkAdminAccess();
|
|
|
|
$request->validate([
|
|
'contracted_at' => 'nullable|date',
|
|
]);
|
|
|
|
$prospect = TenantProspect::findOrFail($id);
|
|
$management = SalesTenantManagement::findOrCreateByProspect($prospect->id);
|
|
|
|
$management->update([
|
|
'contracted_at' => $request->input('contracted_at') ?: null,
|
|
]);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'contracted_at' => $management->contracted_at?->format('Y-m-d'),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 인계일 수동 변경
|
|
*/
|
|
public function updateHandoverDate(int $id, Request $request)
|
|
{
|
|
$this->checkAdminAccess();
|
|
|
|
$request->validate([
|
|
'handover_at' => 'required|date',
|
|
]);
|
|
|
|
$prospect = TenantProspect::findOrFail($id);
|
|
$management = SalesTenantManagement::findOrCreateByProspect($prospect->id);
|
|
|
|
$management->update([
|
|
'handover_at' => $request->input('handover_at'),
|
|
]);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'handover_at' => $management->handover_at?->format('Y-m-d'),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 수당 날짜 기록/수정
|
|
*/
|
|
public function updateCommissionDate(int $id, Request $request)
|
|
{
|
|
$this->checkAdminAccess();
|
|
|
|
$request->validate([
|
|
'field' => 'required|in:first_payment_at,first_partner_paid_at,second_payment_at,second_partner_paid_at,first_subscription_at,manager_paid_at',
|
|
'date' => 'nullable|date',
|
|
]);
|
|
|
|
$prospect = TenantProspect::findOrFail($id);
|
|
$management = SalesTenantManagement::findOrCreateByProspect($prospect->id);
|
|
|
|
$field = $request->input('field');
|
|
|
|
// 1차 필드 → deposit 레코드, 2차 필드 → balance 레코드
|
|
$paymentType = $this->getPaymentTypeForField($field);
|
|
|
|
// 파트너 resolve → 요율 결정
|
|
$partner = $management->salesPartner;
|
|
if (! $partner && $prospect->registered_by) {
|
|
$partner = SalesPartner::where('user_id', $prospect->registered_by)->first();
|
|
}
|
|
$isGroup = $partner?->isGroup() ?? false;
|
|
$partnerRate = $partner?->commission_rate
|
|
?? ($isGroup ? SalesCommissionService::DEFAULT_GROUP_RATE : SalesCommissionService::DEFAULT_PARTNER_RATE);
|
|
$referrerRate = $isGroup
|
|
? SalesCommissionService::DEFAULT_GROUP_REFERRER_RATE
|
|
: SalesCommissionService::DEFAULT_INDIVIDUAL_REFERRER_RATE;
|
|
|
|
// Commission 레코드 조회 또는 생성 (payment_type별 분리)
|
|
$commission = SalesCommission::firstOrCreate(
|
|
['management_id' => $management->id, 'payment_type' => $paymentType],
|
|
[
|
|
'tenant_id' => $prospect->tenant_id ?? 1,
|
|
'payment_amount' => 0,
|
|
'payment_date' => now(),
|
|
'base_amount' => 0,
|
|
'partner_rate' => $partnerRate,
|
|
'manager_rate' => 0,
|
|
'partner_commission' => 0,
|
|
'manager_commission' => 0,
|
|
'referrer_rate' => $referrerRate,
|
|
'referrer_commission' => 0,
|
|
'scheduled_payment_date' => now()->addMonth()->day(10),
|
|
'status' => SalesCommission::STATUS_PENDING,
|
|
'partner_id' => $partner?->id ?? $management->sales_partner_id ?? 0,
|
|
'manager_user_id' => $management->manager_user_id,
|
|
]
|
|
);
|
|
$date = $request->input('date') ?: now()->format('Y-m-d');
|
|
|
|
// 수당지급일 필드는 개발상태가 '인계'일 때만 저장 가능
|
|
$paidFields = ['first_partner_paid_at', 'second_partner_paid_at', 'manager_paid_at'];
|
|
if (in_array($field, $paidFields) && $management->hq_status !== 'handover') {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '개발상태가 인계일 때만 수당이 지급됩니다.',
|
|
], 422);
|
|
}
|
|
|
|
$updateData = [$field => $date];
|
|
|
|
// 납입일 입력 시 수당지급일 자동 계산 (익월 10일) - 인계 상태일 때만
|
|
$autoFields = [
|
|
'first_payment_at' => 'first_partner_paid_at',
|
|
'second_payment_at' => 'second_partner_paid_at',
|
|
];
|
|
|
|
$autoField = null;
|
|
$autoDate = null;
|
|
if (isset($autoFields[$field]) && $management->hq_status === 'handover') {
|
|
$autoField = $autoFields[$field];
|
|
$autoDate = \Carbon\Carbon::parse($date)->addMonth()->day(10)->format('Y-m-d');
|
|
$updateData[$autoField] = $autoDate;
|
|
}
|
|
|
|
// 납입일 변경 시 지급예정일 + 입금일(payment_date)도 함께 업데이트
|
|
if (in_array($field, ['first_payment_at', 'second_payment_at'])) {
|
|
$updateData['scheduled_payment_date'] = \Carbon\Carbon::parse($date)->addMonth()->day(10)->format('Y-m-d');
|
|
$updateData['payment_date'] = $date;
|
|
}
|
|
|
|
$commission->update($updateData);
|
|
|
|
$response = [
|
|
'success' => true,
|
|
'field' => $field,
|
|
'date' => $commission->$field?->format('Y-m-d'),
|
|
'date_display' => $commission->$field?->format('m/d'),
|
|
];
|
|
|
|
if ($autoField) {
|
|
$response['auto_field'] = $autoField;
|
|
$response['auto_date'] = $autoDate;
|
|
}
|
|
|
|
return response()->json($response);
|
|
}
|
|
|
|
/**
|
|
* 상태 토글 (영업중 ↔ 완료)
|
|
*/
|
|
public function toggleStatus(int $id)
|
|
{
|
|
$this->checkAdminAccess();
|
|
|
|
$prospect = TenantProspect::findOrFail($id);
|
|
|
|
if ($prospect->status === TenantProspect::STATUS_ACTIVE) {
|
|
$prospect->update(['status' => TenantProspect::STATUS_COMPLETED]);
|
|
} elseif ($prospect->status === TenantProspect::STATUS_COMPLETED) {
|
|
$prospect->update(['status' => TenantProspect::STATUS_ACTIVE]);
|
|
} else {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '영업중 또는 완료 상태만 변경할 수 있습니다.',
|
|
], 422);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'status' => $prospect->status,
|
|
'status_label' => $prospect->status_label,
|
|
'status_color' => $prospect->status_color,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 가망고객 삭제 (슈퍼관리자 전용)
|
|
*/
|
|
public function destroy(int $id)
|
|
{
|
|
$prospect = TenantProspect::findOrFail($id);
|
|
|
|
// 연관 데이터 삭제
|
|
$management = SalesTenantManagement::where('tenant_prospect_id', $prospect->id)->first();
|
|
if ($management) {
|
|
SalesCommission::where('management_id', $management->id)->delete();
|
|
$management->delete();
|
|
}
|
|
SalesScenarioChecklist::where('tenant_prospect_id', $prospect->id)->delete();
|
|
|
|
$prospect->delete();
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => "'{$prospect->company_name}' 가망고객이 삭제되었습니다.",
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 협업지원금(referrer_commission) 금액 수정
|
|
*/
|
|
public function updateReferrerCommission(int $id, Request $request)
|
|
{
|
|
$this->checkAdminAccess();
|
|
|
|
$request->validate([
|
|
'amount' => 'required|numeric|min:0',
|
|
]);
|
|
|
|
$prospect = TenantProspect::findOrFail($id);
|
|
$management = SalesTenantManagement::findOrCreateByProspect($prospect->id);
|
|
|
|
// 단체 파트너는 수동 수정 불가
|
|
$partner = $management->salesPartner;
|
|
if (! $partner && $prospect->registered_by) {
|
|
$partner = SalesPartner::where('user_id', $prospect->registered_by)->first();
|
|
}
|
|
if ($partner && $partner->isGroup()) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => '단체 파트너는 협업지원금을 수동 변경할 수 없습니다.',
|
|
], 422);
|
|
}
|
|
|
|
$isGroup = $partner?->isGroup() ?? false;
|
|
$partnerRate = $partner?->commission_rate
|
|
?? ($isGroup ? SalesCommissionService::DEFAULT_GROUP_RATE : SalesCommissionService::DEFAULT_PARTNER_RATE);
|
|
|
|
// Commission 레코드 조회 또는 생성
|
|
$commission = SalesCommission::firstOrCreate(
|
|
['management_id' => $management->id],
|
|
[
|
|
'tenant_id' => $prospect->tenant_id ?? 1,
|
|
'payment_type' => 'deposit',
|
|
'payment_amount' => 0,
|
|
'payment_date' => now(),
|
|
'base_amount' => 0,
|
|
'partner_rate' => $partnerRate,
|
|
'manager_rate' => 0,
|
|
'partner_commission' => 0,
|
|
'manager_commission' => 0,
|
|
'referrer_rate' => $isGroup
|
|
? SalesCommissionService::DEFAULT_GROUP_REFERRER_RATE
|
|
: SalesCommissionService::DEFAULT_INDIVIDUAL_REFERRER_RATE,
|
|
'referrer_commission' => 0,
|
|
'scheduled_payment_date' => now()->addMonth()->day(10),
|
|
'status' => SalesCommission::STATUS_PENDING,
|
|
'partner_id' => $partner?->id ?? $management->sales_partner_id ?? 0,
|
|
'manager_user_id' => $management->manager_user_id,
|
|
]
|
|
);
|
|
|
|
$commission->update([
|
|
'referrer_commission' => $request->input('amount'),
|
|
]);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'amount' => (int) $commission->referrer_commission,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 수당 날짜 삭제 (초기화)
|
|
*/
|
|
public function clearCommissionDate(int $id, Request $request)
|
|
{
|
|
$this->checkAdminAccess();
|
|
|
|
$request->validate([
|
|
'field' => 'required|in:first_payment_at,first_partner_paid_at,second_payment_at,second_partner_paid_at,first_subscription_at,manager_paid_at',
|
|
]);
|
|
|
|
$prospect = TenantProspect::findOrFail($id);
|
|
$management = SalesTenantManagement::where('tenant_prospect_id', $prospect->id)->first();
|
|
|
|
if (! $management) {
|
|
return response()->json(['success' => false, 'message' => '관리 정보가 없습니다.']);
|
|
}
|
|
|
|
$field = $request->input('field');
|
|
|
|
// 1차 필드 → deposit 레코드, 2차 필드 → balance 레코드
|
|
$paymentType = $this->getPaymentTypeForField($field);
|
|
|
|
$commission = SalesCommission::where('management_id', $management->id)
|
|
->where('payment_type', $paymentType)
|
|
->first();
|
|
|
|
if (! $commission) {
|
|
return response()->json(['success' => false, 'message' => '수당 정보가 없습니다.']);
|
|
}
|
|
$updateData = [$field => null];
|
|
|
|
// 납입일 삭제 시 수당지급일도 함께 초기화
|
|
$autoFields = [
|
|
'first_payment_at' => 'first_partner_paid_at',
|
|
'second_payment_at' => 'second_partner_paid_at',
|
|
];
|
|
|
|
$autoField = null;
|
|
if (isset($autoFields[$field])) {
|
|
$autoField = $autoFields[$field];
|
|
$updateData[$autoField] = null;
|
|
}
|
|
|
|
$commission->update($updateData);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'field' => $field,
|
|
'auto_field' => $autoField,
|
|
]);
|
|
}
|
|
}
|