Files
shipping-portal/app/Classes/Modules/Transactions/ControllersLogic/CreateGroupsLogic.php
T

290 lines
12 KiB
PHP

<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Jobs\Commands\V2\ReleaseGoodsToCustomerV2CommandJob;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\Groups\DataTransferObjects\GroupObject;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\Modules\Transactions\Processors\CreatePaymentTransactionProcessor;
use App\Models\Group;
use App\Classes\Modules\Groups\Services\CreatesGroup;
use App\Models\Transaction;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Wallets\Processors\CreateWalletTopUpTransactionProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\GroupTransaction;
use App\Http\Resources\WalletTransactionResource;
use App\Models\Wallet;
use App\Classes\Modules\Transactions\Processors\ReleaseGoodsToCustomerProcessor;
use App\Classes\Modules\Transactions\Processors\CheckStorageInvoiceTransactionProcessor;
use Illuminate\Support\Facades\Log;
class CreateGroupsLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Create Group Transaction',
'message' => 'You have successfully created a group transaction'
];
}
/** @var FetchesTransaction */
private $fetchesTransaction;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var FetchesCompanyModule */
private $fetchesCompanyModule;
/** @var CreateWalletTopUpTransactionProcessor */
private $createWalletTopUpTransactionProcessor;
/** @var CreatePaymentTransactionProcessor */
private $createPaymentTransactionProcessor;
/** @var CreatesGroup */
private $createsGroup;
/** @var ReleaseGoodsToCustomerProcessor */
private $releaseGoodsToCustomerProcessor;
/** @var CheckStorageInvoiceTransactionProcessor */
private $checkStorageInvoiceTransactionProcessor;
public function __construct(
FetchesTransaction $fetchesTransaction,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
FetchesCompanyModule $fetchesCompanyModule,
CreateWalletTopUpTransactionProcessor $createWalletTopUpTransactionProcessor,
CreatePaymentTransactionProcessor $createPaymentTransactionProcessor,
CreatesGroup $createsGroup,
ReleaseGoodsToCustomerProcessor $releaseGoodsToCustomerProcessor,
CheckStorageInvoiceTransactionProcessor $checkStorageInvoiceTransactionProcessor
)
{
$this->fetchesTransaction = $fetchesTransaction;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->createWalletTopUpTransactionProcessor = $createWalletTopUpTransactionProcessor;
$this->createPaymentTransactionProcessor = $createPaymentTransactionProcessor;
$this->createsGroup = $createsGroup;
$this->releaseGoodsToCustomerProcessor = $releaseGoodsToCustomerProcessor;
$this->checkStorageInvoiceTransactionProcessor = $checkStorageInvoiceTransactionProcessor;
}
public function logic(Request $request) : JsonResponse
{
$invoice_ids = json_decode($request->route('transaction_ids'));
// todo-new: check why is this not working
// $invoices = $this->fetchesTransaction->execute(['id_in' => $invoice_ids]);
$invoices = Transaction::whereIn('id', $invoice_ids)->get();
$typeOneInvoices = $invoices->filter(function ($invoice) {
return $invoice->type == 1;
});
// Check amount to be paid by customer 1
$amount = $request->input('amount');
if($typeOneInvoices)
{
foreach ($typeOneInvoices as $invoice) {
$storages = $this->checkStorageInvoiceTransactionProcessor->executeShippingTransaction($invoice);
$invoice['storages'] = $storages;
}
$totalAmount = $typeOneInvoices->reduce(function ($total, $transaction) {
$topLevelAmount = $transaction->amount ?? 0;
$storagesAmount = collect($transaction['storages'] ?? [])->reduce(function ($sum, $storage) {
$storageInvoiceAmount = $storage['storageInvoice']['amount'] ?? 0;
return $sum + $storageInvoiceAmount;
}, 0);
return $total + $topLevelAmount + $storagesAmount;
}, 0);
$diff = abs($amount - $totalAmount);
if($diff > 0.01){
$response = ['message' => 'Some information has been updated, please reload the page to proceed. [ref: 001]'];
return $this->response(['data' => $response]);
}
}
// Check amount to be paid by customer 2
$totalAmount = 0;
$proceed = false;
foreach ($invoices as $invoice) {
$totalAmount += $invoice->amount;
}
if(abs($totalAmount - $amount ) > 0.01){
$proceed = true;
}
if($proceed){
// $response = ['message' => 'Total: '.$totalAmount. ', submitted amount: '.$request->input('amount').', proceed: true'];
$response = ['message' => 'Some information has been updated, please reload the page to proceed. [ref: 002]'];
return $this->response(['data' => $response]);
}
$isInvoicesApprove = $this->checkIfInvoicesAreApprove($invoices);
if(!$isInvoicesApprove){
$response = ['message' => 'One of the transactions might be suspended; please check if there are any disputes in progress.'];
return $this->response(['data' => $response]);
}
else{
$paymentMethodStr = $request->input('payment_method');
$paymentMethod = PaymentMethodType::PAYMENT_METHODS[$paymentMethodStr];
$bankCode = $request->input('bank_code');
$result = $this->processInvoices($invoices, $paymentMethodStr, $amount, $bankCode);
if ($paymentMethod === PaymentMethodType::PAYMENT_GATEWAY) {
return $this->resourceResponse(new WalletTransactionResource($result));
}
}
return $this->response([]);
}
private function processInvoices($invoices, $reqPaymentMethod, $reqAmount, $reqBankCode){
$result = [];
$payment_method = PaymentMethodType::PAYMENT_METHODS[$reqPaymentMethod];
$groupPyamentStatus = ApprovalStatus::PENDING_VERIFICATION;
$billNumber = $this->generatesTransactionBillNumber->execute('PYMT-');
foreach ($invoices as $invoice) {
$order = null;
if ($invoice->owner instanceof Transaction) {
if ($invoice->owner) {
if ($invoice->owner->owner) {
$order = $invoice->owner->owner->owner;
}
}
} else if (!($invoice->owner instanceof Transaction) && !($invoice->owner instanceof Wallet)) {
if ($invoice->owner) {
$order = $invoice->owner->owner;
}
}
if (!$order) {
throw new MalformedRequestException("There is an error while paying for invoice {$invoice->bill_no}");
}
}
if ($payment_method == PaymentMethodType::WALLET) {
$companyModuleId = $invoices->first()->receiver;
$wallet = Wallet::where('owner_id', $companyModuleId)->first();
// todo-new: verify currently checking wallet amount based on 'amount' value passed by frontend
if((float) number_format(($wallet->amount - $reqAmount),2) < 0){
throw new MalformedRequestException('Insufficient wallet balance. Please Top up your wallet.');
}
$groupPyamentStatus = ApprovalStatus::APPROVED;
}
$issuer = 0;
$receiver = 0;
$amount = 0;
$original_amount = 0;
$currency_id = 0;
$original_currency_id = 0;
$currency_rate = 0;
$tax = 0;
$service_charge = 0;
$group = new GroupObject(
$issuer,
$receiver,
$amount,
$original_amount,
$currency_id,
$original_currency_id,
$currency_rate,
$tax,
$service_charge,
$payment_method,
'-',
$groupPyamentStatus,
);
$group = $this->createsGroup->execute($group);
foreach ($invoices as $invoice) {
if ($payment_method == PaymentMethodType::WALLET) {
$paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, $reqBankCode, false);
if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
// $pL = $invoice->owner;
// $this->releaseGoodsToCustomerProcessor->execute($pL, $invoice);
$obj = json_encode($invoice);
Log::info("Preparing to release goods for invoice: {$obj}");
ReleaseGoodsToCustomerV2CommandJob::dispatch($invoice);
}
}
$issuer = $invoice->issuer;
$receiver = $invoice->receiver;
$amount += $invoice->amount;
$original_amount += $invoice->original_amount;
$currency_id = $invoice->currency_id;
$original_currency_id = $invoice->original_currency_id;
$currency_rate = $invoice->currency_rate;
$tax += $invoice->tax;
$service_charge += $invoice->service_charge;
// creates group transaction
$groupTransaction = new GroupTransaction();
$groupTransaction->group_id = $group->id;
$groupTransaction->transaction_id = $invoice->id;
$groupTransaction->save();
}
if (in_array($payment_method, [PaymentMethodType::PAYMENT_GATEWAY, PaymentMethodType::CASH])) {
// create only one billplz payment for wallet top up
$amount = floatval(str_replace(',', '', $reqAmount));
$companyModuleId = $invoice->receiver;
$companyModule = $this->fetchesCompanyModule->execute(['id' => $companyModuleId]);
$topUpTransaction = $this->createWalletTopUpTransactionProcessor->execute($companyModule, $amount, $reqBankCode, $payment_method, $billNumber, true);
$result = $topUpTransaction;
}
$group->issuer = $issuer;
$group->receiver = $receiver;
$group->reference = $payment_method === PaymentMethodType::PAYMENT_GATEWAY ? $topUpTransaction->payment_reference : $billNumber;
$group->amount = $amount;
$group->original_amount = $original_amount;
$group->currency_id = $currency_id;
$group->original_currency_id = $original_currency_id;
$group->currency_rate = $currency_rate;
$group->tax = $tax;
$group->service_charge = $service_charge;
$group->status = $groupPyamentStatus;
$group->save();
return $result;
}
private function checkIfInvoicesAreApprove($invoices){
foreach ($invoices as $invoice) {
if($invoice->status !== ApprovalStatus::APPROVED && $invoice->status !== ApprovalStatus::COMPLETED){
return false;
}
}
return true;
}
}