diff --git a/.gitignore b/.gitignore index 476bf6a0..095342e0 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,6 @@ gox.iml rebuild_docker.sh docker/* db/* -docker-compose.yml package-lock.json public/* /public/* diff --git a/app/Classes/Jobs/CreatePerfexCRMCustomer.php b/app/Classes/Jobs/CreatePerfexCRMCustomer.php new file mode 100644 index 00000000..4d7acddd --- /dev/null +++ b/app/Classes/Jobs/CreatePerfexCRMCustomer.php @@ -0,0 +1,41 @@ +createLeadPerfexCRMObject = $createLeadPerfexCRMObject; + } + + public function handle() + { + $lead = (App()->make(FetchesPerfexCRMLead::class))->execute($this->createLeadPerfexCRMObject->getEmail()); + if(!is_null($lead)){ + (App()->make(UpdatesPerfexCRMLead::class))->execute($lead, $this->createLeadPerfexCRMObject->getCompanyReference()); + } + else{ + (App()->make(CreatePerfexCRMLeadProcessor::class))->execute($this->createLeadPerfexCRMObject); + } + } +} diff --git a/app/Classes/Jobs/CreatePerfexCRMInvoice.php b/app/Classes/Jobs/CreatePerfexCRMInvoice.php new file mode 100644 index 00000000..a6905be4 --- /dev/null +++ b/app/Classes/Jobs/CreatePerfexCRMInvoice.php @@ -0,0 +1,42 @@ +transaction = $transaction; + $this->purchaseOrder = $purchaseOrder; + $this->supplier = $supplier; + } + + public function handle() + { + (App()->make(CreatePerfexCRMInvoiceProcessor::class))->execute($this->transaction, $this->purchaseOrder, $this->supplier); + } +} diff --git a/app/Classes/Jobs/CreatePerfexCRMSingleTask.php b/app/Classes/Jobs/CreatePerfexCRMSingleTask.php new file mode 100644 index 00000000..586efe0f --- /dev/null +++ b/app/Classes/Jobs/CreatePerfexCRMSingleTask.php @@ -0,0 +1,42 @@ +createTaskPerfexCRMObject = $createTaskPerfexCRMObject; + } + + public function handle() + { + $lead = (App()->make(FetchesPerfexCRMLead::class))->execute($this->createTaskPerfexCRMObject->getEmail()); + if(!is_null($lead)) + { + $this->createTaskPerfexCRMObject->setLeadId($lead->id); + (App()->make(CreatePerfexCRMTaskProcessor::class))->execute($this->createTaskPerfexCRMObject); + } + } +} diff --git a/app/Classes/Jobs/InitializePerfexCRM.php b/app/Classes/Jobs/InitializePerfexCRM.php new file mode 100644 index 00000000..ac77f87e --- /dev/null +++ b/app/Classes/Jobs/InitializePerfexCRM.php @@ -0,0 +1,33 @@ +initialPerfexCRMObject = $initialPerfexCRMObject; + } + + public function handle() + { + (App()->make(InitializePerfexCRMProcessor::class))->execute($this->initialPerfexCRMObject); + } +} diff --git a/app/Classes/Jobs/UpdatePerfexCRM.php b/app/Classes/Jobs/UpdatePerfexCRM.php new file mode 100644 index 00000000..cbc686e3 --- /dev/null +++ b/app/Classes/Jobs/UpdatePerfexCRM.php @@ -0,0 +1,33 @@ +updatePerfexCRMObject = $updatePerfexCRMObject; + } + + public function handle() + { + (App()->make(UpdatePerfexCRMProcessor::class))->execute($this->updatePerfexCRMObject); + } +} diff --git a/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php b/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php index 2c732126..0e920fe9 100644 --- a/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php +++ b/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php @@ -10,18 +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 { @@ -56,6 +60,9 @@ class CreateCustomerLogic extends AbstractControllerLogic /** @var GenerateEmailVerificationAttemptProcessor */ private $generateEmailVerificationAttemptProcessor; + /** @var CreatePerfexCRMLeadProcessor */ + private $createPerfexCRMLeadProcessor; + /** * CreateCustomerLogic constructor. * @param CreateUserProcessor $createUserProcessor @@ -65,8 +72,10 @@ class CreateCustomerLogic extends AbstractControllerLogic * @param AssignSegmentProcessor $assignSegmentProcessor * @param AuthenticationProcessor $authenticationProcessor * @param GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor + * @param CreatePerfexCRMLeadProcessor $createPerfexCRMLeadProcessor */ - public function __construct(CreateUserProcessor $createUserProcessor, CreateCompanyProcessor $createCompanyProcessor, CreateContactProcessor $createContactProcessor, AssignEmployeeProcessor $assignEmployeeProcessor, AssignSegmentProcessor $assignSegmentProcessor, AuthenticationProcessor $authenticationProcessor, GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor) + public function __construct(CreateUserProcessor $createUserProcessor, CreateCompanyProcessor $createCompanyProcessor, CreateContactProcessor $createContactProcessor, AssignEmployeeProcessor $assignEmployeeProcessor, AssignSegmentProcessor $assignSegmentProcessor, AuthenticationProcessor $authenticationProcessor, GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor, + CreatePerfexCRMLeadProcessor $createPerfexCRMLeadProcessor) { $this->createUserProcessor = $createUserProcessor; $this->createCompanyProcessor = $createCompanyProcessor; @@ -75,6 +84,7 @@ class CreateCustomerLogic extends AbstractControllerLogic $this->assignSegmentProcessor = $assignSegmentProcessor; $this->authenticationProcessor = $authenticationProcessor; $this->generateEmailVerificationAttemptProcessor = $generateEmailVerificationAttemptProcessor; + $this->createPerfexCRMLeadProcessor = $createPerfexCRMLeadProcessor; } /** @@ -101,9 +111,21 @@ class CreateCustomerLogic extends AbstractControllerLogic $this->assignSegmentProcessor->execute($company); - $this->generateEmailVerificationAttemptProcessor->execute($user); + if(config('perfexcrm.is_enabled') == 'true'){ + //$this->createPerfexCRMLeadProcessor->execute($request); + $createLeadPerfexCRMObject = new CreateLeadPerfexCRMObject( + $request->input('name'), + $request->input('email'), + $request->input('phone'), + $request->input('type') === CompanyType::COMPANY_BUSINESS ? $request->input('company_name') : $request->input('name'), + $company->reference + ); + CreatePerfexCRMCustomer::dispatch($createLeadPerfexCRMObject); + } + + $this->generateEmailVerificationAttemptProcessor->execute($user); return $this->response($this->authenticationProcessor->execute($request)); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php b/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php index f32ea123..a6c0b7fd 100644 --- a/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php +++ b/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php @@ -107,9 +107,9 @@ class CallbackBillplzLogic $token = Auth::fromUser(User::find(1)); $request->headers->set('Authorization', 'Bearer '.$token); - $marking = $transaction->owner instanceof Booking ? $transaction->booking->marking : $transaction->owner->owner->bookings()->orderBy('id', 'DESC')->first()->marking; + $marking = $transaction->owner instanceof Booking ? $transaction->booking->marking : (count($transaction->owner->owner->bookings()->get())? $transaction->owner->owner->bookings()->orderBy('id', 'DESC')->first()->marking: null); - return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $marking, 'transaction' => $transaction, 'status' => $status]); + return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $marking ?? null, 'transaction' => $transaction, 'status' => $status]); } } \ No newline at end of file diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingLogic.php index e4fa3666..0fbf2519 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingLogic.php @@ -13,6 +13,8 @@ use App\Classes\Modules\Bookings\Services\CreatesBooking; use App\Classes\Modules\Bookings\Services\GeneratesBookingMarking; use App\Classes\Modules\Bookings\DataTransferObjects\BookingObject; +use App\Classes\Modules\PerfexCRM\Processors\BookingToPerfexCRMProcessor; + use App\Http\Resources\BookingResource; use ErrorException; @@ -44,19 +46,24 @@ class CreateBookingLogic extends AbstractControllerLogic /** @var FetchesCompany */ private $fetchesCompany; + /** @var BookingToPerfexCRMProcessor */ + private $bookingToPerfexCRMProcessor; + /** * CreateBookingLogic constructor. * @param CanCreateBooking $canCreateBooking * @param CreatesBooking $createsBooking * @param GeneratesBookingMarking $generatesBookingMarking * @param FetchesCompany $fetchesCompany + * @param BookingToPerfexCRMProcessor $bookingToPerfexCRMProcessor */ - public function __construct(CanCreateBooking $canCreateBooking, CreatesBooking $createsBooking, GeneratesBookingMarking $generatesBookingMarking, FetchesCompany $fetchesCompany) + public function __construct(CanCreateBooking $canCreateBooking, CreatesBooking $createsBooking, GeneratesBookingMarking $generatesBookingMarking, FetchesCompany $fetchesCompany, BookingToPerfexCRMProcessor $bookingToPerfexCRMProcessor) { $this->canCreateBooking = $canCreateBooking; $this->createsBooking = $createsBooking; $this->generatesBookingMarking = $generatesBookingMarking; $this->fetchesCompany = $fetchesCompany; + $this->bookingToPerfexCRMProcessor = $bookingToPerfexCRMProcessor; } @@ -77,7 +84,11 @@ class CreateBookingLogic extends AbstractControllerLogic $booking = $this->createsBooking->execute($company, $object); + if(config('perfexcrm.is_enabled') == 'true'){ + $this->bookingToPerfexCRMProcessor->execute($booking); + } + return $this->resourceResponse(new BookingResource($booking)); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Companies/ControllersLogic/CreateIdentificationDocumentLogic.php b/app/Classes/Modules/Companies/ControllersLogic/CreateIdentificationDocumentLogic.php index bbf91ea7..c08dc4ef 100644 --- a/app/Classes/Modules/Companies/ControllersLogic/CreateIdentificationDocumentLogic.php +++ b/app/Classes/Modules/Companies/ControllersLogic/CreateIdentificationDocumentLogic.php @@ -9,6 +9,7 @@ use App\Classes\Modules\Companies\Services\UpdatesCompanyStatus; use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject; use App\Classes\Modules\Documents\Services\CreatesDocument; use App\Classes\Modules\Documents\Services\CreatesFiles; +use App\Classes\Modules\PerfexCRM\Processors\NewLeadTaskToPerfexCRMProcessor; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\CompanyType; use App\Classes\ValueObjects\Constants\DocumentType; @@ -42,6 +43,8 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic /** @var UpdatesCompanyStatus */ private $updatesCompanyStatus; + /** @var NewLeadTaskToPerfexCRMProcessor */ + private $newLeadTaskToPerfexCRMProcessor; /** * CreateIdentificationDocumentLogic constructor. @@ -49,13 +52,15 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic * @param CreatesDocument $createsDocument * @param CreatesFiles $createsFile * @param UpdatesCompanyStatus $updatesCompanyStatus + * @param NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor */ - public function __construct(FetchesCompany $fetchesCompany, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesCompanyStatus $updatesCompanyStatus) + public function __construct(FetchesCompany $fetchesCompany, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesCompanyStatus $updatesCompanyStatus, NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor) { $this->fetchesCompany = $fetchesCompany; $this->createsDocument = $createsDocument; $this->createsFile = $createsFile; $this->updatesCompanyStatus = $updatesCompanyStatus; + $this->newLeadTaskToPerfexCRMProcessor = $newLeadTaskToPerfexCRMProcessor; } /** @@ -78,7 +83,11 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic $this->updatesCompanyStatus->execute($company, ApprovalStatus::PENDING_VERIFICATION); + if(config('perfexcrm.is_enabled') == 'true'){ + $this->newLeadTaskToPerfexCRMProcessor->execute($company); + } + return $this->response([]); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/PerfexCRM/DataTransferObjects/CreateLeadPerfexCRMObject.php b/app/Classes/Modules/PerfexCRM/DataTransferObjects/CreateLeadPerfexCRMObject.php new file mode 100644 index 00000000..bea178f5 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/DataTransferObjects/CreateLeadPerfexCRMObject.php @@ -0,0 +1,74 @@ +name = $name; + $this->email = $email; + $this->phone = $phone; + $this->companyName = $companyName; + $this->companyReference = $companyReference; + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @return string + */ + public function getEmail(): string + { + return $this->email; + } + + /** + * @return string + */ + public function getPhone(): string + { + return $this->phone; + } + + /** + * @return string + */ + public function getCompanyName(): string + { + return $this->companyName; + } + + /** + * @return string + */ + public function getCompanyReference(): string + { + return $this->companyReference; + } +} diff --git a/app/Classes/Modules/PerfexCRM/DataTransferObjects/CreateTaskPerfexCRMObject.php b/app/Classes/Modules/PerfexCRM/DataTransferObjects/CreateTaskPerfexCRMObject.php new file mode 100644 index 00000000..70bae013 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/DataTransferObjects/CreateTaskPerfexCRMObject.php @@ -0,0 +1,127 @@ +email = $email; + $this->name = $name; + $this->description = $description; + $this->leadId = $leadId; + $this->projectId = $projectId; + $this->milestoneId = $milestoneId; + $this->reference = $reference; + $this->onTaskCompletion = $onTaskCompletion; + $this->status = $status; + } + + /** + * @return string + */ + public function getEmail(): string + { + return $this->email; + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @return string + */ + public function getDescription(): string + { + return $this->description; + } + + /** + * @return string + */ + public function getLeadId(): string + { + return $this->leadId; + } + + public function setLeadId(string $leadId) + { + $this->leadId = $leadId; + } + + /** + * @return string + */ + public function getProjectId(): string + { + return $this->projectId; + } + + /** + * @return string + */ + public function getMilestoneId(): string + { + return $this->milestoneId; + } + + /** + * @return string + */ + public function getReference(): string + { + return $this->reference; + } + + /** + * @return string + */ + public function getOnTaskCompletion(): string + { + return $this->onTaskCompletion; + } + + /** + * @return string + */ + public function getStatus(): string + { + return $this->status; + } + +} diff --git a/app/Classes/Modules/PerfexCRM/DataTransferObjects/CustomerContactObject.php b/app/Classes/Modules/PerfexCRM/DataTransferObjects/CustomerContactObject.php new file mode 100644 index 00000000..3530524d --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/DataTransferObjects/CustomerContactObject.php @@ -0,0 +1,99 @@ +customerId = $customerId; + $this->firstname = $firstname; + $this->lastname = $lastname; + $this->email = $email; + $this->password = $password; + $this->isPrimary = $isPrimary; + $this->sendSetPasswordEmail = $sendSetPasswordEmail; + } + + /** + * @return int + */ + public function getCustomerId(): int + { + return $this->customerId; + } + + /** + * @return string + */ + public function getFirstName(): string + { + return $this->firstname; + } + + /** + * @return string + */ + public function getLastName(): string + { + return $this->lastname; + } + + /** + * @return string + */ + public function getEmail(): string + { + return $this->email; + } + + /** + * @return string + */ + public function getPassword(): string + { + return $this->password; + } + + /** + * @return string + */ + public function getIsPrimary(): string + { + return $this->isPrimary; + } + + /** + * @return string + */ + public function getSendSetPasswordEmail(): string + { + return $this->sendSetPasswordEmail; + } +} diff --git a/app/Classes/Modules/PerfexCRM/DataTransferObjects/InitialPerfexCRMObject.php b/app/Classes/Modules/PerfexCRM/DataTransferObjects/InitialPerfexCRMObject.php new file mode 100644 index 00000000..66c2c86c --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/DataTransferObjects/InitialPerfexCRMObject.php @@ -0,0 +1,124 @@ +companyName = $companyName; + $this->companyReference = $companyReference; + $this->contactName = $contactName; + $this->contactEmail = $contactEmail; + $this->bookingMarking = $bookingMarking; + $this->projectName = $projectName; + $this->projectStatus = $projectStatus; + $this->milestoneNames = $milestoneNames; + $this->taskNames = $taskNames; + } + + /** + * @return string + */ + public function getCompanyName(): string + { + return $this->companyName; + } + + /** + * @return string + */ + public function getCompanyReference(): string + { + return $this->companyReference; + } + + /** + * @return string + */ + public function getContactName(): string + { + return $this->contactName; + } + + /** + * @return string + */ + public function getContactEmail(): string + { + return $this->contactEmail; + } + + /** + * @return string + */ + public function getBookingMarking(): string + { + return $this->bookingMarking; + } + + /** + * @return string + */ + public function getProjectName(): string + { + return $this->projectName; + } + + /** + * @return string + */ + public function getProjectStatus(): int + { + return $this->projectStatus; + } + + /** + * @return array + */ + public function getMilestoneNames(): array + { + return $this->milestoneNames; + } + + /** + * @return array + */ + public function getTaskNames(): array + { + return $this->taskNames; + } + +} diff --git a/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoicePaymentPerfexCRMObject.php b/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoicePaymentPerfexCRMObject.php new file mode 100644 index 00000000..3d34c540 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoicePaymentPerfexCRMObject.php @@ -0,0 +1,86 @@ +invoiceId = $invoiceId; + $this->amount = $amount; + $this->date = $date; + $this->paymentMode = $paymentMode; + $this->transactionId = $transactionId; + $this->note = $note; + } + + /** + * @return int + */ + public function getInvoiceId(): int + { + return $this->invoiceId; + } + + /** + * @return float + */ + public function getAmount(): float + { + return $this->amount; + } + + /** + * @return string + */ + public function getDate(): string + { + return $this->date; + } + + /** + * @return int + */ + public function getPaymentMode(): int + { + return $this->paymentMode; + } + + /** + * @return string + */ + public function getTransactionId(): string + { + return $this->transactionId; + } + + /** + * @return string + */ + public function getNote(): string + { + return $this->note; + } +} diff --git a/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoicePerfexCRMObject.php b/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoicePerfexCRMObject.php new file mode 100644 index 00000000..f1f21f11 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoicePerfexCRMObject.php @@ -0,0 +1,145 @@ +clientId = $clientId; + $this->number = $number; + $this->date = $date; + $this->dueDate = $dueDate; + $this->currency = $currency; + $this->subTotal = $subTotal; + $this->total = $total; + $this->billingStreet = $billingStreet; + $this->projectId = $projectId; + $this->allowedPaymentModes = $allowedPaymentModes; + $this->invoiceItems = $invoiceItems; + } + + /** + * @return string + */ + public function getClientId(): string + { + return $this->clientId; + } + + /** + * @return string + */ + public function getNumber(): string + { + return $this->number; + } + + /** + * @return string + */ + public function getDate(): string + { + return $this->date; + } + + /** + * @return string + */ + public function getDueDate(): string + { + return $this->dueDate; + } + + /** + * @return string + */ + public function getCurrency(): string + { + return $this->currency; + } + + /** + * @return float + */ + public function getSubTotal(): float + { + return $this->subTotal; + } + + /** + * @return float + */ + public function getTotal(): float + { + return $this->total; + } + + /** + * @return string + */ + public function getBillingStreet(): string + { + return $this->billingStreet; + } + + /** + * @return string + */ + public function getProjectId(): string + { + return $this->projectId; + } + + /** + * @return array + */ + public function getAllowedPaymentModes(): array + { + return $this->allowedPaymentModes; + } + + /** + * @return array + */ + public function getInvoiceItems(): array + { + return $this->invoiceItems; + } +} diff --git a/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoiceSingleItemPerfexCRMObject.php b/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoiceSingleItemPerfexCRMObject.php new file mode 100644 index 00000000..7b9428db --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoiceSingleItemPerfexCRMObject.php @@ -0,0 +1,86 @@ +description = $description; + $this->longDescription = $longDescription; + $this->qty = $qty; + $this->rate = $rate; + $this->order = $order; + $this->unit = $unit; + } + + /** + * @return string + */ + public function getDescription(): string + { + return $this->description; + } + + /** + * @return string + */ + public function getLongDescription(): string + { + return $this->longDescription; + } + + /** + * @return float + */ + public function getQty(): float + { + return $this->qty; + } + + /** + * @return float + */ + public function getRate(): float + { + return $this->rate; + } + + /** + * @return int + */ + public function getOrder(): int + { + return $this->order; + } + + /** + * @return string + */ + public function getUnit(): string + { + return $this->unit; + } +} diff --git a/app/Classes/Modules/PerfexCRM/DataTransferObjects/UpdatePerfexCRMObject.php b/app/Classes/Modules/PerfexCRM/DataTransferObjects/UpdatePerfexCRMObject.php new file mode 100644 index 00000000..a246d25a --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/DataTransferObjects/UpdatePerfexCRMObject.php @@ -0,0 +1,124 @@ +companyName = $companyName; + $this->companyReference = $companyReference; + $this->contactName = $contactName; + $this->contactEmail = $contactEmail; + $this->bookingMarking = $bookingMarking; + $this->projectName = $projectName; + $this->projectStatus = $projectStatus; + $this->milestoneNames = $milestoneNames; + $this->taskNames = $taskNames; + } + + /** + * @return string + */ + public function getCompanyName(): string + { + return $this->companyName; + } + + /** + * @return string + */ + public function getCompanyReference(): string + { + return $this->companyReference; + } + + /** + * @return string + */ + public function getContactName(): string + { + return $this->contactName; + } + + /** + * @return string + */ + public function getContactEmail(): string + { + return $this->contactEmail; + } + + /** + * @return string + */ + public function getBookingMarking(): string + { + return $this->bookingMarking; + } + + /** + * @return string + */ + public function getProjectName(): string + { + return $this->projectName; + } + + /** + * @return int + */ + public function getProjectStatus(): int + { + return $this->projectStatus; + } + + /** + * @return array + */ + public function getMilestoneNames(): array + { + return $this->milestoneNames; + } + + /** + * @return array + */ + public function getTaskNames(): array + { + return $this->taskNames; + } + +} diff --git a/app/Classes/Modules/PerfexCRM/Processors/BookingToPerfexCRMProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/BookingToPerfexCRMProcessor.php new file mode 100644 index 00000000..5929ea1d --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Processors/BookingToPerfexCRMProcessor.php @@ -0,0 +1,44 @@ +company->reference; + $companyName = $booking->company->name; + $employee = $booking->company->employees()->first(); + $contactEmail = $employee->email; + $contactName = $employee->name; + $bookingMarking = $booking->marking; + + $serviceTypeName = $booking->company->services()->where('id', $booking->service_id)->first()->name; + $projectName = 'Exchange | '.$serviceTypeName.' | '.$bookingMarking; + + $updatePerfexCRMObject = new UpdatePerfexCRMObject( + $companyName, + $companyReference, + $contactName, + $contactEmail, + $bookingMarking, + $projectName, + PerfexCRMProjectStatus::NOT_STARTED, + [], + [] + ); + UpdatePerfexCRM::dispatch($updatePerfexCRMObject); + + return true; + } +} diff --git a/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php new file mode 100644 index 00000000..767bd894 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php @@ -0,0 +1,198 @@ +createsPerfexCRMInvoice = $createsPerfexCRMInvoice; + $this->createsPerfexCRMInvoicePayment = $createsPerfexCRMInvoicePayment; + $this->convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer; + $this->fetchesPerfexCRMProject = $fetchesPerfexCRMProject; + $this->createsPerfexCRMCustomerProject = $createsPerfexCRMCustomerProject; + } + + /** + * @param $transaction + * @param $purchaseOrder + * @param $supplier + * @return null|object + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute($transaction, $purchaseOrder, $supplier) { + + $clientId = ""; + $number = $transaction->bill_no; + $prefix = "INV-"; + + //This will remove the prefix if prefix already exist in the string + if (substr($number, 0, strlen($prefix)) == $prefix) { + $number = substr($number, strlen($prefix)); + } + $number = 'EXC-'.$number; + + $date = Carbon::parse($transaction->booking->created_at)->format('Y-m-d'); + $dueDate = Carbon::parse($transaction->booking->created_at)->format('Y-m-d'); + $currency = 1; //cief TODO: To look into Malaysia and Chinese currency + $subTotal = 0.00; + $total = 0.00; + + $billingStreet = ""; + $addresses = $supplier->addresses()->where('billing', '=', true)->first(); + + $billingStreet = $billingStreet.$addresses->street_one; + $billingStreet = $billingStreet.$addresses->street_two.','; + $billingStreet = $billingStreet.$addresses->district()->first()->name.','; + $billingStreet = $billingStreet.$addresses->postcode; + $billingStreet = $billingStreet.$addresses->state()->first()->name.','; + $billingStreet = $billingStreet.$addresses->country()->first()->name; + + + $allowedPaymentModes = []; + $invoiceItems = []; + + $email = $supplier->employees()->first()->email; + + $result = $this->convertsPerfexCRMLeadToCustomer->execute($email); + if(isset($result->payload)){ + $clientId = $result->payload['client_id']; + } + + //get project + $projectId = ""; + $bookingMarking = $transaction->owner->marking; + $serviceTypeName = $transaction->owner->company->services()->where('id', $transaction->owner->service_id)->first()->name; + $projectName = 'Exchange | '.$serviceTypeName.' | '.$bookingMarking; + $project = $this->fetchesPerfexCRMProject->execute($projectName, $clientId); + if(!is_null($project)){ + $projectId = $project->id; + } + else{ + $result = $this->createsPerfexCRMCustomerProject->execute($projectName, PerfexCRMProjectStatus::NOT_STARTED, $clientId); + if(isset($result->payload)){ //Here means project creation successful + $projectId = $result->payload['project_id']; + } + } + + //newitems + foreach ($purchaseOrder->transactionDetails as $key => $transaction_detail){ + $order = $key + 1; + $stockCode = $transaction_detail->product_code; + $description = $transaction_detail->product_name; + $quantity = $transaction_detail->quantity; + $unitPrice = 0.00; + if($transaction->booking()->first()->fix_currency_id !== 1) + $unitPrice = (1/$transaction->currency_rate) * $transaction_detail->price; + else + $unitPrice = $transaction_detail->price; + + //$totalAmount = 0.00; + if($transaction->booking()->first()->fix_currency_id !== 1){ + + //$totalAmount = (float)number_format( (1/$transaction->currency_rate) * $transaction_detail->price, 2,'.','')*$transaction_detail->quantity; + $subTotal += number_format((1/$transaction->currency_rate) * $transaction_detail->price, 2,'.','') * $transaction_detail->quantity; + } + else + { + //$totalAmount = (float)number_format($transaction_detail->price, 2,'.','')*$transaction_detail->quantity; + $subTotal += number_format($transaction_detail->price, 2,'.','') * $transaction_detail->quantity; + } + + //string $description, string $longDescription, int $qty, int $rate, int $order, string $unit + $invoiceSingleItem = new InvoiceSingleItemPerfexCRMObject( + $description, + "", + $quantity, + $unitPrice, + $order, + "" + ); + array_push($invoiceItems, $invoiceSingleItem); + } + + if($transaction->booking()->first()->fix_currency_id !== 1){ + $total = ((1/$transaction->currency_rate) * $transaction->amount) + $transaction->service_charge + $transaction->tax; + } + else{ + $total = $transaction->amount + $transaction->service_charge + $transaction->tax; + } + + //This setting is similar to Setup > Leads > Sources, Setup > Leads > Statuses + //Can be found at Finance > Payment Modes + array_push($allowedPaymentModes, 1, 2); + + $invoicePerfexCRMObject = new InvoicePerfexCRMObject( + $clientId, + $number, + $date, + $dueDate, + $currency, + $subTotal, + $total, + $billingStreet, + $projectId, + $allowedPaymentModes, + $invoiceItems + ); + + $result = $this->createsPerfexCRMInvoice->execute($invoicePerfexCRMObject); + + if(!is_null($result)) + { + if($result->payload['id']){ + $invoicePaymentPerfexCRMObject = new InvoicePaymentPerfexCRMObject( + $result->payload['id'], + $total, + $date, + 1, + "", + "" + ); + $this->createsPerfexCRMInvoicePayment->execute($invoicePaymentPerfexCRMObject); + } + } + //else: logs will record the following: + //"status":false,"error":{"number":"The Invoice number is already in use"},"message":"
The Invoice number is already in use<\/p>"} + + + return true; + } + +} diff --git a/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMLeadProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMLeadProcessor.php new file mode 100644 index 00000000..5a0bc6dc --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMLeadProcessor.php @@ -0,0 +1,36 @@ +createsPerfexCRMLead = $createsPerfexCRMLead; + } + + /** + * @param CreateLeadPerfexCRMObject $createLeadPerfexCRMObject + * @return null|object + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(CreateLeadPerfexCRMObject $createLeadPerfexCRMObject) { + return $this->createsPerfexCRMLead->execute($createLeadPerfexCRMObject); + } + +} diff --git a/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMTaskProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMTaskProcessor.php new file mode 100644 index 00000000..965f6f34 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMTaskProcessor.php @@ -0,0 +1,41 @@ +createsPerfexCRMTask = $createsPerfexCRMTask; + } + + /** + * @param CreateTaskPerfexCRMObject $createTaskPerfexCRMObject + * @return true + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(CreateTaskPerfexCRMObject $createTaskPerfexCRMObject) { + $this->createsPerfexCRMTask->execute( + $createTaskPerfexCRMObject->getName(), + $createTaskPerfexCRMObject->getDescription(), + $createTaskPerfexCRMObject->getLeadId(), + $createTaskPerfexCRMObject->getMilestoneId(), + $createTaskPerfexCRMObject->getProjectId(), + $createTaskPerfexCRMObject->getReference(), + $createTaskPerfexCRMObject->getOnTaskCompletion(), + $createTaskPerfexCRMObject->getStatus(), + ); + return true; + } + +} diff --git a/app/Classes/Modules/PerfexCRM/Processors/InitializePerfexCRMProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/InitializePerfexCRMProcessor.php new file mode 100644 index 00000000..875dd35f --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Processors/InitializePerfexCRMProcessor.php @@ -0,0 +1,195 @@ +convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer; + $this->createsPerfexCRMCustomerProject = $createsPerfexCRMCustomerProject; + $this->createsPerfexCRMMilestone = $createsPerfexCRMMilestone; + $this->createsPerfexCRMTask = $createsPerfexCRMTask; + $this->fetchesPerfexCRMProject = $fetchesPerfexCRMProject; + $this->fetchesPerfexCRMMilestone = $fetchesPerfexCRMMilestone; + $this->fetchesPerfexCRMTask = $fetchesPerfexCRMTask; + $this->createsPerfexCRMCustomer = $createsPerfexCRMCustomer; + $this->createsPerfexCRMCustomerContact = $createsPerfexCRMCustomerContact; + $this->updatesPerfexCRMCustomer = $updatesPerfexCRMCustomer; + } + + /** + * @param InitialPerfexCRMObject $initialPerfexCRMObject + * @return null|object + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(InitialPerfexCRMObject $initialPerfexCRMObject) { + + // 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']; + 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($crmCompany); + if(is_null($result)){ + $crmCompany = $crmCompany." 2"; + $result = $this->createsPerfexCRMCustomer->execute($crmCompany); + } + $crmClientId = $result->payload['clientId']; + + $customerContactObject = new CustomerContactObject( + $crmClientId, + $initialPerfexCRMObject->getContactName(), + $initialPerfexCRMObject->getContactName(), + $initialPerfexCRMObject->getContactEmail(), + "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(), $initialPerfexCRMObject->getProjectStatus(), $crmClientId); + if(isset($result->payload)){ //Here means project creation successful + $projectId = $result->payload['project_id']; + } + else{ + $projectId = $this->fetchesPerfexCRMProject->execute($initialPerfexCRMObject->getProjectName(), $crmClientId)->id; + } + + + $tasks = $initialPerfexCRMObject->getTaskNames(); + if(count($tasks) > 0){ + + //Create tasks with milestone + for($count=0; $count < count($tasks); $count++) { + $milestoneId = 0; //By default milestoneId is 0, having this set at individual task is optional + if($tasks[$count]['milestone'] != "") //Create milestone only if it is defined + { + // Get existing or create milestone, milestone has to exist first before task can appear under it + $result = $this->createsPerfexCRMMilestone->execute($tasks[$count]['milestone'], $projectId, $count); + if(isset($result->payload)){ + $milestoneId = $result->payload['milestone_id']; + } + else{ + $milestone = $this->fetchesPerfexCRMMilestone->execute($tasks[$count]['milestone'], $projectId); + $array = json_decode(json_encode($milestone), true); + $milestoneId = $array[0]['id']; + } + } + + $taskStatus = PerfexCRMTaskStatus::NOT_STARTED; + if($tasks[$count]['status'] != ''){ + $taskStatus = $tasks[$count]['status']; + } + + // Get existing or create task + $result = $this->createsPerfexCRMTask->execute($tasks[$count]['name'], $tasks[$count]['description'], '', $milestoneId, $projectId, $tasks[$count]['reference'], $tasks[$count]['on_task_completion'], $taskStatus); + if(is_null($result)){ + break; //Breaking the rest of the tasks in array assuming that they are all created as a batch previously + } + } + } + return true; + } +} diff --git a/app/Classes/Modules/PerfexCRM/Processors/NewLeadTaskToPerfexCRMProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/NewLeadTaskToPerfexCRMProcessor.php new file mode 100644 index 00000000..bce779f1 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Processors/NewLeadTaskToPerfexCRMProcessor.php @@ -0,0 +1,38 @@ +employees()->first(); + $contactEmail = $employee->email; + + $createTaskPerfexCRMObject = new CreateTaskPerfexCRMObject( + $contactEmail, + PerfexCRMTasks::TASK_IDENTIFICATION_1['name'], + PerfexCRMTasks::TASK_IDENTIFICATION_1['description'], + "", + "", + "", + "", + "", + PerfexCRMTasks::TASK_IDENTIFICATION_1['status'] + ); + + CreatePerfexCRMSingleTask::dispatch($createTaskPerfexCRMObject); + return true; + } + +} diff --git a/app/Classes/Modules/PerfexCRM/Processors/TransactionToPerfexCRMProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/TransactionToPerfexCRMProcessor.php new file mode 100644 index 00000000..cd7ba6b0 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Processors/TransactionToPerfexCRMProcessor.php @@ -0,0 +1,127 @@ +owner instanceof \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; + $bookingMarking = $model->owner->marking; + + $serviceTypeName = $model->owner->company->services()->where('id', $model->owner->service_id)->first()->name; + $projectName = 'Exchange | '.$serviceTypeName.' | '.$bookingMarking; + + if($status == ApprovalStatus::APPROVED) + { + if($model->type == TransactionType::PAYMENT){ + $tasks = [ + PerfexCRMTasks::TASK_1 + ]; + if($model->owner->service_id == 1){ + $tasks = [ + PerfexCRMTasks::TASK_1, + PerfexCRMTasks::TASK_1_DAY_TRANSFER_1, + PerfexCRMTasks::TASK_1_DAY_TRANSFER_2, + PerfexCRMTasks::TASK_1_DAY_TRANSFER_3, + PerfexCRMTasks::TASK_1_DAY_TRANSFER_4, + PerfexCRMTasks::TASK_1_DAY_TRANSFER_5, + PerfexCRMTasks::TASK_1_DAY_TRANSFER_6, + ]; + } + else if($model->owner->service_id == 3){ + $tasks = [ + PerfexCRMTasks::TASK_1, + PerfexCRMTasks::TASK_3_DAY_TRANSFER_1, + PerfexCRMTasks::TASK_3_DAY_TRANSFER_2, + PerfexCRMTasks::TASK_3_DAY_TRANSFER_3, + PerfexCRMTasks::TASK_3_DAY_TRANSFER_4, + PerfexCRMTasks::TASK_3_DAY_TRANSFER_5, + PerfexCRMTasks::TASK_3_DAY_TRANSFER_6, + ]; + } + else if($model->owner->service_id == 4){ + $tasks = [ + PerfexCRMTasks::TASK_1, + PerfexCRMTasks::TASK_1688_PAYMENT_1, + PerfexCRMTasks::TASK_1688_PAYMENT_2, + PerfexCRMTasks::TASK_1688_PAYMENT_3, + PerfexCRMTasks::TASK_1688_PAYMENT_4, + PerfexCRMTasks::TASK_1688_PAYMENT_5, + PerfexCRMTasks::TASK_1688_PAYMENT_6, + PerfexCRMTasks::TASK_1688_PAYMENT_7, + PerfexCRMTasks::TASK_1688_PAYMENT_8, + PerfexCRMTasks::TASK_1688_PAYMENT_9, + PerfexCRMTasks::TASK_1688_PAYMENT_10, + PerfexCRMTasks::TASK_1688_PAYMENT_11, + PerfexCRMTasks::TASK_1688_PAYMENT_12, + PerfexCRMTasks::TASK_1688_PAYMENT_13, + + ]; + } + $updatePerfexCRMObject = new UpdatePerfexCRMObject( + $companyName, + $companyReference, + $contactName, + $contactEmail, + $bookingMarking, + $projectName, + PerfexCRMProjectStatus::IN_PROGRESS, + [], + $tasks + ); + UpdatePerfexCRM::dispatch($updatePerfexCRMObject); + } + } + else if($status == ApprovalStatus::PENDING_VERIFICATION){ + if($model->type == TransactionType::PURCHASE_ORDER){ + $tasks = []; + if($model->owner->service_id == 1 || $model->owner->service_id == 3){ + $tasks = [ + PerfexCRMTasks::TASK_PURCHASE_ORDER_1, + PerfexCRMTasks::TASK_PURCHASE_ORDER_2, + ]; + } + + if(count($tasks) > 0){ + $updatePerfexCRMObject = new UpdatePerfexCRMObject( + $companyName, + $companyReference, + $contactName, + $contactEmail, + $bookingMarking, + $projectName, + PerfexCRMProjectStatus::IN_PROGRESS, + [], + $tasks + ); + UpdatePerfexCRM::dispatch($updatePerfexCRMObject); + } + } + } + } + + return true; + } +} diff --git a/app/Classes/Modules/PerfexCRM/Processors/UpdatePerfexCRMProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/UpdatePerfexCRMProcessor.php new file mode 100644 index 00000000..24d45506 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Processors/UpdatePerfexCRMProcessor.php @@ -0,0 +1,210 @@ +convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer; + $this->createsPerfexCRMCustomerProject = $createsPerfexCRMCustomerProject; + $this->createsPerfexCRMMilestone = $createsPerfexCRMMilestone; + $this->createsPerfexCRMTask = $createsPerfexCRMTask; + $this->fetchesPerfexCRMProject = $fetchesPerfexCRMProject; + $this->fetchesPerfexCRMMilestone = $fetchesPerfexCRMMilestone; + $this->fetchesPerfexCRMTask = $fetchesPerfexCRMTask; + $this->createsPerfexCRMCustomer = $createsPerfexCRMCustomer; + $this->createsPerfexCRMCustomerContact = $createsPerfexCRMCustomerContact; + $this->updatesPerfexCRMTask = $updatesPerfexCRMTask; + $this->updatesPerfexCRMCustomer = $updatesPerfexCRMCustomer; + $this->updatesPerfexCRMProject = $updatesPerfexCRMProject; + } + + /** + * @param UpdatePerfexCRMObject $updatePerfexCRMObject + * @return null|object + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(UpdatePerfexCRMObject $updatePerfexCRMObject) { + + // 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 = $updatePerfexCRMObject->getCompanyName(); + $result = $this->convertsPerfexCRMLeadToCustomer->execute($updatePerfexCRMObject->getContactEmail()); + + if(isset($result->payload)){ + $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($crmCompany); + if(is_null($result)){ + $crmCompany = $crmCompany." 2"; + $result = $this->createsPerfexCRMCustomer->execute($crmCompany); + } + $crmClientId = $result->payload['clientId']; + + $customerContactObject = new CustomerContactObject( + $crmClientId, + $updatePerfexCRMObject->getContactName(), + $updatePerfexCRMObject->getContactName(), + $updatePerfexCRMObject->getContactEmail(), + "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'] === $updatePerfexCRMObject->getCompanyReference()) { + $value_exists = true; + break; + } + } + } + if(!$value_exists); + { + $result = $this->updatesPerfexCRMCustomer->execute($crmClientId, $crmCompany, $updatePerfexCRMObject->getCompanyReference()); + } + + // Get existing or create project, project has to exist first before milestone can appear under it + $result = $this->createsPerfexCRMCustomerProject->execute($updatePerfexCRMObject->getProjectName(), $updatePerfexCRMObject->getProjectStatus(), $crmClientId); + if(isset($result->payload)){ //Here means project creation successful + $projectId = $result->payload['project_id']; + } + else{ + $project = $this->fetchesPerfexCRMProject->execute($updatePerfexCRMObject->getProjectName(), $crmClientId); + $projectId = $project->id; + //if the project status is anything but PerfexCRMProjectStatus::NOT_STARTED, update the project + if($updatePerfexCRMObject->getProjectStatus() != PerfexCRMProjectStatus::NOT_STARTED) + { + $this->updatesPerfexCRMProject->execute($project, $updatePerfexCRMObject->getProjectStatus()); + } + } + + + $tasks = $updatePerfexCRMObject->getTaskNames(); + if(count($tasks) > 0){ + + //Create tasks with milestone + for($count=0; $count < count($tasks); $count++) { + $milestoneId = 0; //By default milestoneId is 0, having this set at individual task is optional + if($tasks[$count]['milestone'] != "") //Create milestone only if it is defined + { + // Get existing or create milestone, milestone has to exist first before task can appear under it + $result = $this->createsPerfexCRMMilestone->execute($tasks[$count]['milestone'], $projectId, $count); + if(isset($result->payload)){ + $milestoneId = $result->payload['milestone_id']; + } + else{ + $milestone = $this->fetchesPerfexCRMMilestone->execute($tasks[$count]['milestone'], $projectId); + $array = json_decode(json_encode($milestone), true); + $milestoneId = $array[0]['id']; + } + } + + $taskStatus = PerfexCRMTaskStatus::NOT_STARTED; + if($tasks[$count]['status'] != ''){ + $taskStatus = $tasks[$count]['status']; + } + + // Get existing or create task + $result = $this->createsPerfexCRMTask->execute($tasks[$count]['name'], $tasks[$count]['description'], '', $milestoneId, $projectId, $tasks[$count]['reference'], $tasks[$count]['on_task_completion'], $taskStatus); + if(is_null($result)){ + break; //Breaking the rest of the tasks in array assuming that they are all created as a batch previously + } + } + } + return true; + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/ConvertsPerfexCRMLeadToCustomer.php b/app/Classes/Modules/PerfexCRM/Services/ConvertsPerfexCRMLeadToCustomer.php new file mode 100644 index 00000000..e6e7323e --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/ConvertsPerfexCRMLeadToCustomer.php @@ -0,0 +1,34 @@ + config('perfexcrm.api_key'),]) + ->get(config('perfexcrm.base_url').'/api/leads/convertocustomer/'.$email); + + 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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomer.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomer.php new file mode 100644 index 00000000..e5a19ce3 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomer.php @@ -0,0 +1,37 @@ + $companyName + ]; + + $response = Http::asForm()->withHeaders([ + 'authtoken' => config('perfexcrm.api_key')]) + ->post(config('perfexcrm.base_url').'/api/customers',$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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerContact.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerContact.php new file mode 100644 index 00000000..519c1495 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerContact.php @@ -0,0 +1,44 @@ + $customerContactObject->getCustomerId(), + 'firstname' => $customerContactObject->getFirstName(), + 'lastname' => $customerContactObject->getLastName(), + 'email' => $customerContactObject->getEmail(), //$email + 'password' => $customerContactObject->getPassword(), + 'is_primary' => $customerContactObject->getIsPrimary(), + //'send_set_password_email' => $customerContactObject->getSendSetPasswordEmail(), + ]; + + $response = Http::asForm()->withHeaders([ + 'authtoken' => config('perfexcrm.api_key')]) + ->post(config('perfexcrm.base_url').'/api/contacts',$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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerProject.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerProject.php new file mode 100644 index 00000000..f5d4de3e --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerProject.php @@ -0,0 +1,43 @@ + $projectName, + 'rel_type' => 'customer', + 'billing_type' => 1, + 'clientid' => $clientId, + 'start_date' => date('Y-m-d'), + 'status' => $status + ]; + + $response = Http::asForm()->withHeaders([ + 'authtoken' => config('perfexcrm.api_key')]) + ->post(config('perfexcrm.base_url').'/api/projects',$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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php new file mode 100644 index 00000000..b595a86f --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php @@ -0,0 +1,60 @@ + $invoicePerfexCRMObject->getClientId(), + 'number' => $invoicePerfexCRMObject->getNumber(), + 'date' => $invoicePerfexCRMObject->getDate(), + 'duedate' => $invoicePerfexCRMObject->getDueDate(), + 'currency' => $invoicePerfexCRMObject->getCurrency(), + 'subtotal' => number_format($invoicePerfexCRMObject->getSubTotal(), 2, '.', ''), + 'total' => number_format($invoicePerfexCRMObject->getTotal(), 2, '.', ''), + 'billing_street' => $invoicePerfexCRMObject->getBillingStreet(), + 'project_id' => $invoicePerfexCRMObject->getProjectId(), + 'allowed_payment_modes[0]' => 1, + 'allowed_payment_modes[1]' => 2, + ]; + + for($count=0; $count < count($invoicePerfexCRMObject->getInvoiceItems()); $count++) { + $oneItem = [ + "newitems[".$count."][description]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->description, + "newitems[".$count."][long_description]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->longDescription, + "newitems[".$count."][qty]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->qty, + "newitems[".$count."][rate]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->rate, + "newitems[".$count."][order]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->order, + "newitems[".$count."][unit]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->unit, + ]; + $data = array_merge($data, $oneItem); + } + + $response = Http::asForm()->withHeaders([ + 'authtoken' => config('perfexcrm.api_key')]) + ->post(config('perfexcrm.base_url').'/api/invoices',$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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php new file mode 100644 index 00000000..f3e92529 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php @@ -0,0 +1,43 @@ + $invoicePaymentPerfexCRMObject->getInvoiceId(), + 'amount' => number_format($invoicePaymentPerfexCRMObject->getAmount(), 2, '.', ''), + 'date' => $invoicePaymentPerfexCRMObject->getDate(), + 'paymentmode' => $invoicePaymentPerfexCRMObject->getPaymentMode(), + 'transactionid' => $invoicePaymentPerfexCRMObject->getTransactionId(), + 'note' => $invoicePaymentPerfexCRMObject->getNote(), + ]; + + $response = Http::asForm()->withHeaders([ + 'authtoken' => config('perfexcrm.api_key')]) + ->post(config('perfexcrm.base_url').'/api/invoices/recordpayment',$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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMLead.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMLead.php new file mode 100644 index 00000000..373f4171 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMLead.php @@ -0,0 +1,50 @@ + [ + 3 => $createLeadPerfexCRMObject->getCompanyReference() + ] + ]; + + $data = [ + 'name' => $createLeadPerfexCRMObject->getName(), + 'email' => $createLeadPerfexCRMObject->getEmail(), + 'phonenumber' => $createLeadPerfexCRMObject->getPhone(), + 'company' => $createLeadPerfexCRMObject->getCompanyName(), + 'source' => 1, //1: Exchange, 2: Shipping Portal + 'status' => 2, //2: Lead, 1: Customer, + 'custom_fields' => $custom_fields + ]; + + $response = Http::asForm()->withHeaders([ + 'authtoken' => config('perfexcrm.api_key')]) + ->post(config('perfexcrm.base_url').'/api/leads/byemail',$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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMMilestone.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMMilestone.php new file mode 100644 index 00000000..80cb49bf --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMMilestone.php @@ -0,0 +1,46 @@ + $milestoneName, + 'project_id' => $projectId, + 'due_date' => date('Y-m-d'), + 'start_date' => date('Y-m-d') + ]; + + if($milestoneOrder != ""){ + $data['milestone_order'] = $milestoneOrder; + } + + $response = Http::asForm()->withHeaders([ + 'authtoken' => config('perfexcrm.api_key')]) + ->post(config('perfexcrm.base_url').'/api/milestones',$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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMTask.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMTask.php new file mode 100644 index 00000000..1674c999 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMTask.php @@ -0,0 +1,68 @@ + $taskName, + 'description' => $taskDescription, + 'milestone' => $milestoneId, + 'startdate' => date('Y-m-d'), + 'rel_type' => 'project', + 'rel_id' => $projectId, + 'status' => $status, + 'is_system_created' => 1, + 'reference' => $reference, + 'on_task_completion' => $on_task_completion + ]; + + if($leadId != '') { + $data = [ + 'name' => $taskName, + 'description' => $taskDescription, + 'milestone' => $milestoneId, + 'startdate' => date('Y-m-d'), + 'rel_type' => 'lead', + 'rel_id' => $leadId, + 'status' => $status, + 'is_system_created' => 1, + 'reference' => $reference, + 'on_task_completion' => $on_task_completion + ]; + } + + $response = Http::asForm()->withHeaders([ + 'authtoken' => config('perfexcrm.api_key')]) + ->post(config('perfexcrm.base_url').'/api/tasks',$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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMCustomer.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMCustomer.php new file mode 100644 index 00000000..9f3928f6 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMCustomer.php @@ -0,0 +1,34 @@ + config('perfexcrm.api_key'),]) + ->get(config('perfexcrm.base_url').'/api/customers/byemail/'.$email); + + 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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMInvoice.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMInvoice.php new file mode 100644 index 00000000..cd7aff30 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMInvoice.php @@ -0,0 +1,36 @@ + config('perfexcrm.api_key'),]) + ->get(config('perfexcrm.base_url').'/api/invoices/customsearch/'.$clientId.'/'.$invoicePrefix.'/'.$invoiceNumber); + + 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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMLead.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMLead.php new file mode 100644 index 00000000..df9c754d --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMLead.php @@ -0,0 +1,34 @@ + config('perfexcrm.api_key'),]) + ->get(config('perfexcrm.base_url').'/api/leads/byemail/'.$email); + + 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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMMilestone.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMMilestone.php new file mode 100644 index 00000000..8a5ba559 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMMilestone.php @@ -0,0 +1,35 @@ + config('perfexcrm.api_key'),]) + ->get(config('perfexcrm.base_url').'/api/milestones/bynameandprojectid/'.rawurlencode($milestoneName).'/'.$projectId); + + 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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMProject.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMProject.php new file mode 100644 index 00000000..c55f2c01 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMProject.php @@ -0,0 +1,40 @@ + $projectName, + 'clientid' => $clientId, + ]; + + $response = Http::asForm()->withHeaders([ + 'authtoken' => config('perfexcrm.api_key')]) + ->post(config('perfexcrm.base_url').'/api/projects/bynameandclientid', $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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php new file mode 100644 index 00000000..97707acb --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php @@ -0,0 +1,35 @@ + config('perfexcrm.api_key'),]) + ->get(config('perfexcrm.base_url').'/api/tasks/bynameandmilestoneid/'.rawurlencode($taskName).'/'.$milestoneId); + + 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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMCustomer.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMCustomer.php new file mode 100644 index 00000000..561795f8 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMCustomer.php @@ -0,0 +1,46 @@ + [ + 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()); + } + } +} diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMInvoice.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMInvoice.php new file mode 100644 index 00000000..5240d931 --- /dev/null +++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMInvoice.php @@ -0,0 +1,68 @@ +The Invoice number field is required.<\/p> + //
The Invoice date field is required.<\/p> + //
The Currency field is required.<\/p> + //
The Items field is required.<\/p> + //
The Allow Payment Mode field is required.<\/p> + //
The Billing Street field is required.<\/p> + //
The Sub Total field is required.<\/p> + //
The Total field is required.<\/p>
+
+ $newInvoiceItems = [];
+ foreach ($invoice->items as $item) {
+ $item['itemid'] = $item['id'];
+ unset($item['id']);
+ $item['order'] = $item['item_order'];
+ unset($item['item_order']);
+ array_push($newInvoiceItems,$item);
+ }
+
+ $data = [
+ 'number' => $invoice->number,
+ 'date' => $invoice->date,
+ 'duedate' => $invoice->date,
+ 'currency' => $invoice->currency,
+ 'subtotal' => $invoice->subtotal,
+ 'total' => $invoice->total,
+ 'billing_street' => $invoice->billing_street,
+ 'shipping_street' => $invoice->billing_street,
+ 'project_id' => $projectId,
+ 'items' => $newInvoiceItems,
+ 'allowed_payment_modes' => $invoice->allowed_payment_modes,
+ ];
+
+ $response = Http::asJson()->withHeaders([
+ 'authtoken' => config('perfexcrm.api_key')])
+ ->put(config('perfexcrm.base_url').'/api/invoices/'.$invoice->id, $data);
+
+ if($response->successful()){
+ $data = $response->json();
+ return (object) $data;
+ }else{
+ Log::error($response);
+ return null;
+ }
+ }catch(\Exception $exception){
+ dd(json_encode($exception));
+ throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
+ }
+ }
+}
diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMLead.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMLead.php
new file mode 100644
index 00000000..b9090c2e
--- /dev/null
+++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMLead.php
@@ -0,0 +1,50 @@
+ [
+ 3 => $companyReference
+ ]
+ ];
+
+ $data = [
+ 'name' => $lead->name,
+ 'email' => $lead->email,
+ 'phonenumber' => $lead->phonenumber,
+ 'company' => $lead->company,
+ 'custom_fields' => $custom_fields,
+ 'source' => $lead->source,
+ 'status' => $lead->status,
+ ];
+
+ $response = Http::asJson()->withHeaders([
+ 'authtoken' => config('perfexcrm.api_key')])
+ ->put(config('perfexcrm.base_url').'/api/leads/'.$lead->id, $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());
+ }
+ }
+}
diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMProject.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMProject.php
new file mode 100644
index 00000000..6c016ff0
--- /dev/null
+++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMProject.php
@@ -0,0 +1,43 @@
+ $project->name,
+ 'clientid' => $project->clientid,
+ // 'rel_type' => 'customer',
+ 'billing_type' => 1,
+ 'start_date' => $project->start_date,
+ 'status' => $status
+ ];
+
+ $response = Http::asJson()->withHeaders([
+ 'authtoken' => config('perfexcrm.api_key')])
+ ->put(config('perfexcrm.base_url').'/api/projects/'.$project->id, $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());
+ }
+ }
+}
diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMTask.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMTask.php
new file mode 100644
index 00000000..928f9c5a
--- /dev/null
+++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMTask.php
@@ -0,0 +1,48 @@
+ $taskName,
+ 'milestone' => $milestoneId,
+ 'startdate' => date('Y-m-d'),
+ 'duedate' => date('Y-m-d'),
+ 'rel_type' => 'project',
+ 'rel_id' => $projectId,
+ 'status' => $status,
+ 'repeat_every' => '',
+ ];
+
+ $response = Http::asJson()->withHeaders([
+ 'authtoken' => config('perfexcrm.api_key')])
+ ->put(config('perfexcrm.base_url').'/api/tasks/'.$taskId, $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());
+ }
+ }
+}
diff --git a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php
index 9268dae0..d48d4d5b 100644
--- a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php
+++ b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php
@@ -18,6 +18,7 @@ use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\SegmentConstants;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\DocumentType;
+use App\Classes\Jobs\CreatePerfexCRMInvoice;
use App\Models\Booking;
use App\Models\SegmentConstant;
@@ -51,6 +52,7 @@ class CreateInvoiceTransactionProcessor
/** @var CreateInvoiceDocumentProcessor */
private $invoiceDocumentProcessor;
+
/**
* CreateInvoiceTransactionProcessor constructor.
* @param ListsTransactions $listsTransactions
@@ -192,6 +194,11 @@ class CreateInvoiceTransactionProcessor
// supply deliver order
$this->invoiceDocumentProcessor->execute($supplier_deliver_order_transaction, $purchaseOrder, $supplier, DocumentType::SUPPLIER_DELIVER_ORDER);
+ // update perfex crm
+ if(config('perfexcrm.is_enabled') == 'true'){
+ CreatePerfexCRMInvoice::dispatch($invoice_transaction, $purchaseOrder, $supplier);
+ }
+
$this->updatesBookingStatus->execute($booking, ApprovalStatus::COMPLETED);
}
}
diff --git a/app/Classes/Modules/Transactions/Processors/UpdateWalletTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/UpdateWalletTransactionProcessor.php
index 7c7277f8..c1d36edb 100644
--- a/app/Classes/Modules/Transactions/Processors/UpdateWalletTransactionProcessor.php
+++ b/app/Classes/Modules/Transactions/Processors/UpdateWalletTransactionProcessor.php
@@ -27,6 +27,9 @@ class UpdateWalletTransactionProcessor
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
+ /** @var UpdatesWallet */
+ private $updatesWallet;
+
public function __construct(UpdatesTransactionStatus $updatesTransactionStatus, UpdatesWallet $updatesWallet, FetchesTransaction $fetchesTransaction)
{
$this->fetchesTransaction = $fetchesTransaction;
diff --git a/app/Classes/Modules/Transactions/Services/UpdatesTransactionStatus.php b/app/Classes/Modules/Transactions/Services/UpdatesTransactionStatus.php
index ec0bb673..2843e0c2 100644
--- a/app/Classes/Modules/Transactions/Services/UpdatesTransactionStatus.php
+++ b/app/Classes/Modules/Transactions/Services/UpdatesTransactionStatus.php
@@ -4,9 +4,27 @@ namespace App\Classes\Modules\Transactions\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\Transaction;
+use App\Classes\Modules\PerfexCRM\Processors\TransactionToPerfexCRMProcessor;
+use App\Classes\Modules\PerfexCRM\Processors\NewLeadTaskToPerfexCRMProcessor;
class UpdatesTransactionStatus extends AbstractUpdateRecord
{
+ /** @var TransactionToPerfexCRMProcessor */
+ private $transactionToPerfexCRMProcessor;
+
+ /** @var NewLeadTaskToPerfexCRMProcessor */
+ private $newLeadTaskToPerfexCRMProcessor;
+
+ /**
+ * UpdatesTransactionStatus constructor.
+ * @param TransactionToPerfexCRMProcessor $transactionToPerfexCRMProcessor
+ * @param NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor
+ */
+ public function __construct(TransactionToPerfexCRMProcessor $transactionToPerfexCRMProcessor, NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor)
+ {
+ $this->transactionToPerfexCRMProcessor = $transactionToPerfexCRMProcessor;
+ $this->newLeadTaskToPerfexCRMProcessor = $newLeadTaskToPerfexCRMProcessor;
+ }
/**
* @param Transaction $model
@@ -16,8 +34,12 @@ class UpdatesTransactionStatus extends AbstractUpdateRecord
*/
public function execute(Transaction $model, int $status)
{
+ if(config('perfexcrm.is_enabled') == 'true'){
+ $this->transactionToPerfexCRMProcessor->execute($model, $status);
+ // $this->newLeadTaskToPerfexCRMProcessor->execute();
+ }
$model->status = $status;
return $this->handler($model);
}
-}
\ No newline at end of file
+}
diff --git a/app/Classes/ValueObjects/Constants/PerfexCRMInvoiceStatus.php b/app/Classes/ValueObjects/Constants/PerfexCRMInvoiceStatus.php
new file mode 100644
index 00000000..2e692129
--- /dev/null
+++ b/app/Classes/ValueObjects/Constants/PerfexCRMInvoiceStatus.php
@@ -0,0 +1,14 @@
+ 'Customer Paid',
+ 'description' => '',
+ 'milestone' => 'MILESTONE 1 - Customer Paid',
+ 'reference' => '',
+ 'on_task_completion' => '',
+ 'status' => PerfexCRMTaskStatus::COMPLETED
+ ];
+
+ public const TASK_1_DAY_TRANSFER_1 = [
+ 'name' => 'Map Bank Transaction Record',
+ 'description' => '○ Purpose: To map a transaction to bank transaction in the bank statement
+ ○ Initial Status: In Progress
+ ○ Deadline: If payment is created before 4:30 pm, it must be made on the same day. If payment is created after 4:30 pm, it must be made the next day
+ ○ Responsible department: Accounts
+ ○ Next step: Change the status of the Approve payment status to "In Progress" upon successful completion of the operation.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: None
+ ○ Outcomes: Bank transaction is mapped successfully, allowing the next steps in the process to be initiated.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1_DAY_TRANSFER_1',
+ 'on_task_completion' => 'TASK_1_DAY_TRANSFER_2',
+ 'status' => PerfexCRMTaskStatus::IN_PROGRESS
+ ];
+ public const TASK_1_DAY_TRANSFER_2 = [
+ 'name' => 'Approve Payment',
+ 'description' => '○ Purpose: To verify and approve the customer\'s payment on exchange
+ ○ Initial Status: Not Started
+ ○ Deadline:If payment is created before 4:30 pm, it must be made on the same day. If payment is created after 4:30 pm, it must be made the next day
+ ○ Responsible department: Accounts
+ ○ Next step:
+ i. Change the status of the Issue Exchange Autocount Invoice operation to "In Progress"
+ ii. Change the status of the Order Placed in White Form operation to "In Progress" upon successful completion.
+ ○ Additional details: When the payment method is FPX or Wallet this task is performed automatically by the system.
+ ○ Dependencies: Map Transaction operation must be completed before this operation can begin.
+ ○ Outcomes: The payment will be approved in exchange, allowing the next steps in the process to be initiated.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1_DAY_TRANSFER_2',
+ 'on_task_completion' => 'TASK_1_DAY_TRANSFER_3',
+ 'status' => ''
+ ];
+ public const TASK_1_DAY_TRANSFER_3 = [
+ 'name' => 'Issue Exchange Autocount Invoince',
+ 'description' => '○ Purpose: To issue an invoice for the customer\'s payment in accounting software.
+ ○ Initial Status: Not Started
+ ○ Deadline: Next day
+ ○ Responsible department: Accounts
+ ○ Next step: Change the status of the Knockoff Invoice operation to "In Progress" upon successful completion.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Approve Payment operation must be completed before this operation can begin.
+ ○ Outcomes: An invoice will be issued in accounting software for the customer\'s payment.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1_DAY_TRANSFER_3',
+ 'on_task_completion' => 'TASK_1_DAY_TRANSFER_4',
+ 'status' => ''
+ ];
+ public const TASK_1_DAY_TRANSFER_4 = [
+ 'name' => 'Knockoff Invoice',
+ 'description' => '○ Purpose: The purpose of this operation is to issue the official receipt and knockoff with invoice for the customer\'s payment.
+ ○ Initial Status: Not Started
+ ○ Deadline: Next day.
+ ○ Responsible Department: Accounts
+ ○ Next Step: None
+ ○ Additional Details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Issue Exchange Autocount Invoice operation must be completed before this operation can begin.
+ ○ Outcomes: The customer\'s payment is applied to the accounting software invoice and invoice is marked as paid.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1_DAY_TRANSFER_4',
+ 'on_task_completion' => 'TASK_1_DAY_TRANSFER_5',
+ 'status' => ''
+ ];
+ public const TASK_1_DAY_TRANSFER_5 = [
+ 'name' => 'Order Placed in White Form',
+ 'description' => '○ Purpose: To confirm that the order has been placed with the supplier.
+ ○ Initial Status: Not Started
+ ○ Deadline: Same day
+ ○ Responsible department: Operations
+ ○ Next step: Change the status of Upload China Bank Slip operation to "In Progress" upon successful completion.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Approve Payment operation must be completed before this operation can begin.
+ ○ Outcomes: The order is placed with a supplier and the customer\'s order is confirmed.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1_DAY_TRANSFER_5',
+ 'on_task_completion' => 'TASK_1_DAY_TRANSFER_6',
+ 'status' => ''
+ ];
+ public const TASK_1_DAY_TRANSFER_6 = [
+ 'name' => 'Upload China Bank Slip',
+ 'description' => '○ Purpose: To confirm that the customer order has been transferred to the customer\'s supplier.
+ ○ Initial Status: Not Started
+ ○ Deadline: Next day
+ ○ Responsible department: Operations
+ ○ Next step: None
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Order Placed in White Form operation must be completed before this operation can begin.
+ ○ Outcomes: The customer can download the payment transfer proof to send to their supplier.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1_DAY_TRANSFER_6',
+ 'on_task_completion' => '',
+ 'status' => ''
+ ];
+
+ public const TASK_3_DAY_TRANSFER_1 = [
+ 'name' => 'Map Bank Transaction Record',
+ 'description' => '○ Purpose: To map a transaction to bank transaction in the bank statement
+ ○ Initial Status: In Progress
+ ○ Deadline: If payment is created before 4:30 pm, it must be made on the same day. If payment is created after 4:30 pm, it must be made the next day
+ ○ Responsible department: Accounts
+ ○ Next step: Change the status of the Approve payment status to "In Progress" upon successful completion of the operation.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: None
+ ○ Outcomes: Bank transaction is mapped successfully, allowing the next steps in the process to be initiated.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_3_DAY_TRANSFER_1',
+ 'on_task_completion' => 'TASK_3_DAY_TRANSFER_2',
+ 'status' => PerfexCRMTaskStatus::IN_PROGRESS
+ ];
+ public const TASK_3_DAY_TRANSFER_2 = [
+ 'name' => 'Approve Payment',
+ 'description' => '○ Purpose: To verify and approve the customer\'s payment on exchange
+ ○ Initial Status: Not Started
+ ○ Deadline:If payment is created before 4:30 pm, it must be made on the same day. If payment is created after 4:30 pm, it must be made the next day
+ ○ Responsible department: Accounts
+ ○ Next step:
+ i. Change the status of the Issue Exchange Autocount Invoice operation to "In Progress"
+ ii. Change the status of the Order Placed in White Form operation to "In Progress" upon successful completion.
+ ○ Additional details: When the payment method is FPX or Wallet this task is performed automatically by the system.
+ ○ Dependencies: Map Transaction operation must be completed before this operation can begin.
+ ○ Outcomes: The payment will be approved in exchange, allowing the next steps in the process to be initiated.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_3_DAY_TRANSFER_2',
+ 'on_task_completion' => 'TASK_3_DAY_TRANSFER_3',
+ 'status' => ''
+ ];
+ public const TASK_3_DAY_TRANSFER_3 = [
+ 'name' => 'Issue Exchange Autocount Invoince',
+ 'description' => '○ Purpose: To issue an invoice for the customer\'s payment in accounting software.
+ ○ Initial Status: Not Started
+ ○ Deadline: Next day
+ ○ Responsible department: Accounts
+ ○ Next step: Change the status of the Knockoff Invoice operation to "In Progress" upon successful completion.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Approve Payment operation must be completed before this operation can begin.
+ ○ Outcomes: An invoice will be issued in accounting software for the customer\'s payment.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_3_DAY_TRANSFER_3',
+ 'on_task_completion' => 'TASK_3_DAY_TRANSFER_4',
+ 'status' => ''
+ ];
+ public const TASK_3_DAY_TRANSFER_4 = [
+ 'name' => 'Knockoff Invoice',
+ 'description' => '○ Purpose: The purpose of this operation is to issue the official receipt and knockoff with invoice for the customer\'s payment.
+ ○ Initial Status: Not Started
+ ○ Deadline: Next day.
+ ○ Responsible Department: Accounts
+ ○ Next Step: None
+ ○ Additional Details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Issue Exchange Autocount Invoice operation must be completed before this operation can begin.
+ ○ Outcomes: The customer\'s payment is applied to the accounting software invoice and invoice is marked as paid.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_3_DAY_TRANSFER_4',
+ 'on_task_completion' => 'TASK_3_DAY_TRANSFER_5',
+ 'status' => ''
+ ];
+ public const TASK_3_DAY_TRANSFER_5 = [
+ 'name' => 'Order Placed in White Form',
+ 'description' => '○ Purpose: To confirm that the order has been placed with the supplier.
+ ○ Initial Status: Not Started
+ ○ Deadline: After 2 days
+ ○ Responsible department: Operations
+ ○ Next step: Change the status of Upload China Bank Slip operation to "In Progress" upon successful completion.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Approve Payment operation must be completed before this operation can begin.
+ ○ Outcomes: The order is placed with a supplier and the customer\'s order is confirmed.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_3_DAY_TRANSFER_5',
+ 'on_task_completion' => 'TASK_3_DAY_TRANSFER_6',
+ 'status' => ''
+ ];
+ public const TASK_3_DAY_TRANSFER_6 = [
+ 'name' => 'Upload China Bank Slip',
+ 'description' => '○ Purpose: To confirm that the customer order has been transferred to the customer\'s supplier.
+ ○ Initial Status: Not Started
+ ○ Deadline: After 3 days
+ ○ Responsible department: Operations
+ ○ Next step: None
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Order Placed in White Form operation must be completed before this operation can begin.
+ ○ Outcomes: The customer can download the payment transfer proof to send to their supplier.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_3_DAY_TRANSFER_6',
+ 'on_task_completion' => '',
+ 'status' => ''
+ ];
+
+
+ public const TASK_1688_PAYMENT_1 = [
+ 'name' => 'Map Bank Transaction Record',
+ 'description' => '○ Purpose: To map a transaction to bank transaction in the bank statement
+ ○ Initial Status: In Progress
+ ○ Deadline: If payment is created before 4:30 pm, it must be made on the same day. If payment is created after 4:30 pm, it must be made the next day
+ ○ Responsible department: Accounts
+ ○ Next step: Change the status of the Approve payment status to "In Progress" upon successful completion of the operation.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: None
+ ○ Outcomes: Bank transaction is mapped successfully, allowing the next
+ steps in the process to be initiated.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1688_PAYMENT_1',
+ 'on_task_completion' => 'TASK_1688_PAYMENT_2',
+ 'status' => PerfexCRMTaskStatus::IN_PROGRESS
+ ];
+ public const TASK_1688_PAYMENT_2 = [
+ 'name' => 'Approve Payment',
+ 'description' => '○ Purpose: To verify and approve the customer\'s payment on exchange
+ ○ Initial Status: Not Started
+ ○ Deadline:If payment is created before 4:30 pm, it must be made on the same day. If payment is created after 4:30 pm, it must be made the next day
+ ○ Responsible department: Accounts
+ ○ Next step:
+ i. Change the status of the Issue Exchange Autocount Invoice operation to "In Progress"
+ ii. Change the status of the Order Placed in White Form operation to "In Progress" upon successful completion.
+ ○ Additional details: When the payment method is FPX or Wallet this task is performed automatically by the system.
+ ○ Dependencies: Map Transaction operation must be completed before this operation can begin.
+ ○ Outcomes: The payment will be approved in exchange, allowing the next steps in the process to be initiated.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1688_PAYMENT_2',
+ 'on_task_completion' => 'TASK_1688_PAYMENT_3',
+ 'status' => ''
+ ];
+ public const TASK_1688_PAYMENT_3 = [
+ 'name' => 'Issue Exchange Autocount Invoice',
+ 'description' => '○ Purpose: To issue an invoice for the customer\'s payment in accounting software.
+ ○ Initial Status: Not Started
+ ○ Deadline: Next day
+ ○ Responsible department: Accounts
+ ○ Next step: Change the status of the Knockoff Invoice operation to "In Progress" upon successful completion.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Approve Payment operation must be completed before this operation can begin.
+ ○ Outcomes: An invoice will be issued in accounting software for the customer\'s payment.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1688_PAYMENT_3',
+ 'on_task_completion' => 'TASK_1688_PAYMENT_4',
+ 'status' => ''
+ ];
+ public const TASK_1688_PAYMENT_4 = [
+ 'name' => 'Knockoff Invoice',
+ 'description' => '○ Purpose: The purpose of this operation is to issue the official receipt and knockoff with invoice for the customer\'s payment.
+ ○ Initial Status: Not Started
+ ○ Deadline: Next day.
+ ○ Responsible Department: Accounts
+ ○ Next Step: None
+ ○ Additional Details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Issue Exchange Autocount Invoice operation must be completed before this operation can begin.
+ ○ Outcomes: The customer\'s payment is applied to the accounting software invoice and invoice is marked as paid.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1688_PAYMENT_4',
+ 'on_task_completion' => 'TASK_1688_PAYMENT_5',
+ 'status' => ''
+ ];
+ public const TASK_1688_PAYMENT_5 = [
+ 'name' => 'Order Placed in White Form',
+ 'description' => '○ Purpose: To confirm that the order has been placed with the supplier.
+ ○ Initial Status: Not Started
+ ○ Deadline: Same Day
+ ○ Responsible department: Operations
+ ○ Next step: Change the status of Send White Form to Operation
+ Department operation to "In Progress" upon successful completion.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Approve Payment operation must be completed before this operation can begin.
+ ○ Outcomes: The order is placed with a supplier and the customer\'s order is confirmed.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1688_PAYMENT_5',
+ 'on_task_completion' => 'TASK_1688_PAYMENT_6',
+ 'status' => ''
+ ];
+ public const TASK_1688_PAYMENT_6 = [
+ 'name' => 'Send White Form to Operation Department',
+ 'description' => '○ Purpose: To give confirmation to the operation department to process the order.
+ ○ Initial Status: Not Started
+ ○ Deadline: Same day
+ ○ Responsible department: Operations
+ ○ Next step: Change the status of Upload China Bank Slip operation to "In Progress" upon successful completion.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Order Placed in White Form operation must be completed before this operation can begin.
+ ○ Outcomes: The customer\'s order is confirmed and placed in a white form.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1688_PAYMENT_6',
+ 'on_task_completion' => 'TASK_1688_PAYMENT_7',
+ 'status' => ''
+ ];
+ public const TASK_1688_PAYMENT_7 = [
+ 'name' => 'Authorize Customer\'s 1688 Account',
+ 'description' => '○ Purpose: To authorize the alipay account to make payment to the customer\'s 1688 account.
+ ○ Initial Status: Not Started
+ ○ Deadline: Same day
+ ○ Responsible department: Operations
+ ○ Next step: Change the status of Make Payment for Customer 1688
+ Order operation to "In Progress" upon successful completion.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Send White Form to Operation Department operation
+ must be completed before this operation can begin.
+ ○ Outcomes: The customer\'s 1688 account is authorized to use the alipay account for making payments.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1688_PAYMENT_7',
+ 'on_task_completion' => 'TASK_1688_PAYMENT_8',
+ 'status' => ''
+ ];
+ public const TASK_1688_PAYMENT_8 = [
+ 'name' => 'Make Payment for Customer 1688 Order',
+ 'description' => '○ Purpose: To confirm that the order has been placed with the supplier.
+ ○ Initial Status: Not Started
+ ○ Deadline: Same day
+ ○ Responsible department: Operations
+ ○ Next step: Change the status of Upload China Bank Slip operation to "In Progress" upon successful completion.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Authorize Customer’s 1688 Account operation must be completed before this operation can begin.
+ ○ Outcomes: The customer’s 1688 order is paid.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1688_PAYMENT_8',
+ 'on_task_completion' => 'TASK_1688_PAYMENT_9',
+ 'status' => ''
+ ];
+ public const TASK_1688_PAYMENT_9 = [
+ 'name' => 'Upload China Bank Slip',
+ 'description' => '○ Purpose: To confirm that the customer order has been transferred to the customer\'s supplier.
+ ○ Initial Status: Not Started
+ ○ Deadline: After 3 days
+ ○ Responsible department: Operations
+ ○ Next step: None
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Make Payment for Customer 1688 Order operation must be completed before this operation can begin.
+ ○ Outcomes: The customer can download the payment transfer proof to send to their supplier.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1688_PAYMENT_9',
+ 'on_task_completion' => 'TASK_1688_PAYMENT_10',
+ 'status' => ''
+ ];
+ public const TASK_1688_PAYMENT_10 = [
+ 'name' => 'Upload 1688 Purchase Order PDF',
+ 'description' => '○ Purpose: To store a copy of the original purchase order document for bookkeeping.
+ ○ Initial Status: Not Started
+ ○ Deadline: Same day
+ ○ Responsible department: Operations
+ ○ Next step: Change the status of Upload China Bank Slip operation to "In Progress" upon successful completion.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Make Payment for Customer 1688 Order operation must be completed before this operation can begin.
+ ○ Outcomes: The 1688 purchase order’s pdf is attached to the booking.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1688_PAYMENT_10',
+ 'on_task_completion' => 'TASK_1688_PAYMENT_11',
+ 'status' => ''
+ ];
+ public const TASK_1688_PAYMENT_11 = [
+ 'name' => 'Fill Up Purchase Order',
+ 'description' => '○ Purpose: To store the purchase order details to generate the invoice.
+ ○ Initial Status: Not Started
+ ○ Deadline: Same day
+ ○ Responsible department: Operations
+ ○ Next step: Change the status of Approve Purchase Order operation to "In Progress" upon successful completion.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Upload 1688 Purchase Order PDF operation must be completed before this operation can begin.
+ ○ Outcomes: The purchase order’s details are added to the booking.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1688_PAYMENT_11',
+ 'on_task_completion' => 'TASK_1688_PAYMENT_12',
+ 'status' => ''
+ ];
+ public const TASK_1688_PAYMENT_12 = [
+ 'name' => 'Approve Purchase Order',
+ 'description' => '○ Purpose: To check that the customer submitted a purchase order that complies with our company’s guidelines.
+ ○ Initial Status: Not Started
+ ○ Deadline: Same day
+ ○ Responsible department: Operations
+ ○ Next step: Change the status of Complete Order bookkeeping operation to "In Progress" upon successful completion.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Fill Up Purchase Order operation must be completed before this operation can begin.
+ ○ Outcomes: The purchase order submitted is approved.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1688_PAYMENT_12',
+ 'on_task_completion' => 'TASK_1688_PAYMENT_13',
+ 'status' => ''
+ ];
+ public const TASK_1688_PAYMENT_13 = [
+ 'name' => 'Complete Order bookeeping',
+ 'description' => '○ Purpose: To complete the bookkeeping for the booking.
+ ○ Initial Status: Not Started
+ ○ Deadline: Same day
+ ○ Responsible department: Operations
+ ○ Next step: None
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Approve Purchase Order and Upload China Bank Slip operation must be completed before this operation can begin.
+ ○ Outcomes: The order is placed with a supplier and the customer’s order is confirmed.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_1688_PAYMENT_13',
+ 'on_task_completion' => '',
+ 'status' => ''
+ ];
+
+
+
+ public const TASK_PURCHASE_ORDER_1 = [
+ 'name' => 'Approve Purchase Order',
+ 'description' => '○ Purpose: To check that the customer submitted a purchase order that complies with our company’s guidelines.
+ ○ Initial Status: In Progress
+ ○ Deadline: Next day
+ ○ Responsible department: Operation
+ ○ Next step: Change the status of the Approve payment status to "In Progress" upon successful completion of the operation.
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: None
+ ○ Outcomes: Bank transaction is mapped successfully, allowing the next steps in the process to be initiated.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_PURCHASE_ORDER_1',
+ 'on_task_completion' => 'TASK_PURCHASE_ORDER_2',
+ 'status' => PerfexCRMTaskStatus::IN_PROGRESS
+ ];
+
+ public const TASK_PURCHASE_ORDER_2 = [
+ 'name' => 'Complete Order bookkeeping',
+ 'description' => '○ Purpose: To complete the bookkeeping for the booking.
+ ○ Initial Status: Not Started
+ ○ Deadline: Next day
+ ○ Responsible department: Account
+ ○ Next step: None
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: Approve Purchase Order and Upload China Bank Slip operation must be completed before this operation can begin.
+ ○ Outcomes: A copy of the documents related to the booking should now all be in the google drive relevant folder.
',
+ 'milestone' => '',
+ 'reference' => 'TASK_PURCHASE_ORDER_2',
+ 'on_task_completion' => '',
+ 'status' => ''
+ ];
+
+
+ public const TASK_IDENTIFICATION_1 = [
+ 'name' => 'Approve Identification Verification',
+ 'description' => '○ Purpose: To ensure the customer submit information matches the information in their identification document.
+ ○ Initial Status: In Progress
+ ○ Deadline: Same Day
+ ○ Responsible department: Operation
+ ○ Next step: None
+ ○ Additional details: ** Any specific requirements or notes for the operation.**
+ ○ Dependencies: None
+ ○ Outcomes: Customer account identification is verified
',
+ 'milestone' => '',
+ 'reference' => 'TASK_IDENTIFICATION_1',
+ 'on_task_completion' => '',
+ 'status' => PerfexCRMTaskStatus::IN_PROGRESS
+ ];
+}
diff --git a/config/perfexcrm.php b/config/perfexcrm.php
new file mode 100644
index 00000000..f67040f5
--- /dev/null
+++ b/config/perfexcrm.php
@@ -0,0 +1,7 @@
+ 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'),
+];
diff --git a/docker-setup/Dockerfile b/docker-setup/Dockerfile
new file mode 100644
index 00000000..13ce0249
--- /dev/null
+++ b/docker-setup/Dockerfile
@@ -0,0 +1,28 @@
+FROM php:7.4-fpm
+
+WORKDIR /var/www/html
+
+RUN docker-php-ext-install pdo pdo_mysql
+
+RUN apt-get update && apt-get install -y \
+ libfreetype6-dev \
+ libjpeg62-turbo-dev \
+ libpng-dev \
+ libzip-dev \
+ zip \
+ cron \
+ supervisor \
+ nano \
+ && docker-php-ext-configure gd --with-freetype --with-jpeg \
+ && docker-php-ext-install -j$(nproc) gd \
+ && docker-php-ext-install zip \
+ && docker-php-ext-install bcmath
+
+COPY --from=composer:1.9.3 /usr/bin/composer /usr/bin/composer
+
+#NODEJS & NPM
+RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
+RUN apt-get -y install nodejs
+
+RUN chown -R www-data:www-data /var/www
+RUN chmod 755 /var/www
\ No newline at end of file
diff --git a/docker-setup/docker-compose.yml b/docker-setup/docker-compose.yml
new file mode 100644
index 00000000..deb02207
--- /dev/null
+++ b/docker-setup/docker-compose.yml
@@ -0,0 +1,54 @@
+version: '3'
+
+networks:
+ exchange-staging:
+
+services:
+ #################################################################
+ nginx:
+ image: nginx:stable-alpine
+ container_name: exchange-ngnix
+ ports:
+ - "8082:80"
+ volumes:
+ - ../:/var/www/html
+ - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
+ depends_on:
+ - php
+ - mysql
+ networks:
+ - exchange-staging
+ #################################################################
+ mysql:
+ image: mysql:5.7.29
+ container_name: exchange-mysql
+ restart: unless-stopped
+ tty: true
+ ports:
+ - 3302:3306
+ environment:
+ MYSQL_ROOT_USER: root
+ MYSQL_ROOT_PASSWORD: root
+ MYSQL_DATABASE: exchange-db
+ MYSQL_USER: master
+ MYSQL_PASSWORD: cDe7gcrRBWetaAP
+ volumes:
+ - mysql-data:/var/lib/mysql
+ networks:
+ - exchange-staging
+ #################################################################
+ php:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ container_name: exchange-php
+ volumes:
+ - ../:/var/www/html
+ ports:
+ - "9002:9000"
+ networks:
+ - exchange-staging
+ #################################################################
+
+volumes:
+ mysql-data:
diff --git a/docker-setup/nginx/default.conf b/docker-setup/nginx/default.conf
new file mode 100644
index 00000000..8761015c
--- /dev/null
+++ b/docker-setup/nginx/default.conf
@@ -0,0 +1,27 @@
+server {
+ listen 80;
+ index index.php index.html;
+ server_name localhost;
+ error_log /var/log/nginx/error.log;
+ access_log /var/log/nginx/access.log;
+ root /var/www/html/public;
+
+ server_name localhost;
+
+ location / {
+ try_files $uri $uri/ /index.php?$query_string;
+ }
+
+ location ~ \.php$ {
+ try_files $uri =404;
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_pass php:9000;
+ fastcgi_index index.php;
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_param PATH_INFO $fastcgi_path_info;
+ fastcgi_intercept_errors on;
+ fastcgi_keep_conn on;
+ fastcgi_param PHP_VALUE "auto_prepend_file= \n allow_url_include=Off";
+ }
+}
\ No newline at end of file
diff --git a/resources/views/pages/payments_redirect.blade.php b/resources/views/pages/payments_redirect.blade.php
index 1f3b04cb..e7f98d9c 100644
--- a/resources/views/pages/payments_redirect.blade.php
+++ b/resources/views/pages/payments_redirect.blade.php
@@ -43,9 +43,11 @@