Skip to content

Commit 9b33760

Browse files
Merge pull request #2001 from amit-webkul/magic-ai
✨ feat : Implementing the AI in krayin CRM.
2 parents 657593d + dadf3b0 commit 9b33760

File tree

22 files changed

+1083
-52
lines changed

22 files changed

+1083
-52
lines changed

composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"maatwebsite/excel": "^3.1",
2323
"mpdf/mpdf": "^8.2",
2424
"prettus/l5-repository": "^2.7.9",
25+
"smalot/pdfparser": "^2.11",
2526
"webklex/laravel-imap": "^5.3"
2627
},
2728
"require-dev": {

composer.lock

+54-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/Webkul/Admin/src/Config/core_config.php

+71
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,77 @@
2929
'options' => 'Webkul\Core\Core@locales',
3030
],
3131
],
32+
], [
33+
'key' => 'general.magic_ai',
34+
'name' => 'admin::app.configuration.index.magic-ai.title',
35+
'info' => 'admin::app.configuration.index.magic-ai.info',
36+
'icon' => 'icon-setting',
37+
'sort' => 3,
38+
], [
39+
'key' => 'general.magic_ai.settings',
40+
'name' => 'admin::app.configuration.index.magic-ai.settings.title',
41+
'info' => 'admin::app.configuration.index.magic-ai.settings.info',
42+
'sort' => 1,
43+
'fields' => [
44+
[
45+
'name' => 'enable',
46+
'title' => 'admin::app.configuration.index.magic-ai.settings.enable',
47+
'type' => 'boolean',
48+
'channel_based' => true,
49+
], [
50+
'name' => 'model',
51+
'title' => 'admin::app.configuration.index.magic-ai.settings.models.title',
52+
'type' => 'select',
53+
'channel_based' => true,
54+
'depends' => 'enable:1',
55+
'options' => [
56+
[
57+
'title' => 'admin::app.configuration.index.magic-ai.settings.models.gpt-4o',
58+
'value' => 'gpt-4o',
59+
], [
60+
'title' => 'admin::app.configuration.index.magic-ai.settings.models.gpt-4o-mini',
61+
'value' => 'gpt-4o-mini',
62+
], [
63+
'title' => 'admin::app.configuration.index.magic-ai.settings.models.gemini-flash',
64+
'value' => 'gemini-1.5-flash',
65+
], [
66+
'title' => 'admin::app.configuration.index.magic-ai.settings.models.deepseek-r1',
67+
'value' => 'deepseek-r1:8b',
68+
], [
69+
'title' => 'admin::app.configuration.index.magic-ai.settings.models.ollama',
70+
'value' => 'llama3.2:latest',
71+
], [
72+
'title' => 'admin::app.configuration.index.magic-ai.settings.models.llama',
73+
'value' => 'llama-3.3-70b-versatile',
74+
],
75+
],
76+
], [
77+
'name' => 'api_key',
78+
'title' => 'admin::app.configuration.index.magic-ai.settings.api-key',
79+
'type' => 'password',
80+
'depends' => 'enable:1,model:gpt-4o,model:gpt-4o-mini,model:gemini-1.5-flash,model:llama-3.3-70b-versatile',
81+
'validation' => 'required_if:enable,1',
82+
'info' => 'admin::app.configuration.index.magic-ai.settings.api-key-info',
83+
], [
84+
'name' => 'api_domain',
85+
'title' => 'admin::app.configuration.index.magic-ai.settings.api-domain',
86+
'type' => 'text',
87+
'info' => 'admin::app.configuration.index.magic-ai.settings.api-domain-info',
88+
'depends' => 'enable:1',
89+
],
90+
],
91+
], [
92+
'key' => 'general.magic_ai.pdf_generation',
93+
'name' => 'admin::app.configuration.index.magic-ai.settings.pdf-generation',
94+
'info' => 'admin::app.configuration.index.magic-ai.settings.pdf-generation-info',
95+
'sort' => 1,
96+
'fields' => [
97+
[
98+
'name' => 'enabled',
99+
'title' => 'admin::app.configuration.index.magic-ai.settings.enable',
100+
'type' => 'boolean',
101+
],
102+
],
32103
],
33104

