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)); } }