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/Modules/PerfexCRM/DataTransferObjects/InvoicePerfexCRMObject.php b/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoicePerfexCRMObject.php index 7e204ff8..f1f21f11 100644 --- a/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoicePerfexCRMObject.php +++ b/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoicePerfexCRMObject.php @@ -7,7 +7,7 @@ use App\Classes\General\Interfaces\DataTransferObject; class InvoicePerfexCRMObject implements DataTransferObject { - /** @var int */ + /** @var string */ private $clientId; /** @var string */ @@ -56,9 +56,9 @@ class InvoicePerfexCRMObject implements DataTransferObject } /** - * @return int + * @return string */ - public function getClientId(): int + public function getClientId(): string { return $this->clientId; } diff --git a/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoiceSingleItemPerfexCRMObject.php b/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoiceSingleItemPerfexCRMObject.php index 4f92895d..7b9428db 100644 --- a/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoiceSingleItemPerfexCRMObject.php +++ b/app/Classes/Modules/PerfexCRM/DataTransferObjects/InvoiceSingleItemPerfexCRMObject.php @@ -14,7 +14,7 @@ class InvoiceSingleItemPerfexCRMObject implements DataTransferObject /** @var string */ public $longDescription; - /** @var int */ + /** @var float */ public $qty; /** @var float */ @@ -26,7 +26,7 @@ class InvoiceSingleItemPerfexCRMObject implements DataTransferObject /** @var string */ public $unit; - public function __construct(string $description, string $longDescription, int $qty, float $rate, int $order, string $unit) + public function __construct(string $description, string $longDescription, float $qty, float $rate, int $order, string $unit) { $this->description = $description; $this->longDescription = $longDescription; @@ -53,9 +53,9 @@ class InvoiceSingleItemPerfexCRMObject implements DataTransferObject } /** - * @return int + * @return float */ - public function getQty(): int + public function getQty(): float { return $this->qty; } diff --git a/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php index 7a893bde..2086276d 100644 --- a/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php +++ b/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php @@ -6,6 +6,7 @@ namespace App\Classes\Modules\PerfexCRM\Processors; use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMInvoice; use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMInvoicePayment; use App\Classes\Modules\PerfexCRM\Services\ConvertsPerfexCRMLeadToCustomer; +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; @@ -23,17 +24,22 @@ class CreatePerfexCRMInvoiceProcessor /** @var ConvertsPerfexCRMLeadToCustomer */ private $convertsPerfexCRMLeadToCustomer; + /** @var FetchesPerfexCRMProject */ + private $fetchesPerfexCRMProject; + /** * CreatePerfexCRMInvoiceProcessor constructor. * @param CreatesPerfexCRMInvoice $createsPerfexCRMInvoice */ public function __construct(CreatesPerfexCRMInvoice $createsPerfexCRMInvoice, CreatesPerfexCRMInvoicePayment $createsPerfexCRMInvoicePayment, - ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer) + ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer, + FetchesPerfexCRMProject $fetchesPerfexCRMProject) { $this->createsPerfexCRMInvoice = $createsPerfexCRMInvoice; $this->createsPerfexCRMInvoicePayment = $createsPerfexCRMInvoicePayment; $this->convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer; + $this->fetchesPerfexCRMProject = $fetchesPerfexCRMProject; } /** @@ -44,12 +50,16 @@ class CreatePerfexCRMInvoiceProcessor * @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'); @@ -67,17 +77,27 @@ class CreatePerfexCRMInvoiceProcessor $billingStreet = $billingStreet.$addresses->state()->first()->name.','; $billingStreet = $billingStreet.$addresses->country()->first()->name; - $projectId = ""; + $allowedPaymentModes = []; $invoiceItems = []; $email = $supplier->employees()->first()->email; - $email = 'dillon37@yahoo.com'; //cief TODO: To be updated to user actual email address + $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; + } + //newitems foreach ($purchaseOrder->transactionDetails as $key => $transaction_detail){ $order = $key + 1; @@ -94,12 +114,12 @@ class CreatePerfexCRMInvoiceProcessor if($transaction->booking()->first()->fix_currency_id !== 1){ //$totalAmount = (float)number_format( (1/$transaction->currency_rate) * $transaction_detail->price, 2,'.','')*$transaction_detail->quantity; - $subTotal += (1/$transaction->currency_rate) * $transaction_detail->price * $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 += $transaction_detail->price * $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 @@ -121,7 +141,8 @@ class CreatePerfexCRMInvoiceProcessor $total = $transaction->amount + $transaction->service_charge + $transaction->tax; } - //cief TODO: To be updated, temporarily hardcoded allow payment modes + //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( @@ -140,18 +161,23 @@ class CreatePerfexCRMInvoiceProcessor $result = $this->createsPerfexCRMInvoice->execute($invoicePerfexCRMObject); - //If there is a checking whether an payment to an invoice need to be generated, do it here - if(true && $result->payload['id']){ - $invoicePaymentPerfexCRMObject = new InvoicePaymentPerfexCRMObject( - $result->payload['id'], - $total, - $date, - 1, - "", - "" - ); - $this->createsPerfexCRMInvoicePayment->execute($invoicePaymentPerfexCRMObject); + 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/Services/CreatesPerfexCRMInvoice.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php index 196e3130..b595a86f 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php @@ -22,8 +22,8 @@ class CreatesPerfexCRMInvoice 'date' => $invoicePerfexCRMObject->getDate(), 'duedate' => $invoicePerfexCRMObject->getDueDate(), 'currency' => $invoicePerfexCRMObject->getCurrency(), - 'subtotal' => $invoicePerfexCRMObject->getSubTotal(), - 'total' => $invoicePerfexCRMObject->getTotal(), + '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, diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php index 035cc1b8..f3e92529 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php @@ -18,7 +18,7 @@ class CreatesPerfexCRMInvoicePayment try{ $data = [ 'invoiceid' => $invoicePaymentPerfexCRMObject->getInvoiceId(), - 'amount' => $invoicePaymentPerfexCRMObject->getAmount(), + 'amount' => number_format($invoicePaymentPerfexCRMObject->getAmount(), 2, '.', ''), 'date' => $invoicePaymentPerfexCRMObject->getDate(), 'paymentmode' => $invoicePaymentPerfexCRMObject->getPaymentMode(), 'transactionid' => $invoicePaymentPerfexCRMObject->getTransactionId(), 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/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/Transactions/Processors/CreateInvoiceTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php index a983a332..d48d4d5b 100644 --- a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php @@ -14,11 +14,11 @@ use App\Classes\Modules\Bookings\Services\CalculatesBookingCurrencyAverageRate; use App\Classes\Modules\Companies\Services\FetchesCompany; use App\Classes\Modules\Bookings\Services\UpdatesBookingStatus; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; -use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMInvoiceProcessor; 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; @@ -52,8 +52,6 @@ class CreateInvoiceTransactionProcessor /** @var CreateInvoiceDocumentProcessor */ private $invoiceDocumentProcessor; - /** @var CreatePerfexCRMInvoiceProcessor */ - private $createPerfexCRMInvoiceProcessor; /** * CreateInvoiceTransactionProcessor constructor. @@ -68,9 +66,8 @@ class CreateInvoiceTransactionProcessor * @param FetchesCompany $fetchesCompany * @param UpdatesBookingStatus $updatesBookingStatus * @param CreateInvoiceDocumentProcessor $invoiceDocumentProcessor - * @param CreatePerfexCRMInvoiceProcessor $createPerfexCRMInvoiceProcessor */ - public function __construct(ListsTransactions $listsTransactions, CreatesTransaction $createsTransaction, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CalculatesBookingPaidAmount $calculatesBookingPaidAmount, CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingTransferredAmount $calculatesBookingTransferredAmount, FetchesServiceConfigurations $fetchesServiceConfigurations, CalculatesBookingCurrencyAverageRate $calculatesBookingCurrencyAverageRate, FetchesCompany $fetchesCompany, UpdatesBookingStatus $updatesBookingStatus, CreateInvoiceDocumentProcessor $invoiceDocumentProcessor, CreatePerfexCRMInvoiceProcessor $createPerfexCRMInvoiceProcessor) + public function __construct(ListsTransactions $listsTransactions, CreatesTransaction $createsTransaction, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CalculatesBookingPaidAmount $calculatesBookingPaidAmount, CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingTransferredAmount $calculatesBookingTransferredAmount, FetchesServiceConfigurations $fetchesServiceConfigurations, CalculatesBookingCurrencyAverageRate $calculatesBookingCurrencyAverageRate, FetchesCompany $fetchesCompany, UpdatesBookingStatus $updatesBookingStatus, CreateInvoiceDocumentProcessor $invoiceDocumentProcessor) { $this->createsTransaction = $createsTransaction; $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; @@ -81,7 +78,6 @@ class CreateInvoiceTransactionProcessor $this->fetchesCompany = $fetchesCompany; $this->updatesBookingStatus = $updatesBookingStatus; $this->invoiceDocumentProcessor = $invoiceDocumentProcessor; - $this->createPerfexCRMInvoiceProcessor = $createPerfexCRMInvoiceProcessor; } @@ -199,10 +195,9 @@ class CreateInvoiceTransactionProcessor $this->invoiceDocumentProcessor->execute($supplier_deliver_order_transaction, $purchaseOrder, $supplier, DocumentType::SUPPLIER_DELIVER_ORDER); // update perfex crm - // if(config('perfexcrm.is_enabled') == 'true'){ - // { - // $this->createPerfexCRMInvoiceProcessor->execute($invoice_transaction, $purchaseOrder, $supplier); - // } + if(config('perfexcrm.is_enabled') == 'true'){ + CreatePerfexCRMInvoice::dispatch($invoice_transaction, $purchaseOrder, $supplier); + } $this->updatesBookingStatus->execute($booking, ApprovalStatus::COMPLETED); } 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 @@ +