107 lines
3.9 KiB
PHP
107 lines
3.9 KiB
PHP
<?php
|
|
|
|
namespace Modules\Crm\Services;
|
|
|
|
use Modules\Crm\Entities\CrmCallAssessment;
|
|
use Modules\Crm\Entities\CrmCompany;
|
|
use Modules\Crm\Entities\CrmCompanyContact;
|
|
use Modules\Crm\Entities\CrmOfferCatalog;
|
|
|
|
class OfferMatchingService
|
|
{
|
|
public function matchForCompany(CrmCompany $company, ?CrmCallAssessment $assessment = null): array
|
|
{
|
|
$catalog = CrmOfferCatalog::where('business_id', $company->business_id)
|
|
->where('is_active', true)
|
|
->get();
|
|
|
|
$cooperation = (int) ($assessment->cooperation_score ?? 0);
|
|
$reception = (int) ($assessment->reception_score ?? 0);
|
|
$requirements = $company->requirements()->get();
|
|
$contacts = $company->contacts()->get();
|
|
|
|
$matched = [];
|
|
|
|
foreach ($catalog as $offer) {
|
|
if ($cooperation < ($offer->min_cooperation_score ?? 1)) {
|
|
continue;
|
|
}
|
|
|
|
if (! empty($offer->target_industries) && ! in_array($company->industry_category_id, $offer->target_industries)) {
|
|
continue;
|
|
}
|
|
|
|
$signals = $offer->required_signals ?? [];
|
|
if (! $this->signalsMatch($signals, $company, $requirements, $contacts, $assessment)) {
|
|
continue;
|
|
}
|
|
|
|
$matched[] = $offer;
|
|
}
|
|
|
|
if (empty($matched)) {
|
|
$matched = $this->defaultOffers($company, $contacts, $cooperation, $reception);
|
|
}
|
|
|
|
return $matched;
|
|
}
|
|
|
|
protected function signalsMatch(array $signals, CrmCompany $company, $requirements, $contacts, ?CrmCallAssessment $assessment): bool
|
|
{
|
|
if (empty($signals)) {
|
|
return true;
|
|
}
|
|
|
|
foreach ($signals as $signal) {
|
|
switch ($signal) {
|
|
case 'technical_service_needed':
|
|
if ($requirements->where('requirement_type', 'technical_service')->isEmpty()) {
|
|
return false;
|
|
}
|
|
break;
|
|
case 'raw_material_match':
|
|
if ($requirements->where('requirement_type', 'raw_material')->isEmpty()) {
|
|
return false;
|
|
}
|
|
break;
|
|
case 'partner_potential':
|
|
$hasPartner = $contacts->where('is_potential_partner', true)->isNotEmpty()
|
|
|| ($assessment && in_array($assessment->partner_potential, ['medium', 'high']));
|
|
if (! $hasPartner) {
|
|
return false;
|
|
}
|
|
break;
|
|
case 'training_needed':
|
|
if ($requirements->where('requirement_type', 'training')->isEmpty()) {
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
protected function defaultOffers(CrmCompany $company, $contacts, int $cooperation, int $reception): array
|
|
{
|
|
$suggestions = [];
|
|
|
|
if ($cooperation >= 3 && $company->requirements()->where('requirement_type', 'technical_service')->exists()) {
|
|
$suggestions[] = (object) ['id' => null, 'name' => __('crm::lang.suggest_annual_service'), 'offer_type' => 'technical_service', 'description' => ''];
|
|
}
|
|
|
|
$partner = $contacts->first(function (CrmCompanyContact $c) use ($reception) {
|
|
return $c->is_potential_partner && $reception >= 4;
|
|
});
|
|
if ($partner) {
|
|
$suggestions[] = (object) ['id' => null, 'name' => __('crm::lang.suggest_regional_agency'), 'offer_type' => 'partnership', 'description' => ''];
|
|
}
|
|
|
|
if ($company->requirements()->where('requirement_type', 'raw_material')->exists()) {
|
|
$suggestions[] = (object) ['id' => null, 'name' => __('crm::lang.suggest_raw_material_quote'), 'offer_type' => 'spare_parts', 'description' => ''];
|
|
}
|
|
|
|
return $suggestions;
|
|
}
|
|
}
|