ultimatepos/Modules/Crm/Services/CallSessionCompletionService.php

138 lines
5.4 KiB
PHP

<?php
namespace Modules\Crm\Services;
use App\User;
use Modules\Crm\Entities\CrmCallAssessment;
use Modules\Crm\Entities\CrmCallSession;
use Modules\Crm\Entities\CrmCompanyOffer;
use Modules\Crm\Entities\CrmPhoneFollowUp;
use Modules\Crm\Entities\CrmPhoneFollowUpLog;
class CallSessionCompletionService
{
public function __construct(
protected CallQueueService $callQueueService,
protected CompanyProfileService $companyProfileService,
protected LeadScoringService $leadScoringService,
protected TelemarketingWorkflowService $workflowService,
protected OfferMatchingService $offerMatchingService,
protected CallSentimentService $sentimentService
) {
}
public function complete(int $session_id, int $user_id, int $business_id, array $data): array
{
$session = $this->callQueueService->endSession($session_id, $user_id, $data['outcome'] ?? null);
if (empty($session)) {
return ['success' => false, 'msg' => __('messages.something_went_wrong')];
}
$phone = CrmPhoneFollowUp::where('business_id', $business_id)->findOrFail($session->phone_follow_up_id);
$company = $this->companyProfileService->findOrCreateForPhone($phone, $user_id);
if (! empty($data['company'])) {
$company->update($data['company']);
$this->companyProfileService->calculateCompletion($company->fresh());
}
if (! empty($data['new_contact'])) {
$company->contacts()->create($data['new_contact']);
$this->companyProfileService->calculateCompletion($company->fresh());
}
if (! empty($data['new_requirement']) && ! empty($data['new_requirement']['item_name'])) {
$company->requirements()->create($data['new_requirement']);
$this->companyProfileService->calculateCompletion($company->fresh());
}
if (! empty($data['offer_ids']) && is_array($data['offer_ids'])) {
foreach ($data['offer_ids'] as $offerId) {
if (empty($offerId)) {
continue;
}
CrmCompanyOffer::create([
'company_id' => $company->id,
'offer_catalog_id' => $offerId,
'call_session_id' => $session->id,
'status' => 'draft',
'sent_via' => 'manual',
'sent_by' => $user_id,
'sent_at' => now(),
]);
}
}
$status = $data['status'] ?? 'contacted';
$outcome = $data['outcome'] ?? '';
if ($outcome === 'no_answer' || $outcome === 'busy') {
$status = 'no_answer';
} elseif ($outcome === 'wrong_number') {
$status = 'not_interested';
} elseif ($outcome === 'answered' && ($data['cooperation_score'] ?? 0) >= 4) {
$status = 'interested';
} elseif ($outcome === 'callback') {
$status = 'contacted';
}
CrmPhoneFollowUpLog::create([
'phone_follow_up_id' => $phone->id,
'status' => $status,
'note' => $data['note'] ?? null,
'created_by' => $user_id,
'call_log_id' => $session->call_log_id,
]);
$phone->update([
'status' => $phone->status === 'converted' ? 'converted' : $status,
'last_follow_up_at' => now(),
'follow_up_count' => $phone->follow_up_count + 1,
]);
$objections = $data['objections'] ?? [];
if (is_string($objections)) {
$objections = json_decode($objections, true) ?: [];
}
$assessment = null;
if (! empty($data['reception_score'])) {
$assessment = CrmCallAssessment::create([
'call_session_id' => $session->id,
'phone_follow_up_id' => $phone->id,
'company_contact_id' => $data['company_contact_id'] ?? null,
'reception_score' => $data['reception_score'],
'tone_score' => $data['tone_score'] ?? null,
'cooperation_score' => $data['cooperation_score'] ?? null,
'decision_maker_reached' => ! empty($data['decision_maker_reached']),
'gatekeeper_blocked' => ! empty($data['gatekeeper_blocked']),
'sentiment' => $data['sentiment'] ?? 'neutral',
'objections' => $objections,
'best_call_time' => $data['best_call_time'] ?? null,
'partner_potential' => $data['partner_potential'] ?? 'none',
'notes' => $data['assessment_notes'] ?? null,
'assessed_by' => $user_id,
]);
$score = $this->leadScoringService->calculateFromAssessment($assessment, $company);
$this->leadScoringService->applyScore($phone, $score, $company);
$this->leadScoringService->handleFlags($assessment, $phone);
$user = User::find($user_id);
if ($user) {
$this->workflowService->afterAssessment($assessment, $phone, $company, $user);
}
}
$matchedOffers = $this->offerMatchingService->matchForCompany($company, $assessment);
return [
'success' => true,
'msg' => __('crm::lang.session_completed'),
'session' => $session,
'matched_offers' => $matchedOffers,
'lead_score' => $phone->fresh()->lead_score,
];
}
}