34105
/**

packages/Webkul/Admin/src/Http/Controllers/Lead/LeadController.php

+69
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919
use Webkul\Attribute\Repositories\AttributeRepository;
2020
use Webkul\Contact\Repositories\PersonRepository;
2121
use Webkul\DataGrid\Enums\DateRangeOptionEnum;
22+
use Webkul\Lead\Helpers\Lead;
2223
use Webkul\Lead\Repositories\LeadRepository;
2324
use Webkul\Lead\Repositories\PipelineRepository;
2425
use Webkul\Lead\Repositories\ProductRepository;
2526
use Webkul\Lead\Repositories\SourceRepository;
2627
use Webkul\Lead\Repositories\StageRepository;
2728
use Webkul\Lead\Repositories\TypeRepository;
29+
use Webkul\Lead\Services\LeadService;
2830
use Webkul\Tag\Repositories\TagRepository;
2931
use Webkul\User\Repositories\UserRepository;
3032

@@ -44,6 +46,7 @@ public function __construct(
4446
protected StageRepository $stageRepository,
4547
protected LeadRepository $leadRepository,
4648
protected ProductRepository $productRepository,
49+
protected PersonRepository $personRepository
4750
) {
4851
request()->request->add(['entity_type' => 'leads']);
4952
}
@@ -625,4 +628,70 @@ private function getKanbanColumns(): array
625628
],
626629
];
627630
}
631+
632+
/**
633+
* Create Lead with specified AI.
634+
*/
635+
public function createByAI(LeadForm $request)
636+
{
637+
if (! $pdfFile = $request->file('file')) {
638+
return response()->json([
639+
'status' => 'error',
640+
'message' => trans('admin::app.leads.file.not-found'),
641+
], 400);
642+
}
643+
644+
$extractedData = LeadService::extractDataFromPdf($pdfFile->getPathName());
645+
646+
if (! empty($extractedData['error'])) {
647+
return response()->json([
648+
'status' => 'error',
649+
'message' => $extractedData['error'],
650+
], 400);
651+
}
652+
653+
$leadData = Lead::mapAIDataToLead($extractedData);
654+
655+
if (
656+
! empty($leadData['status'])
657+
&& $leadData['status'] === 'error'
658+
) {
659+
return response()->json([
660+
'status' => 'error',
661+
'message' => $leadData['message'],
662+
], 400);
663+
}
664+
665+
return self::leadCreate($leadData);
666+
}
667+
668+
/**
669+
* Create lead independent entity.
670+
*/
671+
private function leadCreate($data)
672+
{
673+
$person = $this->personRepository->create($data['person']);
674+
675+
$pipeline = $this->pipelineRepository->getDefaultPipeline();
676+
677+
$stage = $pipeline->stages()->first();
678+
679+
$data = array_merge($data, [
680+
'lead_pipeline_id' => $pipeline->id,
681+
'lead_pipeline_stage_id' => $stage->id,
682+
'expected_close_date' => Carbon::now()->addDays(7),
683+
'person' => [
684+
'id' => $person->id,
685+
'organization_id' => $data['person']['organization_id'] ?? null,
686+
],
687+
]);
688+
689+
$lead = $this->leadRepository->create($data);
690+
691+
Event::dispatch('lead.create.after', $lead);
692+
693+
return response()->json([
694+
'message' => trans('admin::app.leads.create-success'),
695+
], 200);
696+
}
628697
}

packages/Webkul/Admin/src/Resources/lang/ar/app.php

+54-12
Original file line numberDiff line numberDiff line change
@@ -1872,6 +1872,12 @@
18721872
'destroy-success' => 'تم حذف العميل المحتمل بنجاح.',
18731873
'destroy-failed' => 'لا يمكن حذف العميل المحتمل.',
18741874

