Compare commits

...

16 Commits

Author SHA1 Message Date
Dillon 5934fbcb6c Add in missing update project function 2023-03-11 19:43:30 +08:00
Dillon 45c94321b1 Fix a problem in invoice item where the amount cannot be 0 2023-03-11 16:32:49 +08:00
Dillon 4fbe771dce Fix a problem with task name in CRM must be unique 2023-03-10 21:12:43 +08:00
Dillon 1c072d7b96 CRM create all remaining tasks according to documentation 2023-03-10 02:41:41 +08:00
edmondlang eeb7bb77bb delete duplicated invoice 2023-03-09 12:46:00 +08:00
edmondlang 2de60c8262 test delete duplicated invoice 2023-03-09 12:44:36 +08:00
edmondlang c8a2ce71e1 test delete duplicated invoice 2023-03-09 12:39:28 +08:00
edmondlang 7e04580be0 update show duplicated invoice 2023-03-09 12:34:37 +08:00
edmondlang 3d15a8e312 delete duplicate invoice logic 2023-03-09 10:21:40 +08:00
edmondlang 9936e42574 update show duplicated invoice 2023-03-09 10:15:20 +08:00
edmondlang 16ffec01d4 fix missing invoices 2023-03-09 09:28:45 +08:00
edmondlang 7959f8c83c fix missing invoices 2023-03-08 22:02:03 +08:00
edmondlang 16b5660f12 fix duplicated packing list 2023-03-08 15:33:17 +08:00
edmondlang 023954db70 fix duplicated packing list 2023-03-08 14:32:10 +08:00
edmondlang 535b8a59b9 fix invoice drop date 2023-03-08 11:48:38 +08:00
omair saleh dc4d7004a3 Merge branch 'dillon/crm-create-invoice' into 'master'
Dillon/crm create invoice

