diff --git a/ phpunit.dusk.xml b/ phpunit.dusk.xml new file mode 100644 index 00000000..db1abe1e --- /dev/null +++ b/ phpunit.dusk.xml @@ -0,0 +1,16 @@ + + + + + + + + + ./tests/Browser/DryRun/ + + + + + diff --git a/.env.dusk b/.env.dusk new file mode 100644 index 00000000..4041ae24 --- /dev/null +++ b/.env.dusk @@ -0,0 +1,59 @@ +APP_NAME=Laravel +APP_ENV=local +APP_KEY=base64:X521H/hWdbsG6S/JG0Q/BZgTo1azoV18kzqkqMQSDrQ= +APP_DEBUG=true +APP_URL=http://localhost + +LOG_CHANNEL=stack + +DB_CONNECTION=dusk +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=exchange-test +DB_USERNAME=root +DB_PASSWORD= + +BROADCAST_DRIVER=log +CACHE_DRIVER=file +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=smtp +MAIL_HOST=smtp.mailtrap.io +MAIL_PORT=2525 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS=null +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= + +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_APP_CLUSTER=mt1 + +MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" + +FILESYSTEM_DRIVER="documents" + +JWT_SECRET= +JWT_TTL=1440 + +SHIPPING_URL=http://shipping-portal.test/ +MIX_SHIPPING_URL="${SHIPPING_URL}" + +BILLPLZ_BASE_URL="https://www.billplz-sandbox.com" +BILLPLZ_API_KEY="0fa4c710-761b-4a7a-a501-c2c2d02643d5" +BILLPLZ_X_SIGNATURE_KEY="S-pbNVthVRsvnPfZlgLwqqOg" +BILLPLZ_COLLECTION_ID="hev2wdjy" \ No newline at end of file diff --git a/app/Classes/General/Interfaces/Notifiable.php b/app/Classes/General/Interfaces/Notifiable.php new file mode 100644 index 00000000..e9d8f22d --- /dev/null +++ b/app/Classes/General/Interfaces/Notifiable.php @@ -0,0 +1,15 @@ +assignSegmentProcessor->execute($company); - $this->generateEmailVerificationAttemptProcessor->execute($user); + // $this->generateEmailVerificationAttemptProcessor->execute($user); return $this->response($this->authenticationProcessor->execute($request)); diff --git a/app/Classes/Modules/Banks/ControllersLogic/CreateBankLogic.php b/app/Classes/Modules/Banks/ControllersLogic/CreateBankLogic.php index ff5b16c2..53dd5caa 100644 --- a/app/Classes/Modules/Banks/ControllersLogic/CreateBankLogic.php +++ b/app/Classes/Modules/Banks/ControllersLogic/CreateBankLogic.php @@ -6,6 +6,7 @@ use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Banks\Standards\Rules\CanCreateBank; use App\Classes\Modules\Banks\Services\CreatesBank; +use App\Classes\Modules\Banks\Services\CreatesBankLog; use App\Classes\Modules\Banks\DataTransferObjects\BankObject; use App\Http\Resources\BankResource; @@ -32,19 +33,24 @@ class CreateBankLogic extends AbstractControllerLogic /** @var CreatesBank */ private $createsBank; + /** @var CreatesBankLog */ + private $createsBankLog; /** * CreateBankLogic constructor. * @param CanCreateBank $canCreateBank * @param CreatesBank $createsBank + * @param CreatesBankLog $createsBankLog */ public function __construct( CanCreateBank $canCreateBank, - CreatesBank $createsBank + CreatesBank $createsBank, + CreatesBankLog $createsBankLog ) { $this->canCreateBank = $canCreateBank; $this->createsBank = $createsBank; + $this->createsBankLog = $createsBankLog; } /** @@ -56,7 +62,6 @@ class CreateBankLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - $bank_object = new BankObject($request->input('company_id'), $request->input('account_type'), $request->input('bank_name'), $request->input('holder_name'), $request->input('account_no'), $request->input('bank_branch'), $request->input('swift'), $request->input('snap'), @@ -66,6 +71,8 @@ class CreateBankLogic extends AbstractControllerLogic $bank = $this->createsBank->execute($bank_object); + $bankLog = $this->createsBankLog->execute($bank); + return $this->resourceResponse(new BankResource($bank)); } diff --git a/app/Classes/Modules/Banks/ControllersLogic/DeleteBankLogic.php b/app/Classes/Modules/Banks/ControllersLogic/DeleteBankLogic.php index 24975379..3ecac081 100644 --- a/app/Classes/Modules/Banks/ControllersLogic/DeleteBankLogic.php +++ b/app/Classes/Modules/Banks/ControllersLogic/DeleteBankLogic.php @@ -7,6 +7,7 @@ use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Banks\Services\FetchesBank; use App\Classes\Modules\Banks\Standards\Rules\CanDeleteBank; use App\Classes\Modules\Banks\Services\DeletesBank; +use App\Classes\Modules\Banks\Services\CreatesBankLog; use App\Http\Resources\BankResource; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -33,22 +34,27 @@ class DeleteBankLogic extends AbstractControllerLogic /** @var FetchesBank */ private $fetchesBank; + /** @var CreatesBankLog */ + private $createsBankLog; /** * DeleteBankLogic constructor. * @param CanDeleteBank $canDeleteBank * @param DeletesBank $deletesBank * @param FetchesBank $fetchesBank + * @param CreatesBankLog $createsBankLog */ public function __construct( CanDeleteBank $canDeleteBank, DeletesBank $deletesBank, - FetchesBank $fetchesBank + FetchesBank $fetchesBank, + CreatesBankLog $createsBankLog ) { $this->canDeleteBank = $canDeleteBank; $this->deletesBank = $deletesBank; $this->fetchesBank = $fetchesBank; + $this->createsBankLog = $createsBankLog; } /** @@ -69,7 +75,9 @@ class DeleteBankLogic extends AbstractControllerLogic throw new RequestValidationException('You can\'t delete bank account when it set to default'); } - $this->deletesBank->execute($bank); + $bank = $this->deletesBank->execute($bank); + + $bankLog = $this->createsBankLog->execute($bank); return $this->response([]); } diff --git a/app/Classes/Modules/Banks/ControllersLogic/UpdateBankLogic.php b/app/Classes/Modules/Banks/ControllersLogic/UpdateBankLogic.php index 9cb8fdd2..ed6ae159 100644 --- a/app/Classes/Modules/Banks/ControllersLogic/UpdateBankLogic.php +++ b/app/Classes/Modules/Banks/ControllersLogic/UpdateBankLogic.php @@ -10,6 +10,8 @@ use App\Classes\Modules\Banks\Services\FetchesBank; use App\Classes\Modules\Banks\Standards\Rules\CanUpdateBank; use App\Classes\Modules\Banks\Services\UpdatesBank; +use App\Classes\Modules\Banks\Services\CreatesBankLog; + use App\Classes\Modules\Banks\DataTransferObjects\BankObject; use ErrorException; @@ -39,21 +41,27 @@ class UpdateBankLogic extends AbstractControllerLogic /** @var FetchesBank */ private $fetchesBank; + /** @var CreatesBankLog */ + private $createsBankLog; + /** * UpdateBankLogic constructor. * @param CanUpdateBank $canUpdateBank * @param UpdatesBank $updatesBank * @param FetchesBank $fetchesBank + * @param CreatesBankLog $createsBankLog */ public function __construct( CanUpdateBank $canUpdateBank, UpdatesBank $updatesBank, - FetchesBank $fetchesBank + FetchesBank $fetchesBank, + CreatesBankLog $createsBankLog ) { $this->canUpdateBank = $canUpdateBank; $this->updatesBank = $updatesBank; $this->fetchesBank = $fetchesBank; + $this->createsBankLog = $createsBankLog; } /** @@ -84,6 +92,8 @@ class UpdateBankLogic extends AbstractControllerLogic $bank_query = $this->updatesBank->execute($bank, $bankObject); + $bankLog = $this->createsBankLog->execute($bank_query); + return $this->resourceResponse(new BankResource($bank_query)); } diff --git a/app/Classes/Modules/Banks/ControllersLogic/UpdateBankStatusLogic.php b/app/Classes/Modules/Banks/ControllersLogic/UpdateBankStatusLogic.php index 09ee2796..4959face 100644 --- a/app/Classes/Modules/Banks/ControllersLogic/UpdateBankStatusLogic.php +++ b/app/Classes/Modules/Banks/ControllersLogic/UpdateBankStatusLogic.php @@ -6,6 +6,7 @@ use App\Http\Resources\BankResource; use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Banks\Services\FetchesBank; use App\Classes\Modules\Banks\Services\UpdatesBankStatus; +use App\Classes\Modules\Banks\Services\CreatesBankLog; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -28,18 +29,24 @@ class UpdateBankStatusLogic extends AbstractControllerLogic /** @var UpdatesBankStatus */ private $updatesBankStatus; + /** @var CreatesBankLog */ + private $createsBankLog; + /** * UpdateBankStatusLogic constructor. * @param FetchesBank $fetchesBank * @param UpdatesBankStatus $updatesBankStatus + * @param CreatesBankLog $createsBankLog */ public function __construct( FetchesBank $fetchesBank, - UpdatesBankStatus $updatesBankStatus + UpdatesBankStatus $updatesBankStatus, + CreatesBankLog $createsBankLog ) { $this->fetchesBank = $fetchesBank; $this->updatesBankStatus = $updatesBankStatus; + $this->createsBankLog = $createsBankLog; } /** @@ -55,6 +62,8 @@ class UpdateBankStatusLogic extends AbstractControllerLogic $bank_query = $this->updatesBankStatus->execute($bank, $request->input('status')); + $bankLog = $this->createsBankLog->execute($bank_query); + return $this->resourceResponse(new BankResource($bank_query)); } diff --git a/app/Classes/Modules/Banks/Services/CreatesBankLog.php b/app/Classes/Modules/Banks/Services/CreatesBankLog.php new file mode 100644 index 00000000..9d7877e1 --- /dev/null +++ b/app/Classes/Modules/Banks/Services/CreatesBankLog.php @@ -0,0 +1,32 @@ +bank_id = $object->id; + $model->company_id = $object->company_id; + $model->reference = $object->reference; + $model->bank_name = $object->bank_name; + $model->holder_name = $object->holder_name; + $model->account_no = $object->account_no; + $model->bank_branch = $object->bank_branch; + $model->swift = $object->swift; + $model->snap = $object->snap; + $model->type = $object->type; + $model->country_id = $object->country_id; + return $this->handler($model); + + } +} \ 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 2230343f..eb3aec53 100644 --- a/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php +++ b/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php @@ -4,6 +4,7 @@ namespace App\Classes\Modules\Billplzs\ControllersLogic; use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject; use App\Classes\Modules\Wallets\Services\UpdatesWallet; +use App\Classes\Modules\Transactions\Processors\CreateCashBackTransactionProcessor; use App\Classes\Exceptions\ResourceNotFoundException; use App\Classes\Modules\Wallets\Services\UpdatesWalletBalance; @@ -16,6 +17,7 @@ use Illuminate\Http\JsonResponse; use App\Classes\Exceptions\MalformedRequestException; use App\Classes\ValueObjects\Constants\ApprovalStatus; +use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\Modules\Billplzs\Services\GetBillplzBill; use App\Classes\Modules\Billplzs\DataTransferObjects\BillplzXSignatureObject; use App\Classes\General\Abstracts\AbstractControllerLogic; @@ -40,6 +42,9 @@ class CallbackBillplzLogic /** @var UpdatesWalletBalance */ private $updatesWalletBalance; + /** @var CreateCashBackTransactionProcessor */ + private $createCashBackTransactionProcessor; + /** * CallbackBillplzLogic constructor. * @param GetBillplzBill $getBillplzBill @@ -47,12 +52,13 @@ class CallbackBillplzLogic * @param UpdatesTransactionStatus $updatesTransactionStatus * @param UpdatesWalletBalance $updatesWalletBalance */ - public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdatesWalletBalance $updatesWalletBalance) + public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdatesWalletBalance $updatesWalletBalance, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor) { $this->getBillplzBill = $getBillplzBill; $this->fetchesTransaction = $fetchesTransaction; $this->updatesTransactionStatus = $updatesTransactionStatus; $this->updatesWalletBalance = $updatesWalletBalance; + $this->createCashBackTransactionProcessor = $createCashBackTransactionProcessor; } @@ -80,6 +86,7 @@ class CallbackBillplzLogic $status = ApprovalStatus::APPROVED; } + if($billPlz->state === 'due') { $status = $billplzXSignatureObject->getStatus() === 'failed' ? ApprovalStatus::REJECTED : ApprovalStatus::PENDING_VERIFICATION; } @@ -93,6 +100,9 @@ class CallbackBillplzLogic } + if ($transaction->type == TransactionType::PAYMENT) { + $cash_back_transaction = $this->createCashBackTransactionProcessor->execute($transaction); + } $token = Auth::fromUser(User::find(1)); $request->headers->set('Authorization', 'Bearer '.$token); diff --git a/app/Classes/Modules/Bookings/ControllersLogic/ApprovePaymentVerificationLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/ApprovePaymentVerificationLogic.php index b0a01562..d5810e12 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/ApprovePaymentVerificationLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/ApprovePaymentVerificationLogic.php @@ -2,16 +2,16 @@ namespace App\Classes\Modules\Bookings\ControllersLogic; - use App\Classes\General\Abstracts\AbstractControllerLogic; - use App\Classes\Modules\Documents\Services\ApprovesDocument; use App\Classes\Modules\Documents\Services\FetchesDocument; use App\Classes\Modules\Documents\Services\RejectsDocument; use App\Classes\Modules\Transactions\Services\FetchesTransaction; use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; +use App\Classes\Modules\Transactions\Processors\CreateCashBackTransactionProcessor; + use App\Classes\ValueObjects\Constants\ApprovalStatus; use Illuminate\Http\JsonResponse; @@ -26,14 +26,15 @@ class ApprovePaymentVerificationLogic extends AbstractControllerLogic * @param ApprovesDocument $approvesDocument * @param RejectsDocument $rejectsDocument * @param FetchesDocument $fetchesDocument - * @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor + * @param CreateCashBackTransactionProcessor $createCashBackTransactionProcessor */ - public function __construct(FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, FetchesDocument $fetchesDocument) + public function __construct(FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, FetchesDocument $fetchesDocument, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor) { $this->fetchesTransaction = $fetchesTransaction; $this->updatesTransactionStatus = $updatesTransactionStatus; $this->approvesDocument = $approvesDocument; $this->rejectsDocument = $rejectsDocument; + $this->createCashBackTransactionProcessor = $createCashBackTransactionProcessor; } /** @@ -58,6 +59,9 @@ class ApprovePaymentVerificationLogic extends AbstractControllerLogic /** @var RejectsDocument */ private $rejectsDocument; + /** @var CreateCashBackTransactionProcessor */ + private $createCashBackTransactionProcessor; + /** * @param Request $request * @return JsonResponse @@ -65,7 +69,6 @@ class ApprovePaymentVerificationLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - $status = $request->route('status'); $transaction = $this->fetchesTransaction->execute(['id' => $request->route('payment_id')]); @@ -74,7 +77,7 @@ class ApprovePaymentVerificationLogic extends AbstractControllerLogic $this->updatesTransactionStatus->execute($transaction, $status === 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED); - // $this->createInvoiceTransactionProcessor->execute($transaction->booking); + $this->createCashBackTransactionProcessor->execute($transaction); return $this->response([]); } diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php index a0124002..f15a2f41 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php @@ -20,6 +20,9 @@ use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\PaymentMethodType; use App\Classes\ValueObjects\Constants\TransactionType; use App\Http\Resources\TransactionResource; + +use App\Classes\Modules\Transactions\Processors\CreateCashBackTransactionProcessor; + use App\Models\Booking; use App\Models\Transaction; use App\Models\Wallet; @@ -64,6 +67,9 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic /** @var UpdatesTransactionStatus */ private $updatesTransactionStatus; + /** @var CreateCashBackTransactionProcessor */ + private $createCashBackTransactionProcessor; + /** * CreateBookingPaymentLogic constructor. * @param FetchesBookingQuotation $fetchBookingQuotation @@ -74,8 +80,9 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic * @param CreatesBillplzBill $createsBillplzBill * @param UpdatesWalletBalance $updatesWalletBalance * @param UpdatesTransactionStatus $updatesTransactionStatus + * @param CreateCashBackTransactionProcessor $createCashBackTransactionProcessor */ - public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding, CreatesBillplzBill $createsBillplzBill, UpdatesWalletBalance $updatesWalletBalance, UpdatesTransactionStatus $updatesTransactionStatus) + public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding, CreatesBillplzBill $createsBillplzBill, UpdatesWalletBalance $updatesWalletBalance, UpdatesTransactionStatus $updatesTransactionStatus, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor) { $this->fetchBookingQuotation = $fetchBookingQuotation; $this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit; @@ -85,6 +92,7 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic $this->createsBillplzBill = $createsBillplzBill; $this->updatesWalletBalance = $updatesWalletBalance; $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->createCashBackTransactionProcessor = $createCashBackTransactionProcessor; } /** @@ -126,12 +134,11 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic } $transaction_object = new TransactionObject($billNumber, TransactionType::PAYMENT, 1, $booking->company->id, 1, PaymentMethodType::WALLET, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], ''); - $this->createsTransaction->execute($wallet, $transaction_object); + $transaction = $this->createsTransaction->execute($wallet, $transaction_object); $paymentReference = $billNumber; $this->updatesWalletBalance->execute($wallet, ($amount * -1)); - } $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); @@ -144,6 +151,7 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic /** @var Transaction $transaction */ $transaction = $this->createsTransaction->execute($booking, $object); + $cash_back_transaction = $this->createCashBackTransactionProcessor->execute($transaction); if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::WALLET){ $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::APPROVED); diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php index 74e92fa6..d31ee2ce 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php @@ -84,12 +84,14 @@ class CreateBookingRefundLogic extends AbstractControllerLogic $billNumber = $this->generatesTransactionBillNumber->execute('RFD-'); - $refund = $transaction->transactions()->refunds()->sum('amount'); if($refund + $request->input('amount') > $transaction->original_amount) throw new MalformedRequestException('Your refund must not be greater than '. $transaction->original_amount .'.'); - $transactionRefundCalculationObject = new TransactionRefundCalculationObject($booking, $transaction, $request->input('amount')); + $amount = $transaction->booking->fix_currency_id == 1 ? $request->input('amount') : $request->input('amount') / $transaction->currency_rate; + + + $transactionRefundCalculationObject = new TransactionRefundCalculationObject($booking, $transaction, $amount); $transactionRefundCalculationObject->init(); $object = new TransactionObject($billNumber, TransactionType::REFUND, 1, $booking->company->id, diff --git a/app/Classes/Modules/Bookings/ControllersLogic/DownloadBookingDocumentLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/DownloadBookingDocumentLogic.php index d8fdb0df..ff9427fe 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/DownloadBookingDocumentLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/DownloadBookingDocumentLogic.php @@ -14,6 +14,7 @@ use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Storage; use App\Classes\Exceptions\MalformedRequestException; use App\Classes\ValueObjects\Constants\ApprovalStatus; +use App\Classes\ValueObjects\Constants\DocumentType; class DownloadBookingDocumentLogic { @@ -26,9 +27,9 @@ class DownloadBookingDocumentLogic */ public function execute(Request $request) { - Auth::login(User::findOrFail(1)); - $zip_file = $request->input('type').'.zip'; + $document_type = str_replace(' ', '', $request->input('type')); + $zip_file = $document_type.'.zip'; $attachment = storage_path().'/app/documents/collections/' . $zip_file; $zip = new ZipArchive(); @@ -36,19 +37,42 @@ class DownloadBookingDocumentLogic $bookings = Booking::where('status', ApprovalStatus::COMPLETED) ->whereDate('created_at', '>=', Carbon::parse($request->input('startDate'))) - ->whereDate('created_at', '<=', Carbon::parse($request->input('endDate')))->whereHas('transactions', function ($query) use ($request){ + ->whereDate('created_at', '<=', Carbon::parse($request->input('endDate'))) + ->whereHas('transactions', function ($query) use ($request){ return $query->where('type', TransactionType::PAYMENT)->whereHas('transactions', function ($query) use ($request){ return $query->where('type', TransactionType::BILL)->where('issuer', $request->input('supplier')); }); })->get(); - if (!count($bookings)) throw new MalformedRequestException('No available file to download'); - foreach ($bookings as $booking) { - $file = $booking->documents()->where('document_type', $request->input('type'))->first()->files()->first(); - $zip->addFile(Storage::disk('documents')->path($file->file->file_info->original->file), $booking->created_at->format('d_m_Y') . '_' . $booking->marking . '.pdf'); + if (!count($bookings)) { + return response()->json(['no file to download']); } + foreach ($bookings as $booking) { + + if ($document_type == 'INVOICEPODO' || $document_type == 'INVOICEPODOSDO') { + $invoice_file = $booking->documents()->where('document_type', DocumentType::INVOICE)->first()->files()->first(); + $purchase_file = $booking->documents()->where('document_type', DocumentType::PURCHASE_ORDER)->first()->files()->first(); + $deliver_file = $booking->documents()->where('document_type', DocumentType::DELIVER_ORDER)->first()->files()->first(); + if ($document_type == 'INVOICEPODOSDO') { + $supplier_deliver_order_file = $booking->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->first()->files()->first(); + } + + $zip->addFile(Storage::disk('documents')->path($invoice_file->file->file_info->original->file), 'invoice-' . $booking->created_at->format('d_m_Y') . '_' . $booking->marking . '.pdf'); + + $zip->addFile(Storage::disk('documents')->path($purchase_file->file->file_info->original->file), 'purchase-order-' . $booking->created_at->format('d_m_Y') . '_' . $booking->marking . '.pdf'); + + $zip->addFile(Storage::disk('documents')->path($deliver_file->file->file_info->original->file), 'deliver-' . $booking->created_at->format('d_m_Y') . '_' . $booking->marking . '.pdf'); + + $zip->addFile(Storage::disk('documents')->path($supplier_deliver_order_file->file->file_info->original->file), 'supplier-deliver-order-' . $booking->created_at->format('d_m_Y') . '_' . $booking->marking . '.pdf'); + } + else { + $file = $booking->documents()->where('document_type', $document_type)->first()->files()->first(); + $zip->addFile(Storage::disk('documents')->path($file->file->file_info->original->file), $booking->created_at->format('d_m_Y') . '_' . $booking->marking . '.pdf'); + } + + } $zip->close(); while (ob_get_level()) { ob_end_clean(); diff --git a/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingPaymentQuotationLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingPaymentQuotationLogic.php index eaac0adc..3a981946 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingPaymentQuotationLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingPaymentQuotationLogic.php @@ -62,7 +62,6 @@ class FetchBookingPaymentQuotationLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - $booking = Booking::find($request->route('id')); $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $request->input('amount'))), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')]); diff --git a/app/Classes/Modules/Companies/ControllersLogic/ApproveIdentificationDocumentLogic.php b/app/Classes/Modules/Companies/ControllersLogic/ApproveIdentificationDocumentLogic.php index d5e052a9..cf894bfd 100644 --- a/app/Classes/Modules/Companies/ControllersLogic/ApproveIdentificationDocumentLogic.php +++ b/app/Classes/Modules/Companies/ControllersLogic/ApproveIdentificationDocumentLogic.php @@ -13,6 +13,9 @@ use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Documents\Services\FetchesDocument; use App\Classes\Modules\Documents\Services\ApprovesDocument; +use App\Classes\Modules\Notifications\DataTransferObjects\NotificationObject; +Use App\Classes\Modules\Notifications\Processors\CreateNotificationProcessor; +use App\Classes\General\Interfaces\Notifiable; use App\Models\Document; use Illuminate\Http\JsonResponse; @@ -46,6 +49,9 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic /** @var UpdatesCompanyStatus */ private $updatesCompanyStatus; + /** @var CreateNotificationProcessor */ + private $createNotificationProcessor; + /** * ApproveIdentificationDocumentLogic constructor. * @param CanApproveDocument $canApproveDocument @@ -53,14 +59,16 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic * @param RejectsDocument $rejectsDocument * @param FetchesDocument $fetchesDocument * @param UpdatesCompanyStatus $updatesCompanyStatus + * @param CreateNotificationProcessor $createNotificationProcessor */ - public function __construct(CanApproveDocument $canApproveDocument, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, FetchesDocument $fetchesDocument, UpdatesCompanyStatus $updatesCompanyStatus) + public function __construct(CanApproveDocument $canApproveDocument, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, FetchesDocument $fetchesDocument, UpdatesCompanyStatus $updatesCompanyStatus, CreateNotificationProcessor $createNotificationProcessor) { $this->canApproveDocument = $canApproveDocument; $this->approvesDocument = $approvesDocument; $this->rejectsDocument = $rejectsDocument; $this->fetchesDocument = $fetchesDocument; $this->updatesCompanyStatus = $updatesCompanyStatus; + $this->createNotificationProcessor = $createNotificationProcessor; } /** @@ -84,6 +92,16 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic $this->updatesCompanyStatus->execute($document->owner, $status === 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED); + $object = new NotificationObject( + 'ID Verification ' . ( $status === 'approve' ? 'Approved' : 'Rejected' ), + ( $status === 'approve' ? 'Dear user, congratulations that your ' : 'Dear user, we are sorry to inform you that your ' ) . ( $document->type === 'IDENTITY_CARD' ? 'IC' : 'SSM' ) . ( $status === 'approve' ? ' has been approved. Start your first order now!' : ' has been rejected due to ' . ( $request->input('rejectRemark') ?? '' ) . ', please resubmit it for further action.' ), + $document->owner, + $document->owner->employees()->first(), + $document, + ); + + $this->createNotificationProcessor->execute($object); + return $this->resourceResponse(new DocumentResource($document)); } diff --git a/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyStatusLogic.php b/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyStatusLogic.php new file mode 100644 index 00000000..92278bef --- /dev/null +++ b/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyStatusLogic.php @@ -0,0 +1,62 @@ + 'Update Company Account Status', + 'message' => 'You have successfully updated the Company Account Status' + ]; + } + + /** @var FetchesCompany */ + private $fetchesCompany; + + /** @var UpdatesCompanyStatus */ + private $updatesCompanyStatus; + + /** + * UpdateCompanyStatusLogic constructor. + * @param FetchesCompany $fetchesCompany + * @param UpdatesCompanyStatus $updatesCompanyStatus + */ + public function __construct( + FetchesCompany $fetchesCompany, + UpdatesCompanyStatus $updatesCompanyStatus + ) + { + $this->fetchesCompany = $fetchesCompany; + $this->updatesCompanyStatus = $updatesCompanyStatus; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function logic(Request $request) : JsonResponse + { + $company = $this->fetchesCompany->execute(['id' => $request->route('id')]); + + $company_query = $this->updatesCompanyStatus->execute($company, $request->input('status')); + + return $this->resourceResponse(new CompanyResource($company_query)); + + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Companies/Processors/CreateCompanyProcessor.php b/app/Classes/Modules/Companies/Processors/CreateCompanyProcessor.php index fc84e9cc..ad9abeb8 100644 --- a/app/Classes/Modules/Companies/Processors/CreateCompanyProcessor.php +++ b/app/Classes/Modules/Companies/Processors/CreateCompanyProcessor.php @@ -46,9 +46,10 @@ class CreateCompanyProcessor public function execute(Request $request, int $businessType = BusinessType::IMPORTER, ?int $companyType = CompanyType::COMPANY_BUSINESS, ?int $status = ApprovalStatus::PENDING_SUBMISSION): Model { $companyName = $companyType === CompanyType::COMPANY_BUSINESS ? $request->input('company_name') : $request->input('name'); + $companyReference = $request->input('company_reference') ? $request->input('company_reference') : mt_rand(1000, 9999).(new GeneratesInitials())->name($companyName)->length(3)->generate(); $company_object = new CompanyObject( $companyName, - mt_rand(1000, 9999).(new GeneratesInitials())->name($companyName)->length(3)->generate(), + $companyReference, $businessType, $companyType, $status); $this->canCreateCompany->passes($company_object); diff --git a/app/Classes/Modules/Exports/Services/ExportsBookingTransactions.php b/app/Classes/Modules/Exports/Services/ExportsBookingTransactions.php new file mode 100644 index 00000000..aed106ea --- /dev/null +++ b/app/Classes/Modules/Exports/Services/ExportsBookingTransactions.php @@ -0,0 +1,74 @@ +request = $request; + } + + public function headings(): array + { + return [ + 'Ref No', + 'Creted Date', + 'Amount', + 'Rate', + 'Supplier' + ]; + } + + /** + * @return \Illuminate\Support\Collection|mixed + */ + public function query() + { + $supplierIds = array_map(function($value){ + return ['id' => $value]; + }, json_decode($this->request->input('supplierIds'))); + + $dateFrom =Carbon::parse($this->request->input('startDate'))->format('Y-m-d'); + $dateTo =Carbon::parse($this->request->input('endDate'))->format('Y-m-d'); + + return Transaction::where('type', 3)->whereIn('issuer', $supplierIds)->whereBetween('created_at', [$dateFrom, $dateTo]); + } + + /** + * @param $transaction + * @return array + */ + public function map($transaction): array + { + $supplierName = Company::where('id', $transaction->issuer)->get()->first()->name; + $refNo = $transaction->owner->owner == null ? $transaction->owner->marking : $transaction->owner->owner->marking; + + $createdAt = $transaction->created_at->format('d-m-Y'); + $amount = $transaction->amount; + $rate = $transaction->currency_rate; + + return [ + $refNo, + $createdAt, + $amount, + $rate, + $supplierName + ]; + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Exports/Services/ExportsTransactions.php b/app/Classes/Modules/Exports/Services/ExportsTransactions.php index 89a765e5..b7f0e5ad 100644 --- a/app/Classes/Modules/Exports/Services/ExportsTransactions.php +++ b/app/Classes/Modules/Exports/Services/ExportsTransactions.php @@ -13,8 +13,9 @@ use Maatwebsite\Excel\Concerns\Exportable; use Maatwebsite\Excel\Concerns\FromQuery; use Maatwebsite\Excel\Concerns\WithHeadingRow; use Maatwebsite\Excel\Concerns\WithMapping; +use Maatwebsite\Excel\Concerns\ShouldAutoSize; -class ExportsTransactions implements FromQuery, WithHeadingRow, WithMapping +class ExportsTransactions implements FromQuery, WithHeadingRow, WithMapping, ShouldAutoSize { use Exportable; @@ -89,6 +90,7 @@ class ExportsTransactions implements FromQuery, WithHeadingRow, WithMapping $transactionStatus[$transaction->status], \PhpOffice\PhpSpreadsheet\Shared\Date::dateTimeToExcel($transaction->created_at), \PhpOffice\PhpSpreadsheet\Shared\Date::dateTimeToExcel($transaction->updated_at), + $marking ]; } } \ No newline at end of file diff --git a/app/Classes/Modules/Notifications/ControllersLogic/ListNotificationsLogic.php b/app/Classes/Modules/Notifications/ControllersLogic/ListNotificationsLogic.php new file mode 100644 index 00000000..0fdbf6f9 --- /dev/null +++ b/app/Classes/Modules/Notifications/ControllersLogic/ListNotificationsLogic.php @@ -0,0 +1,61 @@ + 'Retrieve Notifications', + 'message' => 'You have successfully retrieved a list of Notifications' + ]; + } + + /** @var ListsNotification */ + private $listsNotification; + + /** + * ListNotificationsLogic constructor. + * @param ListsNotification $listsNotification + */ + public function __construct( + ListsNotification $listsNotification + ) + { + $this->listsNotification = $listsNotification; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function logic(Request $request) : JsonResponse + { + + $filters = [ + // 'target_id'=>auth()->user()->id, + // 'per_page'=>$request->route('per_page') + ]; + + $notifications = $this->listsNotification->execute($filters); + + return $this->collectionResponse(NotificationResource::collection($notifications)); + + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Notifications/DataTransferObjects/NotificationObject.php b/app/Classes/Modules/Notifications/DataTransferObjects/NotificationObject.php new file mode 100644 index 00000000..40dc4f3c --- /dev/null +++ b/app/Classes/Modules/Notifications/DataTransferObjects/NotificationObject.php @@ -0,0 +1,101 @@ +title = $title; + $this->description = $description; + $this->subject = $subject; + $this->target = $target; + $this->causer = $causer; + $this->status = $status; + } + + /** + * @return int + */ + public function getTitle(): string + { + return $this->title; + } + + /** + * @return int + */ + public function getDescription(): string + { + return $this->description; + } + + /** + * @return Notifiable + */ + public function getSubject(): Notifiable + { + return $this->subject; + } + + /** + * @return Notifiable + */ + public function getTarget(): Notifiable + { + return $this->target; + } + + /** + * @return Notifiable + */ + public function getCauser(): Notifiable + { + return $this->causer; + } + + /** + * @return int + */ + public function getStatus(): int + { + return $this->status; + } + + +} diff --git a/app/Classes/Modules/Notifications/Processors/CreateNotificationProcessor.php b/app/Classes/Modules/Notifications/Processors/CreateNotificationProcessor.php new file mode 100644 index 00000000..d6b077f8 --- /dev/null +++ b/app/Classes/Modules/Notifications/Processors/CreateNotificationProcessor.php @@ -0,0 +1,27 @@ +createsNotification = $createsNotification; + } + + public function execute(NotificationObject $object) + { + $notification = $this->createsNotification->execute($object); + return $notification; + } +} diff --git a/app/Classes/Modules/Notifications/Services/CreatesNotification.php b/app/Classes/Modules/Notifications/Services/CreatesNotification.php new file mode 100644 index 00000000..4f5ca5fd --- /dev/null +++ b/app/Classes/Modules/Notifications/Services/CreatesNotification.php @@ -0,0 +1,30 @@ +title = $object->getTitle(); + $model->description = $object->getDescription(); + $model->status = $object->getStatus(); + $model->subject_type = get_class($object->getSubject()); + $model->subject_id = $object->getSubject()->id; + $model->target_type = get_class($object->getTarget()); + $model->target_id = $object->getTarget()->id; + $model->causer_type = get_class($object->getCauser()); + $model->causer_id = $object->getCauser()->id; + $model->save(); + + return $model; + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Notifications/Services/ListsNotification.php b/app/Classes/Modules/Notifications/Services/ListsNotification.php new file mode 100644 index 00000000..707e7ae8 --- /dev/null +++ b/app/Classes/Modules/Notifications/Services/ListsNotification.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php index 1cf71643..0aa0fb7f 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php @@ -5,6 +5,8 @@ namespace App\Classes\Modules\Transactions\ControllersLogic; use App\Classes\Modules\Transactions\Processors\CreateSupplierTransactionProcessor; use App\Models\Document; +use App\Models\Group; + use Illuminate\Http\Request; use Illuminate\Http\JsonResponse; use Meneses\LaravelMpdf\Facades\LaravelMpdf; @@ -71,6 +73,44 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic if(!count($this->createSupplierTransactionProcessor->getBills())) return $this->response([]); + $group = new Group(); + $group->save(); + + $issuer = ''; + $receiver = ''; + $amount = 0; + $original_amount = 0; + $currency_id = 0; + $original_currency_id = ''; + $currency_rate = ''; + $tax = 0; + $service_charge = 0; + + foreach ($this->createSupplierTransactionProcessor->getBills() as $key => $row) { + $group->transactions()->sync($row->id, false); + $issuer = $row->issuer; + $receiver = $row->receiver; + $amount += $row->amount; + $original_amount += $row->original_amount; + $currency_id = $row->currency_id; + $original_currency_id = $row->original_currency_id; + $currency_rate = $row->currency_rate; + $tax += $row->tax; + $service_charge += $row->service_charge; + } + + $group->issuer = $issuer; + $group->receiver = $receiver; + $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->update(); + $pdf = LaravelMpdf::loadView('pages.pdfs.currency_vendor_order', ['transactions' => $this->createSupplierTransactionProcessor->getBills(), 'transferFeeTransactions' => $this->createSupplierTransactionProcessor->getTransferTransactions(), 'supplier' => $supplier]); $object = new DocumentObject( @@ -85,6 +125,7 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic $document = $this->createsDocument->execute($supplier, $object); $this->createsFile->execute($document, $object); + return $this->response([]); } } diff --git a/app/Classes/Modules/Transactions/ControllersLogic/DeleteGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/DeleteGroupLogic.php new file mode 100644 index 00000000..b19a7159 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/DeleteGroupLogic.php @@ -0,0 +1,72 @@ + 'Delete Group Transaction', + 'message' => 'You have successfully deleted this Group Transaction' + ]; + } + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + /** @var FetchesGroup */ + private $fetchesGroup; + + /** @var DeletesTransaction */ + private $deletesTransaction; + + public function __construct( + UpdatesTransactionStatus $updatesTransactionStatus, + FetchesGroup $fetchesGroup, + DeletesTransaction $deletesTransaction + ) + { + $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->fetchesGroup = $fetchesGroup; + $this->deletesTransaction = $deletesTransaction; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $group = $this->fetchesGroup->execute(['id' => $request->route('id')]); + + $items = $group->transactions()->get(); + + foreach($items as $item) { + $bill = $item; + $payment = $bill->owner; + $group->transactions()->detach($bill->id); + $this->updatesTransactionStatus->execute($payment, ApprovalStatus::APPROVED); + $this->deletesTransaction->execute($bill); + } + + $group->delete(); + + return $this->resourceResponse(new GroupResource($group)); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/ControllersLogic/ListGroupsLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ListGroupsLogic.php new file mode 100644 index 00000000..5cf99bbe --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/ListGroupsLogic.php @@ -0,0 +1,42 @@ +listsGroups = $listsGroups; + } + + /** + * @return array + */ + protected function notification():array { + return [ + 'title' => 'Retrieved Groups', + 'message' => 'You have successfully retrieved a list of groups' + ]; + } + + /** @var ListsGroups */ + private $listsGroups; + + public function logic(Request $request) : JsonResponse + { + $query = $this->listsGroups->execute($this->listsGroups->deserializeFilters($request->input('filters'))); + + return $this->collectionResponse(GroupResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php new file mode 100644 index 00000000..e353f06a --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php @@ -0,0 +1,141 @@ + 'Update Group Transaction', + 'message' => 'You have successfully updated this Group Transaction' + ]; + } + + /** @var FetchesGroup */ + private $fetchesGroup; + + /** @var FetchesCompany */ + private $fetchesCompany; + + /** @var CalculatesTransactionServiceCharge */ + private $calculatesTransactionServiceCharge; + + /** @var UpdatesTransaction */ + private $updatesTransaction; + + /** @var CalculatesTransactionTransferFee */ + private $calculatesTransactionTransferFee; + + public function __construct( + FetchesGroup $fetchesGroup, + FetchesCompany $fetchesCompany, + CalculatesTransactionServiceCharge $calculatesTransactionServiceCharge, + UpdatesTransaction $updatesTransaction, + CalculatesTransactionTransferFee $calculatesTransactionTransferFee + ) + { + $this->fetchesGroup = $fetchesGroup; + $this->fetchesCompany = $fetchesCompany; + $this->calculatesTransactionServiceCharge = $calculatesTransactionServiceCharge; + $this->updatesTransaction = $updatesTransaction; + $this->calculatesTransactionTransferFee = $calculatesTransactionTransferFee; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $group = $this->fetchesGroup->execute(['id' => $request->route('id')]); + + $transactions = $group->transactions()->get(); + + $rate = $request->input('rate'); + + $supplier = $this->fetchesCompany->execute(['id' => $request->input('supplier_id')]); + + foreach($transactions as $transaction) { + + $constant = SegmentConstant::where('reference', SegmentConstants::SERVICE_CHARGE)->where('detail->id', $supplier->id)->first(); + $serviceCharge = $this->calculatesTransactionServiceCharge->execute($transaction->original_amount, $rate, $constant); + + $object = new TransactionObject( + $transaction->bill_no, + TransactionType::BILL, + $supplier->id, + 1, + $supplier->banks()->where('default', true)->first()->id, + PaymentMethodType::CASH, + $transaction->original_amount * (1 / $rate), + $transaction->original_amount, + 1, + $transaction->original_currency_id, + $rate, + 0, + $serviceCharge, + null, + ApprovalStatus::PENDING_VERIFICATION + ); + + $billTransaction = $this->updatesTransaction->execute($transaction, $object); + + $transferTransaction = $transaction->transactions()->where('type', TransactionType::TRANSFER_FEE)->first(); + + $transferFee = $this->calculatesTransactionTransferFee->execute($billTransaction->amount, $constant); + + $object = new TransactionObject( + $transferTransaction->bill_no, + TransactionType::TRANSFER_FEE, + 1, + $supplier->id, + $supplier->banks()->where('default', true)->first()->id, + PaymentMethodType::CASH, + $transaction->original_amount, + $transaction->original_amount, + $transaction->original_currency_id, + $transaction->original_currency_id, + 1, + 0, + $transferFee, + null, + ApprovalStatus::PENDING_VERIFICATION + ); + + $this->updatesTransaction->execute($transferTransaction, $object); + } + + $group->issuer = $supplier; + $group->amount = $group->transactions()->sum('amount'); + $group->currency_rate = $rate; + $group->tax = $group->transactions()->sum('tax'); + $group->service_charge = $group->transactions()->sum('service_charge'); + + $group->save(); + + return $this->resourceResponse(new GroupResource($group)); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/Processors/CreateCashBackTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateCashBackTransactionProcessor.php new file mode 100644 index 00000000..738cb2b7 --- /dev/null +++ b/app/Classes/Modules/Transactions/Processors/CreateCashBackTransactionProcessor.php @@ -0,0 +1,122 @@ +createsTransaction = $createsTransaction; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->creditWalletProcessor = $creditWalletProcessor; + } + + + /** + * @param Transaction $transaction + * @return Transaction|\Illuminate\Database\Eloquent\Model + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(Transaction $transaction) + { + // leave this disabled until ready to launch to production + return; + // ((MYR) * (cash back %)) * (1/conversion rate) + $current_total_cash_back = Transaction:: + where('type', TransactionType::CASH_BACK) + ->whereMonth('created_at', Carbon::now()->month)->sum('amount'); + + if ( + $current_total_cash_back < CashBack::MAX && + $transaction->owner()->first()->transactions()->where('type', TransactionType::PURCHASE_ORDER)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->count() > 0 + ) { + + $cash_back_segemnt = CashBack::SEGMENT; + + foreach ($cash_back_segemnt as $key => $row) { + if ($row['max_value'] > $transaction->amount && $row['min_value'] <= $transaction->amount) { + + $method = $this->getRandomWeightedElement($row['weight']); + + $total = $transaction->amount * $row['percent'][$method]; + + $billNumber = $this->generatesTransactionBillNumber->execute('CBACK-'); + + $object = new TransactionObject( + $billNumber, + TransactionType::CASH_BACK, + $transaction->issuer, + 1, + 1, + PaymentMethodType::WALLET, + $total, + $total, + $transaction->currency_id, + $transaction->currency_id, + 1, + 0, + 0, + null, + ApprovalStatus::APPROVED, + null, + 'cash back ' . $transaction->bill_no + ); + + $cash_back_transaction = $this->createsTransaction->execute($transaction, $object); + + $company = $transaction->owner()->first()->company; + $credit = $this->creditWalletProcessor->execute($company, $transaction->type, $cash_back_transaction->amount, 'cash back ' . $transaction->bill_no); + } + } + } + return $transaction; + } + + public function getRandomWeightedElement(array $weightedValues) { + $rand = mt_rand(1, (int) array_sum($weightedValues)); + foreach ($weightedValues as $key => $value) { + $rand -= $value; + if ($rand <= 0) { + return $key; + } + } + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/Processors/CreateInvoiceDocumentProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateInvoiceDocumentProcessor.php new file mode 100644 index 00000000..39b42576 --- /dev/null +++ b/app/Classes/Modules/Transactions/Processors/CreateInvoiceDocumentProcessor.php @@ -0,0 +1,49 @@ +createsDocument = $createsDocument; + $this->createsFile = $createsFile; + } + + /** + * @return void + */ + public function execute($transaction, $purchaseOrder, $supplier, $document_type) + { + $lowercaseDocumentType = strtolower($document_type); + + $order_pdf = LaravelMpdf::loadView('pages.pdfs.' . $lowercaseDocumentType, ['transaction' => $transaction, 'po_order_transaction' => $purchaseOrder, 'supplier' => $supplier]); + $document_object = new DocumentObject( + $document_type, + [chunk_split('data:application/pdf;base64,' . base64_encode($order_pdf->output()))], + '', + ApprovalStatus::COMPLETED, + $lowercaseDocumentType . 's' + ); + + $document = $this->createsDocument->execute($purchaseOrder->booking, $document_object); + $this->createsFile->execute($document, $document_object); + } +} diff --git a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php index 5a29a1a2..5b7987b4 100644 --- a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php @@ -11,20 +11,14 @@ use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; use App\Classes\Modules\Bookings\Services\CalculatesBookingPaidAmount; use App\Classes\Modules\Bookings\Services\CalculatesBookingCurrencyAverageRate; use App\Classes\Modules\Companies\Services\FetchesCompany; -use App\Classes\Modules\Documents\Services\CreatesDocument; -use App\Classes\Modules\Documents\Services\CreatesFiles; use App\Classes\Modules\Bookings\Services\UpdatesBookingStatus; - use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; -use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject; 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\Models\Booking; -use App\Models\Document; use App\Models\SegmentConstant; -use Meneses\LaravelMpdf\Facades\LaravelMpdf; class CreateInvoiceTransactionProcessor { @@ -55,15 +49,12 @@ class CreateInvoiceTransactionProcessor /** @var FetchesCompany */ private $fetchesCompany; - /** @var CreatesDocument */ - private $createsDocument; - - /** @var CreatesFiles */ - private $createsFile; - /** @var UpdatesBookingStatus */ private $updatesBookingStatus; + /** @var CreateInvoiceDocumentProcessor */ + private $invoiceDocumentProcessor; + /** * CreateInvoiceTransactionProcessor constructor. * @param ListsTransactions $listsTransactions @@ -75,11 +66,10 @@ class CreateInvoiceTransactionProcessor * @param FetchesServiceConfigurations $fetchesServiceConfigurations * @param CalculatesBookingCurrencyAverageRate $calculatesBookingCurrencyAverageRate * @param FetchesCompany $fetchesCompany - * @param CreatesDocument $createsDocument - * @param CreatesFiles $createsFile * @param UpdatesBookingStatus $updatesBookingStatus + * @param CreateInvoiceDocumentProcessor $invoiceDocumentProcessor */ - public function __construct(ListsTransactions $listsTransactions, CreatesTransaction $createsTransaction, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CalculatesBookingPaidAmount $calculatesBookingPaidAmount, CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingTransferredAmount $calculatesBookingTransferredAmount, FetchesServiceConfigurations $fetchesServiceConfigurations, CalculatesBookingCurrencyAverageRate $calculatesBookingCurrencyAverageRate, FetchesCompany $fetchesCompany, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesBookingStatus $updatesBookingStatus) + public function __construct(ListsTransactions $listsTransactions, CreatesTransaction $createsTransaction, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CalculatesBookingPaidAmount $calculatesBookingPaidAmount, CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingTransferredAmount $calculatesBookingTransferredAmount, FetchesServiceConfigurations $fetchesServiceConfigurations, CalculatesBookingCurrencyAverageRate $calculatesBookingCurrencyAverageRate, FetchesCompany $fetchesCompany, UpdatesBookingStatus $updatesBookingStatus, CreateInvoiceTransactionProcessor $invoiceDocumentProcessor) { $this->listsTransactions = $listsTransactions; $this->createsTransaction = $createsTransaction; @@ -90,18 +80,16 @@ class CreateInvoiceTransactionProcessor $this->fetchesServiceConfigurations = $fetchesServiceConfigurations; $this->calculatesBookingCurrencyAverageRate = $calculatesBookingCurrencyAverageRate; $this->fetchesCompany = $fetchesCompany; - $this->createsDocument = $createsDocument; - $this->createsFile = $createsFile; $this->updatesBookingStatus = $updatesBookingStatus; + $this->invoiceDocumentProcessor = $invoiceDocumentProcessor; } - /** * @param Booking $booking * @return void * @throws \App\Classes\Exceptions\MalformedRequestException */ - public function execute(Booking $booking) + public function execute(Booking $booking) { if ($booking->status === ApprovalStatus::COMPLETED) { @@ -116,18 +104,18 @@ class CreateInvoiceTransactionProcessor return; } // confirm that all payments has been transferred - if($this->calculatesBookingTransferredAmount->execute($booking) !== $this->calculatesBookingPaidAmount->execute($booking)){ + if ($this->calculatesBookingTransferredAmount->execute($booking) !== $this->calculatesBookingPaidAmount->execute($booking)) { return; } - $po_order_transaction = $booking->transactions() + $purchaseOrder = $booking->transactions() ->where('type', TransactionType::PURCHASE_ORDER) ->complete() ->first(); $constants = SegmentConstant::where('reference', SegmentConstants::SERVICE_TYPE)->where('detail->id', $booking->service->id)->first(); - if($constants->detail->is_billable && !$po_order_transaction) { + if ($constants->detail->is_billable && !$purchaseOrder) { return; } @@ -166,46 +154,18 @@ class CreateInvoiceTransactionProcessor null, ApprovalStatus::APPROVED ); - $invoice_transaction = $this->createsTransaction->execute($po_order_transaction->booking, $transaction_object); + $invoice_transaction = $this->createsTransaction->execute($purchaseOrder->booking, $transaction_object); $supplier = $this->fetchesCompany->execute(['id' => $transaction->receiver]); - $purchase_order_pdf = LaravelMpdf::loadView('pages.pdfs.purchase_order', ['invoice_transaction' => $invoice_transaction, 'po_order_transaction' => $po_order_transaction, 'supplier' => $supplier]); - $document_object = new DocumentObject( - DocumentType::PURCHASE_ORDER, - [chunk_split('data:application/pdf;base64,'.base64_encode($purchase_order_pdf->output()))], - '', - ApprovalStatus::COMPLETED, - 'purchase_orders' - ); - /** @var Document $document */ - $document = $this->createsDocument->execute($po_order_transaction->booking, $document_object); - $this->createsFile->execute($document, $document_object); + // purchase order + $this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::PURCHASE_ORDER); - $deliver_order_pdf = LaravelMpdf::loadView('pages.pdfs.deliver_order', ['invoice_transaction' => $invoice_transaction, 'po_order_transaction' => $po_order_transaction, 'supplier' => $supplier]); - $document_object = new DocumentObject( - DocumentType::DELIVER_ORDER, - [chunk_split('data:application/pdf;base64,'.base64_encode($deliver_order_pdf->output()))], - '', - ApprovalStatus::COMPLETED, - 'delivery_orders' - ); + // deliver order + $this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::DELIVER_ORDER); - /** @var Document $document */ - $document = $this->createsDocument->execute($po_order_transaction->booking, $document_object); - $this->createsFile->execute($document, $document_object); - - - $invoice_pdf = LaravelMpdf::loadView('pages.pdfs.invoice', ['invoice_transaction' => $invoice_transaction, 'po_order_transaction' => $po_order_transaction, 'supplier' => $supplier]); - $document_object = new DocumentObject( - DocumentType::INVOICE, - [chunk_split('data:application/pdf;base64,'.base64_encode($invoice_pdf->output()))], - '', - ApprovalStatus::COMPLETED, - 'invoices' - ); - $document = $this->createsDocument->execute($po_order_transaction->booking, $document_object); - $this->createsFile->execute($document, $document_object); + // invoice + $this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::INVOICE); $billNumber = $this->generatesTransactionBillNumber->execute('SPDO-'); @@ -231,18 +191,10 @@ class CreateInvoiceTransactionProcessor null, ApprovalStatus::APPROVED ); - $supplier_deliver_order_transaction = $this->createsTransaction->execute($po_order_transaction->booking, $transaction_object); + $supplier_deliver_order_transaction = $this->createsTransaction->execute($purchaseOrder->booking, $transaction_object); - $supplier_order_pdf = LaravelMpdf::loadView('pages.pdfs.supplier_deliver_order', ['supplier_deliver_order_transaction' => $supplier_deliver_order_transaction, 'po_order_transaction' => $po_order_transaction, 'supplier' => $supplier]); - $document_object = new DocumentObject( - DocumentType::SUPPLIER_DELIVER_ORDER, - [chunk_split('data:application/pdf;base64,'.base64_encode($supplier_order_pdf->output()))], - '', - ApprovalStatus::COMPLETED, - 'supplier_delivery_orders' - ); - $document = $this->createsDocument->execute($po_order_transaction->booking, $document_object); - $this->createsFile->execute($document, $document_object); + // supply deliver order + $this->invoiceDocumentProcessor->execute($supplier_deliver_order_transaction, $purchaseOrder, $supplier, DocumentType::SUPPLIER_DELIVER_ORDER); $this->updatesBookingStatus->execute($booking, ApprovalStatus::COMPLETED); } diff --git a/app/Classes/Modules/Transactions/Services/CalculatesTransactionServiceCharge.php b/app/Classes/Modules/Transactions/Services/CalculatesTransactionServiceCharge.php index 29751d80..695b465e 100644 --- a/app/Classes/Modules/Transactions/Services/CalculatesTransactionServiceCharge.php +++ b/app/Classes/Modules/Transactions/Services/CalculatesTransactionServiceCharge.php @@ -25,15 +25,18 @@ class CalculatesTransactionServiceCharge * @param SegmentConstant|null $service_charge * @return float */ - public function execute(float $amount, float $rate, ?SegmentConstant $service_charge) { + public function execute(float $amount, float $rate, ?SegmentConstant $service_charge) + { - if(!$service_charge) { + if (!$service_charge) { return 0; } $transfer_fee = $this->calculatesTransactionTransferFee->execute(($amount * (1 / $rate)), $service_charge); - return $service_charge->detail->amount->type === 'percentage' ? (($amount + $transfer_fee) * ( (float) $service_charge->detail->amount->value /100) * (1/$rate)) : (float) $service_charge->detail->amount->value; - + if (isset($service_charge->detail->amount)) { + return $service_charge->detail->amount->type === 'percentage' ? (($amount + $transfer_fee) * ((float) $service_charge->detail->amount->value / 100) * (1 / $rate)) : (float) $service_charge->detail->amount->value; + } else { + return 0; + } } - -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Transactions/Services/CalculatesTransactionTransferFee.php b/app/Classes/Modules/Transactions/Services/CalculatesTransactionTransferFee.php index 5a02a394..0bcaba28 100644 --- a/app/Classes/Modules/Transactions/Services/CalculatesTransactionTransferFee.php +++ b/app/Classes/Modules/Transactions/Services/CalculatesTransactionTransferFee.php @@ -12,13 +12,17 @@ class CalculatesTransactionTransferFee * @param SegmentConstant|null $service_charge * @return float */ - public function execute(float $amount, ?SegmentConstant $service_charge) { + public function execute(float $amount, ?SegmentConstant $service_charge) + { - if(!$service_charge) { + if (!$service_charge) { return 0; } - return $service_charge->detail->transferFee->type === 'percentage' ? $amount * ((float) $service_charge->detail->transferFee->value /100) : (float) $service_charge->detail->transferFee->value; + if (isset($service_charge->detail->transferFee)) { + return $service_charge->detail->transferFee->type === 'percentage' ? $amount * ((float) $service_charge->detail->transferFee->value / 100) : (float) $service_charge->detail->transferFee->value; + } else { + return 0; + } } - -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Transactions/Services/FetchesGroup.php b/app/Classes/Modules/Transactions/Services/FetchesGroup.php new file mode 100644 index 00000000..6533664b --- /dev/null +++ b/app/Classes/Modules/Transactions/Services/FetchesGroup.php @@ -0,0 +1,31 @@ +repository = $repository; + } + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Transactions/Services/ListsGroups.php b/app/Classes/Modules/Transactions/Services/ListsGroups.php new file mode 100644 index 00000000..f9126739 --- /dev/null +++ b/app/Classes/Modules/Transactions/Services/ListsGroups.php @@ -0,0 +1,31 @@ +repository = $repository; + } + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Wallets/Processors/CreditWalletProcessor.php b/app/Classes/Modules/Wallets/Processors/CreditWalletProcessor.php index d86a4465..65f3b9b6 100644 --- a/app/Classes/Modules/Wallets/Processors/CreditWalletProcessor.php +++ b/app/Classes/Modules/Wallets/Processors/CreditWalletProcessor.php @@ -78,7 +78,7 @@ class CreditWalletProcessor $transaction_object = new TransactionObject($billNumber, $transactionType === 2 ? TransactionType::DEBIT_NOTE : TransactionType::CREDIT_NOTE, 1, $wallet->owner->id, 1, PaymentMethodType::CASH, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], $reference); $transaction = $this->createsTransaction->execute($wallet, $transaction_object); - + $updateWalletAmount = $transactionType === 2 ? ($wallet->amount - $transaction->amount) : ($wallet->amount + $transaction->amount); $walletObject = new WalletObject($wallet->owner->id, $wallet->currency_id, $wallet->code, $updateWalletAmount); diff --git a/app/Classes/ValueObjects/Constants/CashBack.php b/app/Classes/ValueObjects/Constants/CashBack.php new file mode 100644 index 00000000..0fdc3df9 --- /dev/null +++ b/app/Classes/ValueObjects/Constants/CashBack.php @@ -0,0 +1,55 @@ + [ + 'min_value' => 0, + 'max_value' => 2000, + 'weight' => [ + '0' => 80, + '1' => 18, + '2' => 2, + ], + 'percent' => [ + '0' => 0.002, + '1' => 0.005, + '2' => 0.02, + ] + ], + '1' => [ + 'min_value' => 2001, + 'max_value' => 10000, + 'weight' => [ + '0' => 85, + '1' => 10, + '2' => 5, + ], + 'percent' => [ + '0' => 0.002, + '1' => 0.005, + '2' => 0.02, + ] + ], + '2' => [ + 'min_value' => 10001, + 'max_value' => 100000, + 'weight' => [ + '0' => 70, + '1' => 20, + '2' => 10, + ], + 'percent' => [ + '0' => 0.002, + '1' => 0.005, + '2' => 0.02, + ] + ], + ]; +} diff --git a/app/Classes/ValueObjects/Constants/TransactionType.php b/app/Classes/ValueObjects/Constants/TransactionType.php index 4814ac04..026f25ba 100644 --- a/app/Classes/ValueObjects/Constants/TransactionType.php +++ b/app/Classes/ValueObjects/Constants/TransactionType.php @@ -29,4 +29,6 @@ final class TransactionType { public const WITHDRAW = 10; public const TRANSFER_FEE = 12; + + public const CASH_BACK = 13; } diff --git a/app/Http/Controllers/Bookings/DownloadBookingDocumentController.php b/app/Http/Controllers/Bookings/DownloadBookingDocumentController.php index d2a7d85c..95427363 100644 --- a/app/Http/Controllers/Bookings/DownloadBookingDocumentController.php +++ b/app/Http/Controllers/Bookings/DownloadBookingDocumentController.php @@ -15,7 +15,7 @@ class DownloadBookingDocumentController * @throws \App\Classes\Exceptions\MalformedRequestException */ public function download(Request $request, DownloadBookingDocumentLogic $logic) { - $logic->execute($request); + return $logic->execute($request); } } \ No newline at end of file diff --git a/app/Http/Controllers/Companies/UpdateCompanyStatusController.php b/app/Http/Controllers/Companies/UpdateCompanyStatusController.php new file mode 100644 index 00000000..43b3ba3c --- /dev/null +++ b/app/Http/Controllers/Companies/UpdateCompanyStatusController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Exports/ExportCustomersToExcelController.php b/app/Http/Controllers/Exports/ExportCustomersToExcelController.php index 39ea3dc5..8563f78a 100644 --- a/app/Http/Controllers/Exports/ExportCustomersToExcelController.php +++ b/app/Http/Controllers/Exports/ExportCustomersToExcelController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers\Exports; use App\Classes\Modules\Exports\Services\ExportsCustomers; use App\Classes\Modules\Exports\Services\ExportsTransactions; +use App\Classes\Modules\Exports\Services\ExportsBookingTransactions; use App\Classes\Modules\Exports\Services\ExportsNullDebtors; use App\Classes\Modules\Exports\Services\ExportsPaymentTransactions; @@ -54,4 +55,10 @@ class ExportCustomersToExcelController ob_end_clean(); return $response; } + + public function bookingTransactions(ExportsBookingTransactions $exportsBookingTransactions, Request $request){ + $response = $exportsBookingTransactions->download('bookingTransactions.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']); + ob_end_clean(); + return $response; + } } \ No newline at end of file diff --git a/app/Http/Controllers/Notifications/ListNotificationsController.php b/app/Http/Controllers/Notifications/ListNotificationsController.php new file mode 100644 index 00000000..58455fc2 --- /dev/null +++ b/app/Http/Controllers/Notifications/ListNotificationsController.php @@ -0,0 +1,19 @@ +execute($request); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Transactions/DeleteGroupController.php b/app/Http/Controllers/Transactions/DeleteGroupController.php new file mode 100644 index 00000000..14ba54f9 --- /dev/null +++ b/app/Http/Controllers/Transactions/DeleteGroupController.php @@ -0,0 +1,20 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/ListGroupsController.php b/app/Http/Controllers/Transactions/ListGroupsController.php new file mode 100644 index 00000000..730633e9 --- /dev/null +++ b/app/Http/Controllers/Transactions/ListGroupsController.php @@ -0,0 +1,21 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/UpdateGroupController.php b/app/Http/Controllers/Transactions/UpdateGroupController.php new file mode 100644 index 00000000..db0b3a17 --- /dev/null +++ b/app/Http/Controllers/Transactions/UpdateGroupController.php @@ -0,0 +1,20 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Wallets/WalletReportController.php b/app/Http/Controllers/Wallets/WalletReportController.php new file mode 100644 index 00000000..998bba53 --- /dev/null +++ b/app/Http/Controllers/Wallets/WalletReportController.php @@ -0,0 +1,29 @@ + [ + 'walletSum' => (float) Wallet::all()->sum('amount'), + 'outgoingSum' => (float) Transaction::where('type', TransactionType::PAYMENT)->where('owner_type', Wallet::class)->sum('amount'), + 'incomingSum' => (float) Transaction::whereIn('type', [TransactionType::TOP_UP, TransactionType::CREDIT_NOTE])->where('owner_type', Wallet::class)->sum('amount'), + ]] + ))->handler(); + } +} diff --git a/app/Http/Resources/BookingResource.php b/app/Http/Resources/BookingResource.php index 0eeb9670..0adfa65d 100644 --- a/app/Http/Resources/BookingResource.php +++ b/app/Http/Resources/BookingResource.php @@ -31,6 +31,7 @@ class BookingResource extends JsonResource 'service' => new ServiceTypeResource($this->service), 'marking' => $this->marking, 'amount' => $this->fix_amount, + 'amount' => $this->fix_amount, 'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)), 'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), diff --git a/app/Http/Resources/GroupResource.php b/app/Http/Resources/GroupResource.php new file mode 100644 index 00000000..2d628d19 --- /dev/null +++ b/app/Http/Resources/GroupResource.php @@ -0,0 +1,29 @@ + $this->id, + 'original_amount' => (double) $this->original_amount, + 'original_currency' => new CurrencyResource($this->original_currency), + 'amount' => (double) $this->amount, + 'currency' => new CurrencyResource($this->currency), + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), + 'currency_rate' => (float) $this->currency_rate, + 'transactions' => TransactionResource::collection($this->transactions()->get()), + ]; + } +} diff --git a/app/Http/Resources/NotificationResource.php b/app/Http/Resources/NotificationResource.php new file mode 100644 index 00000000..564b7b31 --- /dev/null +++ b/app/Http/Resources/NotificationResource.php @@ -0,0 +1,30 @@ + $this->id, + 'title' => $this->title, + 'description' => $this->description, + 'long_ago' => $this->created_at->diffForHumans(), + 'created_at' => $this->created_at->format('d-m-Y') + ]; + + } +} diff --git a/app/Http/Resources/TransactionResource.php b/app/Http/Resources/TransactionResource.php index 30ba223c..e35dcc36 100644 --- a/app/Http/Resources/TransactionResource.php +++ b/app/Http/Resources/TransactionResource.php @@ -30,6 +30,7 @@ class TransactionResource extends JsonResource 'payment_method' => (float) $this->payment_method, 'recipient_bank_account' => new BankResource($booking->bank), 'issuer_name' => $this->issuerCompany->name, + 'issuer_id' => $this->issuerCompany->id, 'amount' => (double) $this->amount, 'original_amount' => (double) $this->original_amount, 'currency' => new CurrencyResource($this->currency), diff --git a/app/Models/AbstractModel.php b/app/Models/AbstractModel.php index 7a7c9c06..47d8754b 100644 --- a/app/Models/AbstractModel.php +++ b/app/Models/AbstractModel.php @@ -3,11 +3,37 @@ namespace App\Models; +use App\Classes\General\Interfaces\Notifiable; use Illuminate\Database\Eloquent\Model; use Spatie\Activitylog\Traits\LogsActivity; +use Illuminate\Database\Eloquent\Relations\MorphTo; -class AbstractModel extends Model +class AbstractModel extends Model implements Notifiable { use LogsActivity; protected static $logFillable = true; + + /** + * @return MorphTo + */ + public function subject(): MorphTo + { + return $this->MorphTo('subject'); + } + + /** + * @return MorphTo + */ + public function target(): MorphTo + { + return $this->MorphTo('target'); + } + + /** + * @return MorphTo + */ + public function causer(): MorphTo + { + return $this->MorphTo('causer'); + } } \ No newline at end of file diff --git a/app/Models/BankLog.php b/app/Models/BankLog.php new file mode 100644 index 00000000..a516d151 --- /dev/null +++ b/app/Models/BankLog.php @@ -0,0 +1,10 @@ +belongsToMany(Transaction::class, GroupTransaction::class); + } + + /** + * @return BelongsTo + */ + public function currency(): BelongsTo + { + return $this->BelongsTo(Currency::class, 'currency_id', 'id'); + } + + /** + * @return BelongsTo + */ + public function original_currency(): BelongsTo + { + return $this->BelongsTo(Currency::class, 'original_currency_id', 'id'); + } +} diff --git a/app/Models/GroupTransaction.php b/app/Models/GroupTransaction.php new file mode 100644 index 00000000..9ab72d18 --- /dev/null +++ b/app/Models/GroupTransaction.php @@ -0,0 +1,27 @@ +BelongsTo(Group::class, 'group_id', 'id'); + } + + /** + * @return BelongsTo + */ + public function transaction(): BelongsTo + { + return $this->BelongsTo(Transaction::class, 'transaction_id', 'id'); + } +} diff --git a/app/Models/Notification.php b/app/Models/Notification.php new file mode 100644 index 00000000..06bd6024 --- /dev/null +++ b/app/Models/Notification.php @@ -0,0 +1,18 @@ +BelongsTo(Package::class, 'package_id', 'id'); + } +} diff --git a/composer.json b/composer.json index 32f52d83..32305073 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "require": { "php": "^7.2.5", "ext-fileinfo": "*", - "ext-json": "^1.6", + "ext-json": "*", "ext-zip": "*", "barryvdh/laravel-dompdf": "^0.9.0", "carlos-meneses/laravel-mpdf": "^2.1", @@ -31,6 +31,7 @@ "require-dev": { "facade/ignition": "^2.0", "fzaninotto/faker": "^1.9.1", + "laravel/dusk": "^6.23", "mockery/mockery": "^1.3.1", "nunomaduro/collision": "^4.1", "phpunit/phpunit": "^8.5" diff --git a/config/database.php b/config/database.php index aeabec6f..ac0b718b 100644 --- a/config/database.php +++ b/config/database.php @@ -63,6 +63,26 @@ return [ ]) : [], ], + 'dusk' => [ + 'driver' => 'mysql', + 'url' => env('DATABASE_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '3306'), + 'database' => env('DB_DATABASE', 'forge'), + 'username' => env('DB_USERNAME', 'forge'), + 'password' => env('DB_PASSWORD', ''), + 'unix_socket' => env('DB_SOCKET', ''), + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_unicode_ci', + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => false, + 'engine' => null, + 'options' => extension_loaded('pdo_mysql') ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + ]) : [], + ], + 'pgsql' => [ 'driver' => 'pgsql', 'url' => env('DATABASE_URL'), diff --git a/database/migrations/2022_03_20_170628_create_groups_table.php b/database/migrations/2022_03_20_170628_create_groups_table.php new file mode 100644 index 00000000..596a6ed5 --- /dev/null +++ b/database/migrations/2022_03_20_170628_create_groups_table.php @@ -0,0 +1,40 @@ +id(); + $table->foreignId('issuer')->unsigned(); + $table->foreignId('receiver')->unsigned(); + $table->decimal('amount', 14, 5)->default(0.00); + $table->decimal('original_amount', 14, 5)->default(0.00); + $table->foreignId('currency_id')->unsigned(); + $table->foreignId('original_currency_id')->unsigned(); + $table->decimal('currency_rate', 14, 5)->default(0.00); + $table->decimal('tax', 14, 5)->default(0.00); + $table->decimal('service_charge', 14, 5)->default(0.00); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('groups'); + } +} diff --git a/database/migrations/2022_03_20_170641_create_group_transactions_table.php b/database/migrations/2022_03_20_170641_create_group_transactions_table.php new file mode 100644 index 00000000..53f33356 --- /dev/null +++ b/database/migrations/2022_03_20_170641_create_group_transactions_table.php @@ -0,0 +1,32 @@ +id(); + $table->foreignId('group_id')->unsigned(); + $table->foreignId('transaction_id')->unsigned(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('group_transactions'); + } +} diff --git a/database/migrations/2022_04_03_225513_create_bank_logs_table.php b/database/migrations/2022_04_03_225513_create_bank_logs_table.php new file mode 100644 index 00000000..02fecbd3 --- /dev/null +++ b/database/migrations/2022_04_03_225513_create_bank_logs_table.php @@ -0,0 +1,51 @@ +id(); + $table->foreignId('bank_id')->unsigned(); + $table->foreignId('company_id')->unsigned(); + $table->string('reference')->nullable(); + $table->string('bank_name'); + $table->string('holder_name'); + $table->string('account_no'); + $table->string('bank_branch')->nullable(); + $table->string('swift')->nullable(); + $table->string('snap')->nullable(); + $table->integer('type')->default(BankAccountType::EXTERNAL); + $table->integer('default')->default(false); + $table->integer('status')->default(ApprovalStatus::APPROVED); + $table->foreignId('country_id')->unsigned(); + $table->softDeletes(); + $table->timestamps(); + + $table->foreign('bank_id')->references('id')->on('banks'); + $table->foreign('country_id')->references('id')->on('countries'); + $table->foreign('company_id')->references('id')->on('companies'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('bank_logs'); + } +} diff --git a/database/migrations/2022_04_15_211421_create_notifications_table.php b/database/migrations/2022_04_15_211421_create_notifications_table.php new file mode 100644 index 00000000..d14cdc89 --- /dev/null +++ b/database/migrations/2022_04_15_211421_create_notifications_table.php @@ -0,0 +1,40 @@ +id(); + $table->string('title'); + $table->text('description'); + $table->morphs('subject'); + $table->morphs('target'); + $table->morphs('causer'); + $table->integer('status')->default(ApprovalStatus::APPROVED); + $table->softDeletes(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('notifications'); + } +} diff --git a/database/seeds/RecoverGroupTransactionTableSeeder.php b/database/seeds/RecoverGroupTransactionTableSeeder.php new file mode 100644 index 00000000..ac1f01d7 --- /dev/null +++ b/database/seeds/RecoverGroupTransactionTableSeeder.php @@ -0,0 +1,80 @@ +get(); + $transaction_group = Transaction:: + select('issuer', 'currency_rate', 'type', DB::raw('count(DISTINCT id) as total'), DB::raw("DATE_FORMAT(created_at, '%Y-%m-%d %H:%i') as new_date")) + ->where('type', 3) + ->groupBy( + 'issuer', + 'currency_rate', + 'new_date' + ) + ->get(); + + foreach ($transaction_group as $key => $row) { + $transaction = Transaction:: + where('type', 3) + ->where('issuer', $row->issuer) + ->where('currency_rate', $row->currency_rate) + ->where(DB::raw("DATE_FORMAT(created_at, '%Y-%m-%d %H:%i')"), $row->new_date) + ->get(); + + $group = new Group(); + $group->save(); + + $issuer = ''; + $receiver = ''; + $amount = 0; + $original_amount = 0; + $currency_id = 0; + $original_currency_id = ''; + $currency_rate = ''; + $tax = 0; + $service_charge = 0; + + foreach ($transaction as $key_2 => $row_2) { + $group->transaction()->sync($row_2->id, false); + $issuer = $row_2->issuer; + $receiver = $row_2->receiver; + $amount += $row_2->amount; + $original_amount += $row_2->original_amount; + $currency_id = $row_2->currency_id; + $original_currency_id = $row_2->original_currency_id; + $currency_rate = $row_2->currency_rate; + $tax += $row_2->tax; + $service_charge += $row_2->service_charge; + } + + $group->issuer = $issuer; + $group->receiver = $receiver; + $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->update(); + } + + DB::commit(); + } +} diff --git a/resources/assets/sass/modules/_typography.scss b/resources/assets/sass/modules/_typography.scss index 605b8e7c..aa4506a9 100644 --- a/resources/assets/sass/modules/_typography.scss +++ b/resources/assets/sass/modules/_typography.scss @@ -316,6 +316,12 @@ hr{ background-color: $color-primary-lighter !important; } +.bg-primary-lighter-hover { + &:hover { + background-color: $color-primary-lighter !important; + } +} + /* Complete ------------------------------------ */ diff --git a/resources/assets/vue/components/accounts/forms/LoginFormComponent.vue b/resources/assets/vue/components/accounts/forms/LoginFormComponent.vue index ed097c68..5ddfdadb 100644 --- a/resources/assets/vue/components/accounts/forms/LoginFormComponent.vue +++ b/resources/assets/vue/components/accounts/forms/LoginFormComponent.vue @@ -7,13 +7,13 @@
- +
- +
@@ -21,7 +21,7 @@

