bp/app/Modules/CRM/Models/DealModel.php

230 lines
8.2 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Modules\CRM\Models;
use CodeIgniter\Model;
class DealModel extends Model
{
protected $table = 'deals';
protected $primaryKey = 'id';
protected $useSoftDeletes = true;
protected $useTimestamps = true;
protected $createdField = 'created_at';
protected $updatedField = 'updated_at';
protected $deletedField = 'deleted_at';
protected $returnType = 'array';
protected $allowedFields = [
'organization_id',
'contact_id',
'company_id',
'title',
'description',
'amount',
'currency',
'stage_id',
'assigned_user_id',
'expected_close_date',
'created_by',
];
/**
* Получить сделки с JOIN-ами для таблицы
*/
public function getForTable(int $organizationId): array
{
return $this->select('
deals.id,
deals.title,
deals.amount,
deals.currency,
deals.expected_close_date,
deals.created_at,
deals.deleted_at,
ds.name as stage_name,
ds.color as stage_color,
ds.type as stage_type,
ds.probability as stage_probability,
c.name as contact_name,
c.email as contact_email,
oc.name as client_name,
au.name as assigned_user_name,
au.email as assigned_user_email,
cb.name as created_by_name
')
->join('deal_stages ds', 'deals.stage_id = ds.id', 'left')
->join('contacts c', 'deals.contact_id = c.id', 'left')
->join('organizations_clients oc', 'deals.company_id = oc.id', 'left')
->join('users au', 'deals.assigned_user_id = au.id', 'left')
->join('users cb', 'deals.created_by = cb.id', 'left')
->where('deals.organization_id', $organizationId)
->orderBy('deals.created_at', 'DESC')
->findAll();
}
/**
* Получить сделки организации с фильтрами
*/
public function getDealsByOrganization(
int $organizationId,
?int $stageId = null,
?int $assignedUserId = null,
?string $search = null,
?string $dateFrom = null,
?string $dateTo = null
): array {
$builder = $this->where('organization_id', $organizationId);
if ($stageId) {
$builder->where('stage_id', $stageId);
}
if ($assignedUserId) {
$builder->where('assigned_user_id', $assignedUserId);
}
if ($search) {
$builder->groupStart()
->like('title', $search)
->orLike('description', $search)
->groupEnd();
}
if ($dateFrom) {
$builder->where('expected_close_date >=', $dateFrom);
}
if ($dateTo) {
$builder->where('expected_close_date <=', $dateTo);
}
return $builder->orderBy('created_at', 'DESC')->findAll();
}
/**
* Получить сделки, сгруппированные по этапам (для Канбана)
*/
public function getDealsGroupedByStage(int $organizationId): array
{
$deals = $this->select('deals.*, ds.name as stage_name, ds.color as stage_color, ds.type as stage_type, au.name as assigned_user_name')
->join('deal_stages ds', 'deals.stage_id = ds.id', 'left')
->join('users au', 'deals.assigned_user_id = au.id', 'left')
->join('contacts c', 'deals.contact_id = c.id', 'left')
->join('organizations_clients oc', 'deals.company_id = oc.id', 'left')
->where('deals.organization_id', $organizationId)
->where('deals.deleted_at', null)
->orderBy('ds.order_index', 'ASC')
->orderBy('deals.created_at', 'DESC')
->findAll();
$grouped = [];
foreach ($deals as $deal) {
$stageId = $deal['stage_id'] ?? 0;
if (!isset($grouped[$stageId])) {
$grouped[$stageId] = [
'stage_name' => $deal['stage_name'] ?? 'Без этапа',
'stage_color' => $deal['stage_color'] ?? '#6B7280',
'stage_type' => $deal['stage_type'] ?? 'progress',
'deals' => [],
'total_amount' => 0,
];
}
$grouped[$stageId]['deals'][] = $deal;
$grouped[$stageId]['total_amount'] += (float) $deal['amount'];
}
return $grouped;
}
/**
* Получить сделки для календаря (по дате закрытия)
*/
public function getDealsForCalendar(int $organizationId, string $month): array
{
return $this->select('deals.*, ds.color as stage_color, ds.name as stage_name')
->join('deal_stages ds', 'deals.stage_id = ds.id', 'left')
->where('deals.organization_id', $organizationId)
->where('deals.deleted_at', null)
->where('deals.expected_close_date >=', date('Y-m-01', strtotime($month)))
->where('deals.expected_close_date <=', date('Y-m-t', strtotime($month)))
->orderBy('expected_close_date', 'ASC')
->findAll();
}
/**
* Получить статистику по сделкам
*/
public function getDealStats(int $organizationId): array
{
$openDeals = $this->select('COUNT(*) as count, COALESCE(SUM(amount), 0) as total')
->where('organization_id', $organizationId)
->where('deleted_at', null)
->whereIn('stage_id', function($builder) use ($organizationId) {
return $builder->select('id')
->from('deal_stages')
->where('organization_id', $organizationId)
->whereIn('type', ['progress']);
})
->get()
->getRow();
$wonDeals = $this->select('COUNT(*) as count, COALESCE(SUM(amount), 0) as total')
->where('organization_id', $organizationId)
->where('deleted_at', null)
->whereIn('stage_id', function($builder) use ($organizationId) {
return $builder->select('id')
->from('deal_stages')
->where('organization_id', $organizationId)
->where('type', 'won');
})
->get()
->getRow();
$lostDeals = $this->select('COUNT(*) as count')
->where('organization_id', $organizationId)
->where('deleted_at', null)
->whereIn('stage_id', function($builder) use ($organizationId) {
return $builder->select('id')
->from('deal_stages')
->where('organization_id', $organizationId)
->where('type', 'lost');
})
->get()
->getRow();
return [
'open_count' => $openDeals->count,
'open_total' => $openDeals->total,
'won_count' => $wonDeals->count,
'won_total' => $wonDeals->total,
'lost_count' => $lostDeals->count,
];
}
/**
* Получить сделку по ID с JOIN-ами
*/
public function getWithJoins(int $dealId, int $organizationId): ?array
{
return $this->select('
deals.*,
ds.name as stage_name,
ds.color as stage_color,
ds.type as stage_type,
ds.probability as stage_probability,
c.name as contact_name,
c.email as contact_email,
oc.name as client_name,
au.name as assigned_user_name,
au.email as assigned_user_email
')
->join('deal_stages ds', 'deals.stage_id = ds.id', 'left')
->join('contacts c', 'deals.contact_id = c.id', 'left')
->join('organizations_clients oc', 'deals.company_id = oc.id', 'left')
->join('users au', 'deals.assigned_user_id = au.id', 'left')
->where('deals.id', $dealId)
->where('deals.organization_id', $organizationId)
->first();
}
}