add CRM module start

This commit is contained in:
root
2026-01-15 07:09:36 +03:00
parent b14f293a45
commit b810a17649
40 changed files with 3807 additions and 14 deletions
+141
View File
@@ -0,0 +1,141 @@
<?php
namespace App\Modules\CRM\Services;
use App\Modules\CRM\Models\DealModel;
use App\Modules\CRM\Models\DealStageModel;
class DealService
{
protected DealModel $dealModel;
protected DealStageModel $stageModel;
public function __construct()
{
$this->dealModel = new DealModel();
$this->stageModel = new DealStageModel();
}
/**
* Создать новую сделку
*/
public function createDeal(array $data, int $userId): int
{
$data['created_by'] = $userId;
return $this->dealModel->insert($data);
}
/**
* Обновить сделку
*/
public function updateDeal(int $dealId, array $data, int $userId): bool
{
$oldDeal = $this->dealModel->find($dealId);
if (!$oldDeal) {
return false;
}
return $this->dealModel->update($dealId, $data);
}
/**
* Изменить этап сделки
*/
public function changeStage(int $dealId, int $newStageId, int $userId): bool
{
$deal = $this->dealModel->find($dealId);
if (!$deal) {
return false;
}
$newStage = $this->stageModel->find($newStageId);
if (!$newStage) {
return false;
}
return $this->dealModel->update($dealId, ['stage_id' => $newStageId]);
}
/**
* Мягко удалить сделку
*/
public function deleteDeal(int $dealId, int $userId): bool
{
$deal = $this->dealModel->find($dealId);
if (!$deal) {
return false;
}
return $this->dealModel->delete($dealId);
}
/**
* Восстановить удалённую сделку
*/
public function restoreDeal(int $dealId, int $userId): bool
{
return $this->dealModel->delete($dealId, false);
}
/**
* Получить сделку по ID
*/
public function getDeal(int $dealId): ?array
{
return $this->dealModel->find($dealId);
}
/**
* Получить сделки с фильтрами
*/
public function getDeals(
int $organizationId,
?int $stageId = null,
?int $assignedUserId = null,
?string $search = null,
?string $dateFrom = null,
?string $dateTo = null
): array {
return $this->dealModel->getDealsByOrganization(
$organizationId,
$stageId,
$assignedUserId,
$search,
$dateFrom,
$dateTo
);
}
/**
* Получить сделки для Канбана
*/
public function getDealsForKanban(int $organizationId): array
{
return $this->dealModel->getDealsGroupedByStage($organizationId);
}
/**
* Получить сделки для календаря
*/
public function getDealsForCalendar(int $organizationId, string $month): array
{
return $this->dealModel->getDealsForCalendar($organizationId, $month);
}
/**
* Получить статистику по сделкам
*/
public function getStats(int $organizationId): array
{
return $this->dealModel->getDealStats($organizationId);
}
/**
* Получить сделку по ID с JOIN-ами
*/
public function getDealWithJoins(int $dealId, int $organizationId): ?array
{
return $this->dealModel->getWithJoins($dealId, $organizationId);
}
}
@@ -0,0 +1,99 @@
<?php
namespace App\Modules\CRM\Services;
use App\Modules\CRM\Models\DealModel;
use App\Modules\CRM\Models\DealStageModel;
class DealStageService
{
protected DealStageModel $stageModel;
public function __construct()
{
$this->stageModel = new DealStageModel();
}
/**
* Создать новый этап
*/
public function createStage(array $data): int
{
$data['order_index'] = $this->stageModel->getNextOrderIndex($data['organization_id']);
return $this->stageModel->insert($data);
}
/**
* Обновить этап
*/
public function updateStage(int $stageId, array $data): bool
{
return $this->stageModel->update($stageId, $data);
}
/**
* Удалить этап (мягкое удаление)
*/
public function deleteStage(int $stageId): bool
{
return $this->stageModel->delete($stageId);
}
/**
* Получить этап по ID
*/
public function getStage(int $stageId): ?array
{
return $this->stageModel->find($stageId);
}
/**
* Получить все этапы организации
*/
public function getOrganizationStages(int $organizationId): array
{
return $this->stageModel->getStagesByOrganization($organizationId);
}
/**
* Изменить порядок этапов
*/
public function reorderStages(int $organizationId, array $stageOrders): bool
{
foreach ($stageOrders as $order => $stageId) {
$this->stageModel->update($stageId, ['order_index' => $order]);
}
return true;
}
/**
* Проврить, можно ли удалить этап (есть ли сделки на этом этапе)
*/
public function canDeleteStage(int $stageId): bool
{
$dealModel = new DealModel();
$count = $dealModel->where('stage_id', $stageId)
->where('deleted_at', null)
->countAllResults();
return $count === 0;
}
/**
* Инициализировать этапы по умолчанию для новой организации
*/
public function initializeDefaultStages(int $organizationId): array
{
return $this->stageModel->createDefaultStages($organizationId);
}
/**
* Получить список этапов для выпадающего списка
*/
public function getStagesList(int $organizationId): array
{
return $this->stageModel->getStagesList($organizationId);
}
}