138 lines
5.4 KiB
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,
|
|
];
|
|
}
|
|
}
|