From 20b22e63410f398a1410f6d9244eef590b87fb97 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Thu, 4 Jun 2026 11:24:22 +0800 Subject: [PATCH] New button to allow admin to switch e-credit note to normal credit note for customer otped in for e-invoice --- .../GenerateCreditNotePdfV2Logic.php | 6 ++ .../UpdateCreditNoteOptLogic.php | 101 ++++++++++++++++++ .../Standards/Rules/CanUpdateCreditNote.php | 42 ++++++++ app/Classes/ValueObjects/Constants/KVPKey.php | 1 + .../UpdateCreditNoteOptController.php | 14 +++ app/Http/Resources/TransactionResource.php | 9 ++ .../elements/PaymentHistoryComponent.vue | 31 +++++- .../elements/CompanyDetailsComponent.vue | 2 +- routes/transaction.php | 3 + 9 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 app/Classes/Modules/Transactions/ControllersLogic/UpdateCreditNoteOptLogic.php create mode 100644 app/Classes/Modules/Transactions/Standards/Rules/CanUpdateCreditNote.php create mode 100644 app/Http/Controllers/Transactions/UpdateCreditNoteOptController.php diff --git a/app/Classes/Modules/Transactions/ControllersLogic/GenerateCreditNotePdfV2Logic.php b/app/Classes/Modules/Transactions/ControllersLogic/GenerateCreditNotePdfV2Logic.php index 5e3df2f5..242e2966 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/GenerateCreditNotePdfV2Logic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/GenerateCreditNotePdfV2Logic.php @@ -48,6 +48,7 @@ class GenerateCreditNotePdfV2Logic $transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); $autoCountInvoiceId = ''; $autoCountEInvoiceValidationLink = 'CIEF'; + $kvpCreditNoteNormalOptInOverride = $transaction->attributesKVP()->where('key', KVPKey::CREDIT_NOTE_NORMAL_OPT_IN_OVERRIDE)->latest()->first(); //transaction type 6 if($transaction->type === TransactionType::REFUND){ //Retrieve TransactionType::CREDIT_NOTE @@ -69,6 +70,7 @@ class GenerateCreditNotePdfV2Logic if($kvp){ $kvpOwner = $kvp->owner; if($kvpOwner && $kvpOwner instanceof Transaction && $kvpOwner->type === TransactionType::REFUND){ + $kvpCreditNoteNormalOptInOverride = $kvpOwner->attributesKVP()->where('key', KVPKey::CREDIT_NOTE_NORMAL_OPT_IN_OVERRIDE)->latest()->first(); //transaction type 6 $booking = $kvpOwner->owner->booking; } } @@ -144,6 +146,10 @@ class GenerateCreditNotePdfV2Logic Log::info('Based on booking created date, E-Credit Note started and company do not wants e-invoice'); $pdfTemplateName = 'pages.pdfs.credit_note_v2'; } + + if($kvpCreditNoteNormalOptInOverride && $kvpCreditNoteNormalOptInOverride->value == 1){ + $pdfTemplateName = 'pages.pdfs.credit_note_v2'; + } } else{ Log::info('Based on booking created date, E-Credit Note not yet started. / Not Yet Ready.'); diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdateCreditNoteOptLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdateCreditNoteOptLogic.php new file mode 100644 index 00000000..50452128 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdateCreditNoteOptLogic.php @@ -0,0 +1,101 @@ + 'Updated Credit Note', + 'message' => 'You have successfully updated this credit note' + ]; + } + + /** @var CanUpdateCreditNote */ + private $canUpdateCreditNote; + + /** @var FetchesTransaction */ + private $fetchesTransaction; + + /** @var FetchesCompany */ + private $fetchesCompany; + + /** @var CreatesKeyValuePair */ + private $createsKeyValuePair; + + /** @var UpdatesKeyValuePair */ + private $updatesKeyValuePair; + + /** + * UpdateCreditNoteOptLogic constructor. + * @param FetchesTransaction $fetchesTransaction + * @param FetchesCompany $fetchesCompany + * @param CreatesKeyValuePair $createsKeyValuePair + * @param UpdatesKeyValuePair $updatesKeyValuePair + * @param CanUpdateCreditNote $canUpdateCreditNote + */ + public function __construct(FetchesTransaction $fetchesTransaction, FetchesCompany $fetchesCompany, CreatesKeyValuePair $createsKeyValuePair, UpdatesKeyValuePair $updatesKeyValuePair, CanUpdateCreditNote $canUpdateCreditNote) + { + $this->fetchesTransaction = $fetchesTransaction; + $this->fetchesCompany = $fetchesCompany; + $this->createsKeyValuePair = $createsKeyValuePair; + $this->updatesKeyValuePair = $updatesKeyValuePair; + $this->canUpdateCreditNote = $canUpdateCreditNote; + } + + /** + * @param Request $request + * @return string|\Symfony\Component\HttpFoundation\Response + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function logic(Request $request): JsonResponse + { + $this->canUpdateCreditNote->passes(); + + $transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]); + + $kvp = $transaction->attributesKVP()->where('key', KVPKey::CREDIT_NOTE_NORMAL_OPT_IN_OVERRIDE)->latest()->first(); + + $supplier = $this->fetchesCompany->execute(['id' => $transaction->receiver]); + if($supplier->e_invoice === 1) { + if($kvp && $kvp->value == 1) { + $this->updateOrCreateKeyValuePair($transaction, KVPKey::CREDIT_NOTE_NORMAL_OPT_IN_OVERRIDE, 0); + } + else + { + $this->updateOrCreateKeyValuePair($transaction, KVPKey::CREDIT_NOTE_NORMAL_OPT_IN_OVERRIDE, 1); + } + } + return $this->response([]); + } + + private function updateOrCreateKeyValuePair($transaction, $key, $value) + { + $keyValuePairObject = new KeyValuePairObject($key, $value); + $metadata = $transaction->attributesKVP()->where('key', $key)->first(); + + if ($metadata) { + $this->updatesKeyValuePair->execute($metadata, $keyValuePairObject); + } else { + $this->createsKeyValuePair->execute($transaction, $keyValuePairObject); + } + } +} diff --git a/app/Classes/Modules/Transactions/Standards/Rules/CanUpdateCreditNote.php b/app/Classes/Modules/Transactions/Standards/Rules/CanUpdateCreditNote.php new file mode 100644 index 00000000..791230ab --- /dev/null +++ b/app/Classes/Modules/Transactions/Standards/Rules/CanUpdateCreditNote.php @@ -0,0 +1,42 @@ +type, RoleTypes::ADMIN_ROLES)) { + return true; + } + return false; + } + + /** + * @param $object + * @return bool + * @throws \App\Classes\Exceptions\RequestValidationException + */ + protected function validators($object): bool + { + return true; + } + + /** + * @param $object + * @return bool + */ + protected function criteria($object): bool + { + return true; + } + +} diff --git a/app/Classes/ValueObjects/Constants/KVPKey.php b/app/Classes/ValueObjects/Constants/KVPKey.php index 66378049..cdc88ab9 100644 --- a/app/Classes/ValueObjects/Constants/KVPKey.php +++ b/app/Classes/ValueObjects/Constants/KVPKey.php @@ -19,6 +19,7 @@ class KVPKey public const AUTOCOUNT_EINVOICE_VALIDATION_LINK_CREDIT_NOTE = 'AUTOCOUNT_EINVOICE_VALIDATION_LINK_CN'; public const CREDIT_NOTE_APPROVAL_DATE = 'CREDIT_NOTE_APPROVAL_DATE'; + public const CREDIT_NOTE_NORMAL_OPT_IN_OVERRIDE = 'CREDIT_NOTE_NORMAL_OPT_IN_OVERRIDE'; public const TRANSACTION_MODEL_CLASS = 'App\Models\Transaction'; diff --git a/app/Http/Controllers/Transactions/UpdateCreditNoteOptController.php b/app/Http/Controllers/Transactions/UpdateCreditNoteOptController.php new file mode 100644 index 00000000..8b67dc6b --- /dev/null +++ b/app/Http/Controllers/Transactions/UpdateCreditNoteOptController.php @@ -0,0 +1,14 @@ +execute($request); + } +} diff --git a/app/Http/Resources/TransactionResource.php b/app/Http/Resources/TransactionResource.php index de3fe122..7fcb0611 100644 --- a/app/Http/Resources/TransactionResource.php +++ b/app/Http/Resources/TransactionResource.php @@ -40,6 +40,8 @@ class TransactionResource extends JsonResource //Check if Transaction of type PAYMENT has an override for recipient bank - ends $eInvoice = false; + $manualOptInNormalCreditNote = false; + if($booking && $this->type === TransactionType::REFUND){ $kvp = $this->attributesKVP()->where('key', KVPKey::TRANSACTION_MODEL_CLASS)->first(); if($kvp){ @@ -51,6 +53,12 @@ class TransactionResource extends JsonResource } } } + $kvp = $this->attributesKVP()->where('key', KVPKey::CREDIT_NOTE_NORMAL_OPT_IN_OVERRIDE)->first(); + if($kvp){ + if($kvp->value == 1){ + $manualOptInNormalCreditNote = true; + } + } } $days = $this->created_at->endOfDay()->addWeekdays($booking->service_id === 3 ? 3 : 1); @@ -90,6 +98,7 @@ class TransactionResource extends JsonResource 'bank' => ((int) $this->type === TransactionType::PAYMENT) ? new BankResource($bank) : null, //When a transaction (of type payment) has an override recipient bank details on booking, this is NOT null 'bank_recipient_edited' => $isEditedBankRecipient, 'e_invoice' => $this->when($this->type === TransactionType::REFUND, $eInvoice), + 'manual_opt_in_normal_credit_note' => $this->when($this->type === TransactionType::REFUND, $manualOptInNormalCreditNote), ]; } } diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index 0f690114..caa6ab5d 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -470,12 +470,37 @@ -
+
- + + + + + + + + + - +
- +
diff --git a/routes/transaction.php b/routes/transaction.php index 6e925123..cc9e5c3e 100644 --- a/routes/transaction.php +++ b/routes/transaction.php @@ -30,6 +30,7 @@ use App\Http\Controllers\Transactions\ApproveBillGroupPaymentVerificationControl use App\Http\Controllers\Transactions\DeleteBillGroupController; use App\Http\Controllers\Transactions\CancelBillGroupController; use App\Http\Controllers\Transactions\CreateBillGroupPaymentTransactionController; +use App\Http\Controllers\Transactions\UpdateCreditNoteOptController; use Illuminate\Support\Facades\Route; Route::group(['prefix' => 'transactions', 'as' => 'transaction.'], function () { @@ -81,4 +82,6 @@ Route::group(['prefix' => 'transactions', 'as' => 'transaction.'], function () { // Route::post('/bulk/po', [CreateBulkPurchaseOrderDocumentController::class, 'create'])->name('bulk.po'); }); }); + + Route::get('/refund/{id}/opt', [UpdateCreditNoteOptController::class, 'opt'])->name('refund.opt'); });