1875+
'file' => [
1876+
'invalid-format' => 'تنسيق JSON غير صالح.',
1877+
'invalid-response' => 'تنسيق استجابة الذكاء الاصطناعي غير صالح.',
1878+
'not-found' => 'الملف غير موجود.',
1879+
],
1880+
18751881
'index' => [
18761882
'title' => 'العملاء المحتملون',
18771883
'create-btn' => 'إنشاء عميل محتمل',
@@ -1936,6 +1942,15 @@
19361942
'all-pipelines' => 'كل المسارات',
19371943
'create-new-pipeline' => 'إنشاء مسار جديد',
19381944
],
1945+
1946+
'upload' => [
1947+
'create-lead' => 'إنشاء عميل محتمل باستخدام الذكاء الاصطناعي',
1948+
'file' => 'تحميل ملف',
1949+
'file-info' => 'يتم قبول ملفات بصيغة PDF فقط.',
1950+
'save-btn' => 'حفظ',
1951+
'sample-pdf' => 'نموذج PDF',
1952+
'upload-pdf' => 'تحميل PDF',
1953+
],
19391954
],
19401955

19411956
'create' => [
@@ -2069,22 +2084,49 @@
20692084
],
20702085

20712086
'email' => [
2072-
'title' => 'Email Settings',
2073-
'info' => 'Email configuration for the application.',
2087+
'title' => 'إعدادات البريد الإلكتروني',
2088+
'info' => 'تكوين البريد الإلكتروني للتطبيق.',
20742089

20752090
'imap' => [
2076-
'title' => 'IMAP Settings',
2077-
'info' => 'IMAP email configuration for receiving emails.',
2091+
'title' => 'إعدادات IMAP',
2092+
'info' => 'تكوين البريد الإلكتروني IMAP لتلقي الرسائل.',
20782093

20792094
'account' => [
2080-
'title' => 'IMAP Account',
2081-
'title-info' => 'Configure your IMAP account settings here.',
2082-
'host' => 'Host',
2083-
'port' => 'Port',
2084-
'encryption' => 'Encryption Type',
2085-
'validate-cert' => 'Validate SSL Certificate',
2086-
'username' => 'IMAP Username',
2087-
'password' => 'IMAP Password',
2095+
'title' => 'حساب IMAP',
2096+
'title-info' => 'قم بتكوين إعدادات حساب IMAP هنا.',
2097+
'host' => 'المضيف',
2098+
'port' => 'المنفذ',
2099+
'encryption' => 'نوع التشفير',
2100+
'validate-cert' => 'التحقق من شهادة SSL',
2101+
'username' => 'اسم مستخدم IMAP',
2102+
'password' => 'كلمة مرور IMAP',
2103+
],
2104+
],
2105+
],
2106+
2107+
'magic-ai' => [
2108+
'title' => 'الذكاء الاصطناعي السحري',
2109+
'info' => 'تكوين الذكاء الاصطناعي السحري للتطبيق.',
2110+
2111+
'settings' => [
2112+
'api-domain' => 'نطاق API لـ LLM',
2113+
'api-domain-info' => 'لـ Olama و Grow فقط، مثال: http://localhost:11434',
2114+
'api-key' => 'مفتاح API',
2115+
'api-key-info' => 'يرجى التأكد من استخدام مفتاح API فريد لكل نوع نموذج للحفاظ على الأداء الأمثل والأمان.',
2116+
'enable' => 'تمكين',
2117+
'info' => 'عزز تجربتك مع ميزة الذكاء الاصطناعي السحري عن طريق إدخال مفتاح API الحصري الخاص بك وتوضيح التكامل السهل. استحوذ على التحكم في بيانات اعتماد OpenAI الخاصة بك وقم بتخصيص الإعدادات وفقًا لاحتياجاتك الخاصة.',
2118+
'pdf-generation' => 'توليد PDF',
2119+
'pdf-generation-info' => 'قم بتمكين ميزة توليد PDF لاستخراج البيانات تلقائيًا من ملفات PDF وتحويلها إلى تنسيق نصي. عزز إنتاجيتك وكفاءتك بتمكين هذه الميزة لتبسيط سير العمل الخاص بك.',
2120+
'title' => 'الإعدادات العامة',
2121+
2122+
'models' => [
2123+
'deepseek-r1' => 'DeepSeek-R1 8db',
2124+
'gemini-flash' => 'Gemini-1.5 Flash',
2125+
'gpt-4o' => 'GPT-4.0',
2126+
'gpt-4o-mini' => 'GPT-4.0 mini',
2127+
'llama' => 'Llama 3.3 (Groq)',
2128+
'ollama' => 'Ollama (llama3.2:latest)',
2129+
'title' => 'النماذج',
20882130
],
20892131
],
20902132
],

0 commit comments

Comments
 (0)