ultimatepos/Modules/AssetExchange/Services/AssetExchangeCrmBridgeService.php

162 lines
5.0 KiB
PHP

<?php
namespace Modules\AssetExchange\Services;
use App\Business;
use App\Contact;
use App\Utils\Util;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Modules\AssetExchange\Models\Commission;
use Modules\AssetExchange\Models\Deal;
use Modules\AssetExchange\Models\Listing;
class AssetExchangeCrmBridgeService
{
public function __construct(
protected Util $commonUtil
) {
}
public function createLeadFromListing(Business $business, Listing $listing): ?Contact
{
if (! Schema::hasTable('contacts')) {
throw new \RuntimeException('جدول مخاطبین موجود نیست.');
}
if (! $this->isCrmAvailable()) {
return null;
}
$listing->loadMissing('seller');
if ($listing->seller_contact_id && $listing->seller) {
return $this->promoteContactToLead($listing->seller, $listing);
}
$contact = Contact::create([
'business_id' => $business->id,
'type' => 'lead',
'name' => $listing->title,
'mobile' => null,
'crm_lead_title' => $listing->title,
'crm_lead_description' => $listing->description,
'crm_lead_value' => $this->commonUtil->num_f($listing->asking_price, false),
'crm_source' => $this->resolveAexSourceId($business->id),
'crm_life_stage' => $this->resolveDefaultLifeStageId($business->id),
'created_by' => auth()->id(),
]);
$listing->update(['seller_contact_id' => $contact->id]);
return $contact;
}
public function syncCommissions(Business $business, Deal $deal): int
{
if (! Schema::hasTable('aex_commissions')) {
return 0;
}
$deal->loadMissing('commissions', 'listing');
if ($deal->status !== 'completed') {
throw new \RuntimeException('فقط معاملات تکمیل‌شده قابل همگام‌سازی کمیسیون هستند.');
}
$synced = 0;
return DB::transaction(function () use ($business, $deal, &$synced) {
foreach ($deal->commissions as $commission) {
if ($commission->status === 'paid' && $commission->crm_commission_id) {
continue;
}
$crmId = $this->syncCommissionToCrm($business, $deal, $commission);
if ($crmId) {
$commission->update([
'crm_commission_id' => $crmId,
'status' => 'synced',
]);
$synced++;
}
}
return $synced;
});
}
protected function promoteContactToLead(Contact $contact, Listing $listing): Contact
{
$contact->update([
'type' => $contact->type === 'supplier' ? 'supplier' : 'lead',
'crm_lead_title' => $listing->title,
'crm_lead_description' => $listing->description,
'crm_lead_value' => $this->commonUtil->num_f($listing->asking_price, false),
'crm_source' => $contact->crm_source ?: $this->resolveAexSourceId($contact->business_id),
'crm_life_stage' => $contact->crm_life_stage ?: $this->resolveDefaultLifeStageId($contact->business_id),
]);
return $contact->fresh();
}
protected function syncCommissionToCrm(Business $business, Deal $deal, Commission $commission): ?int
{
if (! class_exists(\Modules\Crm\Entities\CrmContactPersonCommission::class)) {
return null;
}
if (! Schema::hasTable('crm_contact_person_commissions')) {
return null;
}
if (! $commission->user_id || ! $deal->transaction_sell_id) {
return null;
}
$record = \Modules\Crm\Entities\CrmContactPersonCommission::updateOrCreate(
[
'contact_person_id' => $commission->user_id,
'transaction_id' => $deal->transaction_sell_id,
],
[
'commission_amount' => $commission->amount,
]
);
return $record->id;
}
protected function isCrmAvailable(): bool
{
return Schema::hasColumn('contacts', 'crm_source')
&& Schema::hasColumn('contacts', 'crm_life_stage');
}
protected function resolveAexSourceId(int $businessId): ?string
{
if (! Schema::hasTable('categories')) {
return 'aex_listing';
}
$source = \App\Category::where('business_id', $businessId)
->where('category_type', 'source')
->where('name', 'like', '%AssetExchange%')
->value('id');
return $source ? (string) $source : 'aex_listing';
}
protected function resolveDefaultLifeStageId(int $businessId): ?string
{
if (! Schema::hasTable('categories')) {
return null;
}
return \App\Category::where('business_id', $businessId)
->where('category_type', 'life_stage')
->orderBy('id')
->value('id');
}
}