diff --git a/app/Classes/General/Eloquent/Filters/CurrencyRateIsNotEqual.php b/app/Classes/General/Eloquent/Filters/CurrencyRateIsNotEqual.php new file mode 100644 index 00000000..0372e760 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/CurrencyRateIsNotEqual.php @@ -0,0 +1,20 @@ +where('currency_rate', '!=', $value); + } + +} \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/HasPendingVerifyTransaction.php b/app/Classes/General/Eloquent/Filters/HasPendingVerifyTransaction.php new file mode 100644 index 00000000..c97af23c --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/HasPendingVerifyTransaction.php @@ -0,0 +1,23 @@ +whereHas('transactions', function ($q) { + $q->where('status', ApprovalStatus::PENDING_VERIFICATION); + }); + } +} \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/IsPartialRefund.php b/app/Classes/General/Eloquent/Filters/IsPartialRefund.php new file mode 100644 index 00000000..1378a94c --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/IsPartialRefund.php @@ -0,0 +1,26 @@ +whereHas('owner', function ($q) use ($value) { + if ($value) { + $q->where('original_amount', '!=', DB::raw('transactions.original_amount')); + } else { + $q->where('original_amount', DB::raw('transactions.original_amount')); + } + }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/OwnerDoesNotHaveTransactionType.php b/app/Classes/General/Eloquent/Filters/OwnerDoesNotHaveTransactionType.php new file mode 100644 index 00000000..4dcd401c --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/OwnerDoesNotHaveTransactionType.php @@ -0,0 +1,24 @@ +whereDoesntHave('owner', function($query) use($value) { + return $query->whereHas('transactions', function($query) use($value) { + return $query->where('transactions.type', $value); + }); + }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/OwnerHasTransactionType.php b/app/Classes/General/Eloquent/Filters/OwnerHasTransactionType.php new file mode 100644 index 00000000..7f96643f --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/OwnerHasTransactionType.php @@ -0,0 +1,24 @@ +whereHas('owner', function($query) use($value) { + return $query->whereHas('transactions', function($query) use($value) { + return $query->where('transactions.type', $value); + }); + }); + } +} diff --git a/app/Classes/General/Eloquent/Filters/ReceiverIn.php b/app/Classes/General/Eloquent/Filters/ReceiverIn.php new file mode 100644 index 00000000..3ce91559 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/ReceiverIn.php @@ -0,0 +1,20 @@ +whereIn('receiver', $value); + } + +} \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/WithoutBillGroup.php b/app/Classes/General/Eloquent/Filters/WithoutBillGroup.php new file mode 100644 index 00000000..6d6794e8 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/WithoutBillGroup.php @@ -0,0 +1,22 @@ +whereDoesntHave('billGroup'); + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php index 0648629e..171b4360 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php @@ -14,6 +14,7 @@ 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\ControllersLogic\UpdateRefundTransactionStatusLogic; use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; @@ -48,6 +49,9 @@ class CreateBookingRefundLogic extends AbstractControllerLogic /** @var CreatesTransaction */ private $createsTransaction; + /** @var UpdateRefundTransactionStatusLogic */ + private $updateRefundTransactionStatusLogic; + /** * CreateBookingPaymentLogic constructor. * @param FetchesBookingQuotation $fetchBookingQuotation @@ -55,14 +59,16 @@ class CreateBookingRefundLogic extends AbstractControllerLogic * @param UpdatesTransactionStatus $updatesTransactionStatus * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber * @param CreatesTransaction $createsTransaction + * @param UpdateRefundTransactionStatusLogic $updateRefundTransactionStatusLogic */ - 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, UpdateRefundTransactionStatusLogic $updateRefundTransactionStatusLogic) { $this->fetchBookingQuotation = $fetchBookingQuotation; $this->fetchesTransaction = $fetchesTransaction; $this->updatesTransactionStatus = $updatesTransactionStatus; $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; $this->createsTransaction = $createsTransaction; + $this->updateRefundTransactionStatusLogic = $updateRefundTransactionStatusLogic; } /** @@ -75,12 +81,14 @@ class CreateBookingRefundLogic extends AbstractControllerLogic $transaction = $this->fetchesTransaction->execute(['id' => $request->route('payment_id')]); - if ($transaction->transactions()->bills()->first()) { - throw new MalformedRequestException('Booking under white form cannot request for refund'); - } - $booking = $transaction->owner; + $invoice = $booking->transactions()->where('type', TransactionType::INVOICE)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first(); + + if(auth()->user()->type === 3) { + throw new MalformedRequestException('You do not have the permission to refund the order.'); + } + $billNumber = $this->generatesTransactionBillNumber->execute('RFD-'); $refund = $transaction->transactions()->refunds()->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->sum('original_amount'); @@ -92,7 +100,8 @@ class CreateBookingRefundLogic extends AbstractControllerLogic $refundAmount = bcdiv($request->input('amount'), $transaction->currency_rate, 7); // refund service charges if is fully refund - $refundTotal = ($refund + $request->input('amount')) == $transaction->original_amount ? $refundAmount + $transaction->service_charge + $transaction->tax : $refundAmount; + $isFullyRefund = ($refund + $request->input('amount')) == $transaction->original_amount; + $refundTotal = $isFullyRefund ? $refundAmount + $transaction->service_charge + $transaction->tax : $refundAmount; $object = new TransactionObject($billNumber, TransactionType::REFUND, 1, $booking->company->id, 1, PaymentMethodType::CASH, @@ -100,9 +109,30 @@ class CreateBookingRefundLogic extends AbstractControllerLogic $transaction->original_currency_id, $transaction->currency_rate, 0, 0, null, ApprovalStatus::PENDING_VERIFICATION, [], $transaction->bill_no); - $transaction = $this->createsTransaction->execute($transaction, $object); + $refund_transaction = $this->createsTransaction->execute($transaction, $object); - return $this->resourceResponse(new TransactionResource($transaction)); + $bookingInWhiteForm = $transaction->transactions()->bills()->first(); + + // create supplier refund + if ($bookingInWhiteForm) { + $billNumber = $this->generatesTransactionBillNumber->execute('SRFD-'); + $supplierRefundTotal = bcdiv($request->input('amount'), $bookingInWhiteForm->currency_rate, 7); + + $object = new TransactionObject($billNumber, TransactionType::SUPPLIER_REFUND, 1, $bookingInWhiteForm->issuer, + 1, PaymentMethodType::CASH, + $supplierRefundTotal, $request->input('amount'), 1, + $transaction->original_currency_id, $bookingInWhiteForm->currency_rate, + 0, 0, null, ApprovalStatus::PENDING_VERIFICATION, [], $transaction->bill_no); + + $transaction = $this->createsTransaction->execute($transaction, $object); + } else { + $request->route()->setParameter('id', $refund_transaction->id); + $request->route()->setParameter('status', ApprovalStatus::APPROVED); + $this->updateRefundTransactionStatusLogic->execute($request); + + } + + return $this->resourceResponse(new TransactionResource($refund_transaction)); } diff --git a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php index fabdd058..e40a947d 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php @@ -81,7 +81,7 @@ class UpdateBookingAmountLogic extends AbstractControllerLogic $minimum_amount = $booking->fix_amount - $this->calculatesBookingOutstanding->execute($booking); - if ((float)$input_amount < $minimum_amount) { + if (((float)$input_amount + 0.01) < (float)$minimum_amount) { throw new MalformedRequestException('Booking Amount cannot be less than '. $minimum_amount .'.'); } diff --git a/app/Classes/Modules/Bookings/Services/CalculatesBookingCurrencyAverageRate.php b/app/Classes/Modules/Bookings/Services/CalculatesBookingCurrencyAverageRate.php index da3fe0b4..9cb7717e 100644 --- a/app/Classes/Modules/Bookings/Services/CalculatesBookingCurrencyAverageRate.php +++ b/app/Classes/Modules/Bookings/Services/CalculatesBookingCurrencyAverageRate.php @@ -24,10 +24,22 @@ class CalculatesBookingCurrencyAverageRate public function execute(Booking $booking, $type){ + $transaction = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->latest()->get()[0]; + + $voucherRedemption = $transaction->voucherRedemption; + + $discount = 0; + + if ($voucherRedemption) { + $discount = $voucherRedemption->value; + } + if ($type == TransactionType::PAYMENT) { $totalPayment = $booking->fix_currency_id === 1 ? $booking->transactions()->payments()->complete()->sum('original_amount') : $booking->transactions()->payments()->complete()->selectRaw('sum(amount - service_charge - tax) as sub_total')->get()->sum('sub_total'); - return $this->calculatesBookingPayableAmount->execute($booking, $booking->fix_currency_id) / $totalPayment; + return $this->calculatesBookingPayableAmount->execute($booking, $booking->fix_currency_id) / ($totalPayment + $discount); } else if ($type == TransactionType::BILL) { diff --git a/app/Classes/Modules/Bookings/Services/CalculatesBookingOutstanding.php b/app/Classes/Modules/Bookings/Services/CalculatesBookingOutstanding.php index 5f2c7733..f3a70a6a 100644 --- a/app/Classes/Modules/Bookings/Services/CalculatesBookingOutstanding.php +++ b/app/Classes/Modules/Bookings/Services/CalculatesBookingOutstanding.php @@ -13,20 +13,25 @@ class CalculatesBookingOutstanding /** @var CalculatesBookingFloatingAmount */ private $calculatesBookingFloatingAmount; + /** @var CalculatesBookingRefundAmount */ + private $calculatesBookingRefundAmount; + /** * CalculatesBookingOutstanding constructor. * @param CalculatesBookingPayableAmount $calculatesBookingPayableAmount * @param CalculatesBookingFloatingAmount $calculatesBookingFloatingAmount + * @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount */ - public function __construct(CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingFloatingAmount $calculatesBookingFloatingAmount) + public function __construct(CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingFloatingAmount $calculatesBookingFloatingAmount, CalculatesBookingRefundAmount $calculatesBookingRefundAmount) { $this->calculatesBookingPayableAmount = $calculatesBookingPayableAmount; $this->calculatesBookingFloatingAmount = $calculatesBookingFloatingAmount; + $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; } public function execute(Booking $booking){ - return $booking->fix_amount - $this->calculatesBookingFloatingAmount->execute($booking, $booking->fix_currency_id) - $this->calculatesBookingPayableAmount->execute($booking, $booking->fix_currency_id); + return $booking->fix_amount - $this->calculatesBookingFloatingAmount->execute($booking, $booking->fix_currency_id) - $this->calculatesBookingPayableAmount->execute($booking, $booking->fix_currency_id) + $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id); } } \ 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 239545af..8792aaa6 100644 --- a/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php +++ b/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php @@ -9,7 +9,7 @@ class CalculatesBookingRefundAmount { public function execute(Booking $booking, int $type, ?string $payment_reference = null): float { - $refundAmounts = $booking->transactions()->payments()->get()->map(function ($payment) use ($type) { + $refundAmounts = $booking->transactions()->payments()->complete()->get()->map(function ($payment) use ($type) { return $this->calculateRefundAmount($payment, $type); }); diff --git a/app/Classes/Modules/Bookings/Services/CalculatesBookingTransferredAmount.php b/app/Classes/Modules/Bookings/Services/CalculatesBookingTransferredAmount.php index fc355d64..099d4571 100644 --- a/app/Classes/Modules/Bookings/Services/CalculatesBookingTransferredAmount.php +++ b/app/Classes/Modules/Bookings/Services/CalculatesBookingTransferredAmount.php @@ -13,7 +13,7 @@ class CalculatesBookingTransferredAmount public function execute(Booking $booking){ return $booking->transactions()->payments()->complete()->whereHas('transactions', function($query){ - return $query->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + return $query->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->where('type', TransactionType::BILL); })->sum('original_amount'); } diff --git a/app/Classes/Modules/Remarks/ControllersLogic/CreateRemarkLogic.php b/app/Classes/Modules/Remarks/ControllersLogic/CreateRemarkLogic.php new file mode 100644 index 00000000..46d822c5 --- /dev/null +++ b/app/Classes/Modules/Remarks/ControllersLogic/CreateRemarkLogic.php @@ -0,0 +1,62 @@ + 'Created Remark', + 'message' => 'You have successfully created a new Remark' + ]; + } + + /** @var CreateRemarkProcessor */ + private $createRemarkProcessor; + + /** + * CreateRemarkLogic constructor. + * @param CreateRemarkProcessor $createRemarkProcessor + */ + public function __construct(CreateRemarkProcessor $createRemarkProcessor) + { + $this->createRemarkProcessor = $createRemarkProcessor; + } + + /** + * @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 + { + $classs = '\\App\\Models\\' . Str::studly($request->input('model_type')); + + if (!class_exists($classs)) { + throw new MalformedRequestException('Unable to process this entity'); + } + + $remarkOwner = $classs::find($request->route('id')); + + $remarkObject = new RemarkObject($request->input('content'), auth()->user()->id); + + $remmark = $this->createRemarkProcessor->execute($remarkOwner, $remarkObject); + + return $this->resourceResponse(new RemarkResource($remmark)); + } +} diff --git a/app/Classes/Modules/Remarks/ControllersLogic/DeleteRemarkLogic.php b/app/Classes/Modules/Remarks/ControllersLogic/DeleteRemarkLogic.php new file mode 100644 index 00000000..b593d603 --- /dev/null +++ b/app/Classes/Modules/Remarks/ControllersLogic/DeleteRemarkLogic.php @@ -0,0 +1,66 @@ + 'Deleted Remark', + 'message' => 'You have successfully deleted a Remark' + ]; + } + + + /** @var CanDeleteRemark */ + private $canDeleteRemark; + + /** @var DeletesRemark */ + private $deletesRemark; + + /** @var FetchesRemark */ + private $fetchesRemark; + + /** + * DeleteRemarkControllersLogic constructor. + * @param CanDeleteRemark $canDeleteRemark + * @param DeletesRemark $deletesRemark + * @param FetchesRemark $fetchesRemark + */ + public function __construct(CanDeleteRemark $canDeleteRemark, DeletesRemark $deletesRemark, FetchesRemark $fetchesRemark) + { + $this->canDeleteRemark = $canDeleteRemark; + $this->deletesRemark = $deletesRemark; + $this->fetchesRemark = $fetchesRemark; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $this->canDeleteRemark->passes(); + + $query = $this->fetchesRemark->execute(['id' => $request->route('id')]); + + $this->deletesRemark->execute($query); + + return $this->response([]); + } + +} diff --git a/app/Classes/Modules/Remarks/ControllersLogic/FetchRemarkLogic.php b/app/Classes/Modules/Remarks/ControllersLogic/FetchRemarkLogic.php new file mode 100644 index 00000000..9c5aa5af --- /dev/null +++ b/app/Classes/Modules/Remarks/ControllersLogic/FetchRemarkLogic.php @@ -0,0 +1,59 @@ + 'Retrieved Remark', + 'message' => 'You have successfully retrieved a Remark' + ]; + } + + /** @var CanFetchRemark */ + private $canFetchRemark; + + /** @var FetchesRemark */ + private $fetchesRemark; + + /** + * FetchRemarkControllersLogic constructor. + * @param CanFetchRemark $canFetchRemark + * @param FetchesRemark $fetchesRemark + */ + public function __construct(CanFetchRemark $canFetchRemark, FetchesRemark $fetchesRemark) + { + $this->canFetchRemark = $canFetchRemark; + $this->fetchesRemark = $fetchesRemark; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $this->canFetchRemark->passes(); + + $query = $this->fetchesRemark->execute(['id' => $request->route('id')]); + + return $this->resourceResponse(new RemarkResource($query)); + } + +} diff --git a/app/Classes/Modules/Remarks/ControllersLogic/ListRemarksLogic.php b/app/Classes/Modules/Remarks/ControllersLogic/ListRemarksLogic.php new file mode 100644 index 00000000..c70ccee1 --- /dev/null +++ b/app/Classes/Modules/Remarks/ControllersLogic/ListRemarksLogic.php @@ -0,0 +1,59 @@ + 'Retrieved Remarks', + 'message' => 'You have successfully retrieved a list of Remarks' + ]; + } + + /** @var CanListRemarks */ + private $canListRemarks; + + /** @var ListsRemarks */ + private $listsRemarks; + + /** + * ListRemarksLogic constructor. + * @param CanListRemarks $canListRemarks + * @param ListsRemarks $listsRemarks + */ + public function __construct(CanListRemarks $canListRemarks, ListsRemarks $listsRemarks) + { + $this->canListRemarks = $canListRemarks; + $this->listsRemarks = $listsRemarks; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + $this->canListRemarks->passes(); + + $query = $this->listsRemarks->execute($this->listsRemarks->deserializeFilters($request->input('filters'))); + + return $this->collectionResponse(RemarkResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Remarks/ControllersLogic/UpdateRemarkLogic.php b/app/Classes/Modules/Remarks/ControllersLogic/UpdateRemarkLogic.php new file mode 100644 index 00000000..f120efab --- /dev/null +++ b/app/Classes/Modules/Remarks/ControllersLogic/UpdateRemarkLogic.php @@ -0,0 +1,71 @@ + 'Updated Remark', + 'message' => 'You have successfully updated the Remark' + ]; + } + + /** @var CanUpdateRemark */ + private $canUpdateRemark; + + /** @var UpdatesRemark */ + private $updatesRemark; + + /** @var FetchesRemark */ + private $fetchesRemark; + + /** + * UpdateRemarkLogic constructor. + * @param CanUpdateRemark $canUpdateRemark + * @param UpdatesRemark $updatesRemark + * @param FetchesRemark $fetchesRemark + */ + public function __construct(CanUpdateRemark $canUpdateRemark, UpdatesRemark $updatesRemark, FetchesRemark $fetchesRemark) + { + $this->canUpdateRemark = $canUpdateRemark; + $this->updatesRemark = $updatesRemark; + $this->fetchesRemark = $fetchesRemark; + } + + + /** + * @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 + { + $object = new RemarkObject($request->input('content'), auth()->user()->id); + + $this->canUpdateRemark->passes($object); + + $query = $this->fetchesRemark->execute(['id' => $request->route('id')]); + + $query = $this->updatesRemark->execute($query, $object); + + return $this->resourceResponse(new RemarkResource($query)); + } + +} diff --git a/app/Classes/Modules/Remarks/DataTransferObjects/RemarkObject.php b/app/Classes/Modules/Remarks/DataTransferObjects/RemarkObject.php new file mode 100644 index 00000000..44a9507f --- /dev/null +++ b/app/Classes/Modules/Remarks/DataTransferObjects/RemarkObject.php @@ -0,0 +1,38 @@ +commenterID = $commenterID; + $this->content = $content; + } + + /** + * @return int + */ + public function getCommenterId(): string + { + return $this->commenterID; + } + + /** + * @return string + */ + public function getContent(): ?string + { + return $this->content; + } + +} diff --git a/app/Classes/Modules/Remarks/Processors/CreateRemarkProcessor.php b/app/Classes/Modules/Remarks/Processors/CreateRemarkProcessor.php new file mode 100644 index 00000000..aadbe502 --- /dev/null +++ b/app/Classes/Modules/Remarks/Processors/CreateRemarkProcessor.php @@ -0,0 +1,47 @@ +createsRemark = $createsRemark; + $this->canCreateRemark = $canCreateRemark; + } + + + /** + * @param Remarkable $remarkable + * @param RemarkObject $object + * @return \Illuminate\Database\Eloquent\Model + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function execute(Remarkable $remarkable, RemarkObject $object){ + + $this->canCreateRemark->passes($object); + return $this->createsRemark->execute($remarkable, $object); + + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Remarks/Services/CreatesRemark.php b/app/Classes/Modules/Remarks/Services/CreatesRemark.php new file mode 100644 index 00000000..ac0d57a3 --- /dev/null +++ b/app/Classes/Modules/Remarks/Services/CreatesRemark.php @@ -0,0 +1,31 @@ +commenter_id = $object->getCommenterId(); + $model->content = $object->getContent(); + + return $this->handler($remarkable->remarks(), $model); + + } +} diff --git a/app/Classes/Modules/Remarks/Services/DeletesRemark.php b/app/Classes/Modules/Remarks/Services/DeletesRemark.php new file mode 100644 index 00000000..4c29be9d --- /dev/null +++ b/app/Classes/Modules/Remarks/Services/DeletesRemark.php @@ -0,0 +1,19 @@ +handler($model); + } +} diff --git a/app/Classes/Modules/Remarks/Services/FetchesRemark.php b/app/Classes/Modules/Remarks/Services/FetchesRemark.php new file mode 100644 index 00000000..a3b5c765 --- /dev/null +++ b/app/Classes/Modules/Remarks/Services/FetchesRemark.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Remarks/Services/ListsRemarks.php b/app/Classes/Modules/Remarks/Services/ListsRemarks.php new file mode 100644 index 00000000..53479558 --- /dev/null +++ b/app/Classes/Modules/Remarks/Services/ListsRemarks.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Remarks/Services/UpdatesRemark.php b/app/Classes/Modules/Remarks/Services/UpdatesRemark.php new file mode 100644 index 00000000..4ba9501c --- /dev/null +++ b/app/Classes/Modules/Remarks/Services/UpdatesRemark.php @@ -0,0 +1,26 @@ +commenter_id = $object->getCommenterId(); + $model->content = $object->getContent(); + + return $this->handler($model); + + } +} diff --git a/app/Classes/Modules/Remarks/Standards/Rules/CanCreateRemark.php b/app/Classes/Modules/Remarks/Standards/Rules/CanCreateRemark.php new file mode 100644 index 00000000..a7d2e5b1 --- /dev/null +++ b/app/Classes/Modules/Remarks/Standards/Rules/CanCreateRemark.php @@ -0,0 +1,57 @@ +RemarkValidation = $RemarkValidation; + } + + + /** + * @return bool + */ + protected function authorized($object): bool + { + // TODO Set Authorization rules + return true; + + } + + /** + * @param RemarkObject $object + * @return bool + * @throws \App\Classes\Exceptions\RequestValidationException + */ + protected function validators($object): bool + { + return $this->RemarkValidation->validate($object); + + } + + + /** + * @param RemarkObject $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } + +} diff --git a/app/Classes/Modules/Remarks/Standards/Rules/CanDeleteRemark.php b/app/Classes/Modules/Remarks/Standards/Rules/CanDeleteRemark.php new file mode 100644 index 00000000..1c61ac9d --- /dev/null +++ b/app/Classes/Modules/Remarks/Standards/Rules/CanDeleteRemark.php @@ -0,0 +1,43 @@ +RemarkValidation = $RemarkValidation; + } + + + /** + * @return bool + */ + protected function authorized($object): bool + { + // TODO Set Authorization rules + return true; + + } + + /** + * @param RemarkObject $object + * @return bool + * @throws \App\Classes\Exceptions\RequestValidationException + */ + protected function validators($object): bool + { + return $this->RemarkValidation->validate($object); + + } + + + /** + * @param RemarkObject $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } + +} diff --git a/app/Classes/Modules/Remarks/Standards/Validators/RemarkValidation.php b/app/Classes/Modules/Remarks/Standards/Validators/RemarkValidation.php new file mode 100644 index 00000000..b35d3bde --- /dev/null +++ b/app/Classes/Modules/Remarks/Standards/Validators/RemarkValidation.php @@ -0,0 +1,41 @@ + $object->getCommenterId(), + 'content' => $object->getContent(), + ]; + } + + /** + * @return array + */ + protected function rules(): array { + return [ + 'commenter_id' => 'required', + 'content' => 'required', + ]; + } + + /** + * @return array + */ + protected function messages(): array { + return []; + } + +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/ApproveBillGroupPaymentVerificationLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ApproveBillGroupPaymentVerificationLogic.php new file mode 100644 index 00000000..00117f9e --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/ApproveBillGroupPaymentVerificationLogic.php @@ -0,0 +1,93 @@ +fetchesTransaction = $fetchesTransaction; + $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->approvesDocument = $approvesDocument; + $this->rejectsDocument = $rejectsDocument; + $this->calculatesBillGroupPaymentAmount = $calculatesBillGroupPaymentAmount; + } + + /** + * @return array + */ + protected function notification():array { + return [ + 'title' => 'Payment Status', + 'message' => 'You have successfully updated the payment status' + ]; + } + + /** @var FetchesTransaction */ + private $fetchesTransaction; + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + /** @var ApprovesDocument */ + private $approvesDocument; + + /** @var RejectsDocument */ + private $rejectsDocument; + + /** @var CalculatesBillGroupPaymentAmount */ + private $calculatesBillGroupPaymentAmount; + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $status = $request->route('status'); + + $transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); + + $status === 'approve' ? $this->approvesDocument->execute($transaction->documents()->first()) : $this->rejectsDocument->execute($transaction->documents()->first()); + + $this->updatesTransactionStatus->execute($transaction, $status === 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED); + + $billGroup = $transaction->owner; + $billGroupPayment = $this->calculatesBillGroupPaymentAmount->execute($billGroup); + + if ($status === 'reject') { + $billGroup->status = ApprovalStatus::PENDING_SUBMISSION; + $billGroup->save(); + } else { + if ($billGroupPayment['outstanding_amount'] <= 0 && $billGroupPayment['floating_amount'] <= 0) { + $billGroup->status = ApprovalStatus::APPROVED; + $billGroup->save(); + } + } + + return $this->response([]); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentProofDocumentLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentProofDocumentLogic.php new file mode 100644 index 00000000..2563c230 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentProofDocumentLogic.php @@ -0,0 +1,94 @@ + 'Payment Proof Document', + 'message' => 'You have successfully submitted your payment proof document' + ]; + } + + /** @var FetchesTransaction */ + private $fetchesTransaction; + + /** @var CreatesDocument */ + private $createsDocument; + + /** @var CreatesFiles */ + private $createsFile; + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + /** @var CalculatesBillGroupPaymentAmount */ + private $calculatesBillGroupPaymentAmount; + + /** + * CreateBillGroupPaymentProofDocumentLogic constructor. + * @param FetchesTransaction $fetchesTransaction + * @param CreatesDocument $createsDocument + * @param CreatesFiles $createsFile + * @param UpdatesTransactionStatus $updatesTransactionStatus + * @param CalculatesBillGroupPaymentAmount $calculatesBillGroupPaymentAmount + */ + public function __construct(FetchesTransaction $fetchesTransaction, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesTransactionStatus $updatesTransactionStatus, CalculatesBillGroupPaymentAmount $calculatesBillGroupPaymentAmount) + { + $this->fetchesTransaction = $fetchesTransaction; + $this->createsDocument = $createsDocument; + $this->createsFile = $createsFile; + $this->updatesTransactionStatus = $updatesTransactionStatus; + $this->calculatesBillGroupPaymentAmount = $calculatesBillGroupPaymentAmount; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + + $transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); + + $object = new DocumentObject(DocumentType::BILL_GROUP_PAYMENT_PROOF, $request->input('files'), '', ApprovalStatus::PENDING_VERIFICATION, 'bill_group_payments'); + + /** @var Document $document */ + $document = $this->createsDocument->execute($transaction, $object); + + $this->createsFile->execute($document, $object); + + $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::PENDING_VERIFICATION); + + $billGroup = $transaction->owner; + $billGroupPayment = $this->calculatesBillGroupPaymentAmount->execute($billGroup); + + if ($billGroupPayment['outstanding_amount'] <= 0 && $billGroup->transactions()->where('status', ApprovalStatus::PENDING_SUBMISSION)->count() === 0) { + $billGroup->status = ApprovalStatus::PENDING_VERIFICATION; + $billGroup->save(); + } + + return $this->response([]); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php new file mode 100644 index 00000000..75be47d4 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php @@ -0,0 +1,95 @@ + 'Create Bill Group Payment Transaction', + 'message' => 'You have successfully created payment for this Bill Group' + ]; + } + + /** @var FetchesBillGroup */ + private $fetchesBillGroup; + + /** @var GeneratesTransactionBillNumber */ + private $generatesTransactionBillNumber; + + /** @var CreatesTransaction */ + private $createsTransaction; + + /** @var CalculatesBillGroupPaymentAmount */ + private $calculatesBillGroupPaymentAmount; + + /** + * CreateBillGroupPaymentTransactionLogic constructor. + * @param FetchesBillGroup $fetchesBillGroup + * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber + * @param CreatesTransaction $createsTransaction + * @param CalculatesBillGroupPaymentAmount $calculatesBillGroupPaymentAmount + */ + public function __construct(FetchesBillGroup $fetchesBillGroup, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBillGroupPaymentAmount $calculatesBillGroupPaymentAmount) + { + $this->fetchesBillGroup = $fetchesBillGroup; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->createsTransaction = $createsTransaction; + $this->calculatesBillGroupPaymentAmount = $calculatesBillGroupPaymentAmount; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $billGroup = $this->fetchesBillGroup->execute(['id' => $request->route('id')]); + + $billGroupPayment = $this->calculatesBillGroupPaymentAmount->execute($billGroup); + $outstanding_amount = $billGroupPayment['outstanding_amount']; + + if ($billGroupPayment['outstanding_amount'] <= 0) { + if ($billGroup->transactions()->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->count() !== 0) { + throw new MalformedRequestException('Invalid bill group, payment transaction already exist.'); + } + } + + $payAmount = floatval(str_replace(',', '', $request->input('payAmount'))); + if($payAmount > round($outstanding_amount, 2)) throw new MalformedRequestException('Your payment must not be greater than '. $outstanding_amount .'.'); + + if ($billGroupPayment['outstanding_amount'] == 0 && $payAmount == 0) { + $billGroup->status = ApprovalStatus::APPROVED; + $billGroup->save(); + } else { + $billNumber = $this->generatesTransactionBillNumber->execute('SPLR-PYMT-'); + $transaction_object = new TransactionObject($billNumber, TransactionType::SUPPLIER_PAYMENT, $billGroup->issuer, + $billGroup->receiver, $billGroup->issuerCompany->banks()->where('default', true)->first()->id, PaymentMethodType::CASH, + $payAmount, $payAmount, 1, 1, 1, + 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, [], ''); + $this->createsTransaction->execute($billGroup, $transaction_object); + } + + return $this->resourceResponse(new BillGroupResource($billGroup)); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php new file mode 100644 index 00000000..6213f55f --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php @@ -0,0 +1,195 @@ + 'Create Supplier White Form Order', + 'message' => 'You have successfully created currency supplier white form order' + ]; + } + + /** @var FetchesCompany */ + private $fetchesCompany; + + /** @var CreatesTransaction */ + private $createsTransaction; + + /** @var CreatesDocument */ + private $createsDocument; + + /** @var CreatesFiles */ + private $createsFile; + + /** @var GeneratesTransactionBillNumber */ + private $generatesTransactionBillNumber; + + /** @var UpdateGroupLogic */ + private $updateGroupLogic; + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + + /** + * CreateSupplierBillGroupLogic constructor. + * @param FetchesCompany $fetchesCompany + * @param CreatesTransaction $createsTransaction + * @param CreatesDocument $createsDocument + * @param CreatesFiles $createsFile + * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber + * @param UpdateGroupLogic $updateGroupLogic + * @param UpdatesTransactionStatus $updatesTransactionStatus + */ + public function __construct(FetchesCompany $fetchesCompany, CreatesTransaction $createsTransaction, CreatesDocument $createsDocument, CreatesFiles $createsFile, GeneratesTransactionBillNumber $generatesTransactionBillNumber, UpdateGroupLogic $updateGroupLogic, UpdatesTransactionStatus $updatesTransactionStatus) + { + $this->fetchesCompany = $fetchesCompany; + $this->createsTransaction = $createsTransaction; + $this->createsDocument = $createsDocument; + $this->createsFile = $createsFile; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->updateGroupLogic = $updateGroupLogic; + $this->updatesTransactionStatus = $updatesTransactionStatus; + } + + public function logic(Request $request) : JsonResponse + { + + $supplier = $this->fetchesCompany->execute(['id' => $request->route('id')]); + + $payments = $request->input('payments'); + $supplierRefunds = $request->input('supplierRefunds'); + + foreach ($supplierRefunds as $supplierRefund) { + $refund = Transaction::find($supplierRefund['id']); + + if ($refund->owner->transactions()->where('type', TransactionType::BILL)->first()->issuer !== $supplier->id) { + throw new MalformedRequestException('The supplier refund and bill group does not belongs to same supplier.'); + } + + if ($refund->type !== TransactionType::SUPPLIER_REFUND) { + throw new MalformedRequestException('Only transaction type supplier refund can be used for bill refund.'); + } + + if ($refund->currency_rate == 1) { + throw new MalformedRequestException('Supplier refund with currecy rate 1 cannot be used for bill refund.'); + } + } + + $amount = 0; + $original_amount = 0; + + foreach ($payments as $payment) { + $amount += round($payment['amount'], 2); + $original_amount += round($payment['original_amount'], 2); + } + + $service_charges = 0; + + if ($supplier->id === 4548 || $supplier->id === 2729) { + $amount = round(floatval(str_replace(',', '', $request->input('payment_total'))), 2); + } else { + $service_charges = round(floatval(str_replace(',', '', $request->input('service_charges'))), 2); + } + + $rate = $original_amount / $amount; + + if ($supplier->id === 4548 || $supplier->id === 2729) { + $request['rate'] = $rate; + $request['supplier_id'] = $supplier->id; + foreach ($payments as $payment) { + $request->route()->setParameter('id', $payment['id']); + $this->updateGroupLogic->execute($request); + } + } + + $billGroup = new BillGroup(); + $billGroup->issuer = $supplier->id; + $billGroup->receiver = 1; + $billGroup->reference = $this->generatesTransactionBillNumber->execute('BSPO-'); + $billGroup->amount = $amount; + $billGroup->original_amount = $original_amount; + $billGroup->currency_id = 1; + $billGroup->original_currency_id = $payments[0]['original_currency']['id']; + $billGroup->currency_rate = $rate; + $billGroup->tax = 0; + $billGroup->service_charge = $service_charges; + $billGroup->status = ApprovalStatus::PENDING_SUBMISSION; + $billGroup->save(); + + foreach ($payments as $payment) { + $billGroup->groups()->sync($payment['id'], false); + } + + //create bill refund + $amount += $service_charges; + + foreach ($supplierRefunds as $supplierRefund) { + $refund = Transaction::find($supplierRefund['id']); + $deductedRefunds = $refund->transactions()->where('type', TransactionType::BILL_REFUND)->where('status', ApprovalStatus::APPROVED)->get(); + $refundDeductableAmount = round(($refund->amount - $deductedRefunds->sum('amount')), 2); + $refundDeductableOriginalAmount = round(($refund->original_amount - $deductedRefunds->sum('original_amount')), 2); + + $amount -= $refundDeductableAmount; + $original_amount -= $refundDeductableOriginalAmount; + + if ($amount > 0) { + $deductedRefundAmount = $refundDeductableAmount; + $deductedRefundOriginalAmount = $refundDeductableOriginalAmount; + + $this->updatesTransactionStatus->execute($refund, ApprovalStatus::COMPLETED); + } + + if ($amount < 0) { + $deductedRefundAmount = $refundDeductableAmount + $amount; + $deductedRefundOriginalAmount = $refundDeductableOriginalAmount + $original_amount; + } + + $billNumber = $this->generatesTransactionBillNumber->execute('BRFD-'); + + $object = new TransactionObject($billNumber, TransactionType::BILL_REFUND, $supplier->id, 1, + 1, PaymentMethodType::CASH, + $deductedRefundAmount, $deductedRefundOriginalAmount, $refund->currency_id, + $refund->original_currency_id, $deductedRefundOriginalAmount / $deductedRefundAmount, + 0, 0, null, ApprovalStatus::APPROVED, []); + + $transaction = $this->createsTransaction->execute($refund, $object); + + $billGroup->billRefunds()->sync($transaction->id, false); + } + + return $this->response([]); + } +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php index 4c407cf5..ca0f77fd 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php @@ -129,6 +129,10 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic $service_charge += $row->service_charge; } + $transferFee = (float)$this->createSupplierTransactionProcessor->getTransferTransactions()->sum('service_charge'); + $original_amount += $transferFee; + $amount += $transferFee / $currency_rate; + $group->issuer = $issuer; $group->receiver = $receiver; $group->reference = $this->generatesTransactionBillNumber->execute('SPO-'); diff --git a/app/Classes/Modules/Transactions/ControllersLogic/DeleteBillGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/DeleteBillGroupLogic.php new file mode 100644 index 00000000..1122c111 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/DeleteBillGroupLogic.php @@ -0,0 +1,83 @@ + 'Delete Bill Group Transaction', + 'message' => 'You have successfully deleted this Bill Group Transaction' + ]; + } + + /** @var FetchesBillGroup */ + private $fetchesBillGroup; + + /** @var DeletesTransaction */ + private $deletesTransaction; + + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + + /** + * DeleteBillGroupLogic constructor. + * @param FetchesBillGroup $fetchesBillGroup + * @param DeletesTransaction $deletesTransaction + * @param UpdatesTransactionStatus $updatesTransactionStatus + */ + public function __construct(FetchesBillGroup $fetchesBillGroup, DeletesTransaction $deletesTransaction, UpdatesTransactionStatus $updatesTransactionStatus) + { + $this->fetchesBillGroup = $fetchesBillGroup; + $this->deletesTransaction = $deletesTransaction; + $this->updatesTransactionStatus = $updatesTransactionStatus; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $billGroup = $this->fetchesBillGroup->execute(['id' => $request->route('id')]); + + $transactions = $billGroup->transactions()->get(); + + foreach($transactions as $transaction) { + $this->deletesTransaction->execute($transaction); + } + + $groups = $billGroup->groups()->get(); + + foreach($groups as $group) { + $billGroup->groups()->detach($group->id); + } + + $billRefunds = $billGroup->billRefunds()->get(); + + foreach($billRefunds as $billRefund) { + $billGroup->billRefunds()->detach($billRefund->id); + $this->deletesTransaction->execute($billRefund); + $this->updatesTransactionStatus->execute($billRefund->owner, ApprovalStatus::APPROVED); + } + + $billGroup->delete(); + + return $this->resourceResponse(new BillGroupResource($billGroup)); + } + +} \ No newline at end of file diff --git a/app/Classes/Modules/Transactions/ControllersLogic/ListBillGroupsLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ListBillGroupsLogic.php new file mode 100644 index 00000000..0e39585b --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/ListBillGroupsLogic.php @@ -0,0 +1,42 @@ +listsBillGroups = $listsBillGroups; + } + + /** + * @return array + */ + protected function notification():array { + return [ + 'title' => 'Retrieved Bill Groups', + 'message' => 'You have successfully retrieved a list of bill groups' + ]; + } + + /** @var ListsBillGroups */ + private $listsBillGroups; + + public function logic(Request $request) : JsonResponse + { + $query = $this->listsBillGroups->execute($this->listsBillGroups->deserializeFilters($request->input('filters'))); + + return $this->collectionResponse(BillGroupResource::collection($query)); + } + +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php index aa432aea..f29db055 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupLogic.php @@ -125,6 +125,18 @@ class UpdateGroupLogic extends AbstractControllerLogic $billTransaction = $this->updatesTransaction->execute($transaction, $object); + $supplierRefundTransactions = $transaction->owner->transactions()->supplierRefunds()->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->get(); + + foreach ($supplierRefundTransactions as $supplierRefundTransaction) { + $claimBefore = $supplierRefundTransaction->transactions()->where('type', TransactionType::BILL_REFUND)->where('status', ApprovalStatus::APPROVED)->exists(); + + if (!$claimBefore) { + $supplierRefundTransaction->currency_rate = $rate; + $supplierRefundTransaction->amount = $supplierRefundTransaction->original_amount / $rate; + $supplierRefundTransaction->save(); + } + } + $transferTransaction = $transaction->transactions()->where('type', TransactionType::TRANSFER_FEE)->first(); $transferFee = $this->calculatesTransactionTransferFee->execute($billTransaction->original_amount, $constant); diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php index 09e4b102..cc98847a 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php @@ -2,8 +2,9 @@ namespace App\Classes\Modules\Transactions\ControllersLogic; - +use App\Classes\Exceptions\MalformedRequestException; use App\Classes\General\Abstracts\AbstractControllerLogic; +use App\Classes\Modules\Bookings\ControllersLogic\UpdateBookingAmountLogic; use App\Classes\Modules\Companies\Services\FetchesCompany; use App\Classes\Modules\Transactions\Services\FetchesTransaction; use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; @@ -15,7 +16,8 @@ use Illuminate\Http\Request; use App\Classes\Modules\Wallets\Processors\CreditWalletProcessor; use App\Classes\Modules\Bookings\Services\CalculatesBookingPayableAmount; use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; - +use App\Classes\ValueObjects\Constants\TransactionType; +use Illuminate\Support\Facades\Auth; class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic { @@ -51,6 +53,9 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic /** @var CalculatesBookingRefundAmount */ private $calculatesBookingRefundAmount; + /** @var UpdateBookingAmountLogic */ + private $updateBookingAmountLogic; + /** * CreatePaymentVerificationDocumentLogic constructor. * @param FetchesCompany $fetchesCompany @@ -60,8 +65,9 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic * @param CreditWalletProcessor $creditWalletProcessor * @param CalculatesBookingPayableAmount $calculatesBookingPayableAmount * @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount + * @param UpdateBookingAmountLogic $updateBookingAmountLogic */ - public function __construct(FetchesCompany $fetchesCompany, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, DeletesDocument $deletesDocument, CreditWalletProcessor $creditWalletProcessor, CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingRefundAmount $calculatesBookingRefundAmount) + public function __construct(FetchesCompany $fetchesCompany, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, DeletesDocument $deletesDocument, CreditWalletProcessor $creditWalletProcessor, CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingRefundAmount $calculatesBookingRefundAmount, UpdateBookingAmountLogic $updateBookingAmountLogic) { $this->fetchesCompany = $fetchesCompany; $this->fetchesTransaction = $fetchesTransaction; @@ -70,6 +76,7 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic $this->creditWalletProcessor = $creditWalletProcessor; $this->calculatesBookingPayableAmount = $calculatesBookingPayableAmount; $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; + $this->updateBookingAmountLogic = $updateBookingAmountLogic; } /** @@ -79,21 +86,43 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { + if(auth()->user()->type === 3) { + throw new MalformedRequestException('You do not have the permission to refund the order.'); + } + $refundTransaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); $refundTransaction = $this->updatesTransactionStatus->execute($refundTransaction, $request->route('status')); $paymentTransaction = $refundTransaction->owner; + $supplierRefundTransaction = $paymentTransaction->transactions()->supplierRefunds()->where('status', [ApprovalStatus::PENDING_VERIFICATION])->first(); + $booking = $paymentTransaction->owner; $reference = $refundTransaction->amount == $paymentTransaction->amount ? 'Fully Refund for Ref. ' . $booking->marking : 'Partially Refund for Ref. ' . $booking->marking; + $refundAmount = $this->calculatesBookingRefundAmount->calculateRefundAmount($paymentTransaction, $booking->fix_currency_id); + + $paidAmount = $paymentTransaction->original_amount - $refundAmount; + if ($refundTransaction->status == ApprovalStatus::APPROVED) { $this->creditWalletProcessor->execute($booking->company, $refundTransaction->type, $refundTransaction->amount, $reference); + $po_transaction = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first(); + + if ($po_transaction) { + $this->updatesTransactionStatus->execute($po_transaction, (float) number_format($po_transaction->amount, 2, '.', '') === (float) number_format((float)$booking->fix_amount - $refundAmount, 2, '.', '') ? ApprovalStatus::PENDING_VERIFICATION : ApprovalStatus::PENDING_SUBMISSION); + } + + $request['fix_amount'] = $booking->fix_amount - $refundAmount; + $request->route()->setParameter('id', $booking->id); + $this->updateBookingAmountLogic->execute($request); + } + + if ($supplierRefundTransaction) { + $this->updatesTransactionStatus->execute($supplierRefundTransaction, $request->route('status')); } - $paidAmount = $paymentTransaction->original_amount - $this->calculatesBookingRefundAmount->calculateRefundAmount($paymentTransaction, $booking->fix_currency_id); if (!$paidAmount > 0) { $this->updatesTransactionStatus->execute($paymentTransaction, ApprovalStatus::REFUNDED); } diff --git a/app/Classes/Modules/Transactions/Services/CalculatesBillGroupPaymentAmount.php b/app/Classes/Modules/Transactions/Services/CalculatesBillGroupPaymentAmount.php new file mode 100644 index 00000000..f41de813 --- /dev/null +++ b/app/Classes/Modules/Transactions/Services/CalculatesBillGroupPaymentAmount.php @@ -0,0 +1,25 @@ +billRefunds->sum('amount')), 7); + $floating_amount = round(floatval($billGroup->transactions()->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION])->sum('amount')), 7); + $paid_amount = round(floatval($billGroup->transactions()->where('status', ApprovalStatus::APPROVED)->sum('amount')), 7); + $outstanding_amount = $billGroup->amount - $bill_refund_amount - $paid_amount - $floating_amount + $billGroup->service_charge; + $outstanding_amount = round($outstanding_amount, 7); + + return [ + 'bill_refund_amount' => $bill_refund_amount, + 'floating_amount' => $floating_amount, + 'paid_amount' => $paid_amount, + 'outstanding_amount' => $outstanding_amount, + ]; + } +} diff --git a/app/Classes/Modules/Transactions/Services/FetchesBillGroup.php b/app/Classes/Modules/Transactions/Services/FetchesBillGroup.php new file mode 100644 index 00000000..55e5eb11 --- /dev/null +++ b/app/Classes/Modules/Transactions/Services/FetchesBillGroup.php @@ -0,0 +1,31 @@ +repository = $repository; + } + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Transactions/Services/ListsBillGroups.php b/app/Classes/Modules/Transactions/Services/ListsBillGroups.php new file mode 100644 index 00000000..26379706 --- /dev/null +++ b/app/Classes/Modules/Transactions/Services/ListsBillGroups.php @@ -0,0 +1,31 @@ +repository = $repository; + } + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/ValueObjects/Constants/DocumentType.php b/app/Classes/ValueObjects/Constants/DocumentType.php index 23f9a94a..42f8222b 100644 --- a/app/Classes/ValueObjects/Constants/DocumentType.php +++ b/app/Classes/ValueObjects/Constants/DocumentType.php @@ -25,4 +25,6 @@ final class DocumentType { public const INVOICE = 'INVOICE'; public const SUPPLIER_DELIVER_ORDER = 'SUPPLIER_DELIVER_ORDER'; public const BULK_PURCHASE_ORDER = 'BULK_PURCHASE_ORDER'; + + public const BILL_GROUP_PAYMENT_PROOF = 'BILL_GROUP_PAYMENT_PROOF'; } diff --git a/app/Classes/ValueObjects/Constants/RemarkTypes.php b/app/Classes/ValueObjects/Constants/RemarkTypes.php new file mode 100644 index 00000000..9629e89a --- /dev/null +++ b/app/Classes/ValueObjects/Constants/RemarkTypes.php @@ -0,0 +1,13 @@ +transactions()->payments()->count(); if ($bookingPaymentCount > 1) { - Log::info("Credit note transaction id: {$transaction->id}, there are {$bookingPaymentCount} payment for the booking."); + $this->info("Credit note transaction id: {$transaction->id}, there are {$bookingPaymentCount} payment for the booking."); foreach ($booking->transactions()->payments()->get() as $bp) { if ($transaction->amount - $bp->amount < 0.01) { $bookingPayment = $bp; @@ -107,55 +107,90 @@ class ExpiredRefundedBookingCommand extends Command if (!$bookingPayment) { $bookingPayment = $booking->transactions()->payments()->whereIn('status', [ApprovalStatus::SUSPENDED, ApprovalStatus::EXPIRED, ApprovalStatus::REJECTED])->orderBy('id', 'DESC')->first(); } + } + + if ($bookingPayment) { $status = ApprovalStatus::APPROVAL_STATUS_ID[$bookingPayment->status]; - Log::info("Credit note transaction id: {$transaction->id}, the payment for the booking is in status {$status}"); - } - $bookingPaymentAmount = $bookingPayment->amount; - // check if the booking is fully refund - $amountDifference = bcsub($transaction->amount, $bookingPaymentAmount, 7); + $this->info("Credit note transaction id: {$transaction->id}, the payment for the booking is in status {$status}"); - if (abs($amountDifference) < 0.01) { - // rejecting booking payment transaction - // $bookingPayment->status = ApprovalStatus::REJECTED; - // $bookingPayment->save(); - - //expired booking - // $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); - Log::info("Credit note transaction id: {$transaction->id} is fully refunded, the refunded amount was {$transaction->amount} the payment reference is: {$transaction->payment_reference}"); - // Log::info("Credit note transaction id: {$transaction->id}, Rejected Booking Transaction Payment id: {$bookingPayment->id}, the payment amount was {$bookingPayment->amount}"); - // Log::info("Credit note transaction id: {$transaction->id}, Expired Booking id: {$booking->id}"); - } else { - Log::info("Credit note transaction id: {$transaction->id} is not fully refunded, the refunded amount was {$transaction->amount}, the payment amount was {$bookingPayment->amount}, the payment reference is: {$transaction->payment_reference}"); - } - - $refund = $bookingPayment->transactions()->refunds()->where('amount', $transaction->amount)->where('status', ApprovalStatus::APPROVED)->first(); - - $bookingInWhiteForm = $bookingPayment->transactions()->bills()->first(); - - if ($refund) { - Log::info("Credit note transaction id: {$transaction->id}, already created same amount of refund transaction for same booking payment transaction"); - } - - if ($bookingInWhiteForm) { - Log::info("Credit note transaction id: {$transaction->id}, booking is in white form"); - } - - if (!$refund && !$bookingInWhiteForm) { - $billNumber = $this->generatesTransactionBillNumber->execute('RFD-'); - - $object = new TransactionObject($billNumber, TransactionType::REFUND, 1, $booking->company->id, - 1, PaymentMethodType::CASH, - $transaction->amount, $transaction->amount * $bookingPayment->currency_rate, 1, - $bookingPayment->original_currency_id, $bookingPayment->currency_rate, - 0, 0, null, ApprovalStatus::APPROVED, [], $bookingPayment->bill_no); + $bookingPaymentAmount = $bookingPayment->amount; + // check if the booking is fully refund + $amountDifference = bcsub($transaction->amount, $bookingPaymentAmount, 7); - $transaction = $this->createsTransaction->execute($bookingPayment, $object); + $isFullyRefund = false; + if (abs($amountDifference) < 0.01) { + $isFullyRefund = true; + // update fully refunded booking payment transaction + $bookingPayment->status = ApprovalStatus::REFUNDED; + $bookingPayment->save(); + + //expired booking + // $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); + $this->info("Credit note transaction id: {$transaction->id} is fully refunded, the refunded amount was {$transaction->amount} the payment reference is: {$transaction->payment_reference}"); + // $this->info("Credit note transaction id: {$transaction->id}, Rejected Booking Transaction Payment id: {$bookingPayment->id}, the payment amount was {$bookingPayment->amount}"); + // $this->info("Credit note transaction id: {$transaction->id}, Expired Booking id: {$booking->id}"); + } else { + $this->info("Credit note transaction id: {$transaction->id} is not fully refunded, the refunded amount was {$transaction->amount}, the payment amount was {$bookingPayment->amount}, the payment reference is: {$transaction->payment_reference}"); + } + + $refund = $bookingPayment->transactions()->refunds()->where('amount', $transaction->amount)->where('status', ApprovalStatus::APPROVED)->first(); + + $bookingInWhiteForm = $bookingPayment->transactions()->bills()->first(); + + if ($refund) { + $this->info("Credit note transaction id: {$transaction->id}, already created same amount of refund transaction for same booking payment transaction"); + } + + if (!$refund) { + $billNumber = $this->generatesTransactionBillNumber->execute('RFD-'); + + $object = new TransactionObject($billNumber, TransactionType::REFUND, 1, $booking->company->id, + 1, PaymentMethodType::CASH, + $transaction->amount, $isFullyRefund ? $bookingPayment->original_amount : $transaction->amount * $bookingPayment->currency_rate, 1, + $bookingPayment->original_currency_id, $bookingPayment->currency_rate, + 0, 0, null, ApprovalStatus::APPROVED, [], $bookingPayment->bill_no); + + $transaction = $this->createsTransaction->execute($bookingPayment, $object); + } + + if ($bookingInWhiteForm) { + $original_amount = $isFullyRefund ? $bookingPayment->original_amount : bcmul($transaction->amount, $bookingPayment->currency_rate, 7); + $supplier_refund_amount = bcdiv($original_amount, $bookingInWhiteForm->currency_rate, 7); + + $this->info("Credit note transaction id: {$transaction->id}, booking is in white form, white form currency rate is {$bookingInWhiteForm->currency_rate}"); + + // if ($isFullyRefund && $bookingInWhiteForm->currency_rate == 1) { + // dd ($bookingInWhiteForm->owner_id); + // } + + $refund = $bookingPayment->transactions()->supplierRefunds()->where('original_amount', $original_amount)->first(); + + if (!$refund) { + $billNumber = $this->generatesTransactionBillNumber->execute('SRFD-'); + + $object = new TransactionObject($billNumber, TransactionType::SUPPLIER_REFUND, 1, $bookingInWhiteForm->issuer, + 1, PaymentMethodType::CASH, + $supplier_refund_amount, $original_amount, 1, + $bookingPayment->original_currency_id, $bookingInWhiteForm->currency_rate, + 0, 0, null, ApprovalStatus::APPROVED, [], $bookingPayment->bill_no); + + $transaction = $this->createsTransaction->execute($bookingPayment, $object); + } + } + } else { + // $bookingPayment = $booking->transactions()->payments()->where('status', ApprovalStatus::REFUNDED)->orderBy('id', 'DESC')->first(); + + // if ($bookingPayment) { + // $this->info("Credit note transaction id: {$transaction->id}, booking payment refunded"); + // } else { + $this->info("Credit note transaction id: {$transaction->id}, booking payment not found, the payment reference is: {$transaction->payment_reference}"); + // } } } else { - Log::info("Credit note transaction id: {$transaction->id}, booking marking not found, the payment reference is: {$transaction->payment_reference}"); + $this->info("Credit note transaction id: {$transaction->id}, booking marking not found, the payment reference is: {$transaction->payment_reference}"); } } else { - Log::info("Credit note transaction id: {$transaction->id} does not have booking marking, the payment reference is: {$transaction->payment_reference}"); + $this->info("Credit note transaction id: {$transaction->id} does not have booking marking, the payment reference is: {$transaction->payment_reference}"); } } } diff --git a/app/Console/Commands/UpdateGroupWithTransferFee.php b/app/Console/Commands/UpdateGroupWithTransferFee.php new file mode 100644 index 00000000..dec74d5c --- /dev/null +++ b/app/Console/Commands/UpdateGroupWithTransferFee.php @@ -0,0 +1,68 @@ +get(); + + foreach ($groups as $group) { + $originalTransferFees = (float)Transaction::where('type', TransactionType::TRANSFER_FEE)->whereIn('owner_id', $group->transactions->pluck('id'))->sum('service_charge'); + $correctOriginalAmount = $group->transactions()->sum('original_amount'); + $correctOriginalAmount += $originalTransferFees; + $correctAmount = $group->transactions()->sum('amount'); + $transferFees = $originalTransferFees / $group->currency_rate; + $correctAmount += $transferFees; + + if ($group->original_amount != $correctOriginalAmount) { + $group->original_amount = $correctOriginalAmount; + $group->amount = $correctAmount; + $group->save(); + } + } + } +} diff --git a/app/Http/Controllers/Remarks/CreateRemarkController.php b/app/Http/Controllers/Remarks/CreateRemarkController.php new file mode 100644 index 00000000..a66aa8fd --- /dev/null +++ b/app/Http/Controllers/Remarks/CreateRemarkController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Remarks/DeleteRemarkController.php b/app/Http/Controllers/Remarks/DeleteRemarkController.php new file mode 100644 index 00000000..8d0163c0 --- /dev/null +++ b/app/Http/Controllers/Remarks/DeleteRemarkController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Remarks/FetchRemarkController.php b/app/Http/Controllers/Remarks/FetchRemarkController.php new file mode 100644 index 00000000..ba43be07 --- /dev/null +++ b/app/Http/Controllers/Remarks/FetchRemarkController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Remarks/ListRemarksController.php b/app/Http/Controllers/Remarks/ListRemarksController.php new file mode 100644 index 00000000..f76f752e --- /dev/null +++ b/app/Http/Controllers/Remarks/ListRemarksController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Remarks/UpdateRemarkController.php b/app/Http/Controllers/Remarks/UpdateRemarkController.php new file mode 100644 index 00000000..ae53f6b7 --- /dev/null +++ b/app/Http/Controllers/Remarks/UpdateRemarkController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Controllers/Transactions/ApproveBillGroupPaymentVerificationController.php b/app/Http/Controllers/Transactions/ApproveBillGroupPaymentVerificationController.php new file mode 100644 index 00000000..fbae0c1a --- /dev/null +++ b/app/Http/Controllers/Transactions/ApproveBillGroupPaymentVerificationController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Transactions/CreateBillGroupPaymentProofDocumentController.php b/app/Http/Controllers/Transactions/CreateBillGroupPaymentProofDocumentController.php new file mode 100644 index 00000000..dab95ed8 --- /dev/null +++ b/app/Http/Controllers/Transactions/CreateBillGroupPaymentProofDocumentController.php @@ -0,0 +1,21 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/CreateBillGroupPaymentTransactionController.php b/app/Http/Controllers/Transactions/CreateBillGroupPaymentTransactionController.php new file mode 100644 index 00000000..7e94c84e --- /dev/null +++ b/app/Http/Controllers/Transactions/CreateBillGroupPaymentTransactionController.php @@ -0,0 +1,20 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/CreateSupplierBillGroupController.php b/app/Http/Controllers/Transactions/CreateSupplierBillGroupController.php new file mode 100644 index 00000000..7ab2f48a --- /dev/null +++ b/app/Http/Controllers/Transactions/CreateSupplierBillGroupController.php @@ -0,0 +1,21 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/DeleteBillGroupController.php b/app/Http/Controllers/Transactions/DeleteBillGroupController.php new file mode 100644 index 00000000..2b76632b --- /dev/null +++ b/app/Http/Controllers/Transactions/DeleteBillGroupController.php @@ -0,0 +1,20 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/ListBillGroupsController.php b/app/Http/Controllers/Transactions/ListBillGroupsController.php new file mode 100644 index 00000000..94dbd5e1 --- /dev/null +++ b/app/Http/Controllers/Transactions/ListBillGroupsController.php @@ -0,0 +1,21 @@ +execute($request); + } +} diff --git a/app/Http/Resources/BillGroupResource.php b/app/Http/Resources/BillGroupResource.php new file mode 100644 index 00000000..23c8050e --- /dev/null +++ b/app/Http/Resources/BillGroupResource.php @@ -0,0 +1,82 @@ +make(CalculatesBillGroupPaymentAmount::class))->execute($this->resource); + $bill_refund_amount = $billGroupPayment['bill_refund_amount']; + $floating_amount = $billGroupPayment['floating_amount']; + $paid_amount = $billGroupPayment['paid_amount']; + $outstanding_amount = $billGroupPayment['outstanding_amount']; + + return [ + 'id' => $this->id, + 'reference' => $this->reference, + 'original_amount' => (float) $this->original_amount, + 'original_currency' => new CurrencyResource($this->original_currency), + 'issuer_name' => $this->issuerCompany->name, + 'issuer_id' => $this->issuerCompany->id, + 'amount' => (float) $this->amount, + 'service_charge' => (float) $this->service_charge, + 'currency' => new CurrencyResource($this->currency), + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), + 'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'), + 'currency_rate' => (float) $this->currency_rate, + 'status' => $this->status, + 'groups' => GroupResource::collection($this->groups), + 'bill_refund_amount' => $bill_refund_amount, + 'floating_amount' => $floating_amount, + 'paid_amount' => $paid_amount, + 'outstanding_amount' => $outstanding_amount, + 'payment_history' => $this->transactions->map(function ($transaction) { + return [ + 'id' => $transaction->id, + 'type' => (int) $transaction->type, + 'bill_no' => $transaction->bill_no, + 'payment_method' => (float) $transaction->payment_method, + 'amount' => (double) $transaction->amount, + 'original_amount' => (double) $transaction->original_amount, + 'currency' => new CurrencyResource($transaction->currency), + 'original_currency' => new CurrencyResource($transaction->original_currency), + 'service_charge' => (double) $transaction->service_charge, + 'tax' => (double) $transaction->tax, + 'status' => (int) $transaction->status, + 'statusText' => ApprovalStatus::APPROVAL_STATUS_ID[(int) $transaction->status], + 'documents' => $transaction->documents()->first() ? new DocumentResource($transaction->documents()->first()) : null, + 'updated_at' => Carbon::parse($transaction->updated_at)->format('d-m-Y h:i:s A'), + ]; + }), + 'bill_refunds' => $this->billRefunds->map(function ($transaction) { + return [ + 'id' => $transaction->id, + 'type' => (int) $transaction->type, + 'bill_no' => $transaction->bill_no, + 'payment_method' => (float) $transaction->payment_method, + 'amount' => (double) $transaction->amount, + 'original_amount' => (double) $transaction->original_amount, + 'currency' => new CurrencyResource($transaction->currency), + 'original_currency' => new CurrencyResource($transaction->original_currency), + 'service_charge' => (double) $transaction->service_charge, + 'tax' => (double) $transaction->tax, + 'status' => (int) $transaction->status, + 'statusText' => ApprovalStatus::APPROVAL_STATUS_ID[(int) $transaction->status], + 'updated_at' => Carbon::parse($transaction->updated_at)->format('d-m-Y h:i:s A'), + ]; + }), + ]; + } +} diff --git a/app/Http/Resources/RemarkResource.php b/app/Http/Resources/RemarkResource.php new file mode 100644 index 00000000..24081934 --- /dev/null +++ b/app/Http/Resources/RemarkResource.php @@ -0,0 +1,26 @@ + $this->id, + 'commenter' => new UserResource($this->commenter), + 'owner_id' => $this->owner_id, + 'content' => $this->content, + 'created_at' => $this->created_at->format('d-m-Y H:i'), + 'long_ago' => $this->created_at->diffForHumans() + ]; + } +} diff --git a/app/Http/Resources/TransactionResource.php b/app/Http/Resources/TransactionResource.php index 09967f4c..b431c854 100644 --- a/app/Http/Resources/TransactionResource.php +++ b/app/Http/Resources/TransactionResource.php @@ -3,6 +3,7 @@ namespace App\Http\Resources; use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; +use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\TransactionType; use App\Models\Booking; use Carbon\Carbon; @@ -19,7 +20,7 @@ class TransactionResource extends JsonResource public function toArray($request) { - $booking = in_array((int)$this->type, [TransactionType::BILL, TransactionType::REFUND])? $this->owner->owner : $this->owner; + $booking = in_array((int)$this->type, [TransactionType::BILL, TransactionType::REFUND, TransactionType::SUPPLIER_REFUND])? $this->owner->owner : $this->owner; $days = $this->created_at->endOfDay()->addWeekdays($booking->service_id === 3 ? 3 : 1); return [ @@ -32,8 +33,8 @@ class TransactionResource extends JsonResource 'recipient_bank_account' => new BankResource($booking->bank), 'issuer_name' => $this->issuerCompany->name, 'issuer_id' => $this->issuerCompany->id, - 'amount' => (double) $this->amount, - 'original_amount' => (double) $this->original_amount, + 'amount' => (double) ($this->type === TransactionType::SUPPLIER_REFUND ? $this->amount - $this->transactions()->where('type', TransactionType::BILL_REFUND)->where('status', ApprovalStatus::APPROVED)->sum('amount') : $this->amount), + 'original_amount' => (double) ($this->type === TransactionType::SUPPLIER_REFUND ? $this->original_amount - $this->transactions()->where('type', TransactionType::BILL_REFUND)->where('status', ApprovalStatus::APPROVED)->sum('original_amount') : $this->original_amount), 'currency' => new CurrencyResource($this->currency), 'original_currency' => new CurrencyResource($this->original_currency), 'service_charge' => (double) $this->service_charge, diff --git a/app/Models/BillGroup.php b/app/Models/BillGroup.php new file mode 100644 index 00000000..9270d8e8 --- /dev/null +++ b/app/Models/BillGroup.php @@ -0,0 +1,76 @@ +MorphMany(Transaction::class, 'owner'); + } + + use HasRelationships; + use \Staudenmeir\EloquentHasManyDeep\HasTableAlias; + + public function billRefunds() + { + return $this->belongsToMany(Transaction::class, BillGroupRefund::class); + } + + /** + * @return MorphMany + */ + public function documents(): morphMany + { + return $this->morphMany(Document::class, 'owner'); + } + + /** + * @return BelongsTo + */ + public function currency(): BelongsTo + { + return $this->BelongsTo(Currency::class, 'currency_id', 'id'); + } + + /** + * @return BelongsTo + */ + public function issuerCompany(): BelongsTo + { + return $this->BelongsTo( Company::class, 'issuer', 'id'); + } + + /** + * @return BelongsTo + */ + public function original_currency(): BelongsTo + { + return $this->BelongsTo(Currency::class, 'original_currency_id', 'id'); + } + + public function groups() + { + return $this->belongsToMany(Group::class, BillGroupPayment::class, 'bill_group_id', 'group_id'); + } +} diff --git a/app/Models/BillGroupPayment.php b/app/Models/BillGroupPayment.php new file mode 100644 index 00000000..e34f692c --- /dev/null +++ b/app/Models/BillGroupPayment.php @@ -0,0 +1,27 @@ +BelongsTo(BillGroup::class, 'bill_group_id', 'id'); + } + + /** + * @return BelongsTo + */ + public function group(): BelongsTo + { + return $this->BelongsTo(Group::class, 'group_id', 'id'); + } +} diff --git a/app/Models/BillGroupRefund.php b/app/Models/BillGroupRefund.php new file mode 100644 index 00000000..aa430873 --- /dev/null +++ b/app/Models/BillGroupRefund.php @@ -0,0 +1,27 @@ +BelongsTo(BillGroup::class, 'bill_group_id', 'id'); + } + + /** + * @return BelongsTo + */ + public function transaction(): BelongsTo + { + return $this->BelongsTo(Transaction::class, 'transaction_id', 'id'); + } +} diff --git a/app/Models/Group.php b/app/Models/Group.php index 01dd257e..8cb6cd8a 100644 --- a/app/Models/Group.php +++ b/app/Models/Group.php @@ -6,6 +6,7 @@ use App\Classes\General\Traits\LogData; use Illuminate\Database\Eloquent\Model; use App\Classes\General\Interfaces\Documentable; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\MorphMany; use Staudenmeir\EloquentHasManyDeep\HasManyDeep; use Staudenmeir\EloquentHasManyDeep\HasRelationships; @@ -60,4 +61,12 @@ class Group extends Model implements Documentable { return $this->BelongsTo(Currency::class, 'original_currency_id', 'id'); } + + /** + * @return BelongsToMany + */ + public function billGroup(): BelongsToMany + { + return $this->belongsToMany(BillGroup::class, BillGroupPayment::class, 'group_id', 'bill_group_id'); + } } diff --git a/app/Models/Remark.php b/app/Models/Remark.php new file mode 100644 index 00000000..f2de3a5c --- /dev/null +++ b/app/Models/Remark.php @@ -0,0 +1,27 @@ +morphTo(); + } + + /** + * @return BelongsTo + */ + public function commenter(): BelongsTo + { + return $this->BelongsTo(User::class, 'commenter_id', 'id'); + } +} diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index 185fdb36..aba5decc 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -186,6 +186,20 @@ class Transaction extends AbstractModel implements Documentable, Transactionable return $query->where('type', TransactionType::REFUND); } + /** + * @param Builder $query + * @param string $payment_reference + * @return Builder + */ + public function scopeSupplierRefunds(Builder $query, ?string $payment_reference = NULL) + { + if($payment_reference){ + $query->where('payment_reference', $payment_reference); + } + + return $query->where('type', TransactionType::SUPPLIER_REFUND); + } + /** * @param Builder $query @@ -245,4 +259,12 @@ class Transaction extends AbstractModel implements Documentable, Transactionable return $this->morphMany(VoucherEntityMapping::class, 'owner'); } + /** + * @return MorphMany + */ + public function remarks(): morphMany + { + return $this->morphMany(Remark::class, 'owner'); + } + } diff --git a/database/migrations/2023_12_04_224416_create_bill_groups_table.php b/database/migrations/2023_12_04_224416_create_bill_groups_table.php new file mode 100644 index 00000000..e5fd986c --- /dev/null +++ b/database/migrations/2023_12_04_224416_create_bill_groups_table.php @@ -0,0 +1,44 @@ +id(); + $table->string('reference')->unique(); + $table->foreignId('issuer')->unsigned(); + $table->foreignId('receiver')->unsigned(); + $table->decimal('amount', 14, 5)->default(0.00); + $table->decimal('original_amount', 14, 5)->default(0.00); + $table->foreignId('currency_id')->unsigned(); + $table->foreignId('original_currency_id')->unsigned(); + $table->decimal('currency_rate', 14, 5)->default(0.00); + $table->decimal('tax', 14, 5)->default(0.00); + $table->decimal('service_charge', 14, 5)->default(0.00); + $table->integer('status')->default(ApprovalStatus::PENDING_VERIFICATION); + $table->softDeletes(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('bill_groups'); + } +} diff --git a/database/migrations/2023_12_04_224509_create_bill_group_payments_table.php b/database/migrations/2023_12_04_224509_create_bill_group_payments_table.php new file mode 100644 index 00000000..5e0d2aa2 --- /dev/null +++ b/database/migrations/2023_12_04_224509_create_bill_group_payments_table.php @@ -0,0 +1,34 @@ +id(); + $table->foreignId('bill_group_id')->constrained('bill_groups'); + $table->foreignId('group_id')->constrained('groups'); + $table->softDeletes(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('bill_group_payments'); + } +} diff --git a/database/migrations/2024_02_22_222130_create_bill_group_refunds_table.php b/database/migrations/2024_02_22_222130_create_bill_group_refunds_table.php new file mode 100644 index 00000000..f7b278b1 --- /dev/null +++ b/database/migrations/2024_02_22_222130_create_bill_group_refunds_table.php @@ -0,0 +1,22 @@ +id(); + $table->foreignId('bill_group_id')->unsigned()->on('bill_groups'); + $table->foreignId('transaction_id')->unsigned()->on('transactions'); + }); + } + + public function down() + { + Schema::dropIfExists('bill_group_refunds'); + } +} diff --git a/database/migrations/2024_04_24_180633_create_remarks_table.php b/database/migrations/2024_04_24_180633_create_remarks_table.php new file mode 100644 index 00000000..6656fd77 --- /dev/null +++ b/database/migrations/2024_04_24_180633_create_remarks_table.php @@ -0,0 +1,41 @@ +id(); + $table->morphs('owner'); + $table->bigInteger('commenter_id')->unsigned()->index(); + $table->string('content',200); + $table->integer('type')->default(RemarkTypes::INTERNAL); + $table->softDeletes(); + $table->timestamps(); + }); + + Schema::table('remarks', function (Blueprint $table) { + $table->string('owner_type', 191)->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('remarks'); + } +} diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php index 87d72f71..eb94b74f 100644 --- a/database/seeds/DatabaseSeeder.php +++ b/database/seeds/DatabaseSeeder.php @@ -48,6 +48,6 @@ class DatabaseSeeder extends Seeder $this->call(DummyDataSeeder::class); } - DB::commit(); + // DB::commit(); } } diff --git a/resources/assets/vue/components/bookings/elements/BillGroupComponent.vue b/resources/assets/vue/components/bookings/elements/BillGroupComponent.vue new file mode 100644 index 00000000..e93eb1ad --- /dev/null +++ b/resources/assets/vue/components/bookings/elements/BillGroupComponent.vue @@ -0,0 +1,290 @@ + + + diff --git a/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue b/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue new file mode 100644 index 00000000..f84541d1 --- /dev/null +++ b/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue @@ -0,0 +1,170 @@ + + + \ No newline at end of file diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index a6556cd2..7679b807 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -18,13 +18,13 @@
Payment Amount
- {{item.original_currency.short_code}} {{(Math.round((item.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}} + {{item.original_currency.short_code}} {{(Math.round((item.original_amount - item.refunded_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
Refunded Amount
- {{item.currency.short_code}} {{(Math.round((totalConvertRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}} + {{item.original_currency.short_code}} {{(Math.round((item.refunded_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
@@ -68,15 +68,13 @@
Payment Amount
- {{item.original_currency.short_code}} {{(Math.round((item.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}} + {{item.original_currency.short_code}} {{(Math.round((item.original_amount - item.refunded_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
-
-
-
Refunded Amount
-
-
-
{{item.original_currency.short_code}} {{(Math.round((totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
+
Refunded Amount
+
+ {{item.original_currency.short_code}} {{(Math.round((totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
@@ -291,8 +289,8 @@
-
-
+
+
@@ -347,7 +345,7 @@
-
+
-
+
diff --git a/resources/assets/vue/components/bookings/elements/SupplierPendingOrderComponent.vue b/resources/assets/vue/components/bookings/elements/SupplierPendingOrderComponent.vue index 309f2b9b..860a493c 100644 --- a/resources/assets/vue/components/bookings/elements/SupplierPendingOrderComponent.vue +++ b/resources/assets/vue/components/bookings/elements/SupplierPendingOrderComponent.vue @@ -56,7 +56,7 @@ {{item.original_currency.short_code}}
-
+
diff --git a/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue b/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue new file mode 100644 index 00000000..68839221 --- /dev/null +++ b/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue @@ -0,0 +1,98 @@ + + + diff --git a/resources/assets/vue/components/bookings/elements/TransactionGroupPaymentComponent.vue b/resources/assets/vue/components/bookings/elements/TransactionGroupPaymentComponent.vue new file mode 100644 index 00000000..7fdd579f --- /dev/null +++ b/resources/assets/vue/components/bookings/elements/TransactionGroupPaymentComponent.vue @@ -0,0 +1,132 @@ + + + diff --git a/resources/assets/vue/components/bookings/forms/BillGroupPaymentProofFormComponent.vue b/resources/assets/vue/components/bookings/forms/BillGroupPaymentProofFormComponent.vue new file mode 100644 index 00000000..1adac911 --- /dev/null +++ b/resources/assets/vue/components/bookings/forms/BillGroupPaymentProofFormComponent.vue @@ -0,0 +1,80 @@ + + + \ No newline at end of file diff --git a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue index 9b8045f9..b9a0f2d6 100644 --- a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue @@ -242,6 +242,7 @@ 'data': function () { if (this.data && this.data.purchase_order && this.data.purchase_order.details) { this.products = this.data.purchase_order.details; + this.submitted = this.data.purchase_order ? this.data.purchase_order.status === 1 || this.data.purchase_order.status === 2: false; } else { this.products = []; } diff --git a/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue new file mode 100644 index 00000000..01c099ed --- /dev/null +++ b/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue @@ -0,0 +1,246 @@ + + + \ No newline at end of file diff --git a/resources/assets/vue/components/bookings/sections/BillGroupListSectionComponent.vue b/resources/assets/vue/components/bookings/sections/BillGroupListSectionComponent.vue new file mode 100644 index 00000000..18aa285f --- /dev/null +++ b/resources/assets/vue/components/bookings/sections/BillGroupListSectionComponent.vue @@ -0,0 +1,136 @@ + + + \ No newline at end of file diff --git a/resources/assets/vue/components/bookings/sections/SupplierPendingOrderPaymentSectionComponent.vue b/resources/assets/vue/components/bookings/sections/SupplierPendingOrderPaymentSectionComponent.vue new file mode 100644 index 00000000..eba9fde5 --- /dev/null +++ b/resources/assets/vue/components/bookings/sections/SupplierPendingOrderPaymentSectionComponent.vue @@ -0,0 +1,113 @@ + + + \ No newline at end of file diff --git a/resources/assets/vue/components/general/elements/RemarkComponent.vue b/resources/assets/vue/components/general/elements/RemarkComponent.vue new file mode 100644 index 00000000..f2f9bf30 --- /dev/null +++ b/resources/assets/vue/components/general/elements/RemarkComponent.vue @@ -0,0 +1,32 @@ + + diff --git a/resources/assets/vue/components/general/elements/RemarkListComponent.vue b/resources/assets/vue/components/general/elements/RemarkListComponent.vue new file mode 100644 index 00000000..da218ea9 --- /dev/null +++ b/resources/assets/vue/components/general/elements/RemarkListComponent.vue @@ -0,0 +1,71 @@ + + diff --git a/resources/assets/vue/components/general/forms/DeleteRemarkFormComponent.vue b/resources/assets/vue/components/general/forms/DeleteRemarkFormComponent.vue new file mode 100644 index 00000000..4e50d8c4 --- /dev/null +++ b/resources/assets/vue/components/general/forms/DeleteRemarkFormComponent.vue @@ -0,0 +1,32 @@ + + diff --git a/resources/assets/vue/components/general/forms/GeneralConfirmationFormComponent.vue b/resources/assets/vue/components/general/forms/GeneralConfirmationFormComponent.vue index cdb477ee..6d6ad557 100644 --- a/resources/assets/vue/components/general/forms/GeneralConfirmationFormComponent.vue +++ b/resources/assets/vue/components/general/forms/GeneralConfirmationFormComponent.vue @@ -57,7 +57,16 @@ submitForm() { if (this.params) this.parameters = this.params; return this.submit(this.apiRoute, this.apiMethod, this.section, true, true); - } + }, + successHandler(){ + this.closeModal(); + this.formHandler(); + if (this.section && (this.section === 'paymentInProgressBillGroupList' || this.section === 'paymentVerificationBillGroupList')) { + this.$store.dispatch('toggleSection', {name: 'paymentInProgressBillGroupList', status: !this.$store.getters.isShowing('paymentInProgressBillGroupList')}); + this.$store.dispatch('toggleSection', {name: 'paymentVerificationBillGroupList', status: !this.$store.getters.isShowing('paymentVerificationBillGroupList')}); + this.$store.dispatch('toggleSection', {name: 'paidBillGroupList', status: !this.$store.getters.isShowing('paidBillGroupList')}); + } + }, }, mixins: [componentHandler, ModalFormHandler] diff --git a/resources/assets/vue/components/general/forms/RemarkCommentFormComponent.vue b/resources/assets/vue/components/general/forms/RemarkCommentFormComponent.vue new file mode 100644 index 00000000..7da26ca8 --- /dev/null +++ b/resources/assets/vue/components/general/forms/RemarkCommentFormComponent.vue @@ -0,0 +1,55 @@ + + diff --git a/resources/assets/vue/components/general/forms/RemarkFormComponent.vue b/resources/assets/vue/components/general/forms/RemarkFormComponent.vue new file mode 100644 index 00000000..73a8575f --- /dev/null +++ b/resources/assets/vue/components/general/forms/RemarkFormComponent.vue @@ -0,0 +1,73 @@ + + diff --git a/resources/assets/vue/components/general/forms/ValidationErrorComponent.vue b/resources/assets/vue/components/general/forms/ValidationErrorComponent.vue index d85e38a4..e1020c2e 100644 --- a/resources/assets/vue/components/general/forms/ValidationErrorComponent.vue +++ b/resources/assets/vue/components/general/forms/ValidationErrorComponent.vue @@ -1,10 +1,10 @@ diff --git a/resources/views/pages/dashboards/admin.blade.php b/resources/views/pages/dashboards/admin.blade.php index d7223cc0..ac41424c 100644 --- a/resources/views/pages/dashboards/admin.blade.php +++ b/resources/views/pages/dashboards/admin.blade.php @@ -27,7 +27,7 @@
-
+
-
Refunds
+
Pre-Refunds
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
Post-Refunds
@@ -79,13 +98,84 @@
-
+
+
+
+ Fully Refund +
+ +
- + + +
+
+
+
+ Partial Refund +
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ Fully Refund +
+ +
+
+
+ + + +
+
+
+
+ Partial Refund +
+ +
+
+
+ +
diff --git a/resources/views/pages/pdfs/purchase_order_table.blade.php b/resources/views/pages/pdfs/purchase_order_table.blade.php index cc47100e..5862ac69 100644 --- a/resources/views/pages/pdfs/purchase_order_table.blade.php +++ b/resources/views/pages/pdfs/purchase_order_table.blade.php @@ -60,7 +60,7 @@ Voucher ({{ $voucher_redemption->voucher->code }}) - -{{ number_format($voucherDiscount, 2) }} + {{ number_format($voucherDiscount, 2) }} @endif diff --git a/resources/views/pages/supplier-payments.blade.php b/resources/views/pages/supplier-payments.blade.php new file mode 100644 index 00000000..c94051e7 --- /dev/null +++ b/resources/views/pages/supplier-payments.blade.php @@ -0,0 +1,138 @@ +@extends('layouts.base_portal') +@section('inner_content') +
+
+
+
+
+
+
+
+ Supplier Currency Orders +
+
+
+
+
+
+
+
+ +
+
+
+
+
Pending Payment
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
Payment In Progress
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
Payment Verification
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
Paid Currency Order
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/partials/header.blade.php b/resources/views/partials/header.blade.php index b618e334..eaeeaec7 100644 --- a/resources/views/partials/header.blade.php +++ b/resources/views/partials/header.blade.php @@ -38,6 +38,11 @@
Currency Orders
+
Transfers
diff --git a/routes/api.php b/routes/api.php index 460bd772..2d52b3ea 100644 --- a/routes/api.php +++ b/routes/api.php @@ -67,6 +67,8 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function require __DIR__ . '/milestone.php'; + require __DIR__.'/remark.php'; + // require __DIR__ . '/accounting.php'; //cief todo: To check if this is needed require __DIR__ . '/job.php'; diff --git a/routes/remark.php b/routes/remark.php new file mode 100644 index 00000000..91ae4676 --- /dev/null +++ b/routes/remark.php @@ -0,0 +1,11 @@ + 'Remarks', 'as' => 'remark.', 'prefix' => 'remark'], function () { + Route::get('/{id}/show', 'FetchRemarkController@fetch')->name('show'); + Route::get('/list', 'ListRemarksController@list')->name('list'); + Route::post('/{id}/create', 'CreateRemarkController@create')->name('create'); + Route::put('/update/{id}', 'UpdateRemarkController@update')->name('update'); + Route::delete('/delete/{id}', 'DeleteRemarkController@delete')->name('delete'); +}); diff --git a/routes/transaction.php b/routes/transaction.php index f2f4a630..d20d160d 100644 --- a/routes/transaction.php +++ b/routes/transaction.php @@ -8,6 +8,7 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' => Route::delete('/suspend/{id}', 'SuspendTransactionController@suspend')->name('suspend'); route::post('/supplier/{id}/bill/create', 'CreateSupplierTransactionController@create')->name('supplier.create'); + route::post('/supplier/{id}/bill/group/create', 'CreateSupplierBillGroupController@create')->name('supplier.bill_group.create'); route::post('{id}/bill/verification', 'CreatePaymentProofDocumentController@verify')->name('bill.verification'); route::post('{id}/bill/pay', 'CreatePaymentProofDocumentController@pay')->name('bill.pay'); Route::put('/{id}/bill/{status}', 'UpdatePaymentTransactionStatusController@update')->where('status', 'pending|complete')->name('bill.status'); @@ -33,5 +34,14 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' => Route::put('/{id}/update', 'UpdateGroupController@update')->name('update'); Route::post('/{id}/approve', 'CreateBulkPurchaseOrderDocumentController@aprove')->name('approve'); Route::post('/bulk/po', 'CreateBulkPurchaseOrderDocumentController@create')->name('bulk.po'); + + Route::group(['prefix' => 'bills', 'as' => 'bill.'], function () { + Route::get('/list', 'ListBillGroupsController@list')->name('list'); + Route::post('/transaction/{id}', 'CreateBillGroupPaymentProofDocumentController@create')->name('payment_proof.create'); + Route::post('/transaction/{id}/approval/{status}', 'ApproveBillGroupPaymentVerificationController@approve')->where('status', 'approve|reject')->name('payment_proof.approval'); + Route::delete('/{id}/delete', 'DeleteBillGroupController@delete')->name('delete'); + Route::post('/{id}/pay', 'CreateBillGroupPaymentTransactionController@pay')->name('pay'); + // Route::post('/bulk/po', 'CreateBulkPurchaseOrderDocumentController@create')->name('bulk.po'); + }); }); }); \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 1143c48c..861f5bdf 100644 --- a/routes/web.php +++ b/routes/web.php @@ -2,6 +2,7 @@ use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; use App\Http\Controllers\Accounting\BankStatementController; +use App\Models\Remark; use Carbon\Carbon; use App\Models\User; use App\Models\Wallet; @@ -31,6 +32,7 @@ use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionWithInvo use App\Classes\Modules\Transactions\Services\DeletesTransaction; use Illuminate\Support\Facades\Log; + /* |-------------------------------------------------------------------------- | Web Routes @@ -89,6 +91,10 @@ Route::get('/payments', function () { return view('pages.payments'); })->name('payments'); +Route::get('/supplier-payments', function () { + return view('pages.supplier-payments'); +})->name('supplier.payments'); + Route::get('/billings', function () { return view('pages.billings'); })->name('billings'); @@ -429,6 +435,90 @@ Route::get('/pending_orders', function(){ echo ''; })->name('orders.pending'); +Route::get('/approve_refunds', function(Request $request){ + $type = $request->query('type'); + $payments = Transaction::where('type', TransactionType::PAYMENT)->where('owner_type', Booking::class)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED, ApprovalStatus::REFUNDED]) + ->whereHas('transactions', function ($query) use ($type) { + $query->where('type', TransactionType::REFUND)->where('status', ApprovalStatus::APPROVED); + if (str_contains($type, 'partial')) { + $query->whereColumn('original_amount', '!=','transactions.original_amount'); + } else { + $query->whereColumn('original_amount', 'transactions.original_amount'); + } + }); + + if (str_contains($type, 'post')) { + $payments->whereHas('transactions', function($query) { + $query->where('type', TransactionType::SUPPLIER_REFUND); + }); + } else { + $payments->whereDoesntHave('transactions', function($query) { + $query->where('type', TransactionType::SUPPLIER_REFUND); + }); + } + + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + foreach ($payments->orderBy('updated_at', 'DESC')->get() as $index => $payment){ + $booking = $payment->owner; + $original_refunds = floatval((App()->make(CalculatesBookingRefundAmount::class))->calculateRefundAmount($payment, $booking->fix_currency_id)); + $refunds = $original_refunds / $payment->currency_rate; + if(!$booking instanceof Booking){ + dd($payment); + } + $bankType = str::length($booking->bank->holder_name) > 4 ? 'Company' : 'Personal'; + + if (!preg_match('/[^A-Za-z0-9]/', $booking->bank->holder_name)) + { + $bankType = str_word_count($booking->bank->holder_name) > 4 ? 'Company' : 'Personal'; + } + + $refundTransaction = $payment->transactions()->refunds()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first(); + $remark = $refundTransaction->original_amount === $payment->original_amount ? 'Fully Refund' : 'Partial Refund'; + + if (str_contains($type, 'post')) { + $remark = 'Post ' . $remark; + } else { + $remark = 'Pre ' . $remark; + } + + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + } + echo '
No.Updated AtMarkingPayment MethodRefunded AmountCompany ReferenceRefunded Original AmountRemarkServiceLast Updated AtBank TypeBank Holder Name
'.($index + 1).'.'.$payment->updated_at->format('d-M-y').''.$booking->marking.''.\App\Classes\ValueObjects\Constants\PaymentMethodType::PAYMENT_METHODS_ID[$payment->payment_method].''.$payment->currency->short_code.''.number_format($refunds, 5, '.', '').''.$booking->company->reference.''.$payment->original_currency->short_code.''.number_format($original_refunds, 5, '.', '').''.$remark.''.$booking->service->name.''.$payment->updated_at->diffForHumans().''.$bankType.''.$booking->bank->holder_name.'
'; +})->name('orders.refunds'); + Route::get('/group/text/{id}', function($id){ $group = \App\Models\Group::where('id', $id)->first(); @@ -880,6 +970,17 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, ); })->name('invoice.fix.byCustomerMarking'); +route:: post('/transaction/{id}/create-remark',function ($transactionId) { + $transaction = Transaction::find($transactionId); + $remark = new Remark(); + + $remark->owner_type = get_class($transaction); + $remark->owner_id = $transaction->id; + + $remark->content = request('content'); + $remark->save(); + return redirect()->back(); +})->name('transaction.create-remark'); Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', function ($from_date, $to_date) { @@ -925,6 +1026,8 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo 'Upload bank slip Date'; echo 'PO submit date'; echo 'PO approve date'; + echo 'Remark'; + echo 'Add Remarks'; echo ''; echo ''; echo ''; @@ -944,6 +1047,21 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo '' . ($bill->status === ApprovalStatus::APPROVED ? $bill->updated_at->format('d-m-Y h:i A') : 'Pending Upload') . ''; echo '' . ($po ? $po->updated_at->format('d-m-Y h:i A') : 'Pending Submission') . ''; echo '' . ($po ? ($po->status === ApprovalStatus::APPROVED ? $po->updated_at->format('d-m-Y h:i A') : '' ) : '' ). ''; + $remarks = $bill->remarks; + echo ''; + foreach ($remarks as $remark) { + echo $remark->created_at->format('d-m-Y : h:i A') . ' - '; + echo $remark->content; + echo '
'; + } + echo ''; + echo '' ; + echo '
'; + echo ''; + echo ''; + echo csrf_field(); + echo '
'; + echo ''; echo ''; }