Merge branch 'dillon/crm-gen-invoice-update' into dillon/debug-and-fixes-1-22

This commit is contained in:
Dillon
2023-03-19 22:24:07 +08:00
7 changed files with 282 additions and 76 deletions
+103
View File
@@ -0,0 +1,103 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMInvoiceProcessor;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMInvoicePayment;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMInvoice;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMProject;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMInvoice;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMInvoiceObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePaymentPerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMInvoiceStatus;
use App\Models\Transaction;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
class UpdatePerfexCRMInvoice implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var UpdatePerfexCRMInvoiceObject */
private $updatePerfexCRMInvoiceObject;
/**
* CreatePerfexCRMSingleTask constructor.
* @param UpdatePerfexCRMInvoiceObject $createTaskPerfexCRMObject
*/
public function __construct(UpdatePerfexCRMInvoiceObject $updatePerfexCRMInvoiceObject)
{
$this->updatePerfexCRMInvoiceObject = $updatePerfexCRMInvoiceObject;
}
public function handle()
{
//get the client id
$customer = (App()->make(FetchesPerfexCRMCustomer::class))->execute($this->updatePerfexCRMInvoiceObject->getEmail());
$transaction = $this->updatePerfexCRMInvoiceObject->getTransaction();
//get the invoice id
$invoiceId = 0;
$invoiceStatus = 0;
$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;
$invoice = (App()->make(FetchesPerfexCRMInvoice::class))->execute($customer->userid,"INV-", $number);
if(is_null($invoice)){
$result = (App()->make(CreatePerfexCRMInvoiceProcessor::class))->execute($transaction, null, null, $this->updatePerfexCRMInvoiceObject->getIsPaid());
$invoiceId = $result->payload['id'];
}
else{
$invoiceId = $invoice->id;
$invoiceStatus = $invoice->status;
//This only run when invoice already exist and the invoice does not have a PAID status
if($invoiceStatus != PerfexCRMInvoiceStatus::PAID){
//get project
$projectId = "";
$project = (App()->make(FetchesPerfexCRMProject::class))->execute($this->updatePerfexCRMInvoiceObject->getProjectName(), $customer->userid);
if(!is_null($project)){
$projectId = $project->id;
}
if($projectId == ""){
Log::error(json_encode('UpdatePerfexCRMInvoice debug: '.$this->updatePerfexCRMInvoiceObject->getProjectName()));
Log::error(json_encode($transaction->owner));
}
//update invoice
(App()->make(UpdatesPerfexCRMInvoice::class))->execute($invoice, $projectId);
}
}
//create invoice payment
if($invoiceId != 0 && $invoiceStatus != PerfexCRMInvoiceStatus::PAID){
$date = Carbon::parse($transaction->created_at)->format('Y-m-d');
$invoicePaymentPerfexCRMObject = new InvoicePaymentPerfexCRMObject(
$invoiceId,
"$transaction->amount",
$date,
1,
"",
""
);
(App()->make(CreatesPerfexCRMInvoicePayment::class))->execute($invoicePaymentPerfexCRMObject);
}
}
}
@@ -0,0 +1,62 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
use App\Models\Transaction;
class UpdatePerfexCRMInvoiceObject implements DataTransferObject
{
/** @var string */
private $email;
/** @var Transaction */
private $transaction;
/** @var bool */
private $isPaid;
/** @var string */
private $projectName;
public function __construct(string $email, Transaction $transaction, bool $isPaid, string $projectName)
{
$this->email = $email;
$this->transaction = $transaction;
$this->isPaid = $isPaid;
$this->projectName = $projectName;
}
/**
* @return string
*/
public function getEmail(): string
{
return $this->email;
}
/**
* @return Transaction
*/
public function getTransaction(): Transaction
{
return $this->transaction;
}
/**
* @return bool
*/
public function getIsPaid(): bool
{
return $this->isPaid;
}
/**
* @return string
*/
public function getProjectName(): string
{
return $this->projectName;
}
}
@@ -8,10 +8,12 @@ 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\Services\CreatesPerfexCRMCustomerProject;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePaymentPerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoiceSingleItemPerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMProjectStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use Carbon\Carbon;
class CreatePerfexCRMInvoiceProcessor
@@ -32,6 +34,9 @@ class CreatePerfexCRMInvoiceProcessor
/** @var CreatesPerfexCRMCustomerProject */
private $createsPerfexCRMCustomerProject;
/** @var FetchesCompany */
private $fetchesCompany;
/**
* CreatePerfexCRMInvoiceProcessor constructor.
* @param CreatesPerfexCRMInvoice $createsPerfexCRMInvoice
@@ -40,13 +45,15 @@ class CreatePerfexCRMInvoiceProcessor
CreatesPerfexCRMInvoicePayment $createsPerfexCRMInvoicePayment,
ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer,
FetchesPerfexCRMProject $fetchesPerfexCRMProject,
CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject)
CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject,
FetchesCompany $fetchesCompany)
{
$this->createsPerfexCRMInvoice = $createsPerfexCRMInvoice;
$this->createsPerfexCRMInvoicePayment = $createsPerfexCRMInvoicePayment;
$this->convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer;
$this->fetchesPerfexCRMProject = $fetchesPerfexCRMProject;
$this->createsPerfexCRMCustomerProject = $createsPerfexCRMCustomerProject;
$this->fetchesCompany = $fetchesCompany;
}
/**
@@ -57,19 +64,30 @@ class CreatePerfexCRMInvoiceProcessor
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute($transaction, $purchaseOrder, $supplier) {
$booking = $transaction->booking;
if(is_null($supplier)){
$supplier = $this->fetchesCompany->execute(['id' => $transaction->receiver]);
}
if(is_null($purchaseOrder)){
$purchaseOrder = $booking->transactions()
->where('type', TransactionType::PURCHASE_ORDER)
->complete()
->first();
}
$clientId = "";
$number = $transaction->bill_no;
$prefix = "INV-";
$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');
$number = 'EXC-'.$number;
$date = Carbon::parse($booking->created_at)->format('Y-m-d');
$dueDate = Carbon::parse($booking->created_at)->format('Y-m-d');
$currency = 1; //cief TODO: To look into Malaysia and Chinese currency
$subTotal = 0.00;
$total = 0.00;
@@ -111,47 +129,67 @@ class CreatePerfexCRMInvoiceProcessor
}
}
//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,
if(is_null($purchaseOrder)){
$extraInvoiceSingleItem = new InvoiceSingleItemPerfexCRMObject(
'Refer to booking: '.$booking->marking,
"",
$quantity,
$unitPrice,
$order,
1.00,
$transaction->amount,
1,
""
);
array_push($invoiceItems, $invoiceSingleItem);
}
if($transaction->booking()->first()->fix_currency_id !== 1){
$total = ((1/$transaction->currency_rate) * $transaction->amount) + $transaction->service_charge + $transaction->tax;
$subTotal += number_format($transaction->amount, 2,'.','') * 1;
array_push($invoiceItems, $extraInvoiceSingleItem);
}
else{
$total = $transaction->amount + $transaction->service_charge + $transaction->tax;
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($booking->first()->fix_currency_id !== 1)
$unitPrice = (1/$transaction->currency_rate) * $transaction_detail->price;
else
$unitPrice = $transaction_detail->price;
//$totalAmount = 0.00;
if($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);
}
}
//When this transaction is of TransactionType::PAYMENT, the amount is actually in the currecy user choose to pay (RM)
//So there is no need to convert it
if ($transaction->type == TransactionType::PAYMENT){
$total = $transaction->amount;
}
else{
if($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
@@ -174,25 +212,26 @@ class CreatePerfexCRMInvoiceProcessor
$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);
}
}
//cief todo: When invoices need to be regenerated, need to ensure payment do not get double created
// 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":"<p>The Invoice number is already in use<\/p>"}
return true;
return $result;
}
}
@@ -7,7 +7,8 @@ use App\Classes\ValueObjects\Constants\PerfexCRMTasks;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\PerfexCRMProjectStatus;
use App\Classes\ValueObjects\Constants\PerfexCRMTaskStatus;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMInvoiceObject;
use App\Classes\Jobs\UpdatePerfexCRMInvoice;
use App\Classes\Jobs\UpdatePerfexCRM;
use App\Models\Transaction;
@@ -93,6 +94,14 @@ class TransactionToPerfexCRMProcessor
);
UpdatePerfexCRM::dispatch($updatePerfexCRMObject);
}
$updatePerfexCRMInvoiceOject = new UpdatePerfexCRMInvoiceObject(
$contactEmail,
$model,
true,
$projectName
);
UpdatePerfexCRMInvoice::dispatch($updatePerfexCRMInvoiceOject);
}
else if($status == ApprovalStatus::PENDING_VERIFICATION){
if($model->type == TransactionType::PURCHASE_ORDER){
@@ -41,7 +41,7 @@ class UpdatesPerfexCRMInvoice
$data = [
'number' => $invoice->number,
'date' => $invoice->date,
'duedate' => $invoice->date,
'duedate' => $invoice->duedate,
'currency' => $invoice->currency,
'subtotal' => $invoice->subtotal,
'total' => $invoice->total,
@@ -194,11 +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);
// update perfex crm
// if(config('perfexcrm.is_enabled') == 'true'){
// CreatePerfexCRMInvoice::dispatch($invoice_transaction, $purchaseOrder, $supplier);
// }
}
}
@@ -5,25 +5,19 @@ 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)
public function __construct(TransactionToPerfexCRMProcessor $transactionToPerfexCRMProcessor)
{
$this->transactionToPerfexCRMProcessor = $transactionToPerfexCRMProcessor;
$this->newLeadTaskToPerfexCRMProcessor = $newLeadTaskToPerfexCRMProcessor;
}
/**
@@ -34,12 +28,11 @@ class UpdatesTransactionStatus extends AbstractUpdateRecord
*/
public function execute(Transaction $model, int $status)
{
$model->status = $status;
$result = $this->handler($model);
if(config('perfexcrm.is_enabled') == 'true'){
$this->transactionToPerfexCRMProcessor->execute($model, $status);
// $this->newLeadTaskToPerfexCRMProcessor->execute();
}
$model->status = $status;
return $this->handler($model);
return $result;
}
}