ultimatepos/Modules/Connector/Http/Controllers/Api/V2/CrmExtendedController.php

439 lines
16 KiB
PHP

<?php
namespace Modules\Connector\Http\Controllers\Api\V2;
use App\Business;
use App\Category;
use App\Contact;
use App\Services\Api\BusinessContextService;
use App\User;
use App\Utils\ModuleUtil;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Modules\Connector\Http\Controllers\Api\ContactController as V1ContactController;
use Modules\Crm\Entities\Campaign;
use Modules\Crm\Entities\CrmCallLog;
use Modules\Crm\Entities\CrmContact;
use Modules\Crm\Entities\CrmContactPersonCommission;
use Modules\Crm\Entities\Proposal;
use Modules\Crm\Entities\ProposalTemplate;
use Modules\Crm\Entities\Schedule;
use Modules\Crm\Entities\ScheduleLog;
use Modules\Crm\Utils\CrmUtil;
class CrmExtendedController extends BaseController
{
public function __construct(
protected BusinessContextService $contextService,
protected ModuleUtil $moduleUtil,
protected CrmUtil $crmUtil,
protected V1ContactController $contactController
) {
}
protected function ensureCrm(): void
{
if (! $this->moduleUtil->isModuleInstalled('Crm')) {
abort(403, 'Unauthorized action.');
}
}
public function dashboard(Request $request)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$user = Auth::user();
$user_id = $user->id;
$is_admin = $this->crmUtil->is_admin($user);
$contacts = Contact::where('business_id', $business_id)->Active()->get();
$customers = $contacts->whereIn('type', ['customer', 'both']);
$leads = $contacts->where('type', 'lead');
$my_follow_ups = User::user()
->where('users.id', $user_id)
->join('crm_schedule_users as su', 'su.user_id', '=', 'users.id')
->join('crm_schedules as follow_ups', 'follow_ups.id', '=', 'su.schedule_id')
->select('follow_ups.status', DB::raw('COUNT(su.id) as total_follow_ups'))
->groupBy('follow_ups.status')
->get();
$my_follow_ups_arr = [];
foreach ($my_follow_ups as $follow_up) {
if (! empty($follow_up->status)) {
$my_follow_ups_arr[$follow_up->status] = $follow_up->total_follow_ups;
} else {
$my_follow_ups_arr['__other'] = $follow_up->total_follow_ups;
}
}
$my_call_logs = null;
if (config('constants.enable_crm_call_log')) {
$today = Carbon::now()->format('Y-m-d');
$yesterday = Carbon::yesterday()->format('Y-m-d');
$first_day_of_month = Carbon::now()->startOfMonth()->format('Y-m-d');
$my_call_logs = CrmCallLog::where('business_id', $business_id)
->where('created_by', $user_id)
->whereDate('start_time', '>=', $first_day_of_month)
->select(
DB::raw("SUM(IF(DATE(start_time)='{$today}', 1, 0)) as calls_today"),
DB::raw("SUM(IF(DATE(start_time)='{$yesterday}', 1, 0)) as calls_yesterday"),
DB::raw('COUNT(id) as calls_this_month')
)->first();
}
$todays_followups = Schedule::whereHas('users', function ($q) use ($user_id) {
$q->where('user_id', $user_id);
})
->whereIn('status', ['open', 'scheduled'])
->whereDate('start_datetime', Carbon::now()->format('Y-m-d'))
->count();
$my_leads = CrmContact::where('contacts.business_id', $business_id)
->where('contacts.type', 'lead')
->whereHas('leadUsers', function ($q) use ($user_id) {
$q->where('user_id', $user_id);
})->count();
$my_conversion = Contact::where('converted_by', $user_id)->count();
$leads_by_life_stage = [];
foreach ($leads->groupBy('crm_life_stage') as $stage_id => $group) {
$leads_by_life_stage[] = [
'life_stage_id' => $stage_id,
'count' => $group->count(),
];
}
return $this->success([
'is_admin' => $is_admin,
'todays_followups' => $todays_followups,
'my_leads' => $my_leads,
'my_conversion' => $my_conversion,
'my_follow_ups' => $my_follow_ups_arr,
'follow_up_statuses' => Schedule::statusDropdown(),
'my_call_logs' => $my_call_logs,
'total_customers' => $customers->count(),
'total_leads' => $leads->count(),
'total_sources' => Category::where('business_id', $business_id)->where('category_type', 'source')->count(),
'total_life_stages' => Category::where('business_id', $business_id)->where('category_type', 'life_stage')->count(),
'leads_by_life_stage' => $leads_by_life_stage,
'leads_count_by_source' => CrmContact::getContactsCountBySourceOfGivenTyps($business_id, ['lead']),
'customers_count_by_source' => CrmContact::getContactsCountBySourceOfGivenTyps($business_id, ['customer', 'both']),
]);
}
public function storeLead(Request $request)
{
$this->ensureCrm();
$request->merge(['type' => 'lead']);
return $this->contactController->store($request);
}
public function showLead(Request $request, $id)
{
$this->ensureCrm();
return $this->contactController->show($id);
}
public function updateLead(Request $request, $id)
{
$this->ensureCrm();
$request->merge(['type' => 'lead']);
return $this->contactController->update($request, $id);
}
public function campaigns(Request $request)
{
$this->ensureCrm();
$user = Auth::user();
$business_id = $this->contextService->getBusinessId($request);
$query = Campaign::where('business_id', $business_id)->orderByDesc('created_at');
if (! $user->can('crm.access_all_campaigns') && $user->can('crm.access_own_campaigns')) {
$query->where('created_by', $user->id);
}
return $this->paginated($query->paginate($request->input('per_page', 25)));
}
public function showCampaign(Request $request, $id)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$campaign = Campaign::where('business_id', $business_id)->findOrFail($id);
return $this->success($campaign);
}
public function storeCampaign(Request $request)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$request->validate([
'name' => 'required',
'campaign_type' => 'required|in:sms,email',
]);
$input = $request->only('name', 'campaign_type', 'subject', 'email_body', 'sms_body');
$input['business_id'] = $business_id;
$input['created_by'] = Auth::id();
$input['contact_ids'] = $request->input('contact_ids', []);
$campaign = Campaign::create($input);
return $this->success($campaign, '', 201);
}
public function updateCampaign(Request $request, $id)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$campaign = Campaign::where('business_id', $business_id)->findOrFail($id);
if (! empty($campaign->sent_on)) {
return $this->error('Campaign already sent', 422);
}
$input = $request->only('name', 'campaign_type', 'subject', 'email_body', 'sms_body');
if ($request->has('contact_ids')) {
$input['contact_ids'] = $request->input('contact_ids');
}
$campaign->update($input);
return $this->success($campaign);
}
public function destroyCampaign(Request $request, $id)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$campaign = Campaign::where('business_id', $business_id)->findOrFail($id);
$campaign->delete();
return $this->success(null, 'Deleted');
}
public function callLogs(Request $request)
{
$this->ensureCrm();
$user = Auth::user();
$business_id = $this->contextService->getBusinessId($request);
$query = CrmCallLog::where('crm_call_logs.business_id', $business_id)
->leftJoin('contacts as c', 'crm_call_logs.contact_id', '=', 'c.id')
->leftJoin('users as u', 'crm_call_logs.user_id', '=', 'u.id')
->select(
'crm_call_logs.*',
'c.name as customer_name',
'c.mobile as customer_mobile',
DB::raw("CONCAT(COALESCE(u.surname, ''), ' ', COALESCE(u.first_name, ''), ' ', COALESCE(u.last_name, '')) as user_full_name")
)
->orderByDesc('crm_call_logs.start_time');
if (! $user->can('crm.view_all_call_log') && $user->can('crm.view_own_call_log')) {
$query->where('crm_call_logs.created_by', $user->id);
}
return $this->paginated($query->paginate($request->input('per_page', 25)));
}
public function followUpLogs(Request $request)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$query = ScheduleLog::join('crm_schedules as s', 'crm_schedule_logs.schedule_id', '=', 's.id')
->leftJoin('contacts as c', 's.contact_id', '=', 'c.id')
->where('s.business_id', $business_id)
->select(
'crm_schedule_logs.*',
's.title as schedule_title',
'c.name as contact_name'
)
->orderByDesc('crm_schedule_logs.created_at');
return $this->paginated($query->paginate($request->input('per_page', 25)));
}
public function proposals(Request $request)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$query = Proposal::where('business_id', $business_id)->orderByDesc('created_at');
return $this->paginated($query->paginate($request->input('per_page', 25)));
}
public function showProposal(Request $request, $id)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$proposal = Proposal::with('media')->where('business_id', $business_id)->findOrFail($id);
return $this->success($proposal);
}
public function proposalTemplates(Request $request)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$items = ProposalTemplate::where('business_id', $business_id)
->orderByDesc('created_at')
->limit($request->input('per_page', 100))
->get();
return $this->success($items);
}
public function contactLogins(Request $request)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$query = User::with('contact')
->where('business_id', $business_id)
->whereNotNull('crm_contact_id')
->orderByDesc('created_at');
return $this->paginated($query->paginate($request->input('per_page', 25)));
}
public function commissions(Request $request)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$query = CrmContactPersonCommission::join('users as u', 'crm_contact_person_commissions.contact_person_id', '=', 'u.id')
->join('transactions as t', 'crm_contact_person_commissions.transaction_id', '=', 't.id')
->where('t.business_id', $business_id)
->select(
'crm_contact_person_commissions.*',
DB::raw("CONCAT(COALESCE(u.surname, ''), ' ', COALESCE(u.first_name, ''), ' ', COALESCE(u.last_name, '')) as contact_person_name"),
't.invoice_no',
't.transaction_date'
)
->orderByDesc('crm_contact_person_commissions.created_at');
return $this->paginated($query->paginate($request->input('per_page', 25)));
}
public function taxonomies(Request $request, string $type)
{
$this->ensureCrm();
$allowed = ['source', 'life_stage', 'followup_category'];
if (! in_array($type, $allowed)) {
return $this->error('Invalid taxonomy type', 404);
}
$business_id = $this->contextService->getBusinessId($request);
$items = Category::where('business_id', $business_id)
->where('category_type', $type)
->where('parent_id', 0)
->orderBy('name')
->get();
return $this->success($items);
}
public function reportFollowUpsByUser(Request $request)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$query = User::where('users.business_id', $business_id)
->where('is_cmmsn_agnt', 0)
->join('crm_schedule_users as su', 'su.user_id', '=', 'users.id')
->join('crm_schedules as follow_ups', 'follow_ups.id', '=', 'su.schedule_id')
->select(
DB::raw("CONCAT(COALESCE(users.surname, ''), ' ', COALESCE(users.first_name, ''), ' ', COALESCE(users.last_name, '')) as full_name"),
DB::raw('COUNT(su.id) as total_follow_ups'),
'users.id as user_id'
)
->groupBy('users.id');
if ($request->filled('start_date') && $request->filled('end_date')) {
$query->whereDate('follow_ups.start_datetime', '>=', $request->input('start_date'))
->whereDate('follow_ups.start_datetime', '<=', $request->input('end_date'));
}
return $this->success($query->get());
}
public function reportFollowUpsByContact(Request $request)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$query = Schedule::join('contacts as c', 'crm_schedules.contact_id', '=', 'c.id')
->where('crm_schedules.business_id', $business_id)
->select(
'c.id as contact_id',
'c.name as contact_name',
DB::raw('COUNT(crm_schedules.id) as total_follow_ups')
)
->groupBy('c.id', 'c.name');
if ($request->filled('start_date') && $request->filled('end_date')) {
$query->whereDate('crm_schedules.start_datetime', '>=', $request->input('start_date'))
->whereDate('crm_schedules.start_datetime', '<=', $request->input('end_date'));
}
return $this->success($query->get());
}
public function reportLeadToCustomer(Request $request)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$query = Contact::where('business_id', $business_id)
->where('type', 'customer')
->whereNotNull('converted_by')
->select('id', 'name', 'mobile', 'created_at', 'converted_by', 'converted_on')
->orderByDesc('converted_on');
return $this->success($query->limit(100)->get());
}
public function settings(Request $request)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
return $this->success($this->crmUtil->getCrmSettings($business_id));
}
public function updateSettings(Request $request)
{
$this->ensureCrm();
$business_id = $this->contextService->getBusinessId($request);
$input = $request->only(['order_request_prefix', 'enable_order_request']);
if ($request->has('enable_order_request')) {
$input['enable_order_request'] = 1;
} else {
$input['enable_order_request'] = 0;
}
Business::where('id', $business_id)->update(['crm_settings' => json_encode($input)]);
return $this->success($this->crmUtil->getCrmSettings($business_id));
}
}