See merge request CIEFWorldwideSdnBhd/shipping-portal!148
2023-03-07 15:16:46 +00:00
17 changed files with 501 additions and 142 deletions
@@ -15,7 +15,7 @@ class DoesNotHaveTransactionType implements Filter
public static function apply(Builder $builder, $value)
{
return $builder->whereDoesntHave('transactions', function (Builder $query) use($value) {
$query->where('type', $value);
$query->where('type', $value)->whereIn('status', [0,1,2,3]);
})->whereHas('containers', function ($query){
return $query->whereDate('loading_date', '>=', Carbon::parse('20-09-2022'));
});
@@ -7,6 +7,7 @@ use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Addresses\Services\FetchesAddress;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\PerfexCRM\Processors\NewLeadTaskToPerfexCRMProcessor;
use App\Classes\Modules\Orders\Processors\CreateOrderProcessor;
use App\Classes\Modules\Orders\Services\GeneratesOrderNumber;
use App\Classes\ValueObjects\Constants\WarehouseReferences;
@@ -39,6 +40,8 @@ class CreateOrderLogic extends AbstractControllerLogic
/** @var GeneratesOrderNumber */
private $generatesOrderNumber;
/** @var NewLeadTaskToPerfexCRMProcessor */
private $newLeadTaskToPerfexCRMProcessor;
/**
* CreateOrderLogic constructor.
* @param FetchesCompany $fetchesCompany
@@ -46,22 +49,24 @@ class CreateOrderLogic extends AbstractControllerLogic
* @param CreateOrderProcessor $createOrderProcessor
* @param FetchesCompanyModule $fetchesCompanyModule
* @param GeneratesOrderNumber $generatesOrderNumber
* @param NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor
*/
public function __construct(FetchesCompany $fetchesCompany, FetchesAddress $fetchesAddress, CreateOrderProcessor $createOrderProcessor, FetchesCompanyModule $fetchesCompanyModule, GeneratesOrderNumber $generatesOrderNumber)
public function __construct(FetchesCompany $fetchesCompany, FetchesAddress $fetchesAddress, CreateOrderProcessor $createOrderProcessor, FetchesCompanyModule $fetchesCompanyModule, GeneratesOrderNumber $generatesOrderNumber, NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor)
{
$this->fetchesCompany = $fetchesCompany;
$this->fetchesAddress = $fetchesAddress;
$this->createOrderProcessor = $createOrderProcessor;
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->generatesOrderNumber = $generatesOrderNumber;
$this->newLeadTaskToPerfexCRMProcessor = $newLeadTaskToPerfexCRMProcessor;
}
public function logic(Request $request) : JsonResponse {
$company = $this->fetchesCompany->execute(['id' => $request->input('company_id')]);
$address = $this->fetchesAddress->execute(['id' => $request->input('address_id')]);
$originWarehouse = $this->fetchesCompanyModule->execute(['id' => $request->input('warehouse_id')]);
@@ -76,6 +81,10 @@ class CreateOrderLogic extends AbstractControllerLogic
$order = $this->createOrderProcessor->execute($company, $originWarehouse, $address, $this->generatesOrderNumber->execute());
if(config('perfexcrm.is_enabled') == 'true'){
$this->newLeadTaskToPerfexCRMProcessor->execute($company);
}
return $this->resourceResponse(new OrderResource($order));
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PackingLists\Processors;
use App\Classes\General\Interfaces\Packable;
use App\Classes\Modules\PerfexCRM\Processors\PackingListToPerfexCRMProcessor;
use App\Classes\Modules\PackingLists\DataTransferObjects\PackingListObject;
use App\Classes\Modules\PackingLists\Services\CreatesPackingList;
use App\Classes\Modules\PackingLists\Standards\Rules\CanCreatePackingList;
@@ -25,16 +26,20 @@ class CreatePackingListProcessor
/** @var CreatesPackingList */
private $createsPackingList;
/** @var PackingListToPerfexCRMProcessor */
private $packingListToPerfexCRMProcessor;
/**
* CreatePackingListProcessor constructor.
* @param CanCreatePackingList $canCreatePackingList
* @param CreatesPackingList $createsPackingList
* @param PackingListToPerfexCRMProcessor $packingListToPerfexCRMProcessor
*/
public function __construct(CanCreatePackingList $canCreatePackingList, CreatesPackingList $createsPackingList)
public function __construct(CanCreatePackingList $canCreatePackingList, CreatesPackingList $createsPackingList, PackingListToPerfexCRMProcessor $packingListToPerfexCRMProcessor)
{
$this->canCreatePackingList = $canCreatePackingList;
$this->createsPackingList = $createsPackingList;
$this->packingListToPerfexCRMProcessor = $packingListToPerfexCRMProcessor;
}
/**
@@ -59,6 +64,10 @@ class CreatePackingListProcessor
$object = new PackingListObject($object->getReference().'_01', $appointee_id, $type, ApprovalStatus::PENDING_SUBMISSION);
$this->createsPackingList->execute($object, $packingList);
if(config('perfexcrm.is_enabled') == 'true'){
$this->packingListToPerfexCRMProcessor->execute($packingList);
}
return $packingList;
}
@@ -25,6 +25,9 @@ class InitialPerfexCRMObject implements DataTransferObject
/** @var string */
private $projectName;
/** @var int */
private $projectStatus;
/** @var array */
private $milestoneNames;
@@ -32,7 +35,7 @@ class InitialPerfexCRMObject implements DataTransferObject
private $taskNames;
public function __construct(string $companyName, string $companyReference, string $contactName, string $contactEmail, string $bookingMarking, string $projectName, array $milestoneNames, array $taskNames)
public function __construct(string $companyName, string $companyReference, string $contactName, string $contactEmail, string $bookingMarking, string $projectName, int $projectStatus, array $milestoneNames, array $taskNames)
{
$this->companyName = $companyName;
@@ -41,6 +44,7 @@ class InitialPerfexCRMObject implements DataTransferObject
$this->contactEmail = $contactEmail;
$this->bookingMarking = $bookingMarking;
$this->projectName = $projectName;
$this->projectStatus = $projectStatus;
$this->milestoneNames = $milestoneNames;
$this->taskNames = $taskNames;
}
@@ -93,6 +97,14 @@ class InitialPerfexCRMObject implements DataTransferObject
return $this->projectName;
}
/**
* @return string
*/
public function getProjectStatus(): int
{
return $this->projectStatus;
}
/**
* @return array
*/
@@ -13,6 +13,9 @@ class UpdatePerfexCRMObject implements DataTransferObject
/** @var string */
private $companyReference;
/** @var string */
private $contactName;
/** @var string */
private $contactEmail;
@@ -22,23 +25,28 @@ class UpdatePerfexCRMObject implements DataTransferObject
/** @var string */
private $projectName;
/** @var string */
private $milestoneName;
/** @var int */
private $projectStatus;
/** @var string */
private $taskName;
/** @var array */
private $milestoneNames;
/** @var array */
private $taskNames;
public function __construct(string $companyName, string $companyReference, string $contactEmail, string $bookingMarking, string $projectName, string $milestoneName, string $taskName)
public function __construct(string $companyName, string $companyReference, string $contactName, string $contactEmail, string $bookingMarking, string $projectName, int $projectStatus, array $milestoneNames, array $taskNames)
{
$this->companyName = $companyName;
$this->companyReference = $companyReference;
$this->contactName = $contactName;
$this->contactEmail = $contactEmail;
$this->bookingMarking = $bookingMarking;
$this->projectName = $projectName;
$this->milestoneName = $milestoneName;
$this->taskName = $taskName;
$this->projectStatus = $projectStatus;
$this->milestoneNames = $milestoneNames;
$this->taskNames = $taskNames;
}
/**
@@ -57,6 +65,14 @@ class UpdatePerfexCRMObject implements DataTransferObject
return $this->companyReference;
}
/**
* @return string
*/
public function getContactName(): string
{
return $this->contactName;
}
/**
* @return string
*/
@@ -82,19 +98,26 @@ class UpdatePerfexCRMObject implements DataTransferObject
}
/**
* @return string
* @return int
*/
public function getMilestoneName(): string
public function getProjectStatus(): int
{
return $this->milestoneName;
return $this->projectStatus;
}
/**
* @return string
* @return array
*/
public function getTaskName(): string
public function getMilestoneNames(): array
{
return $this->taskName;
return $this->milestoneNames;
}
/**
* @return array
*/
public function getTaskNames(): array
{
return $this->taskNames;
}
}
@@ -10,6 +10,8 @@ use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMProject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePaymentPerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoiceSingleItemPerfexCRMObject;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomerProject;
use App\Classes\ValueObjects\Constants\PerfexCRMProjectStatus;
use App\Models\PackingList;
use Carbon\Carbon;
@@ -28,6 +30,9 @@ class CreatePerfexCRMInvoiceProcessor
/** @var FetchesPerfexCRMProject */
private $fetchesPerfexCRMProject;
/** @var CreatesPerfexCRMCustomerProject */
private $createsPerfexCRMCustomerProject;
/**
* CreatePerfexCRMInvoiceProcessor constructor.
* @param CreatesPerfexCRMInvoice $createsPerfexCRMInvoice
@@ -35,12 +40,14 @@ class CreatePerfexCRMInvoiceProcessor
public function __construct(CreatesPerfexCRMInvoice $createsPerfexCRMInvoice,
CreatesPerfexCRMInvoicePayment $createsPerfexCRMInvoicePayment,
ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer,
FetchesPerfexCRMProject $fetchesPerfexCRMProject)
FetchesPerfexCRMProject $fetchesPerfexCRMProject,
CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject)
{
$this->createsPerfexCRMInvoice = $createsPerfexCRMInvoice;
$this->createsPerfexCRMInvoicePayment = $createsPerfexCRMInvoicePayment;
$this->convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer;
$this->fetchesPerfexCRMProject = $fetchesPerfexCRMProject;
$this->createsPerfexCRMCustomerProject = $createsPerfexCRMCustomerProject;
}
/**
@@ -97,10 +104,16 @@ class CreatePerfexCRMInvoiceProcessor
$orderReference = $transaction->owner->owner->reference;
$packingListReference = $transaction->owner->reference;
$projectName = 'IZYIM | X1 Shipping | '.$orderReference.' | '.$packingListReference;
$project = (App()->make(FetchesPerfexCRMProject::class))->execute($projectName, $clientId);
$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'];
}
}
}
}
@@ -111,8 +124,7 @@ class CreatePerfexCRMInvoiceProcessor
$quantity = $transaction_detail->quantity;
$unitPrice = $transaction_detail->price;
$subTotal = $transaction_detail->amount;
$subTotal = $subTotal + $transaction_detail->amount;
//string $description, string $longDescription, int $qty, int $rate, int $order, string $unit
$invoiceSingleItem = new InvoiceSingleItemPerfexCRMObject(
@@ -18,7 +18,7 @@ use App\Classes\Modules\PerfexCRM\DataTransferObjects\InitialPerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMMilestones;
use App\Classes\ValueObjects\Constants\PerfexCRMTasks;
use App\Classes\ValueObjects\Constants\PerfexCRMStatus;
use App\Classes\ValueObjects\Constants\PerfexCRMTaskStatus;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Request;
@@ -149,7 +149,7 @@ class InitializePerfexCRMProcessor
}
// Get existing or create project, project has to exist first before milestone can appear under it
$result = $this->createsPerfexCRMCustomerProject->execute($initialPerfexCRMObject->getProjectName(), $crmClientId);
$result = $this->createsPerfexCRMCustomerProject->execute($initialPerfexCRMObject->getProjectName(), $initialPerfexCRMObject->getProjectStatus(), $crmClientId);
if(isset($result->payload)){ //Here means project creation successful
$projectId = $result->payload['project_id'];
}
@@ -157,8 +157,8 @@ class InitializePerfexCRMProcessor
$projectId = $this->fetchesPerfexCRMProject->execute($initialPerfexCRMObject->getProjectName(), $crmClientId)->id;
}
if(!is_null($result)){
$tasks = $initialPerfexCRMObject->getTaskNames();
$tasks = $initialPerfexCRMObject->getTaskNames();
if(count($tasks) > 0){
//Create tasks with milestone
for($count=0; $count < count($tasks); $count++) {
@@ -177,13 +177,16 @@ class InitializePerfexCRMProcessor
}
}
$taskStatus = PerfexCRMStatus::NOT_STARTED;
$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;
@@ -3,28 +3,33 @@
namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateTaskPerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMStatus;
use App\Classes\Jobs\CreatePerfexCRMSingleTask;
use App\Classes\ValueObjects\Constants\PerfexCRMTasks;
use App\Models\Company;
class NewLeadTaskToPerfexCRMProcessor
{
/**
* @param None
* @param Company $company
* @return true
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute()
public function execute(Company $company)
{
$companyModule = $company->companyModules()->first();
$employee = $companyModule->employees()->first();
$contactEmail = $employee->email;
$createTaskPerfexCRMObject = new CreateTaskPerfexCRMObject(
"dillontest1@gmail.com",
"test is the name of the task",
"this is the description of the task",
$contactEmail,
PerfexCRMTasks::TASK_IDENTIFICATION_1['name'],
PerfexCRMTasks::TASK_IDENTIFICATION_1['description'],
"",
"",
"",
"",
"",
PerfexCRMStatus::NOT_STARTED
PerfexCRMTasks::TASK_IDENTIFICATION_1['status']
);
CreatePerfexCRMSingleTask::dispatch($createTaskPerfexCRMObject);
@@ -0,0 +1,51 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMTasks;
use App\Classes\Jobs\UpdatePerfexCRM;
use App\Models\PackingList;
use App\Classes\ValueObjects\Constants\PerfexCRMProjectStatus;
class PackingListToPerfexCRMProcessor
{
/**
* @param PackingList $packingList
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(PackingList $packingList)
{
$order = $packingList->owner;
$companyModule = $order->companyModule()->first();
$connection = $companyModule->inviters()->withPivot('invitee_reference')->first();
$companyName = $companyModule->name;
$companyReference = $connection ? $connection->pivot->invitee_reference:'';
$employee = $companyModule->employees()->first();
$contactEmail = $employee->email;
$contactName = $employee->name;
$orderReference = $packingList->owner->reference;
$packingListReference = $packingList->reference;
$projectName = 'IZYIM | X1 Shipping | '.$orderReference.' | '.$packingListReference;
$updatePerfexCRMObject = new UpdatePerfexCRMObject(
$companyName,
$companyReference,
$contactName,
$contactEmail,
"",
$projectName,
PerfexCRMProjectStatus::NOT_STARTED,
[],
[
PerfexCRMTasks::TASK_LOADED_CONTAINER_1,
PerfexCRMTasks::TASK_LOADED_CONTAINER_2,
]
);
UpdatePerfexCRM::dispatch($updatePerfexCRMObject);
return true;
}
}
@@ -7,13 +7,12 @@ use App\Classes\Modules\PerfexCRM\Processors\InitializePerfexCRMProcessor;
use App\Classes\Modules\PerfexCRM\Services\Init;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InitialPerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMInvoiceObject;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\ValueObjects\Constants\PerfexCRMMilestones;
use App\Classes\ValueObjects\Constants\PerfexCRMTasks;
use App\Classes\ValueObjects\Constants\PerfexCRMProjectStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\Jobs\InitializePerfexCRM;
use App\Classes\Jobs\UpdatePerfexCRMInvoice;
use App\Classes\Jobs\UpdatePerfexCRM;
use App\Models\Transaction;
@@ -51,28 +50,30 @@ class TransactionToPerfexCRMProcessor
*/
public function execute(Transaction $model, int $status)
{
if($model->owner instanceof \App\Models\Transaction && $status == ApprovalStatus::APPROVED){
//dd(json_encode($packingList->owner()->first()->companyModule()->first()->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference));
//dd(json_encode($model->owner->owner->owner()->first()->companyModule()->first()->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference));
$companyModule = $model->owner->owner->owner()->first()->companyModule()->first();
if($model->owner instanceof \App\Models\Transaction && $status == ApprovalStatus::APPROVED)
{
$packingList = $model->owner->owner;
$order = $packingList->owner()->first();
$companyModule = $order->companyModule()->first();
$companyName = $companyModule->name;
$companyReference = $companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
$employee = $companyModule->employees()->first();
$contactEmail = $employee->email;
$contactName = $employee->name;
$orderReference = $model->owner->owner->owner()->first()->reference;
$packingListReference = $model->owner->owner->reference;
$orderReference = $order->reference;
$packingListReference = $packingList->reference;
$projectName = 'IZYIM | X1 Shipping | '.$orderReference.' | '.$packingListReference;
$bookingMarking = $model->owner->owner->id."-".$model->owner->owner->owner->id;
$initialPerfexCRMObject = new InitialPerfexCRMObject(
$bookingMarking = $packingList->id."-".$packingList->owner->id;
$updatePerfexCRMObject = new UpdatePerfexCRMObject(
$companyName,
$companyReference,
$contactName,
$contactEmail,
$bookingMarking,
$projectName,
PerfexCRMProjectStatus::IN_PROGRESS,
[],
[
PerfexCRMTasks::TASK_1,
@@ -83,8 +84,7 @@ class TransactionToPerfexCRMProcessor
]
);
//$this->initializePerfexCRMProcessor->execute($initialPerfexCRMObject);
InitializePerfexCRM::dispatch($initialPerfexCRMObject);
UpdatePerfexCRM::dispatch($updatePerfexCRMObject);
$updatePerfexCRMInvoiceOject = new UpdatePerfexCRMInvoiceObject(
$contactEmail,
@@ -11,11 +11,13 @@ use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMMilestone;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMTask;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomerContact;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMTask;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMProject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CustomerContactObject;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMStatus;
use App\Classes\ValueObjects\Constants\PerfexCRMTaskStatus;
use App\Classes\ValueObjects\Constants\PerfexCRMProjectStatus;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Request;
@@ -49,11 +51,16 @@ class UpdatePerfexCRMProcessor
/** @var CreatesPerfexCRMCustomerContact */
private $createsPerfexCRMCustomerContact;
/** @var UpdatesPerfexCRMTask */
private $updatesPerfexCRMTask;
/** @var UpdatesPerfexCRM */
private $updatePerfexCRM;
/** @var UpdatesPerfexCRMCustomer */
private $updatesPerfexCRMCustomer;
/**
/** @var UpdatesPerfexCRMProject */
private $updatesPerfexCRMProject;
/**
* @param ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer
* @param CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject
* @param CreatesPerfexCRMMilestone $createsPerfexCRMMilestone
@@ -63,18 +70,20 @@ class UpdatePerfexCRMProcessor
* @param FetchesPerfexCRMTask $fetchesPerfexCRMTask
* @param CreatesPerfexCRMCustomer $createsPerfexCRMCustomer
* @param CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact
* @param UpdatesPerfexCRMTask $updatesPerfexCRMTask
* @param UpdatesPerfexCRMCustomer $updatesPerfexCRMCustomer
* @param UpdatesPerfexCRMProject $updatesPerfexCRMProject
*/
public function __construct(ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer,
CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject,
CreatesPerfexCRMMilestone $createsPerfexCRMMilestone,
CreatesPerfexCRMTask $createsPerfexCRMTask,
FetchesPerfexCRMProject $fetchesPerfexCRMProject,
FetchesPerfexCRMMilestone $fetchesPerfexCRMMilestone,
FetchesPerfexCRMTask $fetchesPerfexCRMTask,
CreatesPerfexCRMCustomer $createsPerfexCRMCustomer,
CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact,
UpdatesPerfexCRMTask $updatesPerfexCRMTask)
CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject,
CreatesPerfexCRMMilestone $createsPerfexCRMMilestone,
CreatesPerfexCRMTask $createsPerfexCRMTask,
FetchesPerfexCRMProject $fetchesPerfexCRMProject,
FetchesPerfexCRMMilestone $fetchesPerfexCRMMilestone,
FetchesPerfexCRMTask $fetchesPerfexCRMTask,
CreatesPerfexCRMCustomer $createsPerfexCRMCustomer,
CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact,
UpdatesPerfexCRMCustomer $updatesPerfexCRMCustomer,
UpdatesPerfexCRMProject $updatesPerfexCRMProject)
{
$this->convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer;
$this->createsPerfexCRMCustomerProject = $createsPerfexCRMCustomerProject;
@@ -85,55 +94,113 @@ class UpdatePerfexCRMProcessor
$this->fetchesPerfexCRMTask = $fetchesPerfexCRMTask;
$this->createsPerfexCRMCustomer = $createsPerfexCRMCustomer;
$this->createsPerfexCRMCustomerContact = $createsPerfexCRMCustomerContact;
$this->updatesPerfexCRMTask = $updatesPerfexCRMTask;
}
$this->updatesPerfexCRMCustomer = $updatesPerfexCRMCustomer;
$this->updatesPerfexCRMProject = $updatesPerfexCRMProject;
}
/**
* @param PerfexCRMObject $perfexCRMObject
* @param UpdatePerfexCRMObject $updatePerfexCRMObject
* @return null|object
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(UpdatePerfexCRMObject $updatePerfexCRMObject) {
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
$result = $this->convertsPerfexCRMLeadToCustomer->execute($updatePerfexCRMObject->getContactEmail());
if(isset($result->payload)){
$crmClientId = $result->payload['client_id'];
// 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
}
}
}
// Get existing or create project, project has to exist first before milestone can appear under it
$result = $this->createsPerfexCRMCustomerProject->execute($updatePerfexCRMObject->getProjectName(), $crmClientId);
if(isset($result->payload)){
$projectId = $result->payload['project_id'];
}
else{
$projectId = $this->fetchesPerfexCRMProject->execute($updatePerfexCRMObject->getProjectName(), $crmClientId)->id;
}
// Get existing or create milestone, milestone has to exist first before task can appear under it
$result = $this->createsPerfexCRMMilestone->execute($updatePerfexCRMObject->getMilestoneName(), $projectId);
if(isset($result->payload)){
$milestoneId = $result->payload['milestone_id'];
}
else{
$milestone = $this->fetchesPerfexCRMMilestone->execute($updatePerfexCRMObject->getMilestoneName(), $projectId);
$array = json_decode(json_encode($milestone), true);
$milestoneId = $array[0]['id'];
}
// Get existing or create task
$result = $this->createsPerfexCRMTask->execute($updatePerfexCRMObject->getTaskName(), $milestoneId, $projectId);
if(isset($result->payload)){
$taskId = $result->payload['task_id'];
}
else{
$taskId = $this->fetchesPerfexCRMTask->execute($updatePerfexCRMObject->getTaskName(), $milestoneId)->id;
}
$this->updatesPerfexCRMTask->execute($taskId, $updatePerfexCRMObject->getTaskName(), $milestoneId, $projectId, PerfexCRMStatus::COMPLETED);
return null;
}
return true;
}
}
@@ -14,7 +14,7 @@ class CreatesPerfexCRMCustomerProject
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $projectName, string $clientId) {
public function execute(string $projectName, int $status, string $clientId) {
try{
$data = [
'name' => $projectName,
@@ -22,7 +22,7 @@ class CreatesPerfexCRMCustomerProject
'billing_type' => 1,
'clientid' => $clientId,
'start_date' => date('Y-m-d'),
'status' => 1
'status' => $status
];
$response = Http::asForm()->withHeaders([
@@ -0,0 +1,43 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class UpdatesPerfexCRMProject
{
/**
* @param $project
* @param int $status
* @return null|object
* @throws MalformedRequestException
*/
public function execute($project, int $status) {
try{
$data = [
'name' => $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());
}
}
}
@@ -0,0 +1,16 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class PerfexCRMProjectStatus {
public const NOT_STARTED = 1;
public const IN_PROGRESS = 2;
public const ON_HOLD = 3;
public const FINISHED = 4;
public const CANCELLED = 5;
}
@@ -2,7 +2,7 @@
namespace App\Classes\ValueObjects\Constants;
final class PerfexCRMStatus {
final class PerfexCRMTaskStatus {
public const NOT_STARTED = 1;
@@ -11,7 +11,7 @@ final class PerfexCRMStatus {
public const TESTING = 3;
public const IN_PROGRESS = 4;
public const COMPLETED = 5;
}
@@ -4,13 +4,16 @@ namespace App\Classes\ValueObjects\Constants;
class PerfexCRMTasks
{
//IMPORTANT NOTE: TASK NAME MUST BE UNIQUE ACCORDING TO REL_TYPE
//e.g. rel_type: lead, project
public const TASK_1 = [
'name' => 'Customer Paid',
'description' => '',
'milestone' => 'MILESTONE 1 - Customer Paid',
'reference' => '',
'on_task_completion' => '',
'status' => PerfexCRMStatus::COMPLETED
'status' => PerfexCRMTaskStatus::COMPLETED
];
public const TASK_POST_PAYMENT_1 = [
@@ -26,7 +29,7 @@ class PerfexCRMTasks
'milestone' => '',
'reference' => 'TASK_POST_PAYMENT_1',
'on_task_completion' => 'TASK_POST_PAYMENT_2',
'status' => PerfexCRMStatus::IN_PROGRESS
'status' => PerfexCRMTaskStatus::IN_PROGRESS
];
public const TASK_POST_PAYMENT_2 = [
'name' => 'Approve Payment',
@@ -73,4 +76,48 @@ class PerfexCRMTasks
'on_task_completion' => '',
'status' => ''
];
public const TASK_LOADED_CONTAINER_1 = [
'name' => 'Generate Shipping Invoices',
'description' => '○ Purpose: -<br>
○ Initial Status: In Progress<br>
○ Deadline: Next day<br>
○ Responsible department: Operation<br>
○ Assignee: -<br>
○ Next step: Approve Shipping Invoice change to in progress.<br>',
'milestone' => '',
'reference' => 'TASK_LOADED_CONTAINER_1',
'on_task_completion' => 'TASK_LOADED_CONTAINER_2',
'status' => PerfexCRMTaskStatus::IN_PROGRESS
];
public const TASK_LOADED_CONTAINER_2 = [
'name' => 'Approve Shipping Invoices',
'description' => '○ Purpose: -<br>
○ Initial Status: Not Starteds<br>
○ Deadline: Next day<br>
○ Responsible department: Customer Services<br>
○ Next step: -<br>',
'milestone' => '',
'reference' => 'TASK_LOADED_CONTAINER_2',
'on_task_completion' => '',
'status' => ''
];
public const TASK_IDENTIFICATION_1 = [
'name' => 'Approve Identification Verification (Shipping)',
'description' => '○ Purpose: To ensure the customer submit information matches the information in their identification document.<br>
○ Initial Status: In Progress<br>
○ Deadline: Same Day<br>
○ Responsible department: Operation<br>
○ Next step: None<br>
○ Additional details: ** Any specific requirements or notes for the operation.**<br>
○ Dependencies: None<br>
○ Outcomes: Customer account identification is verified<br>',
'milestone' => '',
'reference' => 'TASK_IDENTIFICATION_1',
'on_task_completion' => '',
'status' => PerfexCRMTaskStatus::IN_PROGRESS
];
}
+93 -31
View File
@@ -802,40 +802,31 @@ Route::get('/invoices/approve', function(Request $request){
Route::get('/invoices/show-duplicated', function(Request $request){
$transactionWithMultipleInvoice = DB::table('transactions')
->where('type', TransactionType::SHIPPING_INVOICE)
->where('status', '!=' , ApprovalStatus::COMPLETED)
->where('status', '!=' , ApprovalStatus::EXPIRED)
->where('deleted_at', null)
->select('owner_id', DB::raw('count(*) as count'))
->groupBy('owner_id')
->having('count', '>', 1)
->get();
// delete invoice type suspended
echo '<table>';
echo "<tr>";
echo "<td style='border:1px solid'>owner_id</td>";
echo "<td style='border:1px solid'>count</td>";
echo "</tr>";
echo 'Total Duplicates: ' . count($transactionWithMultipleInvoice) . '<br>';
$duplicatedOrderId = [];
$duplicatedOrderArray = [];
foreach($transactionWithMultipleInvoice as $invoice) {
$duplicatedOrderId[] = $invoice->owner_id;
echo "<tr>";
echo "<td style='border:1px solid'>$invoice->owner_id</td>";
echo "<td style='border:1px solid'>$invoice->count</td>";
echo "</tr>";
$duplicatedOrderArray[$invoice->owner_id] = $invoice->count;
}
echo '</table>';
$duplicatedInvoice = Transaction::whereIn('owner_id', $duplicatedOrderId)->orderByDesc('owner_id')->get();
// dd($duplicatedInvoice);
echo '<br>';
echo '<table>';
echo "<tr>";
echo "<td style='border:1px solid'>Order Reference</td>";
echo "<td style='border:1px solid'>Status</td>";
echo "<td style='border:1px solid'>Invoice Owner ID</td>";
echo "<td style='border:1px solid'>Invoice Owner ID</td>";
echo "<td style='border:1px solid'>Amount</td>";
echo "<td style='border:1px solid'>Count</td>";
echo "</tr>";
foreach($duplicatedInvoice as $invoice) {
@@ -845,17 +836,16 @@ Route::get('/invoices/show-duplicated', function(Request $request){
echo "<td style='border:1px solid'>".ApprovalStatus::APPROVAL_STATUS_ID[$invoice->status]."</td>";
echo "<td style='border:1px solid'>$invoice->owner_id</td>";
echo "<td style='border:1px solid'>$invoice->amount</td>";
echo "<td style='border:1px solid'>".$duplicatedOrderArray[$invoice->owner_id]."</td>";
echo "</tr>";
}
echo '</table>';
});
Route::get('/invoices/delete-duplicated', function(Request $request){
$duplicatedInvoices = DB::table('transactions')
->where('type', TransactionType::SHIPPING_INVOICE)
->where('status', '!=' , ApprovalStatus::COMPLETED)
->where('status', '!=' , ApprovalStatus::EXPIRED)
->where('deleted_at', null)
->select('owner_id', DB::raw('count(*) as count'))
->groupBy('owner_id')
@@ -870,26 +860,98 @@ Route::get('/invoices/delete-duplicated', function(Request $request){
$paidInvoice = $packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('status', ApprovalStatus::COMPLETED)->get();
$unpaidInvoices = $packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->orderBy('id', 'desc')->get();
// if have completed invoice (verified payment)
if (count($paidInvoice)) {
$packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('status', '!=', ApprovalStatus::COMPLETED)->delete();
continue;
} else {
dump($order->reference . ' -no');
}
// delete duplicated invoices
$unpaidInvoicesIds = $unpaidInvoices->pluck('id')->toArray();
array_shift($unpaidInvoicesIds);
Transaction::whereIn('id', $unpaidInvoicesIds)->delete();
// if have unverified payment
// $paymentHistory = $packingList->transactions()->whereHas('transactions', function($query){
// return $query->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION ,ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]);
// })->get();
// if (count($paymentHistory)) {
// $packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('id', '!=', $paymentHistory->first()->id)->delete();
// continue;
// }
// delete expired invoices
$packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('status', '!=', ApprovalStatus::EXPIRED)->delete();
// // delete duplicated invoices
// $unpaidInvoices = $packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->orderBy('id', 'desc')->get();
// delete suspended invoices
$suspendedInvoices = $packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('status', '!=', ApprovalStatus::SUSPENDED)->orderBy('id', 'desc')->get();
$suspendedInvoicesIds = $suspendedInvoices->pluck('id')->toArray();
array_shift($suspendedInvoicesIds);
Transaction::whereIn('id', $suspendedInvoicesIds)->delete();
// $unpaidInvoicesIds = $unpaidInvoices->pluck('id')->toArray();
// array_shift($unpaidInvoicesIds);
// Transaction::whereIn('id', $unpaidInvoicesIds)->delete();
// // delete expired invoices
// $packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('status', '!=', ApprovalStatus::EXPIRED)->delete();
// // delete suspended invoices
// $suspendedInvoices = $packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('status', '!=', ApprovalStatus::SUSPENDED)->orderBy('id', 'desc')->get();
// $suspendedInvoicesIds = $suspendedInvoices->pluck('id')->toArray();
// array_shift($suspendedInvoicesIds);
// Transaction::whereIn('id', $suspendedInvoicesIds)->delete();
}
});
Route::get('/packing-lists/show-duplicated', function(Request $request){
$results = PackingList::select('reference', 'type', DB::raw('count(*) as total'))
->groupBy('reference', 'type')
->having('total', '>', 1)
->get()
->toArray();
echo '<table>';
echo "<tr>";
echo "<td style='border:1px solid'>reference</td>";
echo "<td style='border:1px solid'>type</td>";
echo "<td style='border:1px solid'>count</td>";
echo "</tr>";
foreach($results as $result) {
// dd($result);
echo "<tr>";
echo "<td style='border:1px solid'>" . $result['reference'] . "</td>";
echo "<td style='border:1px solid'>" . $result['type'] . "</td>";
echo "<td style='border:1px solid'>" . $result['total'] . "</td>";
echo "</tr>";
}
echo '</table>';
});
Route::get('/packing-lists/delete-duplicated', function(Request $request){
$results = PackingList::select('reference', 'type', DB::raw('count(*) as total'))
->groupBy('reference', 'type')
->having('total', '>', 1)
->get()
->toArray();
foreach($results as $result) {
$duplicatedPackingList = PackingList::where('reference', $result['reference'])->where('type', $result['type'])->orderBy('id', 'desc')->get();
// if packinglist has paid inivoice
$paidPackinglist = PackingList::where('reference', $result['reference'])->where('type', $result['type'])->whereHas('transactions', function($query){
return $query->where('type', TransactionType::SHIPPING_INVOICE)->where('status', ApprovalStatus::COMPLETED);
})->get();
if (count($paidPackinglist)) {
// delete all the other packing list
$paidPackinglistID = $paidPackinglist->first()->id;
$duplicatedPackingList = PackingList::where('reference', $result['reference'])->where('type', $result['type'])->where('id', '!=', $paidPackinglistID)->get();
// $duplicatedPackingList->delete();
foreach ($duplicatedPackingList as $p) {
$p->delete();
dump('have paid packinglist, deleting id:' . $p->id);
}
} else {
// delete all but left the latest packing list
$firstItem = $duplicatedPackingList->shift();
// dump('dont have paid packinglist, keep first and delete others');
foreach ($duplicatedPackingList as $p) {
$p->delete();
dump('dont have paid packinglist, keep latest id:' . $firstItem->id . ', and deleting id:' . $p->id);
}
}
}
});