From 13ba4e5c1254ffe1e335c9a3af67a9eb09353584 Mon Sep 17 00:00:00 2001 From: Dillon Date: Fri, 20 Jan 2023 01:23:03 +0800 Subject: [PATCH 001/228] Edit book recipient bank details --- .../UpdateBookingRecipientLogic.php | 94 ++++++++++++ .../UpdateBookingRecipientController.php | 20 +++ .../banks/forms/BankAccountFormComponent.vue | 25 +++- .../banks/forms/PhoneAccountFormComponent.vue | 27 +++- .../BookingRecipientEditComponent.vue | 141 ++++++++++++++++++ .../BookingPaymentQuotationComponent.vue | 33 +++- .../bookings/forms/UpdateBookingComponent.vue | 41 +++++ routes/booking.php | 3 +- 8 files changed, 371 insertions(+), 13 deletions(-) create mode 100644 app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingRecipientLogic.php create mode 100644 app/Http/Controllers/Bookings/UpdateBookingRecipientController.php create mode 100644 resources/assets/vue/components/bookings/elements/BookingRecipientEditComponent.vue create mode 100644 resources/assets/vue/components/bookings/forms/UpdateBookingComponent.vue diff --git a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingRecipientLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingRecipientLogic.php new file mode 100644 index 00000000..8bdee9e3 --- /dev/null +++ b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingRecipientLogic.php @@ -0,0 +1,94 @@ + 'Updated Booking', + 'message' => 'You have successfully updated the Booking' + ]; + } + + /** @var CanUpdateBooking */ + private $canUpdateBooking; + + /** @var UpdatesBooking */ + private $updatesBooking; + + /** @var FetchesBooking */ + private $fetchesBooking; + + + /** + * UpdateBookingRecipientLogic constructor. + * @param CanUpdateBooking $canUpdateBooking + * @param UpdatesBooking $updatesBooking + * @param FetchesBooking $fetchesBooking + */ + public function __construct( + CanUpdateBooking $canUpdateBooking, + UpdatesBooking $updatesBooking, + FetchesBooking $fetchesBooking + ) + { + $this->canUpdateBooking = $canUpdateBooking; + $this->updatesBooking = $updatesBooking; + $this->fetchesBooking = $fetchesBooking; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws ErrorException + */ + public function logic(Request $request) : JsonResponse + { + try { + DB::beginTransaction(); + + $booking = $this->fetchesBooking->execute(['id' => $request->route('id')]); + + + $booking_object = new BookingObject( + $booking->service_id, + $request->input('transferable_bank_id', $booking->transferable_bank_id), + $booking->marking, + $booking->fix_amount, + $booking->fix_currency_id, + $booking->convertible_currency_id, + $booking->conversion_currency_id + ); + $this->canUpdateBooking->passes($booking_object); + $booking = $this->updatesBooking->execute($booking, $booking_object); + + DB::commit(); + + return $this->resourceResponse(new BookingResource($booking)); + + } catch (\Exception $exception){ + throw new ErrorException($exception->getMessage(), $exception->getCode()); + } + } + +} diff --git a/app/Http/Controllers/Bookings/UpdateBookingRecipientController.php b/app/Http/Controllers/Bookings/UpdateBookingRecipientController.php new file mode 100644 index 00000000..670db6da --- /dev/null +++ b/app/Http/Controllers/Bookings/UpdateBookingRecipientController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/resources/assets/vue/components/banks/forms/BankAccountFormComponent.vue b/resources/assets/vue/components/banks/forms/BankAccountFormComponent.vue index 6e9518d9..e1fd6f0d 100644 --- a/resources/assets/vue/components/banks/forms/BankAccountFormComponent.vue +++ b/resources/assets/vue/components/banks/forms/BankAccountFormComponent.vue @@ -136,9 +136,12 @@
{{disabled ? 'Change Recipient Account' : 'Cancel'}}
-
+
Add Account
+
+
Update Details
+
@@ -179,6 +182,10 @@ type: String, required: false, default: 'RMB' + }, + isEditing: { + type: Boolean, + default: false } }, data(){ @@ -224,10 +231,22 @@ }, methods: { submitForm(){ - this.submit(route('api.bank.create'), 'post', this.section, true, false); + if(this.isEditing){ + this.parameters.company_id = this.company_id; + this.parameters.account_type = this.type; + this.submit(route('api.bank.update', this.parameters.id), 'put', this.section, true, false); + } + else{ + this.submit(route('api.bank.create'), 'post', this.section, true, false); + } }, successHandler(response){ - this.type !== 2 ? this.closeModal() : this.$emit('createdBank', response.payload.data); + if(this.isEditing){ + this.type !== 2 ? this.closeModal() : this.$emit('updatedBankDetails', response.payload.data); + } + else{ + this.type !== 2 ? this.closeModal() : this.$emit('createdBank', response.payload.data); + } this.formHandler(); this.resetForm(); }, diff --git a/resources/assets/vue/components/banks/forms/PhoneAccountFormComponent.vue b/resources/assets/vue/components/banks/forms/PhoneAccountFormComponent.vue index 76401d2b..aea24179 100644 --- a/resources/assets/vue/components/banks/forms/PhoneAccountFormComponent.vue +++ b/resources/assets/vue/components/banks/forms/PhoneAccountFormComponent.vue @@ -42,9 +42,12 @@
{{disabled ? 'Change Recipient Account' : 'Cancel'}}
-
+
+
+ +
@@ -80,6 +83,10 @@ type: Object, required: false, default: null + }, + isEditing: { + type: Boolean, + default: false } }, data(){ @@ -115,10 +122,22 @@ submitForm(){ this.parameters.account_type = 3; this.parameters.bank_name = '-'; - this.submit(route('api.bank.create'), 'post', this.section, true, false); + if(this.isEditing){ + this.parameters.company_id = this.company_id; + this.parameters.account_type = this.type; + this.submit(route('api.bank.update', this.parameters.id), 'put', this.section, true, false); + } + else{ + this.submit(route('api.bank.create'), 'post', this.section, true, false); + } }, successHandler(response){ - this.type !== 2 ? this.closeModal() : this.$emit('createdBank', response.payload.data); + if(this.isEditing){ + this.type !== 2 ? this.closeModal() : this.$emit('updatedBankDetails', response.payload.data); + } + else{ + this.type !== 2 ? this.closeModal() : this.$emit('createdBank', response.payload.data); + } this.formHandler(); this.resetForm(); }, @@ -140,4 +159,4 @@ mixins: [FormHandler] } - \ No newline at end of file + diff --git a/resources/assets/vue/components/bookings/elements/BookingRecipientEditComponent.vue b/resources/assets/vue/components/bookings/elements/BookingRecipientEditComponent.vue new file mode 100644 index 00000000..ffdbece2 --- /dev/null +++ b/resources/assets/vue/components/bookings/elements/BookingRecipientEditComponent.vue @@ -0,0 +1,141 @@ + + + diff --git a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue index 37a51a43..e2f5dfad 100644 --- a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue +++ b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue @@ -81,6 +81,14 @@ +
+
+
EDIT
+
+ + + +
@@ -540,12 +548,26 @@ id: '', status: false }, - onlinePayment: { + onlinePayment: { id: '', status: false }, amount: (Math.round((this.data.outstanding_amount + Number.EPSILON) * 100) / 100).toFixed(2), - calculation: null + calculation: null, + recipientBanks: { + company: this.data.company, + serviceType: { + status: false, + id: this.data.service.id, + name: this.data.service.name, + currencies: this.data.service.configurations.currencies, + selectedCurrency: this.data.service.configurations.currencies[0] + }, + bankAccount: this.data.bank, + bankAccountDefault: this.data.bank, + recipientBanks: this.data.company.recipient_banks.accounts, + bookingId: this.data.id + } } }, validations () { @@ -575,14 +597,12 @@ id: bankCode, status: true, } - }, submitForm(){ this.parameters = { payment_method: this.paymentMethod.id, amount: this.amount }; - this.submit(route('api.booking.payment.quotation', this.item.id), 'post', this.section, false, false) this.calculation = null; }, @@ -600,9 +620,12 @@ cancelQuotation(){ this.calculation = null; this.expandPayment = false; + }, + updatedBankDetails(bank){ + this.item.bank = bank; } }, mixins: [componentHandler], directives: {money: VMoney} } - \ No newline at end of file + diff --git a/resources/assets/vue/components/bookings/forms/UpdateBookingComponent.vue b/resources/assets/vue/components/bookings/forms/UpdateBookingComponent.vue new file mode 100644 index 00000000..73d6d51f --- /dev/null +++ b/resources/assets/vue/components/bookings/forms/UpdateBookingComponent.vue @@ -0,0 +1,41 @@ + + + diff --git a/routes/booking.php b/routes/booking.php index 0cbeca76..e54ba278 100644 --- a/routes/booking.php +++ b/routes/booking.php @@ -7,6 +7,7 @@ Route::group(['prefix' => 'booking', 'as' => 'booking.', 'namespace' => 'Booking Route::get('/list', 'ListBookingsController@list')->name('list'); Route::post('/create', 'CreateBookingController@create')->name('create'); Route::put('/update/{id}', 'UpdateBookingController@update')->name('update'); + Route::put('/recipient/update/{id}', 'UpdateBookingRecipientController@update')->name('update.recipient'); Route::put('/cancel/{id}', 'CancelBookingController@cancel')->name('cancel'); Route::put('/restore/{id}', 'RestoreBookingController@restore')->name('restore'); Route::delete('/delete/{id}', 'DeleteBookingController@delete')->name('delete'); @@ -33,4 +34,4 @@ Route::group(['prefix' => 'booking', 'as' => 'booking.', 'namespace' => 'Booking Route::post('{id}/proforma/create', 'CreateProformaInvoiceTransaction@create')->name('proforma.create'); -}); \ No newline at end of file +}); From 0b37cf6e7275c5f5d18f4e8d51715b1b976a92f7 Mon Sep 17 00:00:00 2001 From: Dillon Date: Fri, 20 Jan 2023 23:47:22 +0800 Subject: [PATCH 002/228] Edit recipient details do not allow empty --- .../bookings/elements/BookingRecipientEditComponent.vue | 1 + .../vue/components/bookings/forms/UpdateBookingComponent.vue | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/assets/vue/components/bookings/elements/BookingRecipientEditComponent.vue b/resources/assets/vue/components/bookings/elements/BookingRecipientEditComponent.vue index ffdbece2..6240b629 100644 --- a/resources/assets/vue/components/bookings/elements/BookingRecipientEditComponent.vue +++ b/resources/assets/vue/components/bookings/elements/BookingRecipientEditComponent.vue @@ -129,6 +129,7 @@ this.createBank = false; this.isEditing = false; this.account_no = ''; + this.parameters.bankAccount = {}; }, cancelUpdate(){ this.parameters.bankAccount = this.parameters.bankAccountDefault; diff --git a/resources/assets/vue/components/bookings/forms/UpdateBookingComponent.vue b/resources/assets/vue/components/bookings/forms/UpdateBookingComponent.vue index 73d6d51f..16cae41c 100644 --- a/resources/assets/vue/components/bookings/forms/UpdateBookingComponent.vue +++ b/resources/assets/vue/components/bookings/forms/UpdateBookingComponent.vue @@ -3,7 +3,7 @@
-
+
From cd80950d65bb5552d921a1c0e44be6611d89dbe6 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Sat, 23 Sep 2023 11:56:21 +0800 Subject: [PATCH 003/228] expired booking --- .../Commands/ExpiredBookingCommand.php | 95 +++++++++++++++++++ app/Console/Kernel.php | 4 + 2 files changed, 99 insertions(+) create mode 100644 app/Console/Commands/ExpiredBookingCommand.php diff --git a/app/Console/Commands/ExpiredBookingCommand.php b/app/Console/Commands/ExpiredBookingCommand.php new file mode 100644 index 00000000..2598b380 --- /dev/null +++ b/app/Console/Commands/ExpiredBookingCommand.php @@ -0,0 +1,95 @@ +updatesBookingStatus = $updatesBookingStatus; + } + + /** + * Execute the console command. + * + * @return int + */ + public function handle() + { + // Cancel booking without payment & purchase order (1 month) + $bookings = Booking::where('status', ApprovalStatus::APPROVED) + ->where('created_at', '<', now()->subDays(30)->endOfDay()) + ->where(function ($query) { + $query->whereDoesntHave('transactions') + ->orWhereDoesntHave('transactions', function($transaction) { + return $transaction->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); + })->get(); + + foreach ($bookings as $booking) { + $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); + Log::info("Expired Booking without payment & purchase order, booking id: " . $booking->id); + $transactions = $booking->transactions; + + foreach ($transactions as $transaction) { + $transaction->status = ApprovalStatus::EXPIRED; + $transaction->save(); + Log::info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}"); + } + } + + // Cancel booking without payment but with purchase order (2 month) + $bookings = Booking::where('status', ApprovalStatus::APPROVED) + ->where('created_at', '<', now()->subDays(60)->endOfDay()) + ->where(function ($query) { + $query->whereDoesntHave('transactions', function($transaction) { + return $transaction->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + })->whereHas('transactions', function($transaction) { + return $transaction->where('type', TransactionType::PURCHASE_ORDER); + }); + })->get(); + + foreach ($bookings as $booking) { + $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); + Log::info("Expired Booking without payment but with purchase order, booking id: " . $booking->id); + $transactions = $booking->transactions; + + foreach ($transactions as $transaction) { + $transaction->status = ApprovalStatus::EXPIRED; + $transaction->save(); + Log::info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}"); + } + } + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index cb9cf060..0355aea1 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -43,6 +43,10 @@ class Kernel extends ConsoleKernel ->everyMinute() ->appendOutputTo(storage_path().'/logs/regenerateInvoice.log') ->withoutOverlapping(); + + $schedule->command('booking:expired') + ->dailyAt('02:00') + ->withoutOverlapping(); } /** From 32602cab31318eb8813696fdd238a17181cfd38b Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Sat, 23 Sep 2023 13:00:04 +0800 Subject: [PATCH 004/228] auto fill purchase order command --- .../Commands/AutoFillPurchaseOrderCommand.php | 112 ++++++++++++++++++ .../Commands/ExpiredBookingCommand.php | 4 +- 2 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 app/Console/Commands/AutoFillPurchaseOrderCommand.php diff --git a/app/Console/Commands/AutoFillPurchaseOrderCommand.php b/app/Console/Commands/AutoFillPurchaseOrderCommand.php new file mode 100644 index 00000000..059232d2 --- /dev/null +++ b/app/Console/Commands/AutoFillPurchaseOrderCommand.php @@ -0,0 +1,112 @@ +generatesPurchaseOrderProducts = $generatesPurchaseOrderProducts; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->createPurchaseOrderTransactionProcessor = $createPurchaseOrderTransactionProcessor; + } + + /** + * Execute the console command. + * + * @return int + */ + public function handle() + { + $bookings = Booking::where('status', ApprovalStatus::APPROVED) + ->where('created_at', '<', now()->subDays(60)->endOfDay()) + ->whereHas('transactions', function($transaction) { + return $transaction->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }) + ->whereDoesntHave('transactions', function($transaction){ + $transaction->where('type', TransactionType::PURCHASE_ORDER); + $transaction->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED]); + })->get(); + + foreach ($bookings as $booking) { + $po = Transaction::where('type', TransactionType::PURCHASE_ORDER) + ->where('status', ApprovalStatus::APPROVED)->where('issuer', $booking->company_id) + ->select('*', DB::raw('abs(amount - ' . $booking->fix_amount . ') as nearest_price'))->orderBy('nearest_price')->first(); + + + if (!$po) { + $po = Transaction::where('type', TransactionType::PURCHASE_ORDER) + ->where('status', ApprovalStatus::APPROVED)->select('*', DB::raw('abs(amount - ' . $booking->fix_amount . ') as nearest_price'))->orderBy('nearest_price')->first(); + } + + $products = $this->generatesPurchaseOrderProducts->execute($po, $booking->fix_amount); + + $deference = $booking->fix_amount - $products->sum('total'); + + if($deference > -150 && $deference < 150 && $deference != 0) { + + $products->push([ + 'description' => $deference < 0 ? 'Discount':'Shipping Fee', + 'quantity' => 1, + 'stockCode' => '', + 'total' => $deference, + 'unit_price' => $deference + ]); + } + + $billNumber = $this->generatesTransactionBillNumber->execute('XPO-'); + + $total = $products->sum('total'); + + $object = new TransactionObject($billNumber, TransactionType::PURCHASE_ORDER, $booking->company->id, 1, + 1, PaymentMethodType::CASH, + $total, $total, $booking->fix_currency_id, $booking->fix_currency_id, + 1, 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, $products->toArray()); + + $this->createPurchaseOrderTransactionProcessor->execute($booking, $object); + } + } +} diff --git a/app/Console/Commands/ExpiredBookingCommand.php b/app/Console/Commands/ExpiredBookingCommand.php index 2598b380..37fe8612 100644 --- a/app/Console/Commands/ExpiredBookingCommand.php +++ b/app/Console/Commands/ExpiredBookingCommand.php @@ -55,7 +55,7 @@ class ExpiredBookingCommand extends Command ->orWhereDoesntHave('transactions', function($transaction) { return $transaction->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); }); - })->get(); + })->get(); foreach ($bookings as $booking) { $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); @@ -78,7 +78,7 @@ class ExpiredBookingCommand extends Command })->whereHas('transactions', function($transaction) { return $transaction->where('type', TransactionType::PURCHASE_ORDER); }); - })->get(); + })->get(); foreach ($bookings as $booking) { $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); From f1c23d46dde54f6cbcd768df15370d4972624b54 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Tue, 26 Sep 2023 21:30:51 +0800 Subject: [PATCH 005/228] update --- app/Console/Commands/AutoFillPurchaseOrderCommand.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Console/Commands/AutoFillPurchaseOrderCommand.php b/app/Console/Commands/AutoFillPurchaseOrderCommand.php index 059232d2..65a6fa93 100644 --- a/app/Console/Commands/AutoFillPurchaseOrderCommand.php +++ b/app/Console/Commands/AutoFillPurchaseOrderCommand.php @@ -16,7 +16,7 @@ use App\Classes\ValueObjects\Constants\PaymentMethodType; use App\Models\Transaction; use Illuminate\Support\Facades\DB; -class ExpiredBookingCommand extends Command +class AutoFillPurchaseOrderCommand extends Command { /** * The name and signature of the console command. @@ -61,6 +61,7 @@ class ExpiredBookingCommand extends Command */ public function handle() { + // 5. If purchase order not fill up in 2 month, auto fill up it $bookings = Booking::where('status', ApprovalStatus::APPROVED) ->where('created_at', '<', now()->subDays(60)->endOfDay()) ->whereHas('transactions', function($transaction) { From 75f44fae74126045ebf5ac58108e374596b7045e Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Tue, 26 Sep 2023 21:31:09 +0800 Subject: [PATCH 006/228] update --- app/Console/Commands/ExpiredBookingCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Console/Commands/ExpiredBookingCommand.php b/app/Console/Commands/ExpiredBookingCommand.php index 37fe8612..c5b4081c 100644 --- a/app/Console/Commands/ExpiredBookingCommand.php +++ b/app/Console/Commands/ExpiredBookingCommand.php @@ -47,7 +47,7 @@ class ExpiredBookingCommand extends Command */ public function handle() { - // Cancel booking without payment & purchase order (1 month) + // 1. Cancel booking without payment & purchase order (1 month) $bookings = Booking::where('status', ApprovalStatus::APPROVED) ->where('created_at', '<', now()->subDays(30)->endOfDay()) ->where(function ($query) { @@ -69,7 +69,7 @@ class ExpiredBookingCommand extends Command } } - // Cancel booking without payment but with purchase order (2 month) + // 2. Cancel booking without payment but with purchase order (2 month) $bookings = Booking::where('status', ApprovalStatus::APPROVED) ->where('created_at', '<', now()->subDays(60)->endOfDay()) ->where(function ($query) { From 4be3b11a505c663a78f6f6abc42223f5fe0e1bc5 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Tue, 26 Sep 2023 21:32:20 +0800 Subject: [PATCH 007/228] add auto fill purchase order job inside kernel --- app/Console/Kernel.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 0355aea1..46e77f3a 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -47,6 +47,10 @@ class Kernel extends ConsoleKernel $schedule->command('booking:expired') ->dailyAt('02:00') ->withoutOverlapping(); + + $schedule->command('purchaseOrder:autoFill') + ->dailyAt('03:00') + ->withoutOverlapping(); } /** From a84cbdde6a09d0fecc4342f1014e868fae868f36 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Wed, 27 Sep 2023 14:12:32 +0800 Subject: [PATCH 008/228] add cancel booking for refunded payment --- .../Commands/ExpiredBookingCommand.php | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/app/Console/Commands/ExpiredBookingCommand.php b/app/Console/Commands/ExpiredBookingCommand.php index c5b4081c..d79b7b9c 100644 --- a/app/Console/Commands/ExpiredBookingCommand.php +++ b/app/Console/Commands/ExpiredBookingCommand.php @@ -9,6 +9,7 @@ use Illuminate\Console\Command; use Carbon\Carbon; use Illuminate\Support\Facades\Log; use App\Classes\Modules\Bookings\Services\UpdatesBookingStatus; +use App\Models\Transaction; class ExpiredBookingCommand extends Command { @@ -91,5 +92,62 @@ class ExpiredBookingCommand extends Command Log::info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}"); } } + + // 3. Cancel fully refunded payment & cancel booking + $transactions = Transaction::where('type', TransactionType::CREDIT_NOTE)->get(); + + foreach ($transactions as $transaction) { + // get the booking marking + $marking = substr($transaction->payment_reference, -5); + + // for a special payment reference on transaction id: 152013 + if (!is_numeric($marking)) { + $payment_reference = explode(" ", trim($transaction->payment_reference)); + if (count($payment_reference) > 1) { + $marking = $payment_reference[count($payment_reference) - 2]; + } + } + + if (is_numeric($marking)) { + $booking = Booking::where('marking', $marking)->first(); + + if ($booking) { + if ($booking->status === ApprovalStatus::APPROVED) { + $bookingPayment = $booking->transactions()->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first(); + if (!$bookingPayment) { + $bookingPayment = $booking->transactions()->payments()->count(); + Log::info("Credit note transaction id: {$transaction->id}, there are {$bookingPayment} payment for the booking."); + $bookingPayment = $booking->transactions()->payments()->whereIn('status', [ApprovalStatus::EXPIRED, ApprovalStatus::REJECTED])->first(); + $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); + + 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}"); + } + } else { + $status = ApprovalStatus::APPROVAL_STATUS_ID[$booking->status]; + Log::info("Credit note transaction id: {$transaction->id}, booking status is {$status}"); + } + } else { + Log::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}"); + } + } } } From 946ee7b6f978305c69f8099aed9f8a9e33d4781c Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Fri, 29 Sep 2023 15:42:15 +0800 Subject: [PATCH 009/228] refund booking --- .../CreateBookingRefundLogic.php | 20 ++++++++++--------- .../UpdateRefundTransactionStatusLogic.php | 4 +++- .../elements/PaymentHistoryComponent.vue | 6 +++--- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php index d31ee2ce..398312c9 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php @@ -19,6 +19,7 @@ use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionRefundCalculationObject; +use App\Classes\ValueObjects\Constants\PaymentMethodType; class CreateBookingRefundLogic extends AbstractControllerLogic { @@ -84,21 +85,22 @@ class CreateBookingRefundLogic extends AbstractControllerLogic $billNumber = $this->generatesTransactionBillNumber->execute('RFD-'); - $refund = $transaction->transactions()->refunds()->sum('amount'); + $refund = $transaction->transactions()->refunds()->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->sum('original_amount'); if($refund + $request->input('amount') > $transaction->original_amount) throw new MalformedRequestException('Your refund must not be greater than '. $transaction->original_amount .'.'); - $amount = $transaction->booking->fix_currency_id == 1 ? $request->input('amount') : $request->input('amount') / $transaction->currency_rate; + // $transactionRefundCalculationObject = new TransactionRefundCalculationObject($booking, $transaction, $request->input('amount')); + // $transactionRefundCalculationObject->init(); - - $transactionRefundCalculationObject = new TransactionRefundCalculationObject($booking, $transaction, $amount); - $transactionRefundCalculationObject->init(); + $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; $object = new TransactionObject($billNumber, TransactionType::REFUND, 1, $booking->company->id, - 1, $transactionRefundCalculationObject->getConversionObject()->getPaymentMethod(), - $transactionRefundCalculationObject->getRefundTotalAmount(), $transactionRefundCalculationObject->getAmount(), 1, - $transactionRefundCalculationObject->getConversionObject()->getCurrencyId(), $transactionRefundCalculationObject->getTransaction()->currency_rate, - $transactionRefundCalculationObject->getRefundTax(), $transactionRefundCalculationObject->getRefundServiceCharge(), null, ApprovalStatus::PENDING_VERIFICATION, [], $transaction->bill_no); + 1, PaymentMethodType::CASH, + $refundTotal, $request->input('amount'), 1, + $transaction->original_currency_id, $transaction->currency_rate, + $transaction->tax, $transaction->service_charge, null, ApprovalStatus::PENDING_VERIFICATION, [], $transaction->bill_no); $transaction = $this->createsTransaction->execute($transaction, $object); diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php index b86e4878..bf704359 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php @@ -73,7 +73,9 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic $booking = $transaction->owner->owner; - $reference = 'Credit Voucher for Overpaid for Ref. '.$booking->marking; + $paymentTransaction = $transaction->owner; + + $reference = $transaction->amount == $paymentTransaction->amount ? 'Fully Refund for Ref. ' . $booking->marking : 'Partially Refund for Ref. ' . $booking->marking; if ($transaction->status == ApprovalStatus::APPROVED) { $this->creditWalletProcessor->execute($booking->company, $transaction->type, $transaction->amount, $reference); diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index ce4ba5a7..63cb4687 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -133,7 +133,7 @@
Requested Refund Amount
-
{{item.currency.short_code}} {{(Math.round((totalRequestedRefund + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
{{item.original_currency.short_code}} {{(Math.round((totalRequestedRefund + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
@@ -271,9 +271,9 @@
-
+
- + From 1ac2ac3102c3f2b5e3aff5907d4136fd362e4fb3 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Wed, 29 Nov 2023 23:39:15 +0800 Subject: [PATCH 010/228] Voucherify UI update for kexin to take a look --- .../forms/BookingPaymentQuotationComponent.vue | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue index 6f18170c..50c6c701 100644 --- a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue +++ b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue @@ -244,17 +244,17 @@
- +
- + Apply a voucher
@@ -262,11 +262,11 @@ {{ voucherCodeFailedReason }} Voucher applied
- +
From 52c2dade88e485677bf015b4a3d0cc3d60ea5937 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sun, 3 Dec 2023 23:13:52 +0800 Subject: [PATCH 011/228] Update UI based on kexin feedback --- .../elements/AvailableVouchersComponent.vue | 19 +++++++++++-------- .../BookingPaymentQuotationComponent.vue | 14 +++++++------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue b/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue index 45722aaf..7c3d5494 100644 --- a/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue +++ b/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue @@ -3,18 +3,21 @@
-
-
-

{{ item.voucher.code }}

+
List of Vouchers, click to select
+
+ + {{ item.voucher.code }} +
+
+ Valid till {{ item.voucher.end_date }} -
-
+ + No expiry date -
+
diff --git a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue index 50c6c701..50a421b5 100644 --- a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue +++ b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue @@ -244,11 +244,11 @@
-
+
@@ -256,17 +256,17 @@
+
+
+ +
+
Apply a voucher
{{ voucherCodeFailedReason }} Voucher applied
-
-
- -
-
From 19d08242d52715ade37228e3fc6dc3fa88af32f8 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sun, 3 Dec 2023 23:17:09 +0800 Subject: [PATCH 012/228] Update UI based on kexin feedback --- .../forms/BookingPaymentQuotationComponent.vue | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue index 50a421b5..e0e2ae8d 100644 --- a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue +++ b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue @@ -256,17 +256,17 @@
-
-
- -
-
Apply a voucher
{{ voucherCodeFailedReason }} Voucher applied
+
+
+ +
+
From 96c00ea66b68aace86afe6272cc7ee8594739028 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sun, 3 Dec 2023 23:19:31 +0800 Subject: [PATCH 013/228] Update UI based on kexin feedback --- .../bookings/forms/BookingPaymentQuotationComponent.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue index e0e2ae8d..73f7a006 100644 --- a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue +++ b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue @@ -257,7 +257,7 @@
Apply a voucher -
+
{{ voucherCodeFailedReason }} Voucher applied From 150f6a69d6dc77dcf032723aa49fec3529df3759 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sun, 3 Dec 2023 23:34:36 +0800 Subject: [PATCH 014/228] Update UI based on kexin feedback --- .../bookings/elements/AvailableVouchersComponent.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue b/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue index 7c3d5494..4ac885ff 100644 --- a/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue +++ b/resources/assets/vue/components/bookings/elements/AvailableVouchersComponent.vue @@ -1,9 +1,9 @@ + + \ No newline at end of file diff --git a/resources/assets/vue/components/accounting/sections/ReportTransactionsMappedComponent.vue b/resources/assets/vue/components/accounting/sections/ReportTransactionsMappedComponent.vue index e3d4e0d2..86da623c 100644 --- a/resources/assets/vue/components/accounting/sections/ReportTransactionsMappedComponent.vue +++ b/resources/assets/vue/components/accounting/sections/ReportTransactionsMappedComponent.vue @@ -3,19 +3,74 @@
-
-
-
-
Mapped Report
+
+ +
+
+
+
Mapped Report
+
+
+
+
+
History Imported Invoices Report
+
+
+
+
+
History Imported Receipts Report
+
+
-
+
+
+
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+
+
+ + + + +
+
+ + + + +
+
+
+
Mapped Report
+
+
+
+
@@ -35,7 +90,7 @@
- + @@ -44,22 +99,175 @@
+ + +
+
+
+
+
+
+
+ + + + +
+
+ + + + +
+
+
+
History Imported Invoices Report
+
+
+
+
+
+
+
+
Date
+
+
+
+ + + + +
+
+
+
+ + +
+
+
+
+
+
+
+ + + + +
+
+ + + + +
+
+
+
History Imported Receipts Report
+
+
+
+
+
+
+
+
Date
+
+
+
+ + + + +
+
+
+
\ No newline at end of file + diff --git a/resources/assets/vue/components/general/elements/ListPollingComponent.vue b/resources/assets/vue/components/general/elements/ListPollingComponent.vue new file mode 100644 index 00000000..98e2a44b --- /dev/null +++ b/resources/assets/vue/components/general/elements/ListPollingComponent.vue @@ -0,0 +1,204 @@ + + + diff --git a/routes/api.php b/routes/api.php index 8b4bada0..460bd772 100644 --- a/routes/api.php +++ b/routes/api.php @@ -67,6 +67,10 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function require __DIR__ . '/milestone.php'; + // require __DIR__ . '/accounting.php'; //cief todo: To check if this is needed + + require __DIR__ . '/job.php'; + // require __DIR__ . '/rate.php'; // require __DIR__ . '/receipt.php'; diff --git a/routes/currency.php b/routes/currency.php index b621aad6..ba55c9a2 100644 --- a/routes/currency.php +++ b/routes/currency.php @@ -1,4 +1,4 @@ - 'document', 'as' => 'document.', 'namespace' => 'Documents'], function () { Route::get('/list', 'ListDocumentsController@list')->name('list'); + Route::get('/list/job', 'ListDocumentsJobController@list')->name('list.job'); Route::delete('/{id}/delete', 'DeleteDocumentController@delete')->name('delete'); Route::put('/{id}/approve', 'ApproveDocumentController@approve')->name('status.approve'); Route::put('/{id}/reject', 'RejectDocumentController@reject')->name('status.reject'); Route::put('/{id}/reference/update', 'UpdateDocumentReferenceController@update')->name('reference.update'); -}); \ No newline at end of file +}); diff --git a/routes/job.php b/routes/job.php new file mode 100644 index 00000000..f32d142e --- /dev/null +++ b/routes/job.php @@ -0,0 +1,7 @@ + 'job', 'as' => 'job.', 'namespace' => 'Jobs'], function () { + Route::get('/fetch/{job_id}', 'FetchJobResultController@fetch')->name('fetch'); +}); From 6da337b9dc50e1beb1cef220d2afcbafb37a698e Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sat, 30 Dec 2023 01:26:58 +0800 Subject: [PATCH 024/228] Code sync from Shipping Portal, independent deployment of Vue Polling, additional amendment to run Vue Polling at /billings --- ..._add_new_column_2_to_job_results_table.php | 34 +++++ .../AdminPaymentsBillingSectionComponent.vue | 136 ++++++++++++++++++ .../vue/general/mixins/aws/requestV2.js | 49 +++++++ .../assets/vue/general/mixins/tabHandler.js | 24 ++++ .../assets/vue/vuex/modules/crudRequestV2.js | 47 ++++++ resources/assets/vue/vuex/store.js | 4 +- resources/views/pages/billings.blade.php | 126 +--------------- 7 files changed, 295 insertions(+), 125 deletions(-) create mode 100644 database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php create mode 100644 resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue create mode 100644 resources/assets/vue/general/mixins/aws/requestV2.js create mode 100644 resources/assets/vue/general/mixins/tabHandler.js create mode 100644 resources/assets/vue/vuex/modules/crudRequestV2.js diff --git a/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php b/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php new file mode 100644 index 00000000..12c6d57f --- /dev/null +++ b/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php @@ -0,0 +1,34 @@ +string('request_signature')->after('job_id')->nullable(); + $table->string('result_signature')->after('request_signature')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('job_results', function (Blueprint $table) { + $table->dropColumn('request_signature'); + $table->dropColumn('result_signature'); + }); + } +} diff --git a/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue b/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue new file mode 100644 index 00000000..03244ff4 --- /dev/null +++ b/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue @@ -0,0 +1,136 @@ + + diff --git a/resources/assets/vue/general/mixins/aws/requestV2.js b/resources/assets/vue/general/mixins/aws/requestV2.js new file mode 100644 index 00000000..12b27542 --- /dev/null +++ b/resources/assets/vue/general/mixins/aws/requestV2.js @@ -0,0 +1,49 @@ +export default { + methods: { + poll(url, method, section, successNotification = true, errorNotification = true){ + if(!this.validate()){ return; } + if (section) { + this.$store.dispatch('toggleLoading', {name: section, status: true}) + } + this.$store.dispatch('crudRequestV2', { + endpoint: url, + method: method, + parameters: this.parameters + }).then(response => { + let statusCode = response.status, + success = response.ok; + + response.json().then(response => { + + if(!success){ + this.openModal(); + errorNotification ? this.$store.dispatch('createNotification', {title: response.title, message: response.message, type: 'error'}): null; + this.errorHandler(response, statusCode); return; + } + + successNotification ? this.$store.dispatch('createNotification', {title: response.title, message: response.message, type: 'success'}): null; + this.successHandler(response) + + + }); + }).catch((error) => { + this.$store.dispatch('createNotification', {title: 'Unexpected Error', message: 'An unexpected error has occurred. Try again!', type: 'error'}); + }).then(() => { + if (section) { + this.$store.dispatch('toggleLoading', {name: section, status: false}) + } + }) + + }, + validate() { + if(this.$v){ + this.$v.$touch(); + return !this.$v.$invalid; + } + return true; + }, + successHandler(response){}, + errorHandler(response){} + } + +} diff --git a/resources/assets/vue/general/mixins/tabHandler.js b/resources/assets/vue/general/mixins/tabHandler.js new file mode 100644 index 00000000..81790ed0 --- /dev/null +++ b/resources/assets/vue/general/mixins/tabHandler.js @@ -0,0 +1,24 @@ +export default { + data() { + return { + activeTab: null, + displayedTabs: [], + }; + }, + methods: { + setActiveTab(event) { + const tabName = event.currentTarget.getAttribute('tab-name'); + // console.log(`Tab "${tabName}" clicked`); + this.activeTab = tabName; + if (!this.displayedTabs.includes(tabName)) { + this.displayedTabs.push(tabName); + } + }, + isActiveTab(tabName) { + return this.activeTab === tabName; + }, + showTabContent(tabName) { + return this.displayedTabs.includes(tabName); + }, + }, +} diff --git a/resources/assets/vue/vuex/modules/crudRequestV2.js b/resources/assets/vue/vuex/modules/crudRequestV2.js new file mode 100644 index 00000000..2445190e --- /dev/null +++ b/resources/assets/vue/vuex/modules/crudRequestV2.js @@ -0,0 +1,47 @@ +export default { + actions: { + crudRequestV2({getters, dispatch}, {endpoint, method, parameters}){ + const queryDomain = endpoint.split('?')[0]; + let encodedParams = endpoint.split('?')[1]; + let decodedParams = fullyDecodeURI(encodedParams); + const queryParams = encodeURIComponent(decodedParams); + encodedParams = queryParams.toString(); + let filteredEncodedParams = encodedParams.replace(/%3D/g,'='); + filteredEncodedParams = filteredEncodedParams.replace(/%26/g,'&'); + let combinedAbsoluteUrl = queryDomain; + if(filteredEncodedParams !== undefined && filteredEncodedParams !== 'undefined'){ + combinedAbsoluteUrl = queryDomain + '?' + filteredEncodedParams; + } + + // return fetch(endpoint, { + return fetch(combinedAbsoluteUrl, { + method: method, + responseType: 'json', + body: parameters ? JSON.stringify(parameters):null, + headers: { + 'content-type': 'application/json', + 'Authorization': 'Bearer '+getters.getAccessToken + } + }).then(response => { + if(response.status === 401 && window.location.href !== route('login') && window.location.href.indexOf(route('last_mile_delivery.login')) <= -1){ + dispatch('userAuthentication', {access_token: '', redirect_url: [7, 8].includes(getters.getCompanyModuleType) ? route('last_mile_delivery.login') : route('login')}); + } + + return response; + + }) + } + } +} + +function isEncoded(uri) { + uri = uri || ''; + return uri !== decodeURIComponent(uri); +} + +function fullyDecodeURI(uri){ + while (isEncoded(uri)){ + uri = decodeURIComponent(uri); + } + return uri; +} diff --git a/resources/assets/vue/vuex/store.js b/resources/assets/vue/vuex/store.js index 2c3d911b..ff10c673 100644 --- a/resources/assets/vue/vuex/store.js +++ b/resources/assets/vue/vuex/store.js @@ -4,6 +4,7 @@ import toggleSection from './modules/toggleSection' import toggleLoading from './modules/toggleLoading' import createNotification from './modules/createNotification' import crudRequest from './modules/crudRequest' +import crudRequestV2 from './modules/crudRequestV2' import authentication from './modules/authentication' import loadRequestQueue from './modules/loadRequestQueue' @@ -16,6 +17,7 @@ export default new Vuex.Store({ loadRequestQueue, createNotification, crudRequest, + crudRequestV2, authentication } -}) \ No newline at end of file +}) diff --git a/resources/views/pages/billings.blade.php b/resources/views/pages/billings.blade.php index 4bc012d5..da84f8b9 100644 --- a/resources/views/pages/billings.blade.php +++ b/resources/views/pages/billings.blade.php @@ -3,129 +3,7 @@
- -
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
Invoice
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
Purchase Order
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
Delivery Order
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
Supplier Delivery Order
-
-
-
-
-
-
-
-
-
-
-
-
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
-
-
-
+
-@endsection \ No newline at end of file +@endsection From bf5ea2b2f23a00a49dbae4f76b628a9585ece1e6 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sat, 30 Dec 2023 18:35:17 +0800 Subject: [PATCH 025/228] Code sync from Shipping Portal, independent deployment of Vue Polling, Performance Improvement and tweaking for better user experience --- .../Eloquent/Filters/OrderByIdDesc.php | 20 ++++ .../Eloquent/Filters/RequestSignature.php | 19 ++++ .../Eloquent/Filters/ResultNotNull.php | 18 ++++ .../ControllersLogic/ListBookingJobLogic.php | 25 ++++- .../Processors/ListBookingsJobProcessor.php | 33 ++---- .../ControllersLogic/ListDocumentJobLogic.php | 39 +++---- .../Processors/ListDocumentsJobProcessor.php | 31 +++--- .../ControllersLogic/FetchJobResultLogic.php | 17 ++- .../ListGenericJobObject.php | 31 ++++-- .../UpdateJobResultObject.php | 60 +++++++++++ .../Processors/FetchesJobResultProcessor.php | 45 ++++++++ .../Processors/UpdateJobResultProcessor.php | 64 +++++++++++ .../Jobs/Services/CreatesJobResult.php | 8 +- .../Modules/Jobs/Services/ListsJobResult.php | 33 ++++++ .../Jobs/Services/UpdatesJobResult.php | 28 +++++ .../ListTransactionsJobLogic.php | 31 +++++- .../ListTransactionsJobProcessor.php | 29 +++-- app/Http/Resources/BookingResource.php | 12 +-- app/Http/Resources/CompanyResource.php | 32 +----- app/Http/Resources/DocumentResource.php | 8 +- app/Http/Resources/ListBookingJobResource.php | 81 ++++++++++++++ .../Resources/ListDocumentJobResource.php | 31 ++++++ .../Resources/ListTransactionJobResource.php | 54 ++++++++++ app/Http/Resources/V2/BookingV2Resource.php | 82 ++++++++++++++ app/Http/Resources/V2/CompanyV2Resource.php | 100 ++++++++++++++++++ .../assets/vue/vuex/modules/crudRequestV2.js | 56 +++++----- 26 files changed, 809 insertions(+), 178 deletions(-) create mode 100644 app/Classes/General/Eloquent/Filters/OrderByIdDesc.php create mode 100644 app/Classes/General/Eloquent/Filters/RequestSignature.php create mode 100644 app/Classes/General/Eloquent/Filters/ResultNotNull.php create mode 100644 app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php create mode 100644 app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php create mode 100644 app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php create mode 100644 app/Classes/Modules/Jobs/Services/ListsJobResult.php create mode 100644 app/Classes/Modules/Jobs/Services/UpdatesJobResult.php create mode 100644 app/Http/Resources/ListBookingJobResource.php create mode 100644 app/Http/Resources/ListDocumentJobResource.php create mode 100644 app/Http/Resources/ListTransactionJobResource.php create mode 100644 app/Http/Resources/V2/BookingV2Resource.php create mode 100644 app/Http/Resources/V2/CompanyV2Resource.php diff --git a/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php b/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php new file mode 100644 index 00000000..547ec9bd --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php @@ -0,0 +1,20 @@ +orderBy('id', 'desc'); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/RequestSignature.php b/app/Classes/General/Eloquent/Filters/RequestSignature.php new file mode 100644 index 00000000..67dde0a3 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/RequestSignature.php @@ -0,0 +1,19 @@ +where('request_signature', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/ResultNotNull.php b/app/Classes/General/Eloquent/Filters/ResultNotNull.php new file mode 100644 index 00000000..3f6a0341 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/ResultNotNull.php @@ -0,0 +1,18 @@ +whereNotNull('result'); + } +} diff --git a/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php index c87751a3..ef3570f7 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php @@ -5,12 +5,12 @@ namespace App\Classes\Modules\Bookings\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Jobs\ListBookingsJob; -use App\Classes\Modules\Bookings\Standards\Rules\CanListBookings; use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject; -use ErrorException; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use App\Classes\Modules\Jobs\Services\CreatesJobResult; + class ListBookingJobLogic extends AbstractControllerLogic { @@ -24,6 +24,19 @@ class ListBookingJobLogic extends AbstractControllerLogic ]; } + /** @var CreatesJobResult */ + private $createsJobResult; + + /** + * ListPackingListsJobLogic constructor. + * @param CreatesJobResult $createsJobResult + */ + public function __construct(CreatesJobResult $createsJobResult) + { + $this->createsJobResult = $createsJobResult; + } + + /** * @param Request $request * @return JsonResponse @@ -34,13 +47,17 @@ class ListBookingJobLogic extends AbstractControllerLogic $user = Auth::user(); $userInfo = (object) [ - 'email' => $user->email, 'type' => $user->type, ]; + $userInfoJson = json_encode($userInfo); + $requestSignature = md5($userInfoJson . $request->fullUrl()); + $listGenericJobObject = new ListGenericJobObject( $request->fullUrl(), $request->all(), + $requestSignature, + null, $jobId, $userInfo ); @@ -50,6 +67,8 @@ class ListBookingJobLogic extends AbstractControllerLogic $result = []; $result['job_id'] = $jobId; + $this->createsJobResult->execute($listGenericJobObject); + return $this->response(['data' => $result]); } diff --git a/app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php b/app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php index 6ded2977..2a09eb12 100644 --- a/app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php +++ b/app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php @@ -3,14 +3,10 @@ namespace App\Classes\Modules\Bookings\Processors; use App\Classes\Modules\Bookings\Services\ListsBookings; -use App\Classes\Modules\Jobs\Services\CreatesJobResult; -use App\Classes\Exceptions\MalformedRequestException; +use App\Classes\Modules\Jobs\Processors\UpdateJobResultProcessor; use App\Classes\General\Helper; -use Illuminate\Support\Facades\Http; -use Illuminate\Support\Facades\Log; use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject; -use Illuminate\Http\Resources\Json\ResourceCollection; -use App\Http\Resources\BookingResource; +use App\Http\Resources\ListBookingJobResource; class ListBookingsJobProcessor { @@ -18,24 +14,25 @@ class ListBookingsJobProcessor /** @var ListsBookings */ private $listsBookings; - /** @var CreatesJobResult */ - private $createsJobResult; + /** @var UpdateJobResultProcessor */ + private $updateJobResultProcessor; /** * ListBookingsJobProcessor constructor. * @param ListsBookings $listsBookings - * @param CreatesJobResult $createsJobResult + * @param UpdateJobResultProcessor $updateJobResultProcessor */ - public function __construct(ListsBookings $listsBookings, CreatesJobResult $createsJobResult) + public function __construct(ListsBookings $listsBookings, UpdateJobResultProcessor $updateJobResultProcessor) { $this->listsBookings = $listsBookings; - $this->createsJobResult = $createsJobResult; + $this->updateJobResultProcessor = $updateJobResultProcessor; } /** * @param ListGenericJobObject $listGenericJobObject - * @return null|object + * @return void * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException */ public function execute(ListGenericJobObject $listGenericJobObject) { @@ -43,15 +40,7 @@ class ListBookingsJobProcessor foreach ($query->items() as &$item) { $item['userInfo'] = $listGenericJobObject->getUserInfo(); } - - //cief todo: remove comments - $result = Helper::collectionResponse(BookingResource::collection($query)); - - // $result = new JobBookingCollectionResponse($query, $listGenericJobObject->getuserInfo()); - // $result = $this->collectionResponse(new BookingResourceCollection(BookingResource::collection($query), $listGenericJobObject->getuserInfo())); - - $create = $this->createsJobResult->execute($listGenericJobObject, json_encode($result)); - - return $create; + $resultCurrent = Helper::collectionResponse(ListBookingJobResource::collection($query)); + $this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent); } } diff --git a/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php b/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php index 041bb9c8..5e895ad8 100644 --- a/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php +++ b/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php @@ -4,15 +4,11 @@ namespace App\Classes\Modules\Documents\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; -use App\Classes\Modules\Documents\Services\ListsDocuments; +use App\Classes\Modules\Jobs\Services\CreatesJobResult; use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject; use App\Classes\Jobs\ListDocumentsJob; -use App\Http\Resources\DocumentResource; -use ErrorException; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use App\Classes\General\Helper; -use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Auth; class ListDocumentJobLogic extends AbstractControllerLogic @@ -28,6 +24,19 @@ class ListDocumentJobLogic extends AbstractControllerLogic ]; } + /** @var CreatesJobResult */ + private $createsJobResult; + + /** + * ListDocumentJobLogic constructor. + * @param CreatesJobResult $createsJobResult + */ + public function __construct(CreatesJobResult $createsJobResult) + { + $this->createsJobResult = $createsJobResult; + } + + /** * @param Request $request * @return JsonResponse @@ -42,33 +51,25 @@ class ListDocumentJobLogic extends AbstractControllerLogic 'type' => $user->type, ]; + $userInfoJson = json_encode($userInfo); + $requestSignature = md5($userInfoJson . $request->fullUrl()); $listGenericJobObject = new ListGenericJobObject( $request->fullUrl(), $request->all(), + $requestSignature, + null, $jobId, $userInfo ); ListDocumentsJob::dispatch($listGenericJobObject); - //cief todo: remove comments - // // Create your job instance with delay, so we can back here within delay and take control in our hands. - // $job = new ListDocuments($listGenericJobObject); - // $job->delay(now()->addSeconds(5)); - - // // Dispath your job with our custom_dispatch helper. This will return job id from jobs table - // // $jobId = $this->custom_dispatch($job); - - $result = []; $result['job_id'] = $jobId; + $this->createsJobResult->execute($listGenericJobObject); + return $this->response(['data' => $result]); } - - //cief todo: no longer need jobId - // function custom_dispatch($job): int { - // return app(\Illuminate\Contracts\Bus\Dispatcher::class)->dispatch($job); - // } } diff --git a/app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php b/app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php index eb7cf1c4..70777f0c 100644 --- a/app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php +++ b/app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php @@ -3,15 +3,10 @@ namespace App\Classes\Modules\Documents\Processors; use App\Classes\Modules\Documents\Services\ListsDocuments; -use App\Classes\Modules\Jobs\Services\CreatesJobResult; -use App\Classes\Exceptions\MalformedRequestException; +use App\Classes\Modules\Jobs\Processors\UpdateJobResultProcessor; use App\Classes\General\Helper; -use Illuminate\Support\Facades\Http; -use Illuminate\Support\Facades\Log; use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject; -use App\Http\Controllers\Documents\ListDocumentsController; -use Illuminate\Http\Resources\Json\ResourceCollection; -use App\Http\Resources\DocumentResource; +use App\Http\Resources\ListDocumentJobResource; class ListDocumentsJobProcessor { @@ -19,24 +14,25 @@ class ListDocumentsJobProcessor /** @var ListsDocuments */ private $listsDocuments; - /** @var CreatesJobResult */ - private $createsJobResult; + /** @var UpdateJobResultProcessor */ + private $updateJobResultProcessor; /** * ListDocumentsJobProcessor constructor. * @param ListsDocuments $listsDocuments - * @param CreatesJobResult $createsJobResult + * @param UpdateJobResultProcessor $updateJobResultProcessor */ - public function __construct(ListsDocuments $listsDocuments, CreatesJobResult $createsJobResult) + public function __construct(ListsDocuments $listsDocuments, UpdateJobResultProcessor $updateJobResultProcessor) { $this->listsDocuments = $listsDocuments; - $this->createsJobResult = $createsJobResult; + $this->updateJobResultProcessor = $updateJobResultProcessor; } /** * @param ListGenericJobObject $listGenericJobObject - * @return null|object + * @return void * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException */ public function execute(ListGenericJobObject $listGenericJobObject) { @@ -44,11 +40,8 @@ class ListDocumentsJobProcessor foreach ($query->items() as &$item) { $item['userInfo'] = $listGenericJobObject->getUserInfo(); } - - $result = Helper::collectionResponse(DocumentResource::collection($query)); - - $create = $this->createsJobResult->execute($listGenericJobObject, json_encode($result)); - - return $create; + $resultCurrent = Helper::collectionResponse(ListDocumentJobResource::collection($query)); + $this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent); } } + diff --git a/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php b/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php index 366fda8c..c4b72cf0 100644 --- a/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php +++ b/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php @@ -4,9 +4,8 @@ namespace App\Classes\Modules\Jobs\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; -use App\Classes\Modules\Jobs\Services\FetchesJobResult; +use App\Classes\Modules\Jobs\Processors\FetchesJobResultProcessor; use App\Http\Resources\JobResultResource; -use ErrorException; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -23,16 +22,16 @@ class FetchJobResultLogic extends AbstractControllerLogic ]; } - /** @var FetchesJobResult */ - private $fetchesJobResult; + /** @var FetchesJobResultProcessor */ + private $fetchesJobResultProcessor; /** * FetchJobResultLogic constructor. - * @param FetchesJobResult $fetchesJobResult + * @param FetchesJobResultProcessor $fetchesJobResultProcessor */ - public function __construct(FetchesJobResult $fetchesJobResult) + public function __construct(FetchesJobResultProcessor $fetchesJobResultProcessor) { - $this->fetchesJobResult = $fetchesJobResult; + $this->fetchesJobResultProcessor = $fetchesJobResultProcessor; } @@ -45,10 +44,8 @@ class FetchJobResultLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - $query = $this->fetchesJobResult->execute(['job_id' => $request->route('job_id')]); - + $query = $this->fetchesJobResultProcessor->execute($request); return $this->resourceResponse(new JobResultResource($query)); - } } diff --git a/app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php b/app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php index 365cd316..953d77d7 100644 --- a/app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php +++ b/app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php @@ -2,7 +2,6 @@ namespace App\Classes\Modules\Jobs\DataTransferObjects; -use Illuminate\Http\Request; use App\Classes\General\Interfaces\DataTransferObject; class ListGenericJobObject implements DataTransferObject @@ -16,6 +15,12 @@ class ListGenericJobObject implements DataTransferObject /** @var string */ private $jobId; + /** @var string */ + private $requestSignature; + + /** @var string */ + private $resultSignature; + /** @var object */ private $userInfo; @@ -25,11 +30,13 @@ class ListGenericJobObject implements DataTransferObject /** @var string */ private $jobCommand; - public function __construct(string $name, array $payload, string $jobId, object $userInfo = null) + public function __construct(string $name, array $payload, string $requestSignature, ?string $resultSignature, string $jobId, object $userInfo = null) { $this->name = $name; $this->payload = $payload; $this->jobId = $jobId; + $this->requestSignature = $requestSignature; + $this->resultSignature = $resultSignature; $this->userInfo = $userInfo; } @@ -57,6 +64,22 @@ class ListGenericJobObject implements DataTransferObject return $this->jobId; } + /** + * @return string + */ + public function getRequestSignature(): string + { + return $this->requestSignature; + } + + /** + * @return string + */ + public function getResultSignature(): ?string + { + return $this->resultSignature; + } + /** * @return object */ @@ -81,10 +104,6 @@ class ListGenericJobObject implements DataTransferObject return $this->jobCommand; } - // public function setJobId(int $jobId) - // { - // $this->jobId = $jobId; - // } public function setJobCommandName(string $jobCommandName) { diff --git a/app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php b/app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php new file mode 100644 index 00000000..636c56b0 --- /dev/null +++ b/app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php @@ -0,0 +1,60 @@ +result = $result; + $this->resultSignature = $resultSignature; + $this->jobCommandName = $jobCommandName; + $this->jobCommand = $jobCommand; + } + + /** + * @return string + */ + public function getResult(): string + { + return $this->result; + } + + /** + * @return array + */ + public function getResultSignature(): string + { + return $this->resultSignature; + } + + /** + * @return string + */ + public function getJobCommandName(): string + { + return $this->jobCommandName; + } + + /** + * @return string + */ + public function getJobCommand(): string + { + return $this->jobCommand; + } +} diff --git a/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php b/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php new file mode 100644 index 00000000..e19456e7 --- /dev/null +++ b/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php @@ -0,0 +1,45 @@ +fetchesJobResult = $fetchesJobResult; + } + + + /** + * @param Request $request + * @return Model + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException + * @throws \App\Classes\Exceptions\ResourceNotFoundException + */ + public function execute(Request $request){ + + $res1 = $this->fetchesJobResult->execute(['job_id' => $request->route('job_id')]); + + if(!$res1->result){ + Log::info('Job id: '.$request->route('job_id')); + $res2 = $this->fetchesJobResult->execute(['request_signature' => $res1->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]); + Log::info('Job id: '.$res2->id." , request_signature: ".$res2->request_signature); + return $res2; + } + + return $res1; + } +} diff --git a/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php b/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php new file mode 100644 index 00000000..fff83bb0 --- /dev/null +++ b/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php @@ -0,0 +1,64 @@ +fetchesJobResult = $fetchesJobResult; + $this->updatesJobResult = $updatesJobResult; + } + + /** + * @param ListGenericJobObject $listGenericJobObject + * @param array $resultCurrent + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException + */ + public function execute(ListGenericJobObject $listGenericJobObject, $resultCurrent) { + $jobResultCurrent = $this->fetchesJobResult->execute(['job_id' => $listGenericJobObject->getJobId()]); + $resultCurrentJson = json_encode($resultCurrent); + $resultSignatureCurrent = md5($resultCurrentJson); + + try{ + $jobResultExisting = $this->fetchesJobResult->execute(['request_signature' => $jobResultCurrent->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]); + $resultSignatureExisting = $jobResultExisting->result_signature; + if($resultSignatureExisting != $resultSignatureCurrent){ + $this->updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $listGenericJobObject->getJobCommandName(), $listGenericJobObject->getJobCommand()); + } + } catch (JobResourceNotFoundException $exception){ + $this->updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $listGenericJobObject->getJobCommandName(), $listGenericJobObject->getJobCommand()); + } + } + + private function updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $jobCommandName, $jobCommand){ + $updateJobResultObject = new UpdateJobResultObject( + $resultCurrentJson, + $resultSignatureCurrent, + $jobCommandName, + $jobCommand + ); + $create = $this->updatesJobResult->execute($jobResultCurrent, $updateJobResultObject); + } +} diff --git a/app/Classes/Modules/Jobs/Services/CreatesJobResult.php b/app/Classes/Modules/Jobs/Services/CreatesJobResult.php index 00acc1eb..e70e0e6a 100644 --- a/app/Classes/Modules/Jobs/Services/CreatesJobResult.php +++ b/app/Classes/Modules/Jobs/Services/CreatesJobResult.php @@ -10,18 +10,16 @@ class CreatesJobResult extends AbstractUpdateRecord { /** * @param ListGenericJobObject $listGenericJobObject - * @param string $result * @return \Illuminate\Database\Eloquent\Model * @throws \App\Classes\Exceptions\MalformedRequestException */ - public function execute(ListGenericJobObject $listGenericJobObject, string $result) + public function execute(ListGenericJobObject $listGenericJobObject) { $model = new JobResult(); $model->job_id = $listGenericJobObject->getJobId(); - $model->result = $result; + $model->request_signature = $listGenericJobObject->getRequestSignature(); + $model->result_signature = $listGenericJobObject->getResultSignature(); $model->url = $listGenericJobObject->getName(); - $model->job_command_name = $listGenericJobObject->getJobCommandName(); - $model->job_command = $listGenericJobObject->getJobCommand(); return $this->handler($model); } diff --git a/app/Classes/Modules/Jobs/Services/ListsJobResult.php b/app/Classes/Modules/Jobs/Services/ListsJobResult.php new file mode 100644 index 00000000..55f3b267 --- /dev/null +++ b/app/Classes/Modules/Jobs/Services/ListsJobResult.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Jobs/Services/UpdatesJobResult.php b/app/Classes/Modules/Jobs/Services/UpdatesJobResult.php new file mode 100644 index 00000000..ab3d9385 --- /dev/null +++ b/app/Classes/Modules/Jobs/Services/UpdatesJobResult.php @@ -0,0 +1,28 @@ +result = $updateJobResultObject->getResult(); + $model->result_signature = $updateJobResultObject->getResultSignature(); + $model->job_command_name = $updateJobResultObject->getJobCommandName(); + $model->job_command = $updateJobResultObject->getJobCommand(); + + return $this->handler($model); + + } +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php index d317d7eb..654a360f 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php @@ -5,10 +5,11 @@ namespace App\Classes\Modules\Transactions\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Jobs\ListTransactionsJob; +use App\Classes\Modules\Jobs\Services\CreatesJobResult; use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject; -use ErrorException; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; class ListTransactionsJobLogic extends AbstractControllerLogic { @@ -22,6 +23,19 @@ class ListTransactionsJobLogic extends AbstractControllerLogic ]; } + /** @var CreatesJobResult */ + private $createsJobResult; + + /** + * ListTransactionsJobLogic constructor. + * @param CreatesJobResult $createsJobResult + */ + public function __construct(CreatesJobResult $createsJobResult) + { + $this->createsJobResult = $createsJobResult; + } + + /** * @param Request $request * @return JsonResponse @@ -30,10 +44,21 @@ class ListTransactionsJobLogic extends AbstractControllerLogic { $jobId = uniqid(); + $user = Auth::user(); + $userInfo = (object) [ + 'type' => $user->type, + ]; + + $userInfoJson = json_encode($userInfo); + $requestSignature = md5($userInfoJson . $request->fullUrl()); + $listGenericJobObject = new ListGenericJobObject( $request->fullUrl(), $request->all(), - $jobId + $requestSignature, + null, + $jobId, + $userInfo ); ListTransactionsJob::dispatch($listGenericJobObject); @@ -41,6 +66,8 @@ class ListTransactionsJobLogic extends AbstractControllerLogic $result = []; $result['job_id'] = $jobId; + $this->createsJobResult->execute($listGenericJobObject); + return $this->response(['data' => $result]); } diff --git a/app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php b/app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php index 36671c89..475d4715 100644 --- a/app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php @@ -3,14 +3,10 @@ namespace App\Classes\Modules\Transactions\Processors; use App\Classes\Modules\Transactions\Services\ListsTransactions; -use App\Classes\Modules\Jobs\Services\CreatesJobResult; -use App\Classes\Exceptions\MalformedRequestException; +use App\Classes\Modules\Jobs\Processors\UpdateJobResultProcessor; use App\Classes\General\Helper; -use Illuminate\Support\Facades\Http; -use Illuminate\Support\Facades\Log; use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject; -use Illuminate\Http\Resources\Json\ResourceCollection; -use App\Http\Resources\TransactionResource; +use App\Http\Resources\ListTransactionJobResource; class ListTransactionsJobProcessor { @@ -18,33 +14,32 @@ class ListTransactionsJobProcessor /** @var ListsTransactions */ private $listsTransactions; - /** @var CreatesJobResult */ - private $createsJobResult; + /** @var UpdateJobResultProcessor */ + private $updateJobResultProcessor; /** * ListTransactionsJobProcessor constructor. * @param ListsTransactions $listsTransactions - * @param CreatesJobResult $createsJobResult + * @param UpdateJobResultProcessor $updateJobResultProcessor */ - public function __construct(ListsTransactions $listsTransactions, CreatesJobResult $createsJobResult) + public function __construct(ListsTransactions $listsTransactions, UpdateJobResultProcessor $updateJobResultProcessor) { $this->listsTransactions = $listsTransactions; - $this->createsJobResult = $createsJobResult; + $this->updateJobResultProcessor = $updateJobResultProcessor; } /** * @param ListGenericJobObject $listGenericJobObject - * @return null|object + * @return void * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException */ public function execute(ListGenericJobObject $listGenericJobObject) { $query = $this->listsTransactions->execute($this->listsTransactions->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page']]); - $result = Helper::collectionResponse(TransactionResource::collection($query)); - - $create = $this->createsJobResult->execute($listGenericJobObject, json_encode($result)); - - return $create; + $resultCurrent = Helper::collectionResponse(ListTransactionJobResource::collection($query)); + $this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent); } } + diff --git a/app/Http/Resources/BookingResource.php b/app/Http/Resources/BookingResource.php index c3c2e24d..70fbc95c 100644 --- a/app/Http/Resources/BookingResource.php +++ b/app/Http/Resources/BookingResource.php @@ -11,19 +11,9 @@ use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\ValueObjects\Constants\DocumentType; use Carbon\Carbon; use Illuminate\Http\Resources\Json\JsonResource; -use Illuminate\Http\Resources\Json\AnonymousResourceCollection; -use Illuminate\Support\Facades\Log; class BookingResource extends JsonResource { - private $userInfo; - - public function __construct($resource, $userInfo = null) - { - parent::__construct($resource); - $this->userInfo = $userInfo ?? ($resource->userInfo ?? null); - } - /** * Transform the resource into an array. * @@ -35,7 +25,7 @@ class BookingResource extends JsonResource { return [ 'id' => $this->id, - 'company' => new CompanyResource($this->company, $this->userInfo), + 'company' => new CompanyResource($this->company), 'bank' => new BankResource($this->bank), 'service' => new ServiceTypeResource($this->service), 'marking' => $this->marking, diff --git a/app/Http/Resources/CompanyResource.php b/app/Http/Resources/CompanyResource.php index df3bcf49..eff2bd1b 100644 --- a/app/Http/Resources/CompanyResource.php +++ b/app/Http/Resources/CompanyResource.php @@ -15,18 +15,9 @@ use App\Models\SegmentConstant; use Carbon\Carbon; use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Support\Facades\Auth; -use Illuminate\Support\Facades\Log; class CompanyResource extends JsonResource { - private $userInfo; - - public function __construct($resource, $userInfo = null) - { - parent::__construct($resource); - $this->userInfo = $userInfo; - } - /** * Transform the resource into an array. * @@ -41,26 +32,6 @@ class CompanyResource extends JsonResource $segment = SegmentConstant::where('reference', SegmentConstants::SUPPLIER_CURRENCIES)->where('detail->id', $this->id)->first(); $serviceCharge = SegmentConstant::where('reference', SegmentConstants::SERVICE_CHARGE)->where('detail->id', $this->id)->first(); - $userResource = null; - - $userInfoEmail = $this->userInfo && isset($this->userInfo->email) ? $this->userInfo->email : null; - $userInfoType = $this->userInfo && isset($this->userInfo->type) ? $this->userInfo->type : null; - - if(!$userInfoEmail && Auth::user()){ - $userInfoEmail = Auth::user()->email; - } - if(!$userInfoType && Auth::user()){ - $userInfoType = Auth::user()->type; - } - - //cief todo: remove - // Log::error('CompanyResource 1: '. json_encode($userInfoEmail)); - // Log::error('CompanyResource 2: '. json_encode($userInfoType)); - - if(!is_null($userInfoEmail) && !is_null($userInfoType)){ - $userResource = new UserResource($userInfoType === RoleTypes::USER ? $this->employees()->where('email', '=', $userInfoEmail)->first() : $this->employees()->orderBy('id', 'DESC')->first()); - } - return [ 'id' => $this->id, 'name' => $this->name, @@ -71,8 +42,7 @@ class CompanyResource extends JsonResource 'status' => (int) $this->status, 'contact' => new ContactResource ($this->when($this->has('contacts'), $this->contacts->first())), 'address' => new AddressResource($this->when($this->has('addresses'), $this->addresses->where('billing', true)->first())), - //cief todo: this one need to decide what to do to replace Auth:user() when it is run by job queue - 'employee' => $userResource, + 'employee' => new UserResource(Auth::user()->type === RoleTypes::USER ? $this->employees()->where('email', '=', Auth::user()->email)->first() : $this->employees()->orderBy('id', 'DESC')->first()), 'identification' => new DocumentResource($this->documents->whereIn('document_type', DocumentType::IDENTIFICATION_DOCUMENTS)->first()), 'bookings' => $this->whenLoaded('bookings', $this->bookings()->orderBy('id', 'DESC')->get(), []), 'confirmed_bookings' => $this->bookings()->whereHas('transactions', function ($query){ diff --git a/app/Http/Resources/DocumentResource.php b/app/Http/Resources/DocumentResource.php index 6f9ade71..c0f801bb 100644 --- a/app/Http/Resources/DocumentResource.php +++ b/app/Http/Resources/DocumentResource.php @@ -3,14 +3,8 @@ namespace App\Http\Resources; use App\Models\Booking; -use App\Models\Company; -use App\Models\Document; use Carbon\Carbon; -use Illuminate\Database\Eloquent\Model; use Illuminate\Http\Resources\Json\JsonResource; -use Illuminate\Support\Facades\Log; -use Illuminate\Support\Facades\Auth; -use Illuminate\Http\Resources\Json\AnonymousResourceCollection; class DocumentResource extends JsonResource { @@ -27,7 +21,7 @@ class DocumentResource extends JsonResource 'reference' => $this->reference, 'status' => (int) $this->status, 'document_type' => $this->document_type, - 'owner' => $this->relationLoaded('owner') ? ($this->owner instanceof Booking ? new BookingResource($this->owner, $this->userInfo) : new CompanyResource($this->owner, $this->userInfo)) : null, + 'owner' => $this->relationLoaded('owner') ? ($this->owner instanceof Booking ? new BookingResource($this->owner) : new CompanyResource($this->owner)) : null, 'files' => FileResource::collection($this->files), 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A') ]; diff --git a/app/Http/Resources/ListBookingJobResource.php b/app/Http/Resources/ListBookingJobResource.php new file mode 100644 index 00000000..06f8c38d --- /dev/null +++ b/app/Http/Resources/ListBookingJobResource.php @@ -0,0 +1,81 @@ +userInfo = $userInfo ?? ($resource->userInfo ?? null); + } + + /** + * Transform the resource into an array. + * + * @param \Illuminate\Http\Request $request + * @return array + * @throws \Illuminate\Contracts\Container\BindingResolutionException + */ + public function toArray($request) + { + return [ + 'id' => $this->id, + 'company' => new CompanyResource($this->company, $this->userInfo), + 'bank' => new BankResource($this->bank), + 'service' => new ServiceTypeResource($this->service), + 'marking' => $this->marking, + 'amount' => $this->fix_amount, + 'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'fixed_currency' => new CurrencyResource($this->fixedCurrency), + 'convertible_currency' => new CurrencyResource($this->convertibleCurrency), + 'conversion_currency' => new CurrencyResource($this->conversionCurrency), + 'documents' => [ + 'purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::PURCHASE_ORDER)->first()), + 'delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER)->first()), + 'invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::INVOICE)->first()), + 'supplier_delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->first()), + 'proforma_invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()), + 'ecommerce_purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->first()), + ], + 'status' => $this->status, + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'), + 'created_at_with_time' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), + $this->mergeWhen($this->relationLoaded('transactions'), [ + 'purchase_order' => new TransactionResource($this->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first()), + 'payment_attempts' => TransactionResource::collection( + $this->transactions() + ->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION) + ->whereDate('expires_on', '>=', Carbon::now()) + ->get() + ), + 'expired_payment_attempts' => TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString())->get()), + 'payment_history' => TransactionResource::collection($this->transactions()->where(function($query){ + $query->where(function($query){ + $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]); + })->orWhere(function($query){ + $query->where(function($query){ + $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]); + })->orWhere(function($query){ + $query->where('type', TransactionType::CREDIT_NOTE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); + }); + })->latest()->get()) + ]) + ]; + } +} diff --git a/app/Http/Resources/ListDocumentJobResource.php b/app/Http/Resources/ListDocumentJobResource.php new file mode 100644 index 00000000..edf549ef --- /dev/null +++ b/app/Http/Resources/ListDocumentJobResource.php @@ -0,0 +1,31 @@ + $this->id, + 'reference' => $this->reference, + 'status' => (int) $this->status, + 'document_type' => $this->document_type, + 'owner' => $this->relationLoaded('owner') ? ($this->owner instanceof Booking ? new BookingV2Resource($this->owner, $this->userInfo) : new CompanyV2Resource($this->owner, $this->userInfo)) : null, + 'files' => FileResource::collection($this->files), + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A') + ]; + } +} diff --git a/app/Http/Resources/ListTransactionJobResource.php b/app/Http/Resources/ListTransactionJobResource.php new file mode 100644 index 00000000..6c4c0ece --- /dev/null +++ b/app/Http/Resources/ListTransactionJobResource.php @@ -0,0 +1,54 @@ +type, [TransactionType::BILL, TransactionType::REFUND])? $this->owner->owner : $this->owner; + $days = $this->created_at->endOfDay()->addWeekdays($booking->service_id === 3 ? 3 : 1); + + return [ + 'id' => $this->id, + 'booking' => new BookingResource($booking), + 'type' => (int) $this->type, + 'bill_no' => $this->bill_no, + 'payment_reference' => $this->payment_reference, + 'payment_method' => (float) $this->payment_method, + 'recipient_bank_account' => new BankResource($booking->bank), + 'issuer_name' => $this->issuerCompany->name, + 'issuer_id' => $this->issuerCompany->id, + 'amount' => (double) $this->amount, + 'original_amount' => (double) $this->original_amount, + 'currency' => new CurrencyResource($this->currency), + 'original_currency' => new CurrencyResource($this->original_currency), + 'service_charge' => (double) $this->service_charge, + 'tax' => (double) $this->tax, + 'currency_rate' => (double) $this->currency_rate, + 'status' => (int) $this->status, + 'details' => TransactionDetailResource::collection($this->transactionDetails), + 'documents' => new DocumentResource($this->documents()->first()), + 'transaction_bill' => new TransactionResource($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->bills()->first())), + 'transaction_refunds' => TransactionResource::collection($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->refunds()->get())), + 'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'), + 'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'), + 'interval' => [ + 'value' => $days->gt(Carbon::now()) ? '+' : '-', + 'duration' => $days->diff(Carbon::now())->format('%d'), + ], + 'redemption' => new VoucherRedemptionResource($this->voucherRedemption) + ]; + } +} diff --git a/app/Http/Resources/V2/BookingV2Resource.php b/app/Http/Resources/V2/BookingV2Resource.php new file mode 100644 index 00000000..ee17181e --- /dev/null +++ b/app/Http/Resources/V2/BookingV2Resource.php @@ -0,0 +1,82 @@ +userInfo = $userInfo ?? ($resource->userInfo ?? null); + } + + /** + * Transform the resource into an array. + * + * @param \Illuminate\Http\Request $request + * @return array + * @throws \Illuminate\Contracts\Container\BindingResolutionException + */ + public function toArray($request) + { + return [ + 'id' => $this->id, + 'company' => new CompanyV2Resource($this->company, $this->userInfo), + 'bank' => new V1\BankResource($this->bank), + 'service' => new V1\ServiceTypeResource($this->service), + 'marking' => $this->marking, + 'amount' => $this->fix_amount, + 'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'fixed_currency' => new V1\CurrencyResource($this->fixedCurrency), + 'convertible_currency' => new V1\CurrencyResource($this->convertibleCurrency), + 'conversion_currency' => new V1\CurrencyResource($this->conversionCurrency), + 'documents' => [ + 'purchase_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::PURCHASE_ORDER)->first()), + 'delivery_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER)->first()), + 'invoice' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::INVOICE)->first()), + 'supplier_delivery_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->first()), + 'proforma_invoice' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()), + 'ecommerce_purchase_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->first()), + ], + 'status' => $this->status, + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'), + 'created_at_with_time' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), + $this->mergeWhen($this->relationLoaded('transactions'), [ + 'purchase_order' => new V1\TransactionResource($this->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first()), + 'payment_attempts' => V1\TransactionResource::collection( + $this->transactions() + ->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION) + ->whereDate('expires_on', '>=', Carbon::now()) + ->get() + ), + 'expired_payment_attempts' => V1\TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString())->get()), + 'payment_history' => V1\TransactionResource::collection($this->transactions()->where(function($query){ + $query->where(function($query){ + $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]); + })->orWhere(function($query){ + $query->where(function($query){ + $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]); + })->orWhere(function($query){ + $query->where('type', TransactionType::CREDIT_NOTE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); + }); + })->latest()->get()) + ]) + ]; + } +} diff --git a/app/Http/Resources/V2/CompanyV2Resource.php b/app/Http/Resources/V2/CompanyV2Resource.php new file mode 100644 index 00000000..64fca7c7 --- /dev/null +++ b/app/Http/Resources/V2/CompanyV2Resource.php @@ -0,0 +1,100 @@ +userInfo = $userInfo; + } + + /** + * Transform the resource into an array. + * + * @param \Illuminate\Http\Request $request + * @return array + */ + public function toArray($request) + { + $lastPayment = $this->transactions()->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->orderBy('id', 'DESC')->first(); + $totalPayments = $this->transactions()->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount'); + + $segment = SegmentConstant::where('reference', SegmentConstants::SUPPLIER_CURRENCIES)->where('detail->id', $this->id)->first(); + $serviceCharge = SegmentConstant::where('reference', SegmentConstants::SERVICE_CHARGE)->where('detail->id', $this->id)->first(); + + $userResource = null; + + $userInfoEmail = $this->userInfo && isset($this->userInfo->email) ? $this->userInfo->email : null; + $userInfoType = $this->userInfo && isset($this->userInfo->type) ? $this->userInfo->type : null; + + if(!$userInfoEmail && Auth::user()){ + $userInfoEmail = Auth::user()->email; + } + if(!$userInfoType && Auth::user()){ + $userInfoType = Auth::user()->type; + } + + if(!is_null($userInfoEmail) && !is_null($userInfoType)){ + $userResource = new V1\UserResource($userInfoType === RoleTypes::USER ? $this->employees()->where('email', '=', $userInfoEmail)->first() : $this->employees()->orderBy('id', 'DESC')->first()); + } + + return [ + 'id' => $this->id, + 'name' => $this->name, + 'reference' => $this->reference, + 'debtor' => $this->debtor, + 'type' => (int) $this->type, + 'business_type' => (int) $this->business_type, + 'status' => (int) $this->status, + 'contact' => new V1\ContactResource ($this->when($this->has('contacts'), $this->contacts->first())), + 'address' => new V1\AddressResource($this->when($this->has('addresses'), $this->addresses->where('billing', true)->first())), + 'employee' => $userResource, + 'identification' => new V1\DocumentResource($this->documents->whereIn('document_type', DocumentType::IDENTIFICATION_DOCUMENTS)->first()), + 'bookings' => $this->whenLoaded('bookings', $this->bookings()->orderBy('id', 'DESC')->get(), []), + 'confirmed_bookings' => $this->bookings()->whereHas('transactions', function ($query){ + $query->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + })->count(), + 'total_payments' => (float) $totalPayments, + 'average_spending_per_day' => (float) $totalPayments / ($this->created_at->diff(Carbon::now())->days === 0 ? 1 : $this->created_at->diff(Carbon::now())->days), + 'average_spending_per_booking' => (float) $totalPayments > 0 ? $totalPayments / $this->bookings()->whereHas('transactions', function ($query){ + $query->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + })->count() : $totalPayments, + 'last_payment' => $lastPayment ? $lastPayment->created_at->diffForHumans() : 'No Payments', + 'personal_banks' => V1\BankResource::collection($this->banks->where('type', BankAccountType::PERSONAL)), + 'recipient_banks' => [ + 'accounts' => V1\BankResource::collection($this->banks->where('type', BankAccountType::EXTERNAL)), + 'default' => new V1\BankResource($this->banks->where('type', BankAccountType::EXTERNAL)->where('default', true)->first()) + ], + 'segments' => V1\SegmentResource::collection($this->segments), + 'seasonalSegment' => $this->whenLoaded('seasonalSegments', V1\SeasonalSegmentResource::collection($this->seasonalSegments)), + 'services' => (new FetchesCompanyServices())->getServices($this->servicesConfigurations()), + 'wallet' => $this->whenLoaded('wallets', new V1\WalletResource($this->wallets()->with('transactions')->first()), new V1\WalletResource($this->wallets()->first())), + 'created_at' => $this->created_at->format('d-m-Y'), + $this->mergeWhen($this->business_type === BusinessType::CURRENCY_VENDOR, [ + 'currencies' => $segment ? V1\CurrencyResource::collection(Currency::whereIn('id', $segment->detail->currencies)->get()) : [], + 'service_charge' => $serviceCharge + ]) + + ]; + } +} diff --git a/resources/assets/vue/vuex/modules/crudRequestV2.js b/resources/assets/vue/vuex/modules/crudRequestV2.js index 2445190e..355b1edb 100644 --- a/resources/assets/vue/vuex/modules/crudRequestV2.js +++ b/resources/assets/vue/vuex/modules/crudRequestV2.js @@ -1,35 +1,39 @@ export default { actions: { crudRequestV2({getters, dispatch}, {endpoint, method, parameters}){ - const queryDomain = endpoint.split('?')[0]; - let encodedParams = endpoint.split('?')[1]; - let decodedParams = fullyDecodeURI(encodedParams); - const queryParams = encodeURIComponent(decodedParams); - encodedParams = queryParams.toString(); - let filteredEncodedParams = encodedParams.replace(/%3D/g,'='); - filteredEncodedParams = filteredEncodedParams.replace(/%26/g,'&'); - let combinedAbsoluteUrl = queryDomain; - if(filteredEncodedParams !== undefined && filteredEncodedParams !== 'undefined'){ - combinedAbsoluteUrl = queryDomain + '?' + filteredEncodedParams; - } - - // return fetch(endpoint, { - return fetch(combinedAbsoluteUrl, { - method: method, - responseType: 'json', - body: parameters ? JSON.stringify(parameters):null, - headers: { - 'content-type': 'application/json', - 'Authorization': 'Bearer '+getters.getAccessToken - } - }).then(response => { - if(response.status === 401 && window.location.href !== route('login') && window.location.href.indexOf(route('last_mile_delivery.login')) <= -1){ - dispatch('userAuthentication', {access_token: '', redirect_url: [7, 8].includes(getters.getCompanyModuleType) ? route('last_mile_delivery.login') : route('login')}); + return dispatch('ensureReCaptchaIsSet').then(function () { + const queryDomain = endpoint.split('?')[0]; + let encodedParams = endpoint.split('?')[1]; + let decodedParams = fullyDecodeURI(encodedParams); + const queryParams = encodeURIComponent(decodedParams); + encodedParams = queryParams.toString(); + let filteredEncodedParams = encodedParams.replace(/%3D/g,'='); + filteredEncodedParams = filteredEncodedParams.replace(/%26/g,'&'); + let combinedAbsoluteUrl = queryDomain; + if(filteredEncodedParams !== undefined && filteredEncodedParams !== 'undefined'){ + combinedAbsoluteUrl = queryDomain + '?' + filteredEncodedParams; } - return response; + // return fetch(endpoint, { + return fetch(combinedAbsoluteUrl, { + method: method, + responseType: 'json', + body: parameters ? JSON.stringify(parameters):null, + headers: { + 'content-type': 'application/json', + 'Authorization': 'Bearer '+getters.getAccessToken, + 'captcha-token': getters.getReCaptcha + } + }).then(response => { - }) + if(response.status === 401 && window.location.href !== route('login')){ + dispatch('userAuthentication', {access_token: '', redirect_url: '/'}); + } + + return response; + + }) + }); } } } From 72a945613affdee69e012a863ecf5f798043c30c Mon Sep 17 00:00:00 2001 From: edmondlang Date: Tue, 2 Jan 2024 19:32:02 +0800 Subject: [PATCH 026/228] fix po --- .../pages/pdfs/purchase_order_table.blade.php | 3 ++- routes/web.php | 20 +++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/resources/views/pages/pdfs/purchase_order_table.blade.php b/resources/views/pages/pdfs/purchase_order_table.blade.php index 20fac9b8..69083e93 100644 --- a/resources/views/pages/pdfs/purchase_order_table.blade.php +++ b/resources/views/pages/pdfs/purchase_order_table.blade.php @@ -15,11 +15,12 @@ $subtotal = "0"; $voucherDiscount = $voucher_redemption ? bcmul((string)$voucher_redemption->value, "-1", 2) : "0"; $displayedSubtotal = 0; + $currency_id = $transaction->currency_id @endphp @foreach ($po_order_transaction->transactionDetails as $key => $transaction_detail) @php - $exactUnitPrice = bcdiv($transaction_detail->price, $transaction->currency_rate, 7); + $exactUnitPrice = ($currency_id) === 1 : $transaction_detail->price : bcdiv($transaction_detail->price, $transaction->currency_rate, 7); $displayUnitPrice = round($exactUnitPrice, 2); $itemTotal = bcmul($exactUnitPrice, $transaction_detail->quantity, 5); $displayedItemTotal = round(bcmul($displayUnitPrice, $transaction_detail->quantity, 7), 2); diff --git a/routes/web.php b/routes/web.php index 674f8f0e..bf2892bb 100644 --- a/routes/web.php +++ b/routes/web.php @@ -112,7 +112,7 @@ Route::get('/transfer/{marking}', function ($marking) { return view('pages.bookings.profile', ['marking' => $marking]); })->name('booking.details'); -Route::get('/transfer/{marking}/latest-invoice', function ($marking) { +Route::get('/transfer/{marking}/latest/{document_type}', function ($marking, $document_type) { $booking= Booking::where('marking', $marking)->first(); $purchaseOrder = $booking->transactions() @@ -126,7 +126,23 @@ Route::get('/transfer/{marking}/latest-invoice', function ($marking) { $supplier = Company::where('id', $transaction->receiver)->first(); - $lowercaseDocumentType = strtolower(DocumentType::INVOICE); + $lowercaseDocumentType = null; + switch ($document_type) { + case 'po': + $lowercaseDocumentType = DocumentType::PURCHASE_ORDER; + break; + case 'do': + $lowercaseDocumentType = DocumentType::DELIVER_ORDER; + break; + case 'sdo': + $lowercaseDocumentType = DocumentType::SUPPLIER_DELIVER_ORDER; + break; + default: + $lowercaseDocumentType = DocumentType::INVOICE; + break; + } + + $lowercaseDocumentType = strtolower($lowercaseDocumentType); $voucherRedemption = $transaction->voucherRedemption; From 6cac8e6e094470618aea80f93308a7f0b3520554 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Tue, 2 Jan 2024 19:36:47 +0800 Subject: [PATCH 027/228] code update --- resources/views/pages/pdfs/purchase_order_table.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/pages/pdfs/purchase_order_table.blade.php b/resources/views/pages/pdfs/purchase_order_table.blade.php index 69083e93..c570280d 100644 --- a/resources/views/pages/pdfs/purchase_order_table.blade.php +++ b/resources/views/pages/pdfs/purchase_order_table.blade.php @@ -15,7 +15,7 @@ $subtotal = "0"; $voucherDiscount = $voucher_redemption ? bcmul((string)$voucher_redemption->value, "-1", 2) : "0"; $displayedSubtotal = 0; - $currency_id = $transaction->currency_id + $currency_id = $transaction->currency_id; @endphp @foreach ($po_order_transaction->transactionDetails as $key => $transaction_detail) From c599ae5887a98b4724c1081b471515f396369536 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Tue, 2 Jan 2024 19:40:38 +0800 Subject: [PATCH 028/228] code update --- resources/views/pages/pdfs/purchase_order_table.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/pages/pdfs/purchase_order_table.blade.php b/resources/views/pages/pdfs/purchase_order_table.blade.php index c570280d..99b28dd7 100644 --- a/resources/views/pages/pdfs/purchase_order_table.blade.php +++ b/resources/views/pages/pdfs/purchase_order_table.blade.php @@ -20,7 +20,7 @@ @foreach ($po_order_transaction->transactionDetails as $key => $transaction_detail) @php - $exactUnitPrice = ($currency_id) === 1 : $transaction_detail->price : bcdiv($transaction_detail->price, $transaction->currency_rate, 7); + $exactUnitPrice = ($currency_id) === 1 ? $transaction_detail->price : bcdiv($transaction_detail->price, $transaction->currency_rate, 7); $displayUnitPrice = round($exactUnitPrice, 2); $itemTotal = bcmul($exactUnitPrice, $transaction_detail->quantity, 5); $displayedItemTotal = round(bcmul($displayUnitPrice, $transaction_detail->quantity, 7), 2); From 74c6ca7330bd62ad385c9db3397e6c5745479120 Mon Sep 17 00:00:00 2001 From: Steve Ng Date: Wed, 3 Jan 2024 09:08:54 +0800 Subject: [PATCH 029/228] change posting date to invoice date for shipping portal when export invoice to autocount --- .../General/Services/GuzzleShippingPortal.php | 22 +++++++++++++++++++ .../Services/ExportsInvoiceTransactions.php | 11 +++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 app/Classes/General/Services/GuzzleShippingPortal.php diff --git a/app/Classes/General/Services/GuzzleShippingPortal.php b/app/Classes/General/Services/GuzzleShippingPortal.php new file mode 100644 index 00000000..d753b260 --- /dev/null +++ b/app/Classes/General/Services/GuzzleShippingPortal.php @@ -0,0 +1,22 @@ + false]); + $response = $client->request('GET', $url . '?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&'. $requests); + $body = $response->getBody(); + $data = json_decode($body, true); + $payload = $data['payload']; + return $payload['data']; + } catch (\Exception $exception) { + Log::error($exception->getMessage()); + return []; + } + } +} diff --git a/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php b/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php index a7041b1c..ee07f435 100644 --- a/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php +++ b/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php @@ -19,6 +19,7 @@ use App\Classes\ValueObjects\Constants\TransactionType; use Illuminate\Support\Facades\Log; use App\Classes\General\Eloquent\ApplyFiltersToQuery; use App\Models\StatementTransaction; +use App\Classes\General\Services\GuzzleShippingPortal; class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize { @@ -124,12 +125,11 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading $textToAppend = Carbon::now()->format('[Y-m-d H:i:s]') . ' Shipping Portal Respnose ' . json_encode($row) . PHP_EOL; file_put_contents($errorFilePath, $textToAppend, FILE_APPEND); - - Log::info('Error in Exports Invoice Transactions ' . $this->counter); + $transactionShippingPortal = $this->getFromShippingPortal($statementTransactionOwner->owner_id); return [ 'Transaction Not Found', - $transaction->posting_date->format('m/d/Y H:m'), + (isset($transactionShippingPortal['created_at']) ? Carbon::parse($transactionShippingPortal['created_at'])->format('m/d/Y H:m') : null), $transaction->transaction_description.' - '.$transaction->transaction_description_2, $statementTransactionOwner->system, '', @@ -167,4 +167,9 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading ]; } } + + private function getFromShippingPortal($id){ + $data = (new guzzleShippingPortal)->execute('transactions/mappable/query','filters={"id":'.$id.'}'); + return (count($data) > 0 ? $data[0] : null); + } } From b2dd059fa4e80b9f8f5dae681e6f1089a926b933 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 3 Jan 2024 10:12:06 +0800 Subject: [PATCH 030/228] update logging for GuzzleShippingPortal --- app/Classes/General/Services/GuzzleShippingPortal.php | 3 +++ config/logging.php | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/app/Classes/General/Services/GuzzleShippingPortal.php b/app/Classes/General/Services/GuzzleShippingPortal.php index d753b260..2fed1e9a 100644 --- a/app/Classes/General/Services/GuzzleShippingPortal.php +++ b/app/Classes/General/Services/GuzzleShippingPortal.php @@ -2,6 +2,8 @@ namespace App\Classes\General\Services; +use Illuminate\Support\Facades\Log; + class GuzzleShippingPortal { public function execute($route, $requests) @@ -16,6 +18,7 @@ class GuzzleShippingPortal return $payload['data']; } catch (\Exception $exception) { Log::error($exception->getMessage()); + Log::channel('guzzleShippingPortal')->debug($exception->getMessage()); return []; } } diff --git a/config/logging.php b/config/logging.php index fb872693..d0d0a009 100644 --- a/config/logging.php +++ b/config/logging.php @@ -104,6 +104,10 @@ return [ 'path' => storage_path('logs/regenerateInvoice.log'), 'level' => 'info', ], + 'guzzleShippingPortal' => [ + 'driver' => 'errorlog', + 'level' => 'debug', + ], ], ]; From 24d246d7216f627a6d05f807d6d4afeb2f822cbc Mon Sep 17 00:00:00 2001 From: Steve Ng Date: Fri, 5 Jan 2024 12:06:08 +0800 Subject: [PATCH 031/228] fix the invoice date for IZYIM when export invoice to autocount and have reject function in mapping review --- .../General/Services/GuzzleShippingPortal.php | 25 ------- .../UpdateStatementTransactionStatusLogic.php | 49 ++++-------- .../ListShippingPortalTransactions.php | 1 + .../FetchesBankStatementTransactionOwner.php | 31 ++++++++ .../Services/ExportsInvoiceTransactions.php | 75 +++++++++---------- .../StatementTransactionComponent.vue | 19 ++++- 6 files changed, 98 insertions(+), 102 deletions(-) delete mode 100644 app/Classes/General/Services/GuzzleShippingPortal.php create mode 100644 app/Classes/Modules/Accounting/Services/FetchesBankStatementTransactionOwner.php diff --git a/app/Classes/General/Services/GuzzleShippingPortal.php b/app/Classes/General/Services/GuzzleShippingPortal.php deleted file mode 100644 index 2fed1e9a..00000000 --- a/app/Classes/General/Services/GuzzleShippingPortal.php +++ /dev/null @@ -1,25 +0,0 @@ - false]); - $response = $client->request('GET', $url . '?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&'. $requests); - $body = $response->getBody(); - $data = json_decode($body, true); - $payload = $data['payload']; - return $payload['data']; - } catch (\Exception $exception) { - Log::error($exception->getMessage()); - Log::channel('guzzleShippingPortal')->debug($exception->getMessage()); - return []; - } - } -} diff --git a/app/Classes/Modules/Accounting/ControllersLogic/UpdateStatementTransactionStatusLogic.php b/app/Classes/Modules/Accounting/ControllersLogic/UpdateStatementTransactionStatusLogic.php index 3a006e9e..b208c2e3 100644 --- a/app/Classes/Modules/Accounting/ControllersLogic/UpdateStatementTransactionStatusLogic.php +++ b/app/Classes/Modules/Accounting/ControllersLogic/UpdateStatementTransactionStatusLogic.php @@ -2,16 +2,14 @@ namespace App\Classes\Modules\Accounting\ControllersLogic; -use App\Classes\General\Abstracts\AbstractControllerLogic; -use App\Classes\Modules\Accounting\Services\FetchesBankStatementTransaction; -use App\Http\Resources\BankStatementTransactionResource; -use App\Classes\Modules\Accounting\Services\UpdatesBankStatementTransactionOwnerStatus; -use App\Classes\ValueObjects\Constants\ApprovalStatus; -use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType; -use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; - +use Illuminate\Http\JsonResponse; +use App\Classes\ValueObjects\Constants\ApprovalStatus; +use App\Classes\General\Abstracts\AbstractControllerLogic; +use App\Http\Resources\BankStatementTransactionOwnerResource; +use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType; +use App\Classes\Modules\Accounting\Services\FetchesBankStatementTransactionOwner; +use App\Classes\Modules\Accounting\Services\UpdatesBankStatementTransactionOwnerStatus; class UpdateStatementTransactionStatusLogic extends AbstractControllerLogic { @@ -27,29 +25,23 @@ class UpdateStatementTransactionStatusLogic extends AbstractControllerLogic ]; } - /** @var FetchesBankStatementTransaction */ - private $fetchesBankStatementTransaction; + /** @var FetchesBankStatementTransactionOwner */ + private $fetchesBankStatementTransactionOwner; /** @var UpdatesBankStatementTransactionOwnerStatus */ private $updatesBankStatementTransactionOwnerStatus; - /** @var UpdatesTransactionStatus */ - private $updatesTransactionStatus; - /** * UpdateAnnouncementLogic constructor. - * @param FetchesBankStatementTransaction $fetchesBankStatementTransaction + * @param FetchesBankStatementTransactionOwner $fetchesBankStatementTransactionOwner * @param UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus - * @param UpdatesTransactionStatus $updatesTransactionStatus */ public function __construct( - FetchesBankStatementTransaction $fetchesBankStatementTransaction, - UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus, - UpdatesTransactionStatus $updatesTransactionStatus + FetchesBankStatementTransactionOwner $fetchesBankStatementTransactionOwner, + UpdatesBankStatementTransactionOwnerStatus $updatesBankStatementTransactionOwnerStatus ) { - $this->fetchesBankStatementTransaction = $fetchesBankStatementTransaction; + $this->fetchesBankStatementTransactionOwner = $fetchesBankStatementTransactionOwner; $this->updatesBankStatementTransactionOwnerStatus = $updatesBankStatementTransactionOwnerStatus; - $this->updatesTransactionStatus = $updatesTransactionStatus; } /** @@ -61,21 +53,10 @@ class UpdateStatementTransactionStatusLogic extends AbstractControllerLogic */ public function logic(Request $request): JsonResponse { - $statementTrasaction = $this->fetchesBankStatementTransaction->execute(['id' => $request->route('id')]); - - $statementTrasactionOwner = $statementTrasaction->owners->first(); + $statementTrasactionOwner = $this->fetchesBankStatementTransactionOwner->execute(['id' => $request->route('id')]); $this->updatesBankStatementTransactionOwnerStatus->execute($statementTrasactionOwner, $request->route('status') == 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED); - // todo-new: approve payments status, need to check the owner(if system is shipping, need to api with shipping portal) - // if ($request->route('status') == 'approve') { - // if ($statementTrasactionOwner->transaction->type === StatementTransactionOwnerType::SALES) { - // if ($statementTrasactionOwner->owner->status === ApprovalStatus::PENDING_VERIFICATION) { - // $this->updatesTransactionStatus->execute($statementTrasactionOwner->owner, ApprovalStatus::APPROVED); - // } - // } - // } - - return $this->resourceResponse(new BankStatementTransactionResource($statementTrasaction)); + return $this->resourceResponse(new BankStatementTransactionOwnerResource($statementTrasactionOwner)); } } diff --git a/app/Classes/Modules/Accounting/Processors/ListShippingPortalTransactions.php b/app/Classes/Modules/Accounting/Processors/ListShippingPortalTransactions.php index f80c3c0e..18ec9c36 100644 --- a/app/Classes/Modules/Accounting/Processors/ListShippingPortalTransactions.php +++ b/app/Classes/Modules/Accounting/Processors/ListShippingPortalTransactions.php @@ -13,6 +13,7 @@ class ListShippingPortalTransactions { try { $url = 'https://izyim.cief-malaysia.com/public/api/v1/transactions/mappable/query/with-details'; + // $url = 'http://127.0.0.1:8001/public/api/v1/transactions/mappable/query/with-details'; $client = new \GuzzleHttp\Client(['verify' => false]); $response = $client->request('GET', $url . '?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&filters=' . json_encode($filters)); $body = $response->getBody(); diff --git a/app/Classes/Modules/Accounting/Services/FetchesBankStatementTransactionOwner.php b/app/Classes/Modules/Accounting/Services/FetchesBankStatementTransactionOwner.php new file mode 100644 index 00000000..17c620f5 --- /dev/null +++ b/app/Classes/Modules/Accounting/Services/FetchesBankStatementTransactionOwner.php @@ -0,0 +1,31 @@ +repository = $repository; + } + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php b/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php index ee07f435..62a2c13e 100644 --- a/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php +++ b/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php @@ -19,7 +19,6 @@ use App\Classes\ValueObjects\Constants\TransactionType; use Illuminate\Support\Facades\Log; use App\Classes\General\Eloquent\ApplyFiltersToQuery; use App\Models\StatementTransaction; -use App\Classes\General\Services\GuzzleShippingPortal; class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize { @@ -109,13 +108,13 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading '500-0000', 'CIEF' ]; - } else { + } elseif ($statementTransactionOwner->owner_id) { $row = (App()->make(ListShippingPortalTransactions::class))->execute([ 'id' => $statementTransactionOwner->owner_id, 'with_company' => true, ]); - if (empty($row) || $row[0]['status'] != 'success') { + if (!empty($row) && $row[0]['status'] != 'success') { $textToAppend = Carbon::now()->format('[Y-m-d H:i:s]') . ' Fetch Shipping Transaction Fail ' . json_encode([ 'id' => $statementTransactionOwner->owner_id, 'with_company' => true, @@ -125,51 +124,45 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading $textToAppend = Carbon::now()->format('[Y-m-d H:i:s]') . ' Shipping Portal Respnose ' . json_encode($row) . PHP_EOL; file_put_contents($errorFilePath, $textToAppend, FILE_APPEND); - $transactionShippingPortal = $this->getFromShippingPortal($statementTransactionOwner->owner_id); return [ - 'Transaction Not Found', - (isset($transactionShippingPortal['created_at']) ? Carbon::parse($transactionShippingPortal['created_at'])->format('m/d/Y H:m') : null), - $transaction->transaction_description.' - '.$transaction->transaction_description_2, - $statementTransactionOwner->system, + '<>', + Carbon::parse($row['created_at'])->format('m/d/Y H:m'), + $row['debtor_code'], + $row['type'] === ShippingTransactionType::PAYMENT ? $row['order_reference'] : $row['marking'], '', + 'MYR', + $row['type'] === ShippingTransactionType::PAYMENT ? $row['order_reference'] : $row['bill_no'], + $row['type'] === ShippingTransactionType::PAYMENT ? '' : 'W1', + $row['type'] === ShippingTransactionType::PAYMENT ? 'PLEASE REFER TO THE ATTACHED APPENDIX REF `' . $row['order_reference'] : 'CREDIT SALES', '', - '', - '', - '', - '', - 0, - $transaction->amount, - '', - '', - '', - '' + 1, + round($row['amount'], 2), + '500-0000', + 'CIEF' ]; + } - - $row = $row[0]; - - return [ - '<>', - Carbon::parse($row['updated_at'])->format('m/d/Y H:m'), - $row['debtor_code'], - $row['type'] === ShippingTransactionType::PAYMENT ? $row['order_reference'] : $row['marking'], - '', - 'MYR', - $row['type'] === ShippingTransactionType::PAYMENT ? $row['order_reference'] : $row['bill_no'], - $row['type'] === ShippingTransactionType::PAYMENT ? '' : 'W1', - $row['type'] === ShippingTransactionType::PAYMENT ? 'PLEASE REFER TO THE ATTACHED APPENDIX REF `' . $row['order_reference'] : 'CREDIT SALES', - '', - 1, - round($row['amount'], 2), - '500-0000', - 'CIEF' - ]; } + + return [ + 'Transaction Not Found', + $transaction->posting_date->format('m/d/Y H:m'), + $transaction->transaction_description.' - '.$transaction->transaction_description_2, + $statementTransactionOwner->system, + '', + '', + '', + '', + '', + '', + 0, + $transaction->amount, + '', + '', + '', + '' + ]; } - private function getFromShippingPortal($id){ - $data = (new guzzleShippingPortal)->execute('transactions/mappable/query','filters={"id":'.$id.'}'); - return (count($data) > 0 ? $data[0] : null); - } } diff --git a/resources/assets/vue/components/accounting/elements/StatementTransactionComponent.vue b/resources/assets/vue/components/accounting/elements/StatementTransactionComponent.vue index 0c193871..787f2f37 100644 --- a/resources/assets/vue/components/accounting/elements/StatementTransactionComponent.vue +++ b/resources/assets/vue/components/accounting/elements/StatementTransactionComponent.vue @@ -74,7 +74,7 @@
{{ owner.reference }} -
+
@@ -89,6 +89,21 @@ > + + + + + +
@@ -143,7 +158,7 @@ contentText="Are you sure you want to reject this mapping?" modalType="delete" class="text-center" - :apiRoute="route('api.accounting.statement_transaction.owner.status.update', item.id, 'reject')" + :apiRoute="route('api.accounting.statement_transaction.owner.status.update', item.owners.pending_verification[0].id, 'reject')" apiMethod="post" :section="section" > From 435927ba1919d367d41e6494ec6b651ceaea6f9b Mon Sep 17 00:00:00 2001 From: edmondlang Date: Mon, 8 Jan 2024 18:07:04 +0800 Subject: [PATCH 032/228] update code fix po --- resources/views/pages/pdfs/purchase_order_table.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/pages/pdfs/purchase_order_table.blade.php b/resources/views/pages/pdfs/purchase_order_table.blade.php index 99b28dd7..cc47100e 100644 --- a/resources/views/pages/pdfs/purchase_order_table.blade.php +++ b/resources/views/pages/pdfs/purchase_order_table.blade.php @@ -15,7 +15,7 @@ $subtotal = "0"; $voucherDiscount = $voucher_redemption ? bcmul((string)$voucher_redemption->value, "-1", 2) : "0"; $displayedSubtotal = 0; - $currency_id = $transaction->currency_id; + $currency_id = $transaction->owner->fix_currency_id; @endphp @foreach ($po_order_transaction->transactionDetails as $key => $transaction_detail) From 8a05620edf98b8508cf3e4786d44099ebac7e252 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Mon, 8 Jan 2024 22:41:59 +0800 Subject: [PATCH 033/228] update --- .../Bookings/ControllersLogic/CreateBookingRefundLogic.php | 4 ++++ .../components/bookings/elements/PaymentHistoryComponent.vue | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php index 398312c9..b87f4331 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php @@ -81,6 +81,10 @@ 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; $billNumber = $this->generatesTransactionBillNumber->execute('RFD-'); diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index 63cb4687..0512f768 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -272,7 +272,7 @@
-
+
From 1e168729335842085df9516e20ee0f47c5264f72 Mon Sep 17 00:00:00 2001 From: Steve Ng Date: Tue, 9 Jan 2024 09:08:44 +0800 Subject: [PATCH 034/228] fix the invoice date for IZYIM when export invoice to autocount --- .../Modules/Exports/Services/ExportsInvoiceTransactions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php b/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php index 62a2c13e..836efd34 100644 --- a/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php +++ b/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php @@ -114,7 +114,7 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading 'with_company' => true, ]); - if (!empty($row) && $row[0]['status'] != 'success') { + if (!empty($row) && $row[0]['status'] == 'success') { $textToAppend = Carbon::now()->format('[Y-m-d H:i:s]') . ' Fetch Shipping Transaction Fail ' . json_encode([ 'id' => $statementTransactionOwner->owner_id, 'with_company' => true, From aa57a79ab75c4e344ef037b0d7e407c3f3f529a1 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Thu, 11 Jan 2024 11:22:46 +0800 Subject: [PATCH 035/228] fix ExportsInvoiceTransactions - $row is inside an array --- .../Modules/Exports/Services/ExportsInvoiceTransactions.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php b/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php index 836efd34..85df0be8 100644 --- a/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php +++ b/app/Classes/Modules/Exports/Services/ExportsInvoiceTransactions.php @@ -125,6 +125,8 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading $textToAppend = Carbon::now()->format('[Y-m-d H:i:s]') . ' Shipping Portal Respnose ' . json_encode($row) . PHP_EOL; file_put_contents($errorFilePath, $textToAppend, FILE_APPEND); + $row = $row[0]; + return [ '<>', Carbon::parse($row['created_at'])->format('m/d/Y H:m'), From e5a96e179c0f828ea667863557a7375f2f7e2730 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Sat, 13 Jan 2024 13:27:24 +0800 Subject: [PATCH 036/228] add refund transaction under booking payment history, update on admin currency order dashboard to show the correct amount after refunded --- .../CreateSupplierTransactionLogic.php | 25 +++++- .../CreateSupplierTransactionProcessor.php | 10 ++- .../elements/PaymentHistoryComponent.vue | 85 +++++++++++++++++-- .../SupplierPendingOrderComponent.vue | 23 ++++- .../forms/SupplierPlaceOrderFormComponent.vue | 7 +- 5 files changed, 137 insertions(+), 13 deletions(-) diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php index 2dcbd0f7..fb324267 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php @@ -3,6 +3,7 @@ namespace App\Classes\Modules\Transactions\ControllersLogic; +use App\Classes\Exceptions\MalformedRequestException; use App\Classes\Modules\Transactions\Processors\CreateSupplierTransactionProcessor; use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; use App\Models\Document; @@ -18,6 +19,7 @@ use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Companies\Services\FetchesCompany; use App\Classes\Modules\Documents\Services\CreatesDocument; use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject; +use App\Classes\Modules\Transactions\Services\FetchesTransaction; class CreateSupplierTransactionLogic extends AbstractControllerLogic { @@ -48,6 +50,9 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic /** @var GeneratesTransactionBillNumber */ private $generatesTransactionBillNumber; + /** @var FetchesTransaction */ + private $fetchesTransaction; + /** * CreateSupplierTransactionLogic constructor. @@ -56,14 +61,16 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic * @param CreatesDocument $createsDocument * @param CreatesFiles $createsFile * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber + * @param FetchesTransaction $fetchesTransaction */ - public function __construct(FetchesCompany $fetchesCompany, CreateSupplierTransactionProcessor $createSupplierTransactionProcessor, CreatesDocument $createsDocument, CreatesFiles $createsFile, GeneratesTransactionBillNumber $generatesTransactionBillNumber) + public function __construct(FetchesCompany $fetchesCompany, CreateSupplierTransactionProcessor $createSupplierTransactionProcessor, CreatesDocument $createsDocument, CreatesFiles $createsFile, GeneratesTransactionBillNumber $generatesTransactionBillNumber, FetchesTransaction $fetchesTransaction) { $this->fetchesCompany = $fetchesCompany; $this->createSupplierTransactionProcessor = $createSupplierTransactionProcessor; $this->createsDocument = $createsDocument; $this->createsFile = $createsFile; $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->fetchesTransaction = $fetchesTransaction; } public function logic(Request $request) : JsonResponse @@ -75,6 +82,22 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic $payments = $request->input('payments'); + foreach($payments as $payment){ + $payment = $this->fetchesTransaction->execute(['id' => $payment['id']]); + + $pendingRefundRequest = $payment->transactions()->refunds()->where('status', ApprovalStatus::PENDING_VERIFICATION)->first(); + + if ($pendingRefundRequest) { + throw new MalformedRequestException('Unable to create supplier order for pending refund request payment'); + } + + $totalRefund = $payment->transactions()->refunds()->where('status', ApprovalStatus::APPROVED)->sum('original_amount'); + + if ($payment->original_amount - $totalRefund <= 0) { + throw new MalformedRequestException('Unable to create supplier order for fully refunded payment'); + } + } + $this->createSupplierTransactionProcessor->execute($supplier, $rate, $payments); if(!count($this->createSupplierTransactionProcessor->getBills())) return $this->response([]); diff --git a/app/Classes/Modules/Transactions/Processors/CreateSupplierTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateSupplierTransactionProcessor.php index 9b944a5b..b514b404 100644 --- a/app/Classes/Modules/Transactions/Processors/CreateSupplierTransactionProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/CreateSupplierTransactionProcessor.php @@ -81,15 +81,19 @@ class CreateSupplierTransactionProcessor if($payment->status !== ApprovalStatus::APPROVED) continue; + $totalRefund = $payment->transactions()->refunds()->where('status', ApprovalStatus::APPROVED)->sum('original_amount'); + + $original_amount_after_refund = $payment->original_amount - $totalRefund; + $this->updatesTransactionStatus->execute($payment, ApprovalStatus::COMPLETED); $billNumber = $this->generatesTransactionBillNumber->execute('SPLR-'); $constant = SegmentConstant::where('reference', SegmentConstants::SERVICE_CHARGE)->where('detail->id', $supplier->id)->first(); - $serviceCharge = $this->calculatesTransactionServiceCharge->execute($payment->original_amount, $rate, $constant); + $serviceCharge = $this->calculatesTransactionServiceCharge->execute($original_amount_after_refund, $rate, $constant); $object = new TransactionObject($billNumber, TransactionType::BILL, $supplier->id, 1, $supplier->banks()->where('default', true)->first()->id, PaymentMethodType::CASH, - $payment->original_amount * (1 / $rate), $payment->original_amount, 1, $payment->original_currency_id, + $original_amount_after_refund * (1 / $rate), $original_amount_after_refund, 1, $payment->original_currency_id, $rate, 0, $serviceCharge, null, ApprovalStatus::PENDING_SUBMISSION); /** @var Transaction $billTransaction */ @@ -101,7 +105,7 @@ class CreateSupplierTransactionProcessor $transferFee = $this->calculatesTransactionTransferFee->execute($billTransaction->original_amount, $constant); $object = new TransactionObject($transferFeeNumber, TransactionType::TRANSFER_FEE, 1, $supplier->id, $supplier->banks()->where('default', true)->first()->id, PaymentMethodType::CASH, - $payment->original_amount, $payment->original_amount, $payment->original_currency_id, $payment->original_currency_id, + $original_amount_after_refund, $original_amount_after_refund, $payment->original_currency_id, $payment->original_currency_id, 1, 0, $transferFee, null, ApprovalStatus::PENDING_VERIFICATION); $this->pushTransferFee($this->createsTransaction->execute($billTransaction, $object)); diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index 0512f768..2649edcf 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -24,7 +24,7 @@
Refunded Amount
- {{item.original_currency.short_code}} {{(Math.round((totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}} + {{item.currency.short_code}} {{(Math.round((totalConvertRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
@@ -136,6 +136,12 @@
{{item.original_currency.short_code}} {{(Math.round((totalRequestedRefund + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
+
+
+
{{item.currency.short_code}} {{(Math.round((totalRequestedConvertRefund + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
+
Refunded Amount
@@ -144,6 +150,12 @@
{{item.original_currency.short_code}} {{(Math.round((totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
+
+
+
{{item.currency.short_code}} {{(Math.round((totalConvertRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
+
Rate
@@ -187,6 +199,14 @@
MYR {{(Math.round((item.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
+
+
Your Payment After Refund
+
+
+
MYR {{(Math.round((item.amount - totalConvertRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
+
Your Payment Proof
@@ -279,6 +299,47 @@
+
+
+ +
+
+
+
+
+
+
+
+
+
{{ index + 1 }}. Refund updated on
+
+
+
{{ refund.updated_at }}
+
+
+
+
+
    Refund status
+
+
+
{{ refund.status === 1 ? 'Pending Verification' : refund.status === 2 ? 'Approved' : 'Rejected'}}
+
+
+
+
+
    Requested Refund Amount
+
+
+
{{refund.original_currency.short_code}} {{(Math.round((refund.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
+
+
+
+
+
{{refund.currency.short_code}} {{(Math.round((refund.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
+
+
@@ -291,6 +352,7 @@ data(){ return { expandPaymentDetails: false, + expandRefundTransactions: false, amount: (Math.round(1000 * 100) / 100).toFixed(2), parameters: { amount: (Math.round(1000 * 100) / 100).toFixed(2), @@ -313,12 +375,12 @@ let vm = this; var TotalRequestedRefund = 0; this.data.transaction_refunds.forEach(function(refunds) { - TotalRequestedRefund += refunds.status === 1 ? refunds.original_amount : 0; + TotalRequestedRefund += refunds.status === 1 ? refunds.amount : 0; }); - if (vm.data.booking.fixed_currency.id != 1 && this.data.transaction_refunds[0]) { - TotalRequestedRefund = (TotalRequestedRefund * this.data.transaction_refunds[0].currency_rate); - } - return ((Math.round((TotalRequestedRefund + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")); + // if (vm.data.booking.fixed_currency.id != 1 && this.data.transaction_refunds[0]) { + // TotalRequestedRefund = (TotalRequestedRefund * this.data.transaction_refunds[0].currency_rate); + // } + return TotalRequestedRefund; }, totalRefunds() { var TotalRequestedRefund = 0; @@ -326,11 +388,22 @@ TotalRequestedRefund += refunds.status === 2 ? refunds.original_amount : 0; }); return TotalRequestedRefund; + }, + totalConvertRefunds() { + var TotalRequestedRefund = 0; + this.data.transaction_refunds.forEach(function(refunds) { + TotalRequestedRefund += refunds.status === 2 ? refunds.amount : 0; + }); + return TotalRequestedRefund; } }, methods: { clickExpand(){ this.expandPaymentDetails = !this.expandPaymentDetails; + this.expandRefundTransactions = false; + }, + clickExpandRefundTransactions(){ + this.expandRefundTransactions = !this.expandRefundTransactions; }, }, mixins: [componentHandler] diff --git a/resources/assets/vue/components/bookings/elements/SupplierPendingOrderComponent.vue b/resources/assets/vue/components/bookings/elements/SupplierPendingOrderComponent.vue index e4877e96..309f2b9b 100644 --- a/resources/assets/vue/components/bookings/elements/SupplierPendingOrderComponent.vue +++ b/resources/assets/vue/components/bookings/elements/SupplierPendingOrderComponent.vue @@ -56,6 +56,16 @@ {{item.original_currency.short_code}}
+
+
+
+
Refunded Amount
+
+ {{(Math.round((totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}} +
+
+
+
@@ -95,7 +105,7 @@
Amount
- {{(Math.round((item.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}} + {{(Math.round((item.original_amount - totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
@@ -124,11 +134,20 @@ active: false, } }, + computed: { + totalRefunds() { + var TotalRequestedRefund = 0; + this.data.transaction_refunds.forEach(function(refunds) { + TotalRequestedRefund += refunds.status === 2 ? refunds.original_amount : 0; + }); + return TotalRequestedRefund; + } + }, methods: { activate(){ this.active = !this.active; this.$emit('input', this.item) - } + }, }, mixins: [componentHandler] } diff --git a/resources/assets/vue/components/bookings/forms/SupplierPlaceOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/SupplierPlaceOrderFormComponent.vue index 4ec71edd..0f27eb95 100644 --- a/resources/assets/vue/components/bookings/forms/SupplierPlaceOrderFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/SupplierPlaceOrderFormComponent.vue @@ -115,7 +115,12 @@ computed: { total(){ return this.payments.reduce(function (total, currentValue) { - return total + currentValue.original_amount; + return total + currentValue.original_amount - currentValue.transaction_refunds.reduce(function (totalRefund, refundTransaction) { + if (refundTransaction.status === 2) { + return totalRefund + refundTransaction.original_amount; + } + return totalRefund; + }, 0); }, 0); }, From ef43e1616d5f4281c560c45d6159d49d7cd4308c Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Sun, 14 Jan 2024 12:20:28 +0800 Subject: [PATCH 037/228] update --- .../CreateBookingRefundLogic.php | 2 +- .../Commands/ExpiredBookingCommand.php | 61 +------ .../ExpiredRefundedBookingCommand.php | 156 ++++++++++++++++++ 3 files changed, 160 insertions(+), 59 deletions(-) create mode 100644 app/Console/Commands/ExpiredRefundedBookingCommand.php diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php index b87f4331..7455e689 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php @@ -104,7 +104,7 @@ class CreateBookingRefundLogic extends AbstractControllerLogic 1, PaymentMethodType::CASH, $refundTotal, $request->input('amount'), 1, $transaction->original_currency_id, $transaction->currency_rate, - $transaction->tax, $transaction->service_charge, null, ApprovalStatus::PENDING_VERIFICATION, [], $transaction->bill_no); + 0, 0, null, ApprovalStatus::PENDING_VERIFICATION, [], $transaction->bill_no); $transaction = $this->createsTransaction->execute($transaction, $object); diff --git a/app/Console/Commands/ExpiredBookingCommand.php b/app/Console/Commands/ExpiredBookingCommand.php index d79b7b9c..ca690c67 100644 --- a/app/Console/Commands/ExpiredBookingCommand.php +++ b/app/Console/Commands/ExpiredBookingCommand.php @@ -54,7 +54,9 @@ class ExpiredBookingCommand extends Command ->where(function ($query) { $query->whereDoesntHave('transactions') ->orWhereDoesntHave('transactions', function($transaction) { - return $transaction->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + return $transaction->where('type', TransactionType::PURCHASE_ORDER)->orWhere(function ($q) { + $q->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); }); })->get(); @@ -92,62 +94,5 @@ class ExpiredBookingCommand extends Command Log::info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}"); } } - - // 3. Cancel fully refunded payment & cancel booking - $transactions = Transaction::where('type', TransactionType::CREDIT_NOTE)->get(); - - foreach ($transactions as $transaction) { - // get the booking marking - $marking = substr($transaction->payment_reference, -5); - - // for a special payment reference on transaction id: 152013 - if (!is_numeric($marking)) { - $payment_reference = explode(" ", trim($transaction->payment_reference)); - if (count($payment_reference) > 1) { - $marking = $payment_reference[count($payment_reference) - 2]; - } - } - - if (is_numeric($marking)) { - $booking = Booking::where('marking', $marking)->first(); - - if ($booking) { - if ($booking->status === ApprovalStatus::APPROVED) { - $bookingPayment = $booking->transactions()->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first(); - if (!$bookingPayment) { - $bookingPayment = $booking->transactions()->payments()->count(); - Log::info("Credit note transaction id: {$transaction->id}, there are {$bookingPayment} payment for the booking."); - $bookingPayment = $booking->transactions()->payments()->whereIn('status', [ApprovalStatus::EXPIRED, ApprovalStatus::REJECTED])->first(); - $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); - - 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}"); - } - } else { - $status = ApprovalStatus::APPROVAL_STATUS_ID[$booking->status]; - Log::info("Credit note transaction id: {$transaction->id}, booking status is {$status}"); - } - } else { - Log::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}"); - } - } } } diff --git a/app/Console/Commands/ExpiredRefundedBookingCommand.php b/app/Console/Commands/ExpiredRefundedBookingCommand.php new file mode 100644 index 00000000..4d49cb36 --- /dev/null +++ b/app/Console/Commands/ExpiredRefundedBookingCommand.php @@ -0,0 +1,156 @@ +updatesBookingStatus = $updatesBookingStatus; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->createsTransaction = $createsTransaction; + } + + /** + * Execute the console command. + * + * @return int + */ + public function handle() + { + // 3. Cancel fully refunded payment & cancel booking + $transactions = Transaction::where('type', TransactionType::CREDIT_NOTE)->where('payment_reference', 'LIKE', "%refund%")->get(); + + foreach ($transactions as $transaction) { + // get the booking marking + $payment_reference = explode(" ", trim($transaction->payment_reference)); + // $marking = substr($transaction->payment_reference, -5); + $marking = trim(end($payment_reference)); + + if (!preg_match('/^[0-9]+$/', $marking)) { + $payment_reference = explode(".", trim($transaction->payment_reference)); + $marking = trim(end($payment_reference)); + } + + // for a special payment reference on transaction id: 140231 + if (!preg_match('/^[0-9]+$/', $marking)) { + $payment_reference = explode("No", trim($transaction->payment_reference)); + $marking = end($payment_reference); + } + + // for a special payment reference on transaction id: 152013 + if (!preg_match('/^[0-9]+$/', $marking)) { + $payment_reference = explode(" ", trim($transaction->payment_reference)); + $marking = end($payment_reference); + $marking = prev($payment_reference); + } + + if (preg_match('/^[0-9]+$/', $marking)) { + $booking = Booking::where('marking', $marking)->first(); + + if ($booking) { + $bookingPayment = $booking->transactions()->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first(); + if (!$bookingPayment) { + $bookingPaymentCount = $booking->transactions()->payments()->count(); + if ($bookingPaymentCount > 1) { + Log::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; + break; + } + } + } + + if (!$bookingPayment) { + $bookingPayment = $booking->transactions()->payments()->whereIn('status', [ApprovalStatus::SUSPENDED, ApprovalStatus::EXPIRED, ApprovalStatus::REJECTED])->orderBy('id', 'DESC')->first(); + } + $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); + + 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(); + + if ($refund) { + Log::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, $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); + } + } else { + Log::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}"); + } + } + } +} From c8cabee97b82e78c363e13dc96a1e60f86fb7f14 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Mon, 15 Jan 2024 23:41:12 +0800 Subject: [PATCH 038/228] update --- .../Eloquent/Filters/IsNotFullyRefunded.php | 24 +++++++++++++++++++ .../ExpiredRefundedBookingCommand.php | 12 +++++++--- .../elements/PaymentHistoryComponent.vue | 4 ++-- .../SupplierPendingOrdersSectionComponent.vue | 4 ++-- 4 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 app/Classes/General/Eloquent/Filters/IsNotFullyRefunded.php diff --git a/app/Classes/General/Eloquent/Filters/IsNotFullyRefunded.php b/app/Classes/General/Eloquent/Filters/IsNotFullyRefunded.php new file mode 100644 index 00000000..fdbb2994 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/IsNotFullyRefunded.php @@ -0,0 +1,24 @@ +withSum(['transactions as total_refund_amount' => function($q) { + $q->refunds()->where('status', ApprovalStatus::APPROVED); + }], 'original_amount') + ->having('total_refund_amount', '<', DB::raw('original_amount')); + } +} diff --git a/app/Console/Commands/ExpiredRefundedBookingCommand.php b/app/Console/Commands/ExpiredRefundedBookingCommand.php index 4d49cb36..db7e00a7 100644 --- a/app/Console/Commands/ExpiredRefundedBookingCommand.php +++ b/app/Console/Commands/ExpiredRefundedBookingCommand.php @@ -122,19 +122,25 @@ class ExpiredRefundedBookingCommand extends Command //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}"); + // 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 (!$refund) { + 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, diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index 2649edcf..43e2e96d 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -299,14 +299,14 @@
-
+
-
+
diff --git a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue index 7df9c125..c7382629 100644 --- a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue +++ b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue @@ -117,7 +117,7 @@
- + @@ -195,7 +195,7 @@ }, updateList(){ - this.$refs.pendingOrdersList.updateFilters({per_page: 10000, status: 2, type: 1, original_currency_id_in: [this.selectedCurrency.id], transaction_service_id: this.selectedService.id}); + this.$refs.pendingOrdersList.updateFilters({per_page: 10000, status: 2, type: 1, is_not_fully_refunded: true, original_currency_id_in: [this.selectedCurrency.id], transaction_service_id: this.selectedService.id}); this.selectedSupplier.status = false; this.currencyDropdownLaunch.status = false; From 7151caa9b8c7364df80a76643c78fe206a00b002 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sun, 11 Feb 2024 16:11:42 +0800 Subject: [PATCH 039/228] Proof of concept - Vue Polling a workaround for AWS API Gateway limitation --- app/Classes/Jobs/ListBookingsJob.php | 2 + app/Classes/Jobs/ListDocumentsJob.php | 2 + app/Classes/Jobs/ListTransactionsJob.php | 2 + .../Processors/FetchesJobResultProcessor.php | 10 +- .../Processors/UpdateJobResultProcessor.php | 4 +- .../AdminPaymentsBillingSectionComponent.vue | 26 ++-- ...PaymentsBillingSectionPollingComponent.vue | 136 ++++++++++++++++++ .../SupplierPendingOrdersSectionComponent.vue | 8 +- .../general/elements/ListPollingComponent.vue | 57 ++++---- .../views/pages/billings_experiment.blade.php | 9 ++ routes/job.php | 1 + routes/web.php | 12 +- 12 files changed, 219 insertions(+), 50 deletions(-) create mode 100644 resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionPollingComponent.vue create mode 100644 resources/views/pages/billings_experiment.blade.php diff --git a/app/Classes/Jobs/ListBookingsJob.php b/app/Classes/Jobs/ListBookingsJob.php index 41f976a6..b021b71d 100644 --- a/app/Classes/Jobs/ListBookingsJob.php +++ b/app/Classes/Jobs/ListBookingsJob.php @@ -16,6 +16,8 @@ class ListBookingsJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + public $timeout = 900; + /** @var ListGenericJobObject */ private $listGenericJobObject; diff --git a/app/Classes/Jobs/ListDocumentsJob.php b/app/Classes/Jobs/ListDocumentsJob.php index bbadc169..6e93062b 100644 --- a/app/Classes/Jobs/ListDocumentsJob.php +++ b/app/Classes/Jobs/ListDocumentsJob.php @@ -16,6 +16,8 @@ class ListDocumentsJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + public $timeout = 900; + /** @var ListGenericJobObject */ private $listGenericJobObject; diff --git a/app/Classes/Jobs/ListTransactionsJob.php b/app/Classes/Jobs/ListTransactionsJob.php index 6b8913a2..a2b28656 100644 --- a/app/Classes/Jobs/ListTransactionsJob.php +++ b/app/Classes/Jobs/ListTransactionsJob.php @@ -16,6 +16,8 @@ class ListTransactionsJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + public $timeout = 900; + /** @var ListGenericJobObject */ private $listGenericJobObject; diff --git a/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php b/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php index e19456e7..89783fe8 100644 --- a/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php +++ b/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php @@ -2,6 +2,7 @@ namespace App\Classes\Modules\Jobs\Processors; +use App\Classes\Exceptions\JobResourceNotFoundException; use App\Classes\Modules\Jobs\Services\FetchesJobResult; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; @@ -32,12 +33,13 @@ class FetchesJobResultProcessor public function execute(Request $request){ $res1 = $this->fetchesJobResult->execute(['job_id' => $request->route('job_id')]); + if($request->route('is_last')){ + $res2 = $this->fetchesJobResult->execute(['request_signature' => $res1->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]); + return $res2; + } if(!$res1->result){ - Log::info('Job id: '.$request->route('job_id')); - $res2 = $this->fetchesJobResult->execute(['request_signature' => $res1->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]); - Log::info('Job id: '.$res2->id." , request_signature: ".$res2->request_signature); - return $res2; + throw new JobResourceNotFoundException('Unable to find any job based on the criteria provided'); } return $res1; diff --git a/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php b/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php index fff83bb0..0106417d 100644 --- a/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php +++ b/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php @@ -44,9 +44,9 @@ class UpdateJobResultProcessor try{ $jobResultExisting = $this->fetchesJobResult->execute(['request_signature' => $jobResultCurrent->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]); $resultSignatureExisting = $jobResultExisting->result_signature; - if($resultSignatureExisting != $resultSignatureCurrent){ + //if($resultSignatureExisting != $resultSignatureCurrent){ $this->updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $listGenericJobObject->getJobCommandName(), $listGenericJobObject->getJobCommand()); - } + //} } catch (JobResourceNotFoundException $exception){ $this->updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $listGenericJobObject->getJobCommandName(), $listGenericJobObject->getJobCommand()); } diff --git a/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue b/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue index 03244ff4..966ccbbc 100644 --- a/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue +++ b/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue @@ -90,34 +90,34 @@
- + - -
-
- + +
+
+ - -
-
- + +
+
+ - +
- + - -
+
+
diff --git a/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionPollingComponent.vue b/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionPollingComponent.vue new file mode 100644 index 00000000..47d14857 --- /dev/null +++ b/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionPollingComponent.vue @@ -0,0 +1,136 @@ + + diff --git a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue index e6b66dcf..d2b69080 100644 --- a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue +++ b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue @@ -118,16 +118,16 @@
- - + +
diff --git a/resources/assets/vue/components/general/elements/ListPollingComponent.vue b/resources/assets/vue/components/general/elements/ListPollingComponent.vue index 98e2a44b..fcd3b8b8 100644 --- a/resources/assets/vue/components/general/elements/ListPollingComponent.vue +++ b/resources/assets/vue/components/general/elements/ListPollingComponent.vue @@ -50,6 +50,7 @@ diff --git a/resources/views/pages/billings_experiment.blade.php b/resources/views/pages/billings_experiment.blade.php new file mode 100644 index 00000000..d1caee2d --- /dev/null +++ b/resources/views/pages/billings_experiment.blade.php @@ -0,0 +1,9 @@ +@extends('layouts.base_portal') +@section('inner_content') +
+
+ + +
+
+@endsection diff --git a/routes/job.php b/routes/job.php index f32d142e..028e9468 100644 --- a/routes/job.php +++ b/routes/job.php @@ -4,4 +4,5 @@ use Illuminate\Support\Facades\Route; Route::group(['prefix' => 'job', 'as' => 'job.', 'namespace' => 'Jobs'], function () { Route::get('/fetch/{job_id}', 'FetchJobResultController@fetch')->name('fetch'); + Route::get('/fetch/{job_id}/{is_last}', 'FetchJobResultController@fetch')->name('fetch.last.attempt'); }); diff --git a/routes/web.php b/routes/web.php index ead4b3d2..4e9afd11 100644 --- a/routes/web.php +++ b/routes/web.php @@ -92,6 +92,12 @@ Route::get('/billings', function () { return view('pages.billings'); })->name('billings'); +/* Vue Polling Experiment - Starts */ +Route::get('/billings-experiment', function () { + return view('pages.billings_experiment'); +})->name('billings.experiment'); +/* Vue Polling Experiment - Ends */ + Route::get('/currency_orders', function () { return view('pages.currency_orders'); })->name('currency_orders'); @@ -813,13 +819,13 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, ->withTrashed() ->orderBy('created_at', 'asc') ->first(); - + // get the first bill_no $firstBillNo = $firstInvoice->bill_no; if (strpos($firstBillNo, '-deleted') !== false) { $firstBillNo = substr($firstBillNo, 0, strpos($firstBillNo, '-deleted')); } - + // update currentInvoice bill_no to '-deleted-' $currentInvoice = $booking->transactions()->where('type', TransactionType::INVOICE)->first(); $currentInvoice->bill_no = $currentInvoice->bill_no ."-deleted-" . Str::random(10); @@ -842,4 +848,4 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, } } ); -})->name('invoice.fix.byCustomerMarking'); \ No newline at end of file +})->name('invoice.fix.byCustomerMarking'); From ea4795e5c861616064c9ceae521aefedd60769c2 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sun, 11 Feb 2024 09:53:09 +0000 Subject: [PATCH 040/228] Revert "Merge branch 'dillon/51-vue-polling-experimental-2' into 'master'" This reverts merge request !152 --- .../JobResourceNotFoundException.php | 11 - .../Abstracts/AbstractControllerLogic.php | 15 +- .../General/Eloquent/AbstractFetchRecord.php | 14 +- .../General/Eloquent/AbstractGetRecord.php | 26 +-- .../General/Eloquent/AbstractListRecord.php | 14 +- .../General/Eloquent/Filters/JobId.php | 20 -- .../Eloquent/Filters/OrderByIdDesc.php | 20 -- .../Eloquent/Filters/RequestSignature.php | 19 -- .../Eloquent/Filters/ResultNotNull.php | 18 -- app/Classes/General/Helper.php | 24 -- app/Classes/Jobs/ListBookingsJob.php | 52 ----- app/Classes/Jobs/ListDocumentsJob.php | 63 ------ app/Classes/Jobs/ListTransactionsJob.php | 52 ----- .../ControllersLogic/ListBookingJobLogic.php | 75 ------ .../Processors/ListBookingsJobProcessor.php | 46 ---- .../ControllersLogic/ListDocumentJobLogic.php | 75 ------ .../Processors/ListDocumentsJobProcessor.php | 47 ---- .../ControllersLogic/FetchJobResultLogic.php | 51 ----- .../ListGenericJobObject.php | 118 ---------- .../UpdateJobResultObject.php | 60 ----- .../Processors/FetchesJobResultProcessor.php | 47 ---- .../Processors/UpdateJobResultProcessor.php | 64 ------ .../Jobs/Services/CreatesJobResult.php | 26 --- .../Jobs/Services/FetchesJobResult.php | 33 --- .../Modules/Jobs/Services/ListsJobResult.php | 33 --- .../Jobs/Services/UpdatesJobResult.php | 28 --- .../ListTransactionsJobLogic.php | 74 ------ .../ListTransactionsJobProcessor.php | 45 ---- .../Bookings/ListBookingsJobController.php | 22 -- .../Documents/ListDocumentsJobController.php | 19 -- .../Jobs/FetchJobResultController.php | 19 -- .../ListTransactionsJobController.php | 21 -- app/Http/Resources/BookingResource.php | 2 + app/Http/Resources/CompanyResource.php | 1 + app/Http/Resources/DocumentResource.php | 3 + app/Http/Resources/JobResultResource.php | 22 -- app/Http/Resources/ListBookingJobResource.php | 81 ------- .../Resources/ListDocumentJobResource.php | 31 --- .../Resources/ListTransactionJobResource.php | 54 ----- app/Http/Resources/V2/BookingV2Resource.php | 82 ------- app/Http/Resources/V2/CompanyV2Resource.php | 100 -------- app/Models/JobResult.php | 13 -- ..._08_08_124848_create_job_results_table.php | 35 --- ...31_add_new_column_to_job_results_table.php | 36 --- ..._add_new_column_2_to_job_results_table.php | 34 --- .../AdminPaymentsBillingSectionComponent.vue | 136 ----------- ...PaymentsBillingSectionPollingComponent.vue | 136 ----------- .../SupplierPendingOrdersSectionComponent.vue | 10 +- .../general/elements/ListPollingComponent.vue | 213 ------------------ .../vue/general/mixins/aws/requestV2.js | 49 ---- .../assets/vue/general/mixins/tabHandler.js | 24 -- .../assets/vue/vuex/modules/crudRequestV2.js | 51 ----- resources/assets/vue/vuex/store.js | 4 +- resources/views/pages/billings.blade.php | 126 ++++++++++- .../views/pages/billings_experiment.blade.php | 9 - routes/api.php | 4 - routes/currency.php | 2 +- routes/document.php | 3 +- routes/job.php | 8 - routes/web.php | 12 +- 60 files changed, 152 insertions(+), 2380 deletions(-) delete mode 100644 app/Classes/Exceptions/JobResourceNotFoundException.php delete mode 100644 app/Classes/General/Eloquent/Filters/JobId.php delete mode 100644 app/Classes/General/Eloquent/Filters/OrderByIdDesc.php delete mode 100644 app/Classes/General/Eloquent/Filters/RequestSignature.php delete mode 100644 app/Classes/General/Eloquent/Filters/ResultNotNull.php delete mode 100644 app/Classes/Jobs/ListBookingsJob.php delete mode 100644 app/Classes/Jobs/ListDocumentsJob.php delete mode 100644 app/Classes/Jobs/ListTransactionsJob.php delete mode 100644 app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php delete mode 100644 app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php delete mode 100644 app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php delete mode 100644 app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php delete mode 100644 app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php delete mode 100644 app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php delete mode 100644 app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php delete mode 100644 app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php delete mode 100644 app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php delete mode 100644 app/Classes/Modules/Jobs/Services/CreatesJobResult.php delete mode 100644 app/Classes/Modules/Jobs/Services/FetchesJobResult.php delete mode 100644 app/Classes/Modules/Jobs/Services/ListsJobResult.php delete mode 100644 app/Classes/Modules/Jobs/Services/UpdatesJobResult.php delete mode 100644 app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php delete mode 100644 app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php delete mode 100644 app/Http/Controllers/Bookings/ListBookingsJobController.php delete mode 100644 app/Http/Controllers/Documents/ListDocumentsJobController.php delete mode 100644 app/Http/Controllers/Jobs/FetchJobResultController.php delete mode 100644 app/Http/Controllers/Transactions/ListTransactionsJobController.php delete mode 100644 app/Http/Resources/JobResultResource.php delete mode 100644 app/Http/Resources/ListBookingJobResource.php delete mode 100644 app/Http/Resources/ListDocumentJobResource.php delete mode 100644 app/Http/Resources/ListTransactionJobResource.php delete mode 100644 app/Http/Resources/V2/BookingV2Resource.php delete mode 100644 app/Http/Resources/V2/CompanyV2Resource.php delete mode 100644 app/Models/JobResult.php delete mode 100644 database/migrations/2023_08_08_124848_create_job_results_table.php delete mode 100644 database/migrations/2023_08_29_063531_add_new_column_to_job_results_table.php delete mode 100644 database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php delete mode 100644 resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue delete mode 100644 resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionPollingComponent.vue delete mode 100644 resources/assets/vue/components/general/elements/ListPollingComponent.vue delete mode 100644 resources/assets/vue/general/mixins/aws/requestV2.js delete mode 100644 resources/assets/vue/general/mixins/tabHandler.js delete mode 100644 resources/assets/vue/vuex/modules/crudRequestV2.js delete mode 100644 resources/views/pages/billings_experiment.blade.php delete mode 100644 routes/job.php diff --git a/app/Classes/Exceptions/JobResourceNotFoundException.php b/app/Classes/Exceptions/JobResourceNotFoundException.php deleted file mode 100644 index a8ef358e..00000000 --- a/app/Classes/Exceptions/JobResourceNotFoundException.php +++ /dev/null @@ -1,11 +0,0 @@ -getMessage(), - $exception->getTrace()[0]['file'], - $exception->getTrace()[0]['line'] - )); - } - else{ - log::error($exception); - } - + log::error($exception); return (new ApiResponseObject($this->getNotificationTitle().' failed', $exception->getMessage(), $exception->getCode() ? $exception->getCode() : HttpStatus::SERVER_ERROR))->handler(); diff --git a/app/Classes/General/Eloquent/AbstractFetchRecord.php b/app/Classes/General/Eloquent/AbstractFetchRecord.php index 503fb369..248deee7 100644 --- a/app/Classes/General/Eloquent/AbstractFetchRecord.php +++ b/app/Classes/General/Eloquent/AbstractFetchRecord.php @@ -4,11 +4,9 @@ namespace App\Classes\General\Eloquent; use App\Classes\Exceptions\ResourceNotFoundException; -use App\Classes\Exceptions\JobResourceNotFoundException; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Psy\Exception\ErrorException; -use Illuminate\Support\Facades\Log; abstract class AbstractFetchRecord extends AbstractGetRecord { @@ -29,18 +27,12 @@ abstract class AbstractFetchRecord extends AbstractGetRecord * @return Model * @throws ResourceNotFoundException */ - public function getResults(Builder $query, array $param = []): Model { + public function getResults(Builder $query): Model { if(!$query->exists()){ - $table = $query->getModel()->getTable(); - if($table ==='job_results'){ - throw new JobResourceNotFoundException('Unable to find any job based on the criteria provided'); - } - else{ - throw new ResourceNotFoundException('Unable to find any record based on the criteria provided'); - } + throw new ResourceNotFoundException('Unable to find any record based on the criteria provided'); } return $query->first(); } -} +} \ No newline at end of file diff --git a/app/Classes/General/Eloquent/AbstractGetRecord.php b/app/Classes/General/Eloquent/AbstractGetRecord.php index 1a7eac3e..f927d818 100644 --- a/app/Classes/General/Eloquent/AbstractGetRecord.php +++ b/app/Classes/General/Eloquent/AbstractGetRecord.php @@ -30,25 +30,11 @@ abstract class AbstractGetRecord return $this->filters->only(self::DECORATION_FILTERS); } - // /** - // * @param null|string $json - // * @return array - // */ - // public function deserializeFilters(?string $json): array { - // return $json !== null ? collect(json_decode($json))->toArray() : []; - // } - /** - * @param null|string $param + * @param null|string $json * @return array */ - public function deserializeFilters($param): array { - if(gettype($param) == "array"){ - $json = implode(',', $param); - } - else{ - $json = $param; - } + public function deserializeFilters(?string $json): array { return $json !== null ? collect(json_decode($json))->toArray() : []; } @@ -64,9 +50,9 @@ abstract class AbstractGetRecord * @param array $filters * @return mixed */ - public function handler(array $filters, array $params = []){ + public function handler(array $filters){ $this->filters = collect($filters); - return $this->getResults($this->applyFiltersToQuery(), $params); + return $this->getResults($this->applyFiltersToQuery()); } @@ -79,6 +65,6 @@ abstract class AbstractGetRecord * @param Builder $query * @return mixed */ - abstract function getResults(Builder $query, array $params = []); + abstract function getResults(Builder $query); -} +} \ No newline at end of file diff --git a/app/Classes/General/Eloquent/AbstractListRecord.php b/app/Classes/General/Eloquent/AbstractListRecord.php index f898f108..7b7d0df9 100644 --- a/app/Classes/General/Eloquent/AbstractListRecord.php +++ b/app/Classes/General/Eloquent/AbstractListRecord.php @@ -17,11 +17,11 @@ abstract class AbstractListRecord extends AbstractGetRecord * @return mixed * @throws MalformedRequestException */ - public function execute(array $filters = [], array $param = []){ + public function execute(array $filters = []){ try{ - return $this->handler($filters, $param); + return $this->handler($filters); } catch (QueryException $exception){ log::error($exception); @@ -30,24 +30,18 @@ abstract class AbstractListRecord extends AbstractGetRecord } - /** * @param Builder $query * @return mixed */ - public function getResults(Builder $query, array $param = []) { + public function getResults(Builder $query) { $filters = $this->getDecorationFilters(); if($filters->has('order_by')){ $query = $query->orderBy($filters->get('order_by')->column, $filters->get('order_by')->DESC ? 'DESC': 'ASC'); } - if(!empty($param)){ - return $filters->has('per_page') ? $query->paginate($filters->get('per_page'), ['*'], 'page', $param['page']) : $query->get(); //page data from query parameters e.g ?page=1 - } - else{ - return $filters->has('per_page') ? $query->paginate($filters->get('per_page')) : $query->get(); - } + return $filters->has('per_page') ? $query->paginate($filters->get('per_page')) : $query->get(); } diff --git a/app/Classes/General/Eloquent/Filters/JobId.php b/app/Classes/General/Eloquent/Filters/JobId.php deleted file mode 100644 index 42ac51a4..00000000 --- a/app/Classes/General/Eloquent/Filters/JobId.php +++ /dev/null @@ -1,20 +0,0 @@ -where('job_id', $value); - } - -} diff --git a/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php b/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php deleted file mode 100644 index 547ec9bd..00000000 --- a/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php +++ /dev/null @@ -1,20 +0,0 @@ -orderBy('id', 'desc'); - } - -} diff --git a/app/Classes/General/Eloquent/Filters/RequestSignature.php b/app/Classes/General/Eloquent/Filters/RequestSignature.php deleted file mode 100644 index 67dde0a3..00000000 --- a/app/Classes/General/Eloquent/Filters/RequestSignature.php +++ /dev/null @@ -1,19 +0,0 @@ -where('request_signature', $value); - } - -} diff --git a/app/Classes/General/Eloquent/Filters/ResultNotNull.php b/app/Classes/General/Eloquent/Filters/ResultNotNull.php deleted file mode 100644 index 3f6a0341..00000000 --- a/app/Classes/General/Eloquent/Filters/ResultNotNull.php +++ /dev/null @@ -1,18 +0,0 @@ -whereNotNull('result'); - } -} diff --git a/app/Classes/General/Helper.php b/app/Classes/General/Helper.php index 45c72f53..ac89540b 100644 --- a/app/Classes/General/Helper.php +++ b/app/Classes/General/Helper.php @@ -2,7 +2,6 @@ namespace App\Classes\General; -use Illuminate\Http\Resources\Json\ResourceCollection; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; @@ -43,27 +42,4 @@ class Helper } } } - - /** - * @param null|string $param - * @return array - */ - static function deserializeFilters($param): array { - if(gettype($param) == "array"){ - $json = implode(',', $param); - } - else{ - $json = $param; - } - return $json !== null ? collect(json_decode($json))->toArray() : []; - } - - /** - * @param ResourceCollection $collection - * @return array - */ - static function collectionResponse(ResourceCollection $collection){ - return json_decode($collection->response()->getContent(), true); - } - } diff --git a/app/Classes/Jobs/ListBookingsJob.php b/app/Classes/Jobs/ListBookingsJob.php deleted file mode 100644 index b021b71d..00000000 --- a/app/Classes/Jobs/ListBookingsJob.php +++ /dev/null @@ -1,52 +0,0 @@ -listGenericJobObject = $listGenericJobObject; - } - - public function handle() - { - $rawPayload = $this->job->payload(); - if(isset($rawPayload['data']['commandName'])){ - $this->listGenericJobObject->setJobCommandName($rawPayload['data']['commandName']); - } - - if(isset($rawPayload['data']['command'])){ - $this->listGenericJobObject->setJobCommand($rawPayload['data']['command']); - } - - $result = (App()->make(ListBookingsJobProcessor::class))->execute($this->listGenericJobObject); - } - - public function getJobId(){ - return $this->job->getJobId(); - } -} diff --git a/app/Classes/Jobs/ListDocumentsJob.php b/app/Classes/Jobs/ListDocumentsJob.php deleted file mode 100644 index 6e93062b..00000000 --- a/app/Classes/Jobs/ListDocumentsJob.php +++ /dev/null @@ -1,63 +0,0 @@ -listGenericJobObject = $listGenericJobObject; - } - - public function handle() - { - $rawPayload = $this->job->payload(); - if(isset($rawPayload['data']['commandName'])){ - $this->listGenericJobObject->setJobCommandName($rawPayload['data']['commandName']); - } - - if(isset($rawPayload['data']['command'])){ - $this->listGenericJobObject->setJobCommand($rawPayload['data']['command']); - } - - $result = (App()->make(ListDocumentsJobProcessor::class))->execute($this->listGenericJobObject); - - //cief todo: Insert into DB: job id, query result, timestamp - // Store the result in the job_results table - - //cief todo: why cannot save data in table like this - // $model = new JobResult(); - // $model->job_id = $this->job->getJobId(); - // $model->result = json_encode($result); - // $model->save(); - - // Log::error(json_encode($model->id)); - } - - public function getJobId(){ - return $this->job->getJobId(); - } -} diff --git a/app/Classes/Jobs/ListTransactionsJob.php b/app/Classes/Jobs/ListTransactionsJob.php deleted file mode 100644 index a2b28656..00000000 --- a/app/Classes/Jobs/ListTransactionsJob.php +++ /dev/null @@ -1,52 +0,0 @@ -listGenericJobObject = $listGenericJobObject; - } - - public function handle() - { - $rawPayload = $this->job->payload(); - if(isset($rawPayload['data']['commandName'])){ - $this->listGenericJobObject->setJobCommandName($rawPayload['data']['commandName']); - } - - if(isset($rawPayload['data']['command'])){ - $this->listGenericJobObject->setJobCommand($rawPayload['data']['command']); - } - - $result = (App()->make(ListTransactionsJobProcessor::class))->execute($this->listGenericJobObject); - } - - public function getJobId(){ - return $this->job->getJobId(); - } -} diff --git a/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php deleted file mode 100644 index ef3570f7..00000000 --- a/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php +++ /dev/null @@ -1,75 +0,0 @@ - 'List Booking Job', - 'message' => 'You have successfully submit a job to list bookings' - ]; - } - - /** @var CreatesJobResult */ - private $createsJobResult; - - /** - * ListPackingListsJobLogic constructor. - * @param CreatesJobResult $createsJobResult - */ - public function __construct(CreatesJobResult $createsJobResult) - { - $this->createsJobResult = $createsJobResult; - } - - - /** - * @param Request $request - * @return JsonResponse - */ - public function logic(Request $request) : JsonResponse - { - $jobId = uniqid(); - - $user = Auth::user(); - $userInfo = (object) [ - 'type' => $user->type, - ]; - - $userInfoJson = json_encode($userInfo); - $requestSignature = md5($userInfoJson . $request->fullUrl()); - - $listGenericJobObject = new ListGenericJobObject( - $request->fullUrl(), - $request->all(), - $requestSignature, - null, - $jobId, - $userInfo - ); - - ListBookingsJob::dispatch($listGenericJobObject); - - $result = []; - $result['job_id'] = $jobId; - - $this->createsJobResult->execute($listGenericJobObject); - - return $this->response(['data' => $result]); - } - -} diff --git a/app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php b/app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php deleted file mode 100644 index 2a09eb12..00000000 --- a/app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php +++ /dev/null @@ -1,46 +0,0 @@ -listsBookings = $listsBookings; - $this->updateJobResultProcessor = $updateJobResultProcessor; - } - - /** - * @param ListGenericJobObject $listGenericJobObject - * @return void - * @throws \App\Classes\Exceptions\MalformedRequestException - * @throws \App\Classes\Exceptions\JobResourceNotFoundException - */ - public function execute(ListGenericJobObject $listGenericJobObject) { - - $query = $this->listsBookings->execute($this->listsBookings->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page']]); - foreach ($query->items() as &$item) { - $item['userInfo'] = $listGenericJobObject->getUserInfo(); - } - $resultCurrent = Helper::collectionResponse(ListBookingJobResource::collection($query)); - $this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent); - } -} diff --git a/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php b/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php deleted file mode 100644 index 5e895ad8..00000000 --- a/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php +++ /dev/null @@ -1,75 +0,0 @@ - 'List Document Job', - 'message' => 'You have successfully submit a job to list documents' - ]; - } - - /** @var CreatesJobResult */ - private $createsJobResult; - - /** - * ListDocumentJobLogic constructor. - * @param CreatesJobResult $createsJobResult - */ - public function __construct(CreatesJobResult $createsJobResult) - { - $this->createsJobResult = $createsJobResult; - } - - - /** - * @param Request $request - * @return JsonResponse - */ - public function logic(Request $request) : JsonResponse - { - $jobId = uniqid(); - - $user = Auth::user(); - $userInfo = (object) [ - 'email' => $user->email, - 'type' => $user->type, - ]; - - $userInfoJson = json_encode($userInfo); - $requestSignature = md5($userInfoJson . $request->fullUrl()); - - $listGenericJobObject = new ListGenericJobObject( - $request->fullUrl(), - $request->all(), - $requestSignature, - null, - $jobId, - $userInfo - ); - - ListDocumentsJob::dispatch($listGenericJobObject); - - $result = []; - $result['job_id'] = $jobId; - - $this->createsJobResult->execute($listGenericJobObject); - - return $this->response(['data' => $result]); - } -} diff --git a/app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php b/app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php deleted file mode 100644 index 70777f0c..00000000 --- a/app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php +++ /dev/null @@ -1,47 +0,0 @@ -listsDocuments = $listsDocuments; - $this->updateJobResultProcessor = $updateJobResultProcessor; - } - - /** - * @param ListGenericJobObject $listGenericJobObject - * @return void - * @throws \App\Classes\Exceptions\MalformedRequestException - * @throws \App\Classes\Exceptions\JobResourceNotFoundException - */ - public function execute(ListGenericJobObject $listGenericJobObject) { - - $query = $this->listsDocuments->execute($this->listsDocuments->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page']]); - foreach ($query->items() as &$item) { - $item['userInfo'] = $listGenericJobObject->getUserInfo(); - } - $resultCurrent = Helper::collectionResponse(ListDocumentJobResource::collection($query)); - $this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent); - } -} - diff --git a/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php b/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php deleted file mode 100644 index c4b72cf0..00000000 --- a/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php +++ /dev/null @@ -1,51 +0,0 @@ - 'Retrieved Data', - 'message' => 'You have successfully retrieved data' - ]; - } - - /** @var FetchesJobResultProcessor */ - private $fetchesJobResultProcessor; - - /** - * FetchJobResultLogic constructor. - * @param FetchesJobResultProcessor $fetchesJobResultProcessor - */ - public function __construct(FetchesJobResultProcessor $fetchesJobResultProcessor) - { - $this->fetchesJobResultProcessor = $fetchesJobResultProcessor; - } - - - /** - * @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 - { - $query = $this->fetchesJobResultProcessor->execute($request); - return $this->resourceResponse(new JobResultResource($query)); - } - -} diff --git a/app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php b/app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php deleted file mode 100644 index 953d77d7..00000000 --- a/app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php +++ /dev/null @@ -1,118 +0,0 @@ -name = $name; - $this->payload = $payload; - $this->jobId = $jobId; - $this->requestSignature = $requestSignature; - $this->resultSignature = $resultSignature; - $this->userInfo = $userInfo; - } - - /** - * @return string - */ - public function getName(): string - { - return $this->name; - } - - /** - * @return array - */ - public function getPayload(): array - { - return $this->payload; - } - - /** - * @return string - */ - public function getJobId(): string - { - return $this->jobId; - } - - /** - * @return string - */ - public function getRequestSignature(): string - { - return $this->requestSignature; - } - - /** - * @return string - */ - public function getResultSignature(): ?string - { - return $this->resultSignature; - } - - /** - * @return object - */ - public function getUserInfo(): object - { - return $this->userInfo; - } - - /** - * @return string - */ - public function getJobCommandName(): string - { - return $this->jobCommandName; - } - - /** - * @return string - */ - public function getJobCommand(): string - { - return $this->jobCommand; - } - - - public function setJobCommandName(string $jobCommandName) - { - $this->jobCommandName = $jobCommandName; - } - - public function setJobCommand(string $jobCommand) - { - $this->jobCommand = $jobCommand; - } - -} diff --git a/app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php b/app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php deleted file mode 100644 index 636c56b0..00000000 --- a/app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php +++ /dev/null @@ -1,60 +0,0 @@ -result = $result; - $this->resultSignature = $resultSignature; - $this->jobCommandName = $jobCommandName; - $this->jobCommand = $jobCommand; - } - - /** - * @return string - */ - public function getResult(): string - { - return $this->result; - } - - /** - * @return array - */ - public function getResultSignature(): string - { - return $this->resultSignature; - } - - /** - * @return string - */ - public function getJobCommandName(): string - { - return $this->jobCommandName; - } - - /** - * @return string - */ - public function getJobCommand(): string - { - return $this->jobCommand; - } -} diff --git a/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php b/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php deleted file mode 100644 index 89783fe8..00000000 --- a/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php +++ /dev/null @@ -1,47 +0,0 @@ -fetchesJobResult = $fetchesJobResult; - } - - - /** - * @param Request $request - * @return Model - * @throws \App\Classes\Exceptions\MalformedRequestException - * @throws \App\Classes\Exceptions\JobResourceNotFoundException - * @throws \App\Classes\Exceptions\ResourceNotFoundException - */ - public function execute(Request $request){ - - $res1 = $this->fetchesJobResult->execute(['job_id' => $request->route('job_id')]); - if($request->route('is_last')){ - $res2 = $this->fetchesJobResult->execute(['request_signature' => $res1->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]); - return $res2; - } - - if(!$res1->result){ - throw new JobResourceNotFoundException('Unable to find any job based on the criteria provided'); - } - - return $res1; - } -} diff --git a/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php b/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php deleted file mode 100644 index 0106417d..00000000 --- a/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php +++ /dev/null @@ -1,64 +0,0 @@ -fetchesJobResult = $fetchesJobResult; - $this->updatesJobResult = $updatesJobResult; - } - - /** - * @param ListGenericJobObject $listGenericJobObject - * @param array $resultCurrent - * @return void - * @throws \App\Classes\Exceptions\MalformedRequestException - * @throws \App\Classes\Exceptions\JobResourceNotFoundException - */ - public function execute(ListGenericJobObject $listGenericJobObject, $resultCurrent) { - $jobResultCurrent = $this->fetchesJobResult->execute(['job_id' => $listGenericJobObject->getJobId()]); - $resultCurrentJson = json_encode($resultCurrent); - $resultSignatureCurrent = md5($resultCurrentJson); - - try{ - $jobResultExisting = $this->fetchesJobResult->execute(['request_signature' => $jobResultCurrent->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]); - $resultSignatureExisting = $jobResultExisting->result_signature; - //if($resultSignatureExisting != $resultSignatureCurrent){ - $this->updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $listGenericJobObject->getJobCommandName(), $listGenericJobObject->getJobCommand()); - //} - } catch (JobResourceNotFoundException $exception){ - $this->updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $listGenericJobObject->getJobCommandName(), $listGenericJobObject->getJobCommand()); - } - } - - private function updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $jobCommandName, $jobCommand){ - $updateJobResultObject = new UpdateJobResultObject( - $resultCurrentJson, - $resultSignatureCurrent, - $jobCommandName, - $jobCommand - ); - $create = $this->updatesJobResult->execute($jobResultCurrent, $updateJobResultObject); - } -} diff --git a/app/Classes/Modules/Jobs/Services/CreatesJobResult.php b/app/Classes/Modules/Jobs/Services/CreatesJobResult.php deleted file mode 100644 index e70e0e6a..00000000 --- a/app/Classes/Modules/Jobs/Services/CreatesJobResult.php +++ /dev/null @@ -1,26 +0,0 @@ -job_id = $listGenericJobObject->getJobId(); - $model->request_signature = $listGenericJobObject->getRequestSignature(); - $model->result_signature = $listGenericJobObject->getResultSignature(); - $model->url = $listGenericJobObject->getName(); - - return $this->handler($model); - } -} diff --git a/app/Classes/Modules/Jobs/Services/FetchesJobResult.php b/app/Classes/Modules/Jobs/Services/FetchesJobResult.php deleted file mode 100644 index 1cc99cb6..00000000 --- a/app/Classes/Modules/Jobs/Services/FetchesJobResult.php +++ /dev/null @@ -1,33 +0,0 @@ -repository = $repository; - } - - - /** - * @return Builder - */ - public function getRepository(): Builder - { - return $this->repository->newQuery(); - } -} diff --git a/app/Classes/Modules/Jobs/Services/ListsJobResult.php b/app/Classes/Modules/Jobs/Services/ListsJobResult.php deleted file mode 100644 index 55f3b267..00000000 --- a/app/Classes/Modules/Jobs/Services/ListsJobResult.php +++ /dev/null @@ -1,33 +0,0 @@ -repository = $repository; - } - - - /** - * @return Builder - */ - function getRepository(): Builder - { - return $this->repository->newQuery(); - } -} diff --git a/app/Classes/Modules/Jobs/Services/UpdatesJobResult.php b/app/Classes/Modules/Jobs/Services/UpdatesJobResult.php deleted file mode 100644 index ab3d9385..00000000 --- a/app/Classes/Modules/Jobs/Services/UpdatesJobResult.php +++ /dev/null @@ -1,28 +0,0 @@ -result = $updateJobResultObject->getResult(); - $model->result_signature = $updateJobResultObject->getResultSignature(); - $model->job_command_name = $updateJobResultObject->getJobCommandName(); - $model->job_command = $updateJobResultObject->getJobCommand(); - - return $this->handler($model); - - } -} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php deleted file mode 100644 index 654a360f..00000000 --- a/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php +++ /dev/null @@ -1,74 +0,0 @@ - 'List Transaction Job', - 'message' => 'You have successfully submit a job to list transactions' - ]; - } - - /** @var CreatesJobResult */ - private $createsJobResult; - - /** - * ListTransactionsJobLogic constructor. - * @param CreatesJobResult $createsJobResult - */ - public function __construct(CreatesJobResult $createsJobResult) - { - $this->createsJobResult = $createsJobResult; - } - - - /** - * @param Request $request - * @return JsonResponse - */ - public function logic(Request $request) : JsonResponse - { - $jobId = uniqid(); - - $user = Auth::user(); - $userInfo = (object) [ - 'type' => $user->type, - ]; - - $userInfoJson = json_encode($userInfo); - $requestSignature = md5($userInfoJson . $request->fullUrl()); - - $listGenericJobObject = new ListGenericJobObject( - $request->fullUrl(), - $request->all(), - $requestSignature, - null, - $jobId, - $userInfo - ); - - ListTransactionsJob::dispatch($listGenericJobObject); - - $result = []; - $result['job_id'] = $jobId; - - $this->createsJobResult->execute($listGenericJobObject); - - return $this->response(['data' => $result]); - } - -} diff --git a/app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php b/app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php deleted file mode 100644 index 475d4715..00000000 --- a/app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php +++ /dev/null @@ -1,45 +0,0 @@ -listsTransactions = $listsTransactions; - $this->updateJobResultProcessor = $updateJobResultProcessor; - } - - /** - * @param ListGenericJobObject $listGenericJobObject - * @return void - * @throws \App\Classes\Exceptions\MalformedRequestException - * @throws \App\Classes\Exceptions\JobResourceNotFoundException - */ - public function execute(ListGenericJobObject $listGenericJobObject) { - - $query = $this->listsTransactions->execute($this->listsTransactions->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page']]); - - $resultCurrent = Helper::collectionResponse(ListTransactionJobResource::collection($query)); - $this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent); - } -} - diff --git a/app/Http/Controllers/Bookings/ListBookingsJobController.php b/app/Http/Controllers/Bookings/ListBookingsJobController.php deleted file mode 100644 index 9b32fc77..00000000 --- a/app/Http/Controllers/Bookings/ListBookingsJobController.php +++ /dev/null @@ -1,22 +0,0 @@ -execute($request); - } -} diff --git a/app/Http/Controllers/Documents/ListDocumentsJobController.php b/app/Http/Controllers/Documents/ListDocumentsJobController.php deleted file mode 100644 index 8b763085..00000000 --- a/app/Http/Controllers/Documents/ListDocumentsJobController.php +++ /dev/null @@ -1,19 +0,0 @@ -execute($request); - } -} diff --git a/app/Http/Controllers/Jobs/FetchJobResultController.php b/app/Http/Controllers/Jobs/FetchJobResultController.php deleted file mode 100644 index cfef2f5c..00000000 --- a/app/Http/Controllers/Jobs/FetchJobResultController.php +++ /dev/null @@ -1,19 +0,0 @@ -execute($request); - } -} diff --git a/app/Http/Controllers/Transactions/ListTransactionsJobController.php b/app/Http/Controllers/Transactions/ListTransactionsJobController.php deleted file mode 100644 index fb341d5d..00000000 --- a/app/Http/Controllers/Transactions/ListTransactionsJobController.php +++ /dev/null @@ -1,21 +0,0 @@ -execute($request); - } -} diff --git a/app/Http/Resources/BookingResource.php b/app/Http/Resources/BookingResource.php index 70fbc95c..f3a7881d 100644 --- a/app/Http/Resources/BookingResource.php +++ b/app/Http/Resources/BookingResource.php @@ -11,9 +11,11 @@ use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\ValueObjects\Constants\DocumentType; use Carbon\Carbon; use Illuminate\Http\Resources\Json\JsonResource; +use Illuminate\Support\Facades\Log; class BookingResource extends JsonResource { + /** * Transform the resource into an array. * diff --git a/app/Http/Resources/CompanyResource.php b/app/Http/Resources/CompanyResource.php index eff2bd1b..85ecee16 100644 --- a/app/Http/Resources/CompanyResource.php +++ b/app/Http/Resources/CompanyResource.php @@ -15,6 +15,7 @@ use App\Models\SegmentConstant; use Carbon\Carbon; use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Log; class CompanyResource extends JsonResource { diff --git a/app/Http/Resources/DocumentResource.php b/app/Http/Resources/DocumentResource.php index c0f801bb..59933a67 100644 --- a/app/Http/Resources/DocumentResource.php +++ b/app/Http/Resources/DocumentResource.php @@ -3,7 +3,10 @@ namespace App\Http\Resources; use App\Models\Booking; +use App\Models\Company; +use App\Models\Document; use Carbon\Carbon; +use Illuminate\Database\Eloquent\Model; use Illuminate\Http\Resources\Json\JsonResource; class DocumentResource extends JsonResource diff --git a/app/Http/Resources/JobResultResource.php b/app/Http/Resources/JobResultResource.php deleted file mode 100644 index 51bc1898..00000000 --- a/app/Http/Resources/JobResultResource.php +++ /dev/null @@ -1,22 +0,0 @@ - $this->job_id, - 'result' => $this->result, - ]; - } -} diff --git a/app/Http/Resources/ListBookingJobResource.php b/app/Http/Resources/ListBookingJobResource.php deleted file mode 100644 index 06f8c38d..00000000 --- a/app/Http/Resources/ListBookingJobResource.php +++ /dev/null @@ -1,81 +0,0 @@ -userInfo = $userInfo ?? ($resource->userInfo ?? null); - } - - /** - * Transform the resource into an array. - * - * @param \Illuminate\Http\Request $request - * @return array - * @throws \Illuminate\Contracts\Container\BindingResolutionException - */ - public function toArray($request) - { - return [ - 'id' => $this->id, - 'company' => new CompanyResource($this->company, $this->userInfo), - 'bank' => new BankResource($this->bank), - 'service' => new ServiceTypeResource($this->service), - 'marking' => $this->marking, - 'amount' => $this->fix_amount, - 'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)), - 'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), - 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), - 'fixed_currency' => new CurrencyResource($this->fixedCurrency), - 'convertible_currency' => new CurrencyResource($this->convertibleCurrency), - 'conversion_currency' => new CurrencyResource($this->conversionCurrency), - 'documents' => [ - 'purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::PURCHASE_ORDER)->first()), - 'delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER)->first()), - 'invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::INVOICE)->first()), - 'supplier_delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->first()), - 'proforma_invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()), - 'ecommerce_purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->first()), - ], - 'status' => $this->status, - 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'), - 'created_at_with_time' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), - $this->mergeWhen($this->relationLoaded('transactions'), [ - 'purchase_order' => new TransactionResource($this->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first()), - 'payment_attempts' => TransactionResource::collection( - $this->transactions() - ->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION) - ->whereDate('expires_on', '>=', Carbon::now()) - ->get() - ), - 'expired_payment_attempts' => TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString())->get()), - 'payment_history' => TransactionResource::collection($this->transactions()->where(function($query){ - $query->where(function($query){ - $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]); - })->orWhere(function($query){ - $query->where(function($query){ - $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]); - })->orWhere(function($query){ - $query->where('type', TransactionType::CREDIT_NOTE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); - }); - }); - })->latest()->get()) - ]) - ]; - } -} diff --git a/app/Http/Resources/ListDocumentJobResource.php b/app/Http/Resources/ListDocumentJobResource.php deleted file mode 100644 index edf549ef..00000000 --- a/app/Http/Resources/ListDocumentJobResource.php +++ /dev/null @@ -1,31 +0,0 @@ - $this->id, - 'reference' => $this->reference, - 'status' => (int) $this->status, - 'document_type' => $this->document_type, - 'owner' => $this->relationLoaded('owner') ? ($this->owner instanceof Booking ? new BookingV2Resource($this->owner, $this->userInfo) : new CompanyV2Resource($this->owner, $this->userInfo)) : null, - 'files' => FileResource::collection($this->files), - 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A') - ]; - } -} diff --git a/app/Http/Resources/ListTransactionJobResource.php b/app/Http/Resources/ListTransactionJobResource.php deleted file mode 100644 index 6c4c0ece..00000000 --- a/app/Http/Resources/ListTransactionJobResource.php +++ /dev/null @@ -1,54 +0,0 @@ -type, [TransactionType::BILL, TransactionType::REFUND])? $this->owner->owner : $this->owner; - $days = $this->created_at->endOfDay()->addWeekdays($booking->service_id === 3 ? 3 : 1); - - return [ - 'id' => $this->id, - 'booking' => new BookingResource($booking), - 'type' => (int) $this->type, - 'bill_no' => $this->bill_no, - 'payment_reference' => $this->payment_reference, - 'payment_method' => (float) $this->payment_method, - 'recipient_bank_account' => new BankResource($booking->bank), - 'issuer_name' => $this->issuerCompany->name, - 'issuer_id' => $this->issuerCompany->id, - 'amount' => (double) $this->amount, - 'original_amount' => (double) $this->original_amount, - 'currency' => new CurrencyResource($this->currency), - 'original_currency' => new CurrencyResource($this->original_currency), - 'service_charge' => (double) $this->service_charge, - 'tax' => (double) $this->tax, - 'currency_rate' => (double) $this->currency_rate, - 'status' => (int) $this->status, - 'details' => TransactionDetailResource::collection($this->transactionDetails), - 'documents' => new DocumentResource($this->documents()->first()), - 'transaction_bill' => new TransactionResource($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->bills()->first())), - 'transaction_refunds' => TransactionResource::collection($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->refunds()->get())), - 'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'), - 'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'), - 'interval' => [ - 'value' => $days->gt(Carbon::now()) ? '+' : '-', - 'duration' => $days->diff(Carbon::now())->format('%d'), - ], - 'redemption' => new VoucherRedemptionResource($this->voucherRedemption) - ]; - } -} diff --git a/app/Http/Resources/V2/BookingV2Resource.php b/app/Http/Resources/V2/BookingV2Resource.php deleted file mode 100644 index ee17181e..00000000 --- a/app/Http/Resources/V2/BookingV2Resource.php +++ /dev/null @@ -1,82 +0,0 @@ -userInfo = $userInfo ?? ($resource->userInfo ?? null); - } - - /** - * Transform the resource into an array. - * - * @param \Illuminate\Http\Request $request - * @return array - * @throws \Illuminate\Contracts\Container\BindingResolutionException - */ - public function toArray($request) - { - return [ - 'id' => $this->id, - 'company' => new CompanyV2Resource($this->company, $this->userInfo), - 'bank' => new V1\BankResource($this->bank), - 'service' => new V1\ServiceTypeResource($this->service), - 'marking' => $this->marking, - 'amount' => $this->fix_amount, - 'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)), - 'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), - 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), - 'fixed_currency' => new V1\CurrencyResource($this->fixedCurrency), - 'convertible_currency' => new V1\CurrencyResource($this->convertibleCurrency), - 'conversion_currency' => new V1\CurrencyResource($this->conversionCurrency), - 'documents' => [ - 'purchase_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::PURCHASE_ORDER)->first()), - 'delivery_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER)->first()), - 'invoice' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::INVOICE)->first()), - 'supplier_delivery_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->first()), - 'proforma_invoice' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()), - 'ecommerce_purchase_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->first()), - ], - 'status' => $this->status, - 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'), - 'created_at_with_time' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), - $this->mergeWhen($this->relationLoaded('transactions'), [ - 'purchase_order' => new V1\TransactionResource($this->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first()), - 'payment_attempts' => V1\TransactionResource::collection( - $this->transactions() - ->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION) - ->whereDate('expires_on', '>=', Carbon::now()) - ->get() - ), - 'expired_payment_attempts' => V1\TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString())->get()), - 'payment_history' => V1\TransactionResource::collection($this->transactions()->where(function($query){ - $query->where(function($query){ - $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]); - })->orWhere(function($query){ - $query->where(function($query){ - $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]); - })->orWhere(function($query){ - $query->where('type', TransactionType::CREDIT_NOTE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); - }); - }); - })->latest()->get()) - ]) - ]; - } -} diff --git a/app/Http/Resources/V2/CompanyV2Resource.php b/app/Http/Resources/V2/CompanyV2Resource.php deleted file mode 100644 index 64fca7c7..00000000 --- a/app/Http/Resources/V2/CompanyV2Resource.php +++ /dev/null @@ -1,100 +0,0 @@ -userInfo = $userInfo; - } - - /** - * Transform the resource into an array. - * - * @param \Illuminate\Http\Request $request - * @return array - */ - public function toArray($request) - { - $lastPayment = $this->transactions()->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->orderBy('id', 'DESC')->first(); - $totalPayments = $this->transactions()->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount'); - - $segment = SegmentConstant::where('reference', SegmentConstants::SUPPLIER_CURRENCIES)->where('detail->id', $this->id)->first(); - $serviceCharge = SegmentConstant::where('reference', SegmentConstants::SERVICE_CHARGE)->where('detail->id', $this->id)->first(); - - $userResource = null; - - $userInfoEmail = $this->userInfo && isset($this->userInfo->email) ? $this->userInfo->email : null; - $userInfoType = $this->userInfo && isset($this->userInfo->type) ? $this->userInfo->type : null; - - if(!$userInfoEmail && Auth::user()){ - $userInfoEmail = Auth::user()->email; - } - if(!$userInfoType && Auth::user()){ - $userInfoType = Auth::user()->type; - } - - if(!is_null($userInfoEmail) && !is_null($userInfoType)){ - $userResource = new V1\UserResource($userInfoType === RoleTypes::USER ? $this->employees()->where('email', '=', $userInfoEmail)->first() : $this->employees()->orderBy('id', 'DESC')->first()); - } - - return [ - 'id' => $this->id, - 'name' => $this->name, - 'reference' => $this->reference, - 'debtor' => $this->debtor, - 'type' => (int) $this->type, - 'business_type' => (int) $this->business_type, - 'status' => (int) $this->status, - 'contact' => new V1\ContactResource ($this->when($this->has('contacts'), $this->contacts->first())), - 'address' => new V1\AddressResource($this->when($this->has('addresses'), $this->addresses->where('billing', true)->first())), - 'employee' => $userResource, - 'identification' => new V1\DocumentResource($this->documents->whereIn('document_type', DocumentType::IDENTIFICATION_DOCUMENTS)->first()), - 'bookings' => $this->whenLoaded('bookings', $this->bookings()->orderBy('id', 'DESC')->get(), []), - 'confirmed_bookings' => $this->bookings()->whereHas('transactions', function ($query){ - $query->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); - })->count(), - 'total_payments' => (float) $totalPayments, - 'average_spending_per_day' => (float) $totalPayments / ($this->created_at->diff(Carbon::now())->days === 0 ? 1 : $this->created_at->diff(Carbon::now())->days), - 'average_spending_per_booking' => (float) $totalPayments > 0 ? $totalPayments / $this->bookings()->whereHas('transactions', function ($query){ - $query->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); - })->count() : $totalPayments, - 'last_payment' => $lastPayment ? $lastPayment->created_at->diffForHumans() : 'No Payments', - 'personal_banks' => V1\BankResource::collection($this->banks->where('type', BankAccountType::PERSONAL)), - 'recipient_banks' => [ - 'accounts' => V1\BankResource::collection($this->banks->where('type', BankAccountType::EXTERNAL)), - 'default' => new V1\BankResource($this->banks->where('type', BankAccountType::EXTERNAL)->where('default', true)->first()) - ], - 'segments' => V1\SegmentResource::collection($this->segments), - 'seasonalSegment' => $this->whenLoaded('seasonalSegments', V1\SeasonalSegmentResource::collection($this->seasonalSegments)), - 'services' => (new FetchesCompanyServices())->getServices($this->servicesConfigurations()), - 'wallet' => $this->whenLoaded('wallets', new V1\WalletResource($this->wallets()->with('transactions')->first()), new V1\WalletResource($this->wallets()->first())), - 'created_at' => $this->created_at->format('d-m-Y'), - $this->mergeWhen($this->business_type === BusinessType::CURRENCY_VENDOR, [ - 'currencies' => $segment ? V1\CurrencyResource::collection(Currency::whereIn('id', $segment->detail->currencies)->get()) : [], - 'service_charge' => $serviceCharge - ]) - - ]; - } -} diff --git a/app/Models/JobResult.php b/app/Models/JobResult.php deleted file mode 100644 index f30b5076..00000000 --- a/app/Models/JobResult.php +++ /dev/null @@ -1,13 +0,0 @@ -id(); - $table->string('job_id', 50); - $table->longText('result')->nullable(); - $table->timestamps(); - - // $table->foreign('job_id')->references('id')->on('jobs')->onDelete('cascade'); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('job_results'); - } -} diff --git a/database/migrations/2023_08_29_063531_add_new_column_to_job_results_table.php b/database/migrations/2023_08_29_063531_add_new_column_to_job_results_table.php deleted file mode 100644 index 8e6b8342..00000000 --- a/database/migrations/2023_08_29_063531_add_new_column_to_job_results_table.php +++ /dev/null @@ -1,36 +0,0 @@ -longText('url')->after('result')->nullable(); - $table->string('job_command_name')->after('url')->nullable(); - $table->longText('job_command')->after('job_command_name')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::table('job_results', function (Blueprint $table) { - $table->dropColumn('url'); - $table->dropColumn('job_command_name'); - $table->dropColumn('job_command'); - }); - } -} diff --git a/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php b/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php deleted file mode 100644 index 12c6d57f..00000000 --- a/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php +++ /dev/null @@ -1,34 +0,0 @@ -string('request_signature')->after('job_id')->nullable(); - $table->string('result_signature')->after('request_signature')->nullable(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::table('job_results', function (Blueprint $table) { - $table->dropColumn('request_signature'); - $table->dropColumn('result_signature'); - }); - } -} diff --git a/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue b/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue deleted file mode 100644 index 966ccbbc..00000000 --- a/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue +++ /dev/null @@ -1,136 +0,0 @@ - - diff --git a/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionPollingComponent.vue b/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionPollingComponent.vue deleted file mode 100644 index 47d14857..00000000 --- a/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionPollingComponent.vue +++ /dev/null @@ -1,136 +0,0 @@ - - diff --git a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue index d2b69080..7df9c125 100644 --- a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue +++ b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue @@ -117,17 +117,11 @@
- -
@@ -171,7 +165,7 @@ } }, created(){ - this.submit(route('api.company.list') + '?filters=' + JSON.stringify({'business_type': 3, 'status_in': [1, 2, 0]}), 'get', 'pendingOrdersSection', false, false); //cief todo: Uncaught (in promise) null + this.submit(route('api.company.list') + '?filters=' + JSON.stringify({'business_type': 3, 'status_in': [1, 2, 0]}), 'get', 'pendingOrdersSection', false, false) }, methods: { successHandler(response){ @@ -216,4 +210,4 @@ } - + \ No newline at end of file diff --git a/resources/assets/vue/components/general/elements/ListPollingComponent.vue b/resources/assets/vue/components/general/elements/ListPollingComponent.vue deleted file mode 100644 index fcd3b8b8..00000000 --- a/resources/assets/vue/components/general/elements/ListPollingComponent.vue +++ /dev/null @@ -1,213 +0,0 @@ - - - diff --git a/resources/assets/vue/general/mixins/aws/requestV2.js b/resources/assets/vue/general/mixins/aws/requestV2.js deleted file mode 100644 index 12b27542..00000000 --- a/resources/assets/vue/general/mixins/aws/requestV2.js +++ /dev/null @@ -1,49 +0,0 @@ -export default { - methods: { - poll(url, method, section, successNotification = true, errorNotification = true){ - if(!this.validate()){ return; } - if (section) { - this.$store.dispatch('toggleLoading', {name: section, status: true}) - } - this.$store.dispatch('crudRequestV2', { - endpoint: url, - method: method, - parameters: this.parameters - }).then(response => { - let statusCode = response.status, - success = response.ok; - - response.json().then(response => { - - if(!success){ - this.openModal(); - errorNotification ? this.$store.dispatch('createNotification', {title: response.title, message: response.message, type: 'error'}): null; - this.errorHandler(response, statusCode); return; - } - - successNotification ? this.$store.dispatch('createNotification', {title: response.title, message: response.message, type: 'success'}): null; - this.successHandler(response) - - - }); - }).catch((error) => { - this.$store.dispatch('createNotification', {title: 'Unexpected Error', message: 'An unexpected error has occurred. Try again!', type: 'error'}); - }).then(() => { - if (section) { - this.$store.dispatch('toggleLoading', {name: section, status: false}) - } - }) - - }, - validate() { - if(this.$v){ - this.$v.$touch(); - return !this.$v.$invalid; - } - return true; - }, - successHandler(response){}, - errorHandler(response){} - } - -} diff --git a/resources/assets/vue/general/mixins/tabHandler.js b/resources/assets/vue/general/mixins/tabHandler.js deleted file mode 100644 index 81790ed0..00000000 --- a/resources/assets/vue/general/mixins/tabHandler.js +++ /dev/null @@ -1,24 +0,0 @@ -export default { - data() { - return { - activeTab: null, - displayedTabs: [], - }; - }, - methods: { - setActiveTab(event) { - const tabName = event.currentTarget.getAttribute('tab-name'); - // console.log(`Tab "${tabName}" clicked`); - this.activeTab = tabName; - if (!this.displayedTabs.includes(tabName)) { - this.displayedTabs.push(tabName); - } - }, - isActiveTab(tabName) { - return this.activeTab === tabName; - }, - showTabContent(tabName) { - return this.displayedTabs.includes(tabName); - }, - }, -} diff --git a/resources/assets/vue/vuex/modules/crudRequestV2.js b/resources/assets/vue/vuex/modules/crudRequestV2.js deleted file mode 100644 index 355b1edb..00000000 --- a/resources/assets/vue/vuex/modules/crudRequestV2.js +++ /dev/null @@ -1,51 +0,0 @@ -export default { - actions: { - crudRequestV2({getters, dispatch}, {endpoint, method, parameters}){ - return dispatch('ensureReCaptchaIsSet').then(function () { - const queryDomain = endpoint.split('?')[0]; - let encodedParams = endpoint.split('?')[1]; - let decodedParams = fullyDecodeURI(encodedParams); - const queryParams = encodeURIComponent(decodedParams); - encodedParams = queryParams.toString(); - let filteredEncodedParams = encodedParams.replace(/%3D/g,'='); - filteredEncodedParams = filteredEncodedParams.replace(/%26/g,'&'); - let combinedAbsoluteUrl = queryDomain; - if(filteredEncodedParams !== undefined && filteredEncodedParams !== 'undefined'){ - combinedAbsoluteUrl = queryDomain + '?' + filteredEncodedParams; - } - - // return fetch(endpoint, { - return fetch(combinedAbsoluteUrl, { - method: method, - responseType: 'json', - body: parameters ? JSON.stringify(parameters):null, - headers: { - 'content-type': 'application/json', - 'Authorization': 'Bearer '+getters.getAccessToken, - 'captcha-token': getters.getReCaptcha - } - }).then(response => { - - if(response.status === 401 && window.location.href !== route('login')){ - dispatch('userAuthentication', {access_token: '', redirect_url: '/'}); - } - - return response; - - }) - }); - } - } -} - -function isEncoded(uri) { - uri = uri || ''; - return uri !== decodeURIComponent(uri); -} - -function fullyDecodeURI(uri){ - while (isEncoded(uri)){ - uri = decodeURIComponent(uri); - } - return uri; -} diff --git a/resources/assets/vue/vuex/store.js b/resources/assets/vue/vuex/store.js index ff10c673..2c3d911b 100644 --- a/resources/assets/vue/vuex/store.js +++ b/resources/assets/vue/vuex/store.js @@ -4,7 +4,6 @@ import toggleSection from './modules/toggleSection' import toggleLoading from './modules/toggleLoading' import createNotification from './modules/createNotification' import crudRequest from './modules/crudRequest' -import crudRequestV2 from './modules/crudRequestV2' import authentication from './modules/authentication' import loadRequestQueue from './modules/loadRequestQueue' @@ -17,7 +16,6 @@ export default new Vuex.Store({ loadRequestQueue, createNotification, crudRequest, - crudRequestV2, authentication } -}) +}) \ No newline at end of file diff --git a/resources/views/pages/billings.blade.php b/resources/views/pages/billings.blade.php index da84f8b9..4bc012d5 100644 --- a/resources/views/pages/billings.blade.php +++ b/resources/views/pages/billings.blade.php @@ -3,7 +3,129 @@
- + +
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
Invoice
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
Purchase Order
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
Delivery Order
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
Supplier Delivery Order
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+
-@endsection +@endsection \ No newline at end of file diff --git a/resources/views/pages/billings_experiment.blade.php b/resources/views/pages/billings_experiment.blade.php deleted file mode 100644 index d1caee2d..00000000 --- a/resources/views/pages/billings_experiment.blade.php +++ /dev/null @@ -1,9 +0,0 @@ -@extends('layouts.base_portal') -@section('inner_content') -
-
- - -
-
-@endsection diff --git a/routes/api.php b/routes/api.php index 460bd772..8b4bada0 100644 --- a/routes/api.php +++ b/routes/api.php @@ -67,10 +67,6 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function require __DIR__ . '/milestone.php'; - // require __DIR__ . '/accounting.php'; //cief todo: To check if this is needed - - require __DIR__ . '/job.php'; - // require __DIR__ . '/rate.php'; // require __DIR__ . '/receipt.php'; diff --git a/routes/currency.php b/routes/currency.php index ba55c9a2..b621aad6 100644 --- a/routes/currency.php +++ b/routes/currency.php @@ -1,4 +1,4 @@ - 'document', 'as' => 'document.', 'namespace' => 'Documents'], function () { Route::get('/list', 'ListDocumentsController@list')->name('list'); - Route::get('/list/job', 'ListDocumentsJobController@list')->name('list.job'); Route::delete('/{id}/delete', 'DeleteDocumentController@delete')->name('delete'); Route::put('/{id}/approve', 'ApproveDocumentController@approve')->name('status.approve'); Route::put('/{id}/reject', 'RejectDocumentController@reject')->name('status.reject'); Route::put('/{id}/reference/update', 'UpdateDocumentReferenceController@update')->name('reference.update'); -}); +}); \ No newline at end of file diff --git a/routes/job.php b/routes/job.php deleted file mode 100644 index 028e9468..00000000 --- a/routes/job.php +++ /dev/null @@ -1,8 +0,0 @@ - 'job', 'as' => 'job.', 'namespace' => 'Jobs'], function () { - Route::get('/fetch/{job_id}', 'FetchJobResultController@fetch')->name('fetch'); - Route::get('/fetch/{job_id}/{is_last}', 'FetchJobResultController@fetch')->name('fetch.last.attempt'); -}); diff --git a/routes/web.php b/routes/web.php index a6590c17..bf2892bb 100644 --- a/routes/web.php +++ b/routes/web.php @@ -92,12 +92,6 @@ Route::get('/billings', function () { return view('pages.billings'); })->name('billings'); -/* Vue Polling Experiment - Starts */ -Route::get('/billings-experiment', function () { - return view('pages.billings_experiment'); -})->name('billings.experiment'); -/* Vue Polling Experiment - Ends */ - Route::get('/currency_orders', function () { return view('pages.currency_orders'); })->name('currency_orders'); @@ -836,13 +830,13 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, ->withTrashed() ->orderBy('created_at', 'asc') ->first(); - + // get the first bill_no $firstBillNo = $firstInvoice->bill_no; if (strpos($firstBillNo, '-deleted') !== false) { $firstBillNo = substr($firstBillNo, 0, strpos($firstBillNo, '-deleted')); } - + // update currentInvoice bill_no to '-deleted-' $currentInvoice = $booking->transactions()->where('type', TransactionType::INVOICE)->first(); $currentInvoice->bill_no = $currentInvoice->bill_no ."-deleted-" . Str::random(10); @@ -865,4 +859,4 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, } } ); -})->name('invoice.fix.byCustomerMarking'); +})->name('invoice.fix.byCustomerMarking'); \ No newline at end of file From f8230990f4f46348cd37551bd18fa1f75a2232d2 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sun, 11 Feb 2024 10:28:05 +0000 Subject: [PATCH 041/228] Revert "Merge branch 'revert-b9668bb6' into 'master'" This reverts merge request !157 --- .../JobResourceNotFoundException.php | 11 + .../Abstracts/AbstractControllerLogic.php | 15 +- .../General/Eloquent/AbstractFetchRecord.php | 14 +- .../General/Eloquent/AbstractGetRecord.php | 26 ++- .../General/Eloquent/AbstractListRecord.php | 14 +- .../General/Eloquent/Filters/JobId.php | 20 ++ .../Eloquent/Filters/OrderByIdDesc.php | 20 ++ .../Eloquent/Filters/RequestSignature.php | 19 ++ .../Eloquent/Filters/ResultNotNull.php | 18 ++ app/Classes/General/Helper.php | 24 ++ app/Classes/Jobs/ListBookingsJob.php | 52 +++++ app/Classes/Jobs/ListDocumentsJob.php | 63 ++++++ app/Classes/Jobs/ListTransactionsJob.php | 52 +++++ .../ControllersLogic/ListBookingJobLogic.php | 75 ++++++ .../Processors/ListBookingsJobProcessor.php | 46 ++++ .../ControllersLogic/ListDocumentJobLogic.php | 75 ++++++ .../Processors/ListDocumentsJobProcessor.php | 47 ++++ .../ControllersLogic/FetchJobResultLogic.php | 51 +++++ .../ListGenericJobObject.php | 118 ++++++++++ .../UpdateJobResultObject.php | 60 +++++ .../Processors/FetchesJobResultProcessor.php | 47 ++++ .../Processors/UpdateJobResultProcessor.php | 64 ++++++ .../Jobs/Services/CreatesJobResult.php | 26 +++ .../Jobs/Services/FetchesJobResult.php | 33 +++ .../Modules/Jobs/Services/ListsJobResult.php | 33 +++ .../Jobs/Services/UpdatesJobResult.php | 28 +++ .../ListTransactionsJobLogic.php | 74 ++++++ .../ListTransactionsJobProcessor.php | 45 ++++ .../Bookings/ListBookingsJobController.php | 22 ++ .../Documents/ListDocumentsJobController.php | 19 ++ .../Jobs/FetchJobResultController.php | 19 ++ .../ListTransactionsJobController.php | 21 ++ app/Http/Resources/BookingResource.php | 2 - app/Http/Resources/CompanyResource.php | 1 - app/Http/Resources/DocumentResource.php | 3 - app/Http/Resources/JobResultResource.php | 22 ++ app/Http/Resources/ListBookingJobResource.php | 81 +++++++ .../Resources/ListDocumentJobResource.php | 31 +++ .../Resources/ListTransactionJobResource.php | 54 +++++ app/Http/Resources/V2/BookingV2Resource.php | 82 +++++++ app/Http/Resources/V2/CompanyV2Resource.php | 100 ++++++++ app/Models/JobResult.php | 13 ++ ..._08_08_124848_create_job_results_table.php | 35 +++ ...31_add_new_column_to_job_results_table.php | 36 +++ ..._add_new_column_2_to_job_results_table.php | 34 +++ .../AdminPaymentsBillingSectionComponent.vue | 136 +++++++++++ ...PaymentsBillingSectionPollingComponent.vue | 136 +++++++++++ .../SupplierPendingOrdersSectionComponent.vue | 10 +- .../general/elements/ListPollingComponent.vue | 213 ++++++++++++++++++ .../vue/general/mixins/aws/requestV2.js | 49 ++++ .../assets/vue/general/mixins/tabHandler.js | 24 ++ .../assets/vue/vuex/modules/crudRequestV2.js | 51 +++++ resources/assets/vue/vuex/store.js | 4 +- resources/views/pages/billings.blade.php | 126 +---------- .../views/pages/billings_experiment.blade.php | 9 + routes/api.php | 4 + routes/currency.php | 2 +- routes/document.php | 3 +- routes/job.php | 8 + routes/web.php | 12 +- 60 files changed, 2380 insertions(+), 152 deletions(-) create mode 100644 app/Classes/Exceptions/JobResourceNotFoundException.php create mode 100644 app/Classes/General/Eloquent/Filters/JobId.php create mode 100644 app/Classes/General/Eloquent/Filters/OrderByIdDesc.php create mode 100644 app/Classes/General/Eloquent/Filters/RequestSignature.php create mode 100644 app/Classes/General/Eloquent/Filters/ResultNotNull.php create mode 100644 app/Classes/Jobs/ListBookingsJob.php create mode 100644 app/Classes/Jobs/ListDocumentsJob.php create mode 100644 app/Classes/Jobs/ListTransactionsJob.php create mode 100644 app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php create mode 100644 app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php create mode 100644 app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php create mode 100644 app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php create mode 100644 app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php create mode 100644 app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php create mode 100644 app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php create mode 100644 app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php create mode 100644 app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php create mode 100644 app/Classes/Modules/Jobs/Services/CreatesJobResult.php create mode 100644 app/Classes/Modules/Jobs/Services/FetchesJobResult.php create mode 100644 app/Classes/Modules/Jobs/Services/ListsJobResult.php create mode 100644 app/Classes/Modules/Jobs/Services/UpdatesJobResult.php create mode 100644 app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php create mode 100644 app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php create mode 100644 app/Http/Controllers/Bookings/ListBookingsJobController.php create mode 100644 app/Http/Controllers/Documents/ListDocumentsJobController.php create mode 100644 app/Http/Controllers/Jobs/FetchJobResultController.php create mode 100644 app/Http/Controllers/Transactions/ListTransactionsJobController.php create mode 100644 app/Http/Resources/JobResultResource.php create mode 100644 app/Http/Resources/ListBookingJobResource.php create mode 100644 app/Http/Resources/ListDocumentJobResource.php create mode 100644 app/Http/Resources/ListTransactionJobResource.php create mode 100644 app/Http/Resources/V2/BookingV2Resource.php create mode 100644 app/Http/Resources/V2/CompanyV2Resource.php create mode 100644 app/Models/JobResult.php create mode 100644 database/migrations/2023_08_08_124848_create_job_results_table.php create mode 100644 database/migrations/2023_08_29_063531_add_new_column_to_job_results_table.php create mode 100644 database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php create mode 100644 resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue create mode 100644 resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionPollingComponent.vue create mode 100644 resources/assets/vue/components/general/elements/ListPollingComponent.vue create mode 100644 resources/assets/vue/general/mixins/aws/requestV2.js create mode 100644 resources/assets/vue/general/mixins/tabHandler.js create mode 100644 resources/assets/vue/vuex/modules/crudRequestV2.js create mode 100644 resources/views/pages/billings_experiment.blade.php create mode 100644 routes/job.php diff --git a/app/Classes/Exceptions/JobResourceNotFoundException.php b/app/Classes/Exceptions/JobResourceNotFoundException.php new file mode 100644 index 00000000..a8ef358e --- /dev/null +++ b/app/Classes/Exceptions/JobResourceNotFoundException.php @@ -0,0 +1,11 @@ +getMessage(), + $exception->getTrace()[0]['file'], + $exception->getTrace()[0]['line'] + )); + } + else{ + log::error($exception); + } + return (new ApiResponseObject($this->getNotificationTitle().' failed', $exception->getMessage(), $exception->getCode() ? $exception->getCode() : HttpStatus::SERVER_ERROR))->handler(); diff --git a/app/Classes/General/Eloquent/AbstractFetchRecord.php b/app/Classes/General/Eloquent/AbstractFetchRecord.php index 248deee7..503fb369 100644 --- a/app/Classes/General/Eloquent/AbstractFetchRecord.php +++ b/app/Classes/General/Eloquent/AbstractFetchRecord.php @@ -4,9 +4,11 @@ namespace App\Classes\General\Eloquent; use App\Classes\Exceptions\ResourceNotFoundException; +use App\Classes\Exceptions\JobResourceNotFoundException; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Psy\Exception\ErrorException; +use Illuminate\Support\Facades\Log; abstract class AbstractFetchRecord extends AbstractGetRecord { @@ -27,12 +29,18 @@ abstract class AbstractFetchRecord extends AbstractGetRecord * @return Model * @throws ResourceNotFoundException */ - public function getResults(Builder $query): Model { + public function getResults(Builder $query, array $param = []): Model { if(!$query->exists()){ - throw new ResourceNotFoundException('Unable to find any record based on the criteria provided'); + $table = $query->getModel()->getTable(); + if($table ==='job_results'){ + throw new JobResourceNotFoundException('Unable to find any job based on the criteria provided'); + } + else{ + throw new ResourceNotFoundException('Unable to find any record based on the criteria provided'); + } } return $query->first(); } -} \ No newline at end of file +} diff --git a/app/Classes/General/Eloquent/AbstractGetRecord.php b/app/Classes/General/Eloquent/AbstractGetRecord.php index f927d818..1a7eac3e 100644 --- a/app/Classes/General/Eloquent/AbstractGetRecord.php +++ b/app/Classes/General/Eloquent/AbstractGetRecord.php @@ -30,11 +30,25 @@ abstract class AbstractGetRecord return $this->filters->only(self::DECORATION_FILTERS); } + // /** + // * @param null|string $json + // * @return array + // */ + // public function deserializeFilters(?string $json): array { + // return $json !== null ? collect(json_decode($json))->toArray() : []; + // } + /** - * @param null|string $json + * @param null|string $param * @return array */ - public function deserializeFilters(?string $json): array { + public function deserializeFilters($param): array { + if(gettype($param) == "array"){ + $json = implode(',', $param); + } + else{ + $json = $param; + } return $json !== null ? collect(json_decode($json))->toArray() : []; } @@ -50,9 +64,9 @@ abstract class AbstractGetRecord * @param array $filters * @return mixed */ - public function handler(array $filters){ + public function handler(array $filters, array $params = []){ $this->filters = collect($filters); - return $this->getResults($this->applyFiltersToQuery()); + return $this->getResults($this->applyFiltersToQuery(), $params); } @@ -65,6 +79,6 @@ abstract class AbstractGetRecord * @param Builder $query * @return mixed */ - abstract function getResults(Builder $query); + abstract function getResults(Builder $query, array $params = []); -} \ No newline at end of file +} diff --git a/app/Classes/General/Eloquent/AbstractListRecord.php b/app/Classes/General/Eloquent/AbstractListRecord.php index 7b7d0df9..f898f108 100644 --- a/app/Classes/General/Eloquent/AbstractListRecord.php +++ b/app/Classes/General/Eloquent/AbstractListRecord.php @@ -17,11 +17,11 @@ abstract class AbstractListRecord extends AbstractGetRecord * @return mixed * @throws MalformedRequestException */ - public function execute(array $filters = []){ + public function execute(array $filters = [], array $param = []){ try{ - return $this->handler($filters); + return $this->handler($filters, $param); } catch (QueryException $exception){ log::error($exception); @@ -30,18 +30,24 @@ abstract class AbstractListRecord extends AbstractGetRecord } + /** * @param Builder $query * @return mixed */ - public function getResults(Builder $query) { + public function getResults(Builder $query, array $param = []) { $filters = $this->getDecorationFilters(); if($filters->has('order_by')){ $query = $query->orderBy($filters->get('order_by')->column, $filters->get('order_by')->DESC ? 'DESC': 'ASC'); } - return $filters->has('per_page') ? $query->paginate($filters->get('per_page')) : $query->get(); + if(!empty($param)){ + return $filters->has('per_page') ? $query->paginate($filters->get('per_page'), ['*'], 'page', $param['page']) : $query->get(); //page data from query parameters e.g ?page=1 + } + else{ + return $filters->has('per_page') ? $query->paginate($filters->get('per_page')) : $query->get(); + } } diff --git a/app/Classes/General/Eloquent/Filters/JobId.php b/app/Classes/General/Eloquent/Filters/JobId.php new file mode 100644 index 00000000..42ac51a4 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/JobId.php @@ -0,0 +1,20 @@ +where('job_id', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php b/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php new file mode 100644 index 00000000..547ec9bd --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php @@ -0,0 +1,20 @@ +orderBy('id', 'desc'); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/RequestSignature.php b/app/Classes/General/Eloquent/Filters/RequestSignature.php new file mode 100644 index 00000000..67dde0a3 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/RequestSignature.php @@ -0,0 +1,19 @@ +where('request_signature', $value); + } + +} diff --git a/app/Classes/General/Eloquent/Filters/ResultNotNull.php b/app/Classes/General/Eloquent/Filters/ResultNotNull.php new file mode 100644 index 00000000..3f6a0341 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/ResultNotNull.php @@ -0,0 +1,18 @@ +whereNotNull('result'); + } +} diff --git a/app/Classes/General/Helper.php b/app/Classes/General/Helper.php index ac89540b..45c72f53 100644 --- a/app/Classes/General/Helper.php +++ b/app/Classes/General/Helper.php @@ -2,6 +2,7 @@ namespace App\Classes\General; +use Illuminate\Http\Resources\Json\ResourceCollection; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; @@ -42,4 +43,27 @@ class Helper } } } + + /** + * @param null|string $param + * @return array + */ + static function deserializeFilters($param): array { + if(gettype($param) == "array"){ + $json = implode(',', $param); + } + else{ + $json = $param; + } + return $json !== null ? collect(json_decode($json))->toArray() : []; + } + + /** + * @param ResourceCollection $collection + * @return array + */ + static function collectionResponse(ResourceCollection $collection){ + return json_decode($collection->response()->getContent(), true); + } + } diff --git a/app/Classes/Jobs/ListBookingsJob.php b/app/Classes/Jobs/ListBookingsJob.php new file mode 100644 index 00000000..b021b71d --- /dev/null +++ b/app/Classes/Jobs/ListBookingsJob.php @@ -0,0 +1,52 @@ +listGenericJobObject = $listGenericJobObject; + } + + public function handle() + { + $rawPayload = $this->job->payload(); + if(isset($rawPayload['data']['commandName'])){ + $this->listGenericJobObject->setJobCommandName($rawPayload['data']['commandName']); + } + + if(isset($rawPayload['data']['command'])){ + $this->listGenericJobObject->setJobCommand($rawPayload['data']['command']); + } + + $result = (App()->make(ListBookingsJobProcessor::class))->execute($this->listGenericJobObject); + } + + public function getJobId(){ + return $this->job->getJobId(); + } +} diff --git a/app/Classes/Jobs/ListDocumentsJob.php b/app/Classes/Jobs/ListDocumentsJob.php new file mode 100644 index 00000000..6e93062b --- /dev/null +++ b/app/Classes/Jobs/ListDocumentsJob.php @@ -0,0 +1,63 @@ +listGenericJobObject = $listGenericJobObject; + } + + public function handle() + { + $rawPayload = $this->job->payload(); + if(isset($rawPayload['data']['commandName'])){ + $this->listGenericJobObject->setJobCommandName($rawPayload['data']['commandName']); + } + + if(isset($rawPayload['data']['command'])){ + $this->listGenericJobObject->setJobCommand($rawPayload['data']['command']); + } + + $result = (App()->make(ListDocumentsJobProcessor::class))->execute($this->listGenericJobObject); + + //cief todo: Insert into DB: job id, query result, timestamp + // Store the result in the job_results table + + //cief todo: why cannot save data in table like this + // $model = new JobResult(); + // $model->job_id = $this->job->getJobId(); + // $model->result = json_encode($result); + // $model->save(); + + // Log::error(json_encode($model->id)); + } + + public function getJobId(){ + return $this->job->getJobId(); + } +} diff --git a/app/Classes/Jobs/ListTransactionsJob.php b/app/Classes/Jobs/ListTransactionsJob.php new file mode 100644 index 00000000..a2b28656 --- /dev/null +++ b/app/Classes/Jobs/ListTransactionsJob.php @@ -0,0 +1,52 @@ +listGenericJobObject = $listGenericJobObject; + } + + public function handle() + { + $rawPayload = $this->job->payload(); + if(isset($rawPayload['data']['commandName'])){ + $this->listGenericJobObject->setJobCommandName($rawPayload['data']['commandName']); + } + + if(isset($rawPayload['data']['command'])){ + $this->listGenericJobObject->setJobCommand($rawPayload['data']['command']); + } + + $result = (App()->make(ListTransactionsJobProcessor::class))->execute($this->listGenericJobObject); + } + + public function getJobId(){ + return $this->job->getJobId(); + } +} diff --git a/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php new file mode 100644 index 00000000..ef3570f7 --- /dev/null +++ b/app/Classes/Modules/Bookings/ControllersLogic/ListBookingJobLogic.php @@ -0,0 +1,75 @@ + 'List Booking Job', + 'message' => 'You have successfully submit a job to list bookings' + ]; + } + + /** @var CreatesJobResult */ + private $createsJobResult; + + /** + * ListPackingListsJobLogic constructor. + * @param CreatesJobResult $createsJobResult + */ + public function __construct(CreatesJobResult $createsJobResult) + { + $this->createsJobResult = $createsJobResult; + } + + + /** + * @param Request $request + * @return JsonResponse + */ + public function logic(Request $request) : JsonResponse + { + $jobId = uniqid(); + + $user = Auth::user(); + $userInfo = (object) [ + 'type' => $user->type, + ]; + + $userInfoJson = json_encode($userInfo); + $requestSignature = md5($userInfoJson . $request->fullUrl()); + + $listGenericJobObject = new ListGenericJobObject( + $request->fullUrl(), + $request->all(), + $requestSignature, + null, + $jobId, + $userInfo + ); + + ListBookingsJob::dispatch($listGenericJobObject); + + $result = []; + $result['job_id'] = $jobId; + + $this->createsJobResult->execute($listGenericJobObject); + + return $this->response(['data' => $result]); + } + +} diff --git a/app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php b/app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php new file mode 100644 index 00000000..2a09eb12 --- /dev/null +++ b/app/Classes/Modules/Bookings/Processors/ListBookingsJobProcessor.php @@ -0,0 +1,46 @@ +listsBookings = $listsBookings; + $this->updateJobResultProcessor = $updateJobResultProcessor; + } + + /** + * @param ListGenericJobObject $listGenericJobObject + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException + */ + public function execute(ListGenericJobObject $listGenericJobObject) { + + $query = $this->listsBookings->execute($this->listsBookings->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page']]); + foreach ($query->items() as &$item) { + $item['userInfo'] = $listGenericJobObject->getUserInfo(); + } + $resultCurrent = Helper::collectionResponse(ListBookingJobResource::collection($query)); + $this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent); + } +} diff --git a/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php b/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php new file mode 100644 index 00000000..5e895ad8 --- /dev/null +++ b/app/Classes/Modules/Documents/ControllersLogic/ListDocumentJobLogic.php @@ -0,0 +1,75 @@ + 'List Document Job', + 'message' => 'You have successfully submit a job to list documents' + ]; + } + + /** @var CreatesJobResult */ + private $createsJobResult; + + /** + * ListDocumentJobLogic constructor. + * @param CreatesJobResult $createsJobResult + */ + public function __construct(CreatesJobResult $createsJobResult) + { + $this->createsJobResult = $createsJobResult; + } + + + /** + * @param Request $request + * @return JsonResponse + */ + public function logic(Request $request) : JsonResponse + { + $jobId = uniqid(); + + $user = Auth::user(); + $userInfo = (object) [ + 'email' => $user->email, + 'type' => $user->type, + ]; + + $userInfoJson = json_encode($userInfo); + $requestSignature = md5($userInfoJson . $request->fullUrl()); + + $listGenericJobObject = new ListGenericJobObject( + $request->fullUrl(), + $request->all(), + $requestSignature, + null, + $jobId, + $userInfo + ); + + ListDocumentsJob::dispatch($listGenericJobObject); + + $result = []; + $result['job_id'] = $jobId; + + $this->createsJobResult->execute($listGenericJobObject); + + return $this->response(['data' => $result]); + } +} diff --git a/app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php b/app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php new file mode 100644 index 00000000..70777f0c --- /dev/null +++ b/app/Classes/Modules/Documents/Processors/ListDocumentsJobProcessor.php @@ -0,0 +1,47 @@ +listsDocuments = $listsDocuments; + $this->updateJobResultProcessor = $updateJobResultProcessor; + } + + /** + * @param ListGenericJobObject $listGenericJobObject + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException + */ + public function execute(ListGenericJobObject $listGenericJobObject) { + + $query = $this->listsDocuments->execute($this->listsDocuments->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page']]); + foreach ($query->items() as &$item) { + $item['userInfo'] = $listGenericJobObject->getUserInfo(); + } + $resultCurrent = Helper::collectionResponse(ListDocumentJobResource::collection($query)); + $this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent); + } +} + diff --git a/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php b/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php new file mode 100644 index 00000000..c4b72cf0 --- /dev/null +++ b/app/Classes/Modules/Jobs/ControllersLogic/FetchJobResultLogic.php @@ -0,0 +1,51 @@ + 'Retrieved Data', + 'message' => 'You have successfully retrieved data' + ]; + } + + /** @var FetchesJobResultProcessor */ + private $fetchesJobResultProcessor; + + /** + * FetchJobResultLogic constructor. + * @param FetchesJobResultProcessor $fetchesJobResultProcessor + */ + public function __construct(FetchesJobResultProcessor $fetchesJobResultProcessor) + { + $this->fetchesJobResultProcessor = $fetchesJobResultProcessor; + } + + + /** + * @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 + { + $query = $this->fetchesJobResultProcessor->execute($request); + return $this->resourceResponse(new JobResultResource($query)); + } + +} diff --git a/app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php b/app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php new file mode 100644 index 00000000..953d77d7 --- /dev/null +++ b/app/Classes/Modules/Jobs/DataTransferObjects/ListGenericJobObject.php @@ -0,0 +1,118 @@ +name = $name; + $this->payload = $payload; + $this->jobId = $jobId; + $this->requestSignature = $requestSignature; + $this->resultSignature = $resultSignature; + $this->userInfo = $userInfo; + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @return array + */ + public function getPayload(): array + { + return $this->payload; + } + + /** + * @return string + */ + public function getJobId(): string + { + return $this->jobId; + } + + /** + * @return string + */ + public function getRequestSignature(): string + { + return $this->requestSignature; + } + + /** + * @return string + */ + public function getResultSignature(): ?string + { + return $this->resultSignature; + } + + /** + * @return object + */ + public function getUserInfo(): object + { + return $this->userInfo; + } + + /** + * @return string + */ + public function getJobCommandName(): string + { + return $this->jobCommandName; + } + + /** + * @return string + */ + public function getJobCommand(): string + { + return $this->jobCommand; + } + + + public function setJobCommandName(string $jobCommandName) + { + $this->jobCommandName = $jobCommandName; + } + + public function setJobCommand(string $jobCommand) + { + $this->jobCommand = $jobCommand; + } + +} diff --git a/app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php b/app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php new file mode 100644 index 00000000..636c56b0 --- /dev/null +++ b/app/Classes/Modules/Jobs/DataTransferObjects/UpdateJobResultObject.php @@ -0,0 +1,60 @@ +result = $result; + $this->resultSignature = $resultSignature; + $this->jobCommandName = $jobCommandName; + $this->jobCommand = $jobCommand; + } + + /** + * @return string + */ + public function getResult(): string + { + return $this->result; + } + + /** + * @return array + */ + public function getResultSignature(): string + { + return $this->resultSignature; + } + + /** + * @return string + */ + public function getJobCommandName(): string + { + return $this->jobCommandName; + } + + /** + * @return string + */ + public function getJobCommand(): string + { + return $this->jobCommand; + } +} diff --git a/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php b/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php new file mode 100644 index 00000000..89783fe8 --- /dev/null +++ b/app/Classes/Modules/Jobs/Processors/FetchesJobResultProcessor.php @@ -0,0 +1,47 @@ +fetchesJobResult = $fetchesJobResult; + } + + + /** + * @param Request $request + * @return Model + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException + * @throws \App\Classes\Exceptions\ResourceNotFoundException + */ + public function execute(Request $request){ + + $res1 = $this->fetchesJobResult->execute(['job_id' => $request->route('job_id')]); + if($request->route('is_last')){ + $res2 = $this->fetchesJobResult->execute(['request_signature' => $res1->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]); + return $res2; + } + + if(!$res1->result){ + throw new JobResourceNotFoundException('Unable to find any job based on the criteria provided'); + } + + return $res1; + } +} diff --git a/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php b/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php new file mode 100644 index 00000000..0106417d --- /dev/null +++ b/app/Classes/Modules/Jobs/Processors/UpdateJobResultProcessor.php @@ -0,0 +1,64 @@ +fetchesJobResult = $fetchesJobResult; + $this->updatesJobResult = $updatesJobResult; + } + + /** + * @param ListGenericJobObject $listGenericJobObject + * @param array $resultCurrent + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException + */ + public function execute(ListGenericJobObject $listGenericJobObject, $resultCurrent) { + $jobResultCurrent = $this->fetchesJobResult->execute(['job_id' => $listGenericJobObject->getJobId()]); + $resultCurrentJson = json_encode($resultCurrent); + $resultSignatureCurrent = md5($resultCurrentJson); + + try{ + $jobResultExisting = $this->fetchesJobResult->execute(['request_signature' => $jobResultCurrent->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]); + $resultSignatureExisting = $jobResultExisting->result_signature; + //if($resultSignatureExisting != $resultSignatureCurrent){ + $this->updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $listGenericJobObject->getJobCommandName(), $listGenericJobObject->getJobCommand()); + //} + } catch (JobResourceNotFoundException $exception){ + $this->updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $listGenericJobObject->getJobCommandName(), $listGenericJobObject->getJobCommand()); + } + } + + private function updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $jobCommandName, $jobCommand){ + $updateJobResultObject = new UpdateJobResultObject( + $resultCurrentJson, + $resultSignatureCurrent, + $jobCommandName, + $jobCommand + ); + $create = $this->updatesJobResult->execute($jobResultCurrent, $updateJobResultObject); + } +} diff --git a/app/Classes/Modules/Jobs/Services/CreatesJobResult.php b/app/Classes/Modules/Jobs/Services/CreatesJobResult.php new file mode 100644 index 00000000..e70e0e6a --- /dev/null +++ b/app/Classes/Modules/Jobs/Services/CreatesJobResult.php @@ -0,0 +1,26 @@ +job_id = $listGenericJobObject->getJobId(); + $model->request_signature = $listGenericJobObject->getRequestSignature(); + $model->result_signature = $listGenericJobObject->getResultSignature(); + $model->url = $listGenericJobObject->getName(); + + return $this->handler($model); + } +} diff --git a/app/Classes/Modules/Jobs/Services/FetchesJobResult.php b/app/Classes/Modules/Jobs/Services/FetchesJobResult.php new file mode 100644 index 00000000..1cc99cb6 --- /dev/null +++ b/app/Classes/Modules/Jobs/Services/FetchesJobResult.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + public function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Jobs/Services/ListsJobResult.php b/app/Classes/Modules/Jobs/Services/ListsJobResult.php new file mode 100644 index 00000000..55f3b267 --- /dev/null +++ b/app/Classes/Modules/Jobs/Services/ListsJobResult.php @@ -0,0 +1,33 @@ +repository = $repository; + } + + + /** + * @return Builder + */ + function getRepository(): Builder + { + return $this->repository->newQuery(); + } +} diff --git a/app/Classes/Modules/Jobs/Services/UpdatesJobResult.php b/app/Classes/Modules/Jobs/Services/UpdatesJobResult.php new file mode 100644 index 00000000..ab3d9385 --- /dev/null +++ b/app/Classes/Modules/Jobs/Services/UpdatesJobResult.php @@ -0,0 +1,28 @@ +result = $updateJobResultObject->getResult(); + $model->result_signature = $updateJobResultObject->getResultSignature(); + $model->job_command_name = $updateJobResultObject->getJobCommandName(); + $model->job_command = $updateJobResultObject->getJobCommand(); + + return $this->handler($model); + + } +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php new file mode 100644 index 00000000..654a360f --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsJobLogic.php @@ -0,0 +1,74 @@ + 'List Transaction Job', + 'message' => 'You have successfully submit a job to list transactions' + ]; + } + + /** @var CreatesJobResult */ + private $createsJobResult; + + /** + * ListTransactionsJobLogic constructor. + * @param CreatesJobResult $createsJobResult + */ + public function __construct(CreatesJobResult $createsJobResult) + { + $this->createsJobResult = $createsJobResult; + } + + + /** + * @param Request $request + * @return JsonResponse + */ + public function logic(Request $request) : JsonResponse + { + $jobId = uniqid(); + + $user = Auth::user(); + $userInfo = (object) [ + 'type' => $user->type, + ]; + + $userInfoJson = json_encode($userInfo); + $requestSignature = md5($userInfoJson . $request->fullUrl()); + + $listGenericJobObject = new ListGenericJobObject( + $request->fullUrl(), + $request->all(), + $requestSignature, + null, + $jobId, + $userInfo + ); + + ListTransactionsJob::dispatch($listGenericJobObject); + + $result = []; + $result['job_id'] = $jobId; + + $this->createsJobResult->execute($listGenericJobObject); + + return $this->response(['data' => $result]); + } + +} diff --git a/app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php b/app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php new file mode 100644 index 00000000..475d4715 --- /dev/null +++ b/app/Classes/Modules/Transactions/Processors/ListTransactionsJobProcessor.php @@ -0,0 +1,45 @@ +listsTransactions = $listsTransactions; + $this->updateJobResultProcessor = $updateJobResultProcessor; + } + + /** + * @param ListGenericJobObject $listGenericJobObject + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\JobResourceNotFoundException + */ + public function execute(ListGenericJobObject $listGenericJobObject) { + + $query = $this->listsTransactions->execute($this->listsTransactions->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page']]); + + $resultCurrent = Helper::collectionResponse(ListTransactionJobResource::collection($query)); + $this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent); + } +} + diff --git a/app/Http/Controllers/Bookings/ListBookingsJobController.php b/app/Http/Controllers/Bookings/ListBookingsJobController.php new file mode 100644 index 00000000..9b32fc77 --- /dev/null +++ b/app/Http/Controllers/Bookings/ListBookingsJobController.php @@ -0,0 +1,22 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Documents/ListDocumentsJobController.php b/app/Http/Controllers/Documents/ListDocumentsJobController.php new file mode 100644 index 00000000..8b763085 --- /dev/null +++ b/app/Http/Controllers/Documents/ListDocumentsJobController.php @@ -0,0 +1,19 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Jobs/FetchJobResultController.php b/app/Http/Controllers/Jobs/FetchJobResultController.php new file mode 100644 index 00000000..cfef2f5c --- /dev/null +++ b/app/Http/Controllers/Jobs/FetchJobResultController.php @@ -0,0 +1,19 @@ +execute($request); + } +} diff --git a/app/Http/Controllers/Transactions/ListTransactionsJobController.php b/app/Http/Controllers/Transactions/ListTransactionsJobController.php new file mode 100644 index 00000000..fb341d5d --- /dev/null +++ b/app/Http/Controllers/Transactions/ListTransactionsJobController.php @@ -0,0 +1,21 @@ +execute($request); + } +} diff --git a/app/Http/Resources/BookingResource.php b/app/Http/Resources/BookingResource.php index f3a7881d..70fbc95c 100644 --- a/app/Http/Resources/BookingResource.php +++ b/app/Http/Resources/BookingResource.php @@ -11,11 +11,9 @@ use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\ValueObjects\Constants\DocumentType; use Carbon\Carbon; use Illuminate\Http\Resources\Json\JsonResource; -use Illuminate\Support\Facades\Log; class BookingResource extends JsonResource { - /** * Transform the resource into an array. * diff --git a/app/Http/Resources/CompanyResource.php b/app/Http/Resources/CompanyResource.php index 85ecee16..eff2bd1b 100644 --- a/app/Http/Resources/CompanyResource.php +++ b/app/Http/Resources/CompanyResource.php @@ -15,7 +15,6 @@ use App\Models\SegmentConstant; use Carbon\Carbon; use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Support\Facades\Auth; -use Illuminate\Support\Facades\Log; class CompanyResource extends JsonResource { diff --git a/app/Http/Resources/DocumentResource.php b/app/Http/Resources/DocumentResource.php index 59933a67..c0f801bb 100644 --- a/app/Http/Resources/DocumentResource.php +++ b/app/Http/Resources/DocumentResource.php @@ -3,10 +3,7 @@ namespace App\Http\Resources; use App\Models\Booking; -use App\Models\Company; -use App\Models\Document; use Carbon\Carbon; -use Illuminate\Database\Eloquent\Model; use Illuminate\Http\Resources\Json\JsonResource; class DocumentResource extends JsonResource diff --git a/app/Http/Resources/JobResultResource.php b/app/Http/Resources/JobResultResource.php new file mode 100644 index 00000000..51bc1898 --- /dev/null +++ b/app/Http/Resources/JobResultResource.php @@ -0,0 +1,22 @@ + $this->job_id, + 'result' => $this->result, + ]; + } +} diff --git a/app/Http/Resources/ListBookingJobResource.php b/app/Http/Resources/ListBookingJobResource.php new file mode 100644 index 00000000..06f8c38d --- /dev/null +++ b/app/Http/Resources/ListBookingJobResource.php @@ -0,0 +1,81 @@ +userInfo = $userInfo ?? ($resource->userInfo ?? null); + } + + /** + * Transform the resource into an array. + * + * @param \Illuminate\Http\Request $request + * @return array + * @throws \Illuminate\Contracts\Container\BindingResolutionException + */ + public function toArray($request) + { + return [ + 'id' => $this->id, + 'company' => new CompanyResource($this->company, $this->userInfo), + 'bank' => new BankResource($this->bank), + 'service' => new ServiceTypeResource($this->service), + 'marking' => $this->marking, + 'amount' => $this->fix_amount, + 'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'fixed_currency' => new CurrencyResource($this->fixedCurrency), + 'convertible_currency' => new CurrencyResource($this->convertibleCurrency), + 'conversion_currency' => new CurrencyResource($this->conversionCurrency), + 'documents' => [ + 'purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::PURCHASE_ORDER)->first()), + 'delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER)->first()), + 'invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::INVOICE)->first()), + 'supplier_delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->first()), + 'proforma_invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()), + 'ecommerce_purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->first()), + ], + 'status' => $this->status, + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'), + 'created_at_with_time' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), + $this->mergeWhen($this->relationLoaded('transactions'), [ + 'purchase_order' => new TransactionResource($this->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first()), + 'payment_attempts' => TransactionResource::collection( + $this->transactions() + ->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION) + ->whereDate('expires_on', '>=', Carbon::now()) + ->get() + ), + 'expired_payment_attempts' => TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString())->get()), + 'payment_history' => TransactionResource::collection($this->transactions()->where(function($query){ + $query->where(function($query){ + $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]); + })->orWhere(function($query){ + $query->where(function($query){ + $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]); + })->orWhere(function($query){ + $query->where('type', TransactionType::CREDIT_NOTE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); + }); + })->latest()->get()) + ]) + ]; + } +} diff --git a/app/Http/Resources/ListDocumentJobResource.php b/app/Http/Resources/ListDocumentJobResource.php new file mode 100644 index 00000000..edf549ef --- /dev/null +++ b/app/Http/Resources/ListDocumentJobResource.php @@ -0,0 +1,31 @@ + $this->id, + 'reference' => $this->reference, + 'status' => (int) $this->status, + 'document_type' => $this->document_type, + 'owner' => $this->relationLoaded('owner') ? ($this->owner instanceof Booking ? new BookingV2Resource($this->owner, $this->userInfo) : new CompanyV2Resource($this->owner, $this->userInfo)) : null, + 'files' => FileResource::collection($this->files), + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A') + ]; + } +} diff --git a/app/Http/Resources/ListTransactionJobResource.php b/app/Http/Resources/ListTransactionJobResource.php new file mode 100644 index 00000000..6c4c0ece --- /dev/null +++ b/app/Http/Resources/ListTransactionJobResource.php @@ -0,0 +1,54 @@ +type, [TransactionType::BILL, TransactionType::REFUND])? $this->owner->owner : $this->owner; + $days = $this->created_at->endOfDay()->addWeekdays($booking->service_id === 3 ? 3 : 1); + + return [ + 'id' => $this->id, + 'booking' => new BookingResource($booking), + 'type' => (int) $this->type, + 'bill_no' => $this->bill_no, + 'payment_reference' => $this->payment_reference, + 'payment_method' => (float) $this->payment_method, + 'recipient_bank_account' => new BankResource($booking->bank), + 'issuer_name' => $this->issuerCompany->name, + 'issuer_id' => $this->issuerCompany->id, + 'amount' => (double) $this->amount, + 'original_amount' => (double) $this->original_amount, + 'currency' => new CurrencyResource($this->currency), + 'original_currency' => new CurrencyResource($this->original_currency), + 'service_charge' => (double) $this->service_charge, + 'tax' => (double) $this->tax, + 'currency_rate' => (double) $this->currency_rate, + 'status' => (int) $this->status, + 'details' => TransactionDetailResource::collection($this->transactionDetails), + 'documents' => new DocumentResource($this->documents()->first()), + 'transaction_bill' => new TransactionResource($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->bills()->first())), + 'transaction_refunds' => TransactionResource::collection($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->refunds()->get())), + 'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'), + 'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'), + 'interval' => [ + 'value' => $days->gt(Carbon::now()) ? '+' : '-', + 'duration' => $days->diff(Carbon::now())->format('%d'), + ], + 'redemption' => new VoucherRedemptionResource($this->voucherRedemption) + ]; + } +} diff --git a/app/Http/Resources/V2/BookingV2Resource.php b/app/Http/Resources/V2/BookingV2Resource.php new file mode 100644 index 00000000..ee17181e --- /dev/null +++ b/app/Http/Resources/V2/BookingV2Resource.php @@ -0,0 +1,82 @@ +userInfo = $userInfo ?? ($resource->userInfo ?? null); + } + + /** + * Transform the resource into an array. + * + * @param \Illuminate\Http\Request $request + * @return array + * @throws \Illuminate\Contracts\Container\BindingResolutionException + */ + public function toArray($request) + { + return [ + 'id' => $this->id, + 'company' => new CompanyV2Resource($this->company, $this->userInfo), + 'bank' => new V1\BankResource($this->bank), + 'service' => new V1\ServiceTypeResource($this->service), + 'marking' => $this->marking, + 'amount' => $this->fix_amount, + 'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'fixed_currency' => new V1\CurrencyResource($this->fixedCurrency), + 'convertible_currency' => new V1\CurrencyResource($this->convertibleCurrency), + 'conversion_currency' => new V1\CurrencyResource($this->conversionCurrency), + 'documents' => [ + 'purchase_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::PURCHASE_ORDER)->first()), + 'delivery_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER)->first()), + 'invoice' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::INVOICE)->first()), + 'supplier_delivery_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->first()), + 'proforma_invoice' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()), + 'ecommerce_purchase_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->first()), + ], + 'status' => $this->status, + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'), + 'created_at_with_time' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), + $this->mergeWhen($this->relationLoaded('transactions'), [ + 'purchase_order' => new V1\TransactionResource($this->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first()), + 'payment_attempts' => V1\TransactionResource::collection( + $this->transactions() + ->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION) + ->whereDate('expires_on', '>=', Carbon::now()) + ->get() + ), + 'expired_payment_attempts' => V1\TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString())->get()), + 'payment_history' => V1\TransactionResource::collection($this->transactions()->where(function($query){ + $query->where(function($query){ + $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]); + })->orWhere(function($query){ + $query->where(function($query){ + $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]); + })->orWhere(function($query){ + $query->where('type', TransactionType::CREDIT_NOTE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); + }); + })->latest()->get()) + ]) + ]; + } +} diff --git a/app/Http/Resources/V2/CompanyV2Resource.php b/app/Http/Resources/V2/CompanyV2Resource.php new file mode 100644 index 00000000..64fca7c7 --- /dev/null +++ b/app/Http/Resources/V2/CompanyV2Resource.php @@ -0,0 +1,100 @@ +userInfo = $userInfo; + } + + /** + * Transform the resource into an array. + * + * @param \Illuminate\Http\Request $request + * @return array + */ + public function toArray($request) + { + $lastPayment = $this->transactions()->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->orderBy('id', 'DESC')->first(); + $totalPayments = $this->transactions()->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount'); + + $segment = SegmentConstant::where('reference', SegmentConstants::SUPPLIER_CURRENCIES)->where('detail->id', $this->id)->first(); + $serviceCharge = SegmentConstant::where('reference', SegmentConstants::SERVICE_CHARGE)->where('detail->id', $this->id)->first(); + + $userResource = null; + + $userInfoEmail = $this->userInfo && isset($this->userInfo->email) ? $this->userInfo->email : null; + $userInfoType = $this->userInfo && isset($this->userInfo->type) ? $this->userInfo->type : null; + + if(!$userInfoEmail && Auth::user()){ + $userInfoEmail = Auth::user()->email; + } + if(!$userInfoType && Auth::user()){ + $userInfoType = Auth::user()->type; + } + + if(!is_null($userInfoEmail) && !is_null($userInfoType)){ + $userResource = new V1\UserResource($userInfoType === RoleTypes::USER ? $this->employees()->where('email', '=', $userInfoEmail)->first() : $this->employees()->orderBy('id', 'DESC')->first()); + } + + return [ + 'id' => $this->id, + 'name' => $this->name, + 'reference' => $this->reference, + 'debtor' => $this->debtor, + 'type' => (int) $this->type, + 'business_type' => (int) $this->business_type, + 'status' => (int) $this->status, + 'contact' => new V1\ContactResource ($this->when($this->has('contacts'), $this->contacts->first())), + 'address' => new V1\AddressResource($this->when($this->has('addresses'), $this->addresses->where('billing', true)->first())), + 'employee' => $userResource, + 'identification' => new V1\DocumentResource($this->documents->whereIn('document_type', DocumentType::IDENTIFICATION_DOCUMENTS)->first()), + 'bookings' => $this->whenLoaded('bookings', $this->bookings()->orderBy('id', 'DESC')->get(), []), + 'confirmed_bookings' => $this->bookings()->whereHas('transactions', function ($query){ + $query->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + })->count(), + 'total_payments' => (float) $totalPayments, + 'average_spending_per_day' => (float) $totalPayments / ($this->created_at->diff(Carbon::now())->days === 0 ? 1 : $this->created_at->diff(Carbon::now())->days), + 'average_spending_per_booking' => (float) $totalPayments > 0 ? $totalPayments / $this->bookings()->whereHas('transactions', function ($query){ + $query->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + })->count() : $totalPayments, + 'last_payment' => $lastPayment ? $lastPayment->created_at->diffForHumans() : 'No Payments', + 'personal_banks' => V1\BankResource::collection($this->banks->where('type', BankAccountType::PERSONAL)), + 'recipient_banks' => [ + 'accounts' => V1\BankResource::collection($this->banks->where('type', BankAccountType::EXTERNAL)), + 'default' => new V1\BankResource($this->banks->where('type', BankAccountType::EXTERNAL)->where('default', true)->first()) + ], + 'segments' => V1\SegmentResource::collection($this->segments), + 'seasonalSegment' => $this->whenLoaded('seasonalSegments', V1\SeasonalSegmentResource::collection($this->seasonalSegments)), + 'services' => (new FetchesCompanyServices())->getServices($this->servicesConfigurations()), + 'wallet' => $this->whenLoaded('wallets', new V1\WalletResource($this->wallets()->with('transactions')->first()), new V1\WalletResource($this->wallets()->first())), + 'created_at' => $this->created_at->format('d-m-Y'), + $this->mergeWhen($this->business_type === BusinessType::CURRENCY_VENDOR, [ + 'currencies' => $segment ? V1\CurrencyResource::collection(Currency::whereIn('id', $segment->detail->currencies)->get()) : [], + 'service_charge' => $serviceCharge + ]) + + ]; + } +} diff --git a/app/Models/JobResult.php b/app/Models/JobResult.php new file mode 100644 index 00000000..f30b5076 --- /dev/null +++ b/app/Models/JobResult.php @@ -0,0 +1,13 @@ +id(); + $table->string('job_id', 50); + $table->longText('result')->nullable(); + $table->timestamps(); + + // $table->foreign('job_id')->references('id')->on('jobs')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('job_results'); + } +} diff --git a/database/migrations/2023_08_29_063531_add_new_column_to_job_results_table.php b/database/migrations/2023_08_29_063531_add_new_column_to_job_results_table.php new file mode 100644 index 00000000..8e6b8342 --- /dev/null +++ b/database/migrations/2023_08_29_063531_add_new_column_to_job_results_table.php @@ -0,0 +1,36 @@ +longText('url')->after('result')->nullable(); + $table->string('job_command_name')->after('url')->nullable(); + $table->longText('job_command')->after('job_command_name')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('job_results', function (Blueprint $table) { + $table->dropColumn('url'); + $table->dropColumn('job_command_name'); + $table->dropColumn('job_command'); + }); + } +} diff --git a/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php b/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php new file mode 100644 index 00000000..12c6d57f --- /dev/null +++ b/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php @@ -0,0 +1,34 @@ +string('request_signature')->after('job_id')->nullable(); + $table->string('result_signature')->after('request_signature')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('job_results', function (Blueprint $table) { + $table->dropColumn('request_signature'); + $table->dropColumn('result_signature'); + }); + } +} diff --git a/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue b/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue new file mode 100644 index 00000000..966ccbbc --- /dev/null +++ b/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue @@ -0,0 +1,136 @@ + + diff --git a/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionPollingComponent.vue b/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionPollingComponent.vue new file mode 100644 index 00000000..47d14857 --- /dev/null +++ b/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionPollingComponent.vue @@ -0,0 +1,136 @@ + + diff --git a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue index 7df9c125..d2b69080 100644 --- a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue +++ b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue @@ -117,11 +117,17 @@
+ +
@@ -165,7 +171,7 @@ } }, created(){ - this.submit(route('api.company.list') + '?filters=' + JSON.stringify({'business_type': 3, 'status_in': [1, 2, 0]}), 'get', 'pendingOrdersSection', false, false) + this.submit(route('api.company.list') + '?filters=' + JSON.stringify({'business_type': 3, 'status_in': [1, 2, 0]}), 'get', 'pendingOrdersSection', false, false); //cief todo: Uncaught (in promise) null }, methods: { successHandler(response){ @@ -210,4 +216,4 @@ } - \ No newline at end of file + diff --git a/resources/assets/vue/components/general/elements/ListPollingComponent.vue b/resources/assets/vue/components/general/elements/ListPollingComponent.vue new file mode 100644 index 00000000..fcd3b8b8 --- /dev/null +++ b/resources/assets/vue/components/general/elements/ListPollingComponent.vue @@ -0,0 +1,213 @@ + + + diff --git a/resources/assets/vue/general/mixins/aws/requestV2.js b/resources/assets/vue/general/mixins/aws/requestV2.js new file mode 100644 index 00000000..12b27542 --- /dev/null +++ b/resources/assets/vue/general/mixins/aws/requestV2.js @@ -0,0 +1,49 @@ +export default { + methods: { + poll(url, method, section, successNotification = true, errorNotification = true){ + if(!this.validate()){ return; } + if (section) { + this.$store.dispatch('toggleLoading', {name: section, status: true}) + } + this.$store.dispatch('crudRequestV2', { + endpoint: url, + method: method, + parameters: this.parameters + }).then(response => { + let statusCode = response.status, + success = response.ok; + + response.json().then(response => { + + if(!success){ + this.openModal(); + errorNotification ? this.$store.dispatch('createNotification', {title: response.title, message: response.message, type: 'error'}): null; + this.errorHandler(response, statusCode); return; + } + + successNotification ? this.$store.dispatch('createNotification', {title: response.title, message: response.message, type: 'success'}): null; + this.successHandler(response) + + + }); + }).catch((error) => { + this.$store.dispatch('createNotification', {title: 'Unexpected Error', message: 'An unexpected error has occurred. Try again!', type: 'error'}); + }).then(() => { + if (section) { + this.$store.dispatch('toggleLoading', {name: section, status: false}) + } + }) + + }, + validate() { + if(this.$v){ + this.$v.$touch(); + return !this.$v.$invalid; + } + return true; + }, + successHandler(response){}, + errorHandler(response){} + } + +} diff --git a/resources/assets/vue/general/mixins/tabHandler.js b/resources/assets/vue/general/mixins/tabHandler.js new file mode 100644 index 00000000..81790ed0 --- /dev/null +++ b/resources/assets/vue/general/mixins/tabHandler.js @@ -0,0 +1,24 @@ +export default { + data() { + return { + activeTab: null, + displayedTabs: [], + }; + }, + methods: { + setActiveTab(event) { + const tabName = event.currentTarget.getAttribute('tab-name'); + // console.log(`Tab "${tabName}" clicked`); + this.activeTab = tabName; + if (!this.displayedTabs.includes(tabName)) { + this.displayedTabs.push(tabName); + } + }, + isActiveTab(tabName) { + return this.activeTab === tabName; + }, + showTabContent(tabName) { + return this.displayedTabs.includes(tabName); + }, + }, +} diff --git a/resources/assets/vue/vuex/modules/crudRequestV2.js b/resources/assets/vue/vuex/modules/crudRequestV2.js new file mode 100644 index 00000000..355b1edb --- /dev/null +++ b/resources/assets/vue/vuex/modules/crudRequestV2.js @@ -0,0 +1,51 @@ +export default { + actions: { + crudRequestV2({getters, dispatch}, {endpoint, method, parameters}){ + return dispatch('ensureReCaptchaIsSet').then(function () { + const queryDomain = endpoint.split('?')[0]; + let encodedParams = endpoint.split('?')[1]; + let decodedParams = fullyDecodeURI(encodedParams); + const queryParams = encodeURIComponent(decodedParams); + encodedParams = queryParams.toString(); + let filteredEncodedParams = encodedParams.replace(/%3D/g,'='); + filteredEncodedParams = filteredEncodedParams.replace(/%26/g,'&'); + let combinedAbsoluteUrl = queryDomain; + if(filteredEncodedParams !== undefined && filteredEncodedParams !== 'undefined'){ + combinedAbsoluteUrl = queryDomain + '?' + filteredEncodedParams; + } + + // return fetch(endpoint, { + return fetch(combinedAbsoluteUrl, { + method: method, + responseType: 'json', + body: parameters ? JSON.stringify(parameters):null, + headers: { + 'content-type': 'application/json', + 'Authorization': 'Bearer '+getters.getAccessToken, + 'captcha-token': getters.getReCaptcha + } + }).then(response => { + + if(response.status === 401 && window.location.href !== route('login')){ + dispatch('userAuthentication', {access_token: '', redirect_url: '/'}); + } + + return response; + + }) + }); + } + } +} + +function isEncoded(uri) { + uri = uri || ''; + return uri !== decodeURIComponent(uri); +} + +function fullyDecodeURI(uri){ + while (isEncoded(uri)){ + uri = decodeURIComponent(uri); + } + return uri; +} diff --git a/resources/assets/vue/vuex/store.js b/resources/assets/vue/vuex/store.js index 2c3d911b..ff10c673 100644 --- a/resources/assets/vue/vuex/store.js +++ b/resources/assets/vue/vuex/store.js @@ -4,6 +4,7 @@ import toggleSection from './modules/toggleSection' import toggleLoading from './modules/toggleLoading' import createNotification from './modules/createNotification' import crudRequest from './modules/crudRequest' +import crudRequestV2 from './modules/crudRequestV2' import authentication from './modules/authentication' import loadRequestQueue from './modules/loadRequestQueue' @@ -16,6 +17,7 @@ export default new Vuex.Store({ loadRequestQueue, createNotification, crudRequest, + crudRequestV2, authentication } -}) \ No newline at end of file +}) diff --git a/resources/views/pages/billings.blade.php b/resources/views/pages/billings.blade.php index 4bc012d5..da84f8b9 100644 --- a/resources/views/pages/billings.blade.php +++ b/resources/views/pages/billings.blade.php @@ -3,129 +3,7 @@
- -
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
Invoice
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
Purchase Order
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
Delivery Order
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
Supplier Delivery Order
-
-
-
-
-
-
-
-
-
-
-
-
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
-
-
-
+
-@endsection \ No newline at end of file +@endsection diff --git a/resources/views/pages/billings_experiment.blade.php b/resources/views/pages/billings_experiment.blade.php new file mode 100644 index 00000000..d1caee2d --- /dev/null +++ b/resources/views/pages/billings_experiment.blade.php @@ -0,0 +1,9 @@ +@extends('layouts.base_portal') +@section('inner_content') +
+
+ + +
+
+@endsection diff --git a/routes/api.php b/routes/api.php index 8b4bada0..460bd772 100644 --- a/routes/api.php +++ b/routes/api.php @@ -67,6 +67,10 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function require __DIR__ . '/milestone.php'; + // require __DIR__ . '/accounting.php'; //cief todo: To check if this is needed + + require __DIR__ . '/job.php'; + // require __DIR__ . '/rate.php'; // require __DIR__ . '/receipt.php'; diff --git a/routes/currency.php b/routes/currency.php index b621aad6..ba55c9a2 100644 --- a/routes/currency.php +++ b/routes/currency.php @@ -1,4 +1,4 @@ - 'document', 'as' => 'document.', 'namespace' => 'Documents'], function () { Route::get('/list', 'ListDocumentsController@list')->name('list'); + Route::get('/list/job', 'ListDocumentsJobController@list')->name('list.job'); Route::delete('/{id}/delete', 'DeleteDocumentController@delete')->name('delete'); Route::put('/{id}/approve', 'ApproveDocumentController@approve')->name('status.approve'); Route::put('/{id}/reject', 'RejectDocumentController@reject')->name('status.reject'); Route::put('/{id}/reference/update', 'UpdateDocumentReferenceController@update')->name('reference.update'); -}); \ No newline at end of file +}); diff --git a/routes/job.php b/routes/job.php new file mode 100644 index 00000000..028e9468 --- /dev/null +++ b/routes/job.php @@ -0,0 +1,8 @@ + 'job', 'as' => 'job.', 'namespace' => 'Jobs'], function () { + Route::get('/fetch/{job_id}', 'FetchJobResultController@fetch')->name('fetch'); + Route::get('/fetch/{job_id}/{is_last}', 'FetchJobResultController@fetch')->name('fetch.last.attempt'); +}); diff --git a/routes/web.php b/routes/web.php index bf2892bb..a6590c17 100644 --- a/routes/web.php +++ b/routes/web.php @@ -92,6 +92,12 @@ Route::get('/billings', function () { return view('pages.billings'); })->name('billings'); +/* Vue Polling Experiment - Starts */ +Route::get('/billings-experiment', function () { + return view('pages.billings_experiment'); +})->name('billings.experiment'); +/* Vue Polling Experiment - Ends */ + Route::get('/currency_orders', function () { return view('pages.currency_orders'); })->name('currency_orders'); @@ -830,13 +836,13 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, ->withTrashed() ->orderBy('created_at', 'asc') ->first(); - + // get the first bill_no $firstBillNo = $firstInvoice->bill_no; if (strpos($firstBillNo, '-deleted') !== false) { $firstBillNo = substr($firstBillNo, 0, strpos($firstBillNo, '-deleted')); } - + // update currentInvoice bill_no to '-deleted-' $currentInvoice = $booking->transactions()->where('type', TransactionType::INVOICE)->first(); $currentInvoice->bill_no = $currentInvoice->bill_no ."-deleted-" . Str::random(10); @@ -859,4 +865,4 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, } } ); -})->name('invoice.fix.byCustomerMarking'); \ No newline at end of file +})->name('invoice.fix.byCustomerMarking'); From f08343439052ff23e122217e123cd3d314b5a7f6 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Fri, 16 Feb 2024 14:59:11 +0800 Subject: [PATCH 042/228] update refund ui and logic --- .../CreateBookingPaymentLogic.php | 10 +- .../CreateBookingRefundLogic.php | 8 +- .../ControllersLogic/FetchBookingLogic.php | 2 +- .../FetchBookingPaymentQuotationLogic.php | 9 +- .../CalculatesBookingRefundAmount.php | 27 ++- .../UpdateRefundTransactionStatusLogic.php | 21 ++- app/Http/Resources/BookingResource.php | 4 +- app/Http/Resources/TransactionResource.php | 1 + .../elements/PaymentHistoryComponent.vue | 105 ++++++++---- .../elements/RefundConfirmationComponent.vue | 157 ++++++++---------- .../elements/RefundVerificationComponent.vue | 2 +- .../forms/PurchaseOrderFormComponent.vue | 6 +- routes/transaction.php | 2 +- 13 files changed, 208 insertions(+), 146 deletions(-) diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php index c429d91d..ab654675 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php @@ -19,6 +19,7 @@ use App\Classes\ValueObjects\Constants\PaymentMethodType; use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\Modules\Currencies\DataTransferObjects\CurrencyConversionObject; use App\Http\Resources\TransactionResource; +use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; use App\Classes\Modules\Transactions\Processors\CreateCashBackTransactionProcessor; use App\Classes\Modules\Vouchers\Processors\Voucherify\BookingToVoucherifyProcessor; @@ -77,6 +78,9 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic /** @var BookingToVoucherifyProcessor */ private $bookingToVoucherifyProcessor; + /** @var CalculatesBookingRefundAmount */ + private $calculatesBookingRefundAmount; + /** * CreateBookingPaymentLogic constructor. * @param FetchesBookingQuotation $fetchBookingQuotation @@ -90,8 +94,9 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic * @param CreateCashBackTransactionProcessor $createCashBackTransactionProcessor * @param RecalculatesWalletBalance $recalculatesWalletBalance * @param BookingToVoucherifyProcessor $bookingToVoucherifyProcessor + * @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount */ - public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding, CreatesBillplzBill $createsBillplzBill, UpdatesWalletBalance $updatesWalletBalance, UpdatesTransactionStatus $updatesTransactionStatus, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor, RecalculatesWalletBalance $recalculatesWalletBalance, BookingToVoucherifyProcessor $bookingToVoucherifyProcessor) + public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding, CreatesBillplzBill $createsBillplzBill, UpdatesWalletBalance $updatesWalletBalance, UpdatesTransactionStatus $updatesTransactionStatus, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor, RecalculatesWalletBalance $recalculatesWalletBalance, BookingToVoucherifyProcessor $bookingToVoucherifyProcessor, CalculatesBookingRefundAmount $calculatesBookingRefundAmount) { $this->fetchBookingQuotation = $fetchBookingQuotation; $this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit; @@ -104,6 +109,7 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic $this->createCashBackTransactionProcessor = $createCashBackTransactionProcessor; $this->recalculatesWalletBalance = $recalculatesWalletBalance; $this->bookingToVoucherifyProcessor = $bookingToVoucherifyProcessor; + $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; } /** @@ -119,7 +125,7 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $request->input('amount'))), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')]); - $outstanding = $this->calculatesBookingOutstanding->execute($booking); + $outstanding = $this->calculatesBookingOutstanding->execute($booking) + $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id); if($conversionObject->getAmount() > round($outstanding, 2)) throw new MalformedRequestException('Your payment must not be greater than '. $outstanding .'.'); diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php index 7455e689..0648629e 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php @@ -15,7 +15,6 @@ use App\Classes\Modules\Transactions\Services\CreatesTransaction; use App\Classes\Modules\Transactions\Services\FetchesTransaction; use App\Classes\Modules\Bookings\Services\FetchesBookingQuotation; use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; -use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionRefundCalculationObject; @@ -49,9 +48,6 @@ class CreateBookingRefundLogic extends AbstractControllerLogic /** @var CreatesTransaction */ private $createsTransaction; - /** @var CalculatesBookingRefundAmount */ - private $calculatesBookingRefundAmount; - /** * CreateBookingPaymentLogic constructor. * @param FetchesBookingQuotation $fetchBookingQuotation @@ -59,16 +55,14 @@ class CreateBookingRefundLogic extends AbstractControllerLogic * @param UpdatesTransactionStatus $updatesTransactionStatus * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber * @param CreatesTransaction $createsTransaction - * @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount */ - public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingRefundAmount $calculatesBookingRefundAmount) + public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction) { $this->fetchBookingQuotation = $fetchBookingQuotation; $this->fetchesTransaction = $fetchesTransaction; $this->updatesTransactionStatus = $updatesTransactionStatus; $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; $this->createsTransaction = $createsTransaction; - $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; } /** diff --git a/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingLogic.php index d9857548..d1f2286e 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingLogic.php @@ -18,7 +18,7 @@ class FetchBookingLogic extends AbstractControllerLogic */ protected function notification():array { return [ - 'title' => 'Retrieved Address', + 'title' => 'Retrieved Booking', 'message' => 'You have successfully retrieved a Address' ]; } diff --git a/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingPaymentQuotationLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingPaymentQuotationLogic.php index 8effdb2f..e9a42101 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingPaymentQuotationLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/FetchBookingPaymentQuotationLogic.php @@ -14,6 +14,7 @@ use App\Classes\ValueObjects\Constants\PaymentMethodType; use App\Models\Booking; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; class FetchBookingPaymentQuotationLogic extends AbstractControllerLogic { @@ -40,6 +41,9 @@ class FetchBookingPaymentQuotationLogic extends AbstractControllerLogic /** @var CalculatesBookingOutstanding */ private $calculatesBookingOutstanding; + /** @var CalculatesBookingRefundAmount */ + private $calculatesBookingRefundAmount; + /** * FetchBookingPaymentQuotationLogic constructor. * @param FetchesBookingQuotation $fetchBookingQuotation @@ -47,12 +51,13 @@ class FetchBookingPaymentQuotationLogic extends AbstractControllerLogic * @param FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit * @param CalculatesBookingOutstanding $calculatesBookingOutstanding */ - public function __construct(FetchesBookingQuotation $fetchBookingQuotation, GeneratesBookingQuotation $generatesBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, CalculatesBookingOutstanding $calculatesBookingOutstanding) + public function __construct(FetchesBookingQuotation $fetchBookingQuotation, GeneratesBookingQuotation $generatesBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, CalculatesBookingOutstanding $calculatesBookingOutstanding, CalculatesBookingRefundAmount $calculatesBookingRefundAmount) { $this->fetchBookingQuotation = $fetchBookingQuotation; $this->generatesBookingQuotation = $generatesBookingQuotation; $this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit; $this->calculatesBookingOutstanding = $calculatesBookingOutstanding; + $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; } /** @@ -66,7 +71,7 @@ class FetchBookingPaymentQuotationLogic extends AbstractControllerLogic $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $request->input('amount'))), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')]); - $outstanding = $this->calculatesBookingOutstanding->execute($booking); + $outstanding = $this->calculatesBookingOutstanding->execute($booking) + $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id); if($conversionObject->getAmount() > round($outstanding, 2)) throw new MalformedRequestException('Your payment must not be greater than '.$booking->fixedCurrency->short_code.' '. number_format((float)$outstanding, 2, '.', ',')); //Voucherify diff --git a/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php b/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php index 14a4a9ef..f6dab1f4 100644 --- a/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php +++ b/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php @@ -2,19 +2,30 @@ namespace App\Classes\Modules\Bookings\Services; - use App\Classes\ValueObjects\Constants\ApprovalStatus; -use App\Classes\ValueObjects\Constants\TransactionType; use App\Models\Booking; -use Carbon\Carbon; class CalculatesBookingRefundAmount { + public function execute(Booking $booking, int $type, ?string $payment_reference = null): float + { + $refundAmounts = $booking->transactions()->payments()->get()->map(function ($payment) use ($type) { + return $this->calculateRefundAmount($payment, $type); + }); - public function execute(Booking $booking, int $type, ?string $payment_reference = NULL){ - return $type === 1 ? - $booking->transactions()->refunds($payment_reference) - ->selectRaw('sum(amount - service_charge - tax) as sub_total')->get()->sum('sub_total') : $booking->transactions()->refunds($payment_reference)->sum('original_amount'); + $totalRefundAmount = $refundAmounts->sum(); + + return $totalRefundAmount; } -} \ No newline at end of file + private function calculateRefundAmount($payment, int $type): float + { + $refundTransactions = $payment->transactions()->refunds()->whereIn('status', [ApprovalStatus::APPROVED]); + + if ($type === 1) { + return $refundTransactions->selectRaw('sum(amount - service_charge - tax) as sub_total')->get()->sum('sub_total'); + } + + return $refundTransactions->sum('original_amount'); + } +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php index bf704359..04fa5e6a 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php @@ -13,6 +13,8 @@ use Illuminate\Http\JsonResponse; 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; class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic @@ -43,6 +45,12 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic /** @var CreditWalletProcessor */ private $creditWalletProcessor; + /** @var CalculatesBookingPayableAmount */ + private $calculatesBookingPayableAmount; + + /** @var CalculatesBookingRefundAmount */ + private $calculatesBookingRefundAmount; + /** * CreatePaymentVerificationDocumentLogic constructor. * @param FetchesCompany $fetchesCompany @@ -50,14 +58,18 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic * @param UpdatesTransactionStatus $updatesTransactionStatus * @param DeletesDocument $deletesDocument * @param CreditWalletProcessor $creditWalletProcessor + * @param CalculatesBookingPayableAmount $calculatesBookingPayableAmount + * @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount */ - public function __construct(FetchesCompany $fetchesCompany, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, DeletesDocument $deletesDocument, CreditWalletProcessor $creditWalletProcessor) + public function __construct(FetchesCompany $fetchesCompany, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, DeletesDocument $deletesDocument, CreditWalletProcessor $creditWalletProcessor, CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingRefundAmount $calculatesBookingRefundAmount) { $this->fetchesCompany = $fetchesCompany; $this->fetchesTransaction = $fetchesTransaction; $this->updatesTransactionStatus = $updatesTransactionStatus; $this->deletesDocument = $deletesDocument; $this->creditWalletProcessor = $creditWalletProcessor; + $this->calculatesBookingPayableAmount = $calculatesBookingPayableAmount; + $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; } /** @@ -69,7 +81,7 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic { $transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); - $transaction = $this->updatesTransactionStatus->execute($transaction, $request->input('status')); + $transaction = $this->updatesTransactionStatus->execute($transaction, $request->route('status')); $booking = $transaction->owner->owner; @@ -81,7 +93,10 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic $this->creditWalletProcessor->execute($booking->company, $transaction->type, $transaction->amount, $reference); } - + $paidAmount = $this->calculatesBookingPayableAmount->execute($booking, $booking->fix_currency_id) - $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id); + if (!$paidAmount > 0) { + $this->updatesTransactionStatus->execute($paymentTransaction, ApprovalStatus::REFUNDED); + } return $this->response([]); } diff --git a/app/Http/Resources/BookingResource.php b/app/Http/Resources/BookingResource.php index f3a7881d..ea3278c4 100644 --- a/app/Http/Resources/BookingResource.php +++ b/app/Http/Resources/BookingResource.php @@ -34,7 +34,7 @@ class BookingResource extends JsonResource 'amount' => $this->fix_amount, 'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)), 'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), - 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) + floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), 'fixed_currency' => new CurrencyResource($this->fixedCurrency), 'convertible_currency' => new CurrencyResource($this->convertibleCurrency), 'conversion_currency' => new CurrencyResource($this->conversionCurrency), @@ -60,7 +60,7 @@ class BookingResource extends JsonResource 'expired_payment_attempts' => TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString())->get()), 'payment_history' => TransactionResource::collection($this->transactions()->where(function($query){ $query->where(function($query){ - $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]); + $query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED, ApprovalStatus::REFUNDED]); })->orWhere(function($query){ $query->where(function($query){ $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]); diff --git a/app/Http/Resources/TransactionResource.php b/app/Http/Resources/TransactionResource.php index 27fd17ab..9e743042 100644 --- a/app/Http/Resources/TransactionResource.php +++ b/app/Http/Resources/TransactionResource.php @@ -45,6 +45,7 @@ class TransactionResource extends JsonResource 'transaction_refunds' => TransactionResource::collection($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->refunds()->get())), 'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'), 'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'), + 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), 'interval' => [ 'value' => $days->gt(Carbon::now()) ? '+' : '-', 'duration' => $days->diff(Carbon::now())->format('%d'), diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index 43e2e96d..00d51f06 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -4,12 +4,12 @@
-
+
Status
-
- {{ item.status === 1 ? 'Pending Verification' : item.status === 4 ? 'Rejected' : 'Processing Payment'}} +
+ {{ item.status === 7 ? 'Refunded' : (item.status === 1 ? 'Processing Payment' : 'Transferred')}}
{{ item.status === 1 ? 'Pending Verification' : item.status === 4 ? 'Rejected' : 'Processing Payment'}} @@ -39,7 +39,7 @@
-
+
@@ -147,13 +147,13 @@
Refunded Amount
-
{{item.original_currency.short_code}} {{(Math.round((totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
{{item.original_currency.short_code}} {{(Math.round((totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
-
{{item.currency.short_code}} {{(Math.round((totalConvertRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
{{item.currency.short_code}} {{(Math.round((totalConvertRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
@@ -292,7 +292,7 @@
-
+
@@ -301,42 +301,83 @@
- +
-
-
-
-
{{ index + 1 }}. Refund updated on
+
+
+
+
Created At
+
+ {{ refund.created_at }} +
+
+
+
Status
+
+
{{ refund.status === 1 ? 'Pending Verification' : refund.status === 2 ? 'Approved' : 'Rejected'}}
+
+
+
+
Amount
+
+
{{refund.currency.short_code}} {{(Math.round((refund.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
-
{{ refund.updated_at }}
+
Amount
+
+
{{refund.original_currency.short_code}} {{(Math.round((refund.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
-
+
-
    Refund status
-
-
-
{{ refund.status === 1 ? 'Pending Verification' : refund.status === 2 ? 'Approved' : 'Rejected'}}
-
-
-
-
-
    Requested Refund Amount
-
-
-
{{refund.original_currency.short_code}} {{(Math.round((refund.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
-
-
-
-
-
-
{{refund.currency.short_code}} {{(Math.round((refund.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+ + + + + + + + + + +
diff --git a/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue b/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue index de2cd48f..ec5f1ac6 100644 --- a/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue +++ b/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue @@ -3,64 +3,42 @@
-
-
-
Request Refund
+
Request Refund
+
+
+
+
+
Refund Type:
+
+
+ {{ method.name }}
-
+
-
+ + + + +
+
+
-
-
-
-
-
-
-
-
-
Refund Type:
-
-
- Full Refund -
-
- Partial Refund -
-
-
-
-
-
- - - - -
-
-
-
-
{{data.booking.fixed_currency.short_code}}
-
-
-
-
-
-
-
-
-
-
+
{{ data.booking.fixed_currency.short_code }}
- +
@@ -71,47 +49,54 @@ \ No newline at end of file + }, + mixins: [FormHandler, ModalFormHandler] +} + diff --git a/resources/assets/vue/components/bookings/elements/RefundVerificationComponent.vue b/resources/assets/vue/components/bookings/elements/RefundVerificationComponent.vue index 42d5682e..24ec68a6 100644 --- a/resources/assets/vue/components/bookings/elements/RefundVerificationComponent.vue +++ b/resources/assets/vue/components/bookings/elements/RefundVerificationComponent.vue @@ -115,7 +115,7 @@ approveRefund(status){ this.isLoading = true; this.parameters.status = status; - this.submit(this.route('api.transaction.refund.status.update', this.data.id), 'put', 'listRefundTransactionSection', true, true); + this.submit(this.route('api.transaction.refund.status.update', this.data.id, status), 'put', 'listRefundTransactionSection', true, true); }, }, mixins: [componentHandler, staticFormHandler] diff --git a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue index 9a1bf774..9b8045f9 100644 --- a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue @@ -240,7 +240,11 @@ }, watch: { 'data': function () { - this.products = this.data.purchase_order.details + if (this.data && this.data.purchase_order && this.data.purchase_order.details) { + this.products = this.data.purchase_order.details; + } else { + this.products = []; + } } }, methods: { diff --git a/routes/transaction.php b/routes/transaction.php index e714d6b7..f2f4a630 100644 --- a/routes/transaction.php +++ b/routes/transaction.php @@ -11,7 +11,7 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' => 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'); - Route::put('/{id}/refund/status/update', 'UpdateRefundTransactionStatusController@update')->name('refund.status.update'); + Route::put('/{id}/refund/status/update/{status}', 'UpdateRefundTransactionStatusController@update')->name('refund.status.update'); route::delete('{id}/bill/delete', 'DeletePaymentProofDocumentController@delete')->name('bill.delete'); From 609b71f549e5062640d464b673bce6842f2603b6 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Mon, 19 Feb 2024 00:57:42 +0800 Subject: [PATCH 043/228] code upfate for refund booking --- .../Services/CalculatesBookingRefundAmount.php | 2 +- .../UpdateRefundTransactionStatusLogic.php | 14 +++++++------- app/Http/Resources/TransactionResource.php | 2 ++ .../elements/PaymentHistoryComponent.vue | 2 +- .../elements/RefundConfirmationComponent.vue | 16 +++++++++++++--- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php b/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php index f6dab1f4..239545af 100644 --- a/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php +++ b/app/Classes/Modules/Bookings/Services/CalculatesBookingRefundAmount.php @@ -18,7 +18,7 @@ class CalculatesBookingRefundAmount return $totalRefundAmount; } - private function calculateRefundAmount($payment, int $type): float + public function calculateRefundAmount($payment, int $type): float { $refundTransactions = $payment->transactions()->refunds()->whereIn('status', [ApprovalStatus::APPROVED]); diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php index 04fa5e6a..d0e5802a 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php @@ -79,18 +79,18 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - $transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); + $refundTransaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); - $transaction = $this->updatesTransactionStatus->execute($transaction, $request->route('status')); + $refundTransaction = $this->updatesTransactionStatus->execute($refundTransaction, $request->route('status')); - $booking = $transaction->owner->owner; + $paymentTransaction = $refundTransaction->owner; - $paymentTransaction = $transaction->owner; + $booking = $paymentTransaction->owner; - $reference = $transaction->amount == $paymentTransaction->amount ? 'Fully Refund for Ref. ' . $booking->marking : 'Partially Refund for Ref. ' . $booking->marking; + $reference = $refundTransaction->amount == $paymentTransaction->amount ? 'Fully Refund for Ref. ' . $booking->marking : 'Partially Refund for Ref. ' . $booking->marking; - if ($transaction->status == ApprovalStatus::APPROVED) { - $this->creditWalletProcessor->execute($booking->company, $transaction->type, $transaction->amount, $reference); + if ($refundTransaction->status == ApprovalStatus::APPROVED) { + $this->creditWalletProcessor->execute($booking->company, $refundTransaction->type, $refundTransaction->amount, $reference); } $paidAmount = $this->calculatesBookingPayableAmount->execute($booking, $booking->fix_currency_id) - $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id); diff --git a/app/Http/Resources/TransactionResource.php b/app/Http/Resources/TransactionResource.php index 9e743042..09967f4c 100644 --- a/app/Http/Resources/TransactionResource.php +++ b/app/Http/Resources/TransactionResource.php @@ -2,6 +2,7 @@ namespace App\Http\Resources; +use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; use App\Classes\ValueObjects\Constants\TransactionType; use App\Models\Booking; use Carbon\Carbon; @@ -43,6 +44,7 @@ class TransactionResource extends JsonResource 'documents' => new DocumentResource($this->documents()->first()), 'transaction_bill' => new TransactionResource($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->bills()->first())), 'transaction_refunds' => TransactionResource::collection($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->refunds()->get())), + 'refunded_amount' => $this->booking ? floatval((App()->make(CalculatesBookingRefundAmount::class))->calculateRefundAmount($this->resource, $this->booking->fix_currency_id)) : null, 'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'), 'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'), 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index 00d51f06..877ec248 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -291,7 +291,7 @@
-
+
diff --git a/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue b/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue index ec5f1ac6..75253aaa 100644 --- a/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue +++ b/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue @@ -35,13 +35,20 @@
+
+
+
Paid Amount: {{ paidAmount }}
+
Refund Amount: {{ refundAmount }}
+
+
- +
@@ -78,11 +85,15 @@ export default { }, computed: { refundAmount() { - return (Math.round((this.data.booking.amount - this.totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2); + // return (Math.round((this.data.booking.amount - this.totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2); + return (Math.round((this.data.original_amount - this.data.refunded_amount + Number.EPSILON) * 100) / 100).toFixed(2); }, refundMaxValue() { return this.refundAmount; }, + paidAmount() { + return this.data.original_amount; + }, }, methods: { submitForm() { @@ -94,7 +105,6 @@ export default { if (this.refundMethod.name === 'Fully Refund') { this.refundAmount = this.refundMaxValue; } - console.log(this.refundAmount); }, }, mixins: [FormHandler, ModalFormHandler] From 9e3c34eb7383e9c2bb6855487e336bfe9de34bc6 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Tue, 20 Feb 2024 22:41:28 +0800 Subject: [PATCH 044/228] change payment status when it has been fully refunded --- .../ControllersLogic/UpdateRefundTransactionStatusLogic.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php index d0e5802a..09e4b102 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php @@ -93,7 +93,7 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic $this->creditWalletProcessor->execute($booking->company, $refundTransaction->type, $refundTransaction->amount, $reference); } - $paidAmount = $this->calculatesBookingPayableAmount->execute($booking, $booking->fix_currency_id) - $this->calculatesBookingRefundAmount->execute($booking, $booking->fix_currency_id); + $paidAmount = $paymentTransaction->original_amount - $this->calculatesBookingRefundAmount->calculateRefundAmount($paymentTransaction, $booking->fix_currency_id); if (!$paidAmount > 0) { $this->updatesTransactionStatus->execute($paymentTransaction, ApprovalStatus::REFUNDED); } From 9aa75630ff3dbff177816678db84d5609b5a4099 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 21 Feb 2024 00:20:45 +0800 Subject: [PATCH 045/228] update code for refund booking --- app/Http/Resources/BookingResource.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Http/Resources/BookingResource.php b/app/Http/Resources/BookingResource.php index 04204a37..6803eec9 100644 --- a/app/Http/Resources/BookingResource.php +++ b/app/Http/Resources/BookingResource.php @@ -32,7 +32,8 @@ class BookingResource extends JsonResource 'amount' => $this->fix_amount, 'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)), 'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), - 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) + floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + // 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) + floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)), + 'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)), 'fixed_currency' => new CurrencyResource($this->fixedCurrency), 'convertible_currency' => new CurrencyResource($this->convertibleCurrency), 'conversion_currency' => new CurrencyResource($this->conversionCurrency), From df17a8497ddc98fcc7ca39ffd1b2bdbd45b0e811 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 21 Feb 2024 00:33:08 +0800 Subject: [PATCH 046/228] comment partial refund function --- .../ControllersLogic/CreateSupplierTransactionLogic.php | 1 + .../sections/SupplierPendingOrdersSectionComponent.vue | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php index fb324267..4c407cf5 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierTransactionLogic.php @@ -82,6 +82,7 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic $payments = $request->input('payments'); + // todo-refund: activate this for partial refund foreach($payments as $payment){ $payment = $this->fetchesTransaction->execute(['id' => $payment['id']]); diff --git a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue index aee9ab40..fa345d58 100644 --- a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue +++ b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue @@ -200,7 +200,9 @@ }, updateList(){ - this.$refs.pendingOrdersList.updateFilters({per_page: 10000, status: 2, type: 1, is_not_fully_refunded: true, original_currency_id_in: [this.selectedCurrency.id], transaction_service_id: this.selectedService.id}); + // todo-refund: activate this for partial refund + // this.$refs.pendingOrdersList.updateFilters({per_page: 10000, status: 2, type: 1, original_currency_id_in: [this.selectedCurrency.id], transaction_service_id: this.selectedService.id, is_not_fully_refunded: true}); + this.$refs.pendingOrdersList.updateFilters({per_page: 10000, status: 2, type: 1, original_currency_id_in: [this.selectedCurrency.id], transaction_service_id: this.selectedService.id}); this.selectedSupplier.status = false; this.currencyDropdownLaunch.status = false; From 25de31ea2e2bb0e653f5ad7091a635ce043d18c3 Mon Sep 17 00:00:00 2001 From: Sai0224 Date: Sat, 24 Feb 2024 12:15:26 +0800 Subject: [PATCH 047/228] supplier bill payment refund module --- .../Eloquent/Filters/BelongsToSupplierId.php | 24 ++++++ ...CreateBillGroupPaymentTransactionLogic.php | 6 ++ .../CreateSupplierBillGroupLogic.php | 57 ++++++++++++- .../ControllersLogic/DeleteBillGroupLogic.php | 17 +++- .../CalculatesBillGroupPaymentAmount.php | 4 +- .../Constants/TransactionType.php | 5 ++ .../ExpiredRefundedBookingCommand.php | 16 ++++ app/Http/Resources/BillGroupResource.php | 19 +++++ app/Http/Resources/TransactionResource.php | 7 +- app/Models/BillGroup.php | 8 ++ app/Models/BillGroupRefund.php | 27 +++++++ app/Models/Transaction.php | 14 ++++ ...222130_create_bill_group_refunds_table.php | 22 +++++ .../bookings/elements/BillGroupComponent.vue | 36 +++++++++ .../BillGroupPaymentSummaryComponent.vue | 13 ++- .../elements/SupplierRefundComponent.vue | 80 +++++++++++++++++++ .../TransactionGroupPaymentComponent.vue | 8 -- ...pplierWhiteFormPlaceOrderFormComponent.vue | 58 +++++++++++++- 18 files changed, 403 insertions(+), 18 deletions(-) create mode 100644 app/Classes/General/Eloquent/Filters/BelongsToSupplierId.php create mode 100644 app/Models/BillGroupRefund.php create mode 100644 database/migrations/2024_02_22_222130_create_bill_group_refunds_table.php create mode 100644 resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue diff --git a/app/Classes/General/Eloquent/Filters/BelongsToSupplierId.php b/app/Classes/General/Eloquent/Filters/BelongsToSupplierId.php new file mode 100644 index 00000000..63536412 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/BelongsToSupplierId.php @@ -0,0 +1,24 @@ +whereHas('owner', function ($q) use ($value) { + $q->whereHas('transactions', function ($q2) use ($value) { + $q2->where('type', TransactionType::BILL)->where('issuer', $value); + }); + }); + } +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php index 5c1ae1bf..92a6343d 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php @@ -68,6 +68,12 @@ class CreateBillGroupPaymentTransactionLogic extends AbstractControllerLogic $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 .'.'); diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php index f89af62c..b67db312 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php @@ -21,9 +21,11 @@ use App\Classes\Modules\Documents\Services\CreatesDocument; use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; use App\Classes\Modules\Transactions\Services\CreatesTransaction; +use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; use App\Classes\ValueObjects\Constants\PaymentMethodType; use App\Classes\ValueObjects\Constants\TransactionType; use App\Models\BillGroup; +use App\Models\Transaction; class CreateSupplierBillGroupLogic extends AbstractControllerLogic { @@ -57,6 +59,9 @@ class CreateSupplierBillGroupLogic extends AbstractControllerLogic /** @var UpdateGroupLogic */ private $updateGroupLogic; + /** @var UpdatesTransactionStatus */ + private $updatesTransactionStatus; + /** * CreateSupplierBillGroupLogic constructor. @@ -66,8 +71,9 @@ class CreateSupplierBillGroupLogic extends AbstractControllerLogic * @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) + public function __construct(FetchesCompany $fetchesCompany, CreatesTransaction $createsTransaction, CreatesDocument $createsDocument, CreatesFiles $createsFile, GeneratesTransactionBillNumber $generatesTransactionBillNumber, UpdateGroupLogic $updateGroupLogic, UpdatesTransactionStatus $updatesTransactionStatus) { $this->fetchesCompany = $fetchesCompany; $this->createsTransaction = $createsTransaction; @@ -75,6 +81,7 @@ class CreateSupplierBillGroupLogic extends AbstractControllerLogic $this->createsFile = $createsFile; $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; $this->updateGroupLogic = $updateGroupLogic; + $this->updatesTransactionStatus = $updatesTransactionStatus; } public function logic(Request $request) : JsonResponse @@ -83,6 +90,19 @@ class CreateSupplierBillGroupLogic extends AbstractControllerLogic $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.'); + } + } $amount = 0; $original_amount = 0; @@ -129,6 +149,41 @@ class CreateSupplierBillGroupLogic extends AbstractControllerLogic $billGroup->groups()->sync($payment['id'], false); } + //create bill refund + foreach ($supplierRefunds as $supplierRefund) { + $refund = Transaction::find($supplierRefund['id']); + $deductedRefunds = $refund->transactions()->where('type', TransactionType::BILL_REFUND)->where('status', ApprovalStatus::APPROVED)->get(); + $refundDeductableAmount = $refund->amount - $deductedRefunds->sum('amount'); + $refundDeductableOriginalAmount = $refund->original_amount - $deductedRefunds->sum('original_amount'); + + $amount -= round($refundDeductableAmount, 2); + $original_amount -= round($refundDeductableOriginalAmount, 2); + + 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/DeleteBillGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/DeleteBillGroupLogic.php index 56464409..1122c111 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/DeleteBillGroupLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/DeleteBillGroupLogic.php @@ -5,6 +5,8 @@ namespace App\Classes\Modules\Transactions\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Transactions\Services\FetchesBillGroup; use App\Classes\Modules\Transactions\Services\DeletesTransaction; +use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; +use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Http\Resources\BillGroupResource; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -28,15 +30,20 @@ class DeleteBillGroupLogic extends AbstractControllerLogic /** @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) + public function __construct(FetchesBillGroup $fetchesBillGroup, DeletesTransaction $deletesTransaction, UpdatesTransactionStatus $updatesTransactionStatus) { $this->fetchesBillGroup = $fetchesBillGroup; $this->deletesTransaction = $deletesTransaction; + $this->updatesTransactionStatus = $updatesTransactionStatus; } /** @@ -59,7 +66,15 @@ class DeleteBillGroupLogic extends AbstractControllerLogic 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)); diff --git a/app/Classes/Modules/Transactions/Services/CalculatesBillGroupPaymentAmount.php b/app/Classes/Modules/Transactions/Services/CalculatesBillGroupPaymentAmount.php index 812f8a3c..1a130b41 100644 --- a/app/Classes/Modules/Transactions/Services/CalculatesBillGroupPaymentAmount.php +++ b/app/Classes/Modules/Transactions/Services/CalculatesBillGroupPaymentAmount.php @@ -8,11 +8,13 @@ use App\Models\BillGroup; class CalculatesBillGroupPaymentAmount { public function execute(BillGroup $billGroup){ + $bill_refund_amount = floatval($billGroup->billRefunds->sum('amount')); $floating_amount = floatval($billGroup->transactions()->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION])->sum('amount')); $paid_amount = floatval($billGroup->transactions()->where('status', ApprovalStatus::APPROVED)->sum('amount')); - $outstanding_amount = $billGroup->amount - $paid_amount - $floating_amount + $billGroup->service_charge; + $outstanding_amount = $billGroup->amount - $bill_refund_amount - $paid_amount - $floating_amount + $billGroup->service_charge; return [ + 'bill_refund_amount' => $bill_refund_amount, 'floating_amount' => $floating_amount, 'paid_amount' => $paid_amount, 'outstanding_amount' => $outstanding_amount, diff --git a/app/Classes/ValueObjects/Constants/TransactionType.php b/app/Classes/ValueObjects/Constants/TransactionType.php index fbab3119..e14930b0 100644 --- a/app/Classes/ValueObjects/Constants/TransactionType.php +++ b/app/Classes/ValueObjects/Constants/TransactionType.php @@ -33,4 +33,9 @@ final class TransactionType { public const CASH_BACK = 13; public const SUPPLIER_PAYMENT = 14; + + public const SUPPLIER_REFUND = 15; + + public const BILL_REFUND = 16; + } diff --git a/app/Console/Commands/ExpiredRefundedBookingCommand.php b/app/Console/Commands/ExpiredRefundedBookingCommand.php index db7e00a7..0fcbd87b 100644 --- a/app/Console/Commands/ExpiredRefundedBookingCommand.php +++ b/app/Console/Commands/ExpiredRefundedBookingCommand.php @@ -151,6 +151,22 @@ class ExpiredRefundedBookingCommand extends Command $transaction = $this->createsTransaction->execute($bookingPayment, $object); } + + if ($bookingInWhiteForm) { + $refund = $bookingPayment->transactions()->supplierRefunds()->where('amount', $transaction->amount)->where('status', ApprovalStatus::APPROVED)->first(); + + if (!$refund) { + $billNumber = $this->generatesTransactionBillNumber->execute('SRFD-'); + + $object = new TransactionObject($billNumber, TransactionType::SUPPLIER_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); + + $transaction = $this->createsTransaction->execute($bookingPayment, $object); + } + } } else { Log::info("Credit note transaction id: {$transaction->id}, booking marking not found, the payment reference is: {$transaction->payment_reference}"); } diff --git a/app/Http/Resources/BillGroupResource.php b/app/Http/Resources/BillGroupResource.php index 6f61aeb7..23c8050e 100644 --- a/app/Http/Resources/BillGroupResource.php +++ b/app/Http/Resources/BillGroupResource.php @@ -18,6 +18,7 @@ class BillGroupResource extends JsonResource public function toArray($request) { $billGroupPayment = (App()->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']; @@ -37,6 +38,7 @@ class BillGroupResource extends JsonResource '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, @@ -58,6 +60,23 @@ class BillGroupResource extends JsonResource '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/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 index 6986ee52..9270d8e8 100644 --- a/app/Models/BillGroup.php +++ b/app/Models/BillGroup.php @@ -29,6 +29,14 @@ class BillGroup extends Model implements Documentable, Transactionable return $this->MorphMany(Transaction::class, 'owner'); } + use HasRelationships; + use \Staudenmeir\EloquentHasManyDeep\HasTableAlias; + + public function billRefunds() + { + return $this->belongsToMany(Transaction::class, BillGroupRefund::class); + } + /** * @return MorphMany */ 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/Transaction.php b/app/Models/Transaction.php index 185fdb36..4161632b 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 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/resources/assets/vue/components/bookings/elements/BillGroupComponent.vue b/resources/assets/vue/components/bookings/elements/BillGroupComponent.vue index 42727055..e93eb1ad 100644 --- a/resources/assets/vue/components/bookings/elements/BillGroupComponent.vue +++ b/resources/assets/vue/components/bookings/elements/BillGroupComponent.vue @@ -58,6 +58,42 @@
+
+
+
Bill Refunds
+
+
+
+
Date
+
+ {{refund.updated_at}} +
+
+
+
Reference
+
+ {{refund.bill_no}} +
+
+
+
Amount
+
+ {{ refund.currency.short_code }} {{ formatAmount(refund.amount) }} +
+
+
+
Status
+
+ {{ refund.statusText }} +
+
+
+
+
+
No Selected Refunds
+
+
+
Payment History
diff --git a/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue b/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue index 9ad4f1d3..c826f154 100644 --- a/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue @@ -36,6 +36,17 @@
MYR 0.00
+
+
+
Bill Refund Total:
+
+
+
- {{selectedBillGroup.currency.short_code}} {{formatAmount(selectedBillGroup.bill_refund_amount)}}
+
+
+
MYR 0.00
+
+
Paid Total:
@@ -69,7 +80,7 @@
MYR 0.00
-
+
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..6626ce56 --- /dev/null +++ b/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue @@ -0,0 +1,80 @@ + + + diff --git a/resources/assets/vue/components/bookings/elements/TransactionGroupPaymentComponent.vue b/resources/assets/vue/components/bookings/elements/TransactionGroupPaymentComponent.vue index b86cdce7..7fdd579f 100644 --- a/resources/assets/vue/components/bookings/elements/TransactionGroupPaymentComponent.vue +++ b/resources/assets/vue/components/bookings/elements/TransactionGroupPaymentComponent.vue @@ -117,14 +117,6 @@ this.active = this.payments.some(payment => payment.id === this.item.id); }, methods: { - deleteGroupTransaction() { - this.isLoading = true; - this.submit(this.route('api.transaction.group.delete', this.item.id), 'delete', this.section, true, true); - }, - updateDo() { - this.isLoading = true; - this.submit(this.route('api.transaction.group.bulk.po'), 'post', this.section, true, true); - }, activate(){ this.active = !this.active; this.$emit('input', this.item) diff --git a/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue index 2ba56062..5b28e017 100644 --- a/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue @@ -16,7 +16,7 @@
Order Total:
-
{{ this.payments.length > 0 ? this.payments[0].original_currency.short_code : "CNY"}} {{(Math.round((this.originalTotal + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
{{ this.payments.length > 0 ? this.payments[0].original_currency.short_code : "CNY"}} {{ formatNumber(this.originalTotal) }}
@@ -24,7 +24,7 @@
-
MYR {{(Math.round((this.total + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
MYR {{ formatNumber(this.total) }}
@@ -43,6 +43,17 @@
{{ billGroupCurrencyRate }}
+
+
+
Bill Refund Total:
+
+
+
- CNY {{ parameters.payment_total }}
+
+
+
- MYR {{ formatNumber(refundTotal > paymentTotal ? paymentTotal : refundTotal) }}
+
+
Payment Total:
@@ -51,7 +62,7 @@
MYR {{ parameters.payment_total }}
-
MYR {{(Math.round((paymentTotal + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
MYR {{ formatNumber(paymentTotal) }}
@@ -84,6 +95,18 @@
+
+
+
+ Supplier Refund +
+ + + +
+
@@ -108,8 +131,16 @@ required: true }, }, + watch: { + 'supplier': function() { + this.supplierRefundListKey ++; + this.supplierRefunds = [] + }, + }, data(){ return { + supplierRefunds: [], + supplierRefundListKey: 1, parameters: { service_charges: '0', payment_total: '0', @@ -150,6 +181,16 @@ paymentTotal(){ return this.total ? this.total + parseFloat(this.parameters.service_charges.replaceAll(',', '')) : 0; }, + refundOriginalTotal(){ + return this.supplierRefunds.reduce(function (total, currentValue) { + return total + currentValue.original_amount; + }, 0); + }, + refundTotal(){ + return this.supplierRefunds.reduce(function (total, currentValue) { + return total + currentValue.amount; + }, 0); + }, billGroupCurrencyRate(){ const paymentTotal = parseFloat(this.parameters.payment_total.replaceAll(',', '')); return this.originalTotal && paymentTotal > 0 ? (this.originalTotal / paymentTotal).toFixed(5) : 1; @@ -162,6 +203,9 @@ submitForm(){ this.parameters = { payments: this.payments, + supplierRefunds: this.supplierRefunds.sort((a, b) => { + return a.amount - b.amount; + }), service_charges: this.is1688Supplier ? '0' : this.parameters.service_charges, payment_total: this.is1688Supplier ? this.parameters.payment_total : '0', }; @@ -170,6 +214,8 @@ }, successHandler(){ this.refreshList(); + this.supplierRefunds = [] + this.supplierRefundListKey ++; this.$store.dispatch('toggleSection', {name: 'paymentInProgressBillGroupList', status: !this.$store.getters.isShowing('paymentInProgressBillGroupList')}); this.parameters = { payments: [], @@ -177,6 +223,12 @@ payment_total: '0', }; }, + refundOrder(supplierRefund){ + this.supplierRefunds.some(item => item.id === supplierRefund.id) ? this.supplierRefunds = this.supplierRefunds.filter(item => item.id !== supplierRefund.id) : this.supplierRefunds.push(supplierRefund); + }, + formatNumber(value) { + return (Math.round((value + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + } }, mixins: [FormHandler] } From 767d6c84fee67eb6065e5d2ee931c24d76ce98f0 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Sun, 25 Feb 2024 20:43:01 +0800 Subject: [PATCH 048/228] update to bill refund for 1688 supplier --- .../CreateSupplierBillGroupLogic.php | 4 +++- .../elements/SupplierRefundComponent.vue | 7 ++++++ ...pplierWhiteFormPlaceOrderFormComponent.vue | 23 ++++++++++++++----- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php index b67db312..ef0560e7 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php @@ -150,7 +150,9 @@ class CreateSupplierBillGroupLogic extends AbstractControllerLogic } //create bill refund - foreach ($supplierRefunds as $supplierRefund) { + $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 = $refund->amount - $deductedRefunds->sum('amount'); diff --git a/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue b/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue index 6626ce56..1a42fe6c 100644 --- a/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue +++ b/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue @@ -19,6 +19,9 @@
Amount
+
{{item.currency.short_code}} {{((Math.round(( item.amount + Number.EPSILON) * 100) / 100)).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
@@ -39,6 +42,10 @@ type: String, required: true }, + is1688Supplier:{ + type: Boolean, + required: true + }, payments:{ type: Array, required: true diff --git a/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue index 5b28e017..9b7f8eb1 100644 --- a/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue @@ -48,10 +48,10 @@
Bill Refund Total:
-
- CNY {{ parameters.payment_total }}
+
- {{ this.supplierRefunds.length > 0 ? this.supplierRefunds[0].currency.short_code : 'MYR' }} {{ this.inputPaymentTotal > 0 ? refundTotal > this.inputPaymentTotal ? this.inputPaymentTotal : formatNumber(refundTotal) : '0.00' }}
-
- MYR {{ formatNumber(refundTotal > paymentTotal ? paymentTotal : refundTotal) }}
+
- {{ this.supplierRefunds[0].currency.short_code }} {{ formatNumber(refundTotal > paymentTotal ? paymentTotal : refundTotal) }}
@@ -59,10 +59,18 @@
Payment Total:
-
MYR {{ parameters.payment_total }}
+
MYR {{ formatNumber(this.inputPaymentTotal) }}
-
MYR {{ formatNumber(paymentTotal) }}
+
MYR {{ formatNumber(paymentTotal - refundTotal > 0 ? (paymentTotal - refundTotal) : 0) }}
+
+
+
+
+
Payment Total After Refund:
+
+
+
{{ this.supplierRefunds.length > 0 ? this.supplierRefunds[0].currency.short_code : 'MYR' }} {{ refundTotal > this.inputPaymentTotal ? '0.00' : formatNumber(this.inputPaymentTotal - refundTotal) }}
@@ -102,7 +110,7 @@
@@ -166,6 +174,9 @@ } }, computed: { + inputPaymentTotal(){ + return parseFloat(this.parameters.payment_total.replaceAll(',', '')); + }, originalTotal(){ return this.payments.reduce(function (total, currentValue) { return total + currentValue.original_amount; @@ -192,7 +203,7 @@ }, 0); }, billGroupCurrencyRate(){ - const paymentTotal = parseFloat(this.parameters.payment_total.replaceAll(',', '')); + const paymentTotal = this.inputPaymentTotal; return this.originalTotal && paymentTotal > 0 ? (this.originalTotal / paymentTotal).toFixed(5) : 1; }, is1688Supplier(){ From 28c0aeff77b7b4cf7ca0985be4f431b2832616c1 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Mon, 26 Feb 2024 00:38:25 +0800 Subject: [PATCH 049/228] dont show payment on homepage if it is in refund process --- .../Filters/DoesNotHaveRefundInProgress.php | 24 +++++++++++++++++++ .../SupplierPendingOrdersSectionComponent.vue | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 app/Classes/General/Eloquent/Filters/DoesNotHaveRefundInProgress.php diff --git a/app/Classes/General/Eloquent/Filters/DoesNotHaveRefundInProgress.php b/app/Classes/General/Eloquent/Filters/DoesNotHaveRefundInProgress.php new file mode 100644 index 00000000..60618626 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/DoesNotHaveRefundInProgress.php @@ -0,0 +1,24 @@ +whereDoesntHave('transactions', function ($query) { + return $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION]); + }); + } +} diff --git a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue index fa345d58..8f6fb8c7 100644 --- a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue +++ b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue @@ -117,7 +117,7 @@
- + @@ -202,7 +202,7 @@ // todo-refund: activate this for partial refund // this.$refs.pendingOrdersList.updateFilters({per_page: 10000, status: 2, type: 1, original_currency_id_in: [this.selectedCurrency.id], transaction_service_id: this.selectedService.id, is_not_fully_refunded: true}); - this.$refs.pendingOrdersList.updateFilters({per_page: 10000, status: 2, type: 1, original_currency_id_in: [this.selectedCurrency.id], transaction_service_id: this.selectedService.id}); + this.$refs.pendingOrdersList.updateFilters({per_page: 10, status: 2, type: 1, original_currency_id_in: [this.selectedCurrency.id], transaction_service_id: this.selectedService.id, does_not_have_refund_in_progress: true}); this.selectedSupplier.status = false; this.currencyDropdownLaunch.status = false; From f84b04c26caa336abad90a87e66991c21f44532c Mon Sep 17 00:00:00 2001 From: edmondlang Date: Tue, 27 Feb 2024 01:08:16 +0800 Subject: [PATCH 050/228] update logging and indentation --- app/Console/Commands/ExpiredBookingCommand.php | 6 ++++-- app/Console/Kernel.php | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/app/Console/Commands/ExpiredBookingCommand.php b/app/Console/Commands/ExpiredBookingCommand.php index ca690c67..5779a9e9 100644 --- a/app/Console/Commands/ExpiredBookingCommand.php +++ b/app/Console/Commands/ExpiredBookingCommand.php @@ -66,9 +66,10 @@ class ExpiredBookingCommand extends Command $transactions = $booking->transactions; foreach ($transactions as $transaction) { + $prevStatus = $transaction->status; $transaction->status = ApprovalStatus::EXPIRED; $transaction->save(); - Log::info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}"); + Log::info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}"); } } @@ -89,9 +90,10 @@ class ExpiredBookingCommand extends Command $transactions = $booking->transactions; foreach ($transactions as $transaction) { + $prevStatus = $transaction->status; $transaction->status = ApprovalStatus::EXPIRED; $transaction->save(); - Log::info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}"); + Log::info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}"); } } } diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 412ed70f..5e9aa8a8 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -45,12 +45,12 @@ class Kernel extends ConsoleKernel ->withoutOverlapping(); $schedule->command('booking:expired') - ->dailyAt('02:00') - ->withoutOverlapping(); + ->dailyAt('02:00') + ->withoutOverlapping(); $schedule->command('purchaseOrder:autoFill') - ->dailyAt('03:00') - ->withoutOverlapping(); + ->dailyAt('03:00') + ->withoutOverlapping(); } /** From 5fd2f6ef7f709a5e676bfd8ecfed9660a6dd0784 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Wed, 28 Feb 2024 01:34:39 +0800 Subject: [PATCH 051/228] -complete supplier bill group when oustanding is 0 -create refund and supplier refund if the request refund order is in white form --- .../CreateBookingRefundLogic.php | 20 +++++++++++++------ ...CreateBillGroupPaymentTransactionLogic.php | 19 +++++++++++------- .../UpdateRefundTransactionStatusLogic.php | 6 ++++++ .../CalculatesBillGroupPaymentAmount.php | 13 ++++++------ .../ExpiredRefundedBookingCommand.php | 4 ++-- .../BillGroupPaymentSummaryComponent.vue | 7 ++++++- .../elements/PaymentHistoryComponent.vue | 2 +- .../elements/SupplierRefundComponent.vue | 10 +++++++++- ...pplierWhiteFormPlaceOrderFormComponent.vue | 2 +- 9 files changed, 58 insertions(+), 25 deletions(-) diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php index 0648629e..c99f42df 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php @@ -75,10 +75,6 @@ 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; $billNumber = $this->generatesTransactionBillNumber->execute('RFD-'); @@ -100,9 +96,21 @@ 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)); + // create supplier refund + if ($transaction->transactions()->bills()->first()) { + $billNumber = $this->generatesTransactionBillNumber->execute('SRFD-'); + $object = new TransactionObject($billNumber, TransactionType::SUPPLIER_REFUND, 1, $booking->company->id, + 1, PaymentMethodType::CASH, + $refundTotal, $request->input('amount'), 1, + $transaction->original_currency_id, $transaction->currency_rate, + 0, 0, null, ApprovalStatus::PENDING_VERIFICATION, [], $transaction->bill_no); + + $transaction = $this->createsTransaction->execute($transaction, $object); + } + + return $this->resourceResponse(new TransactionResource($refund_transaction)); } diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php index 92a6343d..e2fc6dc1 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php @@ -77,13 +77,18 @@ class CreateBillGroupPaymentTransactionLogic extends AbstractControllerLogic $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 .'.'); - $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); - + 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)); } diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php index 09e4b102..02107a77 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php @@ -85,6 +85,8 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic $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; @@ -93,6 +95,10 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic $this->creditWalletProcessor->execute($booking->company, $refundTransaction->type, $refundTransaction->amount, $reference); } + 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 index 1a130b41..f41de813 100644 --- a/app/Classes/Modules/Transactions/Services/CalculatesBillGroupPaymentAmount.php +++ b/app/Classes/Modules/Transactions/Services/CalculatesBillGroupPaymentAmount.php @@ -7,11 +7,13 @@ use App\Models\BillGroup; class CalculatesBillGroupPaymentAmount { - public function execute(BillGroup $billGroup){ - $bill_refund_amount = floatval($billGroup->billRefunds->sum('amount')); - $floating_amount = floatval($billGroup->transactions()->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION])->sum('amount')); - $paid_amount = floatval($billGroup->transactions()->where('status', ApprovalStatus::APPROVED)->sum('amount')); + public function execute(BillGroup $billGroup) + { + $bill_refund_amount = round(floatval($billGroup->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, @@ -20,5 +22,4 @@ class CalculatesBillGroupPaymentAmount 'outstanding_amount' => $outstanding_amount, ]; } - -} \ No newline at end of file +} diff --git a/app/Console/Commands/ExpiredRefundedBookingCommand.php b/app/Console/Commands/ExpiredRefundedBookingCommand.php index 0fcbd87b..6cc24e28 100644 --- a/app/Console/Commands/ExpiredRefundedBookingCommand.php +++ b/app/Console/Commands/ExpiredRefundedBookingCommand.php @@ -140,7 +140,7 @@ class ExpiredRefundedBookingCommand extends Command Log::info("Credit note transaction id: {$transaction->id}, booking is in white form"); } - if (!$refund && !$bookingInWhiteForm) { + if (!$refund) { $billNumber = $this->generatesTransactionBillNumber->execute('RFD-'); $object = new TransactionObject($billNumber, TransactionType::REFUND, 1, $booking->company->id, @@ -153,7 +153,7 @@ class ExpiredRefundedBookingCommand extends Command } if ($bookingInWhiteForm) { - $refund = $bookingPayment->transactions()->supplierRefunds()->where('amount', $transaction->amount)->where('status', ApprovalStatus::APPROVED)->first(); + $refund = $bookingPayment->transactions()->supplierRefunds()->where('amount', $transaction->amount)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first(); if (!$refund) { $billNumber = $this->generatesTransactionBillNumber->execute('SRFD-'); diff --git a/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue b/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue index c826f154..284f681d 100644 --- a/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue @@ -96,11 +96,16 @@
-
+
+
+
+ +
+
diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index 877ec248..82dfcfc5 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -292,7 +292,7 @@
-
+
diff --git a/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue b/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue index 1a42fe6c..872ebef4 100644 --- a/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue +++ b/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue @@ -54,6 +54,10 @@ type: Number, required: true }, + inputPaymentTotal: { + type: Number, + required: true + }, refundTotal: { type: Number, required: true @@ -65,7 +69,11 @@ }, computed: { clickable(){ - return this.refundTotal < this.paymentTotal || this.supplierRefunds.some((i) => this.item.id === i.id ); + if (this.is1688Supplier) { + return this.refundTotal < this.inputPaymentTotal || this.supplierRefunds.some((i) => this.item.id === i.id ); + } else { + return this.refundTotal < this.paymentTotal || this.supplierRefunds.some((i) => this.item.id === i.id ); + } } }, data(){ diff --git a/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue index 9b7f8eb1..4ca36c2e 100644 --- a/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue @@ -110,7 +110,7 @@
From 5c105398246dcef286210d70ace5a99463a0ff5b Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Wed, 28 Feb 2024 20:53:20 +0800 Subject: [PATCH 052/228] resolve supplier refund amount to follow white form rate --- .../Eloquent/Filters/BelongsToSupplierId.php | 24 -------------- .../Filters/CurrencyRateIsNotEqual.php | 20 ++++++++++++ .../General/Eloquent/Filters/ReceiverIn.php | 20 ++++++++++++ .../CreateBookingRefundLogic.php | 15 ++++++--- .../CreateSupplierBillGroupLogic.php | 4 +++ .../ControllersLogic/UpdateGroupLogic.php | 12 +++++++ .../ExpiredRefundedBookingCommand.php | 31 ++++++++++++------- ...pplierWhiteFormPlaceOrderFormComponent.vue | 2 +- 8 files changed, 86 insertions(+), 42 deletions(-) delete mode 100644 app/Classes/General/Eloquent/Filters/BelongsToSupplierId.php create mode 100644 app/Classes/General/Eloquent/Filters/CurrencyRateIsNotEqual.php create mode 100644 app/Classes/General/Eloquent/Filters/ReceiverIn.php diff --git a/app/Classes/General/Eloquent/Filters/BelongsToSupplierId.php b/app/Classes/General/Eloquent/Filters/BelongsToSupplierId.php deleted file mode 100644 index 63536412..00000000 --- a/app/Classes/General/Eloquent/Filters/BelongsToSupplierId.php +++ /dev/null @@ -1,24 +0,0 @@ -whereHas('owner', function ($q) use ($value) { - $q->whereHas('transactions', function ($q2) use ($value) { - $q2->where('type', TransactionType::BILL)->where('issuer', $value); - }); - }); - } -} 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/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/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php index c99f42df..75ad76a1 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php @@ -88,7 +88,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, @@ -98,13 +99,17 @@ class CreateBookingRefundLogic extends AbstractControllerLogic $refund_transaction = $this->createsTransaction->execute($transaction, $object); + $bookingInWhiteForm = $transaction->transactions()->bills()->first(); + // create supplier refund - if ($transaction->transactions()->bills()->first()) { + if ($bookingInWhiteForm) { $billNumber = $this->generatesTransactionBillNumber->execute('SRFD-'); - $object = new TransactionObject($billNumber, TransactionType::SUPPLIER_REFUND, 1, $booking->company->id, + $supplierRefundTotal = bcdiv($request->input('amount'), $bookingInWhiteForm->currency_rate, 7); + + $object = new TransactionObject($billNumber, TransactionType::SUPPLIER_REFUND, 1, $bookingInWhiteForm->issuer, 1, PaymentMethodType::CASH, - $refundTotal, $request->input('amount'), 1, - $transaction->original_currency_id, $transaction->currency_rate, + $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); diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php index ef0560e7..33284726 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php @@ -102,6 +102,10 @@ class CreateSupplierBillGroupLogic extends AbstractControllerLogic 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; 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/Console/Commands/ExpiredRefundedBookingCommand.php b/app/Console/Commands/ExpiredRefundedBookingCommand.php index 6cc24e28..d64cf385 100644 --- a/app/Console/Commands/ExpiredRefundedBookingCommand.php +++ b/app/Console/Commands/ExpiredRefundedBookingCommand.php @@ -114,10 +114,12 @@ class ExpiredRefundedBookingCommand extends Command // check if the booking is fully refund $amountDifference = bcsub($transaction->amount, $bookingPaymentAmount, 7); + $isFullyRefund = false; if (abs($amountDifference) < 0.01) { - // rejecting booking payment transaction - // $bookingPayment->status = ApprovalStatus::REJECTED; - // $bookingPayment->save(); + $isFullyRefund = true; + // update fully refunded booking payment transaction + $bookingPayment->status = ApprovalStatus::REFUNDED; + $bookingPayment->save(); //expired booking // $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); @@ -136,16 +138,12 @@ class ExpiredRefundedBookingCommand extends Command 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) { $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, + $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); @@ -153,15 +151,24 @@ class ExpiredRefundedBookingCommand extends Command } if ($bookingInWhiteForm) { - $refund = $bookingPayment->transactions()->supplierRefunds()->where('amount', $transaction->amount)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first(); + $original_amount = $isFullyRefund ? $bookingPayment->original_amount : bcmul($transaction->amount, $bookingPayment->currency_rate, 7); + $supplier_refund_amount = bcdiv($original_amount, $bookingInWhiteForm->currency_rate, 7); + + Log::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, $booking->company->id, + $object = new TransactionObject($billNumber, TransactionType::SUPPLIER_REFUND, 1, $bookingInWhiteForm->issuer, 1, PaymentMethodType::CASH, - $transaction->amount, $transaction->amount * $bookingPayment->currency_rate, 1, - $bookingPayment->original_currency_id, $bookingPayment->currency_rate, + $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); diff --git a/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue index 4ca36c2e..01c099ed 100644 --- a/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/SupplierWhiteFormPlaceOrderFormComponent.vue @@ -108,7 +108,7 @@
Supplier Refund
- + From ca2f41e95c5d61a172c9a98e10476bc6ca5827b6 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Fri, 1 Mar 2024 08:16:54 +0800 Subject: [PATCH 053/228] fix bug for payment transaction not found after status update to refunded --- .../ExpiredRefundedBookingCommand.php | 124 ++++++++++-------- 1 file changed, 68 insertions(+), 56 deletions(-) diff --git a/app/Console/Commands/ExpiredRefundedBookingCommand.php b/app/Console/Commands/ExpiredRefundedBookingCommand.php index d64cf385..87f44f81 100644 --- a/app/Console/Commands/ExpiredRefundedBookingCommand.php +++ b/app/Console/Commands/ExpiredRefundedBookingCommand.php @@ -107,72 +107,84 @@ 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); - $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); - 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 (!$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); + $bookingPaymentAmount = $bookingPayment->amount; + // check if the booking is fully refund + $amountDifference = bcsub($transaction->amount, $bookingPaymentAmount, 7); + + $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); + 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"); + } - $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); - - Log::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, + $billNumber = $this->generatesTransactionBillNumber->execute('RFD-'); + + $object = new TransactionObject($billNumber, TransactionType::REFUND, 1, $booking->company->id, 1, PaymentMethodType::CASH, - $supplier_refund_amount, $original_amount, 1, - $bookingPayment->original_currency_id, $bookingInWhiteForm->currency_rate, + $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); + + Log::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) { + // Log::info("Credit note transaction id: {$transaction->id}, booking payment refunded"); + // } else { + Log::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}"); From efb909555e0a3edbf15eb95083a1b5a4994400e4 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Fri, 1 Mar 2024 14:28:52 +0800 Subject: [PATCH 054/228] debug payment not showing issue --- routes/web.php | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/routes/web.php b/routes/web.php index a6590c17..1fb2878f 100644 --- a/routes/web.php +++ b/routes/web.php @@ -866,3 +866,55 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, } ); })->name('invoice.fix.byCustomerMarking'); + +Route::get('/transfer/{marking}/payment-details', function ($marking) { + $booking = Booking::where('marking', $marking)->first(); + + $transactions = $booking->transactions()->withTrashed()->get(); + + $statusLabels = [ + 0 => 'PAYMENT_ATTEMPT', + 1 => 'PAYMENT', + 2 => 'INVOICE', + 3 => 'BILL', + 4 => 'PROFORMA', + 5 => 'TOP_UP', + 6 => 'REFUND', + 7 => 'PURCHASE_ORDER', + 8 => 'SUPPLIER_DELIVER', + 9 => 'CREDIT_NOTE', + 10 => 'WITHDRAW', + 11 => 'DEBIT_NOTE', + 12 => 'TRANSFER_FEE', + 13 => 'CASH_BACK', + ]; + + $ApprovalStatus = ApprovalStatus::APPROVAL_STATUS_ID; + + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + + foreach ($transactions as $transaction) { + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + } + + echo ''; + echo '
IDAmountTypeStatusCreated AtDeleted At
' . $transaction->id . '' . $transaction->amount . '' . $statusLabels[$transaction->type] . '' . $ApprovalStatus [$transaction->status] . '' . $transaction->created_at . '' . $transaction->deleted_at . '
'; +}); From 5cf55453fd690186aa03413add24a54d38805a3e Mon Sep 17 00:00:00 2001 From: edmondlang Date: Fri, 1 Mar 2024 21:57:06 +0800 Subject: [PATCH 055/228] show-booking-expired for debug payment not showing --- app/Console/Kernel.php | 12 ++++---- routes/web.php | 70 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 5e9aa8a8..d1f54f52 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -44,13 +44,13 @@ class Kernel extends ConsoleKernel ->appendOutputTo(storage_path().'/logs/delete-bulk-download-files.log') ->withoutOverlapping(); - $schedule->command('booking:expired') - ->dailyAt('02:00') - ->withoutOverlapping(); + // $schedule->command('booking:expired') + // ->dailyAt('02:00') + // ->withoutOverlapping(); - $schedule->command('purchaseOrder:autoFill') - ->dailyAt('03:00') - ->withoutOverlapping(); + // $schedule->command('purchaseOrder:autoFill') + // ->dailyAt('03:00') + // ->withoutOverlapping(); } /** diff --git a/routes/web.php b/routes/web.php index 1fb2878f..44380046 100644 --- a/routes/web.php +++ b/routes/web.php @@ -872,6 +872,8 @@ Route::get('/transfer/{marking}/payment-details', function ($marking) { $transactions = $booking->transactions()->withTrashed()->get(); + $paymentMethods = PaymentMethodType::PAYMENT_METHODS_ID; + $statusLabels = [ 0 => 'PAYMENT_ATTEMPT', 1 => 'PAYMENT', @@ -898,6 +900,7 @@ Route::get('/transfer/{marking}/payment-details', function ($marking) { echo 'Amount'; echo 'Type'; echo 'Status'; + echo 'Payment Method'; echo 'Created At'; echo 'Deleted At'; echo ''; @@ -910,6 +913,7 @@ Route::get('/transfer/{marking}/payment-details', function ($marking) { echo '' . $transaction->amount . ''; echo '' . $statusLabels[$transaction->type] . ''; echo '' . $ApprovalStatus [$transaction->status] . ''; + echo '' . $paymentMethods [$transaction->payment_method] . ''; echo '' . $transaction->created_at . ''; echo '' . $transaction->deleted_at . ''; echo ''; @@ -917,4 +921,70 @@ Route::get('/transfer/{marking}/payment-details', function ($marking) { echo ''; echo ''; + + echo '
'; + echo 'Wallet Details'; + +})->name('booking.details.transactions'); + +Route::get('show-booking-expired', function () { + $transactions = Transaction::where('type', TransactionType::PAYMENT) + ->where('status', ApprovalStatus::EXPIRED) + ->whereDate('updated_at', '>=', '2024-02-16') + ->orderBy('updated_at', 'desc') + ->get(); + // print_r(count($transactions)); + + + $statusLabels = [ + 0 => 'PAYMENT_ATTEMPT', + 1 => 'PAYMENT', + 2 => 'INVOICE', + 3 => 'BILL', + 4 => 'PROFORMA', + 5 => 'TOP_UP', + 6 => 'REFUND', + 7 => 'PURCHASE_ORDER', + 8 => 'SUPPLIER_DELIVER', + 9 => 'CREDIT_NOTE', + 10 => 'WITHDRAW', + 11 => 'DEBIT_NOTE', + 12 => 'TRANSFER_FEE', + 13 => 'CASH_BACK', + ]; + + $ApprovalStatus = ApprovalStatus::APPROVAL_STATUS_ID; + + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + + $counter = 1; + + foreach ($transactions as $transaction) { + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + } + + echo ''; + echo '
CounterIDBookingPaymentsAmountTypeStatusUpdated At
' . $counter++ . '' . $transaction->id . '' . ''.$transaction->owner->marking.'' . '' . 'Payments' . '' . $transaction->amount . '' . $statusLabels[$transaction->type] . '' . $ApprovalStatus [$transaction->status] . '' . $transaction->updated_at . '
'; }); From dfc2ddd09b8809b5db806139d92e4ddc333c2f6f Mon Sep 17 00:00:00 2001 From: edmondlang Date: Fri, 1 Mar 2024 22:49:14 +0800 Subject: [PATCH 056/228] debug payment not showing issue --- routes/web.php | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/routes/web.php b/routes/web.php index 44380046..ddc5ae7e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -922,8 +922,10 @@ Route::get('/transfer/{marking}/payment-details', function ($marking) { echo ''; echo ''; - echo '
'; - echo 'Wallet Details'; + echo '
----------------------------------------------------------------
'; + + echo 'Wallet Details'; + })->name('booking.details.transactions'); @@ -931,6 +933,7 @@ Route::get('show-booking-expired', function () { $transactions = Transaction::where('type', TransactionType::PAYMENT) ->where('status', ApprovalStatus::EXPIRED) ->whereDate('updated_at', '>=', '2024-02-16') + ->take(10) ->orderBy('updated_at', 'desc') ->get(); // print_r(count($transactions)); @@ -954,6 +957,8 @@ Route::get('show-booking-expired', function () { ]; $ApprovalStatus = ApprovalStatus::APPROVAL_STATUS_ID; + + $paymentMethods = PaymentMethodType::PAYMENT_METHODS_ID; echo ''; echo ''; @@ -965,6 +970,8 @@ Route::get('show-booking-expired', function () { echo ''; echo ''; echo ''; + echo ''; + echo ''; echo ''; echo ''; echo ''; @@ -973,6 +980,23 @@ Route::get('show-booking-expired', function () { $counter = 1; foreach ($transactions as $transaction) { + + $billplz_status = null; + + if ($transaction->payment_method == PaymentMethodType::PAYMENT_GATEWAY) { + $response = Http::withBasicAuth(config('billplz.api_key') . ':', '')->get(config('billplz.base_url') . '/api/v3/bills/' . $transaction->payment_reference); + if ($response->successful()) { + $data = $response->json(); + if ($data['paid']) { + $billplz_status = 'Paid'; + } else { + $billplz_status = $transaction->id . " => Fraud"; + } + } else { + $billplz_status = $transaction->id . " => billplz error"; + } + } + echo ''; echo ''; echo ''; @@ -981,6 +1005,8 @@ Route::get('show-booking-expired', function () { echo ''; echo ''; echo ''; + echo ''; + echo ''; echo ''; echo ''; } From b2dd34106ccfea281d1bad2a6fde0e4a2a266a57 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Fri, 1 Mar 2024 22:51:56 +0800 Subject: [PATCH 057/228] debug payment not showing issue --- routes/web.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/routes/web.php b/routes/web.php index ddc5ae7e..bc6730f5 100644 --- a/routes/web.php +++ b/routes/web.php @@ -973,6 +973,7 @@ Route::get('show-booking-expired', function () { echo ''; echo ''; echo ''; + echo ''; echo ''; echo ''; echo ''; @@ -1008,6 +1009,7 @@ Route::get('show-booking-expired', function () { echo ''; echo ''; echo ''; + echo ''; echo ''; } From 42a399999a8edb965da5b5686467ea116f45bf4c Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Fri, 1 Mar 2024 23:28:14 +0800 Subject: [PATCH 058/228] uncomment and log to specific file for booking expired command --- app/Console/Commands/ExpiredBookingCommand.php | 8 ++++---- app/Console/Kernel.php | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/Console/Commands/ExpiredBookingCommand.php b/app/Console/Commands/ExpiredBookingCommand.php index 5779a9e9..2be39c15 100644 --- a/app/Console/Commands/ExpiredBookingCommand.php +++ b/app/Console/Commands/ExpiredBookingCommand.php @@ -62,14 +62,14 @@ class ExpiredBookingCommand extends Command foreach ($bookings as $booking) { $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); - Log::info("Expired Booking without payment & purchase order, booking id: " . $booking->id); + $this->info("Expired Booking without payment & purchase order, booking id: " . $booking->id); $transactions = $booking->transactions; foreach ($transactions as $transaction) { $prevStatus = $transaction->status; $transaction->status = ApprovalStatus::EXPIRED; $transaction->save(); - Log::info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}"); + $this->info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}"); } } @@ -86,14 +86,14 @@ class ExpiredBookingCommand extends Command foreach ($bookings as $booking) { $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); - Log::info("Expired Booking without payment but with purchase order, booking id: " . $booking->id); + $this->info("Expired Booking without payment but with purchase order, booking id: " . $booking->id); $transactions = $booking->transactions; foreach ($transactions as $transaction) { $prevStatus = $transaction->status; $transaction->status = ApprovalStatus::EXPIRED; $transaction->save(); - Log::info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}"); + $this->info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}"); } } } diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index d1f54f52..e455eea1 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -44,9 +44,10 @@ class Kernel extends ConsoleKernel ->appendOutputTo(storage_path().'/logs/delete-bulk-download-files.log') ->withoutOverlapping(); - // $schedule->command('booking:expired') - // ->dailyAt('02:00') - // ->withoutOverlapping(); + $schedule->command('booking:expired') + ->dailyAt('02:00') + ->appendOutputTo(storage_path().'/logs/expire-booking.log') + ->withoutOverlapping(); // $schedule->command('purchaseOrder:autoFill') // ->dailyAt('03:00') From 8b22b49937d5b66d1d6cf0c1b39f838e97c4e7a4 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Sat, 2 Mar 2024 00:25:00 +0800 Subject: [PATCH 059/228] remove testing code --- routes/web.php | 150 ------------------------------------------------- 1 file changed, 150 deletions(-) diff --git a/routes/web.php b/routes/web.php index bc6730f5..a6590c17 100644 --- a/routes/web.php +++ b/routes/web.php @@ -866,153 +866,3 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, } ); })->name('invoice.fix.byCustomerMarking'); - -Route::get('/transfer/{marking}/payment-details', function ($marking) { - $booking = Booking::where('marking', $marking)->first(); - - $transactions = $booking->transactions()->withTrashed()->get(); - - $paymentMethods = PaymentMethodType::PAYMENT_METHODS_ID; - - $statusLabels = [ - 0 => 'PAYMENT_ATTEMPT', - 1 => 'PAYMENT', - 2 => 'INVOICE', - 3 => 'BILL', - 4 => 'PROFORMA', - 5 => 'TOP_UP', - 6 => 'REFUND', - 7 => 'PURCHASE_ORDER', - 8 => 'SUPPLIER_DELIVER', - 9 => 'CREDIT_NOTE', - 10 => 'WITHDRAW', - 11 => 'DEBIT_NOTE', - 12 => 'TRANSFER_FEE', - 13 => 'CASH_BACK', - ]; - - $ApprovalStatus = ApprovalStatus::APPROVAL_STATUS_ID; - - echo '
AmountTypeStatusPayment MethodBillPlz ResponseUpdated At
' . $counter++ . '' . $transaction->id . '' . $transaction->amount . '' . $statusLabels[$transaction->type] . '' . $ApprovalStatus [$transaction->status] . '' . $paymentMethods [$transaction->payment_method] . '' . $billplz_status . '' . $transaction->updated_at . '
Payment MethodBillPlz ResponseUpdated AtCreated At
' . $paymentMethods [$transaction->payment_method] . '' . $billplz_status . '' . $transaction->updated_at . '' . $transaction->created_at . '
'; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - - foreach ($transactions as $transaction) { - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - } - - echo ''; - echo '
IDAmountTypeStatusPayment MethodCreated AtDeleted At
' . $transaction->id . '' . $transaction->amount . '' . $statusLabels[$transaction->type] . '' . $ApprovalStatus [$transaction->status] . '' . $paymentMethods [$transaction->payment_method] . '' . $transaction->created_at . '' . $transaction->deleted_at . '
'; - - echo '
----------------------------------------------------------------
'; - - echo 'Wallet Details'; - - -})->name('booking.details.transactions'); - -Route::get('show-booking-expired', function () { - $transactions = Transaction::where('type', TransactionType::PAYMENT) - ->where('status', ApprovalStatus::EXPIRED) - ->whereDate('updated_at', '>=', '2024-02-16') - ->take(10) - ->orderBy('updated_at', 'desc') - ->get(); - // print_r(count($transactions)); - - - $statusLabels = [ - 0 => 'PAYMENT_ATTEMPT', - 1 => 'PAYMENT', - 2 => 'INVOICE', - 3 => 'BILL', - 4 => 'PROFORMA', - 5 => 'TOP_UP', - 6 => 'REFUND', - 7 => 'PURCHASE_ORDER', - 8 => 'SUPPLIER_DELIVER', - 9 => 'CREDIT_NOTE', - 10 => 'WITHDRAW', - 11 => 'DEBIT_NOTE', - 12 => 'TRANSFER_FEE', - 13 => 'CASH_BACK', - ]; - - $ApprovalStatus = ApprovalStatus::APPROVAL_STATUS_ID; - - $paymentMethods = PaymentMethodType::PAYMENT_METHODS_ID; - - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - - $counter = 1; - - foreach ($transactions as $transaction) { - - $billplz_status = null; - - if ($transaction->payment_method == PaymentMethodType::PAYMENT_GATEWAY) { - $response = Http::withBasicAuth(config('billplz.api_key') . ':', '')->get(config('billplz.base_url') . '/api/v3/bills/' . $transaction->payment_reference); - if ($response->successful()) { - $data = $response->json(); - if ($data['paid']) { - $billplz_status = 'Paid'; - } else { - $billplz_status = $transaction->id . " => Fraud"; - } - } else { - $billplz_status = $transaction->id . " => billplz error"; - } - } - - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - } - - echo ''; - echo '
CounterIDBookingPaymentsAmountTypeStatusPayment MethodBillPlz ResponseUpdated AtCreated At
' . $counter++ . '' . $transaction->id . '' . ''.$transaction->owner->marking.'' . '' . 'Payments' . '' . $transaction->amount . '' . $statusLabels[$transaction->type] . '' . $ApprovalStatus [$transaction->status] . '' . $paymentMethods [$transaction->payment_method] . '' . $billplz_status . '' . $transaction->updated_at . '' . $transaction->created_at . '
'; -}); From 2d5bbac3b1f5d21889f3a7846ae33e7f4b32a010 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Sat, 2 Mar 2024 00:32:55 +0800 Subject: [PATCH 060/228] update ExpiredBookingCommand logging - add timestamp --- app/Console/Commands/ExpiredBookingCommand.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/Console/Commands/ExpiredBookingCommand.php b/app/Console/Commands/ExpiredBookingCommand.php index 2be39c15..fe4f260e 100644 --- a/app/Console/Commands/ExpiredBookingCommand.php +++ b/app/Console/Commands/ExpiredBookingCommand.php @@ -62,14 +62,14 @@ class ExpiredBookingCommand extends Command foreach ($bookings as $booking) { $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); - $this->info("Expired Booking without payment & purchase order, booking id: " . $booking->id); + $this->info(Carbon::now() . " : Expired Booking without payment & purchase order, booking id: " . $booking->id); $transactions = $booking->transactions; foreach ($transactions as $transaction) { $prevStatus = $transaction->status; $transaction->status = ApprovalStatus::EXPIRED; $transaction->save(); - $this->info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}"); + $this->info(Carbon::now() . " : Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}"); } } @@ -86,14 +86,14 @@ class ExpiredBookingCommand extends Command foreach ($bookings as $booking) { $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED); - $this->info("Expired Booking without payment but with purchase order, booking id: " . $booking->id); + $this->info(Carbon::now() . " : Expired Booking without payment but with purchase order, booking id: " . $booking->id); $transactions = $booking->transactions; foreach ($transactions as $transaction) { $prevStatus = $transaction->status; $transaction->status = ApprovalStatus::EXPIRED; $transaction->save(); - $this->info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}"); + $this->info(Carbon::now() . " : Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}. Status before update: {$prevStatus}"); } } } From 73819e967e34f00996b8a069e06010d71439dbd5 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Wed, 6 Mar 2024 20:56:24 +0800 Subject: [PATCH 061/228] open partial refund, categorize refunds section in dashboard --- .../Eloquent/Filters/IsPartialRefund.php | 26 ++++++++ .../OwnerDoesNotHaveTransactionType.php | 24 ++++++++ .../Filters/OwnerHasTransactionType.php | 24 ++++++++ .../elements/RefundConfirmationComponent.vue | 10 ++- .../views/pages/dashboards/admin.blade.php | 61 ++++++++++++++++++- 5 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 app/Classes/General/Eloquent/Filters/IsPartialRefund.php create mode 100644 app/Classes/General/Eloquent/Filters/OwnerDoesNotHaveTransactionType.php create mode 100644 app/Classes/General/Eloquent/Filters/OwnerHasTransactionType.php 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/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue b/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue index 75253aaa..c87122a5 100644 --- a/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue +++ b/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue @@ -38,6 +38,7 @@
Paid Amount: {{ paidAmount }}
+
Paid Amount: {{ (Math.round((this.data.refunded_amount + Number.EPSILON) * 100) / 100).toFixed(2) }}
Refund Amount: {{ refundAmount }}
@@ -69,10 +70,11 @@ export default { }, data() { return { + refundAmount: (Math.round((this.data.original_amount - this.data.refunded_amount + Number.EPSILON) * 100) / 100).toFixed(2), refundMethod: { name: 'Fully Refund', status: false }, refundMethods: [ { name: 'Fully Refund', label: 'Full Refund' }, - // { name: 'Partially Refund', label: 'Partial Refund' } + { name: 'Partially Refund', label: 'Partial Refund' } ] } }, @@ -84,12 +86,8 @@ export default { } }, computed: { - refundAmount() { - // return (Math.round((this.data.booking.amount - this.totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2); - return (Math.round((this.data.original_amount - this.data.refunded_amount + Number.EPSILON) * 100) / 100).toFixed(2); - }, refundMaxValue() { - return this.refundAmount; + return (Math.round((this.data.original_amount - this.data.refunded_amount + Number.EPSILON) * 100) / 100).toFixed(2); }, paidAmount() { return this.data.original_amount; diff --git a/resources/views/pages/dashboards/admin.blade.php b/resources/views/pages/dashboards/admin.blade.php index d7223cc0..7ccdb219 100644 --- a/resources/views/pages/dashboards/admin.blade.php +++ b/resources/views/pages/dashboards/admin.blade.php @@ -81,11 +81,68 @@
+
+
+ Pre-Refund +
+
+
+
+ Fully Refund +
+
- + + +
+
+
+
+ Partial Refund +
+
+
+
+ + + +
+
+
+
+ Post-Refund +
+
+
+
+ Fully Refund +
+
+
+
+ + + +
+
+
+
+ Partial Refund +
+
+
+
+ +
From df7f9531e82ca8fcc3750318716cbd4d7f816cf1 Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Thu, 7 Mar 2024 11:38:03 +0800 Subject: [PATCH 062/228] fix payment history display transfer status --- .../elements/PaymentHistoryComponent.vue | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index 877ec248..90270fee 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -8,8 +8,17 @@
Status
-
- {{ item.status === 7 ? 'Refunded' : (item.status === 1 ? 'Processing Payment' : 'Transferred')}} +
+ {{ item.status === 1 ? 'Pending Verification' : item.status === 4 ? 'Rejected' : 'Processing Payment'}} +
+
+ {{ item.status === 1 ? 'Pending Verification' : item.status === 4 ? 'Rejected' : 'Processing Payment'}} +
+
+
+
Status
+
+ {{ item.status === 7 ? 'Refunded' : (item.status === 1 ? 'Pending Verification' : item.status === 4 ? 'Rejected' : 'Payment Approved')}}
{{ item.status === 1 ? 'Pending Verification' : item.status === 4 ? 'Rejected' : 'Processing Payment'}} @@ -18,7 +27,7 @@
Payment Amount
- {{item.currency.short_code}} {{(Math.round((item.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}} + {{item.original_currency.short_code}} {{(Math.round((item.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
@@ -61,7 +70,7 @@
Status
-
+
{{ item.transaction_bill.status === 1 ? 'Processing Payment' : 'Transferred'}}
From 32224f6803cc36185e53387794063098b12bde8e Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Thu, 7 Mar 2024 11:43:19 +0800 Subject: [PATCH 063/228] fix payment history display transfer status --- .../bookings/elements/PaymentHistoryComponent.vue | 9 --------- 1 file changed, 9 deletions(-) diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index 90270fee..1db22609 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -6,15 +6,6 @@
-
-
Status
-
- {{ item.status === 1 ? 'Pending Verification' : item.status === 4 ? 'Rejected' : 'Processing Payment'}} -
-
- {{ item.status === 1 ? 'Pending Verification' : item.status === 4 ? 'Rejected' : 'Processing Payment'}} -
-
Status
From 70300412467eeeb9b0877c6afb34877c8def563b Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Thu, 7 Mar 2024 11:46:46 +0800 Subject: [PATCH 064/228] fix payment history display transfer status --- .../components/bookings/elements/PaymentHistoryComponent.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index 1db22609..a6556cd2 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -61,7 +61,7 @@
Status
-
+
{{ item.transaction_bill.status === 1 ? 'Processing Payment' : 'Transferred'}}
From b0e3467fbe40bf1590a041509511eb5e7fc60412 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Thu, 7 Mar 2024 15:41:21 +0800 Subject: [PATCH 065/228] export pending order should not export order with refund in progress --- routes/web.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/routes/web.php b/routes/web.php index a6590c17..9016724c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -386,7 +386,11 @@ Route::get('/segments', function (Request $request) { })->name('segments'); Route::get('/pending_orders', function(){ - $payments = Transaction::where('type', TransactionType::PAYMENT)->where('owner_type', Booking::class)->whereIn('status', [ApprovalStatus::APPROVED])->get(); + $payments = Transaction::where('type', TransactionType::PAYMENT)->where('owner_type', Booking::class)->whereIn('status', [ApprovalStatus::APPROVED]) + ->whereDoesntHave('transactions', function ($query) { + return $query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION]); + }) + ->get(); echo ''; $i = 0; From 4d501c8b7c3a27a9104a6947ccd6ca236bda3c90 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Thu, 7 Mar 2024 17:21:18 +0800 Subject: [PATCH 066/228] update log info --- .../ExpiredRefundedBookingCommand.php | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/Console/Commands/ExpiredRefundedBookingCommand.php b/app/Console/Commands/ExpiredRefundedBookingCommand.php index 87f44f81..92900a71 100644 --- a/app/Console/Commands/ExpiredRefundedBookingCommand.php +++ b/app/Console/Commands/ExpiredRefundedBookingCommand.php @@ -95,7 +95,7 @@ class ExpiredRefundedBookingCommand extends Command if (!$bookingPayment) { $bookingPaymentCount = $booking->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; @@ -111,7 +111,7 @@ class ExpiredRefundedBookingCommand extends Command 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}"); + $this->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 @@ -126,11 +126,11 @@ class ExpiredRefundedBookingCommand extends Command //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}"); + $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 { - 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}"); + $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(); @@ -138,7 +138,7 @@ class ExpiredRefundedBookingCommand extends Command $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"); + $this->info("Credit note transaction id: {$transaction->id}, already created same amount of refund transaction for same booking payment transaction"); } if (!$refund) { @@ -157,7 +157,7 @@ class ExpiredRefundedBookingCommand extends Command $original_amount = $isFullyRefund ? $bookingPayment->original_amount : bcmul($transaction->amount, $bookingPayment->currency_rate, 7); $supplier_refund_amount = bcdiv($original_amount, $bookingInWhiteForm->currency_rate, 7); - Log::info("Credit note transaction id: {$transaction->id}, booking is in white form, white form currency rate is {$bookingInWhiteForm->currency_rate}"); + $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); @@ -181,16 +181,16 @@ class ExpiredRefundedBookingCommand extends Command // $bookingPayment = $booking->transactions()->payments()->where('status', ApprovalStatus::REFUNDED)->orderBy('id', 'DESC')->first(); // if ($bookingPayment) { - // Log::info("Credit note transaction id: {$transaction->id}, booking payment refunded"); + // $this->info("Credit note transaction id: {$transaction->id}, booking payment refunded"); // } else { - Log::info("Credit note transaction id: {$transaction->id}, booking payment not found, the payment reference is: {$transaction->payment_reference}"); + $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}"); } } } From 6d8cce464c2ee568bdeaf24a08692843b3e7d61b Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Fri, 8 Mar 2024 03:08:21 +0800 Subject: [PATCH 067/228] don't paginate the pending currency order page --- .../bookings/sections/SupplierPendingOrdersSectionComponent.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue index 8f6fb8c7..fb766fe4 100644 --- a/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue +++ b/resources/assets/vue/components/bookings/sections/SupplierPendingOrdersSectionComponent.vue @@ -202,7 +202,7 @@ // todo-refund: activate this for partial refund // this.$refs.pendingOrdersList.updateFilters({per_page: 10000, status: 2, type: 1, original_currency_id_in: [this.selectedCurrency.id], transaction_service_id: this.selectedService.id, is_not_fully_refunded: true}); - this.$refs.pendingOrdersList.updateFilters({per_page: 10, status: 2, type: 1, original_currency_id_in: [this.selectedCurrency.id], transaction_service_id: this.selectedService.id, does_not_have_refund_in_progress: true}); + this.$refs.pendingOrdersList.updateFilters({per_page: 10000, status: 2, type: 1, original_currency_id_in: [this.selectedCurrency.id], transaction_service_id: this.selectedService.id, does_not_have_refund_in_progress: true}); this.selectedSupplier.status = false; this.currencyDropdownLaunch.status = false; From 2d34b157f59a2256cd7623770214634f26cfc6f5 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Mon, 11 Mar 2024 01:00:38 +0800 Subject: [PATCH 068/228] update refund section to have 2 tabs, where each tab categorized by full and partial refund --- .../views/pages/dashboards/admin.blade.php | 49 ++++++++++++------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/resources/views/pages/dashboards/admin.blade.php b/resources/views/pages/dashboards/admin.blade.php index 7ccdb219..ac5b1d08 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,15 +98,10 @@
-
+
- Pre-Refund -
-
-
-
Fully Refund
@@ -100,8 +114,8 @@
-
-
+
+
Partial Refund
@@ -114,13 +128,12 @@
-
+
+
+
+
+
- Post-Refund -
-
-
-
Fully Refund
@@ -133,8 +146,8 @@
-
-
+
+
Partial Refund
From 626bec90d2381ca7ea1b3f61bd5f739c2434a331 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Mon, 11 Mar 2024 01:14:40 +0800 Subject: [PATCH 069/228] update export pending order so that partial refund booking show correct amount --- routes/web.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/routes/web.php b/routes/web.php index 9016724c..ef5538ab 100644 --- a/routes/web.php +++ b/routes/web.php @@ -25,6 +25,7 @@ use Spatie\Activitylog\Models\Activity; use Webklex\PDFMerger\Facades\PDFMergerFacade as PDFMerger; use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject; use App\Classes\Modules\Bookings\Processors\CreatePurchaseOrderFor1688OrderProcessor; +use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; use App\Classes\Modules\Documents\Services\DeletesDocument; use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionWithInvoiceNoProcessor; use App\Classes\Modules\Transactions\Services\DeletesTransaction; @@ -396,6 +397,8 @@ Route::get('/pending_orders', function(){ $i = 0; foreach ($payments as $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); } @@ -411,11 +414,11 @@ Route::get('/pending_orders', function(){ echo '
'; echo ''; echo ''; - echo ''; + echo ''; echo ''; echo ''; echo ''; - echo ''; + echo ''; echo ''; echo ''; echo ''; From a1bbc69ec51c87695d7da30eb34bf9c91d4f4d37 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Mon, 11 Mar 2024 22:13:01 +0800 Subject: [PATCH 070/228] -update payment amount under payment history section on booking page -export approved refund payment --- .../elements/PaymentHistoryComponent.vue | 16 +++-- routes/web.php | 59 +++++++++++++++++++ 2 files changed, 66 insertions(+), 9 deletions(-) diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index 68213ea2..f3b3fb38 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, ",")}}
diff --git a/routes/web.php b/routes/web.php index bc613043..2370a7fc 100644 --- a/routes/web.php +++ b/routes/web.php @@ -433,6 +433,65 @@ Route::get('/pending_orders', function(){ echo '
'.$booking->marking.''.\App\Classes\ValueObjects\Constants\PaymentMethodType::PAYMENT_METHODS_ID[$payment->payment_method].''.$payment->currency->short_code.''.$payment->amount.''.number_format(bcsub($payment->amount, $refunds, 7), 5, '.', '').''.$booking->company->reference.''.$payment->original_currency->short_code.''.$payment->original_amount.''.number_format(bcsub($payment->original_amount, $original_refunds, 7), 5, '.', '').''.$booking->service->name.''.$payment->updated_at->diffForHumans().'
'; })->name('orders.pending'); +Route::get('/approve_refunds', function(){ + $payments = Transaction::where('type', TransactionType::PAYMENT)->where('owner_type', Booking::class)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED, ApprovalStatus::REFUNDED]) + ->whereHas('transactions', function ($query) { + return $query->where('type', TransactionType::REFUND)->where('status', ApprovalStatus::APPROVED); + }) + ->orderBy('updated_at', 'DESC') + ->get(); + + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + foreach ($payments 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'; + } + + 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 AmountServiceLast 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, '.', '').''.$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(); From 3cd2e244619ae33e537f9cc842c9194defc7e844 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Mon, 11 Mar 2024 22:18:10 +0800 Subject: [PATCH 071/228] add export refunded transactions button --- resources/views/pages/dashboards/admin.blade.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/resources/views/pages/dashboards/admin.blade.php b/resources/views/pages/dashboards/admin.blade.php index ac5b1d08..25a2500e 100644 --- a/resources/views/pages/dashboards/admin.blade.php +++ b/resources/views/pages/dashboards/admin.blade.php @@ -104,6 +104,11 @@
Fully Refund
+
@@ -136,6 +141,11 @@
Fully Refund
+
From b63cea4c09ced24e91cc21185c217c65d433d16e Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Tue, 12 Mar 2024 12:03:49 +0800 Subject: [PATCH 072/228] update purchase order amount and status upon refund approval --- .../UpdateRefundTransactionStatusLogic.php | 11 +++++++++-- .../bookings/forms/PurchaseOrderFormComponent.vue | 10 +++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php index 02107a77..91b82f16 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php @@ -15,7 +15,7 @@ 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; class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic { @@ -91,15 +91,22 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic $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); + 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); + } } if ($supplierRefundTransaction) { $this->updatesTransactionStatus->execute($supplierRefundTransaction, $request->route('status')); } - $paidAmount = $paymentTransaction->original_amount - $this->calculatesBookingRefundAmount->calculateRefundAmount($paymentTransaction, $booking->fix_currency_id); + $paidAmount = $paymentTransaction->original_amount - $refundAmount; if (!$paidAmount > 0) { $this->updatesTransactionStatus->execute($paymentTransaction, ApprovalStatus::REFUNDED); } diff --git a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue index 9b8045f9..8df6cfe3 100644 --- a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue @@ -117,7 +117,7 @@
-
+
-
{{(Math.round(( poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3)}}/{{(Math.round((data.amount + Number.EPSILON) * 1000) / 1000).toFixed(3)}} {{data.fixed_currency.short_code}}
+
{{(Math.round(( poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3)}}/{{(Math.round((data.amount - data.payment_history[0].refunded_amount + Number.EPSILON) * 1000) / 1000).toFixed(3)}} {{data.fixed_currency.short_code}}
- +
-
+
** you purchase order will be saved but wont be approved until your purchase order's total matches your transfer order's total.
@@ -285,7 +285,7 @@ this.submit(route('api.transaction.po.import', this.data.id), 'post', this.section, true, true); }, successHandler(){ - if((Math.round((this.poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3) === (Math.round((this.data.amount + Number.EPSILON) * 1000) / 1000).toFixed(3)){ + if((Math.round((this.poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3) === (Math.round((this.data.amount - data.payment_history[0].refunded_amount + Number.EPSILON) * 1000) / 1000).toFixed(3)){ this.submitted = true; } this.updateList() From 36cde82a19ba93a70230105b2efcd9782f536ccd Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Thu, 14 Mar 2024 15:52:20 +0800 Subject: [PATCH 073/228] Send welcome email with voucher to user upon successful verification of customer email adddress --- .../General/Interfaces/KeyValueInterface.php | 12 ++++ app/Classes/Jobs/SendWelcomeVoucherEmail.php | 70 +++++++++++++++++++ .../ControllersLogic/CreateCustomerLogic.php | 3 +- .../UserEmailVerificationLogic.php | 29 +++++++- .../KeyValuePairObject.php | 44 ++++++++++++ .../Accounts/Services/CreatesKeyValuePair.php | 28 ++++++++ .../ListUserVouchersLogic.php | 7 ++ .../Notifications/WelcomeVoucherEmail.php | 43 ++++++++++++ .../ValueObjects/Constants/Vouchers.php | 8 +++ app/Http/Resources/KeyValueBasicResource.php | 24 +++++++ app/Http/Resources/UserRewardResource.php | 8 +++ app/Http/Resources/VoucherResource.php | 17 +++-- app/Models/KeyValuePair.php | 15 ++++ app/Models/User.php | 21 +++++- ...08_135259_create_key_value_pairs_table.php | 37 ++++++++++ .../SingleUserRewardItemComponent.vue | 7 ++ .../emails/accounts/welcome_voucher.blade.php | 8 +++ routes/web.php | 18 +++-- 18 files changed, 384 insertions(+), 15 deletions(-) create mode 100644 app/Classes/General/Interfaces/KeyValueInterface.php create mode 100644 app/Classes/Jobs/SendWelcomeVoucherEmail.php create mode 100644 app/Classes/Modules/Accounts/DataTransferObjects/KeyValuePairObject.php create mode 100644 app/Classes/Modules/Accounts/Services/CreatesKeyValuePair.php create mode 100644 app/Classes/Notifications/WelcomeVoucherEmail.php create mode 100644 app/Classes/ValueObjects/Constants/Vouchers.php create mode 100644 app/Http/Resources/KeyValueBasicResource.php create mode 100644 app/Models/KeyValuePair.php create mode 100644 database/migrations/2024_03_08_135259_create_key_value_pairs_table.php create mode 100644 resources/views/emails/accounts/welcome_voucher.blade.php diff --git a/app/Classes/General/Interfaces/KeyValueInterface.php b/app/Classes/General/Interfaces/KeyValueInterface.php new file mode 100644 index 00000000..fbee5265 --- /dev/null +++ b/app/Classes/General/Interfaces/KeyValueInterface.php @@ -0,0 +1,12 @@ +user = $user; + $this->voucher = $voucher; + $this->emailSentCount = $emailSentCount; + } + + + public function handle() + { + $currentDatetime = Carbon::now(); + $dateToCompare = Carbon::parse($this->voucher->end_date); + if (!$this->user->hasAttribute($this->voucher->code."_EMAIL_COUNT") + && $this->user->rewards->where('voucher_id', $this->voucher->id)->count() > 0 + && $currentDatetime->isBefore($dateToCompare)) + { + //Key #1 + $keyValuePairObject = new KeyValuePairObject( + $this->voucher->code."_EMAIL_COUNT", + $this->emailSentCount + ); + (App()->make(CreatesKeyValuePair::class))->execute($this->user, $keyValuePairObject); + + //Key #2 + $keyValuePairObject = new KeyValuePairObject( + $this->voucher->code."_EMAIL_DATE_".$this->emailSentCount, + Carbon::now() + ); + (App()->make(CreatesKeyValuePair::class))->execute($this->user, $keyValuePairObject); + + $this->user->notify(new WelcomeVoucherEmail($this->user, $this->voucher)); + } + } +} diff --git a/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php b/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php index fa6a9ae7..0f7bdb61 100644 --- a/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php +++ b/app/Classes/Modules/Accounts/ControllersLogic/CreateCustomerLogic.php @@ -30,6 +30,7 @@ use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\App; use App\Classes\Modules\Segments\Services\CreatesSeasonalSegment; +use App\Classes\ValueObjects\Constants\Vouchers; class CreateCustomerLogic extends AbstractControllerLogic { @@ -159,7 +160,7 @@ class CreateCustomerLogic extends AbstractControllerLogic $this->newCustomerToVoucherifyProcessor->execute($company->id, $user, true); - $this->createVoucherProcessor->execute($user, 'WELCOME50%OFF'); + $this->createVoucherProcessor->execute($user, Vouchers::WELCOME_50_PERCENT_OFF); return $this->response($this->authenticationProcessor->execute($request, false)); diff --git a/app/Classes/Modules/Accounts/ControllersLogic/UserEmailVerificationLogic.php b/app/Classes/Modules/Accounts/ControllersLogic/UserEmailVerificationLogic.php index bae6f5eb..13a8bcc7 100644 --- a/app/Classes/Modules/Accounts/ControllersLogic/UserEmailVerificationLogic.php +++ b/app/Classes/Modules/Accounts/ControllersLogic/UserEmailVerificationLogic.php @@ -9,6 +9,9 @@ use App\Classes\Modules\Accounts\Services\CompletesEmailVerificationAttempt; use App\Classes\Modules\Accounts\Services\FetchesEmailVerificationAttempt; use App\Classes\Modules\Accounts\Services\VerifiesUser; use App\Classes\Modules\Accounts\Standards\Criteria\EmailVerificationActiveAttemptExists; +use App\Classes\Modules\Vouchers\Services\FetchesVoucher; +use App\Classes\Jobs\SendWelcomeVoucherEmail; +use App\Classes\ValueObjects\Constants\Vouchers; use App\Models\UserEmailVerification; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -36,19 +39,29 @@ class UserEmailVerificationLogic extends AbstractControllerLogic /** @var VerifiesUser */ private $verifiesUser; + /** @var SendWelcomeVoucherEmail */ + private $sendWelcomeVoucherEmail; + + /** @var FetchesVoucher */ + private $fetchesVoucher; + /** * UserEmailVerificationLogic constructor. * @param EmailVerificationActiveAttemptExists $emailVerificationActiveAttemptExists * @param CompletesEmailVerificationAttempt $completesEmailVerificationAttempt * @param FetchesEmailVerificationAttempt $fetchesEmailVerificationAttempt * @param VerifiesUser $verifiesUser + * @param SendWelcomeVoucherEmail $sendWelcomeVoucherEmail + * @param FetchesVoucher $fetchesVoucher */ - public function __construct(EmailVerificationActiveAttemptExists $emailVerificationActiveAttemptExists, CompletesEmailVerificationAttempt $completesEmailVerificationAttempt, FetchesEmailVerificationAttempt $fetchesEmailVerificationAttempt, VerifiesUser $verifiesUser) + public function __construct(EmailVerificationActiveAttemptExists $emailVerificationActiveAttemptExists, CompletesEmailVerificationAttempt $completesEmailVerificationAttempt, FetchesEmailVerificationAttempt $fetchesEmailVerificationAttempt, VerifiesUser $verifiesUser, SendWelcomeVoucherEmail $sendWelcomeVoucherEmail, FetchesVoucher $fetchesVoucher) { $this->emailVerificationActiveAttemptExists = $emailVerificationActiveAttemptExists; $this->completesEmailVerificationAttempt = $completesEmailVerificationAttempt; $this->fetchesEmailVerificationAttempt = $fetchesEmailVerificationAttempt; $this->verifiesUser = $verifiesUser; + $this->sendWelcomeVoucherEmail = $sendWelcomeVoucherEmail; + $this->fetchesVoucher = $fetchesVoucher; } /** @@ -68,9 +81,19 @@ class UserEmailVerificationLogic extends AbstractControllerLogic $this->completesEmailVerificationAttempt->execute($attempt); - $this->verifiesUser->execute($attempt->user); + $user = $attempt->user; + $this->verifiesUser->execute($user); + + // if (env('SENDING_EMAIL_WELCOME_VOUCHER_ENABLED', false)){ + if (app()->environment('production') && env('SENDING_EMAIL_WELCOME_VOUCHER_ENABLED', false)){ + try{ //In case voucher got deleted unintentionally + $voucher = $this->fetchesVoucher->execute(['code' => Vouchers::WELCOME_50_PERCENT_OFF]); + if($voucher) $this->sendWelcomeVoucherEmail::dispatch($user, $voucher, 1); + } + catch(\Exception $e){} + } return $this->response([]); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Accounts/DataTransferObjects/KeyValuePairObject.php b/app/Classes/Modules/Accounts/DataTransferObjects/KeyValuePairObject.php new file mode 100644 index 00000000..fd1eff49 --- /dev/null +++ b/app/Classes/Modules/Accounts/DataTransferObjects/KeyValuePairObject.php @@ -0,0 +1,44 @@ +key = $key; + $this->value = $value; + } + + /** + * @return string + */ + public function getKey(): string + { + return $this->key; + } + + /** + * @return string + */ + public function getValue(): string + { + return $this->value; + } + +} diff --git a/app/Classes/Modules/Accounts/Services/CreatesKeyValuePair.php b/app/Classes/Modules/Accounts/Services/CreatesKeyValuePair.php new file mode 100644 index 00000000..c963ec4e --- /dev/null +++ b/app/Classes/Modules/Accounts/Services/CreatesKeyValuePair.php @@ -0,0 +1,28 @@ +key = $object->getKey(); + $model->value = $object->getValue(); + + return $this->handler($kv->attributes(), $model); + + } +} diff --git a/app/Classes/Modules/Vouchers/ControllersLogic/ListUserVouchersLogic.php b/app/Classes/Modules/Vouchers/ControllersLogic/ListUserVouchersLogic.php index 16356f0f..013be9d6 100644 --- a/app/Classes/Modules/Vouchers/ControllersLogic/ListUserVouchersLogic.php +++ b/app/Classes/Modules/Vouchers/ControllersLogic/ListUserVouchersLogic.php @@ -4,9 +4,11 @@ namespace App\Classes\Modules\Vouchers\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Rewards\Services\ListsUserRewards; +use App\Classes\ValueObjects\Constants\RoleTypes; use App\Http\Resources\UserRewardResource; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; class ListUserVouchersLogic extends AbstractControllerLogic { @@ -40,6 +42,11 @@ class ListUserVouchersLogic extends AbstractControllerLogic public function logic(Request $request) : JsonResponse { $query = $this->listsUserRewards->execute($this->listsUserRewards->deserializeFilters($request->input('filters'))); + + if(in_array(Auth::user()->type, RoleTypes::ADMIN_ROLES)){ + $request->merge(['isAdmin' => true]); + } + return $this->collectionResponse(UserRewardResource::collection($query)); } diff --git a/app/Classes/Notifications/WelcomeVoucherEmail.php b/app/Classes/Notifications/WelcomeVoucherEmail.php new file mode 100644 index 00000000..0800b8cc --- /dev/null +++ b/app/Classes/Notifications/WelcomeVoucherEmail.php @@ -0,0 +1,43 @@ +user = $user; + $this->voucher = $voucher; + } + + + public function toMail() + { + $this->voucher->end_date = Carbon::parse($this->voucher->end_date)->format('Y-m-d'); + $mailMessage = (new MailMessage) + ->subject('Welcome Voucher') + ->view('emails.accounts.welcome_voucher', ['user' => $this->user, 'voucher' => $this->voucher]); + + return $mailMessage; + } + + +} diff --git a/app/Classes/ValueObjects/Constants/Vouchers.php b/app/Classes/ValueObjects/Constants/Vouchers.php new file mode 100644 index 00000000..d43194f9 --- /dev/null +++ b/app/Classes/ValueObjects/Constants/Vouchers.php @@ -0,0 +1,8 @@ + $this->id, + 'key' => $this->key, + 'value' => $this->value, + ]; + } +} diff --git a/app/Http/Resources/UserRewardResource.php b/app/Http/Resources/UserRewardResource.php index ed693b4c..b988a1d3 100644 --- a/app/Http/Resources/UserRewardResource.php +++ b/app/Http/Resources/UserRewardResource.php @@ -2,6 +2,7 @@ namespace App\Http\Resources; + use Illuminate\Http\Resources\Json\JsonResource; class UserRewardResource extends JsonResource @@ -14,6 +15,13 @@ class UserRewardResource extends JsonResource */ public function toArray($request) { + $emailReminder = null; + if ($request->has('isAdmin')) { + $keyValuePairs = $this->user->attributes()->get(); + $emailReminder = KeyValueBasicResource::collection($keyValuePairs); + $this->voucher->email = $emailReminder; + } + return [ 'id' => $this->id, 'user_id' => $this->user_id, diff --git a/app/Http/Resources/VoucherResource.php b/app/Http/Resources/VoucherResource.php index 54193eeb..3f3112bb 100644 --- a/app/Http/Resources/VoucherResource.php +++ b/app/Http/Resources/VoucherResource.php @@ -2,6 +2,7 @@ namespace App\Http\Resources; +use ArrayObject; use Illuminate\Http\Resources\Json\JsonResource; class VoucherResource extends JsonResource @@ -14,9 +15,16 @@ class VoucherResource extends JsonResource */ public function toArray($request) { - $filteredRedemptions = $this->redemptions->filter(function ($redemption) { - return $redemption->transaction && $redemption->transaction->owner; - }); + $filteredRedemptions = new ArrayObject([]); + if ($request->has('filters') && str_contains($request->input('filters'), "has_active_reward")) { + $filteredRedemptions = new ArrayObject([]); + } + else{ + $filteredRedemptions = $this->redemptions->filter(function ($redemption) { + return $redemption->transaction && $redemption->transaction->owner; + }); + } + return [ 'id' => $this->id, 'name' => $this->name, @@ -25,7 +33,8 @@ class VoucherResource extends JsonResource 'value' => (float) $this->value, 'start_date' => $this->start_date, 'end_date' => $this->end_date, - 'is_redeemed' => $filteredRedemptions->count() > 0 + 'is_redeemed' => $filteredRedemptions->count() > 0, + 'email' => $this->email ? new KeyValueBasicResource($this->email->where('key', $this->code.'_EMAIL_COUNT')->first()) : null, ]; } } diff --git a/app/Models/KeyValuePair.php b/app/Models/KeyValuePair.php new file mode 100644 index 00000000..3ad6d6cd --- /dev/null +++ b/app/Models/KeyValuePair.php @@ -0,0 +1,15 @@ +morphTo(); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 4bc7ec17..7e0a4aa9 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Classes\General\Interfaces\KeyValueInterface; use App\Classes\General\Interfaces\Voucherifiable; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -26,7 +27,8 @@ class User extends AbstractModel implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, - Voucherifiable + Voucherifiable, + KeyValueInterface { use HasRoles, Notifiable, Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail, SoftDeletes; @@ -101,4 +103,21 @@ class User extends AbstractModel implements { return $this->HasMany(UserReward::class, 'user_id', 'id'); } + + public function hasAttribute(string $key, $value = null): bool + { + $query = $this->attributes()->where('key', $key); + + if ($value !== null) { + $query->where('value', $value); + } + + return $query->exists(); + } + + + public function attributes(): MorphMany + { + return $this->morphMany(KeyValuePair::class, 'owner'); + } } diff --git a/database/migrations/2024_03_08_135259_create_key_value_pairs_table.php b/database/migrations/2024_03_08_135259_create_key_value_pairs_table.php new file mode 100644 index 00000000..b952ff56 --- /dev/null +++ b/database/migrations/2024_03_08_135259_create_key_value_pairs_table.php @@ -0,0 +1,37 @@ +id(); + $table->string('owner_type'); //'user', 'order', 'transaction' + $table->unsignedBigInteger('owner_id'); + $table->string('key'); + $table->string('value'); + $table->timestamps(); + + $table->index(['owner_type', 'owner_id']); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('key_value_pairs'); + } +} diff --git a/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue b/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue index 8f25ab60..9cc2409a 100644 --- a/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue +++ b/resources/assets/vue/components/companies/elements/SingleUserRewardItemComponent.vue @@ -9,6 +9,10 @@

RM{{ item.voucher.value/100 }} Discount

{{ item.voucher.value }}% Discount

+
+ + +
-
+
-
{{(Math.round(( poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3)}}/{{(Math.round((data.amount - data.payment_history[0].refunded_amount + Number.EPSILON) * 1000) / 1000).toFixed(3)}} {{data.fixed_currency.short_code}}
+
{{(Math.round(( poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3)}}/{{(Math.round((data.paid_amount + Number.EPSILON) * 1000) / 1000).toFixed(3)}} {{data.fixed_currency.short_code}}
- +
-
+
** you purchase order will be saved but wont be approved until your purchase order's total matches your transfer order's total.
@@ -285,7 +285,7 @@ this.submit(route('api.transaction.po.import', this.data.id), 'post', this.section, true, true); }, successHandler(){ - if((Math.round((this.poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3) === (Math.round((this.data.amount - data.payment_history[0].refunded_amount + Number.EPSILON) * 1000) / 1000).toFixed(3)){ + if((Math.round((this.poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3) === (Math.round((this.data.paid_amount + Number.EPSILON) * 1000) / 1000).toFixed(3)){ this.submitted = true; } this.updateList() diff --git a/resources/views/pages/dashboards/admin.blade.php b/resources/views/pages/dashboards/admin.blade.php index 25a2500e..ac41424c 100644 --- a/resources/views/pages/dashboards/admin.blade.php +++ b/resources/views/pages/dashboards/admin.blade.php @@ -105,7 +105,7 @@ Fully Refund
@@ -123,6 +123,11 @@
Partial Refund
+
@@ -142,7 +147,7 @@ Fully Refund
@@ -160,6 +165,11 @@
Partial Refund
+
diff --git a/routes/web.php b/routes/web.php index 2370a7fc..ade589a5 100644 --- a/routes/web.php +++ b/routes/web.php @@ -433,13 +433,27 @@ Route::get('/pending_orders', function(){ echo ''; })->name('orders.pending'); -Route::get('/approve_refunds', function(){ +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) { - return $query->where('type', TransactionType::REFUND)->where('status', ApprovalStatus::APPROVED); - }) - ->orderBy('updated_at', 'DESC') - ->get(); + ->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 ''; @@ -452,12 +466,13 @@ Route::get('/approve_refunds', function(){ echo ''; echo ''; echo ''; + echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; - foreach ($payments as $index => $payment){ + 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; @@ -471,6 +486,15 @@ Route::get('/approve_refunds', function(){ $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 ''; @@ -483,6 +507,7 @@ Route::get('/approve_refunds', function(){ echo ''; echo ''; echo ''; + echo ''; echo ''; echo ''; echo ''; From c498aec61dcfb78314caed6b68326763bfbfa27e Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Sat, 16 Mar 2024 09:44:56 +0800 Subject: [PATCH 076/228] -fix purchase order section state issue when refund request is approved on booking page -fix supplier bill group dashboard payment issue --- .../ApproveBillGroupPaymentVerificationLogic.php | 2 +- .../CreateBillGroupPaymentProofDocumentLogic.php | 2 +- .../CreateBillGroupPaymentTransactionLogic.php | 2 +- .../ControllersLogic/CreateSupplierBillGroupLogic.php | 8 ++++---- .../elements/BillGroupPaymentSummaryComponent.vue | 4 ++-- .../bookings/forms/PurchaseOrderFormComponent.vue | 1 + 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/app/Classes/Modules/Transactions/ControllersLogic/ApproveBillGroupPaymentVerificationLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ApproveBillGroupPaymentVerificationLogic.php index f12060b4..00117f9e 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/ApproveBillGroupPaymentVerificationLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/ApproveBillGroupPaymentVerificationLogic.php @@ -81,7 +81,7 @@ class ApproveBillGroupPaymentVerificationLogic extends AbstractControllerLogic $billGroup->status = ApprovalStatus::PENDING_SUBMISSION; $billGroup->save(); } else { - if ($billGroupPayment['outstanding_amount'] <= 0) { + if ($billGroupPayment['outstanding_amount'] <= 0 && $billGroupPayment['floating_amount'] <= 0) { $billGroup->status = ApprovalStatus::APPROVED; $billGroup->save(); } diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentProofDocumentLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentProofDocumentLogic.php index 79e01eb0..2563c230 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentProofDocumentLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentProofDocumentLogic.php @@ -83,7 +83,7 @@ class CreateBillGroupPaymentProofDocumentLogic extends AbstractControllerLogic $billGroup = $transaction->owner; $billGroupPayment = $this->calculatesBillGroupPaymentAmount->execute($billGroup); - if ($billGroupPayment['outstanding_amount'] <= 0) { + if ($billGroupPayment['outstanding_amount'] <= 0 && $billGroup->transactions()->where('status', ApprovalStatus::PENDING_SUBMISSION)->count() === 0) { $billGroup->status = ApprovalStatus::PENDING_VERIFICATION; $billGroup->save(); } diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php index e2fc6dc1..75be47d4 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateBillGroupPaymentTransactionLogic.php @@ -68,7 +68,7 @@ class CreateBillGroupPaymentTransactionLogic extends AbstractControllerLogic $billGroupPayment = $this->calculatesBillGroupPaymentAmount->execute($billGroup); $outstanding_amount = $billGroupPayment['outstanding_amount']; - if ($billGroupPayment['outstanding_amount'] == 0) { + 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.'); } diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php index 33284726..6213f55f 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreateSupplierBillGroupLogic.php @@ -159,11 +159,11 @@ class CreateSupplierBillGroupLogic extends AbstractControllerLogic foreach ($supplierRefunds as $supplierRefund) { $refund = Transaction::find($supplierRefund['id']); $deductedRefunds = $refund->transactions()->where('type', TransactionType::BILL_REFUND)->where('status', ApprovalStatus::APPROVED)->get(); - $refundDeductableAmount = $refund->amount - $deductedRefunds->sum('amount'); - $refundDeductableOriginalAmount = $refund->original_amount - $deductedRefunds->sum('original_amount'); + $refundDeductableAmount = round(($refund->amount - $deductedRefunds->sum('amount')), 2); + $refundDeductableOriginalAmount = round(($refund->original_amount - $deductedRefunds->sum('original_amount')), 2); - $amount -= round($refundDeductableAmount, 2); - $original_amount -= round($refundDeductableOriginalAmount, 2); + $amount -= $refundDeductableAmount; + $original_amount -= $refundDeductableOriginalAmount; if ($amount > 0) { $deductedRefundAmount = $refundDeductableAmount; diff --git a/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue b/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue index 284f681d..f84541d1 100644 --- a/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/BillGroupPaymentSummaryComponent.vue @@ -80,7 +80,7 @@
MYR 0.00
-
+
@@ -101,7 +101,7 @@
-
+
diff --git a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue index 3e0c9ca6..ad3627ba 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 = []; } From 0a12bca442e128fa05c8056bbb2395b182fbee1a Mon Sep 17 00:00:00 2001 From: edmondlang Date: Sun, 17 Mar 2024 15:03:46 +0800 Subject: [PATCH 077/228] check if have refund in progress --- .../bookings/elements/PaymentHistoryComponent.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index f3b3fb38..e3be870f 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -289,7 +289,7 @@
-
+
@@ -434,6 +434,10 @@ TotalRequestedRefund += refunds.status === 2 ? refunds.amount : 0; }); return TotalRequestedRefund; + }, + hasRefundInProgress() { + var refundTransactionsStatus = this.data.transaction_refunds.length > 0 ? this.data.transaction_refunds.map(refund => refund.status) : []; + return refundTransactionsStatus.includes(0) || refundTransactionsStatus.includes(1) } }, methods: { From 01bbb1e21a650b482ce2db52a10aedb6606c9215 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sun, 17 Mar 2024 16:06:47 +0800 Subject: [PATCH 078/228] Amendment on welcome voocher email requested by kexin --- .../views/emails/accounts/welcome_voucher.blade.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/resources/views/emails/accounts/welcome_voucher.blade.php b/resources/views/emails/accounts/welcome_voucher.blade.php index aaf8ccdb..7cd60aa1 100644 --- a/resources/views/emails/accounts/welcome_voucher.blade.php +++ b/resources/views/emails/accounts/welcome_voucher.blade.php @@ -1,8 +1,13 @@ @extends('emails.layout.base') @section('content') -

Hello, {{$user->name}}

-

Welcome to Exchange! We're thrilled to have you onboard as a new member. To kick things off, please use the following voucher for your first purchase

-

Voucher code: {{$voucher->code}}

-

This voucher is valid until {{ $voucher->end_date}}

+ +

Hello from CIEF! Thanks for signing up with us. Thinking about using our RMB payment transfer services? Use code 【{{$voucher->code}}】 and get a 50% discount on your first order. Why not give it a try?

+

Any questions? I'm here to help. Start here: {{env('APP_URL').'/dashboard'}}

+

叮咚!非常感谢您在我们代付网站注册, 您是否对我们的代付服务感兴趣却还在犹豫或者在因为其他因素还没正式使用呢? 如果是首次下单, 不妨使用我们专门为新用户准备的独家优惠, 只需在首次下单时使用代码【{{$voucher->code}}】,就能享有5折的手续费折扣呢! 尝试了一次, 或许你会喜欢我们公司的服务,点击以下网址开始启用吧!

+

{{env('APP_URL').'/dashboard'}}

+

如果您有任何疑问或需要更多信息,随时联系我。我们期待着能为您提供物流以及代付服务!

+ +

Thanks

+

谢谢!

@endsection From 122888f39af6f98471600425cf66d2e1cc2aa5d2 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Mon, 18 Mar 2024 12:58:17 +0800 Subject: [PATCH 079/228] Vue Polling - update info log location when job is not found --- app/Classes/General/Abstracts/AbstractControllerLogic.php | 2 +- config/logging.php | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/Classes/General/Abstracts/AbstractControllerLogic.php b/app/Classes/General/Abstracts/AbstractControllerLogic.php index 61c70f44..f26e2ad0 100644 --- a/app/Classes/General/Abstracts/AbstractControllerLogic.php +++ b/app/Classes/General/Abstracts/AbstractControllerLogic.php @@ -69,7 +69,7 @@ abstract class AbstractControllerLogic } catch (ErrorException|GeneralExceptions $exception){ if ($exception instanceof JobResourceNotFoundException) { - Log::error(sprintf( + Log::channel('vue_polling')->info(sprintf( "Uncaught exception '%s' with message '%s' in %s:%d", get_class($exception), $exception->getMessage(), diff --git a/config/logging.php b/config/logging.php index d0d0a009..e480e00e 100644 --- a/config/logging.php +++ b/config/logging.php @@ -108,6 +108,13 @@ return [ 'driver' => 'errorlog', 'level' => 'debug', ], + + 'vue_polling' => [ + 'driver' => 'single', + 'path' => storage_path('logs/laravel_vue_plling.log'), + 'level' => 'info', + ], + ], ]; From 29d17c4f1f033455c76291df0c42fddd3922b0b4 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Mon, 18 Mar 2024 13:09:12 +0800 Subject: [PATCH 080/228] Vue Polling - update info log location for PerfexCRM --- .../PerfexCRM/Services/ConvertsPerfexCRMLeadToCustomer.php | 2 +- .../Modules/PerfexCRM/Services/CreatesPerfexCRMCustomer.php | 2 +- .../PerfexCRM/Services/CreatesPerfexCRMCustomerContact.php | 2 +- .../PerfexCRM/Services/CreatesPerfexCRMCustomerProject.php | 2 +- .../Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php | 2 +- .../PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php | 2 +- .../Modules/PerfexCRM/Services/CreatesPerfexCRMLead.php | 2 +- .../PerfexCRM/Services/CreatesPerfexCRMMilestone.php | 2 +- .../Modules/PerfexCRM/Services/CreatesPerfexCRMTask.php | 2 +- .../Modules/PerfexCRM/Services/FetchesPerfexCRMCustomer.php | 2 +- .../Modules/PerfexCRM/Services/FetchesPerfexCRMInvoice.php | 2 +- .../Modules/PerfexCRM/Services/FetchesPerfexCRMLead.php | 2 +- .../PerfexCRM/Services/FetchesPerfexCRMMilestone.php | 2 +- .../Modules/PerfexCRM/Services/FetchesPerfexCRMProject.php | 2 +- .../Modules/PerfexCRM/Services/UpdatesPerfexCRMInvoice.php | 2 +- .../Modules/PerfexCRM/Services/UpdatesPerfexCRMLead.php | 2 +- .../Modules/PerfexCRM/Services/UpdatesPerfexCRMProject.php | 2 +- .../Modules/PerfexCRM/Services/UpdatesPerfexCRMTask.php | 2 +- config/logging.php | 6 ++++++ 19 files changed, 24 insertions(+), 18 deletions(-) diff --git a/app/Classes/Modules/PerfexCRM/Services/ConvertsPerfexCRMLeadToCustomer.php b/app/Classes/Modules/PerfexCRM/Services/ConvertsPerfexCRMLeadToCustomer.php index e6e7323e..92e90a52 100644 --- a/app/Classes/Modules/PerfexCRM/Services/ConvertsPerfexCRMLeadToCustomer.php +++ b/app/Classes/Modules/PerfexCRM/Services/ConvertsPerfexCRMLeadToCustomer.php @@ -24,7 +24,7 @@ class ConvertsPerfexCRMLeadToCustomer return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomer.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomer.php index e5a19ce3..b7eabaa7 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomer.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomer.php @@ -27,7 +27,7 @@ class CreatesPerfexCRMCustomer $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerContact.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerContact.php index 519c1495..12d3d7e8 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerContact.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerContact.php @@ -34,7 +34,7 @@ class CreatesPerfexCRMCustomerContact $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerProject.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerProject.php index f5d4de3e..1f513f31 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerProject.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMCustomerProject.php @@ -33,7 +33,7 @@ class CreatesPerfexCRMCustomerProject $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php index ba0c2755..df952c4b 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoice.php @@ -53,7 +53,7 @@ class CreatesPerfexCRMInvoice $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php index f3e92529..64590232 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMInvoicePayment.php @@ -33,7 +33,7 @@ class CreatesPerfexCRMInvoicePayment $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMLead.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMLead.php index 373f4171..5ecef6e7 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMLead.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMLead.php @@ -40,7 +40,7 @@ class CreatesPerfexCRMLead $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMMilestone.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMMilestone.php index 80cb49bf..91afd314 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMMilestone.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMMilestone.php @@ -36,7 +36,7 @@ class CreatesPerfexCRMMilestone $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMTask.php b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMTask.php index feb8f9c8..45105fa9 100644 --- a/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMTask.php +++ b/app/Classes/Modules/PerfexCRM/Services/CreatesPerfexCRMTask.php @@ -56,7 +56,7 @@ class CreatesPerfexCRMTask $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMCustomer.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMCustomer.php index 9f3928f6..6efebec4 100644 --- a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMCustomer.php +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMCustomer.php @@ -24,7 +24,7 @@ class FetchesPerfexCRMCustomer return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMInvoice.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMInvoice.php index cd7aff30..7946cfec 100644 --- a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMInvoice.php +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMInvoice.php @@ -26,7 +26,7 @@ class FetchesPerfexCRMInvoice return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMLead.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMLead.php index df9c754d..a3543b20 100644 --- a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMLead.php +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMLead.php @@ -24,7 +24,7 @@ class FetchesPerfexCRMLead return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMMilestone.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMMilestone.php index 30ae0737..9c482fe7 100644 --- a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMMilestone.php +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMMilestone.php @@ -30,7 +30,7 @@ class FetchesPerfexCRMMilestone return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMProject.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMProject.php index c55f2c01..ce9762d8 100644 --- a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMProject.php +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMProject.php @@ -30,7 +30,7 @@ class FetchesPerfexCRMProject return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMInvoice.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMInvoice.php index 9adb9460..9825dde2 100644 --- a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMInvoice.php +++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMInvoice.php @@ -60,7 +60,7 @@ class UpdatesPerfexCRMInvoice $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMLead.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMLead.php index f8fbc944..69ac7fa8 100644 --- a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMLead.php +++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMLead.php @@ -41,7 +41,7 @@ class UpdatesPerfexCRMLead $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMProject.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMProject.php index cf782806..4b65347e 100644 --- a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMProject.php +++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMProject.php @@ -33,7 +33,7 @@ class UpdatesPerfexCRMProject $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMTask.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMTask.php index 95a09525..053fa16d 100644 --- a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMTask.php +++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMTask.php @@ -40,7 +40,7 @@ class UpdatesPerfexCRMTask $data = $response->json(); return (object) $data; }else{ - Log::error($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/config/logging.php b/config/logging.php index e480e00e..d4894384 100644 --- a/config/logging.php +++ b/config/logging.php @@ -115,6 +115,12 @@ return [ 'level' => 'info', ], + 'perfex_crm' => [ + 'driver' => 'single', + 'path' => storage_path('logs/laravel_perfex_crm.log'), + 'level' => 'info', + ], + ], ]; From 1ca7a25affdbc67ef50fd7300ff737caac77a9d9 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Mon, 18 Mar 2024 13:25:24 +0800 Subject: [PATCH 081/228] Vue Polling - update info log location for PerfexCRM, standardization exercise --- app/Classes/Jobs/UpdatePerfexCRMInvoice.php | 7 +++---- .../Processors/CreatePerfexCRMInvoiceProcessor.php | 4 ++-- .../Processors/FetchPerfexCRMInvoiceProcessor.php | 2 +- .../PerfexCRM/Processors/UpdatePerfexCRMProcessor.php | 4 ++-- .../Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php | 2 +- .../PerfexCRM/Services/UpdatesPerfexCRMCustomer.php | 2 +- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/app/Classes/Jobs/UpdatePerfexCRMInvoice.php b/app/Classes/Jobs/UpdatePerfexCRMInvoice.php index 26131bca..93f26b84 100644 --- a/app/Classes/Jobs/UpdatePerfexCRMInvoice.php +++ b/app/Classes/Jobs/UpdatePerfexCRMInvoice.php @@ -57,16 +57,15 @@ class UpdatePerfexCRMInvoice implements ShouldQueue $number = 'EXC-'.$number; $invoice = (App()->make(FetchesPerfexCRMInvoice::class))->execute($customer->userid,"INV-", $number); - Log::error(json_encode('UpdatePerfexCRMInvoice debug $number: '.$number)); + Log::channel('perfex_crm')->info(json_encode('UpdatePerfexCRMInvoice debug $number: '.$number)); if(is_null($invoice)){ $result = (App()->make(CreatePerfexCRMInvoiceProcessor::class))->execute($transaction); if ($result) { $invoiceId = $result->payload['id']; } else { - // Log::error(json_encode('UpdatePerfexCRMInvoice CreatePerfexCRMInvoiceProcessor failed')); $log['message'] = 'UpdatePerfexCRMInvoice CreatePerfexCRMInvoiceProcessor failed'; - Helper::debugLogger($log); + Log::channel('perfex_crm')->info($log); } } else{ @@ -75,7 +74,7 @@ class UpdatePerfexCRMInvoice implements ShouldQueue //This only run when invoice already exist and the invoice does not have a PAID status if($invoiceStatus != PerfexCRMInvoiceStatus::PAID){ - Log::error(json_encode('UpdatePerfexCRMInvoice debug $this->updatePerfexCRMInvoiceObject->getProjectId(): '.$this->updatePerfexCRMInvoiceObject->getProjectId())); + Log::channel('perfex_crm')->info('UpdatePerfexCRMInvoice debug $this->updatePerfexCRMInvoiceObject->getProjectId(): '.$this->updatePerfexCRMInvoiceObject->getProjectId()); //update invoice (App()->make(UpdatesPerfexCRMInvoice::class))->execute($invoice, $this->updatePerfexCRMInvoiceObject->getProjectId()); diff --git a/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php index 4edb2ef5..dae44588 100644 --- a/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php +++ b/app/Classes/Modules/PerfexCRM/Processors/CreatePerfexCRMInvoiceProcessor.php @@ -108,12 +108,12 @@ class CreatePerfexCRMInvoiceProcessor $email = null; if ($firstSupplier) { $email = $firstSupplier->email; - Log::error('CreatePerfexCRMInvoiceProcessor debug:'.$email); + Log::channel('perfex_crm')->info('CreatePerfexCRMInvoiceProcessor debug:'.$email); } else { $bookingMarking = $transaction->owner->marking; $serviceTypeName = $transaction->owner->company->services()->where('id', $transaction->owner->service_id)->first()->name; $projectName = 'Exchange | '.$serviceTypeName.' | '.$bookingMarking; - Log::error('$projectName: '.$projectName); + Log::channel('perfex_crm')->info('$projectName: '.$projectName); return $email; } diff --git a/app/Classes/Modules/PerfexCRM/Processors/FetchPerfexCRMInvoiceProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/FetchPerfexCRMInvoiceProcessor.php index 4c8ee9bf..c073fb7a 100644 --- a/app/Classes/Modules/PerfexCRM/Processors/FetchPerfexCRMInvoiceProcessor.php +++ b/app/Classes/Modules/PerfexCRM/Processors/FetchPerfexCRMInvoiceProcessor.php @@ -62,7 +62,7 @@ class FetchPerfexCRMInvoiceProcessor $invoiceId = $result->payload['id']; } else { $log['message'] = 'FetchPerfexCRMInvoiceProcessor failed for transaction > bill_no: '.$number; - Helper::debugLogger($log); + Log::channel('perfex_crm')->info($log); } } else{ diff --git a/app/Classes/Modules/PerfexCRM/Processors/UpdatePerfexCRMProcessor.php b/app/Classes/Modules/PerfexCRM/Processors/UpdatePerfexCRMProcessor.php index fbf64be8..ac422c33 100644 --- a/app/Classes/Modules/PerfexCRM/Processors/UpdatePerfexCRMProcessor.php +++ b/app/Classes/Modules/PerfexCRM/Processors/UpdatePerfexCRMProcessor.php @@ -217,8 +217,8 @@ class UpdatePerfexCRMProcessor } $result = $this->fetchesPerfexCRMTask->execute($taskName, $milestoneId, 'project', $projectId, $updatePerfexCRMObject->getInvoiceId()); - // Log::error("UpdatePerfexCRMProcessor task: ".$taskName." , ".json_encode($result)); - Log::error("UpdatePerfexCRMProcessor task: ".$taskName); + // Log::channel('perfex_crm')->info("UpdatePerfexCRMProcessor task: ".$taskName." , ".json_encode($result)); + Log::channel('perfex_crm')->info("UpdatePerfexCRMProcessor task: ".$taskName); if(isset($result->payload)){ //&& $result->payload[0]['status'] == PerfexCRMTaskStatus::NOT_STARTED diff --git a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php index 6cd4f052..0ab2b0fd 100644 --- a/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php +++ b/app/Classes/Modules/PerfexCRM/Services/FetchesPerfexCRMTask.php @@ -44,7 +44,7 @@ class FetchesPerfexCRMTask return (object) $data; }else{ - Helper::debugLogger($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ diff --git a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMCustomer.php b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMCustomer.php index 6d91c081..15963c31 100644 --- a/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMCustomer.php +++ b/app/Classes/Modules/PerfexCRM/Services/UpdatesPerfexCRMCustomer.php @@ -38,7 +38,7 @@ class UpdatesPerfexCRMCustomer $data = $response->json(); return (object) $data; }else{ - Helper::debugLogger($response); + Log::channel('perfex_crm')->info($response); return null; } }catch(\Exception $exception){ From 15482469a6673350f4fcada22b939cdb5f45dbcd Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Mon, 18 Mar 2024 13:29:51 +0800 Subject: [PATCH 082/228] Vue Polling - update info log location for PerfexCRM, standardization exercise --- app/Classes/Jobs/UpdatePerfexCRMInvoice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Classes/Jobs/UpdatePerfexCRMInvoice.php b/app/Classes/Jobs/UpdatePerfexCRMInvoice.php index 93f26b84..80a60c15 100644 --- a/app/Classes/Jobs/UpdatePerfexCRMInvoice.php +++ b/app/Classes/Jobs/UpdatePerfexCRMInvoice.php @@ -57,7 +57,7 @@ class UpdatePerfexCRMInvoice implements ShouldQueue $number = 'EXC-'.$number; $invoice = (App()->make(FetchesPerfexCRMInvoice::class))->execute($customer->userid,"INV-", $number); - Log::channel('perfex_crm')->info(json_encode('UpdatePerfexCRMInvoice debug $number: '.$number)); + Log::channel('perfex_crm')->info(('UpdatePerfexCRMInvoice debug $number: '.$number)); if(is_null($invoice)){ $result = (App()->make(CreatePerfexCRMInvoiceProcessor::class))->execute($transaction); From daa422d41ae15d57c5fb8ef4a65e388256c9a11b Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Mon, 18 Mar 2024 22:13:05 +0800 Subject: [PATCH 083/228] -auto update booking fix amount once refund approve --- .../Services/CalculatesBookingOutstanding.php | 9 +++++++-- .../UpdateRefundTransactionStatusLogic.php | 17 ++++++++++++++--- .../elements/SupplierPendingOrderComponent.vue | 4 ++-- 3 files changed, 23 insertions(+), 7 deletions(-) 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/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php index 91b82f16..25db0f31 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php @@ -4,6 +4,7 @@ namespace App\Classes\Modules\Transactions\ControllersLogic; 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; @@ -51,6 +52,9 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic /** @var CalculatesBookingRefundAmount */ private $calculatesBookingRefundAmount; + /** @var UpdateBookingAmountLogic */ + private $updateBookingAmountLogic; + /** * CreatePaymentVerificationDocumentLogic constructor. * @param FetchesCompany $fetchesCompany @@ -60,8 +64,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 +75,7 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic $this->creditWalletProcessor = $creditWalletProcessor; $this->calculatesBookingPayableAmount = $calculatesBookingPayableAmount; $this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount; + $this->updateBookingAmountLogic = $updateBookingAmountLogic; } /** @@ -93,20 +99,25 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic $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'] = $paidAmount; + $request->route()->setParameter('id', $booking->id); + $this->updateBookingAmountLogic->execute($request); } if ($supplierRefundTransaction) { $this->updatesTransactionStatus->execute($supplierRefundTransaction, $request->route('status')); } - $paidAmount = $paymentTransaction->original_amount - $refundAmount; if (!$paidAmount > 0) { $this->updatesTransactionStatus->execute($paymentTransaction, ApprovalStatus::REFUNDED); } 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}}
-
+
From 04b8dfb0ddb52c6877eb07ec29506145256b0461 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Tue, 19 Mar 2024 00:23:09 +0800 Subject: [PATCH 084/228] -fix issue where cannot approve PO when we have refunded transaction --- .../Bookings/Services/CalculatesBookingTransferredAmount.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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'); } From c95c274db7ded39b5c070e72a3dbc74109f20836 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Mon, 25 Mar 2024 00:47:52 +0800 Subject: [PATCH 085/228] update --- .../bookings/elements/SupplierRefundComponent.vue | 9 ++++++--- .../bookings/forms/PurchaseOrderFormComponent.vue | 10 +++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue b/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue index 872ebef4..68839221 100644 --- a/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue +++ b/resources/assets/vue/components/bookings/elements/SupplierRefundComponent.vue @@ -17,11 +17,14 @@ {{item.created_at}}
+
+
Reference
+ +
Amount
-
{{item.currency.short_code}} {{((Math.round(( item.amount + Number.EPSILON) * 100) / 100)).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
diff --git a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue index ad3627ba..b9a0f2d6 100644 --- a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue @@ -117,7 +117,7 @@
-
+
-
{{(Math.round(( poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3)}}/{{(Math.round((data.paid_amount + Number.EPSILON) * 1000) / 1000).toFixed(3)}} {{data.fixed_currency.short_code}}
+
{{(Math.round(( poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3)}}/{{(Math.round((data.amount + Number.EPSILON) * 1000) / 1000).toFixed(3)}} {{data.fixed_currency.short_code}}
- +
-
+
** you purchase order will be saved but wont be approved until your purchase order's total matches your transfer order's total.
@@ -286,7 +286,7 @@ this.submit(route('api.transaction.po.import', this.data.id), 'post', this.section, true, true); }, successHandler(){ - if((Math.round((this.poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3) === (Math.round((this.data.paid_amount + Number.EPSILON) * 1000) / 1000).toFixed(3)){ + if((Math.round((this.poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3) === (Math.round((this.data.amount + Number.EPSILON) * 1000) / 1000).toFixed(3)){ this.submitted = true; } this.updateList() From 3deba3468aec8eb4b2526c4370eea62b50a18077 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Mon, 25 Mar 2024 15:06:46 +0800 Subject: [PATCH 086/228] -Approve refund - only super admin -If invoice generated - only super admin can request refund --- .../ControllersLogic/CreateBookingRefundLogic.php | 10 ++++++---- .../UpdateRefundTransactionStatusLogic.php | 7 ++++++- .../bookings/elements/PaymentHistoryComponent.vue | 4 ++-- .../bookings/elements/RefundVerificationComponent.vue | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php index 062db191..7e176363 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php @@ -73,14 +73,16 @@ class CreateBookingRefundLogic 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.'); - } - $transaction = $this->fetchesTransaction->execute(['id' => $request->route('payment_id')]); $booking = $transaction->owner; + $invoice = $booking->transactions()->where('type', TransactionType::INVOICE)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first(); + + if(auth()->user()->type === 3 || ($invoice && !(auth()->user()->type === 0 || auth()->user()->type === 1))) { + 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'); diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php index 25db0f31..615ded20 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php @@ -2,7 +2,7 @@ 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; @@ -17,6 +17,7 @@ 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 { @@ -85,6 +86,10 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { + if (!(Auth::user()->type === 0 || Auth::user()->type === 1)) { + throw new MalformedRequestException('Only super admin can update refund status.'); + } + $refundTransaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); $refundTransaction = $this->updatesTransactionStatus->execute($refundTransaction, $request->route('status')); diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index e3be870f..ec0c0d7a 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -290,7 +290,7 @@
-
+
@@ -345,7 +345,7 @@
-
+
-
+
From 3af3c95032ba9592d62d7085800c8840719c30aa Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 27 Mar 2024 01:09:55 +0800 Subject: [PATCH 087/228] show white form transactions in date range --- routes/web.php | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/routes/web.php b/routes/web.php index b90ef72e..d6798271 100644 --- a/routes/web.php +++ b/routes/web.php @@ -879,3 +879,61 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, } ); })->name('invoice.fix.byCustomerMarking'); + + +Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', function ($from_date, $to_date) { + $approvedTransactions = Transaction::where('type', TransactionType::PAYMENT)->where('status', ApprovalStatus::APPROVED)->where('owner_type', '!=', Wallet::class)->get(); + + echo '

Approved Payments

'; + echo '
Refunded Original AmountRemarkServiceLast Updated AtBank TypeBank Holder Name
'.($index + 1).'.'.$payment->updated_at->format('d-M-y').''.$payment->original_currency->short_code.''.number_format($original_refunds, 5, '.', '').''.$remark.''.$booking->service->name.''.$payment->updated_at->diffForHumans().''.$bankType.'
'; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + + foreach ($approvedTransactions as $approvedTransaction) { + echo ''; + echo ''; + echo ''; + echo ''; + } + + echo ''; + echo '
BookingPayment Date
' . $approvedTransaction->owner->marking . '' . $approvedTransaction->created_at . '
'; + + $startDate = Carbon::createFromFormat('d-m-Y', $from_date)->startOfDay(); + $endDate = Carbon::createFromFormat('d-m-Y', $to_date)->endOfDay(); + + $approvalSatatusArray = ApprovalStatus::APPROVAL_STATUS_ID; + + echo '

Bills in the date range

'; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + + + $datas = Transaction::where('type', TransactionType::BILL)->whereBetween('created_at', [$startDate, $endDate])->get(); + + foreach ($datas as $data) { + echo ''; + $payment = $data->owner; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + } + + echo ''; + echo '
StatusBills Created AtBookingPayment Date
' . $approvalSatatusArray[$data['status']] . '' . $data->created_at . '' . $data->owner->owner->marking . '' . $payment->created_at . '
'; +}); From 937610272c3a8bf84b61227ac236acdc3cfb4d81 Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Wed, 27 Mar 2024 09:42:24 +0800 Subject: [PATCH 088/228] tidy up whiteform report --- routes/web.php | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/routes/web.php b/routes/web.php index d6798271..06e0dc67 100644 --- a/routes/web.php +++ b/routes/web.php @@ -882,14 +882,17 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', function ($from_date, $to_date) { - $approvedTransactions = Transaction::where('type', TransactionType::PAYMENT)->where('status', ApprovalStatus::APPROVED)->where('owner_type', '!=', Wallet::class)->get(); - echo '

Approved Payments

'; + $approvedTransactions = Transaction::where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->where('owner_type', '!=', Wallet::class)->orderBy('status')->get(); + + echo '

Pending Orders Payments

'; echo ''; echo ''; echo ''; echo ''; + echo ''; echo ''; + echo ''; echo ''; echo ''; echo ''; @@ -897,7 +900,9 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', foreach ($approvedTransactions as $approvedTransaction) { echo ''; echo ''; + echo ''; echo ''; + echo ''; echo ''; } @@ -907,30 +912,34 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', $startDate = Carbon::createFromFormat('d-m-Y', $from_date)->startOfDay(); $endDate = Carbon::createFromFormat('d-m-Y', $to_date)->endOfDay(); - $approvalSatatusArray = ApprovalStatus::APPROVAL_STATUS_ID; echo '

Bills in the date range

'; echo '
BookingAmountPayment DateStatus
' . $approvedTransaction->owner->marking . '' . $approvedTransaction->amount . '' . $approvedTransaction->created_at . '' . ApprovalStatus::APPROVAL_STATUS_ID[$approvedTransaction->status] . '
'; echo ''; echo ''; - echo ''; - echo ''; echo ''; - echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; echo ''; echo ''; echo ''; - $datas = Transaction::where('type', TransactionType::BILL)->whereBetween('created_at', [$startDate, $endDate])->get(); + $bills = Transaction::where('type', TransactionType::BILL)->whereBetween('created_at', [$startDate, $endDate])->get(); - foreach ($datas as $data) { + foreach ($bills as $bill) { echo ''; - $payment = $data->owner; - echo ''; - echo ''; - echo ''; + $payment = $bill->owner; + $po = $payment->owner->transaction()->where('type', TransactionType::PURCHASE_ORDER)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->first(); + echo ''; echo ''; + echo ''; + echo ''; + echo ''; + echo ''; echo ''; } From 9a6e41ff3b17553aa838acf65cba7c57946c8d35 Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Wed, 27 Mar 2024 09:47:42 +0800 Subject: [PATCH 089/228] tidy up whiteform report --- routes/web.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/routes/web.php b/routes/web.php index 06e0dc67..246cb94b 100644 --- a/routes/web.php +++ b/routes/web.php @@ -900,7 +900,7 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', foreach ($approvedTransactions as $approvedTransaction) { echo ''; echo ''; - echo ''; + echo ''; echo ''; echo ''; echo ''; @@ -918,8 +918,10 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo ''; echo ''; echo ''; + echo ''; echo ''; echo ''; + echo ''; echo ''; echo ''; echo ''; @@ -933,10 +935,11 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', foreach ($bills as $bill) { echo ''; $payment = $bill->owner; - $po = $payment->owner->transaction()->where('type', TransactionType::PURCHASE_ORDER)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->first(); + $po = $payment->owner->transactions()->where('type', TransactionType::PURCHASE_ORDER)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->first(); echo ''; echo ''; echo ''; + echo ''; echo ''; echo ''; echo ''; From baa8551b66aff21e8b3e4204ffdbaa255f66b59c Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Wed, 27 Mar 2024 09:54:58 +0800 Subject: [PATCH 090/228] tidy up whiteform report --- routes/web.php | 1 + 1 file changed, 1 insertion(+) diff --git a/routes/web.php b/routes/web.php index 246cb94b..ab187f16 100644 --- a/routes/web.php +++ b/routes/web.php @@ -936,6 +936,7 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo ''; $payment = $bill->owner; $po = $payment->owner->transactions()->where('type', TransactionType::PURCHASE_ORDER)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->first(); + var_dump($po); echo ''; echo ''; echo ''; From eb857937983887ad7ecc65c41137e863fe8372dc Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Wed, 27 Mar 2024 10:02:25 +0800 Subject: [PATCH 091/228] tidy up whiteform report --- routes/web.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/routes/web.php b/routes/web.php index ab187f16..d899f657 100644 --- a/routes/web.php +++ b/routes/web.php @@ -936,13 +936,12 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo ''; $payment = $bill->owner; $po = $payment->owner->transactions()->where('type', TransactionType::PURCHASE_ORDER)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->first(); - var_dump($po); echo ''; echo ''; echo ''; echo ''; echo ''; - echo ''; +// echo ''; echo ''; echo ''; } From b9765fbcf7e5b60652927a70d67b101236040391 Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Wed, 27 Mar 2024 10:03:26 +0800 Subject: [PATCH 092/228] tidy up whiteform report --- routes/web.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/routes/web.php b/routes/web.php index d899f657..6f4d12e7 100644 --- a/routes/web.php +++ b/routes/web.php @@ -941,8 +941,8 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo ''; echo ''; echo ''; -// echo ''; - echo ''; + echo ''; + echo ''; echo ''; } From bb1cb6d44e4300ee253a28f486738d95a58cb0c1 Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Wed, 27 Mar 2024 10:11:02 +0800 Subject: [PATCH 093/228] tidy up whiteform report --- routes/web.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/routes/web.php b/routes/web.php index 6f4d12e7..1143c48c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -901,7 +901,7 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo ''; echo ''; echo ''; - echo ''; + echo ''; echo ''; echo ''; } @@ -937,12 +937,13 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', $payment = $bill->owner; $po = $payment->owner->transactions()->where('type', TransactionType::PURCHASE_ORDER)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->first(); echo ''; - echo ''; - echo ''; + echo ''; + echo ''; + echo ''; echo ''; - echo ''; - echo ''; - echo ''; + echo ''; + echo ''; + echo ''; echo ''; } From dc61f23fa88a9df088d000f973cf8fbcc8c2618d Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Mon, 1 Apr 2024 12:59:30 +0800 Subject: [PATCH 094/228] include pending verification status to expirying payment function --- .../ControllersLogic/ExpireBookingPaymentControllerLogic.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Classes/Modules/Bookings/ControllersLogic/ExpireBookingPaymentControllerLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/ExpireBookingPaymentControllerLogic.php index 8ee2bbfa..1b0a9ebb 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/ExpireBookingPaymentControllerLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/ExpireBookingPaymentControllerLogic.php @@ -45,7 +45,7 @@ class ExpireBookingPaymentControllerLogic extends AbstractControllerLogic $booking = $this->fetchesBooking->execute(['id' => $request->route('id')]); $payment = $booking->transactions() - ->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]) + ->payments()->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]) ->first(); $payment->status = ApprovalStatus::EXPIRED; From 02d28f8fba43548b9e1c00865981d751cd8cdc54 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Mon, 8 Apr 2024 21:17:37 +0800 Subject: [PATCH 095/228] fix invoice amount not tally when voucher is apply for booking --- .../CalculatesBookingCurrencyAverageRate.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) 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) { From aeb0be11bf935becee6301f215750eaa3fdd5387 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Tue, 9 Apr 2024 00:20:19 +0800 Subject: [PATCH 096/228] remove - in the invoice discount section, amount is already in negative --- resources/views/pages/pdfs/purchase_order_table.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 @@ - + @endif From 69e9328e748673128839a993f019670a0145305e Mon Sep 17 00:00:00 2001 From: edmondlang Date: Tue, 16 Apr 2024 22:34:41 +0800 Subject: [PATCH 097/228] fix bug cant approve the refund because booking amount cant be updated, error - Booking Amount cannot be less than xxxxx --- .../Bookings/ControllersLogic/UpdateBookingAmountLogic.php | 2 +- .../ControllersLogic/UpdateRefundTransactionStatusLogic.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php index 615ded20..d2fa5ec6 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php @@ -114,7 +114,7 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic $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'] = $paidAmount; + $request['fix_amount'] = $booking->fix_amount - $refundAmount; $request->route()->setParameter('id', $booking->id); $this->updateBookingAmountLogic->execute($request); } From a8c13e9425dae66b93fb459d52019c735ec2cd48 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Mon, 22 Apr 2024 18:25:48 +0800 Subject: [PATCH 098/228] comment DB::commit() to fix the database seeder --- database/seeds/DatabaseSeeder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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(); } } From 332a12008c37e412620cbe2fb17a2a24483be806 Mon Sep 17 00:00:00 2001 From: Dodowingster Date: Wed, 24 Apr 2024 15:18:28 +0800 Subject: [PATCH 099/228] initial commit --- .../ControllersLogic/CreateRemarkLogic.php | 62 ++++++++++++++++ .../ControllersLogic/DeleteRemarkLogic.php | 66 +++++++++++++++++ .../ControllersLogic/FetchRemarkLogic.php | 59 +++++++++++++++ .../ControllersLogic/ListRemarksLogic.php | 59 +++++++++++++++ .../ControllersLogic/UpdateRemarkLogic.php | 71 ++++++++++++++++++ .../DataTransferObjects/RemarkObject.php | 38 ++++++++++ .../Processors/CreateRemarkProcessor.php | 47 ++++++++++++ .../Remarks/Services/CreatesRemark.php | 31 ++++++++ .../Remarks/Services/DeletesRemark.php | 19 +++++ .../Remarks/Services/FetchesRemark.php | 33 +++++++++ .../Modules/Remarks/Services/ListsRemarks.php | 33 +++++++++ .../Remarks/Services/UpdatesRemark.php | 26 +++++++ .../Standards/Rules/CanCreateRemark.php | 57 +++++++++++++++ .../Standards/Rules/CanDeleteRemark.php | 43 +++++++++++ .../Standards/Rules/CanFetchRemark.php | 43 +++++++++++ .../Standards/Rules/CanListRemarks.php | 43 +++++++++++ .../Standards/Rules/CanUpdateRemark.php | 57 +++++++++++++++ .../Standards/Validators/RemarkValidation.php | 41 +++++++++++ .../Remarks/CreateRemarkController.php | 20 +++++ .../Remarks/DeleteRemarkController.php | 20 +++++ .../Remarks/FetchRemarkController.php | 20 +++++ .../Remarks/ListRemarksController.php | 20 +++++ .../Remarks/UpdateRemarkController.php | 20 +++++ app/Http/Resources/RemarkResource.php | 26 +++++++ .../general/elements/RemarkComponent.vue | 32 ++++++++ .../general/elements/RemarkListComponent.vue | 71 ++++++++++++++++++ .../forms/DeleteRemarkFormComponent.vue | 32 ++++++++ .../forms/RemarkCommentFormComponent.vue | 55 ++++++++++++++ .../general/forms/RemarkFormComponent.vue | 73 +++++++++++++++++++ routes/remark.php | 11 +++ 30 files changed, 1228 insertions(+) create mode 100644 app/Classes/Modules/Remarks/ControllersLogic/CreateRemarkLogic.php create mode 100644 app/Classes/Modules/Remarks/ControllersLogic/DeleteRemarkLogic.php create mode 100644 app/Classes/Modules/Remarks/ControllersLogic/FetchRemarkLogic.php create mode 100644 app/Classes/Modules/Remarks/ControllersLogic/ListRemarksLogic.php create mode 100644 app/Classes/Modules/Remarks/ControllersLogic/UpdateRemarkLogic.php create mode 100644 app/Classes/Modules/Remarks/DataTransferObjects/RemarkObject.php create mode 100644 app/Classes/Modules/Remarks/Processors/CreateRemarkProcessor.php create mode 100644 app/Classes/Modules/Remarks/Services/CreatesRemark.php create mode 100644 app/Classes/Modules/Remarks/Services/DeletesRemark.php create mode 100644 app/Classes/Modules/Remarks/Services/FetchesRemark.php create mode 100644 app/Classes/Modules/Remarks/Services/ListsRemarks.php create mode 100644 app/Classes/Modules/Remarks/Services/UpdatesRemark.php create mode 100644 app/Classes/Modules/Remarks/Standards/Rules/CanCreateRemark.php create mode 100644 app/Classes/Modules/Remarks/Standards/Rules/CanDeleteRemark.php create mode 100644 app/Classes/Modules/Remarks/Standards/Rules/CanFetchRemark.php create mode 100644 app/Classes/Modules/Remarks/Standards/Rules/CanListRemarks.php create mode 100644 app/Classes/Modules/Remarks/Standards/Rules/CanUpdateRemark.php create mode 100644 app/Classes/Modules/Remarks/Standards/Validators/RemarkValidation.php create mode 100644 app/Http/Controllers/Remarks/CreateRemarkController.php create mode 100644 app/Http/Controllers/Remarks/DeleteRemarkController.php create mode 100644 app/Http/Controllers/Remarks/FetchRemarkController.php create mode 100644 app/Http/Controllers/Remarks/ListRemarksController.php create mode 100644 app/Http/Controllers/Remarks/UpdateRemarkController.php create mode 100644 app/Http/Resources/RemarkResource.php create mode 100644 resources/assets/vue/components/general/elements/RemarkComponent.vue create mode 100644 resources/assets/vue/components/general/elements/RemarkListComponent.vue create mode 100644 resources/assets/vue/components/general/forms/DeleteRemarkFormComponent.vue create mode 100644 resources/assets/vue/components/general/forms/RemarkCommentFormComponent.vue create mode 100644 resources/assets/vue/components/general/forms/RemarkFormComponent.vue create mode 100644 routes/remark.php 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/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/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/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/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/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'); +}); From 631282eaf5205ad975bc82dd04e03e985a9d797f Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 24 Apr 2024 18:09:22 +0800 Subject: [PATCH 100/228] add remarks table migration --- .../ValueObjects/Constants/RemarkTypes.php | 13 ++++++ ...2024_04_24_180633_create_remarks_table.php | 41 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 app/Classes/ValueObjects/Constants/RemarkTypes.php create mode 100644 database/migrations/2024_04_24_180633_create_remarks_table.php 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 @@ +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'); + } +} From 9879b16f2ae1fb371f966c59e4063ca32f559033 Mon Sep 17 00:00:00 2001 From: Dodowingster Date: Thu, 25 Apr 2024 10:22:08 +0800 Subject: [PATCH 101/228] feat: remarks and add remarks --- routes/web.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/routes/web.php b/routes/web.php index 355dc7f1..079831aa 100644 --- a/routes/web.php +++ b/routes/web.php @@ -31,6 +31,7 @@ use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionWithInvo use App\Classes\Modules\Transactions\Services\DeletesTransaction; use Illuminate\Support\Facades\Log; + /* |-------------------------------------------------------------------------- | Web Routes @@ -968,6 +969,7 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, ); })->name('invoice.fix.byCustomerMarking'); +require __DIR__.'/remark.php'; Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', function ($from_date, $to_date) { @@ -981,6 +983,8 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo ''; echo ''; echo ''; + echo ''; + echo ''; echo ''; echo ''; echo ''; @@ -991,6 +995,13 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo ''; echo ''; echo ''; + echo ''; + echo ''; echo ''; } From 3383f6b138547b352cf24869f409bccafe68f904 Mon Sep 17 00:00:00 2001 From: Dodowingster Date: Thu, 25 Apr 2024 13:39:40 +0800 Subject: [PATCH 102/228] initial commit --- app/Models/Remark.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 app/Models/Remark.php 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'); + } +} From a9414712f5fc037385709d48d238bcd13d464039 Mon Sep 17 00:00:00 2001 From: Dodowingster Date: Thu, 25 Apr 2024 13:40:04 +0800 Subject: [PATCH 103/228] feat: added remark.php --- routes/api.php | 2 ++ 1 file changed, 2 insertions(+) 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'; From 7fb4ae724c312398044bf41588a10359b4ede364 Mon Sep 17 00:00:00 2001 From: Dodowingster Date: Thu, 25 Apr 2024 13:40:23 +0800 Subject: [PATCH 104/228] refactor: adding remarks --- routes/web.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/routes/web.php b/routes/web.php index 079831aa..6a8ce6ca 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; @@ -969,10 +970,18 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, ); })->name('invoice.fix.byCustomerMarking'); -require __DIR__.'/remark.php'; +route:: post('/transaction/{id}/create-remark',function ($transactionId) { + $transaction = Transaction::find($transactionId); + $remark = new Remark(); + $remark->content = request('content'); + $remark->transaction_id; + $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) { + $approvedTransactions = Transaction::where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->where('owner_type', '!=', Wallet::class)->orderBy('status')->get(); echo '

Pending Orders Payments

'; @@ -997,9 +1006,10 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo '
'; echo ''; echo ''; echo ''; @@ -1048,4 +1058,6 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo ''; echo '
StatusBills Created AtBookingPayment DateCustomer payment dateWhite form dateUpload bank slip DatePO submit datePO approve date
' . $approvalSatatusArray[$data['status']] . '' . $data->created_at . '' . $data->owner->owner->marking . '' . $payment->owner->marking . '' . $payment->created_at . '' . $bill->created_at . '' . $bill->status === ApprovalStatus::APPROVED ? $bill->updated_at : 'Pending Upload' . '' . $po ? $po->updated_at : 'Pending Submission' . '' . $po ? ($po->status === ApprovalStatus::APPROVED ? $po->updated_at : '' ) : '' . '
' . $approvedTransaction->owner->marking . '' . $approvedTransaction->amount . '' . round($approvedTransaction->amount, 2) . '' . $approvedTransaction->created_at . '' . ApprovalStatus::APPROVAL_STATUS_ID[$approvedTransaction->status] . '
BookingAmountCustomer payment dateWhite form dateSupplierUpload bank slip DatePO submit datePO approve date
' . $payment->owner->marking . '' . $payment->created_at . '' . $bill->created_at . '' . $bill->issuerCompany->name . '' . $bill->status === ApprovalStatus::APPROVED ? $bill->updated_at : 'Pending Upload' . '' . $po ? $po->updated_at : 'Pending Submission' . '' . $po ? ($po->status === ApprovalStatus::APPROVED ? $po->updated_at : '' ) : '' . '
' . $payment->owner->marking . '' . $payment->created_at . '' . $bill->created_at . '
' . $payment->owner->marking . '' . $payment->created_at . '' . $bill->created_at . '' . $bill->issuerCompany->name . '' . $bill->status === ApprovalStatus::APPROVED ? $bill->updated_at : 'Pending Upload' . '' . $po ? $po->updated_at : 'Pending Submission' . '' . $po ? $po->updated_at : 'Pending Submission' . '' . $po ? ($po->status === ApprovalStatus::APPROVED ? $po->updated_at : '' ) : '' . '
' . $bill->created_at . '' . $bill->issuerCompany->name . '' . $bill->status === ApprovalStatus::APPROVED ? $bill->updated_at : 'Pending Upload' . '' . $po ? $po->updated_at : 'Pending Submission' . '' . $po ? ($po->status === ApprovalStatus::APPROVED ? $po->updated_at : '' ) : '' . '' . ($po ? $po->updated_at : 'Pending Submission') . '' . ($po ? ($po->status === ApprovalStatus::APPROVED ? $po->updated_at : '' ) : '' ). '
' . $approvedTransaction->owner->marking . '' . round($approvedTransaction->amount, 2) . '' . $approvedTransaction->created_at . '' . $approvedTransaction->created_at->format('d-m-Y h:i A') . '' . ApprovalStatus::APPROVAL_STATUS_ID[$approvedTransaction->status] . '
' . $payment->owner->marking . '' . $payment->created_at . '' . $bill->created_at . '' . round($payment->amount, 2) . '' . $payment->created_at->format('d-m-Y h:i A') . '' . $bill->created_at->format('d-m-Y h:i A') . '' . $bill->issuerCompany->name . '' . $bill->status === ApprovalStatus::APPROVED ? $bill->updated_at : 'Pending Upload' . '' . ($po ? $po->updated_at : 'Pending Submission') . '' . ($po ? ($po->status === ApprovalStatus::APPROVED ? $po->updated_at : '' ) : '' ). '' . ($bill->status === ApprovalStatus::APPROVED ? $bill->updated_at->format('d-m-Y h:i A') : 'Pending Upload') . '' . ($po ? $po->updated_at->format('d-m-Y h:i A') : 'Pending Submission') . '' . ($po ? ($po->status === ApprovalStatus::APPROVED ? $po->updated_at->format('d-m-Y h:i A') : '' ) : '' ). '
Voucher ({{ $voucher_redemption->voucher->code }})-{{ number_format($voucherDiscount, 2) }}{{ number_format($voucherDiscount, 2) }}
AmountPayment DateStatusRemarkAdd Remarks
' . round($approvedTransaction->amount, 2) . '' . $approvedTransaction->created_at->format('d-m-Y h:i A') . '' . ApprovalStatus::APPROVAL_STATUS_ID[$approvedTransaction->status] . '' . $approvedTransaction->remarks . '' ; + echo '
'; + echo ''; + echo ''; + echo '
'; + echo '
' . ApprovalStatus::APPROVAL_STATUS_ID[$approvedTransaction->status] . '' . $approvedTransaction->remarks . '' ; - echo '
'; + echo ''; echo ''; echo ''; + echo csrf_field(); echo '
'; echo '
'; + + }); From 30172a6d7ad214a7d3c2a5821ac554f8a929a3e2 Mon Sep 17 00:00:00 2001 From: Dodowingster Date: Thu, 25 Apr 2024 14:20:31 +0800 Subject: [PATCH 105/228] refactor: proper remark database commit --- routes/web.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/routes/web.php b/routes/web.php index 6a8ce6ca..7dd5a3ef 100644 --- a/routes/web.php +++ b/routes/web.php @@ -974,7 +974,7 @@ route:: post('/transaction/{id}/create-remark',function ($transactionId) { $transaction = Transaction::find($transactionId); $remark = new Remark(); $remark->content = request('content'); - $remark->transaction_id; + $remark->id = $transactionId; $remark->save(); return redirect()->back(); })->name('transaction.create-remark'); @@ -1004,7 +1004,12 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo '' . round($approvedTransaction->amount, 2) . ''; echo '' . $approvedTransaction->created_at->format('d-m-Y h:i A') . ''; echo '' . ApprovalStatus::APPROVAL_STATUS_ID[$approvedTransaction->status] . ''; - echo '' . $approvedTransaction->remarks . ''; + $remark = Remark::where('id', $approvedTransaction->id)->first(); + if ($remark) { + echo '' . $remark->content . ''; + } else { + echo 'No remark found'; + } echo '' ; echo '
'; echo ''; From 29507f51200cef7575b70ff78e6accc5defe17f3 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Thu, 25 Apr 2024 14:50:59 +0800 Subject: [PATCH 106/228] update remark on transactions --- app/Models/Transaction.php | 8 ++++++++ routes/web.php | 22 +++++++++++----------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index 4161632b..aba5decc 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -259,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/routes/web.php b/routes/web.php index 7dd5a3ef..7dc095f3 100644 --- a/routes/web.php +++ b/routes/web.php @@ -973,15 +973,17 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, 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->id = $transactionId; $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) { - $approvedTransactions = Transaction::where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->where('owner_type', '!=', Wallet::class)->orderBy('status')->get(); echo '

Pending Orders Payments

'; @@ -1004,15 +1006,15 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo '' . round($approvedTransaction->amount, 2) . ''; echo '' . $approvedTransaction->created_at->format('d-m-Y h:i A') . ''; echo '' . ApprovalStatus::APPROVAL_STATUS_ID[$approvedTransaction->status] . ''; - $remark = Remark::where('id', $approvedTransaction->id)->first(); - if ($remark) { - echo '' . $remark->content . ''; - } else { - echo 'No remark found'; - } + $remarks = $approvedTransaction->remarks; + echo ''; + foreach ($remarks as $remark) { + echo "

$remark->content

"; + } + echo ''; echo '' ; echo ''; - echo ''; + echo ''; echo ''; echo csrf_field(); echo ''; @@ -1063,6 +1065,4 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo ''; echo ''; - - }); From 32d8b26451acc1fccc6f983432b547a88461b6b1 Mon Sep 17 00:00:00 2001 From: Dodowingster Date: Thu, 25 Apr 2024 15:52:38 +0800 Subject: [PATCH 107/228] feat: added date and time for remarks --- routes/web.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/routes/web.php b/routes/web.php index 7dc095f3..d8ea0f1b 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1009,7 +1009,9 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', $remarks = $approvedTransaction->remarks; echo ''; foreach ($remarks as $remark) { - echo "

$remark->content

"; + echo $remark->created_at->format('d-m-Y | h:i A') . ' - '; + echo $remark->content; + echo '
'; } echo ''; echo '' ; From 20cb00ed248da5d86b3dfc88ee3b6cdd1cd66a50 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Thu, 25 Apr 2024 16:48:39 +0800 Subject: [PATCH 108/228] update add remark on white form transactions --- routes/web.php | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/routes/web.php b/routes/web.php index d8ea0f1b..861f5bdf 100644 --- a/routes/web.php +++ b/routes/web.php @@ -994,8 +994,6 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo 'Amount'; echo 'Payment Date'; echo 'Status'; - echo 'Remark'; - echo 'Add Remarks'; echo ''; echo ''; echo ''; @@ -1006,21 +1004,6 @@ Route::get('/show-white-form-transactions-in-date-range/{from_date}/{to_date}', echo '' . round($approvedTransaction->amount, 2) . ''; echo '' . $approvedTransaction->created_at->format('d-m-Y h:i A') . ''; echo '' . ApprovalStatus::APPROVAL_STATUS_ID[$approvedTransaction->status] . ''; - $remarks = $approvedTransaction->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 ''; } @@ -1043,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 ''; @@ -1062,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 ''; } From 7655853a6de4b28cbdf3f2751d88a125cbee3af2 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Mon, 29 Apr 2024 21:19:34 +0800 Subject: [PATCH 109/228] -open refund function for all admin (ignore whether the booking has invoice or not) -when refund is before the whiteform, auto approve the transaction --- .../ControllersLogic/CreateBookingRefundLogic.php | 15 +++++++++++++-- .../UpdateRefundTransactionStatusLogic.php | 4 ++-- .../bookings/elements/PaymentHistoryComponent.vue | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingRefundLogic.php index 7e176363..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; } /** @@ -79,7 +85,7 @@ class CreateBookingRefundLogic extends AbstractControllerLogic $invoice = $booking->transactions()->where('type', TransactionType::INVOICE)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first(); - if(auth()->user()->type === 3 || ($invoice && !(auth()->user()->type === 0 || auth()->user()->type === 1))) { + if(auth()->user()->type === 3) { throw new MalformedRequestException('You do not have the permission to refund the order.'); } @@ -119,6 +125,11 @@ class CreateBookingRefundLogic extends AbstractControllerLogic 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/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php index d2fa5ec6..cc98847a 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php @@ -86,8 +86,8 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - if (!(Auth::user()->type === 0 || Auth::user()->type === 1)) { - throw new MalformedRequestException('Only super admin can update refund status.'); + 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')]); diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index ec0c0d7a..7679b807 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -290,7 +290,7 @@
-
+
From b528ac66fcdff4a0e02debe14c7a29451b0cc54e Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Tue, 30 Apr 2024 17:46:25 +0800 Subject: [PATCH 110/228] update estimated delivery date for E2E --- .../Services/GeneratesBookingQuotation.php | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/app/Classes/Modules/Bookings/Services/GeneratesBookingQuotation.php b/app/Classes/Modules/Bookings/Services/GeneratesBookingQuotation.php index 8ea1b88d..3a0b1536 100644 --- a/app/Classes/Modules/Bookings/Services/GeneratesBookingQuotation.php +++ b/app/Classes/Modules/Bookings/Services/GeneratesBookingQuotation.php @@ -19,7 +19,31 @@ class GeneratesBookingQuotation $hours = $date->diffInHours($date->copy()->addMinutes($paymentAttemptLimit)->subDays($days)) ; $minutes = $date->diffInMinutes($date->copy()->addMinutes($paymentAttemptLimit)->subDays($days)->subHours($hours)); - $receive_date = $currencyConversionObject ? Carbon::now()->endOfDay()->addWeekdays($currencyConversionObject->getServiceId() === 3 ? 3 : 1)->timezone('Asia/Singapore')->format('4:00 \P\M, jS M, Y \G\M\T T') : null; + // Initialize $receive_date to null by default + $receive_date = null; + + if ($currencyConversionObject) { + $serviceId = $currencyConversionObject->getServiceId(); + + switch ($serviceId) { + case 3: + $daysToAdd = 3; + break; + case 5: + $daysToAdd = 7; + break; + default: + $daysToAdd = 1; + break; + } + + $receive_date = Carbon::now() + ->endOfDay() + ->addWeekdays($daysToAdd) + ->timezone('Asia/Singapore') + ->format('4:00 PM, jS M, Y GMT T'); + } + return [ 'bank' => new BankResource(Bank::find($calculationObject->getConfigurations()->getBankId())), From f57b1e625f001e8fc9a00a2f1b4547643742398e Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Tue, 30 Apr 2024 17:49:30 +0800 Subject: [PATCH 111/228] update estimated delivery date for E2E --- .../Modules/Bookings/Services/GeneratesBookingQuotation.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Classes/Modules/Bookings/Services/GeneratesBookingQuotation.php b/app/Classes/Modules/Bookings/Services/GeneratesBookingQuotation.php index 3a0b1536..5c1ecdd9 100644 --- a/app/Classes/Modules/Bookings/Services/GeneratesBookingQuotation.php +++ b/app/Classes/Modules/Bookings/Services/GeneratesBookingQuotation.php @@ -41,7 +41,7 @@ class GeneratesBookingQuotation ->endOfDay() ->addWeekdays($daysToAdd) ->timezone('Asia/Singapore') - ->format('4:00 PM, jS M, Y GMT T'); + ->format('4:00 \P\M, jS M, Y \G\M\T T'); } From 76e76e077ac97bbc6a097c89b878b691fee63ddf Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Mon, 6 May 2024 17:20:01 +0800 Subject: [PATCH 112/228] edit transfer fee functionality for individual whiteform --- .../UpdateGroupTransferFeeLogic.php | 82 +++++++++++++++++++ .../Services/CreatesTransaction.php | 7 +- .../UpdateGroupTransferFeeController.php | 20 +++++ app/Http/Resources/GroupResource.php | 8 ++ app/Models/Group.php | 8 ++ .../bookings/elements/BillGroupComponent.vue | 6 ++ .../elements/EditTransferFeeFormComponent.vue | 79 ++++++++++++++++++ .../TransactionGroupPaymentComponent.vue | 18 ++++ routes/transaction.php | 1 + 9 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupTransferFeeLogic.php create mode 100644 app/Http/Controllers/Transactions/UpdateGroupTransferFeeController.php create mode 100644 resources/assets/vue/components/bookings/elements/EditTransferFeeFormComponent.vue diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupTransferFeeLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupTransferFeeLogic.php new file mode 100644 index 00000000..2864eb73 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupTransferFeeLogic.php @@ -0,0 +1,82 @@ + 'Update Group Transfer Fee', + 'message' => 'You have successfully updated transfer fee for this Group Transaction' + ]; + } + + /** @var FetchesGroup */ + private $fetchesGroup; + + /** @var CreatesTransaction */ + private $createsTransaction; + + /** @var GeneratesTransactionBillNumber */ + private $generatesTransactionBillNumber; + + /** + * UpdateGroupTransferFeeLogic constructor. + * @param FetchesGroup $fetchesGroup + * @param CreatesTransaction $createsTransaction + * @param GeneratesTransactionBillNumber $generatesTransactionBillNumber + */ + public function __construct(FetchesGroup $fetchesGroup, CreatesTransaction $createsTransaction, GeneratesTransactionBillNumber $generatesTransactionBillNumber) + { + $this->fetchesGroup = $fetchesGroup; + $this->createsTransaction = $createsTransaction; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + } + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request) : JsonResponse + { + $group = $this->fetchesGroup->execute(['id' => $request->route('id')]); + $supplier = $group->issuerCompany; + $fee = $request->input('fee'); + + $transfer_fee = $group->morphTransactions()->where('type', TransactionType::TRANSFER_FEE)->first(); + + if ($transfer_fee) { + $transfer_fee->amount = $fee; + $transfer_fee->original_amount = $fee; + $transfer_fee->save(); + } else { + $transferFeeNumber = $this->generatesTransactionBillNumber->execute('TRFR-'); + $object = new TransactionObject($transferFeeNumber, TransactionType::TRANSFER_FEE, 1, $supplier->id, + $supplier->banks()->where('default', true)->first()->id, PaymentMethodType::CASH, + $fee, $fee, $group->original_currency_id, $group->original_currency_id, + 1, 0, 0, null, ApprovalStatus::APPROVED); + + $this->createsTransaction->execute($group, $object); + } + + return $this->resourceResponse(new GroupResource($group)); + } + +} diff --git a/app/Classes/Modules/Transactions/Services/CreatesTransaction.php b/app/Classes/Modules/Transactions/Services/CreatesTransaction.php index 06530564..b545c5ed 100644 --- a/app/Classes/Modules/Transactions/Services/CreatesTransaction.php +++ b/app/Classes/Modules/Transactions/Services/CreatesTransaction.php @@ -5,6 +5,7 @@ namespace App\Classes\Modules\Transactions\Services; use App\Classes\General\Eloquent\AbstractUpdateRelationshipRecord; use App\Classes\General\Interfaces\Transactionable; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; +use App\Models\Group; use App\Models\Transaction; class CreatesTransaction extends AbstractUpdateRelationshipRecord @@ -15,7 +16,7 @@ class CreatesTransaction extends AbstractUpdateRelationshipRecord * @return \Illuminate\Database\Eloquent\Model * @throws \App\Classes\Exceptions\MalformedRequestException */ - public function execute(Transactionable $transactionable, TransactionObject $object) { + public function execute(Transactionable|Group $transactionable, TransactionObject $object) { $model = new Transaction(); $model->bill_no = $object->getBillNo(); $model->type = $object->getTransactionType(); @@ -34,6 +35,10 @@ class CreatesTransaction extends AbstractUpdateRelationshipRecord $model->status = $object->getStatus(); $model->payment_reference = $object->getPaymentReference(); + if ($transactionable instanceof Group) { + return $this->handler($transactionable->morphTransactions(), $model); + } + return $this->handler($transactionable->transactions(), $model); } diff --git a/app/Http/Controllers/Transactions/UpdateGroupTransferFeeController.php b/app/Http/Controllers/Transactions/UpdateGroupTransferFeeController.php new file mode 100644 index 00000000..948dff39 --- /dev/null +++ b/app/Http/Controllers/Transactions/UpdateGroupTransferFeeController.php @@ -0,0 +1,20 @@ +execute($request); + } +} diff --git a/app/Http/Resources/GroupResource.php b/app/Http/Resources/GroupResource.php index abd017ec..fdddd195 100644 --- a/app/Http/Resources/GroupResource.php +++ b/app/Http/Resources/GroupResource.php @@ -21,6 +21,13 @@ class GroupResource extends JsonResource */ public function toArray($request) { + $transfer_fee = $this->morphTransactions()->where('type', TransactionType::TRANSFER_FEE)->first(); + + if ($transfer_fee) { + $transfer_fee = (float) $transfer_fee->amount; + } else { + $transfer_fee = 0; + } if(!$this->issuerCompany){ dd($this->id); @@ -36,6 +43,7 @@ class GroupResource extends JsonResource 'currency' => new CurrencyResource($this->currency), 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), 'currency_rate' => (float) $this->currency_rate, + 'transfer_fee' => $transfer_fee, 'transactions' => $this->transactions()->get()->pluck('owner.owner.marking'), 'complete_transactions' => $this->transactions()->whereHasMorph('owner', [Transaction::class], function($query){ return $query->whereHas('booking', function($query){ diff --git a/app/Models/Group.php b/app/Models/Group.php index 8cb6cd8a..2b8cceae 100644 --- a/app/Models/Group.php +++ b/app/Models/Group.php @@ -21,6 +21,14 @@ class Group extends Model implements Documentable return $this->belongsToMany(Transaction::class, GroupTransaction::class); } + /** + * @return MorphMany + */ + public function morphTransactions(): MorphMany + { + return $this->MorphMany(Transaction::class, 'owner'); + } + /** * @return MorphMany */ diff --git a/resources/assets/vue/components/bookings/elements/BillGroupComponent.vue b/resources/assets/vue/components/bookings/elements/BillGroupComponent.vue index e93eb1ad..9a309cde 100644 --- a/resources/assets/vue/components/bookings/elements/BillGroupComponent.vue +++ b/resources/assets/vue/components/bookings/elements/BillGroupComponent.vue @@ -216,6 +216,12 @@ {{ group.currency.short_code }} {{formatAmount(group.amount)}}
+
+
Transfer Fee
+
+ {{ group.original_currency.short_code }} {{formatAmount(group.transfer_fee)}} +
+
PO Completion
diff --git a/resources/assets/vue/components/bookings/elements/EditTransferFeeFormComponent.vue b/resources/assets/vue/components/bookings/elements/EditTransferFeeFormComponent.vue new file mode 100644 index 00000000..93b01124 --- /dev/null +++ b/resources/assets/vue/components/bookings/elements/EditTransferFeeFormComponent.vue @@ -0,0 +1,79 @@ + + diff --git a/resources/assets/vue/components/bookings/elements/TransactionGroupPaymentComponent.vue b/resources/assets/vue/components/bookings/elements/TransactionGroupPaymentComponent.vue index 7fdd579f..2696ceb5 100644 --- a/resources/assets/vue/components/bookings/elements/TransactionGroupPaymentComponent.vue +++ b/resources/assets/vue/components/bookings/elements/TransactionGroupPaymentComponent.vue @@ -36,6 +36,12 @@ {{item.original_currency.short_code}} {{(Math.round((item.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
+
+
Transfer Fee
+
+ {{item.original_currency.short_code}} {{(Math.round((item.transfer_fee + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}} +
+
Amount
@@ -75,6 +81,18 @@
+
+
+
+ + + + +
+
+
diff --git a/routes/transaction.php b/routes/transaction.php index d20d160d..654b3fb8 100644 --- a/routes/transaction.php +++ b/routes/transaction.php @@ -32,6 +32,7 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' => Route::get('/list', 'ListGroupsController@list')->name('list'); Route::delete('/{id}/delete', 'DeleteGroupController@delete')->name('delete'); Route::put('/{id}/update', 'UpdateGroupController@update')->name('update'); + Route::put('/{id}/update/fee', 'UpdateGroupTransferFeeController@update')->name('fee.update'); Route::post('/{id}/approve', 'CreateBulkPurchaseOrderDocumentController@aprove')->name('approve'); Route::post('/bulk/po', 'CreateBulkPurchaseOrderDocumentController@create')->name('bulk.po'); From f3413b9c6c22a5d7986317671f2debe3f3d9b5a4 Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Tue, 7 May 2024 11:20:14 +0800 Subject: [PATCH 113/228] change service description --- .../vue/components/bookings/forms/BookingFormComponent.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/assets/vue/components/bookings/forms/BookingFormComponent.vue b/resources/assets/vue/components/bookings/forms/BookingFormComponent.vue index d9c009b5..9593e940 100644 --- a/resources/assets/vue/components/bookings/forms/BookingFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/BookingFormComponent.vue @@ -93,8 +93,8 @@
-

Recipient will receive the transfer on the next working day. Check out our three-day transfer option to get a better rate!

-

Enjoy a better rate with this option! The recipient will receive the transfer after three working days.

+

The recipient can expect to receive the transfer within 1-3 working days. Explore our BANK TRANSFER (SAVER) option for a better rate!

+

Enjoy a better rate with this option! The recipient will receive the transfer after 3-5 working days..

From 26f8ca87cd5a5ded079e5da27d259ee67c83b148 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Wed, 8 May 2024 12:58:23 +0800 Subject: [PATCH 114/228] fix partial refund bug --- .../ControllersLogic/UpdateRefundTransactionStatusLogic.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php index cc98847a..6b755db1 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateRefundTransactionStatusLogic.php @@ -100,7 +100,7 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic $booking = $paymentTransaction->owner; - $reference = $refundTransaction->amount == $paymentTransaction->amount ? 'Fully Refund for Ref. ' . $booking->marking : 'Partially Refund for Ref. ' . $booking->marking; + $reference = $refundTransaction->amount - $paymentTransaction->amount < 0.01 ? 'Fully Refund for Ref. ' . $booking->marking : 'Partially Refund for Ref. ' . $booking->marking; $refundAmount = $this->calculatesBookingRefundAmount->calculateRefundAmount($paymentTransaction, $booking->fix_currency_id); @@ -114,7 +114,7 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic $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['fix_amount'] = $paidAmount; $request->route()->setParameter('id', $booking->id); $this->updateBookingAmountLogic->execute($request); } From b8d741f57ce70b4d310504d67469168a19d6c189 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Wed, 8 May 2024 20:07:06 +0800 Subject: [PATCH 115/228] fix edit transfer fee bug --- .../UpdateGroupTransferFeeLogic.php | 21 ++++++++++++++++++- .../Services/CreatesTransaction.php | 7 +------ .../elements/EditTransferFeeFormComponent.vue | 2 +- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupTransferFeeLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupTransferFeeLogic.php index 2864eb73..b4cd4d02 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupTransferFeeLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateGroupTransferFeeLogic.php @@ -11,6 +11,7 @@ use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\PaymentMethodType; use App\Classes\ValueObjects\Constants\TransactionType; +use App\Models\Transaction; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -73,7 +74,25 @@ class UpdateGroupTransferFeeLogic extends AbstractControllerLogic $fee, $fee, $group->original_currency_id, $group->original_currency_id, 1, 0, 0, null, ApprovalStatus::APPROVED); - $this->createsTransaction->execute($group, $object); + $model = new Transaction(); + $model->bill_no = $object->getBillNo(); + $model->type = $object->getTransactionType(); + $model->issuer = $object->getIssuer(); + $model->receiver = $object->getReceiver(); + $model->recipient_bank_account_id = $object->getRecipientBankAccountId(); + $model->payment_method = $object->getPaymentMethod(); + $model->amount = $object->getAmount(); + $model->original_amount = $object->getOriginalAmount(); + $model->currency_id = $object->getCurrencyId(); + $model->original_currency_id = $object->getOriginalCurrencyId(); + $model->currency_rate = $object->getCurrencyRate(); + $model->tax = $object->getTax(); + $model->service_charge = $object->getServiceCharge(); + $model->expires_on = $object->getExpiresOn(); + $model->status = $object->getStatus(); + $model->payment_reference = $object->getPaymentReference(); + + $group->morphTransactions()->save($model); } return $this->resourceResponse(new GroupResource($group)); diff --git a/app/Classes/Modules/Transactions/Services/CreatesTransaction.php b/app/Classes/Modules/Transactions/Services/CreatesTransaction.php index b545c5ed..06530564 100644 --- a/app/Classes/Modules/Transactions/Services/CreatesTransaction.php +++ b/app/Classes/Modules/Transactions/Services/CreatesTransaction.php @@ -5,7 +5,6 @@ namespace App\Classes\Modules\Transactions\Services; use App\Classes\General\Eloquent\AbstractUpdateRelationshipRecord; use App\Classes\General\Interfaces\Transactionable; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; -use App\Models\Group; use App\Models\Transaction; class CreatesTransaction extends AbstractUpdateRelationshipRecord @@ -16,7 +15,7 @@ class CreatesTransaction extends AbstractUpdateRelationshipRecord * @return \Illuminate\Database\Eloquent\Model * @throws \App\Classes\Exceptions\MalformedRequestException */ - public function execute(Transactionable|Group $transactionable, TransactionObject $object) { + public function execute(Transactionable $transactionable, TransactionObject $object) { $model = new Transaction(); $model->bill_no = $object->getBillNo(); $model->type = $object->getTransactionType(); @@ -35,10 +34,6 @@ class CreatesTransaction extends AbstractUpdateRelationshipRecord $model->status = $object->getStatus(); $model->payment_reference = $object->getPaymentReference(); - if ($transactionable instanceof Group) { - return $this->handler($transactionable->morphTransactions(), $model); - } - return $this->handler($transactionable->transactions(), $model); } diff --git a/resources/assets/vue/components/bookings/elements/EditTransferFeeFormComponent.vue b/resources/assets/vue/components/bookings/elements/EditTransferFeeFormComponent.vue index 93b01124..bb82964a 100644 --- a/resources/assets/vue/components/bookings/elements/EditTransferFeeFormComponent.vue +++ b/resources/assets/vue/components/bookings/elements/EditTransferFeeFormComponent.vue @@ -60,7 +60,7 @@ return { error: '', parameters: { - fee: (Math.round((this.transfer_fee + Number.EPSILON) * 10000) / 10000).toFixed(5) + fee: (Math.round((this.transfer_fee + Number.EPSILON) * 100) / 100).toFixed(2) }, } }, From 2ad1841e54cf7fdff3f2e98d0d21bd44b2a875dc Mon Sep 17 00:00:00 2001 From: edmondlang Date: Thu, 9 May 2024 15:46:12 +0800 Subject: [PATCH 116/228] clean up web export route --- routes/web.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/routes/web.php b/routes/web.php index 861f5bdf..0d14a526 100644 --- a/routes/web.php +++ b/routes/web.php @@ -220,12 +220,6 @@ Route::post('/support', function (Request $request) { Route::get('/online_payment/redirect', 'Billplz\CallbackBillplzController@callback')->name('online_payment.redirect'); -Route::get('/export/customers/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@export'); -Route::get('/export/transactions/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@transactions'); -Route::get('/export/analytic/booking', 'Exports\ExportAnalyticToExcelController@bookingData'); -Route::get('/export/analytic/bills', 'Exports\ExportAnalyticToExcelController@billingData'); -Route::get('/export/customers/leads', 'Exports\ExportCustomersToExcelController@leadsData')->name('leads.export'); - Route::get('/products', function (\App\Classes\Modules\Exports\Services\ExportsProducts $exportsProducts) { return $exportsProducts->download('products.csv', Excel::CSV, ['Content-Type' => 'text/csv']); })->name('products.random'); @@ -293,6 +287,9 @@ Route::get('/export/invoice-transactions/f614e339d7058904a831aad742e24d55', 'Exp Route::get('/export/receipt-transactions/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@receiptTransactions')->name('receiptTransactions.export'); Route::get('/export/imported-invoice-mapped', 'Exports\ExportCustomersToExcelController@importedInvoiceMapped')->name('importedInvoiceMapped.export'); Route::get('/export/imported-receipt-mapped', 'Exports\ExportCustomersToExcelController@importedReceiptMapped')->name('importedReceiptMapped.export'); +Route::get('/export/analytic/booking', 'Exports\ExportAnalyticToExcelController@bookingData'); +Route::get('/export/analytic/bills', 'Exports\ExportAnalyticToExcelController@billingData'); +Route::get('/export/customers/leads', 'Exports\ExportCustomersToExcelController@leadsData')->name('leads.export'); Route::get('/products', function (\App\Classes\Modules\Exports\Services\ExportsProducts $exportsProducts) { $bookings = Booking::where(function($query){ From f03d91ba422a1e5d0f29e559b788a66dbbbb3f9d Mon Sep 17 00:00:00 2001 From: edmondlang Date: Fri, 10 May 2024 00:00:01 +0800 Subject: [PATCH 117/228] add remarks for refund --- .../General/Abstracts/AbstractRule.php | 4 +-- app/Classes/General/Interfaces/Remarkable.php | 13 ++++++++++ .../CreateBookingRefundLogic.php | 14 ++++++++++- .../Standards/Rules/CanCreateRemark.php | 2 +- .../Standards/Rules/CanDeleteRemark.php | 2 +- .../Standards/Rules/CanFetchRemark.php | 2 +- .../Standards/Rules/CanListRemarks.php | 2 +- .../Standards/Rules/CanUpdateRemark.php | 2 +- app/Http/Resources/TransactionResource.php | 1 + app/Models/Transaction.php | 3 ++- .../elements/PaymentHistoryComponent.vue | 8 ++++++ .../elements/RefundConfirmationComponent.vue | 13 +++++++++- .../general/elements/RemarkComponent.vue | 25 ++++++++++++++++--- .../general/elements/RemarkListComponent.vue | 4 +-- .../forms/RemarkCommentFormComponent.vue | 5 +++- 15 files changed, 83 insertions(+), 17 deletions(-) create mode 100644 app/Classes/General/Interfaces/Remarkable.php diff --git a/app/Classes/General/Abstracts/AbstractRule.php b/app/Classes/General/Abstracts/AbstractRule.php index d2e0568b..8a9b6f86 100644 --- a/app/Classes/General/Abstracts/AbstractRule.php +++ b/app/Classes/General/Abstracts/AbstractRule.php @@ -27,7 +27,7 @@ abstract class AbstractRule public function passes(?DataTransferObject $object = null): bool { try { if(!$this->authorized()){ - throw new AccessForbiddenException('You don\'t have permission to preform this action'); + throw new AccessForbiddenException('You don\'t have permission to perform this action'); } $this->validators($object); @@ -36,7 +36,7 @@ abstract class AbstractRule return true; } catch(AccessForbiddenException $exception){ - throw new AccessForbiddenException('You don\'t have permission to preform this action'); + throw new AccessForbiddenException('You don\'t have permission to perform this action'); } catch(\Exception $exception){ throw new RequestValidationException($exception->getMessage()); } diff --git a/app/Classes/General/Interfaces/Remarkable.php b/app/Classes/General/Interfaces/Remarkable.php new file mode 100644 index 00000000..dcbd94ce --- /dev/null +++ b/app/Classes/General/Interfaces/Remarkable.php @@ -0,0 +1,13 @@ +fetchBookingQuotation = $fetchBookingQuotation; $this->fetchesTransaction = $fetchesTransaction; @@ -69,6 +75,7 @@ class CreateBookingRefundLogic extends AbstractControllerLogic $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; $this->createsTransaction = $createsTransaction; $this->updateRefundTransactionStatusLogic = $updateRefundTransactionStatusLogic; + $this->createRemarkProcessor = $createRemarkProcessor; } /** @@ -132,6 +139,11 @@ class CreateBookingRefundLogic extends AbstractControllerLogic } + if($request->input('refundRemark')){ + $remarkObject = new RemarkObject($request->input('refundRemark'), Auth()->user()->id); + $this->createRemarkProcessor->execute($this->fetchesTransaction->execute(['id' => $refund_transaction->id]), $remarkObject); + } + return $this->resourceResponse(new TransactionResource($refund_transaction)); } diff --git a/app/Classes/Modules/Remarks/Standards/Rules/CanCreateRemark.php b/app/Classes/Modules/Remarks/Standards/Rules/CanCreateRemark.php index a7d2e5b1..fc51178f 100644 --- a/app/Classes/Modules/Remarks/Standards/Rules/CanCreateRemark.php +++ b/app/Classes/Modules/Remarks/Standards/Rules/CanCreateRemark.php @@ -26,7 +26,7 @@ class CanCreateRemark extends AbstractRule /** * @return bool */ - protected function authorized($object): bool + protected function authorized(): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Remarks/Standards/Rules/CanDeleteRemark.php b/app/Classes/Modules/Remarks/Standards/Rules/CanDeleteRemark.php index 1c61ac9d..7ddece31 100644 --- a/app/Classes/Modules/Remarks/Standards/Rules/CanDeleteRemark.php +++ b/app/Classes/Modules/Remarks/Standards/Rules/CanDeleteRemark.php @@ -13,7 +13,7 @@ class CanDeleteRemark extends AbstractRule /** * @return bool */ - protected function authorized($object): bool + protected function authorized(): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Remarks/Standards/Rules/CanFetchRemark.php b/app/Classes/Modules/Remarks/Standards/Rules/CanFetchRemark.php index 31ae8301..6642611c 100644 --- a/app/Classes/Modules/Remarks/Standards/Rules/CanFetchRemark.php +++ b/app/Classes/Modules/Remarks/Standards/Rules/CanFetchRemark.php @@ -13,7 +13,7 @@ class CanFetchRemark extends AbstractRule /** * @return bool */ - protected function authorized($object): bool + protected function authorized(): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Remarks/Standards/Rules/CanListRemarks.php b/app/Classes/Modules/Remarks/Standards/Rules/CanListRemarks.php index b1372049..4911a53b 100644 --- a/app/Classes/Modules/Remarks/Standards/Rules/CanListRemarks.php +++ b/app/Classes/Modules/Remarks/Standards/Rules/CanListRemarks.php @@ -13,7 +13,7 @@ class CanListRemarks extends AbstractRule /** * @return bool */ - protected function authorized($object): bool + protected function authorized(): bool { // TODO Set Authorization rules return true; diff --git a/app/Classes/Modules/Remarks/Standards/Rules/CanUpdateRemark.php b/app/Classes/Modules/Remarks/Standards/Rules/CanUpdateRemark.php index f6fd6587..8a8c10e8 100644 --- a/app/Classes/Modules/Remarks/Standards/Rules/CanUpdateRemark.php +++ b/app/Classes/Modules/Remarks/Standards/Rules/CanUpdateRemark.php @@ -26,7 +26,7 @@ class CanUpdateRemark extends AbstractRule /** * @return bool */ - protected function authorized($object): bool + protected function authorized(): bool { // TODO Set Authorization rules return true; diff --git a/app/Http/Resources/TransactionResource.php b/app/Http/Resources/TransactionResource.php index b431c854..d259d777 100644 --- a/app/Http/Resources/TransactionResource.php +++ b/app/Http/Resources/TransactionResource.php @@ -53,6 +53,7 @@ class TransactionResource extends JsonResource 'value' => $days->gt(Carbon::now()) ? '+' : '-', 'duration' => $days->diff(Carbon::now())->format('%d'), ], + 'remarks' => RemarkResource::collection($this->remarks), 'redemption' => new VoucherRedemptionResource($this->voucherRedemption) ]; } diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index aba5decc..31b67e69 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -3,6 +3,7 @@ namespace App\Models; use App\Classes\General\Interfaces\Documentable; +use App\Classes\General\Interfaces\Remarkable; use App\Classes\General\Interfaces\Transactionable; use App\Classes\General\Interfaces\Voucherifiable; use App\Classes\General\Traits\LogData; @@ -21,7 +22,7 @@ use Staudenmeir\EloquentHasManyDeep\HasTableAlias; use App\Models\StatementTransactionOwner; -class Transaction extends AbstractModel implements Documentable, Transactionable, Voucherifiable +class Transaction extends AbstractModel implements Documentable, Transactionable, Voucherifiable, Remarkable { use HasTableAlias; use SoftDeletes; diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index 7679b807..ac77bc06 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -332,6 +332,14 @@
{{ refund.status === 1 ? 'Pending Verification' : refund.status === 2 ? 'Approved' : 'Rejected'}}
+
+ + + + + + +
Amount
diff --git a/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue b/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue index c87122a5..3470891a 100644 --- a/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue +++ b/resources/assets/vue/components/bookings/elements/RefundConfirmationComponent.vue @@ -35,6 +35,14 @@
+
+
+ + + + +
+
Paid Amount: {{ paidAmount }}
@@ -71,6 +79,7 @@ export default { data() { return { refundAmount: (Math.round((this.data.original_amount - this.data.refunded_amount + Number.EPSILON) * 100) / 100).toFixed(2), + refundRemark: '', refundMethod: { name: 'Fully Refund', status: false }, refundMethods: [ { name: 'Fully Refund', label: 'Full Refund' }, @@ -82,7 +91,8 @@ export default { return { refundAmount: { maxValue: maxValue(this.refundMaxValue) - } + }, + refundRemark: {} } }, computed: { @@ -96,6 +106,7 @@ export default { methods: { submitForm() { this.parameters.amount = this.refundAmount; + this.parameters.refundRemark = this.refundRemark; this.submit(this.route('api.booking.refund.create', this.data.booking.id, this.data.id), 'post', this.section, true, true) }, updateRefundType(refund) { diff --git a/resources/assets/vue/components/general/elements/RemarkComponent.vue b/resources/assets/vue/components/general/elements/RemarkComponent.vue index f2f9bf30..bd96c5e8 100644 --- a/resources/assets/vue/components/general/elements/RemarkComponent.vue +++ b/resources/assets/vue/components/general/elements/RemarkComponent.vue @@ -3,17 +3,34 @@
-
- +
+

Remarks

- +
+
+
+
+
+
+
+
+
+

Nothing To + Show Here Yet!

+
+
+
+
+
+
+
-
diff --git a/resources/assets/vue/components/general/elements/RemarkListComponent.vue b/resources/assets/vue/components/general/elements/RemarkListComponent.vue index da218ea9..85d8a6a8 100644 --- a/resources/assets/vue/components/general/elements/RemarkListComponent.vue +++ b/resources/assets/vue/components/general/elements/RemarkListComponent.vue @@ -41,12 +41,12 @@

{{item.content}}

- +
- +
diff --git a/resources/assets/vue/components/general/forms/RemarkCommentFormComponent.vue b/resources/assets/vue/components/general/forms/RemarkCommentFormComponent.vue index 7da26ca8..0bada956 100644 --- a/resources/assets/vue/components/general/forms/RemarkCommentFormComponent.vue +++ b/resources/assets/vue/components/general/forms/RemarkCommentFormComponent.vue @@ -1,5 +1,5 @@