обновлена модель сделок: добавлена возмжность нескольких клиентов. Обновлена форма создания клиентов
This commit is contained in:
parent
ea577e9a3b
commit
a8056ce610
@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Deal;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use Modules\Contracts\Models\Contract;
|
||||
|
||||
class ContractController extends Controller
|
||||
{
|
||||
public function index(Contract $contract)
|
||||
{
|
||||
return view(
|
||||
'clients.contract.index',
|
||||
[
|
||||
'contract' => $contract
|
||||
]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public function getAllDealsInCompany(Request $request)
|
||||
{
|
||||
$user = auth()->user();
|
||||
}
|
||||
}
|
||||
@ -7,11 +7,14 @@
|
||||
use Livewire\WithoutUrlPagination;
|
||||
|
||||
use App\Models\User;
|
||||
use Modules\Main\Models\Deal\Client;
|
||||
use Modules\Main\Models\Agent\Agent;
|
||||
use Modules\Main\Models\Company\CompanyAdmin;
|
||||
use App\Models\Deal\Deal;
|
||||
use App\Models\Deal\DealStatus;
|
||||
use App\Models\Deal\Client;
|
||||
use Modules\Main\Models\Deal\Deal;
|
||||
use Modules\Main\Models\Deal\DealStatus;
|
||||
|
||||
use Livewire\Attributes\On;
|
||||
|
||||
class ClientsTable extends Component
|
||||
{
|
||||
use WithPagination, WithoutUrlPagination;
|
||||
@ -27,52 +30,48 @@ public function mount($status = null, $count = 10, $mode = 'full')
|
||||
$this->mode = $mode;
|
||||
}
|
||||
|
||||
#[On('clientCreated')]
|
||||
public function getDeals()
|
||||
{
|
||||
$deals = false;
|
||||
$user = auth()->user();
|
||||
|
||||
$clients = false;
|
||||
$user = auth()->user();
|
||||
|
||||
if ($admin = CompanyAdmin::where('user_id', $user->id)->first())
|
||||
{
|
||||
/*$deals = Deal::whereIn('agent_id', function ($query) use ($admin)
|
||||
$deals = Deal::whereIn('agent_id', function ($query) use ($admin)
|
||||
{
|
||||
$query->select('id');
|
||||
$query->from('agents');
|
||||
$query->where('company_id', $admin->company_id);
|
||||
});*/
|
||||
$agentsOfCompany = Agent::where('company_id', $admin->company_id)->get()->pluck('id');
|
||||
$clients = Client::whereIn('id', function ($query) use ($agentsOfCompany)
|
||||
{
|
||||
$query->select('client_id')
|
||||
->from('deals')
|
||||
->whereIn('agent_id', $agentsOfCompany);
|
||||
});
|
||||
}
|
||||
elseif ($agent = Agent::where('user_id', $user->id)->first())
|
||||
{
|
||||
//$deals = Deal::where('agent_id', $agent->id);
|
||||
$deals = Deal::where('agent_id', $agent->id);
|
||||
}
|
||||
|
||||
$clients = Client::whereIn('id', function ($query) use ($agent)
|
||||
$deals = $deals->pluck('id');
|
||||
$clients = Client::join('deal_clients', 'users.id', '=', 'deal_clients.client_id')
|
||||
->whereIn('users.id', function ($query) use ($deals)
|
||||
{
|
||||
$query->select('client_id')
|
||||
->from('deals')
|
||||
->where('agent_id', $agent->id);
|
||||
->from('deal_clients')
|
||||
->whereIn('deal_id', $deals);
|
||||
})
|
||||
->orderBy('deal_clients.id', 'desc')
|
||||
->with('deals');
|
||||
;
|
||||
|
||||
});
|
||||
}
|
||||
$clients = $clients->orderBy('name');
|
||||
return $clients;
|
||||
}
|
||||
public function render()
|
||||
|
||||
function getClients()
|
||||
{
|
||||
$clients = $this->getDeals();
|
||||
if ($this->status && $this->status == DealStatus::UNIQUE)
|
||||
{
|
||||
/*$deals = $deals
|
||||
->whereIn('status', [DealStatus::UNIQUE])
|
||||
->orderBy('id', 'desc')->paginate($this->count, ['*'], 'unique_clients');*/
|
||||
$clients = $clients->whereHas('deals', function ($query)
|
||||
{
|
||||
$query->where('status', DealStatus::UNIQUE);
|
||||
@ -82,9 +81,6 @@ public function render()
|
||||
}
|
||||
elseif ($this->status && $this->status == DealStatus::NOT_UNIQUE)
|
||||
{
|
||||
/*$deals = $deals
|
||||
->whereIn('status', [DealStatus::MODERATION, DealStatus::NEW , DealStatus::NOT_UNIQUE])
|
||||
->orderBy('id', 'desc')->paginate($this->count, ['*'], 'not_unique_clients');*/
|
||||
$clients = $clients->whereHas('deals', function ($query)
|
||||
{
|
||||
$query->whereIn('status', [DealStatus::MODERATION, DealStatus::NEW , DealStatus::NOT_UNIQUE]);
|
||||
@ -95,22 +91,18 @@ public function render()
|
||||
/*$deals = $deals->orderBy('id', 'desc')->paginate($this->count, ['*'], 'all_clients');*/
|
||||
$clients = $clients->paginate($this->count, ['*'], 'all_clients');
|
||||
}
|
||||
return $clients;
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
|
||||
return view(
|
||||
'livewire.clients-table',
|
||||
[
|
||||
'clients' => $clients,
|
||||
'clients' => $this->getClients(),
|
||||
'statuses' => DealStatus::class
|
||||
]
|
||||
);
|
||||
}
|
||||
function getClients()
|
||||
{
|
||||
/*$clients = User::whereIn('id', function ($query)
|
||||
{
|
||||
|
||||
});*/
|
||||
$clients = false;
|
||||
//$clients = Client::ofAgent();
|
||||
return $clients;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,198 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire;
|
||||
|
||||
use Livewire\Component;
|
||||
use App\Models\User;
|
||||
use App\Models\Deal\Deal;
|
||||
use App\Models\Deal\DealStatus;
|
||||
use App\Models\Complex;
|
||||
use App\Models\Agent\Agent;
|
||||
use App\Models\Bitrix\SendClient;
|
||||
use App\Models\Company\CompanyAdmin;
|
||||
|
||||
|
||||
class CreateClientForm extends Component
|
||||
{
|
||||
const NEW = 1;
|
||||
const ERROR = 2;
|
||||
const SUCCESS = 3;
|
||||
const READY = 4;
|
||||
public $client;
|
||||
public $clientSecondary;
|
||||
public $complexes;
|
||||
public $status;
|
||||
public $result;
|
||||
public $agent;
|
||||
protected $messages = [
|
||||
'client.firstName.required' => 'Необходимо указать имя клиента',
|
||||
'client.secondName.required' => 'Необходимо указать фамилию клиента',
|
||||
'client.phone.required' => 'Необходимо указать телефон',
|
||||
'client.phone.regex' => 'Телефон должен быть в международном формате',
|
||||
'client.phone.unique' => 'Клиент с таким телефоном уже существует',
|
||||
'agent.integer' => 'Необходимо указать агента, от которого добавляется контакт'
|
||||
];
|
||||
protected function rules()
|
||||
{
|
||||
return [
|
||||
'agent' => ['required', 'integer'],
|
||||
'client.firstName' => ['required', 'string', 'max:255'],
|
||||
'client.secondName' => ['required', 'string', 'max:255'],
|
||||
'client.phone' => ['required', 'string', 'regex:/^(\+7)([0-9]{3})([-]{1})([0-9]{3})([-]{1})([0-9]{4})/i']
|
||||
//'client.phone' => ['required', 'string', 'regex:/^\+7 \d{3} \d{3}-\d{2}-\d{2}$/'],
|
||||
//'client.phone' => ['required', 'string']
|
||||
];
|
||||
}
|
||||
public function mount()
|
||||
{
|
||||
$agent = Agent::where('user_id', auth()->user()->id)->first();
|
||||
$this->client = [
|
||||
'firstName' => '',
|
||||
'secondName' => '',
|
||||
'phone' => '',
|
||||
'complexId' => ''
|
||||
];
|
||||
$this->status = self::NEW;
|
||||
|
||||
if ($agent)
|
||||
{
|
||||
$this->agent = $agent->id;
|
||||
$this->complexes = Complex::where('city_id', $agent->company->city_id)->get();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->agent = false;
|
||||
$admin = CompanyAdmin::where('user_id', auth()->user()->id)->first();
|
||||
if ($admin)
|
||||
{
|
||||
$this->complexes = Complex::where('city_id', $admin->company_id)->get();
|
||||
}
|
||||
}
|
||||
$this->clientSecondary = false;
|
||||
}
|
||||
public function update()
|
||||
{
|
||||
}
|
||||
|
||||
public function updated($propertyName)
|
||||
{
|
||||
$this->status = self::NEW;
|
||||
$this->validateOnly($propertyName);
|
||||
}
|
||||
public function getClientSecondary()
|
||||
{
|
||||
$this->clientSecondary = [
|
||||
'firstName' => '',
|
||||
'secondName' => '',
|
||||
'phone' => '',
|
||||
'complexId' => ''
|
||||
];
|
||||
}
|
||||
public function deleteClientSecondary()
|
||||
{
|
||||
$this->clientSecondary = false;
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
if (
|
||||
$this->client['firstName']
|
||||
&& $this->client['secondName']
|
||||
&& $this->client['phone']
|
||||
&& $this->client['complexId']
|
||||
&& $this->status == self::NEW
|
||||
)
|
||||
{
|
||||
$this->status = self::READY;
|
||||
}
|
||||
$data = [
|
||||
'adminAccount' => false
|
||||
];
|
||||
if ($adminAccount = CompanyAdmin::where('user_id', auth()->user()->id)->first())
|
||||
{
|
||||
$data = [
|
||||
'adminAccount' => $adminAccount,
|
||||
'agents' => Agent::where('company_id', $adminAccount->company_id)->get()
|
||||
];
|
||||
}
|
||||
return view(
|
||||
'livewire.create-client-form',
|
||||
$data
|
||||
);
|
||||
}
|
||||
public function resetData()
|
||||
{
|
||||
$this->mount();
|
||||
}
|
||||
public function back()
|
||||
{
|
||||
$this->status = self::NEW;
|
||||
}
|
||||
public function save()
|
||||
{
|
||||
$validated = $this->validate($this->rules());
|
||||
$newUser = User::updateOrCreate(
|
||||
['phone' => $this->client['phone']],
|
||||
[
|
||||
'name' => trim($this->client['firstName'] . ' ' . $this->client['secondName']),
|
||||
'phone' => $this->client['phone']
|
||||
]
|
||||
);
|
||||
$data = [
|
||||
'agent_id' => $this->agent
|
||||
,
|
||||
'client_id' => $newUser->id
|
||||
,
|
||||
'complex_id' => $this->client['complexId']
|
||||
];
|
||||
//$data['confirm_token'] = $this->client['confirmToken'] = hash('sha256', json_encode($data));
|
||||
|
||||
if ($newDeal = Deal::create($data))
|
||||
{
|
||||
if ($bitrixId = $this->sendToBitrix($newDeal))
|
||||
{
|
||||
$newDeal->bitrix_id = $bitrixId;
|
||||
$newDeal->status = DealStatus::MODERATION;
|
||||
$newDeal->save();
|
||||
$this->result = $bitrixId;
|
||||
return $this->status = self::SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
$newDeal->delete();
|
||||
}
|
||||
}
|
||||
return $this->status = self::ERROR;
|
||||
}
|
||||
public function sendToBitrix(Deal $deal)
|
||||
{
|
||||
$agent = $deal->agent;
|
||||
$agentName = $agent->user->getPartialsName();
|
||||
$data = [
|
||||
'CLIENT_FIRST_NAME' => $this->client['firstName'],
|
||||
'CLIENT_SECOND_NAME' => $this->client['secondName'],
|
||||
'CLIENT_PHONE' => '+7' . $this->client['phone'],
|
||||
'BROKER_FIRST_NAME' => $agentName['firstName'],
|
||||
'BROKER_SECOND_NAME' => $agentName['secondName'],
|
||||
'BROKER_PHONE' => $agent->user->phone,
|
||||
'BROKER_INN' => $agent->company->inn,
|
||||
//'BROKER_CONTACT' => $agent->bitrixId(),
|
||||
'OBJECT_NAME' => Complex::find($this->client['complexId'])->name,
|
||||
'CALLBACK_URL' => route('api.client', ['hash' => $deal->confirmToken]),
|
||||
];
|
||||
$sender = new SendClient($deal->id, $data);
|
||||
if ($bitrixId = $agent->bitrixId())
|
||||
{
|
||||
$sender->setAgentId($bitrixId);
|
||||
}
|
||||
$response = $sender->send();
|
||||
if ($response)
|
||||
{
|
||||
return $response;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Bitrix;
|
||||
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class SendClient
|
||||
{
|
||||
private $IBLOCK_TYPE_ID = 'lists';
|
||||
|
||||
//CONFIG для Альфы
|
||||
|
||||
private $URL = 'https://b24alfa.pro/rest/3165/v90a792nderzu0dj/lists.element.add.json';
|
||||
private $IBLOCK_ID = 27;
|
||||
private $ID;
|
||||
const NAME = "NAME";
|
||||
const CLIENT_SECOND_NAME = "PROPERTY_94";
|
||||
const CLIENT_FIRST_NAME = "PROPERTY_95";
|
||||
const CLIENT_PHONE = "PROPERTY_96";
|
||||
const BROKER_SECOND_NAME = "PROPERTY_97";
|
||||
const BROKER_FIRST_NAME = "PROPERTY_98";
|
||||
const BROKER_PHONE = "PROPERTY_99";
|
||||
const OBJECT_NAME = "PROPERTY_100";
|
||||
const CALLBACK_URL = "PROPERTY_105";
|
||||
const BROKER_CONTACT = "PROPERTY_108";
|
||||
|
||||
private $data = [];
|
||||
|
||||
public function __construct($id, $data)
|
||||
{
|
||||
$this->ID = env('BITRIX_CODE_PREFIX', '') . $id;
|
||||
$data = array_change_key_case($data, CASE_UPPER);
|
||||
$finalData = [];
|
||||
$refl = new \ReflectionClass(__CLASS__);
|
||||
$constants = $refl->getConstants();
|
||||
foreach ($constants as $constName => $constValue)
|
||||
{
|
||||
foreach ($data as $key => $value)
|
||||
{
|
||||
if ($constName == $key)
|
||||
{
|
||||
$finalData[$constValue] = $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$finalData['NAME'] = $finalData[self::CLIENT_FIRST_NAME] . ' ' . $finalData[self::CLIENT_SECOND_NAME];
|
||||
$this->data = $finalData;
|
||||
return;
|
||||
}
|
||||
public function setBitrixId($id)
|
||||
{
|
||||
$this->data['PROPERTY_123'] = $id;
|
||||
}
|
||||
|
||||
public function setAgentId($id)
|
||||
{
|
||||
$this->data['PROPERTY_108'] = $id;
|
||||
}
|
||||
|
||||
public function send()
|
||||
{
|
||||
$data = [
|
||||
'IBLOCK_TYPE_ID' => $this->IBLOCK_TYPE_ID,
|
||||
'IBLOCK_ID' => $this->IBLOCK_ID,
|
||||
'ELEMENT_CODE' => $this->ID,
|
||||
'FIELDS' => $this->data
|
||||
];
|
||||
$sender = new BitrixSender($this->URL, $data);
|
||||
return $sender->send();
|
||||
}
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Bitrix;
|
||||
use App\Models\Company\Company;
|
||||
use App\Models\Bitrix\BitrixSender;
|
||||
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class SendCompany
|
||||
{
|
||||
private $IBLOCK_TYPE_ID = 'rest_entity';
|
||||
|
||||
//CONFIG для Альфы
|
||||
|
||||
private $URL = 'https://b24alfa.pro/rest/3165/v90a792nderzu0dj/lists.element.add.json';
|
||||
private $IBLOCK_ID = 24;
|
||||
private $ID;
|
||||
const NAME = "NAME";
|
||||
const INN = "PROPERTY_118";
|
||||
const PHONE = "PROPERTY_121";
|
||||
const EMAIL = "PROPERTY_120";
|
||||
const LEGAL_ADDRESS = "PROPERTY_119";
|
||||
const CALLBACK_URL = "PROPERTY_122";
|
||||
private $data = [];
|
||||
|
||||
public function __construct($id, array $data)
|
||||
{
|
||||
$this->ID = env('BITRIX_CODE_PREFIX', '') . $id;
|
||||
$data = array_change_key_case($data, CASE_UPPER);
|
||||
$finalData = $this->castConstants($data);
|
||||
$this->data = $finalData;
|
||||
return;
|
||||
}
|
||||
|
||||
private function castConstants($data)
|
||||
{
|
||||
$finalData = [];
|
||||
$refl = new \ReflectionClass(__CLASS__);
|
||||
$constants = $refl->getConstants();
|
||||
foreach ($constants as $constName => $constValue)
|
||||
{
|
||||
foreach ($data as $key => $value)
|
||||
{
|
||||
if ($constName == $key)
|
||||
{
|
||||
$finalData[$constValue] = $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $finalData;
|
||||
}
|
||||
public function send()
|
||||
{
|
||||
$data = [
|
||||
'IBLOCK_TYPE_ID' => $this->IBLOCK_TYPE_ID,
|
||||
'IBLOCK_ID' => $this->IBLOCK_ID,
|
||||
'ELEMENT_CODE' => $this->ID,
|
||||
'FIELDS' => $this->data
|
||||
];
|
||||
$sender = new BitrixSender($this->URL, $data);
|
||||
return $sender->send();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
\DB::table('deals')->whereNotNull('client_id')->orderBy('id')->chunk(1000, function ($rows)
|
||||
{
|
||||
foreach ($rows as $row)
|
||||
{
|
||||
\DB::table('deal_clients')->updateOrInsert(['deal_id' => $row->id, 'client_id' => $row->client_id]);
|
||||
// Or if you're creating new records in the new table based on the old, use insert:
|
||||
// \DB::table('new_table_name')->insert(['id' => $row->id, 'field_name' => $row->field_name]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('deals', function (Blueprint $table)
|
||||
{
|
||||
$table->dropForeign(['client_id']);
|
||||
$table->dropColumn(['client_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
@ -7,6 +7,12 @@
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
use Modules\Main\Models\Deal\Deal;
|
||||
use Modules\Main\Models\Deal\Client;
|
||||
use Modules\Main\Models\Deal\DealClients;
|
||||
use Modules\Main\Models\Agent\Agent;
|
||||
use Modules\Main\Models\Company\Company;
|
||||
use Modules\Main\Models\Complex;
|
||||
|
||||
class BitrixId extends Model
|
||||
{
|
||||
@ -20,4 +26,91 @@ public function bitrixable(): MorphTo
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (BitrixId $bitrixId)
|
||||
{
|
||||
if ($bitrixId->bx_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch ( $bitrixId->bitrixable_type )
|
||||
{
|
||||
case Deal::class:
|
||||
$deal = Deal::findOrFail($bitrixId->bitrixable_id);
|
||||
$sender = new SendDeal($deal);
|
||||
$result = $sender->send();
|
||||
if ($result == true)
|
||||
{
|
||||
$id = $sender->resultData['id'];
|
||||
$bitrixId->bx_id = $id;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case Agent::class:
|
||||
$agent = Agent::findOrFail($bitrixId->bitrixable_id);
|
||||
$sender = new SendAgent($agent);
|
||||
$result = $sender->send();
|
||||
if ($result == true)
|
||||
{
|
||||
$id = $sender->resultData['id'];
|
||||
$bitrixId->bx_id = $id;
|
||||
return;
|
||||
};
|
||||
break;
|
||||
case DealClients::class:
|
||||
$dealClient = DealClients::findOrFail($bitrixId->bitrixable_id);
|
||||
$client = $dealClient->client;
|
||||
$sender = new SendClient($client);
|
||||
$result = $sender->send();
|
||||
if ($result)
|
||||
{
|
||||
$id = $sender->resultData['id'];
|
||||
$bitrixId->bx_id = $id;
|
||||
$bitrixId->bitrixable_type = Client::class;
|
||||
$bitrixId->bitrixable_id = $client->id;
|
||||
return;
|
||||
};
|
||||
break;
|
||||
case Company::class:
|
||||
$company = Company::findOrFail($bitrixId->bitrixable_id);
|
||||
$sender = new SendCompany($company);
|
||||
$result = $sender->send();
|
||||
if ($result == true)
|
||||
{
|
||||
$id = $sender->resultData['id'];
|
||||
$bitrixId->bx_id = $id;
|
||||
return;
|
||||
};
|
||||
break;
|
||||
}
|
||||
throw new \Exception('Error of bitrix identifier getter for ' . $bitrixId->bitrixable_type . ' with id ' . $bitrixId->bitrixable_id);
|
||||
|
||||
});
|
||||
static::created(function (BitrixId $bitrixId)
|
||||
{
|
||||
if (!$bitrixId->bx_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch ( $bitrixId->bitrixable_type )
|
||||
{
|
||||
case Deal::class:
|
||||
$deal = Deal::findOrFail($bitrixId->bitrixable_id);
|
||||
$agentAppender = new SendDealAgent($deal);
|
||||
$agentAppender->send();
|
||||
break;
|
||||
case Client::class:
|
||||
$client = Client::findOrFail($bitrixId->bitrixable_id);
|
||||
if ($dealClient = DealClients::where('client_id', $client->id)->orderByDesc('id')->first())
|
||||
{
|
||||
$clientAppender = new SendDealClient(Deal::find($dealClient->deal_id), $client);
|
||||
$result = $clientAppender->send();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,58 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Bitrix;
|
||||
namespace Modules\Bitrix\Models;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class BitrixSender
|
||||
{
|
||||
public $url;
|
||||
public $data;
|
||||
{
|
||||
protected $url;
|
||||
protected $data;
|
||||
public $resultData;
|
||||
public function __construct(string $url, array $data)
|
||||
{
|
||||
{
|
||||
$this->url = $url;
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
||||
public function send()
|
||||
{
|
||||
{
|
||||
$postdata = http_build_query(
|
||||
$this->data
|
||||
);
|
||||
$opts = array(
|
||||
'ssl' => array(
|
||||
'verify_peer' => true,
|
||||
'ssl' => array(
|
||||
'verify_peer' => true,
|
||||
'verify_peername' => true
|
||||
),
|
||||
'http' => array(
|
||||
'method' => 'POST',
|
||||
'header' =>
|
||||
'method' => 'POST',
|
||||
'header' =>
|
||||
'Content-type: application/x-www-form-urlencoded' . "\r\n" .
|
||||
'',
|
||||
'content' => $postdata
|
||||
)
|
||||
);
|
||||
try
|
||||
{
|
||||
{
|
||||
$context = stream_context_create($opts);
|
||||
$result = file_get_contents($this->url, false, $context);
|
||||
$result = json_decode($result, $associative = true);
|
||||
$this->resultData = $result;
|
||||
if (array_key_exists('result', $result))
|
||||
{
|
||||
return $result['result'];
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
Log::build([
|
||||
'driver' => 'single',
|
||||
'path' => storage_path('logs/bitrix.log'),
|
||||
])->error($e->getMessage());
|
||||
return false;
|
||||
return $result['result'];
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
Log::build([
|
||||
'driver' => 'single',
|
||||
'path' => storage_path('logs/bitrix.log'),
|
||||
])->error($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
22
app/Modules/Bitrix/Models/SendAgent.php
Normal file
22
app/Modules/Bitrix/Models/SendAgent.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Bitrix\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
use Modules\Main\Models\Agent\Agent;
|
||||
use Modules\Main\Models\Complex;
|
||||
class SendAgent extends BitrixSender
|
||||
{
|
||||
use HasFactory;
|
||||
public function __construct(Agent $agent)
|
||||
{
|
||||
$this->data = [
|
||||
'name' => $agent->user->name,
|
||||
'phones' => [$agent->user->phone],
|
||||
];
|
||||
dd($this->data);
|
||||
$this->url = 'https://b24alfa.pro/channels/lk/createContact/';
|
||||
}
|
||||
}
|
||||
21
app/Modules/Bitrix/Models/SendClient.php
Normal file
21
app/Modules/Bitrix/Models/SendClient.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Bitrix\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
use Modules\Main\Models\Deal\Client;
|
||||
use Modules\Main\Models\Complex;
|
||||
class SendClient extends BitrixSender
|
||||
{
|
||||
use HasFactory;
|
||||
public function __construct(Client $client)
|
||||
{
|
||||
$this->data = [
|
||||
'name' => $client->name,
|
||||
'phones' => [$client->phone],
|
||||
];
|
||||
$this->url = 'https://b24alfa.pro/channels/lk/createContact/';
|
||||
}
|
||||
}
|
||||
21
app/Modules/Bitrix/Models/SendCompany.php
Normal file
21
app/Modules/Bitrix/Models/SendCompany.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Bitrix\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
use Modules\Main\Models\Agent\Agent;
|
||||
use Modules\Main\Models\Complex;
|
||||
class SendCompany extends BitrixSender
|
||||
{
|
||||
use HasFactory;
|
||||
public function __construct(Agent $agent)
|
||||
{
|
||||
$this->data = [
|
||||
'name' => $agent->user->name,
|
||||
'phones' => [$agent->user->phone],
|
||||
];
|
||||
$this->url = 'https://b24alfa.pro/channels/lk/createCompany/';
|
||||
}
|
||||
}
|
||||
20
app/Modules/Bitrix/Models/SendDeal.php
Normal file
20
app/Modules/Bitrix/Models/SendDeal.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Bitrix\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
use Modules\Main\Models\Deal\Deal;
|
||||
use Modules\Main\Models\Complex;
|
||||
class SendDeal extends BitrixSender
|
||||
{
|
||||
use HasFactory;
|
||||
public function __construct(Deal $deal)
|
||||
{
|
||||
$this->data = [
|
||||
'complexName' => $deal->complex->name
|
||||
];
|
||||
$this->url = 'https://b24alfa.pro/channels/lk/createSmartProcess/';
|
||||
}
|
||||
}
|
||||
22
app/Modules/Bitrix/Models/SendDealAgent.php
Normal file
22
app/Modules/Bitrix/Models/SendDealAgent.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Bitrix\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
use Modules\Main\Models\Deal\Deal;
|
||||
use Modules\Main\Models\Agent\Agent;
|
||||
class SendDealAgent extends BitrixSender
|
||||
{
|
||||
use HasFactory;
|
||||
public function __construct(Deal $deal)
|
||||
{
|
||||
$this->data = [
|
||||
'spId' => $deal->bitrixId(),
|
||||
'contactId' => $deal->agent->bitrixId(),
|
||||
'type' => 'agent'
|
||||
];
|
||||
$this->url = 'https://b24alfa.pro/channels/lk/addContactToSmartProcess/';
|
||||
}
|
||||
}
|
||||
23
app/Modules/Bitrix/Models/SendDealClient.php
Normal file
23
app/Modules/Bitrix/Models/SendDealClient.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Bitrix\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
use Modules\Main\Models\Deal\Deal;
|
||||
use Modules\Main\Models\Deal\Client;
|
||||
|
||||
class SendDealClient extends BitrixSender
|
||||
{
|
||||
use HasFactory;
|
||||
public function __construct(Deal $deal, Client $client)
|
||||
{
|
||||
$this->data = [
|
||||
'spId' => $deal->bitrixId(),
|
||||
'contactId' => $client->bitrixId(),
|
||||
'type' => 'contact'
|
||||
];
|
||||
$this->url = 'https://b24alfa.pro/channels/lk/addContactToSmartProcess/';
|
||||
}
|
||||
}
|
||||
@ -26,17 +26,48 @@ public function bitrixId()
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public function setBitrixId($id): bool
|
||||
public function setBitrixId($id = null)
|
||||
{
|
||||
$this->bitrixy()->delete();
|
||||
$bitrixId = new BitrixId([
|
||||
'bx_id' => $id
|
||||
]);
|
||||
if ($this->bitrixy()->save($bitrixId))
|
||||
$bitrixy = $this->bitrixy;
|
||||
if (!$bitrixy)
|
||||
{
|
||||
return true;
|
||||
$bitrixId = new BitrixId();
|
||||
$bitrixId->bx_id = $id ?? null;
|
||||
$this->bitrixy()->save($bitrixId);
|
||||
}
|
||||
return false;
|
||||
if ($id)
|
||||
{
|
||||
$bitrixy = $this->bitrixy;
|
||||
$bitrixy->bx_id = $id;
|
||||
$bitrixy->save();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
protected static function create(array $attributes = [])
|
||||
{
|
||||
$model = new static();
|
||||
$model->fill($attributes);
|
||||
$model->save();
|
||||
$model->setBitrixId();
|
||||
return $model;
|
||||
}
|
||||
|
||||
public static function firstOrCreate($attributes = [], $values = [])
|
||||
{
|
||||
$model = new static();
|
||||
foreach ($attributes as $key => $value)
|
||||
{
|
||||
$model = $model->where($key, $value);
|
||||
}
|
||||
if ($model->count())
|
||||
{
|
||||
return $model->first();
|
||||
}
|
||||
else
|
||||
{
|
||||
self::create(array_merge($attributes, $values));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,116 +2,165 @@
|
||||
|
||||
namespace Modules\ClientCreateForm\Http\Livewire;
|
||||
|
||||
use Exception;
|
||||
use Laravel\Prompts\FormStep;
|
||||
use Livewire\Component;
|
||||
use Livewire\Attributes\Validate;
|
||||
|
||||
use Modules\Main\Models\Deal\Deal;
|
||||
use Modules\Main\Models\Deal\Client;
|
||||
use Modules\Main\Models\Deal\DealClients;
|
||||
class ClientCreateLivewire extends Component
|
||||
{
|
||||
//public ClientCreateForm $form;
|
||||
|
||||
public $status;
|
||||
public $availableAgents;
|
||||
public $complexes;
|
||||
public $maxClientsCount;
|
||||
public $maxClientPhonesCount;
|
||||
public $maxContactsCount;
|
||||
public $maxContactPhonesCount;
|
||||
|
||||
/////////////////////
|
||||
public $agent;
|
||||
public $clients;
|
||||
public $currentClientIndex;
|
||||
public $currentClient;
|
||||
public $addSecondaryClient;
|
||||
public $secondaryClient;
|
||||
public $clientLabels;
|
||||
public $agentId;
|
||||
public $contacts;
|
||||
public $complexId;
|
||||
public $currentContactIndex;
|
||||
public $contactLabels;
|
||||
public $bitrixId;
|
||||
|
||||
protected function rules()
|
||||
{
|
||||
return [
|
||||
'contacts.*' => ['required', 'min:1'],
|
||||
'contacts.*.firstName' => ['required', 'string', 'max:50'],
|
||||
'contacts.*.secondName' => ['required', 'string', 'max:50'],
|
||||
'contacts.*.phones.*' => 'required|string|regex:/^(\+7)([(]{1})([0-9]{3})([)]{1})([\s]{1})([0-9]{3})([-]{1})([0-9]{2})([-]{1})([0-9]{2})/',
|
||||
'complexId' => ['required'],
|
||||
'agentId' => ['required'],
|
||||
];
|
||||
}
|
||||
protected function messages()
|
||||
{
|
||||
return [
|
||||
'contacts.*.firstName.reqired' => 'Необходимо указать имя (отчество) клиента',
|
||||
'contacts.*.secondName.reqired' => 'Необходимо указать фамилию клиента',
|
||||
'contacts.*.firstName.max' => 'Указанное имя клиента слишком длинное',
|
||||
'contacts.*.secondName.max' => 'Указанное имя клиента слишком длинное',
|
||||
'contacts.*.phones.*.reqired' => 'Необходимо указать номер телефона клиента',
|
||||
'contacts.*.phones.*.regex' => 'Указанный номер телефона некорректный',
|
||||
|
||||
];
|
||||
}
|
||||
public function mount()
|
||||
{
|
||||
$this->status = FormStatus::NEW;
|
||||
$this->complexes = GetAvailableComplexes();
|
||||
$this->availableAgents = GetAvailableAgents();
|
||||
$this->maxClientsCount = 2;
|
||||
$this->maxClientPhonesCount = 2;
|
||||
$this->clientLabels = ['Основной контакт', 'Супруг/супруга'];
|
||||
|
||||
$this->status = FormStatus::NEW;
|
||||
$this->secondaryClient = false;
|
||||
$this->addSecondaryClient = true;
|
||||
$this->maxContactsCount = 2;
|
||||
$this->maxContactPhonesCount = 1;
|
||||
$this->contactLabels = ['Основной контакт', 'Супруг/супруга'];
|
||||
if (count($this->availableAgents) == 1) //чтобы не выводить в форму
|
||||
{ //и не заставлять пользователя указывать вручную
|
||||
$this->agent = $this->availableAgents[0]['id'];
|
||||
$this->agentId = $this->availableAgents[0]['id'];
|
||||
}
|
||||
$this->addClient();
|
||||
$this->addClient();//по-умолчанию сразу выводить супруга
|
||||
$this->setCurrentClient(0);
|
||||
$this->contacts = [];
|
||||
$this->addContact();
|
||||
$this->addContact();//по-умолчанию сразу выводить супруга
|
||||
$this->setCurrentContactIndex(0);
|
||||
}
|
||||
public function updated($propertyName)
|
||||
|
||||
/**
|
||||
* Метод срабатывает, когда пользователь нажимает в форме
|
||||
* на кнопку "Добавить супруга"
|
||||
* @return void
|
||||
*/
|
||||
public function addContact()
|
||||
{
|
||||
$this->status = FormStatus::NEW;
|
||||
}
|
||||
public function addClient()
|
||||
{
|
||||
if (!isset($this->clients))
|
||||
if (!isset($this->contacts))
|
||||
{
|
||||
$this->clients = [];
|
||||
$this->contacts = [];
|
||||
}
|
||||
if ($this->maxClientsCount > count($this->clients))
|
||||
if ($this->maxContactsCount > count($this->contacts))
|
||||
{
|
||||
$this->clients[] = [
|
||||
$this->contacts[] = [
|
||||
'firstName' => '',
|
||||
'secondName' => '',
|
||||
'phones' => [''],
|
||||
'complexId' => ''
|
||||
'phones' => ['']
|
||||
];
|
||||
}
|
||||
$this->setCurrentClient(count($this->clients) - 1);
|
||||
$this->setCurrentContactIndex(count($this->contacts) - 1);
|
||||
}
|
||||
/**
|
||||
* Метод срабатывает, когда пользователь нажимает кнопку "Удалить контакт"
|
||||
* Кнопка доступна на всех вкладках, кроме первой
|
||||
* @param mixed $index Индекс контакта по порядку следования на вкладках
|
||||
* @return void
|
||||
*/
|
||||
public function deleteContact($index = false)
|
||||
{
|
||||
if ($index === false)
|
||||
{
|
||||
$index = $this->currentClientIndex;
|
||||
$index = $this->currentContactIndex;
|
||||
}
|
||||
if ($index > 0)
|
||||
{
|
||||
unset($this->clients[$index]);
|
||||
$this->clients = array_values($this->clients);
|
||||
$this->setCurrentClient($index - 1);
|
||||
unset($this->contacts[$index]);
|
||||
$this->contacts = array_values($this->contacts);
|
||||
$this->setCurrentContactIndex($index - 1);
|
||||
}
|
||||
}
|
||||
public function setCurrentClient($index)
|
||||
/**
|
||||
* Вызвается при переходе пользователя по вкладкам
|
||||
* @param mixed $index
|
||||
* @return void
|
||||
*/
|
||||
public function setCurrentContactIndex($index)
|
||||
{
|
||||
$this->saveClient();
|
||||
$this->updateCurrentClientIndex($index);
|
||||
$this->currentContactIndex = $index;
|
||||
$this->updated('currentContactIndex');
|
||||
}
|
||||
public function toggleSecondClient()
|
||||
/**
|
||||
* Вызывается, когда пользователь нажимает на кнопку
|
||||
* "Добавить супруга" на первой вкладке
|
||||
* @return void
|
||||
*/
|
||||
public function toggleSecondContact()
|
||||
{
|
||||
if ($this->currentClientIndex == 0)
|
||||
if ($this->currentContactIndex == 0)
|
||||
{
|
||||
if (count($this->clients) == 2)
|
||||
if (count($this->contacts) == 2)
|
||||
{
|
||||
$this->deleteContact(1);
|
||||
}
|
||||
elseif (count($this->clients) == 1)
|
||||
elseif (count($this->contacts) == 1)
|
||||
{
|
||||
$this->addClient();
|
||||
$this->addContact();
|
||||
}
|
||||
}
|
||||
}
|
||||
private function updateCurrentClientIndex($index)
|
||||
/**
|
||||
* Вызывается, когда пользователь нажимает на кнопку "добавить телефон"
|
||||
* на вкладке любого из контактов
|
||||
* @return void
|
||||
*/
|
||||
public function addPhoneForCurrentContact()
|
||||
{
|
||||
$this->currentClient = $this->clients[$index];
|
||||
$this->currentClientIndex = $index;
|
||||
}
|
||||
public function saveClient()
|
||||
{
|
||||
if (isset($this->currentClientIndex))
|
||||
if (count($this->contacts[$this->currentContactIndex]['phones']) < $this->maxContactPhonesCount)
|
||||
{
|
||||
//$this->form->validate();
|
||||
$this->clients[$this->currentClientIndex] = $this->currentClient;
|
||||
$this->contacts[$this->currentContactIndex]['phones'][] = '';
|
||||
}
|
||||
}
|
||||
public function addPhoneForClient()
|
||||
public function updated($propertyName)
|
||||
{
|
||||
if (count($this->currentClient['phones']) < $this->maxClientPhonesCount)
|
||||
$this->status = FormStatus::IN_PROCESS;
|
||||
$this->validateOnly($propertyName);
|
||||
try
|
||||
{
|
||||
$this->currentClient['phones'][] = '';
|
||||
$this->validate();
|
||||
$this->status = FormStatus::READY;
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$this->status = FormStatus::IN_PROCESS;
|
||||
}
|
||||
}
|
||||
public function render()
|
||||
@ -123,6 +172,7 @@ public function render()
|
||||
public function rendered()
|
||||
{
|
||||
$this->dispatch('phoneInputAdded');
|
||||
|
||||
}
|
||||
public function resetData()
|
||||
{
|
||||
@ -130,75 +180,50 @@ public function resetData()
|
||||
}
|
||||
public function back()
|
||||
{
|
||||
$this->status = FormStatus::NEW;
|
||||
$this->status = FormStatus::IN_PROCESS;
|
||||
}
|
||||
|
||||
//далее - сохранение клиента в базу и отправка в битрикс.
|
||||
//надо разделить на invoke классы!
|
||||
/*public function save()
|
||||
public function save()
|
||||
{
|
||||
$validated = $this->form->validate();
|
||||
$newUser = User::updateOrCreate(
|
||||
['phone' => $this->client['phone']],
|
||||
[
|
||||
'name' => trim($this->client['firstName'] . ' ' . $this->client['secondName']),
|
||||
'phone' => $this->client['phone']
|
||||
]
|
||||
);
|
||||
$data = [
|
||||
'agent_id' => $this->agent
|
||||
,
|
||||
'client_id' => $newUser->id
|
||||
,
|
||||
'complex_id' => $this->client['complexId']
|
||||
];
|
||||
if (
|
||||
!$deal = Deal::create([
|
||||
'agent_id' => $this->agentId,
|
||||
'complex_id' => $this->complexId
|
||||
])
|
||||
)
|
||||
{
|
||||
$this->status = FormStatus::ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
if ($newDeal = Deal::create($data))
|
||||
foreach ($this->contacts as $contact)
|
||||
{
|
||||
if ($bitrixId = $this->sendToBitrix($newDeal))
|
||||
if (
|
||||
!$newUser = Client::updateOrCreate(
|
||||
['phone' => $contact['phones'][0]],
|
||||
[
|
||||
'name' => trim($contact['firstName'] . ' ' . $contact['secondName']),
|
||||
'phone' => $contact['phones'][0]
|
||||
]
|
||||
)
|
||||
)
|
||||
{
|
||||
$newDeal->bitrix_id = $bitrixId;
|
||||
$newDeal->status = DealStatus::MODERATION;
|
||||
$newDeal->save();
|
||||
$this->bitrixId = $bitrixId;
|
||||
return $this->status = FormStatus::SUCCESS;
|
||||
$this->status = FormStatus::ERROR;
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (
|
||||
!$dealClient = DealClients::firstOrCreate([
|
||||
'deal_id' => $deal->id,
|
||||
'client_id' => $newUser->id
|
||||
])
|
||||
)
|
||||
{
|
||||
$newDeal->delete();
|
||||
$this->status = FormStatus::ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return $this->status = FormStatus::ERROR;
|
||||
$this->status = FormStatus::SUCCESS;
|
||||
$this->dispatch('clientCreated');
|
||||
|
||||
}
|
||||
public function sendToBitrix(Deal $deal)
|
||||
{
|
||||
$agent = $deal->agent;
|
||||
$agentName = $agent->user->getPartialsName();
|
||||
$data = [
|
||||
'CLIENT_FIRST_NAME' => $this->client['firstName'],
|
||||
'CLIENT_SECOND_NAME' => $this->client['secondName'],
|
||||
'CLIENT_PHONE' => '+7' . $this->client['phone'],
|
||||
'BROKER_FIRST_NAME' => $agentName['firstName'],
|
||||
'BROKER_SECOND_NAME' => $agentName['secondName'],
|
||||
'BROKER_PHONE' => $agent->user->phone,
|
||||
'BROKER_INN' => $agent->company->inn,
|
||||
//'BROKER_CONTACT' => $agent->bitrixId(),
|
||||
'OBJECT_NAME' => Complex::find($this->client['complexId'])->name,
|
||||
'CALLBACK_URL' => route('api.client', ['hash' => $deal->confirmToken]),
|
||||
];
|
||||
$sender = new SendClient($deal->id, $data);
|
||||
if ($bitrixId = $agent->bitrixId())
|
||||
{
|
||||
$sender->setAgentId($bitrixId);
|
||||
}
|
||||
$response = $sender->send();
|
||||
if ($response)
|
||||
{
|
||||
return $response;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
@ -8,27 +8,27 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-100" wire:loading.remove wire:target="save, resetData, back">
|
||||
@if ($status == FormStatus::NEW || $status == FormStatus::READY)
|
||||
@if ($status == FormStatus::NEW || $status == FormStatus::IN_PROCESS || $status == FormStatus::READY)
|
||||
<ul class="nav nav-tabs d-flex align-items-end border-0 pb-0">
|
||||
@foreach ($clients as $clientIndex => $clientItem)
|
||||
@foreach ($contacts as $contactIndex => $contactItem)
|
||||
<li
|
||||
class="nav-item overflow-hidden @if ($clientIndex == $currentClientIndex) rounded-top border-top border-end border-start bg-light @else m-1 bg-secondary-subtle rounded rouded-5 @endif">
|
||||
<a class="nav-link me-1 border-0 @if ($clientIndex == $currentClientIndex) active text-primary @else py-1 text-dark @endif"
|
||||
aria-current="page" href="#" wire:click="setCurrentClient({{ $clientIndex }})">
|
||||
class="nav-item overflow-hidden @if ($contactIndex == $currentContactIndex) rounded-top border-top border-end border-start bg-light @else m-1 bg-secondary-subtle rounded rouded-5 @endif">
|
||||
<a class="nav-link me-1 border-0 @if ($contactIndex == $currentContactIndex) active text-primary @else py-1 text-dark @endif"
|
||||
aria-current="page" href="#" wire:click="setCurrentContactIndex({{ $contactIndex }})">
|
||||
<i class="bi bi-person-standing"></i>
|
||||
<span class="d-none d-xl-inline">
|
||||
@if (array_key_exists($clientIndex, $clientLabels))
|
||||
{{ $clientLabels[$clientIndex] }}
|
||||
@if (array_key_exists($contactIndex, $contactLabels))
|
||||
{{ $contactLabels[$contactIndex] }}
|
||||
@else
|
||||
Контакт {{ $clientIndex + 1 }}
|
||||
Контакт {{ $contactIndex + 1 }}
|
||||
@endif
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@endforeach
|
||||
@if ($maxClientsCount > count($clients))
|
||||
@if ($maxContactsCount > count($contacts))
|
||||
<li class="align-middle ps-2 mb-2">
|
||||
<a class="text-light " href="#" wire:click="addClient">
|
||||
<a class="text-light " href="#" wire:click="addContact">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="currentColor"
|
||||
class="bi bi-person-fill-add" viewBox="0 0 16 16">
|
||||
<path
|
||||
@ -45,13 +45,13 @@ class="bi bi-person-fill-add" viewBox="0 0 16 16">
|
||||
<div class="row mx-2 g-2">
|
||||
<div class="col-12 col-xl-6">
|
||||
<div class="form-floating mb-3 m-xl-0">
|
||||
<input wire:model.live="currentClient.firstName" id="currentClient.firstName"
|
||||
type="text"
|
||||
class="form-control rounded-4 @error('currentClient.firstName') is-invalid @enderror"
|
||||
name="currentClient.firstName" required autocomplete="currentClient.firstName"
|
||||
placeholder="Имя">
|
||||
<label for="currentClient.firstName">Имя</label>
|
||||
@error('currentClient.firstName')
|
||||
<input wire:model.live="contacts.{{ $currentContactIndex }}.firstName"
|
||||
id="contacts.{{ $currentContactIndex }}.firstName" type="text"
|
||||
class="form-control rounded-4 @error('contacts.' . $currentContactIndex . '.firstName') is-invalid @enderror"
|
||||
name="contacts.{{ $currentContactIndex }}.firstName" required
|
||||
autocomplete="contacts.{{ $currentContactIndex }}.firstName" placeholder="Имя">
|
||||
<label for="contacts.{{ $currentContactIndex }}.firstName">Имя</label>
|
||||
@error('contacts.' . $currentContactIndex . '.firstName')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@ -60,13 +60,14 @@ class="form-control rounded-4 @error('currentClient.firstName') is-invalid @ende
|
||||
</div>
|
||||
<div class="col-12 col-xl-6">
|
||||
<div class="form-floating mb-3 m-xl-0">
|
||||
<input wire:model.live="currentClient.secondName" id="currentClient.secondName"
|
||||
type="text"
|
||||
class="form-control rounded-4 @error('currentClient.secondName') is-invalid @enderror"
|
||||
name="currentClient.secondName" required autocomplete="currentClient.secondName"
|
||||
<input wire:model.live="contacts.{{ $currentContactIndex }}.secondName"
|
||||
id="contacts.{{ $currentContactIndex }}.secondName" type="text"
|
||||
class="form-control rounded-4 @error('contacts.' . $currentContactIndex . '.secondName') is-invalid @enderror"
|
||||
name="contacts.{{ $currentContactIndex }}.secondName" required
|
||||
autocomplete="contacts.{{ $currentContactIndex }}.secondName"
|
||||
placeholder="Фамилия">
|
||||
<label for="currentClient.secondName">Фамилия</label>
|
||||
@error('currentClient.secondName')
|
||||
<label for="contacts.{{ $currentContactIndex }}.secondName">Фамилия</label>
|
||||
@error('contacts.' . $currentContactIndex . '.secondName')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@ -74,24 +75,28 @@ class="form-control rounded-4 @error('currentClient.secondName') is-invalid @end
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@foreach ($currentClient['phones'] as $phoneKey => $phone)
|
||||
@foreach ($contacts[$currentContactIndex]['phones'] as $phoneKey => $phone)
|
||||
<div class="col-12 hstack gap-2">
|
||||
<div class="form-floating me-auto w-100">
|
||||
<input wire:model="currentClient.phone.{{ $phoneKey }}"
|
||||
id="currentClient.phone.{{ $phoneKey }}" type="tel" data-phone-pattern
|
||||
class="form-control rounded-4 @error('currentClient.phone.{{ $phoneKey }}') is-invalid @enderror"
|
||||
name="currentClient.phone.{{ $phoneKey }}" required autocomplete="phone"
|
||||
placeholder="Телефон клиента">
|
||||
<label for="currentClient.phone.{{ $phoneKey }}">Телефон
|
||||
{{ count($currentClient['phones']) > 1 ? ' ' . ($phoneKey + 1) : '' }}</label>
|
||||
@error('currentClient.phone.{{ $phoneKey }}')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<input
|
||||
wire:model.live="contacts.{{ $currentContactIndex }}.phones.{{ $phoneKey }}"
|
||||
id="contacts.{{ $currentContactIndex }}.phones.{{ $phoneKey }}"
|
||||
type="text" data-phone-pattern
|
||||
class="form-control rounded-4 @error('contacts.' . $currentContactIndex . '.phones.' . $phoneKey) is-invalid @enderror"
|
||||
name="contacts.{{ $currentContactIndex }}.phones.{{ $phoneKey }}" required
|
||||
autocomplete="phone" placeholder="Телефон клиента">
|
||||
<label
|
||||
for="contacts.{{ $currentContactIndex }}.phones.{{ $phoneKey }}">Телефон
|
||||
{{ count($contacts[$currentContactIndex]['phones']) > 1 ? ' ' . ($phoneKey + 1) : '' }}</label>
|
||||
|
||||
@error('contacts.' . $currentContactIndex . '.phones.' . $phoneKey)
|
||||
<span class="invalid-feedback d-block" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
@if (count($currentClient['phones']) == $phoneKey + 1 &&
|
||||
count($this->currentClient['phones']) < $this->maxClientPhonesCount)
|
||||
@if (count($contacts[$currentContactIndex]['phones']) == $phoneKey + 1 &&
|
||||
count($contacts[$currentContactIndex]['phones']) < $this->maxContactPhonesCount)
|
||||
<a class="" href="#" wire:click="addPhoneForClient"
|
||||
title="Добавить еще один телефон для клиента">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30"
|
||||
@ -106,16 +111,16 @@ class="form-control rounded-4 @error('currentClient.phone.{{ $phoneKey }}') is-i
|
||||
</div>
|
||||
@endforeach
|
||||
<div class="col-12">
|
||||
@if ($currentClientIndex == 0 && count($clients) <= 2)
|
||||
@if ($currentContactIndex == 0 && count($contacts) <= 2)
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" wire:click="toggleSecondClient" type="checkbox"
|
||||
<input class="form-check-input" wire:click="toggleSecondContact" type="checkbox"
|
||||
role="switch" id="switchCheckChecked"
|
||||
@if (count($clients) == 2) checked @endif>
|
||||
@if (count($contacts) == 2) checked @endif>
|
||||
<label class="form-check-label" for="switchCheckChecked">Добавить контакт
|
||||
супруга/супруги</label>
|
||||
</div>
|
||||
@endif
|
||||
@if ($currentClientIndex > 0)
|
||||
@if ($currentContactIndex > 0)
|
||||
<div class="text-end">
|
||||
<a wire:click="deleteContact" class="text-primary"
|
||||
style="text-decoration: underline dotted;" href="#">
|
||||
@ -125,12 +130,12 @@ class="form-control rounded-4 @error('currentClient.phone.{{ $phoneKey }}') is-i
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-floating mb-3">
|
||||
<select wire:model.live="client.complexId"
|
||||
class="form-select rounded-4 @error('client.complexId') is-invalid @enderror" id="client.complexId"
|
||||
name="client.complexId" aria-label="Жилой комплекс">
|
||||
<select wire:model.live="complexId"
|
||||
class="form-select rounded-4 @error('complexId') is-invalid @enderror" id="complexId"
|
||||
name="complexId" aria-label="Жилой комплекс">
|
||||
<option selected></option>
|
||||
@foreach ($complexes as $complex)
|
||||
<option value="{{ $complex['id'] }}">
|
||||
@ -138,18 +143,19 @@ class="form-select rounded-4 @error('client.complexId') is-invalid @enderror" id
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<label for="client.complexId">Жилой комплекс</label>
|
||||
@error('client.complexId')
|
||||
<label for="complexId">Жилой комплекс</label>
|
||||
@error('complexId')
|
||||
<span class="invalid-feedback " role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
@if (count($availableAgents) > 1)
|
||||
|
||||
<div class="form-floating mb-3">
|
||||
<select wire:model.live="agent" class="form-select rounded-4 @error('agent') is-invalid @enderror"
|
||||
id="agent" name="agent" aria-label="Агент">
|
||||
<select wire:model.live="agentId"
|
||||
class="form-select rounded-4 @error('agentId') is-invalid @enderror" id="agentId"
|
||||
name="agent" aria-label="Агент">
|
||||
<option selected></option>
|
||||
@foreach ($availableAgents as $agent)
|
||||
<option value="{{ $agent['id'] }}">
|
||||
@ -157,8 +163,8 @@ class="form-select rounded-4 @error('client.complexId') is-invalid @enderror" id
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<label for="client.complexId">Агент</label>
|
||||
@error('agent')
|
||||
<label for="agentId">Агент</label>
|
||||
@error('agentId')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
<strong>{{ $message }}</strong>
|
||||
</span>
|
||||
@ -166,16 +172,16 @@ class="form-select rounded-4 @error('client.complexId') is-invalid @enderror" id
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($status == FormStatus::READY && !$errors->any())
|
||||
@if ($status != FormStatus::READY)
|
||||
<div class="">
|
||||
<button wire:click="save" class="btn btn-secondary rounded-4 fw-bold fs-5 w-100 py-3"
|
||||
<button disabled class="btn btn-secondary disabled rounded-4 fw-bold fs-5 w-100 py-3"
|
||||
style="background-color: #20184d;">
|
||||
Создать нового клиента
|
||||
</button>
|
||||
</div>
|
||||
@else
|
||||
<div class="">
|
||||
<button disabled class="btn btn-secondary disabled rounded-4 fw-bold fs-5 w-100 py-3"
|
||||
<button wire:click="save" class="btn btn-secondary rounded-4 fw-bold fs-5 w-100 py-3"
|
||||
style="background-color: #20184d;">
|
||||
Создать нового клиента
|
||||
</button>
|
||||
@ -197,7 +203,7 @@ class="bi bi-check-circle-fill" viewBox="0 0 16 16">
|
||||
<div class="text-center fs-5 ">Мы проверим его уникальность и направим Вам информацию в личном
|
||||
кабинете</div>
|
||||
<div class="text-center mt-3">
|
||||
<button wire:click="$refresh" class="btn active border-white border-3 rounded">Продолжить</button>
|
||||
<button wire:click="resetData" class="btn active border-white border-3 rounded">Добавить еще</button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
@ -29,7 +29,15 @@ public function index(Request $request)
|
||||
'filter' => $filter
|
||||
]);
|
||||
}
|
||||
|
||||
public function show(Contract $contract)
|
||||
{
|
||||
return view(
|
||||
'contracts::contract',
|
||||
[
|
||||
'contract' => $contract
|
||||
]
|
||||
);
|
||||
}
|
||||
public function delete(Contract $contract)
|
||||
{
|
||||
$deal = $contract->deal;
|
||||
|
||||
@ -49,6 +49,16 @@ private function getContracts()
|
||||
|
||||
return $contracts->get();
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('contracts::livewire.table.index', [
|
||||
'contracts' => $this->getContracts(),
|
||||
'statuses' => ContractStatus::class
|
||||
]);
|
||||
}
|
||||
|
||||
/* ДАЛЕЕ - методы для применения всяких фильтров */
|
||||
private function appendMode(&$query)
|
||||
{
|
||||
if ($this->mode == 'active')
|
||||
@ -87,11 +97,5 @@ private function appendFilter(&$query)
|
||||
}
|
||||
}
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('contracts::livewire.table.index', [
|
||||
'contracts' => $this->getContracts(),
|
||||
'statuses' => ContractStatus::class
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,7 +5,7 @@
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
use App\Models\Deal\Deal;
|
||||
use Modules\Main\Models\Deal\Deal;
|
||||
class Contract extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
@ -20,7 +20,6 @@ class Contract extends Model
|
||||
'reward',
|
||||
'square',
|
||||
'floor',
|
||||
|
||||
'room',//Номер квартиры
|
||||
'date',//дата ДДУ
|
||||
'reg_date',//Дата регистрации ДДУ
|
||||
|
||||
@ -8,6 +8,6 @@
|
||||
Route::any('/contracts', [ContractsController::class, 'index'])->name('contracts');
|
||||
Route::post('/contracts/{contract}/delete', [ContractsController::class, 'delete'])->name('contract.delete');
|
||||
Route::post('/contracts/{contract}/comment', [ContractsController::class, 'comment'])->name('contract.comment');
|
||||
|
||||
Route::get('/contract/{contract}', [ContractsController::class, 'show'])->name('contract');
|
||||
|
||||
});
|
||||
239
app/Modules/Contracts/Views/contract.blade.php
Normal file
239
app/Modules/Contracts/Views/contract.blade.php
Normal file
@ -0,0 +1,239 @@
|
||||
@php($title = 'Договор')
|
||||
@extends('layouts.app')
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-8">
|
||||
<!--Имя и контакты-->
|
||||
@foreach ($contract->deal->clients as $client)
|
||||
<div class="row py-5">
|
||||
<div class="col">
|
||||
<div class="fs-6 text-secondary">ФИО</div>
|
||||
<div class="fw-bold fs-5 text-truncate">{{ $client->name }}</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="fs-6 text-secondary">Телефон</div>
|
||||
<div class="fw-bold fs-5 text-truncate">{{ $client->phone }}</div>
|
||||
</div>
|
||||
@if ($client->email)
|
||||
<div class="col">
|
||||
<div class="fs-6 text-secondary">Email</div>
|
||||
<div class="fw-bold fs-5 text-truncate">{{ $client->email }}</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="d-none col text-end">
|
||||
<a href="" class="btn border-1 border-secondary-subtle text-secondary rounded-4 p-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"
|
||||
class="bi bi-arrow-right" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd"
|
||||
d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
<!--Город-->
|
||||
<div class="row bg-white py-3">
|
||||
<div class="col-9">
|
||||
<div class="fs-5 fw-bold my-2">{{ $contract->deal->complex->city->name }}</div>
|
||||
<div class="fs-5 fw-bold text-secondary my-2">{{ $contract->deal->complex->name }}</div>
|
||||
</div>
|
||||
<div class="col-3 text-end">
|
||||
</div>
|
||||
</div>
|
||||
<!--Основная часть-->
|
||||
<div class="row">
|
||||
<div class="col col-lg-8">
|
||||
<div class="row my-4">
|
||||
<div class="col col-md-6">
|
||||
<div class="fs-6 text-secondary">Статус</div>
|
||||
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">
|
||||
{{ __('contracts.status_' . $contract->status) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col col-md-6">
|
||||
<div class="fs-6 text-secondary">Дата обновления</div>
|
||||
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">
|
||||
{{ $contract->updated_at->format('d.m.y H:i') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
@if ($contract->square)
|
||||
<div class="col col-md-4">
|
||||
<div class="fs-6 text-secondary">Площадь объекта</div>
|
||||
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">{{ $contract->square }}</div>
|
||||
</div>
|
||||
@endif
|
||||
@if ($contract->floor)
|
||||
<div class="col col-md-4">
|
||||
<div class="fs-6 text-secondary">Этаж</div>
|
||||
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">{{ $contract->floor }}</div>
|
||||
</div>
|
||||
@endif
|
||||
@if ($contract->room)
|
||||
<div class="col col-md-4">
|
||||
<div class="fs-6 text-secondary">Помещение</div>
|
||||
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">{{ $contract->room }}</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="row my-4">
|
||||
<div class="col col-md-6">
|
||||
<div class="fs-6 text-secondary">Стоимость</div>
|
||||
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">
|
||||
{{ number_format($contract->price, 2, ',', ' ') }}
|
||||
<div class="fs-6">
|
||||
<span class="badge bg-secondary">{{ $contract->payment_type }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col col-md-6">
|
||||
<div class="fs-6 text-secondary">Вознаграждение</div>
|
||||
<div class="fw-bold fs-5 text-truncate text-dark-emphasis">
|
||||
{{ number_format(GetAgentPaymentForContract($contract), 2, ',', ' ') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col col-lg-4 p-3">
|
||||
<div class="rounded-4 ratio ratio-1x1 rounded overflow-hidden" style="background-color:#ebeef5"
|
||||
data-base64="">
|
||||
@if ($contract->base64_image)
|
||||
<div class="w-100 h-100 d-flex align-items-center overflow-hidden zoomable-container"
|
||||
style='background-image:url("data:image/jpeg;base64, {{ $contract->base64_image }}");'>
|
||||
<div class="text-center mx-auto zoom-button">
|
||||
<svg class="text-white" xmlns="http://www.w3.org/2000/svg" width="70" height="70"
|
||||
fill="currentColor" class="bi bi-zoom-in" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd"
|
||||
d="M6.5 12a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11M13 6.5a6.5 6.5 0 1 1-13 0 6.5 6.5 0 0 1 13 0" />
|
||||
<path
|
||||
d="M10.344 11.742q.044.06.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1 1 0 0 0-.115-.1 6.5 6.5 0 0 1-1.398 1.4z" />
|
||||
<path fill-rule="evenodd"
|
||||
d="M6.5 3a.5.5 0 0 1 .5.5V6h2.5a.5.5 0 0 1 0 1H7v2.5a.5.5 0 0 1-1 0V7H3.5a.5.5 0 0 1 0-1H6V3.5a.5.5 0 0 1 .5-.5" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row pt-3 border-1 border-top">
|
||||
<div class="col">
|
||||
<div class="fs-6 text-secondary hstack gap-2">
|
||||
<span>Комментарий к договору</span>
|
||||
@if ($contract->comment)
|
||||
<a class="ms-auto" href="#" data-bs-toggle="modal" data-bs-target="#contractCommentModal">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||
class="bi bi-pen" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="m13.498.795.149-.149a1.207 1.207 0 1 1 1.707 1.708l-.149.148a1.5 1.5 0 0 1-.059 2.059L4.854 14.854a.5.5 0 0 1-.233.131l-4 1a.5.5 0 0 1-.606-.606l1-4a.5.5 0 0 1 .131-.232l9.642-9.642a.5.5 0 0 0-.642.056L6.854 4.854a.5.5 0 1 1-.708-.708L9.44.854A1.5 1.5 0 0 1 11.5.796a1.5 1.5 0 0 1 1.998-.001m-.644.766a.5.5 0 0 0-.707 0L1.95 11.756l-.764 3.057 3.057-.764L14.44 3.854a.5.5 0 0 0 0-.708z" />
|
||||
</svg>
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
@if ($contract->comment)
|
||||
<div class="fw-bold fs-5 text-dark-emphasis">{{ $contract->comment }}</div>
|
||||
@else
|
||||
<div><a href="#" data-bs-toggle="modal" data-bs-target="#contractCommentModal">Оставьте
|
||||
комментарий</a>, он будет виден
|
||||
только вам</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-4 py-3 text-dark" style="background-color:#eef5fb">
|
||||
<div class="fw-bold fs-5 mb-3">История договора</div>
|
||||
@if ($contract->deal->notifications->count() == 0)
|
||||
<div class="d-flex justify-content-center align-items-center">
|
||||
<div class="d-grid gap-1 p-3">
|
||||
<i class="bi bi-inbox display-5 text-center"></i>
|
||||
<span class="fs-6 fw-semibold">{{ __('notifications.has no history') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
@foreach ($contract->deal->notifications as $notification)
|
||||
<div class="d-flex flex-row mb-3">
|
||||
<div class="pe-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" fill="currentColor"
|
||||
class="bi bi-record-circle-fill align-middle" viewBox="0 0 16 16">
|
||||
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0m-8 3a3 3 0 1 0 0-6 3 3 0 0 0 0 6" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="">
|
||||
<div class="text-secondary">{{ $notification->created_at }}</div>
|
||||
<div class="fw-bold text-dark-emphasis">{{ $notification->data['text'] }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="contractCommentModal" tabindex="-1" aria-labelledby="exampleModalLabel"
|
||||
aria-hidden="true">
|
||||
<form class="modal-dialog" method="post"
|
||||
action="{{ route('contract.comment', ['contract' => $contract]) }}">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="exampleModalLabel">Комментарий к договору</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@csrf
|
||||
<div class="mb-3">
|
||||
<label for="contractComment" class="form-label">Ваш комментарий</label>
|
||||
<textarea class="form-control" id="contractComment" name="comment" rows="3">{{ $contract->comment }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
|
||||
<button type="submit" class="btn btn-primary">Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
.zoomable-container {
|
||||
backdrop-filter: blur(10px);
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.zoomable-container:not(.zoomed):hover {
|
||||
transform: scale(1.5);
|
||||
background-color: rgb(33 33 33 / 60%);
|
||||
background-blend-mode: multiply;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.zoomable-container.zoomed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.zoomable-container.zoomed .zoom-button {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
var images = document.querySelectorAll(".zoomable-container");
|
||||
Array.prototype.forEach.call(images, function(img) {
|
||||
// Do stuff here
|
||||
|
||||
img.addEventListener('click', function() {
|
||||
console.log(img.classList.contains('zoomed'));
|
||||
if (!img.classList.contains('zoomed')) {
|
||||
img.classList.add('zoomed');
|
||||
} else {
|
||||
img.classList.remove('zoomed');
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
@ -16,13 +16,18 @@
|
||||
<tbody class="">
|
||||
@foreach ($contracts as $contract)
|
||||
<tr class="d-flex d-lg-table-row flex-column flex-md-row my-4 my-lg-0" scope="row">
|
||||
<td class="align-middle d-flex flex-row">
|
||||
<td class="align-middle d-flex flex-row d-lg-table-cell">
|
||||
<div class="d-block d-md-none me-2">
|
||||
<div class="border rounded-pill "
|
||||
style="width: 1.5rem; height:1.5rem;background-color:{{ $statuses::getHtmlColor($contract->status) }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-100">{{ $contract->deal->user->name }}</div>
|
||||
<div class="w-100">
|
||||
@php($clients = $contract->deal->clients)
|
||||
@foreach ($clients as $client)
|
||||
<div>{{ $client->name }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</td>
|
||||
<td class="d-block d-lg-none d-flex flex-row">
|
||||
<div class="w-100">
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('deal_clients', function (Blueprint $table)
|
||||
{
|
||||
$table->id();
|
||||
$table->foreignId(column: 'deal_id')->references('id')->on('deals')->onDelete('cascade');
|
||||
$table->foreignId(column: 'client_id')->references('id')->on('users');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('docs');
|
||||
}
|
||||
};
|
||||
@ -81,7 +81,7 @@ protected static function booted(): void
|
||||
}
|
||||
private function notify()
|
||||
{
|
||||
$this->user->notify(new AgentCreated($this));
|
||||
//$this->user->notify(new AgentCreated($this));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,10 +6,12 @@
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Modules\Payment\Traits\Paymentable;
|
||||
use Modules\Main\Models\City;
|
||||
use Modules\Bitrix\Traits\Bitrixable;
|
||||
class Company extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Paymentable;
|
||||
use Bitrixable;
|
||||
const STATUS_NEW = 'new';
|
||||
const STATUS_ACCEPTED = 'accepted';
|
||||
const STATUS_DECLINED = 'declined';
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Deal;
|
||||
namespace Modules\Main\Models\Deal;
|
||||
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
@ -9,22 +9,39 @@
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
|
||||
use Modules\User\Models\User;
|
||||
use App\Models\Deal\Deal;
|
||||
use Modules\Main\Models\Agent\Agent;
|
||||
use Modules\Bitrix\Traits\Bitrixable;
|
||||
class Client extends User
|
||||
{
|
||||
use Bitrixable;
|
||||
protected $table = 'users';
|
||||
public function deals()
|
||||
{
|
||||
return $this->hasMany(Deal::class, 'client_id');
|
||||
}
|
||||
return $this->hasManyThrough(
|
||||
Deal::class
|
||||
,
|
||||
DealClients::class
|
||||
,
|
||||
'client_id'
|
||||
,
|
||||
'id'
|
||||
,
|
||||
'id'
|
||||
,
|
||||
'deal_id'
|
||||
);
|
||||
|
||||
}
|
||||
public function dealsWithContracts()
|
||||
{
|
||||
return $this->hasMany(Deal::class, 'client_id')->whereHas('contracts');
|
||||
return $this->hasManyThrough(Deal::class, DealClients::class)->whereHas('contracts');
|
||||
}
|
||||
public function ofAgent(Agent $agent)
|
||||
{
|
||||
return $this->deals->where('agent_id', $agent->id);
|
||||
}
|
||||
public function create()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
66
app/Modules/Main/Models/Deal/Deal.php
Normal file
66
app/Modules/Main/Models/Deal/Deal.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Main\Models\Deal;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Modules\User\Models\User;
|
||||
use Modules\User\Models\UserRole;
|
||||
use Modules\User\Models\Role;
|
||||
use Modules\Contracts\Models\Contract;
|
||||
use Modules\Main\Models\Complex;
|
||||
use Modules\Main\Models\Agent\Agent;
|
||||
use Modules\Bitrix\Traits\Bitrixable;
|
||||
class Deal extends Model
|
||||
{
|
||||
use HasFactory, Notifiable, Bitrixable;
|
||||
protected $fillable = [
|
||||
'complex_id',
|
||||
'agent_id',
|
||||
'bitrix_id',
|
||||
'is_unique',
|
||||
'confirm_token'
|
||||
];
|
||||
public function complex()
|
||||
{
|
||||
return $this->belongsTo(Complex::class, 'complex_id');
|
||||
}
|
||||
public function clients()
|
||||
{
|
||||
return $this->hasManyThrough(
|
||||
Client::class
|
||||
,
|
||||
DealClients::class
|
||||
,
|
||||
'deal_id'
|
||||
,
|
||||
'id'
|
||||
,
|
||||
'id'
|
||||
,
|
||||
'client_id'
|
||||
|
||||
);
|
||||
//return $this->hasMany(DealClients::class);
|
||||
}
|
||||
public function agent()
|
||||
{
|
||||
return $this->belongsTo(Agent::class, 'agent_id');
|
||||
}
|
||||
|
||||
public function contract()
|
||||
{
|
||||
return $this->hasOne(Contract::class, 'deal_id');
|
||||
}
|
||||
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::creating(function (Deal $deal)
|
||||
{
|
||||
$deal->confirm_token = hash('sha256', json_encode($deal->all()));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
44
app/Modules/Main/Models/Deal/DealClients.php
Normal file
44
app/Modules/Main/Models/Deal/DealClients.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Main\Models\Deal;
|
||||
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
|
||||
use Modules\User\Models\User;
|
||||
use Modules\User\Models\UserRole;
|
||||
use Modules\User\Models\Role;
|
||||
|
||||
use Modules\Main\Models\Agent\Agent;
|
||||
use Modules\Bitrix\Traits\Bitrixable;
|
||||
|
||||
class DealClients extends User
|
||||
{
|
||||
use Bitrixable;
|
||||
protected $table = 'deal_clients';
|
||||
protected $fillable = ['deal_id', 'client_id'];
|
||||
public function deal()
|
||||
{
|
||||
return $this->belongsTo(Deal::class);
|
||||
}
|
||||
|
||||
public function client()
|
||||
{
|
||||
return $this->belongsTo(related: Client::class);
|
||||
}
|
||||
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::created(function (DealClients $dealClient)
|
||||
{
|
||||
UserRole::create([
|
||||
'user_id' => $dealClient->client_id,
|
||||
'role_id' => Role::CLIENT
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
11
app/Modules/Main/Models/Deal/DealStatus.php
Normal file
11
app/Modules/Main/Models/Deal/DealStatus.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Main\Models\Deal;
|
||||
|
||||
final class DealStatus
|
||||
{
|
||||
public const NEW = 'NEW';
|
||||
public const MODERATION = 'MODERATION';
|
||||
public const UNIQUE = 'UNIQUE';
|
||||
public const NOT_UNIQUE = 'NOT UNIQUE';
|
||||
}
|
||||
@ -4,7 +4,7 @@
|
||||
@if ($clients->count() == 0)
|
||||
<div class="text-center py-5">Нет данных для отображения</div>
|
||||
@endif
|
||||
<div class="vstack gap-3">
|
||||
<div class="vstack gap-2">
|
||||
@foreach ($clients as $client)
|
||||
<?php
|
||||
$complexesNames = [];
|
||||
@ -19,7 +19,6 @@
|
||||
$complexesNames = implode(', ', array: $complexesNames);
|
||||
$dealsWithContracts = $client->deals()->whereHas('contract');
|
||||
?>
|
||||
|
||||
@if ($mode == 'full')
|
||||
<div class="d-flex flex-row m-0 my-2 px-2 client-row">
|
||||
<div class="d-flex flex-column flex-md-row w-100">
|
||||
@ -35,7 +34,6 @@
|
||||
{{ $client->phone }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col col-md-1 text-end contracts-link">
|
||||
@if ($dealsWithContracts->count() == 1)
|
||||
<a href="{{ route('contract', ['contract' => $dealsWithContracts->first()->contract]) }}"
|
||||
@ -60,7 +58,7 @@ class="icon-link icon-link-hover">
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="m-2">
|
||||
<div class="m-2 my-1">
|
||||
@if ($dealsWithContracts->count() == 1)
|
||||
<a href="{{ route('contract', ['contract' => $dealsWithContracts->first()->contract]) }}"
|
||||
class="icon-link icon-link-hover w-100 hstack gap-2 text-decoration-none">
|
||||
@ -90,6 +88,10 @@ class="icon-link icon-link-hover w-100 hstack gap-2 text-decoration-none">
|
||||
d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8" />
|
||||
</svg>
|
||||
</a>
|
||||
@else
|
||||
<a href="" class="icon-link icon-link-hover w-100 hstack gap-2 text-decoration-none">
|
||||
<span class="text-dark">{{ $client->name }}</span>
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@ -8,8 +8,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row d-none d-md-flex">
|
||||
<div class="col-12 col-lg-6 mb-2">
|
||||
<div class="" data-bs-toggle="modal" data-bs-target="#plan7Modal">
|
||||
<div class="col-12 col-lg-6 d-flex flex-column">
|
||||
<div class="mb-auto" data-bs-toggle="modal" data-bs-target="#plan7Modal">
|
||||
<a href="#"
|
||||
class="list-group-item list-group-item-action p-3 bg-white rounded border border-light-subtle"
|
||||
aria-current="true">
|
||||
@ -27,7 +27,7 @@ class="list-group-item list-group-item-action p-3 bg-white rounded border border
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<div class="">
|
||||
<div class="hstack gap-2">
|
||||
<div class="fs-5 fw-bold">Клиенты</div>
|
||||
<div class="ms-auto p-2">
|
||||
@ -40,7 +40,7 @@ class="list-group-item list-group-item-action p-3 bg-white rounded border border
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="p-2 px-sm-4 py-sm-3 bg-primary border rounded-3 mx-auto" style="min-height:30em;">
|
||||
<div class="p-2 px-sm-4 py-sm-3 bg-primary border rounded-3 mx-auto h-100" style="min-height:30em;">
|
||||
<div class="h4 pb-2 mb-2 fw-bold ">
|
||||
<small>Добавить клиента</small>
|
||||
</div>
|
||||
|
||||
@ -39,7 +39,6 @@
|
||||
{
|
||||
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
|
||||
Route::get('/clients/table', [App\Http\Controllers\ClientsTableController::class, 'index'])->name('clients.table');
|
||||
Route::get('/contract/{contract}', [App\Http\Controllers\Deal\ContractController::class, 'index'])->name('contract');
|
||||
Route::get('/company/details/{company?}', [App\Http\Controllers\Company\DetailsController::class, 'index'])->name('company.details');
|
||||
|
||||
Route::post('/company/{company}/details/', [App\Http\Controllers\Company\DetailsController::class, 'store'])->name('company.details.store');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user