diff --git a/.env.example b/.env.example index 6367c9b8..f3d4fd56 100644 --- a/.env.example +++ b/.env.example @@ -56,5 +56,3 @@ 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" -BILLPLZ_REDIRECT_URL="http://localhost:9003/bookings/billplz" -BILLPLZ_CALLBACK_URL="localhost:9003/api/v1/billplz/callback" \ No newline at end of file diff --git a/app/Classes/General/Eloquent/AbstractUpdateRecord.php b/app/Classes/General/Eloquent/AbstractUpdateRecord.php index 44129c92..17690ce4 100644 --- a/app/Classes/General/Eloquent/AbstractUpdateRecord.php +++ b/app/Classes/General/Eloquent/AbstractUpdateRecord.php @@ -17,7 +17,6 @@ abstract class AbstractUpdateRecord */ public function handler(Model $model){ try{ - if($model->save()){ return $model; } } catch (QueryException $exception){ diff --git a/app/Classes/General/Eloquent/Filters/IsPublished.php b/app/Classes/General/Eloquent/Filters/IsPublished.php index 9b5b23c1..3e9c8ca4 100644 --- a/app/Classes/General/Eloquent/Filters/IsPublished.php +++ b/app/Classes/General/Eloquent/Filters/IsPublished.php @@ -5,7 +5,7 @@ namespace App\Classes\General\Eloquent\Filters; use Carbon\Carbon; use Illuminate\Database\Eloquent\Builder; -class isPublished implements Filter +class IsPublished implements Filter { /** diff --git a/app/Classes/General/Eloquent/Filters/PaymentReference.php b/app/Classes/General/Eloquent/Filters/PaymentReference.php index 10c1fa49..5f5d53f5 100644 --- a/app/Classes/General/Eloquent/Filters/PaymentReference.php +++ b/app/Classes/General/Eloquent/Filters/PaymentReference.php @@ -14,7 +14,7 @@ class PaymentReference implements Filter */ public static function apply(Builder $builder, $value) { - return $builder->where('payment_reference', $value); + return $builder->where('payment_reference', '=', $value); } } \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/WithTotalPayments.php b/app/Classes/General/Eloquent/Filters/WithTotalPayments.php index d93e55e2..9721f8d7 100644 --- a/app/Classes/General/Eloquent/Filters/WithTotalPayments.php +++ b/app/Classes/General/Eloquent/Filters/WithTotalPayments.php @@ -5,6 +5,7 @@ namespace App\Classes\General\Eloquent\Filters; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\TransactionType; +use App\Models\Booking; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\DB; @@ -19,7 +20,7 @@ class WithTotalPayments implements Filter public static function apply(Builder $builder, $value) { return $builder->leftJoin('bookings', 'companies.id', '=', 'bookings.company_id')->rightJoin('transactions', function ($join) { - $join->on('bookings.id', '=', 'transactions.booking_id')->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); - })->addSelect(['companies.*', DB::raw('SUM(transactions.amount) as total_payments')])->groupBy(['companies.id']); + $join->on('bookings.id', '=', 'transactions.owner_id')->where('owner_type', '=', Booking::class)->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + })->addSelect(['companies.*', DB::raw('SUM(transactions.amount) as total_payments'), DB::raw('SUM(transactions.amount / DATEDIFF(companies.created_at, CURRENT_DATE)) as spending_average_per_day'), DB::raw('SUM(transactions.amount) / count(distinct bookings.id) as spending_average_booking')])->groupBy(['companies.id']); } } \ No newline at end of file diff --git a/app/Classes/Modules/Accounts/ControllersLogic/DeleteUserLogic.php b/app/Classes/Modules/Accounts/ControllersLogic/DeleteUserLogic.php index 485e9cf3..e7aa57f8 100644 --- a/app/Classes/Modules/Accounts/ControllersLogic/DeleteUserLogic.php +++ b/app/Classes/Modules/Accounts/ControllersLogic/DeleteUserLogic.php @@ -53,24 +53,18 @@ class DeleteUserLogic extends AbstractControllerLogic /** * @param Request $request * @return JsonResponse - * @throws ErrorException + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException */ public function logic(Request $request) : JsonResponse { - try { - DB::beginTransaction(); + $user = $this->fetchesUser->execute(['id' => $request->route('id')]); + $this->canDeleteUser->passes(); + $this->deletesUser->execute($user); - $user = $this->fetchesUser->execute(['id' => $request->route('id')]); - $this->canDeleteUser->passes(); - $this->deletesUser->execute($user); - - DB::commit(); - return $this->resourceResponse(new UserResource($user)); - - } catch (\Exception $exception){ - throw new ErrorException($exception->getMessage(), $exception->getCode()); - } + return $this->resourceResponse(new UserResource($user)); } } \ No newline at end of file diff --git a/app/Classes/Modules/Accounts/DataTransferObjects/FullNameObject.php b/app/Classes/Modules/Accounts/DataTransferObjects/FullNameObject.php index c17a8b72..59396c54 100644 --- a/app/Classes/Modules/Accounts/DataTransferObjects/FullNameObject.php +++ b/app/Classes/Modules/Accounts/DataTransferObjects/FullNameObject.php @@ -4,7 +4,7 @@ namespace App\Classes\Modules\Accounts\DataTransferObjects; use App\Classes\General\Interfaces\DataTransferObject; -class FullnameObject implements DataTransferObject +class FullNameObject implements DataTransferObject { /** @var string */ private $name; @@ -12,11 +12,6 @@ class FullnameObject implements DataTransferObject /** * UserObject constructor. * @param string $name - * @param string $email - * @param string $password - * @param string $passwordConfirmation - * @param int|null $type - * @param int|null $status */ public function __construct(string $name) { diff --git a/app/Classes/Modules/Addresses/DataTransferObjects/AddressObject.php b/app/Classes/Modules/Addresses/DataTransferObjects/AddressObject.php index 8c164317..48e3bb62 100644 --- a/app/Classes/Modules/Addresses/DataTransferObjects/AddressObject.php +++ b/app/Classes/Modules/Addresses/DataTransferObjects/AddressObject.php @@ -22,7 +22,7 @@ class AddressObject implements DataTransferObject /** @var int */ private $districtId; - /** @var int */ + /** @var string */ private $postCode; /** @@ -32,9 +32,9 @@ class AddressObject implements DataTransferObject * @param int $countryId * @param int $stateId * @param int $districtId - * @param int $postCode + * @param string $postCode */ - public function __construct(string $streetOne, ?string $streetTwo, int $countryId, int $stateId, int $districtId, int $postCode) + public function __construct(string $streetOne, ?string $streetTwo, int $countryId, int $stateId, int $districtId, string $postCode) { $this->streetOne = $streetOne; $this->streetTwo = $streetTwo; @@ -85,9 +85,9 @@ class AddressObject implements DataTransferObject } /** - * @return int + * @return string */ - public function getPostCode(): int + public function getPostCode(): string { return $this->postCode; } diff --git a/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php b/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php index 8dece746..1503f6ee 100644 --- a/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php +++ b/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php @@ -2,8 +2,12 @@ namespace App\Classes\Modules\Billplzs\ControllersLogic; -use ErrorException; +use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject; +use App\Classes\Modules\Wallets\Services\UpdatesWallet; +use App\Classes\Exceptions\ResourceNotFoundException; +use App\Http\Resources\TransactionResource; +use App\Models\User; use Illuminate\Http\Request; use Illuminate\Http\JsonResponse; @@ -14,19 +18,12 @@ use App\Classes\Modules\Billplzs\DataTransferObjects\BillplzXSignatureObject; use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Transactions\Services\FetchesTransaction; use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; +use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Log; -class CallbackBillplzLogic extends AbstractControllerLogic +class CallbackBillplzLogic { - /** - * @return array - */ - protected function notification():array { - return [ - 'title' => 'Callback Billplz', - 'message' => 'You have successfully receive Billplz callback' - ]; - } /** @var GetBillplzBill */ private $getBillplzBill; @@ -37,44 +34,68 @@ class CallbackBillplzLogic extends AbstractControllerLogic /** @var UpdatesTransactionStatus */ private $updatesTransactionStatus; + /** @var UpdatesWallet */ + private $updatesWallet; /** * CreateBookingLogic constructor. - * @param CreateGetBillplzBillsBillplzBill $getBillplzBill + * @param GetBillplzBill $getBillplzBill * @param FetchesTransaction $fetchesTransaction * @param UpdatesTransactionStatus $updatesTransactionStatus */ - public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus) + public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdatesWallet $updatesWallet) { $this->getBillplzBill = $getBillplzBill; $this->fetchesTransaction = $fetchesTransaction; $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->updatesWallet = $updatesWallet; } /** * @param Request $request - * @return JsonResponse - * @throws \App\Classes\Exceptions\AccessForbiddenException - * @throws \App\Classes\Exceptions\MalformedRequestException - * @throws \App\Classes\Exceptions\RequestValidationException + * @return bool|\Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @throws MalformedRequestException + * @throws ResourceNotFoundException */ - public function logic(Request $request) : JsonResponse + public function execute(Request $request) { - $billplzXSignatureObject = new BillplzXSignatureObject($request); - if(!$billplzXSignatureObject->isValidSignature()) throw new MalformedRequestException('Unable to get correct response from billplz server.'); + if(!$billplzXSignatureObject->isValidSignature()){ + throw new MalformedRequestException('Billplz Payment validation failed.'); + } $billPlz = $this->getBillplzBill->execute($billplzXSignatureObject->getBillPlzId()); - if(!$billPlz) throw new MalformedRequestException('Unable to get correct response from billplz server.'); + if(!$billPlz) throw new ResourceNotFoundException('Billplz bill not found.'); $transaction = $this->fetchesTransaction->execute(['payment_reference' => $billplzXSignatureObject->getBillPlzId()]); - if($billPlz->state == 'paid') $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::APPROVED); - - return $this->response(['data' => $billPlz]); + if($billPlz->state === 'paid') { + $status = ApprovalStatus::APPROVED; + if ( + $transaction->owner_type == 'App\Models\Wallet' && + $transaction->status == ApprovalStatus::PENDING_VERIFICATION + ) { + $wallet = $transaction->owner; + $updateWalletAmount = $wallet->amount + $transaction->amount; + $walletOject = new WalletObject($wallet->company->id, $wallet->currency_id, $wallet->code, $updateWalletAmount); + $wallet = $this->updatesWallet->execute($wallet, $walletOject); + } + + } + + if($billPlz->state === 'due') { + $status = $billplzXSignatureObject->getStatus() === 'failed' ? ApprovalStatus::REJECTED : ApprovalStatus::PENDING_VERIFICATION; + } + + $this->updatesTransactionStatus->execute($transaction, $status); + + $token = Auth::fromUser(User::find(1)); + $request->headers->set('Authorization', 'Bearer '.$token); + + return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $transaction->booking->marking, 'payment_reference' => $transaction->payment_reference, 'status' => $status, 'amount' => $transaction->amount]); } } \ No newline at end of file diff --git a/app/Classes/Modules/Billplzs/ControllersLogic/CreateBillplzBillLogic.php b/app/Classes/Modules/Billplzs/ControllersLogic/CreateBillplzBillLogic.php index 7aabd468..a7069841 100644 --- a/app/Classes/Modules/Billplzs/ControllersLogic/CreateBillplzBillLogic.php +++ b/app/Classes/Modules/Billplzs/ControllersLogic/CreateBillplzBillLogic.php @@ -40,9 +40,7 @@ class CreateBillplzBillLogic extends AbstractControllerLogic /** * @param Request $request * @return JsonResponse - * @throws \App\Classes\Exceptions\AccessForbiddenException - * @throws \App\Classes\Exceptions\MalformedRequestException - * @throws \App\Classes\Exceptions\RequestValidationException + * @throws MalformedRequestException */ public function logic(Request $request) : JsonResponse { diff --git a/app/Classes/Modules/Billplzs/DataTransferObjects/BillplzXSignatureObject.php b/app/Classes/Modules/Billplzs/DataTransferObjects/BillplzXSignatureObject.php index db3e3ad6..c1295886 100644 --- a/app/Classes/Modules/Billplzs/DataTransferObjects/BillplzXSignatureObject.php +++ b/app/Classes/Modules/Billplzs/DataTransferObjects/BillplzXSignatureObject.php @@ -4,6 +4,7 @@ namespace App\Classes\Modules\Billplzs\DataTransferObjects; use Illuminate\Http\Request; use App\Classes\General\Interfaces\DataTransferObject; +use function PHPSTORM_META\map; class BillplzXSignatureObject implements DataTransferObject { @@ -11,6 +12,9 @@ class BillplzXSignatureObject implements DataTransferObject /** @var string */ private $billPlzId; + /** @var string */ + private $status; + /** @var array */ private $billPlzConstructArray; @@ -20,6 +24,9 @@ class BillplzXSignatureObject implements DataTransferObject /** @var string */ private $billPlzComputedXSignature; + /** @var string */ + private $type; + /** @var Request */ private $request; @@ -28,22 +35,26 @@ class BillplzXSignatureObject implements DataTransferObject public function __construct(Request $request) { - $this->request = $request; - $this->billPlzId = $request->id ? $request->id : $request->{'billplz[id]'}; + $this->type = $request->exists('billplz') ? 'redirect' : 'callback'; - $this->requestXSignature = $request->x_signature ? $request->x_signature : $request->{'billplz[x_signature]'}; + $this->request = $this->type === 'redirect' ? $request->input('billplz') : $request; + + $this->billPlzId = $this->request['id']; + + $this->status = $this->request['transaction_status']; + + $this->requestXSignature = $this->request['x_signature']; $this->_constructBillplzArray()->_natSortBillplzArray()->_constructBillplzString()->_computeBillplzXSignature(); } private function _constructBillplzArray(){ - foreach($this->request->all() as $key => $value){ - if($key != 'x_signature' && $key != 'billplz[x_signature]'){ - $key = str_replace(']', '', str_replace('[', '', $key)); - $this->billPlzConstructArray[] = $key.$value; - } - } + + $this->billPlzConstructArray = collect($this->request)->forget('x_signature')->map(function($item, $key){ + return $this->type === 'redirect' ? 'billplz'.$key.$item : $key.$item; + })->toArray(); + return $this; } @@ -72,6 +83,11 @@ class BillplzXSignatureObject implements DataTransferObject return $this->billPlzId; } + public function getStatus(): string + { + return $this->status; + } + /** * @return array */ @@ -98,7 +114,7 @@ class BillplzXSignatureObject implements DataTransferObject public function isValidSignature(): bool { - return $this->billPlzComputedXSignature == $this->requestXSignature ? true : false; + return $this->billPlzComputedXSignature === $this->requestXSignature ? true : false; } } \ No newline at end of file diff --git a/app/Classes/Modules/Billplzs/Services/CreatesBillplzBill.php b/app/Classes/Modules/Billplzs/Services/CreatesBillplzBill.php index 607b45fa..ef3b5f4e 100644 --- a/app/Classes/Modules/Billplzs/Services/CreatesBillplzBill.php +++ b/app/Classes/Modules/Billplzs/Services/CreatesBillplzBill.php @@ -7,22 +7,30 @@ use App\Classes\Exceptions\MalformedRequestException; class CreatesBillplzBill { + /** - * @return \Illuminate\Database\Eloquent\Model - * @throws \App\Classes\Exceptions\MalformedRequestException + * @param string $name + * @param string $email + * @param string $description + * @param float $amount + * @param string $billNumber + * @param null|string $bankCode + * @return null|object + * @throws MalformedRequestException */ - public function execute(string $name, string $email, string $description, float $amount, string $billNumber, ?string $bankCode = null) { + public function execute(string $name, string $email, string $description, float $amount, string $billNumber, ?string $bankCode = null) { try{ - $response = Http::withBasicAuth(config('billplz.api_key').':', '')->withOptions(["verify"=>false])->post(config('billplz.base_url').'/api/v3/bills', [ +// config('billplz.maybank') + $response = Http::withBasicAuth(config('billplz.api_key').':', '')->post(config('billplz.base_url').'/api/v3/bills', [ 'collection_id' => config('billplz.collection_id'), 'name' => $name, 'email' => $email, 'description' => $description, - 'amount' => $amount, - 'redirect_url' => config('billplz.redirect_url'), - 'callback_url' => config('billplz.callback_url'), + 'amount' => $this->finalizeAmount($amount), + 'redirect_url' => route('online_payment.redirect'), + 'callback_url' => route('api.online_payment.callback'), 'reference_1_label' => 'Bank Code', - 'reference_1' => $bankCode ? $bankCode : config('billplz.maybank'), + 'reference_1' => $bankCode ? $bankCode : '', 'reference_2_label' => 'Bill Number', 'reference_2' => $billNumber ]); @@ -40,4 +48,9 @@ class CreatesBillplzBill throw new MalformedRequestException('Unable to get correct response from billplz server' . $exception->getMessage()); } } + + protected function finalizeAmount($amount){ + $number = round($amount, 2) * 100; + return (string) $number; + } } \ No newline at end of file diff --git a/app/Classes/Modules/Billplzs/Services/GetBillplzBill.php b/app/Classes/Modules/Billplzs/Services/GetBillplzBill.php index ff7c129f..2a86b403 100644 --- a/app/Classes/Modules/Billplzs/Services/GetBillplzBill.php +++ b/app/Classes/Modules/Billplzs/Services/GetBillplzBill.php @@ -2,13 +2,16 @@ namespace App\Classes\Modules\Billplzs\Services; +use App\Classes\Exceptions\MalformedRequestException; use Illuminate\Support\Facades\Http; class GetBillplzBill { + /** - * @return \Illuminate\Database\Eloquent\Model - * @throws \App\Classes\Exceptions\MalformedRequestException + * @param string $billPlzId + * @return null|object + * @throws MalformedRequestException */ public function execute(string $billPlzId) { try{ diff --git a/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php index ff4796cc..f7d1d775 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php @@ -61,7 +61,11 @@ class ApprovePurchaseOrderLogic extends AbstractControllerLogic $booking = $this->fetchesBooking->execute(['id' => $request->route('id')]); - $this->updatesTransactionStatus->execute($booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first(), ApprovalStatus::APPROVED); + $purchaseOrder = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first(); + + $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->where('id', '!=', $purchaseOrder->id)->delete(); + + $this->updatesTransactionStatus->execute($purchaseOrder, ApprovalStatus::APPROVED); $this->createInvoiceTransactionProcessor->execute($booking); diff --git a/app/Classes/Modules/Bookings/ControllersLogic/AutoPurchaseOrderFillLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/AutoPurchaseOrderFillLogic.php new file mode 100644 index 00000000..ed9ec6d8 --- /dev/null +++ b/app/Classes/Modules/Bookings/ControllersLogic/AutoPurchaseOrderFillLogic.php @@ -0,0 +1,113 @@ +generatesPurchaseOrderProducts = $generatesPurchaseOrderProducts; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->createPurchaseOrderTransactionProcessor = $createPurchaseOrderTransactionProcessor; + } + + + /** + * @return array + */ + protected function notification():array { + return [ + 'title' => 'Purchase Order Approval', + 'message' => 'You have successfully updated the Purchase order status' + ]; + } + + /** @var GeneratesPurchaseOrderProducts */ + private $generatesPurchaseOrderProducts; + + /** @var GeneratesTransactionBillNumber */ + private $generatesTransactionBillNumber; + + /** @var CreatePurchaseOrderTransactionProcessor */ + private $createPurchaseOrderTransactionProcessor; + + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $bookings = Booking::whereMonth('created_at', 7) + ->whereYear('created_at', 2021) + ->whereDoesntHave('transactions', function($q){ + $q->where('type', TransactionType::PURCHASE_ORDER); + $q->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED]); + })->get(); + foreach ($bookings as $booking) { + $po = Transaction::where('type', TransactionType::PURCHASE_ORDER) + ->where('status', ApprovalStatus::APPROVED)->where('issuer', $booking->company_id) + ->select('*', DB::raw('abs(amount - ' . $booking->fix_amount . ') as nearest_price'))->orderBy('nearest_price')->first(); + + + if (!$po) { + $po = Transaction::where('type', TransactionType::PURCHASE_ORDER) + ->where('status', ApprovalStatus::APPROVED)->select('*', DB::raw('abs(amount - ' . $booking->fix_amount . ') as nearest_price'))->orderBy('nearest_price')->first(); + } + + $products = $this->generatesPurchaseOrderProducts->execute($po, $booking->fix_amount); + + $deference = $booking->fix_amount - $products->sum('total'); + + if($deference > -150 && $deference < 150 && $deference != 0) { + + $products->push([ + 'description' => $deference < 0 ? 'Discount':'Shipping Fee', + 'quantity' => 1, + 'stockCode' => '', + 'total' => $deference, + 'unit_price' => $deference + ]); + } + + $billNumber = $this->generatesTransactionBillNumber->execute('XPO-'); + + $total = $products->sum('total'); + + $object = new TransactionObject($billNumber, TransactionType::PURCHASE_ORDER, $booking->company->id, 1, + 1, PaymentMethodType::CASH, + $total, $total, $booking->fix_currency_id, $booking->fix_currency_id, + 1, 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, $products->toArray()); + + $this->createPurchaseOrderTransactionProcessor->execute($booking, $object); + } + + return $this->response([]); + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php index db1c0d2b..a16be8d2 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php @@ -99,7 +99,7 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::PAYMENT_GATEWAY){ - $billPlzBill = $this->createsBillplzBill->execute($request->user()->name, $request->user()->email, 'This payment is made on behave '.$booking->company->name, $configurations->getTotal(), $billNumber, $request->input('bank_code')); + $billPlzBill = $this->createsBillplzBill->execute($request->user()->name, $request->user()->email, 'This payment is made for transfer ref. '.$booking->marking, $configurations->getTotal(), $billNumber, $request->input('bank_code')); } $object = new TransactionObject($billNumber, TransactionType::PAYMENT, 1, $booking->company->id, @@ -109,7 +109,7 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic $configurations->getTax(), $configurations->getServiceCharge(), Carbon::now()->addMinutes($paymentAttemptLimit), ApprovalStatus::PENDING_SUBMISSION, [], isset($billPlzBill) ? $billPlzBill->id : NULL); $transaction = $this->createsTransaction->execute($booking, $object); - + return $this->resourceResponse(new TransactionResource($transaction)); } diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php index 507f7062..411b9163 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php @@ -3,21 +3,22 @@ namespace App\Classes\Modules\Bookings\ControllersLogic; +use App\Models\Booking; +use Illuminate\Http\Request; +use Illuminate\Http\JsonResponse; +use App\Http\Resources\TransactionResource; use App\Classes\Exceptions\MalformedRequestException; -use App\Classes\General\Abstracts\AbstractControllerLogic; -use App\Classes\Modules\Bookings\Services\FetchesBookingQuotation; -use App\Classes\Modules\Transactions\Services\FetchesTransaction; -use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; -use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; -use App\Classes\Modules\Transactions\DataTransferObjects\TransactionRefundCalculationObject; -use App\Classes\Modules\Transactions\Services\CreatesTransaction; -use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\TransactionType; -use App\Http\Resources\TransactionResource; -use App\Models\Booking; -use Illuminate\Http\JsonResponse; -use Illuminate\Http\Request; +use App\Classes\General\Abstracts\AbstractControllerLogic; +use App\Classes\Modules\Transactions\Services\CreatesTransaction; +use App\Classes\Modules\Transactions\Services\FetchesTransaction; +use App\Classes\Modules\Bookings\Services\FetchesBookingQuotation; +use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; +use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; +use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; +use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; +use App\Classes\Modules\Transactions\DataTransferObjects\TransactionRefundCalculationObject; class CreateBookingRefundLogic extends AbstractControllerLogic { @@ -47,6 +48,9 @@ class CreateBookingRefundLogic extends AbstractControllerLogic /** @var CreatesTransaction */ private $createsTransaction; + /** @var CalculatesBookingRefundAmount */ + private $calculatesBookingRefundAmount; + /** * CreateBookingPaymentLogic constructor. * @param FetchesBookingQuotation $fetchBookingQuotation @@ -54,14 +58,16 @@ class CreateBookingRefundLogic extends AbstractControllerLogic * @param UpdatesTransactionStatus $updatesTransactionStatus * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber * @param CreatesTransaction $createsTransaction + * @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount */ - public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction) + public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingRefundAmount $calculatesBookingRefundAmount) { $this->fetchBookingQuotation = $fetchBookingQuotation; $this->fetchesTransaction = $fetchesTransaction; $this->updatesTransactionStatus = $updatesTransactionStatus; $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; $this->createsTransaction = $createsTransaction; + $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; } /** @@ -82,6 +88,11 @@ class CreateBookingRefundLogic extends AbstractControllerLogic $customerBooking = $booking->transactions()->payments()->complete()->where('original_amount', '=', $transaction->original_amount)->where('id', '<', $transaction->id)->orderByDesc('id')->first(); } + $refund = $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id, $transaction->bill_no); + dd($refund); + + 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, (int) $transaction->type === TransactionType::BILL ? $customerBooking : $transaction, $request->input('amount')); $transactionRefundCalculationObject->init(); diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateProformaInvoiceTransactionLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateProformaInvoiceTransactionLogic.php new file mode 100644 index 00000000..b37019a5 --- /dev/null +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateProformaInvoiceTransactionLogic.php @@ -0,0 +1,71 @@ + 'Create Proforma Invoice Transaction', + 'message' => 'You have successfully create proforma invoice transaction' + ]; + } + + /** @var CanFetchBooking */ + private $canFetchBooking; + + /** @var FetchesBooking */ + private $fetchesBooking; + + /** @var CreateProformaInvoiceTransactionProcessor */ + private $CreateProformaInvoiceTransactionProcessor; + + /** + * FetchBookingLogic constructor. + * @param CanFetchBooking $canFetchBooking + * @param FetchesBooking $fetchesBooking + * @param CreateProformaInvoiceTransactionProcessor $CreateProformaInvoiceTransactionProcessor + */ + public function __construct( + CanFetchBooking $canFetchBooking, + FetchesBooking $fetchesBooking, + CreateProformaInvoiceTransactionProcessor $CreateProformaInvoiceTransactionProcessor + ) + { + $this->canFetchBooking = $canFetchBooking; + $this->fetchesBooking = $fetchesBooking; + $this->CreateProformaInvoiceTransactionProcessor = $CreateProformaInvoiceTransactionProcessor; + } + + + /** + * @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 + { + $this->canFetchBooking->passes(); + + $booking = $this->fetchesBooking->execute(['id' => $request->route('id')]); + + $this->CreateProformaInvoiceTransactionProcessor->execute($booking); + + return $this->resourceResponse(new BookingResource($booking)); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Bookings/ControllersLogic/RegenerateInvoiceBookingLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/RegenerateInvoiceBookingLogic.php new file mode 100644 index 00000000..d1cdbada --- /dev/null +++ b/app/Classes/Modules/Bookings/ControllersLogic/RegenerateInvoiceBookingLogic.php @@ -0,0 +1,110 @@ + 'Regenerate Booking Invoice', + 'message' => 'You have successfully regenerate booking invoice' + ]; + } + + /** @var CanFetchBooking */ + private $canFetchBooking; + + /** @var FetchesBooking */ + private $fetchesBooking; + + /** @var DeletesTransaction */ + private $deletesTransaction; + + /** @var UpdatesBookingStatus */ + private $updatesBookingStatus; + + /** @var DeletesDocument */ + private $deletesDocument; + + /** @var CreateInvoiceTransactionProcessor */ + private $createInvoiceTransactionProcessor; + + /** + * FetchBookingLogic constructor. + * @param CanFetchBooking $canFetchBooking + * @param FetchesBooking $fetchesBooking + * @param DeletesTransaction $deletesTransaction + * @param UpdatesBookingStatus $updatesBookingStatus + * @param DeletesDocument $deletesDocument + * @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor + */ + public function __construct( + CanFetchBooking $canFetchBooking, + FetchesBooking $fetchesBooking, + DeletesTransaction $deletesTransaction, + UpdatesBookingStatus $updatesBookingStatus, + DeletesDocument $deletesDocument, + CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor + ) + { + $this->canFetchBooking = $canFetchBooking; + $this->fetchesBooking = $fetchesBooking; + $this->deletesTransaction = $deletesTransaction; + $this->updatesBookingStatus = $updatesBookingStatus; + $this->deletesDocument = $deletesDocument; + $this->createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function logic(Request $request) : JsonResponse + { + $this->canFetchBooking->passes(); + + $booking = $this->fetchesBooking->execute([ + 'id' => $request->route('id'), + 'status' => ApprovalStatus::COMPLETED, + 'with_transactions' => true] + ); + + $this->updatesBookingStatus->execute($booking, ApprovalStatus::APPROVED); + + $transaction = $booking->transactions()->whereIn('type', [TransactionType::INVOICE, TransactionType::SUPPLIER_DELIVER])->get(); + foreach ($transaction as $key => $row) { + $this->deletesTransaction->execute($row); + } + + $document = $booking->documents()->get(); + foreach ($document as $key => $row) { + $this->deletesDocument->execute($row); + } + + $this->createInvoiceTransactionProcessor->execute($booking); + + return $this->resourceResponse(new BookingResource($booking)); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php new file mode 100644 index 00000000..fabdd058 --- /dev/null +++ b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php @@ -0,0 +1,100 @@ + 'Updated Booking', + 'message' => 'You have successfully updated the Booking' + ]; + } + + /** @var CanUpdateBooking */ + private $canUpdateBooking; + + /** @var UpdatesBookingFixedAmount */ + private $updatesBookingFixedAmount; + + /** @var FetchesBooking */ + private $fetchesBooking; + + /** @var CalculatesBookingOutstanding */ + private $calculatesBookingOutstanding; + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + /** + * UpdateBookingAmountLogic constructor. + * @param CanUpdateBooking $canUpdateBooking + * @param UpdatesBookingFixedAmount $updatesBookingFixedAmount + * @param FetchesBooking $fetchesBooking + * @param CalculatesBookingOutstanding $calculatesBookingOutstanding + * @param UpdatesTransactionStatus $updatesTransactionStatus + */ + public function __construct(CanUpdateBooking $canUpdateBooking, UpdatesBookingFixedAmount $updatesBookingFixedAmount, FetchesBooking $fetchesBooking, CalculatesBookingOutstanding $calculatesBookingOutstanding, UpdatesTransactionStatus $updatesTransactionStatus) + { + $this->canUpdateBooking = $canUpdateBooking; + $this->updatesBookingFixedAmount = $updatesBookingFixedAmount; + $this->fetchesBooking = $fetchesBooking; + $this->calculatesBookingOutstanding = $calculatesBookingOutstanding; + $this->updatesTransactionStatus = $updatesTransactionStatus; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $booking = $this->fetchesBooking->execute(['id' => $request->route('id')]); + + $input_amount = number_format( floatval(str_replace(',', '', $request->input('fix_amount', $booking->fix_amount))), 5, '.', ''); + + $minimum_amount = $booking->fix_amount - $this->calculatesBookingOutstanding->execute($booking); + + if ((float)$input_amount < $minimum_amount) { + throw new MalformedRequestException('Booking Amount cannot be less than '. $minimum_amount .'.'); + } + + $poTransaction = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first(); + $booking->transactions()->where('type', TransactionType::PROFORMA)->delete(); + + if($poTransaction) { + $this->updatesTransactionStatus->execute($poTransaction, ApprovalStatus::PENDING_SUBMISSION); + } + + $booking = $this->updatesBookingFixedAmount->execute($booking, $input_amount); + + return $this->resourceResponse(new BookingResource($booking)); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php b/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php index 2dec77fa..14a4a9ef 100644 --- a/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php +++ b/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php @@ -11,8 +11,10 @@ use Carbon\Carbon; class CalculatesBookingRefundAmount { - public function execute(Booking $booking){ - return $booking->transactions()->refunds()->complete()->sum('original_amount'); + public function execute(Booking $booking, int $type, ?string $payment_reference = NULL){ + return $type === 1 ? + $booking->transactions()->refunds($payment_reference) + ->selectRaw('sum(amount - service_charge - tax) as sub_total')->get()->sum('sub_total') : $booking->transactions()->refunds($payment_reference)->sum('original_amount'); } } \ No newline at end of file diff --git a/app/Classes/Modules/Bookings/Services/CalculatesBookingTransferredAmount.php b/app/Classes/Modules/Bookings/Services/CalculatesBookingTransferredAmount.php index 5224e044..57a5525c 100644 --- a/app/Classes/Modules/Bookings/Services/CalculatesBookingTransferredAmount.php +++ b/app/Classes/Modules/Bookings/Services/CalculatesBookingTransferredAmount.php @@ -12,7 +12,7 @@ class CalculatesBookingTransferredAmount { public function execute(Booking $booking){ - return $booking->transactions()->bills()->transferred()->sum('original_amount'); + return $booking->transactions()->bills()->complete()->sum('original_amount'); } } \ No newline at end of file diff --git a/app/Classes/Modules/Bookings/Services/UpdatesBooking.php b/app/Classes/Modules/Bookings/Services/UpdatesBooking.php index 37ca5b7c..2c0ec871 100644 --- a/app/Classes/Modules/Bookings/Services/UpdatesBooking.php +++ b/app/Classes/Modules/Bookings/Services/UpdatesBooking.php @@ -17,8 +17,8 @@ class UpdatesBooking extends AbstractUpdateRecord */ public function execute(Booking $model, BookingObject $object) { - $model->transferable_bank_id = $object->getTransferableBankId(); - $model->reference = $object->getReference(); + $model->bank_id = $object->getTransferableBankId(); + $model->marking = $object->getMarking(); $model->fix_amount = $object->getFixAmount(); $model->fix_currency_id = $object->getFixCurrencyId(); $model->convertible_currency_id = $object->getConvertibleCurrencyId(); diff --git a/app/Classes/Modules/Bookings/Services/UpdatesBookingFixedAmount.php b/app/Classes/Modules/Bookings/Services/UpdatesBookingFixedAmount.php new file mode 100644 index 00000000..24be06f4 --- /dev/null +++ b/app/Classes/Modules/Bookings/Services/UpdatesBookingFixedAmount.php @@ -0,0 +1,23 @@ +fix_amount = $fixedAmount; + return $this->handler($model); + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Bookings/Standards/Rules/CanDeleteBooking.php b/app/Classes/Modules/Bookings/Standards/Rules/CanDeleteBooking.php index dfd307bc..d1fcfe15 100644 --- a/app/Classes/Modules/Bookings/Standards/Rules/CanDeleteBooking.php +++ b/app/Classes/Modules/Bookings/Standards/Rules/CanDeleteBooking.php @@ -4,6 +4,7 @@ namespace App\Classes\Modules\Bookings\Standards\Rules; use App\Classes\General\Abstracts\AbstractRule; use App\Classes\Modules\Bookings\DataTransferObjects\BookingObject; +use Illuminate\Support\Facades\Auth; class CanDeleteBooking extends AbstractRule { @@ -14,7 +15,7 @@ class CanDeleteBooking extends AbstractRule { // TODO Set Authorization rules - if (!\Auth::user()->can('delete booking')) { + if (!Auth::user()->can('delete booking')) { return false; } diff --git a/app/Classes/Modules/Bookings/Standards/Rules/CanUpdateBooking.php b/app/Classes/Modules/Bookings/Standards/Rules/CanUpdateBooking.php index bf5c022c..7158a825 100644 --- a/app/Classes/Modules/Bookings/Standards/Rules/CanUpdateBooking.php +++ b/app/Classes/Modules/Bookings/Standards/Rules/CanUpdateBooking.php @@ -5,6 +5,7 @@ namespace App\Classes\Modules\Bookings\Standards\Rules; use App\Classes\General\Abstracts\AbstractRule; use App\Classes\Modules\Bookings\Standards\Validators\BookingValidation; +use Illuminate\Support\Facades\Auth; class CanUpdateBooking extends AbstractRule { @@ -29,7 +30,7 @@ class CanUpdateBooking extends AbstractRule { // TODO Set Authorization rules - if (!\Auth::user()->can('edit booking')) { + if (!Auth::user()->can('edit booking')) { return false; } diff --git a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanCreateRate.php b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanCreateRate.php index 842a548b..cf63f89c 100644 --- a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanCreateRate.php +++ b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanCreateRate.php @@ -5,6 +5,7 @@ namespace App\Classes\Modules\Currencies\Standards\Rules\Rates; use App\Classes\General\Abstracts\AbstractRule; use App\Classes\Modules\Currencies\Standards\Validators\Rates\RateValidation; use App\Classes\Modules\Currencies\DataTransferObjects\RateObject; +use Illuminate\Support\Facades\Auth; class CanCreateRate extends AbstractRule { @@ -27,7 +28,7 @@ class CanCreateRate extends AbstractRule protected function authorized(): bool { // TODO Set Authorization rules - if (!\Auth::user()->can('add currency_rate')) { + if (!Auth::user()->can('add currency_rate')) { return false; } diff --git a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanDeleteRate.php b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanDeleteRate.php index 4ebefb9e..37fff506 100644 --- a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanDeleteRate.php +++ b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanDeleteRate.php @@ -4,6 +4,7 @@ namespace App\Classes\Modules\Currencies\Standards\Rules\Rates; use App\Classes\General\Abstracts\AbstractRule; use App\Classes\Modules\Currencies\DataTransferObjects\RateObject; +use Illuminate\Support\Facades\Auth; class CanDeleteRate extends AbstractRule { @@ -14,7 +15,7 @@ class CanDeleteRate extends AbstractRule { // TODO Set Authorization rules - if (!\Auth::user()->can('delete currency_rate')) { + if (!Auth::user()->can('delete currency_rate')) { return false; } diff --git a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanListRates.php b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanListRates.php index 496ba1e5..bd49c263 100644 --- a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanListRates.php +++ b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanListRates.php @@ -4,6 +4,7 @@ namespace App\Classes\Modules\Currencies\Standards\Rules\Rates; use App\Classes\General\Abstracts\AbstractRule; use App\Classes\Modules\Currencies\DataTransferObjects\CurrencyObject; +use Illuminate\Support\Facades\Auth; class CanListRates extends AbstractRule { @@ -14,7 +15,7 @@ class CanListRates extends AbstractRule { // TODO Set Authorization rules - if (!\Auth::user()->can('view currency_rate')) { + if (!Auth::user()->can('view currency_rate')) { return false; } diff --git a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanUpdateRate.php b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanUpdateRate.php index 59564725..8a153c54 100644 --- a/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanUpdateRate.php +++ b/app/Classes/Modules/Currencies/Standards/Rules/Rates/CanUpdateRate.php @@ -6,6 +6,7 @@ namespace App\Classes\Modules\Currencies\Standards\Rules\Rates; use App\Classes\General\Abstracts\AbstractRule; use App\Classes\Modules\Currencies\Standards\Validators\Rates\RateValidation; use App\Classes\Modules\Currencies\DataTransferObjects\RateObject; +use Illuminate\Support\Facades\Auth; class CanUpdateRate extends AbstractRule { @@ -29,7 +30,7 @@ class CanUpdateRate extends AbstractRule { // TODO Set Authorization rules - if (!\Auth::user()->can('view currency_rate')) { + if (!Auth::user()->can('view currency_rate')) { return false; } diff --git a/app/Classes/Modules/Documents/Services/DeletesDocument.php b/app/Classes/Modules/Documents/Services/DeletesDocument.php new file mode 100644 index 00000000..e0f02819 --- /dev/null +++ b/app/Classes/Modules/Documents/Services/DeletesDocument.php @@ -0,0 +1,19 @@ +handler($model); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Exports/Services/ExportsProducts.php b/app/Classes/Modules/Exports/Services/ExportsProducts.php new file mode 100644 index 00000000..541f1d21 --- /dev/null +++ b/app/Classes/Modules/Exports/Services/ExportsProducts.php @@ -0,0 +1,51 @@ +whereHas('transaction', function($query){ + return $query->where('type', \App\Classes\ValueObjects\Constants\TransactionType::PURCHASE_ORDER)->where('status', ApprovalStatus::APPROVED); + })->limit(50); + } + + /** + * @param $product + * @return array + */ + public function map($product): array + { + + return [ + $product->product_code, + $product->product_name, + $product->price, + ]; + } +} \ 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 4fd48239..a49d1f85 100644 --- a/app/Classes/Modules/Exports/Services/ExportsTransactions.php +++ b/app/Classes/Modules/Exports/Services/ExportsTransactions.php @@ -36,7 +36,7 @@ class ExportsTransactions implements FromQuery, WithHeadingRow, WithMapping 1 => 'PAYMENT', 2 => 'INVOICE', 3 => 'BILL', - 4 => 'PERFORMA', + 4 => 'PROFORMA', 5 => 'TOP_UP', 6 => 'REFUND', 7 => 'PURCHASE_ORDER', diff --git a/app/Classes/Modules/Segments/Standards/Rules/CanCreateSegment.php b/app/Classes/Modules/Segments/Standards/Rules/CanCreateSegment.php index 50f7e81d..f7b05a10 100644 --- a/app/Classes/Modules/Segments/Standards/Rules/CanCreateSegment.php +++ b/app/Classes/Modules/Segments/Standards/Rules/CanCreateSegment.php @@ -5,6 +5,7 @@ namespace App\Classes\Modules\Segments\Standards\Rules; use App\Classes\General\Abstracts\AbstractRule; use App\Classes\Modules\Segments\DataTransferObjects\SegmentObject; use App\Classes\Modules\Segments\Standards\Validators\SegmentValidation; +use Illuminate\Support\Facades\Auth; class CanCreateSegment extends AbstractRule { @@ -27,7 +28,7 @@ class CanCreateSegment extends AbstractRule protected function authorized(): bool { // TODO Set Authorization rules - if (!\Auth::user()->can('add segment')) { + if (!Auth::user()->can('add segment')) { return false; } diff --git a/app/Classes/Modules/Segments/Standards/Rules/CanDeleteSegment.php b/app/Classes/Modules/Segments/Standards/Rules/CanDeleteSegment.php index 197b0a5f..9faf4da6 100644 --- a/app/Classes/Modules/Segments/Standards/Rules/CanDeleteSegment.php +++ b/app/Classes/Modules/Segments/Standards/Rules/CanDeleteSegment.php @@ -4,6 +4,7 @@ namespace App\Classes\Modules\Segments\Standards\Rules; use App\Classes\General\Abstracts\AbstractRule; use App\Classes\Modules\Segments\DataTransferObjects\SegmentObject; +use Illuminate\Support\Facades\Auth; class CanDeleteSegment extends AbstractRule { @@ -14,7 +15,7 @@ class CanDeleteSegment extends AbstractRule { // TODO Set Authorization rules - if (!\Auth::user()->can('delete segment')) { + if (!Auth::user()->can('delete segment')) { return false; } diff --git a/app/Classes/Modules/Segments/Standards/Rules/CanUpdateSegment.php b/app/Classes/Modules/Segments/Standards/Rules/CanUpdateSegment.php index 58a8c0ca..8287dfd6 100644 --- a/app/Classes/Modules/Segments/Standards/Rules/CanUpdateSegment.php +++ b/app/Classes/Modules/Segments/Standards/Rules/CanUpdateSegment.php @@ -6,6 +6,7 @@ namespace App\Classes\Modules\Segments\Standards\Rules; use App\Classes\General\Abstracts\AbstractRule; use App\Classes\Modules\Segments\DataTransferObjects\SegmentObject; use App\Classes\Modules\Segments\Standards\Validators\SegmentValidation; +use Illuminate\Support\Facades\Auth; class CanUpdateSegment extends AbstractRule { @@ -30,7 +31,7 @@ class CanUpdateSegment extends AbstractRule { // TODO Set Authorization rules - if (!\Auth::user()->can('edit segment')) { + if (!Auth::user()->can('edit segment')) { return false; } diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreatePurchaseOrderTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreatePurchaseOrderTransactionLogic.php index aa4c6f4d..9bab107f 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreatePurchaseOrderTransactionLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreatePurchaseOrderTransactionLogic.php @@ -7,6 +7,7 @@ use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Bookings\Services\FetchesBooking; use App\Classes\Modules\Companies\Services\FetchesCompany; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; +use App\Classes\Modules\Transactions\Processors\CreatePurchaseOrderTransactionProcessor; use App\Classes\Modules\Transactions\Services\CreatesTransaction; use App\Classes\Modules\Transactions\Services\CreatesTransactionDetail; use App\Classes\Modules\Transactions\Services\DeletesTransactionDetails; @@ -25,26 +26,6 @@ use Illuminate\Http\Request; class CreatePurchaseOrderTransactionLogic extends AbstractControllerLogic { - /** - * CreatePurchaseOrderTransactionLogic constructor. - * @param FetchesBooking $fetchesBooking - * @param UpdatesTransactionStatus $updatesTransactionStatus - * @param CreatesTransaction $createsTransaction - * @param CreatesTransactionDetail $createsTransactionDetail - * @param UpdatesTransaction $updatesTransaction - * @param DeletesTransactionDetails $deletesTransactionDetails - * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber - */ - public function __construct(FetchesBooking $fetchesBooking, UpdatesTransactionStatus $updatesTransactionStatus, CreatesTransaction $createsTransaction, CreatesTransactionDetail $createsTransactionDetail, UpdatesTransaction $updatesTransaction, DeletesTransactionDetails $deletesTransactionDetails, GeneratesTransactionBillNumber $generatesTransactionBillNumber) - { - $this->fetchesBooking = $fetchesBooking; - $this->updatesTransactionStatus = $updatesTransactionStatus; - $this->createsTransaction = $createsTransaction; - $this->createsTransactionDetail = $createsTransactionDetail; - $this->updatesTransaction = $updatesTransaction; - $this->deletesTransactionDetails = $deletesTransactionDetails; - $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; - } /** * @return array @@ -59,37 +40,35 @@ class CreatePurchaseOrderTransactionLogic extends AbstractControllerLogic /** @var FetchesBooking */ private $fetchesBooking; - /** @var UpdatesTransactionStatus */ - private $updatesTransactionStatus; - - /** @var CreatesTransaction */ - private $createsTransaction; - - /** @var CreatesTransactionDetail */ - private $createsTransactionDetail; - - /** @var UpdatesTransaction */ - private $updatesTransaction; - - /** @var DeletesTransactionDetails */ - private $deletesTransactionDetails; - /** @var GeneratesTransactionBillNumber */ private $generatesTransactionBillNumber; + /** @var CreatePurchaseOrderTransactionProcessor */ + private $createPurchaseOrderTransactionProcessor; + + /** + * CreatePurchaseOrderTransactionLogic constructor. + * @param FetchesBooking $fetchesBooking + * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber + * @param CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor + */ + public function __construct(FetchesBooking $fetchesBooking, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor) + { + $this->fetchesBooking = $fetchesBooking; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->createPurchaseOrderTransactionProcessor = $createPurchaseOrderTransactionProcessor; + } /** * @param Request $request + * @param string $id * @return JsonResponse * @throws \App\Classes\Exceptions\MalformedRequestException */ - public function logic(Request $request) : JsonResponse + public function logic(Request $request, $id = '') : JsonResponse { /** @var Booking $booking */ - $booking = $this->fetchesBooking->execute(['id' => $request->route('id')]); - - /** @var Transaction $transaction */ - $transaction = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first(); + $booking = $this->fetchesBooking->execute(['id' => $request->route('id') ?? $id]); $billNumber = $this->generatesTransactionBillNumber->execute('PO-'); @@ -102,15 +81,8 @@ class CreatePurchaseOrderTransactionLogic extends AbstractControllerLogic $total, $total, $booking->fix_currency_id, $booking->fix_currency_id, 1, 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, $request->input('products')); - !$transaction ? $transaction = $this->createsTransaction->execute($booking, $object) : $transaction = $this->updatesTransaction->execute($transaction, $object); - $this->updatesTransactionStatus->execute($transaction, (float) number_format($total, 2, '.', '') === (float) number_format((float)$booking->fix_amount, 2, '.', '') ? ApprovalStatus::PENDING_VERIFICATION : ApprovalStatus::PENDING_SUBMISSION); - - $this->deletesTransactionDetails->execute($transaction); - - foreach ($object->getDetails() as $product){ - $this->createsTransactionDetail->execute($transaction, $product); - } + $transaction = $this->createPurchaseOrderTransactionProcessor->execute($booking, $object); return $this->resourceResponse(new TransactionResource($transaction)); diff --git a/app/Classes/Modules/Transactions/ControllersLogic/DeleteTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/DeleteTransactionLogic.php new file mode 100644 index 00000000..7995e447 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/DeleteTransactionLogic.php @@ -0,0 +1,72 @@ + 'Deleted Transaction', + 'message' => 'You have successfully deleted a transaction' + ]; + } + + /** @var FetchesTransaction */ + private $fetchesTransaction; + + /** @var DeletesTransaction */ + private $deletesTransaction; + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + /** + * CreatePaymentVerificationDocumentLogic constructor. + * @param FetchesTransaction $fetchesTransaction + * @param DeletesTransaction $deletesTransaction + */ + public function __construct(FetchesTransaction $fetchesTransaction, DeletesTransaction $deletesTransaction, UpdatesTransactionStatus $updatesTransactionStatus) + { + $this->fetchesTransaction = $fetchesTransaction; + $this->deletesTransaction = $deletesTransaction; + $this->updatesTransactionStatus = $updatesTransactionStatus; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); + + $this->deletesTransaction->execute($transaction); + + $payment_transaction = $transaction->booking->transactions()->payments()->complete()->where('original_amount', '=', $transaction->original_amount)->where('id', '<', $transaction->id)->orderByDesc('id')->first(); + + $this->updatesTransactionStatus->execute($payment_transaction, ApprovalStatus::APPROVED); + + return $this->response([]); + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdatePaymentTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdatePaymentTransactionStatusLogic.php new file mode 100644 index 00000000..11f0a377 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdatePaymentTransactionStatusLogic.php @@ -0,0 +1,76 @@ + 'Updated Transaction', + 'message' => 'You have successfully updated a transaction' + ]; + } + + /** @var FetchesTransaction */ + private $fetchesTransaction; + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + /** @var DeletesDocument */ + private $deletesDocument; + + /** + * CreatePaymentVerificationDocumentLogic constructor. + * @param FetchesTransaction $fetchesTransaction + * @param UpdatesTransactionStatus $updatesTransactionStatus + * @param DeletesDocument $deletesDocument + */ + public function __construct(FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, DeletesDocument $deletesDocument) + { + $this->fetchesTransaction = $fetchesTransaction; + $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->deletesDocument = $deletesDocument; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); + $status = $request->route('status'); + + $this->updatesTransactionStatus->execute($transaction, $status === 'pending' ? ApprovalStatus::PENDING_VERIFICATION : ApprovalStatus::COMPLETED); + + if ($status == 'pending') { + $document = $transaction->documents()->first(); + if ($document) { + $this->deletesDocument->execute($document); + } + } + + return $this->response([]); + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php index ff76d197..e583eaf9 100644 --- a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php @@ -115,7 +115,6 @@ class CreateInvoiceTransactionProcessor if ((float) $booking_amount > (float) $payable_amount) { return; } - // confirm that all payments has been transferred if($this->calculatesBookingTransferredAmount->execute($booking) !== $this->calculatesBookingPaidAmount->execute($booking)){ return; diff --git a/app/Classes/Modules/Transactions/Processors/CreateProformaInvoiceTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateProformaInvoiceTransactionProcessor.php new file mode 100644 index 00000000..3e7e8137 --- /dev/null +++ b/app/Classes/Modules/Transactions/Processors/CreateProformaInvoiceTransactionProcessor.php @@ -0,0 +1,188 @@ +createsTransaction = $createsTransaction; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->calculatesBookingPayableAmount = $calculatesBookingPayableAmount; + $this->calculatesBookingCurrencyAverageRate = $calculatesBookingCurrencyAverageRate; + $this->fetchesCompany = $fetchesCompany; + $this->createsDocument = $createsDocument; + $this->createsFile = $createsFile; + $this->calculatesBookingOutstanding = $calculatesBookingOutstanding; + $this->generatesBookingQuotation = $generatesBookingQuotation; + $this->fetchesBookingQuotation = $fetchesBookingQuotation; + $this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit; + } + + + /** + * @param Booking $booking + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(Booking $booking) + { + + $po_order_transaction = $booking->transactions() + ->where('type', TransactionType::PURCHASE_ORDER) + ->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED]) + ->first(); + + $outstanding = $this->calculatesBookingOutstanding->execute($booking); + + $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $outstanding)), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, PaymentMethodType::CASH); + + $configurations = $this->fetchesBookingQuotation->execute($booking->company, $conversionObject); + + $paymentAttemptLimit = $this->fetchesCompanyPaymentAttemptLimit->execute($booking->company); + + $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); + + + $object = new TransactionObject($billNumber, TransactionType::PAYMENT, 1, $booking->company->id, + $configurations->getConfigurations()->getBankId(), $configurations->getConversionObject()->getPaymentMethod(), + $configurations->getTotal(), $configurations->getForeignTotal(), 1, + $configurations->getConversionObject()->getCurrencyId(), $configurations->getConfigurations()->getRate(), + $configurations->getTax(), $configurations->getServiceCharge(), Carbon::now()->addMinutes($paymentAttemptLimit), ApprovalStatus::PENDING_SUBMISSION, [], isset($billPlzBill) ? $billPlzBill->id : NULL); + + $this->createsTransaction->execute($booking, $object); + + $billNumber = $this->generatesTransactionBillNumber->execute('PROFORMA-'); + + $payable_amount = $booking->transactions()->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::SUSPENDED])->payments()->sum('amount'); + $booking_amount = $booking->fix_amount; + + $transaction = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->first(); + + $booking_currency_average_rate = $booking_amount / $booking->transactions()->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::SUSPENDED])->payments()->selectRaw('sum(amount - service_charge - tax) as sub_total')->get()->sum('sub_total'); + + $total_service_charge = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::SUSPENDED]) + ->sum('service_charge'); + + $total_tax = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->whereIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::SUSPENDED]) + ->sum('tax'); + + $transaction_object = new TransactionObject( + $billNumber, + TransactionType::PROFORMA, + $transaction->issuer, + $transaction->receiver, + $transaction->recipient_bank_account_id, + $transaction->payment_method, + $payable_amount, + $booking_amount, + $transaction->currency_id, + $transaction->original_currency_id, + $booking_currency_average_rate, + $total_tax, + $total_service_charge, + null, + ApprovalStatus::APPROVED + ); + + $perofrma_transaction = $this->createsTransaction->execute($po_order_transaction->booking, $transaction_object); + + $supplier = $this->fetchesCompany->execute(['id' => $transaction->receiver]); + + $purchase_order_pdf = LaravelMpdf::loadView('pages.pdfs.proforma_invoice', ['invoice_transaction' => $perofrma_transaction, 'po_order_transaction' => $po_order_transaction, 'supplier' => $supplier]); + $document_object = new DocumentObject( + DocumentType::PROFORMA_INVOICE, + [chunk_split('data:application/pdf;base64,'.base64_encode($purchase_order_pdf->output()))], + '', + ApprovalStatus::COMPLETED, + 'proforma_invoices' + ); + + /** @var Document $document */ + $document = $this->createsDocument->execute($po_order_transaction->booking, $document_object); + $this->createsFile->execute($document, $document_object); + + + } +} diff --git a/app/Classes/Modules/Transactions/Processors/CreatePurchaseOrderTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreatePurchaseOrderTransactionProcessor.php new file mode 100644 index 00000000..76773c75 --- /dev/null +++ b/app/Classes/Modules/Transactions/Processors/CreatePurchaseOrderTransactionProcessor.php @@ -0,0 +1,76 @@ +updatesTransactionStatus = $updatesTransactionStatus; + $this->createsTransaction = $createsTransaction; + $this->createsTransactionDetail = $createsTransactionDetail; + $this->updatesTransaction = $updatesTransaction; + $this->deletesTransactionDetails = $deletesTransactionDetails; + } + + + /** + * @param Booking $booking + * @param TransactionObject $object + * @return Transaction|\Illuminate\Database\Eloquent\Model + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(Booking $booking, TransactionObject $object){ + /** @var Transaction $transaction */ + $transaction = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first(); + + !$transaction ? $transaction = $this->createsTransaction->execute($booking, $object) : $transaction = $this->updatesTransaction->execute($transaction, $object); + + $this->updatesTransactionStatus->execute($transaction, (float) number_format($object->getAmount(), 2, '.', '') === (float) number_format((float)$booking->fix_amount, 2, '.', '') ? ApprovalStatus::PENDING_VERIFICATION : ApprovalStatus::PENDING_SUBMISSION); + + $this->deletesTransactionDetails->execute($transaction); + + foreach ($object->getDetails() as $product){ + $this->createsTransactionDetail->execute($transaction, $product); + } + + return $transaction; + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/Services/CreatesTransaction.php b/app/Classes/Modules/Transactions/Services/CreatesTransaction.php index b2e13067..06530564 100644 --- a/app/Classes/Modules/Transactions/Services/CreatesTransaction.php +++ b/app/Classes/Modules/Transactions/Services/CreatesTransaction.php @@ -5,12 +5,12 @@ namespace App\Classes\Modules\Transactions\Services; use App\Classes\General\Eloquent\AbstractUpdateRelationshipRecord; use App\Classes\General\Interfaces\Transactionable; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; -use App\Models\Booking; use App\Models\Transaction; class CreatesTransaction extends AbstractUpdateRelationshipRecord { /** + * @param Transactionable $transactionable * @param TransactionObject $object * @return \Illuminate\Database\Eloquent\Model * @throws \App\Classes\Exceptions\MalformedRequestException diff --git a/app/Classes/Modules/Transactions/Services/DeletesTransaction.php b/app/Classes/Modules/Transactions/Services/DeletesTransaction.php new file mode 100644 index 00000000..66416d60 --- /dev/null +++ b/app/Classes/Modules/Transactions/Services/DeletesTransaction.php @@ -0,0 +1,19 @@ +handler($model); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/Services/GeneratesPurchaseOrderProducts.php b/app/Classes/Modules/Transactions/Services/GeneratesPurchaseOrderProducts.php new file mode 100644 index 00000000..16d162eb --- /dev/null +++ b/app/Classes/Modules/Transactions/Services/GeneratesPurchaseOrderProducts.php @@ -0,0 +1,72 @@ +products = $products; + } + + + public function execute(Transaction $transaction, float $amount){ + + $products = collect(); + + $amountDifference = $amount - $transaction->amount; + $transactionDetails = $transaction->transactionDetails()->select('*', DB::raw('abs(price - '.abs($amountDifference).') as nearest_price'))->orderBy('nearest_price')->get(); + foreach ($transactionDetails as $product) { + $units = floor(abs($amountDifference) / $product->price); + $quantity = $product->quantity; + + if($product->price <= 0){ + $amountDifference = $amountDifference + ($product->price * $product->quantity); + continue; + } + + if($amountDifference > 0){ + $quantity = $product->quantity + $units; + $amountDifference = $amountDifference - ($product->price * $units); + } + + if($amountDifference < 0) { + $units = ceil(abs($amountDifference) / $product->price); + $quantity = $product->quantity - $units; + + if($quantity <= 0){ + $amountDifference = $amountDifference + ($product->price * $product->quantity); + continue; + } + + $amountDifference = $amountDifference + ($product->price * $quantity); + } + + $products->push([ + 'description' => $product->product_name, + 'quantity' => (int) $quantity, + 'stockCode' => $product->product_code, + 'total' => $product->price * $quantity, + 'unit_price' => (float) $product->price, + ]); + + } + + return $products; + + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Wallets/ControllersLogic/CreditWalletLogic.php b/app/Classes/Modules/Wallets/ControllersLogic/CreditWalletLogic.php new file mode 100644 index 00000000..e2941c3c --- /dev/null +++ b/app/Classes/Modules/Wallets/ControllersLogic/CreditWalletLogic.php @@ -0,0 +1,107 @@ + 'Credit into Company Wallet', + 'message' => 'You have successfully credit company wallet' + ]; + } + + + /** @var FetchesWallet */ + private $fetchesWallet; + + /** @var GeneratesTransactionBillNumber */ + private $generatesTransactionBillNumber; + + /** @var CreatesTransaction */ + private $createsTransaction; + + /** @var UpdatesWallet */ + private $updatesWallet; + + /** + * CreateWalletLogic constructor. + * @param FetchesWallet $fetchesWallet + * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber + * @param CreatesTransaction $createsTransaction + * @param UpdatesWallet $updatesWallet + */ + public function __construct( + FetchesWallet $fetchesWallet, + GeneratesTransactionBillNumber $generatesTransactionBillNumber, + CreatesTransaction $createsTransaction, + UpdatesWallet $updatesWallet + ) + { + $this->fetchesWallet = $fetchesWallet; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->createsTransaction = $createsTransaction; + $this->updatesWallet = $updatesWallet; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $wallet = $this->fetchesWallet->execute(['id' => $request->input('wallet_id')]); + + $billNumber = $this->generatesTransactionBillNumber->execute('DEBIT-NOTE-'); + + $transaction_object = new TransactionObject( + $billNumber, + TransactionType::CREDIT_NOTE, + 1, + $wallet->company->id, + 1, + PaymentMethodType::WALLET, + $request->input('amount'), + $request->input('amount'), + 1, + 1, + 1, + 0, + 0, + null, + ApprovalStatus::PENDING_SUBMISSION, + [] + ); + + $transaction = $this->createsTransaction->execute($wallet, $transaction_object); + $updateWalletAmount = $wallet->amount + $transaction->amount; + + $walletOject = new WalletObject($wallet->company->id, $wallet->currency_id, $wallet->code, $updateWalletAmount); + + $wallet = $this->updatesWallet->execute($wallet, $walletOject); + + return $this->resourceResponse(new WalletResource($wallet)); + } +} diff --git a/app/Classes/Modules/Wallets/ControllersLogic/DebitWalletLogic.php b/app/Classes/Modules/Wallets/ControllersLogic/DebitWalletLogic.php new file mode 100644 index 00000000..9437b320 --- /dev/null +++ b/app/Classes/Modules/Wallets/ControllersLogic/DebitWalletLogic.php @@ -0,0 +1,107 @@ + 'Debit into Company Wallet', + 'message' => 'You have successfully debit company wallet' + ]; + } + + + /** @var FetchesWallet */ + private $fetchesWallet; + + /** @var GeneratesTransactionBillNumber */ + private $generatesTransactionBillNumber; + + /** @var CreatesTransaction */ + private $createsTransaction; + + /** @var UpdatesWallet */ + private $updatesWallet; + + /** + * CreateWalletLogic constructor. + * @param FetchesWallet $fetchesWallet + * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber + * @param CreatesTransaction $createsTransaction + * @param UpdatesWallet $updatesWallet + */ + public function __construct( + FetchesWallet $fetchesWallet, + GeneratesTransactionBillNumber $generatesTransactionBillNumber, + CreatesTransaction $createsTransaction, + UpdatesWallet $updatesWallet + ) + { + $this->fetchesWallet = $fetchesWallet; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->createsTransaction = $createsTransaction; + $this->updatesWallet = $updatesWallet; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $wallet = $this->fetchesWallet->execute(['id' => $request->input('wallet_id')]); + + $billNumber = $this->generatesTransactionBillNumber->execute('DEBIT-NOTE-'); + + $transaction_object = new TransactionObject( + $billNumber, + TransactionType::DEBIT_NOTE, + 1, + $wallet->company->id, + 1, + PaymentMethodType::WALLET, + $request->input('amount'), + $request->input('amount'), + 1, + 1, + 1, + 0, + 0, + null, + ApprovalStatus::PENDING_SUBMISSION, + [] + ); + + $transaction = $this->createsTransaction->execute($wallet, $transaction_object); + $updateWalletAmount = $wallet->amount - $transaction->amount; + + $walletOject = new WalletObject($wallet->company->id, $wallet->currency_id, $wallet->code, $updateWalletAmount); + + $wallet = $this->updatesWallet->execute($wallet, $walletOject); + + return $this->resourceResponse(new WalletResource($wallet)); + } +} diff --git a/app/Classes/Modules/Wallets/ControllersLogic/TopUpWalletLogic.php b/app/Classes/Modules/Wallets/ControllersLogic/TopUpWalletLogic.php index 8497ec32..0c51118a 100644 --- a/app/Classes/Modules/Wallets/ControllersLogic/TopUpWalletLogic.php +++ b/app/Classes/Modules/Wallets/ControllersLogic/TopUpWalletLogic.php @@ -3,15 +3,18 @@ namespace App\Classes\Modules\Wallets\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; - use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject; -use App\Classes\Modules\Wallets\Services\ListsWallet; -use App\Classes\Modules\Wallets\Services\FetchesWallet; +use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; +use App\Classes\Modules\Companies\Services\FetchesCompany; +use App\Classes\Modules\Wallets\Services\CreatesWallet; +use App\Classes\Modules\Wallets\Services\GeneratesWalletCode; +use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; +use App\Classes\Modules\Billplzs\Services\CreatesBillplzBill; +use App\Classes\Modules\Transactions\Services\CreatesTransaction; use App\Classes\ValueObjects\Constants\TransactionType; - -use App\Classes\Modules\Wallets\Standards\Rules\CanTopUpWallet; +use App\Classes\ValueObjects\Constants\PaymentMethodType; +use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Http\Resources\WalletResource; -use App\Classes\Modules\Transactions\Processors\CreateWalletTransactionProcessor; use ErrorException; use Illuminate\Http\JsonResponse; @@ -30,26 +33,50 @@ class TopUpWalletLogic extends AbstractControllerLogic ]; } - /** @var FetchesWallet */ - private $fetchesWallet; - /** @var CanTopUpWallet */ - private $canTopUpWallet; + /** @var FetchesCompany */ + private $fetchesCompany; - /** @var CreateWalletTransactionProcessor */ - private $createWalletTransactionProcessor; + /** @var GeneratesWalletCode */ + private $generatesWalletCode; + + /** @var CreatesWallet */ + private $createsWallet; + + /** @var GeneratesTransactionBillNumber */ + private $generatesTransactionBillNumber; + + /** @var CreatesWalletTransaction */ + private $createsWalletTransaction; + + /** @var CreatesBillplzBill */ + private $createsBillplzBill; + + /** @var CreatesTransaction */ + private $createsTransaction; /** * CreateWalletLogic constructor. - * @param CreatesWallet $createsWallet + * @param FetchesCompany $fetchesCompany * @param GeneratesWalletCode $generatesWalletCode - * @param CanCreateCompanyWallet $canCreateCompanyWallet + * @param CreatesWallet $createsWallet + * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber */ - public function __construct(CanTopUpWallet $canTopUpWallet, FetchesWallet $fetchesWallet, CreateWalletTransactionProcessor $createWalletTransactionProcessor) + public function __construct( + FetchesCompany $fetchesCompany, + GeneratesWalletCode $generatesWalletCode, + CreatesWallet $createsWallet, + GeneratesTransactionBillNumber $generatesTransactionBillNumber, + CreatesBillplzBill $createsBillplzBill, + CreatesTransaction $createsTransaction + ) { - $this->canTopUpWallet = $canTopUpWallet; - $this->fetchesWallet = $fetchesWallet; - $this->createWalletTransactionProcessor = $createWalletTransactionProcessor; + $this->fetchesCompany = $fetchesCompany; + $this->generatesWalletCode = $generatesWalletCode; + $this->createsWallet = $createsWallet; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->createsBillplzBill = $createsBillplzBill; + $this->createsTransaction = $createsTransaction; } /** @@ -59,13 +86,45 @@ class TopUpWalletLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - $wallet = $this->fetchesWallet->execute(['id' => $request->input('wallet_id')]); + $company = $this->fetchesCompany->execute(['id' => $request->input('company_id')]); + if (!$company->wallets()->first()) { + $object = new WalletObject($company->id, 1, $this->generatesWalletCode->execute()); + $wallet = $this->createsWallet->execute($object, $company); + } - $walletOject = new WalletObject( $wallet->company->id, $wallet->currency_id, $wallet->code, $request->input('amount')); + $user = $company->employees()->first(); + $billNumber = $this->generatesTransactionBillNumber->execute('TOPUP-'); + + $billPlzBill = $this->createsBillplzBill->execute( + $user->name, + $user->email, + 'This payment is made for wallet topup. ' . $company->reference, + $request->input('amount'), + $billNumber, + $request->input('bank_code') + ); - $this->canTopUpWallet->passes($walletOject); + $transaction_object = new TransactionObject( + $billNumber, + TransactionType::TOP_UP, + 1, + $company->id, + 1, + PaymentMethodType::PAYMENT_GATEWAY, + $request->input('amount'), + $request->input('amount'), + 1, + 1, + 1, + 0, + 0, + null, + ApprovalStatus::PENDING_SUBMISSION, + [], + $billPlzBill->id + ); - $transaction = $this->createWalletTransactionProcessor->execute($wallet, $walletOject, TransactionType::TOP_UP); + $transaction = $this->createsTransaction->execute($company->wallets()->first(), $transaction_object); return $this->resourceResponse(new WalletResource($wallet)); } diff --git a/app/Classes/Modules/Wallets/Services/CreatesWallet.php b/app/Classes/Modules/Wallets/Services/CreatesWallet.php index c114b9de..2a927e6d 100644 --- a/app/Classes/Modules/Wallets/Services/CreatesWallet.php +++ b/app/Classes/Modules/Wallets/Services/CreatesWallet.php @@ -21,8 +21,6 @@ class CreatesWallet extends AbstractUpdateRelationshipRecord $model->code = $object->getCode(); $model->currency_id = $object->getCurrency(); - return $this->handler($company->wallets(), $model); - } } diff --git a/app/Classes/ValueObjects/Constants/DocumentType.php b/app/Classes/ValueObjects/Constants/DocumentType.php index 2b053163..04edf25c 100644 --- a/app/Classes/ValueObjects/Constants/DocumentType.php +++ b/app/Classes/ValueObjects/Constants/DocumentType.php @@ -17,6 +17,7 @@ final class DocumentType { public const WALLET_TOP_UP_PAYMENT_PROOF = 'WALLET_TOP_UP_PAYMENT_PROOF'; public const WALLET_REFUND_PAYMENT_PROOF = 'WALLET_REFUND_PAYMENT_PROOF'; + public const PROFORMA_INVOICE = 'PROFORMA_INVOICE'; public const PURCHASE_ORDER = 'PURCHASE_ORDER'; public const DELIVER_ORDER = 'DELIVER_ORDER'; public const INVOICE = 'INVOICE'; diff --git a/app/Classes/ValueObjects/Constants/TransactionType.php b/app/Classes/ValueObjects/Constants/TransactionType.php index 05771c12..040f63fa 100644 --- a/app/Classes/ValueObjects/Constants/TransactionType.php +++ b/app/Classes/ValueObjects/Constants/TransactionType.php @@ -12,7 +12,7 @@ final class TransactionType { public const BILL = 3; - public const PERFORMA = 4; + public const PROFORMA = 4; public const TOP_UP = 5; @@ -24,5 +24,7 @@ final class TransactionType { public const CREDIT_NOTE = 9; + public const DEBIT_NOTE = 11; + public const WITHDRAW = 10; } diff --git a/app/Http/Controllers/Billplzs/CallbackBillplzController.php b/app/Http/Controllers/Billplz/CallbackBillplzController.php similarity index 50% rename from app/Http/Controllers/Billplzs/CallbackBillplzController.php rename to app/Http/Controllers/Billplz/CallbackBillplzController.php index 33525632..9ee281e6 100644 --- a/app/Http/Controllers/Billplzs/CallbackBillplzController.php +++ b/app/Http/Controllers/Billplz/CallbackBillplzController.php @@ -1,19 +1,21 @@ execute($request); } diff --git a/app/Http/Controllers/Billplzs/CreateBillplzBillController.php b/app/Http/Controllers/Billplz/CreateBillplzBillController.php similarity index 82% rename from app/Http/Controllers/Billplzs/CreateBillplzBillController.php rename to app/Http/Controllers/Billplz/CreateBillplzBillController.php index cd62cfec..c10bad79 100644 --- a/app/Http/Controllers/Billplzs/CreateBillplzBillController.php +++ b/app/Http/Controllers/Billplz/CreateBillplzBillController.php @@ -1,6 +1,6 @@ login(User::find(1)); + return $logic->execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Bookings/CreateProformaInvoiceTransaction.php b/app/Http/Controllers/Bookings/CreateProformaInvoiceTransaction.php new file mode 100644 index 00000000..11b0739c --- /dev/null +++ b/app/Http/Controllers/Bookings/CreateProformaInvoiceTransaction.php @@ -0,0 +1,20 @@ +execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Bookings/RegenerateInvoiceBookingController.php b/app/Http/Controllers/Bookings/RegenerateInvoiceBookingController.php new file mode 100644 index 00000000..d63c1b9c --- /dev/null +++ b/app/Http/Controllers/Bookings/RegenerateInvoiceBookingController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Bookings/UpdateBookingAmountController.php b/app/Http/Controllers/Bookings/UpdateBookingAmountController.php new file mode 100644 index 00000000..d0f6dd6c --- /dev/null +++ b/app/Http/Controllers/Bookings/UpdateBookingAmountController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Transactions/CreateTransactionController.php b/app/Http/Controllers/Transactions/CreateTransactionController.php index c311ca19..fa67604a 100644 --- a/app/Http/Controllers/Transactions/CreateTransactionController.php +++ b/app/Http/Controllers/Transactions/CreateTransactionController.php @@ -10,6 +10,6 @@ class CreateTransactionController { public function create(Request $request, CreateTransactionLogic $logic): JsonResponse { - return $logic->execute($request); + return $logic->logic($request); } } \ No newline at end of file diff --git a/app/Http/Controllers/Transactions/DeletePaymentProofDocumentController.php b/app/Http/Controllers/Transactions/DeletePaymentProofDocumentController.php new file mode 100644 index 00000000..d90cf1df --- /dev/null +++ b/app/Http/Controllers/Transactions/DeletePaymentProofDocumentController.php @@ -0,0 +1,14 @@ +execute($request); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Transactions/UpdatePaymentTransactionStatusController.php b/app/Http/Controllers/Transactions/UpdatePaymentTransactionStatusController.php new file mode 100644 index 00000000..047bc1dc --- /dev/null +++ b/app/Http/Controllers/Transactions/UpdatePaymentTransactionStatusController.php @@ -0,0 +1,14 @@ +execute($request); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Wallets/CreditWalletController.php b/app/Http/Controllers/Wallets/CreditWalletController.php new file mode 100644 index 00000000..b3143588 --- /dev/null +++ b/app/Http/Controllers/Wallets/CreditWalletController.php @@ -0,0 +1,15 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Wallets/DebitWalletController.php b/app/Http/Controllers/Wallets/DebitWalletController.php new file mode 100644 index 00000000..7feafb39 --- /dev/null +++ b/app/Http/Controllers/Wallets/DebitWalletController.php @@ -0,0 +1,15 @@ +execute($request); + } +} diff --git a/app/Http/Resources/BookingResource.php b/app/Http/Resources/BookingResource.php index 30f2a733..80199df9 100644 --- a/app/Http/Resources/BookingResource.php +++ b/app/Http/Resources/BookingResource.php @@ -5,6 +5,7 @@ namespace App\Http\Resources; use App\Classes\Modules\Bookings\Services\CalculatesBookingFloatingAmount; use App\Classes\Modules\Bookings\Services\CalculatesBookingOutstanding; use App\Classes\Modules\Bookings\Services\CalculatesBookingPayableAmount; +use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\ValueObjects\Constants\DocumentType; @@ -23,7 +24,6 @@ class BookingResource extends JsonResource */ public function toArray($request) { - // dd($this->service); return [ 'id' => $this->id, 'company' => new CompanyResource($this->company), @@ -32,8 +32,8 @@ class BookingResource extends JsonResource 'marking' => $this->marking, '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)), - 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)), + '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)), 'fixed_currency' => new CurrencyResource($this->fixedCurrency), 'convertible_currency' => new CurrencyResource($this->convertibleCurrency), 'conversion_currency' => new CurrencyResource($this->conversionCurrency), @@ -42,6 +42,7 @@ class BookingResource extends JsonResource 'delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER)->first()), 'invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::INVOICE)->first()), 'supplier_delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->first()), + 'proforma_invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()), ], 'status' => $this->status, 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'), @@ -56,9 +57,17 @@ class BookingResource extends JsonResource 'expired_payment_attempts' => TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '<', Carbon::now())->get()), 'payment_history' => TransactionResource::collection($this->transactions()->where(function($query){ $query->where(function($query){ - $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED]); + $query->where(function($query){ + $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED]); + })->orWhere(function($query){ + $query->where('type', TransactionType::BILL)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); })->orWhere(function($query){ - $query->where('type', TransactionType::BILL)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + $query->where(function($query){ + $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]); + })->orWhere(function($query){ + $query->where('type', TransactionType::CREDIT_NOTE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); }); })->latest()->get()) ]) diff --git a/app/Http/Resources/CompanyResource.php b/app/Http/Resources/CompanyResource.php index a35c7082..5488df0e 100644 --- a/app/Http/Resources/CompanyResource.php +++ b/app/Http/Resources/CompanyResource.php @@ -12,6 +12,7 @@ use App\Classes\ValueObjects\Constants\SegmentConstants; use App\Classes\ValueObjects\Constants\TransactionType; use App\Models\Currency; use App\Models\SegmentConstant; +use Carbon\Carbon; use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Support\Facades\Auth; @@ -26,6 +27,7 @@ class CompanyResource extends JsonResource public function toArray($request) { $lastPayment = $this->transactions()->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->orderBy('id', 'DESC')->first(); + $totalPayments = $this->transactions()->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount'); return [ 'id' => $this->id, 'name' => $this->name, @@ -38,7 +40,14 @@ class CompanyResource extends JsonResource 'employee' => new UserResource(Auth::user()->type === RoleTypes::USER ? $this->employees()->where('email', '=', Auth::user()->email)->first() : $this->employees()->orderBy('id', 'DESC')->first()), 'identification' => new DocumentResource($this->documents->whereIn('document_type', DocumentType::IDENTIFICATION_DOCUMENTS)->first()), 'bookings' => $this->whenLoaded('bookings', $this->bookings()->orderBy('id', 'DESC')->get(), []), - 'total_payments' => (float) $this->transactions()->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount'), + 'confirmed_bookings' => $this->bookings()->whereHas('transactions', function ($query){ + $query->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + })->count(), + 'total_payments' => (float) $totalPayments, + 'average_spending_per_day' => (float) $totalPayments / ($this->created_at->diff(Carbon::now())->days === 0 ? 1 : $this->created_at->diff(Carbon::now())->days), + 'average_spending_per_booking' => (float) $totalPayments > 0 ? $totalPayments / $this->bookings()->whereHas('transactions', function ($query){ + $query->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + })->count() : $totalPayments, 'last_payment' => $lastPayment ? $lastPayment->created_at->diffForHumans() : 'No Payments', 'personal_banks' => BankResource::collection($this->banks->where('type', BankAccountType::PERSONAL)), 'recipient_banks' => [ @@ -51,10 +60,8 @@ class CompanyResource extends JsonResource $segment = SegmentConstant::where('reference', SegmentConstants::SUPPLIER_CURRENCIES)->where('detail->id', $this->id)->first(); return $segment ? CurrencyResource::collection(Currency::whereIn('id', $segment->detail->currencies)->get()) : []; }), + 'wallet' => WalletResource::collection($this->wallets), 'created_at' => $this->created_at->format('d-m-Y') - - ]; - } } diff --git a/app/Http/Resources/TransactionResource.php b/app/Http/Resources/TransactionResource.php index 14506635..9a9d8a7a 100644 --- a/app/Http/Resources/TransactionResource.php +++ b/app/Http/Resources/TransactionResource.php @@ -3,7 +3,6 @@ namespace App\Http\Resources; use App\Classes\ValueObjects\Constants\TransactionType; -use App\Models\Transaction; use Carbon\Carbon; use Illuminate\Http\Resources\Json\JsonResource; @@ -23,9 +22,9 @@ class TransactionResource extends JsonResource 'type' => (int) $this->type, 'bill_no' => $this->bill_no, 'payment_reference' => $this->payment_reference, - 'payment_method' => $this->payment_method, + 'payment_method' => (float) $this->payment_method, + 'recipient_bank_account' => new BankResource($this->when((int) $this->type === TransactionType::BILL, $this->booking->bank)), 'issuer_name' => $this->issuerCompany->name, - 'recipient_bank_account' => new BankResource($this->when((int) $this->type === TransactionType::BILL,$this->booking->bank)), 'amount' => (double) $this->amount, 'original_amount' => (double) $this->original_amount, 'currency' => new CurrencyResource($this->currency), @@ -38,7 +37,11 @@ class TransactionResource extends JsonResource 'documents' => new DocumentResource($this->documents()->first()), 'customer_booking' => new TransactionResource($this->when((int) $this->type === TransactionType::BILL, $this->booking->transactions()->payments()->complete()->where('original_amount', '=', $this->original_amount)->where('id', '<', $this->id)->orderByDesc('id')->first())), 'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'), - 'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A') + 'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'), + 'interval' => [ + 'value' => (Carbon::parse($this->created_at)->addDays(3)->gt(Carbon::now()) ) ? '+' : '-' , + 'duration' => Carbon::parse($this->created_at)->addDays(3)->diff(Carbon::now())->format('%d'), + ], ]; } } diff --git a/app/Http/Resources/WalletResource.php b/app/Http/Resources/WalletResource.php index 37ff5dbd..39c634eb 100644 --- a/app/Http/Resources/WalletResource.php +++ b/app/Http/Resources/WalletResource.php @@ -2,6 +2,7 @@ namespace App\Http\Resources; +use App\Classes\ValueObjects\Constants\TransactionType; use Illuminate\Http\Resources\Json\JsonResource; class WalletResource extends JsonResource @@ -19,7 +20,17 @@ class WalletResource extends JsonResource 'code' => $this->code, 'currency_id' => $this->currency_id, 'amount' => (double) $this->amount, - 'company_id' => (int) $this->company_id + 'company_id' => (int) $this->owner->id, + 'transactions' => $this->transactions()->orderBy('id', 'DESC')->get(), + 'topup_transactions' => $this->transactions()->where('type', TransactionType::TOP_UP)->orderBy('id', 'DESC')->get(), + + // 'transaction' => $this->whenLoaded('transactions', function() { + // return [ + // 'topup' => $this->transactions + // ]; + // }), + // 'transaction' // all + // 'top_transaction' // only topup ]; } } diff --git a/app/Models/Booking.php b/app/Models/Booking.php index c3492241..ea01b302 100644 --- a/app/Models/Booking.php +++ b/app/Models/Booking.php @@ -6,11 +6,8 @@ use App\Classes\General\Interfaces\Documentable; use App\Classes\General\Interfaces\Transactionable; use App\Classes\ValueObjects\Constants\RoleTypes; use App\Scopes\CustomerBookingsScope; -use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\MorphMany; -use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\SoftDeletes; /** @@ -22,8 +19,8 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property string marking * @property string reference * @property float fix_amount - * @property \App\Models\Currency convertible_currency_id - * @property \App\Models\Currency conversion_currency_id + * @property int convertible_currency_id + * @property int conversion_currency_id */ class Booking extends AbstractModel implements Documentable, Transactionable { diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index 42a850c3..a3e16c79 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -7,6 +7,7 @@ use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\TransactionType; use Carbon\Carbon; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; @@ -17,6 +18,8 @@ use Illuminate\Database\Eloquent\Relations\MorphTo; class Transaction extends AbstractModel implements Documentable { + use SoftDeletes; + protected $table = 'transactions'; public function owner(): morphTo @@ -126,10 +129,15 @@ class Transaction extends AbstractModel implements Documentable /** * @param Builder $query + * @param string $payment_reference * @return Builder */ - public function scopeRefunds(Builder $query) + public function scopeRefunds(Builder $query, ?string $payment_reference = NULL) { + if($payment_reference){ + $query->where('payment_reference', $payment_reference); + } + return $query->where('type', TransactionType::REFUND); } diff --git a/app/Models/User.php b/app/Models/User.php index d41cbb7f..6fd8b6b0 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -5,6 +5,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\SoftDeletes; use Spatie\Permission\Traits\HasRoles; use Tymon\JWTAuth\Contracts\JWTSubject; @@ -23,7 +24,7 @@ class User extends AbstractModel implements AuthorizableContract, CanResetPasswordContract { - use HasRoles, Notifiable, Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail; + use HasRoles, Notifiable, Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail, SoftDeletes; /** diff --git a/app/Models/Wallet.php b/app/Models/Wallet.php index 52d8f718..29c3ddc9 100644 --- a/app/Models/Wallet.php +++ b/app/Models/Wallet.php @@ -2,13 +2,14 @@ namespace App\Models; +use App\Classes\General\Interfaces\Transactionable; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\MorphMany; -class Wallet extends AbstractModel +class Wallet extends AbstractModel implements Transactionable { use SoftDeletes; diff --git a/composer.json b/composer.json index 3323db18..32f52d83 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ "ext-zip": "*", "barryvdh/laravel-dompdf": "^0.9.0", "carlos-meneses/laravel-mpdf": "^2.1", - "doctrine/dbal": "2.*", + "doctrine/dbal": "^2.12.1", "fideloper/proxy": "^4.2", "fruitcake/laravel-cors": "^1.0", "guzzlehttp/guzzle": "^6.3", diff --git a/config/billplz.php b/config/billplz.php index ac5b3a75..fb8ed920 100644 --- a/config/billplz.php +++ b/config/billplz.php @@ -1,7 +1,7 @@ env('BILLPLZ_BASE_URL', 'https://www.billplz-sandbox.com'), + 'base_url' => env('BILLPLZ_BASE_URL', 'https://www.billplz.com'), 'api_key' => env('BILLPLZ_API_KEY', '0fa4c710-761b-4a7a-a501-c2c2d02643d5'), 'x_signature_key' => env('BILLPLZ_X_SIGNATURE_KEY', 'S-pbNVthVRsvnPfZlgLwqqOg'), 'collection_id' => env('BILLPLZ_COLLECTION_ID', 'hev2wdjy'), diff --git a/database/seeds/FakeBookingTransactions.php b/database/seeds/FakeBookingTransactions.php index 08ff95f7..7eafda1d 100644 --- a/database/seeds/FakeBookingTransactions.php +++ b/database/seeds/FakeBookingTransactions.php @@ -230,7 +230,7 @@ class FakeBookingTransactions extends Seeder Constants\TransactionType::PAYMENT, Constants\TransactionType::INVOICE, Constants\TransactionType::BILL, - Constants\TransactionType::PERFORMA, + Constants\TransactionType::PROFORMA, Constants\TransactionType::TOP_UP, Constants\TransactionType::REFUND, Constants\TransactionType::PURCHASE_ORDER, diff --git a/resources/assets/images/—Pngtree—2019 chinese new year lantern_951828.jpg b/resources/assets/images/—Pngtree—2019 chinese new year lantern_951828.jpg new file mode 100644 index 00000000..dd7ceda3 Binary files /dev/null and b/resources/assets/images/—Pngtree—2019 chinese new year lantern_951828.jpg differ diff --git a/resources/assets/sass/modules/_buttons.scss b/resources/assets/sass/modules/_buttons.scss index e4c1e5b4..3a9879eb 100644 --- a/resources/assets/sass/modules/_buttons.scss +++ b/resources/assets/sass/modules/_buttons.scss @@ -120,6 +120,10 @@ button:focus{ outline: none !important; } + +button:disabled { + cursor: not-allowed; +} /* Alternate buttons -------------------------------------------------- diff --git a/resources/assets/vue/components/accounts/forms/LogOutFormComponent.vue b/resources/assets/vue/components/accounts/forms/LogOutFormComponent.vue index b32d8912..4956260f 100644 --- a/resources/assets/vue/components/accounts/forms/LogOutFormComponent.vue +++ b/resources/assets/vue/components/accounts/forms/LogOutFormComponent.vue @@ -1,10 +1,25 @@