CRM integration MVP Phase 1

This commit is contained in:
Dillon
2023-02-17 06:28:59 +08:00
parent d0e6caed9f
commit 4d7b41b0a4
16 changed files with 257 additions and 70 deletions
@@ -0,0 +1,33 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMLeadProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
class CreatePerfexCRMCustomer implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var CreateLeadPerfexCRMObject */
private $createLeadPerfexCRMObject;
/**
* CreatePerfexCRMCustomer constructor.
* @param CreateLeadPerfexCRMObject $createLeadPerfexCRMObject
*/
public function __construct(CreateLeadPerfexCRMObject $createLeadPerfexCRMObject)
{
$this->createLeadPerfexCRMObject = $createLeadPerfexCRMObject;
}
public function handle()
{
(App()->make(CreatePerfexCRMLeadProcessor::class))->execute($this->createLeadPerfexCRMObject);
}
}
@@ -10,19 +10,22 @@ use App\Classes\Modules\Accounts\Processors\GenerateEmailVerificationAttemptProc
use App\Classes\Modules\Companies\Processors\AssignEmployeeProcessor;
use App\Classes\Modules\Companies\Processors\AssignSegmentProcessor;
use App\Classes\Modules\Companies\Processors\CreateCompanyProcessor;
use App\Classes\Modules\Companies\DataTransferObjects\EmploymentObject;
use App\Classes\Modules\Contacts\Processors\CreateContactProcessor;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMLeadProcessor;
use App\Classes\Modules\Companies\DataTransferObjects\EmploymentObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\BusinessType;
use App\Classes\ValueObjects\Constants\CompanyType;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Classes\Jobs\CreatePerfexCRMCustomer;
use App\Models\Company;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
class CreateCustomerLogic extends AbstractControllerLogic
{
@@ -108,10 +111,16 @@ class CreateCustomerLogic extends AbstractControllerLogic
$this->assignSegmentProcessor->execute($company);
$this->createPerfexCRMLeadProcessor->execute($request);
if(config('perfexcrm.is_enabled') == 'true'){
//$this->createPerfexCRMLeadProcessor->execute($request);
$createLeadPerfexCRMObject = new CreateLeadPerfexCRMObject(
$request->input('name'),
$request->input('email')
);
CreatePerfexCRMCustomer::dispatch($createLeadPerfexCRMObject);
}
//cief TODO: This line is intentionally commented because otherwise frontend cannot load/hit error
//$this->generateEmailVerificationAttemptProcessor->execute($user);
$this->generateEmailVerificationAttemptProcessor->execute($user);
return $this->response($this->authenticationProcessor->execute($request));
@@ -0,0 +1,40 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class CreateLeadPerfexCRMObject implements DataTransferObject
{
/** @var string */
private $name;
/** @var string */
private $email;
public function __construct(string $name, string $email)
{
$this->name = $name;
$this->email = $email;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @return string
*/
public function getEmail(): string
{
return $this->email;
}
}
@@ -13,6 +13,9 @@ class InitialPerfexCRMObject implements DataTransferObject
/** @var string */
private $companyReference;
/** @var string */
private $contactName;
/** @var string */
private $contactEmail;
@@ -29,11 +32,12 @@ class InitialPerfexCRMObject implements DataTransferObject
private $taskNames;
public function __construct(string $companyName, string $companyReference, string $contactEmail, string $bookingMarking, string $projectName, array $milestoneNames, array $taskNames)
public function __construct(string $companyName, string $companyReference, string $contactName, string $contactEmail, string $bookingMarking, string $projectName, array $milestoneNames, array $taskNames)
{
$this->companyName = $companyName;
$this->companyReference = $companyReference;
$this->contactName = $contactName;
$this->contactEmail = $contactEmail;
$this->bookingMarking = $bookingMarking;
$this->projectName = $projectName;
@@ -57,6 +61,14 @@ class InitialPerfexCRMObject implements DataTransferObject
return $this->companyReference;
}
/**
* @return string
*/
public function getContactName(): string
{
return $this->contactName;
}
/**
* @return string
*/
@@ -7,7 +7,7 @@ use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMLead;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Request;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
class CreatePerfexCRMLeadProcessor
{
@@ -25,12 +25,12 @@ class CreatePerfexCRMLeadProcessor
}
/**
* @param Request $request
* @param CreateLeadPerfexCRMObject $createLeadPerfexCRMObject
* @return null|object
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Request $request) {
return $this->createsPerfexCRMLead->execute($request->input('name'), $request->input('email'));
public function execute(CreateLeadPerfexCRMObject $createLeadPerfexCRMObject) {
return $this->createsPerfexCRMLead->execute($createLeadPerfexCRMObject->getName(), $createLeadPerfexCRMObject->getEmail());
}
}
@@ -11,12 +11,14 @@ use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMMilestone;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMTask;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomerContact;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CustomerContactObject;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InitialPerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMMilestones;
use App\Classes\ValueObjects\Constants\PerfexCRMTasks;
use App\Classes\ValueObjects\Constants\PerfexCRMStatus;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Request;
@@ -53,6 +55,9 @@ class InitializePerfexCRMProcessor
/** @var UpdatesPerfexCRM */
private $updatePerfexCRM;
/** @var UpdatesPerfexCRMCustomer */
private $updatesPerfexCRMCustomer;
/**
* @param ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer
* @param CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject
@@ -63,6 +68,7 @@ class InitializePerfexCRMProcessor
* @param FetchesPerfexCRMTask $fetchesPerfexCRMTask
* @param CreatesPerfexCRMCustomer $createsPerfexCRMCustomer
* @param CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact
* @param UpdatesPerfexCRMCustomer $updatesPerfexCRMCustomer
*/
public function __construct(ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer,
CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject,
@@ -72,7 +78,8 @@ class InitializePerfexCRMProcessor
FetchesPerfexCRMMilestone $fetchesPerfexCRMMilestone,
FetchesPerfexCRMTask $fetchesPerfexCRMTask,
CreatesPerfexCRMCustomer $createsPerfexCRMCustomer,
CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact)
CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact,
UpdatesPerfexCRMCustomer $updatesPerfexCRMCustomer)
{
$this->convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer;
$this->createsPerfexCRMCustomerProject = $createsPerfexCRMCustomerProject;
@@ -83,6 +90,7 @@ class InitializePerfexCRMProcessor
$this->fetchesPerfexCRMTask = $fetchesPerfexCRMTask;
$this->createsPerfexCRMCustomer = $createsPerfexCRMCustomer;
$this->createsPerfexCRMCustomerContact = $createsPerfexCRMCustomerContact;
$this->updatesPerfexCRMCustomer = $updatesPerfexCRMCustomer;
}
/**
@@ -94,28 +102,52 @@ class InitializePerfexCRMProcessor
// Customer has to exist first before Project can appear under it
// Check with Perfex CRM, if this user (email) was previously a lead, should automatically now become a customer
$crmCompany = $initialPerfexCRMObject->getCompanyName();
$result = $this->convertsPerfexCRMLeadToCustomer->execute($initialPerfexCRMObject->getContactEmail());
if(isset($result->payload)){
$crmClientId = $result->payload['client_id'];
$crmClientId = $result->payload['client_id'];
if (isset($result->payload['company'])) {
$crmCompany = $result->payload['company'];
}
}
else{
//if reach this point, this means this user is not a official customer nor is a lead in crm
//Create Customer has 2 parts: Create Company (client), Create Contact
$result = $this->createsPerfexCRMCustomer->execute($initialPerfexCRMObject->getCompanyName());
$result = $this->createsPerfexCRMCustomer->execute($crmCompany);
if(is_null($result)){
$crmCompany = $crmCompany." 2";
$result = $this->createsPerfexCRMCustomer->execute($crmCompany);
}
$crmClientId = $result->payload['clientId'];
$customerContactObject = new CustomerContactObject(
$crmClientId,
$initialPerfexCRMObject->getCompanyName(),
$initialPerfexCRMObject->getCompanyName(),
$initialPerfexCRMObject->getContactName(),
$initialPerfexCRMObject->getContactName(),
$initialPerfexCRMObject->getContactEmail(),
"123456abcabc",
"pU^T@sC#9Q",
"on",
"on"
);
$result = $this->createsPerfexCRMCustomerContact->execute($customerContactObject);
}
//Update custom fields to identify company reference from exchange or shipping portal
$value_exists = false;
if (isset($result->payload['customfields'])) {
foreach ($result->payload['customfields'] as $element) {
if ($element['value'] === $initialPerfexCRMObject->getCompanyReference()) {
$value_exists = true;
break;
}
}
}
if(!$value_exists);
{
$result = $this->updatesPerfexCRMCustomer->execute($crmClientId, $crmCompany, $initialPerfexCRMObject->getCompanyReference());
}
// Get existing or create project, project has to exist first before milestone can appear under it
$result = $this->createsPerfexCRMCustomerProject->execute($initialPerfexCRMObject->getProjectName(), $crmClientId);
if(isset($result->payload)){ //Here means project creation successful
@@ -145,8 +177,13 @@ class InitializePerfexCRMProcessor
}
}
$taskStatus = PerfexCRMStatus::NOT_STARTED;
if($tasks[$count]['name'] == PerfexCRMTasks::TASK_1['name']){
$taskStatus = PerfexCRMStatus::COMPLETED;
}
// Get existing or create task
$result = $this->createsPerfexCRMTask->execute($tasks[$count]['name'], $milestoneId, $projectId, $tasks[$count]['reference']);
$result = $this->createsPerfexCRMTask->execute($tasks[$count]['name'], $milestoneId, $projectId, $tasks[$count]['reference'], $taskStatus);
}
}
return true;
@@ -49,59 +49,62 @@ class TransactionToPerfexCRMProcessor
*/
public function execute(Transaction $model, int $status)
{
$companyName = "dillon37"; //cief TODO: To be updated by removing this line to user actual company name
if(!is_null($model->owner->company)){
$proceed = false;
if($model->owner instanceof \App\Models\Booking){
//For owner_type > App\Models\Booking
$companyReference = $model->owner->company->reference;
$companyName = $model->owner->company->name;
$employee = $model->owner->company->employees()->first();
$contactEmail = $employee->email;
$contactName = $employee->name;
$proceed = true;
}
else{
else if($model->owner instanceof \App\Models\Wallet){
//For owner_type > App\Models\Wallet
$companyReference = $model->owner->owner->reference;
$companyName = $model->owner->company->name;
$company = $this->fetchesCompany->execute(['id' => $model->owner->owner->id]);
$email = $company->employees()->first()->email;
$employee = $company->employees()->first();
$contactEmail = $employee->email;
$contactName = $employee->name;
$proceed = true;
}
$contactEmail = "dillon37@yahoo.com"; //cief TODO: To be updated to user actual email address
$bookingMarking = $model->owner->marking;
if($model->owner instanceof \App\Models\Booking && $model->payment_reference != null && $status == ApprovalStatus::APPROVED){
if($proceed && $model->owner instanceof \App\Models\Booking && $model->payment_reference != null && $status == ApprovalStatus::APPROVED){
$initialPerfexCRMObject = new InitialPerfexCRMObject(
$companyName,
$companyReference,
$contactName,
$contactEmail,
$bookingMarking,
$companyReference.'-'.$bookingMarking,
[],
[
PerfexCRMTasks::TASK_1,
PerfexCRMTasks::TASK_2,
PerfexCRMTasks::TASK_3,
PerfexCRMTasks::TASK_4,
PerfexCRMTasks::TASK_5,
PerfexCRMTasks::TASK_6,
PerfexCRMTasks::TASK_7,
PerfexCRMTasks::TASK_8,
PerfexCRMTasks::TASK_9,
PerfexCRMTasks::TASK_10,
]
);
//$this->initializePerfexCRMProcessor->execute($initialPerfexCRMObject);
InitializePerfexCRM::dispatch($initialPerfexCRMObject);
$updatePerfexCRMObject = new UpdatePerfexCRMObject(
$companyName,
$companyReference,
$contactEmail,
$bookingMarking,
$companyReference.'-'.$bookingMarking,
PerfexCRMTasks::TASK_1['milestone'],
PerfexCRMTasks::TASK_1['name']
);
// $updatePerfexCRMObject = new UpdatePerfexCRMObject(
// $companyName,
// $companyReference,
// $contactEmail,
// $bookingMarking,
// $companyReference.'-'.$bookingMarking,
// PerfexCRMTasks::TASK_1['milestone'],
// PerfexCRMTasks::TASK_1['name']
// );
//Mark task in Perfex CRM as done (5 means completed task)
// $this->updatePerfexCRMProcessor->execute($updatePerfexCRMObject);
UpdatePerfexCRM::dispatch($updatePerfexCRMObject);
// //Mark task in Perfex CRM as done (5 means completed task)
// // $this->updatePerfexCRMProcessor->execute($updatePerfexCRMObject);
// UpdatePerfexCRM::dispatch($updatePerfexCRMObject);
}
/*
else if($model->owner instanceof \App\Models\Booking && $status == ApprovalStatus::APPROVED){
$updatePerfexCRMObject = new UpdatePerfexCRMObject(
@@ -134,6 +137,7 @@ class TransactionToPerfexCRMProcessor
//$this->updatePerfexCRMProcessor->execute($updatePerfexCRMObject);
UpdatePerfexCRM::dispatch($updatePerfexCRMObject);
}
*/
return true;
}
@@ -15,6 +15,7 @@ use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMTask;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CustomerContactObject;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMStatus;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Request;
@@ -100,23 +101,6 @@ class UpdatePerfexCRMProcessor
if(isset($result->payload)){
$crmClientId = $result->payload['client_id'];
}
else{
//if reach this point, this means this user is not a official customer nor is a lead in crm
//Create Customer has 2 parts: Create Company (client), Create Contact
$result = $this->createsPerfexCRMCustomer->execute($updatePerfexCRMObject->getCompanyName());
$crmClientId = $result->payload['clientId'];
$customerContactObject = new CustomerContactObject(
$crmClientId,
$updatePerfexCRMObject->getCompanyName(),
$updatePerfexCRMObject->getCompanyName(),
$updatePerfexCRMObject->getContactEmail(),
"123456abcabc",
"on",
"on"
);
$result = $this->createsPerfexCRMCustomerContact->execute($customerContactObject);
}
// Get existing or create project, project has to exist first before milestone can appear under it
$result = $this->createsPerfexCRMCustomerProject->execute($updatePerfexCRMObject->getProjectName(), $crmClientId);
@@ -147,8 +131,7 @@ class UpdatePerfexCRMProcessor
$taskId = $this->fetchesPerfexCRMTask->execute($updatePerfexCRMObject->getTaskName(), $milestoneId)->id;
}
//cief TODO: To update task status dynamically, now is hardcoded 5 (5 means completed task)
$this->updatesPerfexCRMTask->execute($taskId, $updatePerfexCRMObject->getTaskName(), $milestoneId, $projectId, 5);
$this->updatesPerfexCRMTask->execute($taskId, $updatePerfexCRMObject->getTaskName(), $milestoneId, $projectId, PerfexCRMStatus::COMPLETED);
return null;
}
@@ -23,7 +23,7 @@ class CreatesPerfexCRMCustomerContact
'email' => $customerContactObject->getEmail(), //$email
'password' => $customerContactObject->getPassword(),
'is_primary' => $customerContactObject->getIsPrimary(),
'send_set_password_email' => $customerContactObject->getSendSetPasswordEmail(),
//'send_set_password_email' => $customerContactObject->getSendSetPasswordEmail(),
];
$response = Http::asForm()->withHeaders([
@@ -19,8 +19,8 @@ class CreatesPerfexCRMLead
$data = [
'name' => $name,
'email' => $email,
'source' => 3,
'status' => 2
'source' => 1, //1: Exchange, 2: Shipping Portal
'status' => 2 //2: Lead, 1: Customer
];
$response = Http::asForm()->withHeaders([
@@ -0,0 +1,46 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class UpdatesPerfexCRMCustomer
{
/**
* @param string $customerId
* @param string $companyReference
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $customerId, string $companyName, string $companyReference) {
try{
$custom_fields = [
"customers" => [
1 => $companyReference
]
];
$data = [
'company' => $companyName,
'custom_fields' => $custom_fields
];
$response = Http::asJson()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->put(config('perfexcrm.base_url').'/api/customers/'.$customerId, $data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -205,7 +205,10 @@ class CreateInvoiceTransactionProcessor
$this->invoiceDocumentProcessor->execute($supplier_deliver_order_transaction, $purchaseOrder, $supplier, DocumentType::SUPPLIER_DELIVER_ORDER);
// update perfex crm
$this->createPerfexCRMInvoiceProcessor->execute($invoice_transaction, $purchaseOrder, $supplier);
// if(config('perfexcrm.is_enabled') == 'true'){
// {
// $this->createPerfexCRMInvoiceProcessor->execute($invoice_transaction, $purchaseOrder, $supplier);
// }
$this->updatesBookingStatus->execute($booking, ApprovalStatus::COMPLETED);
}
@@ -28,7 +28,9 @@ class UpdatesTransactionStatus extends AbstractUpdateRecord
*/
public function execute(Transaction $model, int $status)
{
$this->transactionToPerfexCRMProcessor->execute($model, $status);
if(config('perfexcrm.is_enabled') == 'true'){
$this->transactionToPerfexCRMProcessor->execute($model, $status);
}
$model->status = $status;
return $this->handler($model);
}
@@ -0,0 +1,17 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class PerfexCRMStatus {
public const NOT_STARTED = 1;
public const AWAITING_FEEDBACK = 2;
public const TESTING = 3;
public const IN_PROGRESS = 4;
public const COMPLETED = 5;
}
@@ -5,7 +5,7 @@ namespace App\Classes\ValueObjects\Constants;
class PerfexCRMTasks
{
public const TASK_1 = [
'name' => 'TASK A',
'name' => 'Customer Paid',
'milestone' => 'MILESTONE 1 - Customer Paid',
'reference' => ''
];
+3 -2
View File
@@ -1,6 +1,7 @@
<?php
return [
'base_url' => env('PERFEXCRM_BASE_URL', 'http://192.168.1.102:8084'), //cief todo: Update crm api domain here
'api_key' => env('PERFEXCRM_API_KEY', 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiZGlsbG9uIiwibmFtZSI6ImRldmVsb3BtZW50IiwiQVBJX1RJTUUiOjE2NzAwNjM0OTB9.ClR07m_QvvOHe4-hsTFAyXLvLCkXcym3cQpq0V8PHLo'),
'base_url' => env('PERFEXCRM_BASE_URL', 'http://192.168.1.100:8084'), //cief todo: Update crm api domain here
'api_key' => env('PERFEXCRM_API_KEY', 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiZXhjaGFuZ2Utc2hpcHBpbmciLCJuYW1lIjoiRXhjaGFuZ2UgYW5kIFNoaXBwaW5nIFBvcnRhbCIsIkFQSV9USU1FIjoxNjc1MDg2Mzc4fQ.SGAHWl5stcxQwp55TBGeMRVTdlLeWQIbsvJh5glyVvs'),
'is_enabled' => env('PERFEXCRM_IS_ENABLED', 'true'),
];