Forgot password?

-
Sign In
+
Sign In
@@ -55,4 +55,4 @@ mixins: [loginFormValidation] } - \ No newline at end of file + diff --git a/resources/assets/vue/components/accounts/forms/RegistrationFormComponent.vue b/resources/assets/vue/components/accounts/forms/RegistrationFormComponent.vue index 429d0b9a..9f49275e 100644 --- a/resources/assets/vue/components/accounts/forms/RegistrationFormComponent.vue +++ b/resources/assets/vue/components/accounts/forms/RegistrationFormComponent.vue @@ -33,7 +33,7 @@ viewBox="0 0 172 172" style=" fill:#000000;"> -

Company

+

Company

@@ -43,7 +43,7 @@ width="45" height="45" viewBox="0 0 172 172" style=" fill:#000000;">
-

Personal

+

Personal

@@ -62,7 +62,7 @@
- +
@@ -70,13 +70,13 @@
- +
- +
@@ -95,7 +95,7 @@
- +
@@ -103,13 +103,13 @@
- +
- +
@@ -135,7 +135,7 @@
- +
@@ -156,7 +156,7 @@
- +
diff --git a/resources/assets/vue/components/bookings/elements/BillingComponent.vue b/resources/assets/vue/components/bookings/elements/BillingComponent.vue index 70f511ed..f24078ed 100644 --- a/resources/assets/vue/components/bookings/elements/BillingComponent.vue +++ b/resources/assets/vue/components/bookings/elements/BillingComponent.vue @@ -84,7 +84,14 @@ export default { type: 'INVOICE', supplier: null }, - documents: ['INVOICE', 'PURCHASE_ORDER', 'DELIVER_ORDER', 'SUPPLIER_DELIVER_ORDER'], + documents: [ + 'INVOICE', + 'PURCHASE_ORDER', + 'DELIVER_ORDER', + 'SUPPLIER_DELIVER_ORDER', + 'INVOICE + PO + DO', + 'INVOICE + PO + DO + SDO' + ], selectedDocumentStatus: false } }, diff --git a/resources/assets/vue/components/bookings/elements/BookingConfirmationComponent.vue b/resources/assets/vue/components/bookings/elements/BookingConfirmationComponent.vue index b5a2bcd1..e04d0bfb 100644 --- a/resources/assets/vue/components/bookings/elements/BookingConfirmationComponent.vue +++ b/resources/assets/vue/components/bookings/elements/BookingConfirmationComponent.vue @@ -100,7 +100,7 @@
-
+
@@ -115,7 +115,7 @@
-
+
@@ -320,4 +320,4 @@ }, mixins: [FormHandler] } - \ No newline at end of file + diff --git a/resources/assets/vue/components/bookings/elements/CurrencyOrderComponent.vue b/resources/assets/vue/components/bookings/elements/CurrencyOrderComponent.vue index ad4c3e42..a88fd5a9 100644 --- a/resources/assets/vue/components/bookings/elements/CurrencyOrderComponent.vue +++ b/resources/assets/vue/components/bookings/elements/CurrencyOrderComponent.vue @@ -40,7 +40,7 @@
Currency Order Placed
-
Are you sure you that the currency order has been placed with the supplier?
+
Are you sure that the currency order has been placed with the supplier?
diff --git a/resources/assets/vue/components/bookings/elements/DownloadBillingWithDatesComponent.vue b/resources/assets/vue/components/bookings/elements/DownloadBillingWithDatesComponent.vue new file mode 100644 index 00000000..99be4562 --- /dev/null +++ b/resources/assets/vue/components/bookings/elements/DownloadBillingWithDatesComponent.vue @@ -0,0 +1,83 @@ + + + diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index 51352679..abec64a7 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -123,7 +123,7 @@
Requested Refund Amount
-
{{item.original_currency.short_code}} {{(Math.round((totalRequestedRefund + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
{{item.currency.short_code}} {{(Math.round((totalRequestedRefund + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
@@ -219,8 +219,8 @@
-
-
+
+
@@ -249,12 +249,25 @@ }, computed: { totalRequestedRefund() { + let vm = this; var TotalRequestedRefund = 0; this.data.transaction_refunds.forEach(function(refunds) { TotalRequestedRefund += refunds.status === 1 ? refunds.original_amount : 0; }); + return TotalRequestedRefund; }, + totalRequestedConvertRefund() { + let vm = this; + var TotalRequestedRefund = 0; + this.data.transaction_refunds.forEach(function(refunds) { + TotalRequestedRefund += refunds.status === 1 ? refunds.original_amount : 0; + }); + if (vm.data.booking.fixed_currency.id != 1 && this.data.transaction_refunds[0]) { + TotalRequestedRefund = (TotalRequestedRefund * this.data.transaction_refunds[0].currency_rate); + } + return ((Math.round((TotalRequestedRefund + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")); + }, totalRefunds() { var TotalRequestedRefund = 0; this.data.transaction_refunds.forEach(function(refunds) { diff --git a/resources/assets/vue/components/bookings/elements/RefundVerificationComponent.vue b/resources/assets/vue/components/bookings/elements/RefundVerificationComponent.vue index e78a14f6..42d5682e 100644 --- a/resources/assets/vue/components/bookings/elements/RefundVerificationComponent.vue +++ b/resources/assets/vue/components/bookings/elements/RefundVerificationComponent.vue @@ -28,7 +28,7 @@
Amount
- {{(Math.round((data.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}} + {{(Math.round((data.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
diff --git a/resources/assets/vue/components/bookings/elements/TransactionGroupComponent.vue b/resources/assets/vue/components/bookings/elements/TransactionGroupComponent.vue new file mode 100644 index 00000000..51562c23 --- /dev/null +++ b/resources/assets/vue/components/bookings/elements/TransactionGroupComponent.vue @@ -0,0 +1,98 @@ + + + diff --git a/resources/assets/vue/components/bookings/elements/UploadDebtorExcelComponent.vue b/resources/assets/vue/components/bookings/elements/UploadDebtorExcelComponent.vue index 946bafe1..a956a07c 100644 --- a/resources/assets/vue/components/bookings/elements/UploadDebtorExcelComponent.vue +++ b/resources/assets/vue/components/bookings/elements/UploadDebtorExcelComponent.vue @@ -1,31 +1,44 @@