From d215e5558d13d017db25fe2eec6d2befacfde2e9 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Fri, 12 Sep 2025 12:59:34 +0800 Subject: [PATCH 01/11] E-Invoice - Enhancement to allow EInvoice to be generated for cases with refund --- .../RegenerateInvoiceBookingLogic.php | 23 +- .../RegenerateInvoiceBookingV2Processor.php | 118 +++++++ .../CalculatesBookingCurrencyAverageRate.php | 17 +- .../CalculatesBookingPayableAmount.php | 11 +- .../CreateInvoiceDocumentProcessor.php | 23 +- .../CreateInvoiceTransactionV2Processor.php | 303 ++++++++++++++++++ .../RegenerateEInvoiceRefundComponent.vue | 43 +++ .../BookingDetailsSectionComponent.vue | 62 +++- .../views/pages/pdfs/e_invoice.blade.php | 2 +- .../pages/pdfs/purchase_order_table.blade.php | 75 +++-- 10 files changed, 630 insertions(+), 47 deletions(-) create mode 100644 app/Classes/Modules/Bookings/Processors/RegenerateInvoiceBookingV2Processor.php create mode 100644 app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionV2Processor.php create mode 100644 resources/assets/vue/components/bookings/forms/RegenerateEInvoiceRefundComponent.vue diff --git a/app/Classes/Modules/Bookings/ControllersLogic/RegenerateInvoiceBookingLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/RegenerateInvoiceBookingLogic.php index bf88251f..486912a5 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/RegenerateInvoiceBookingLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/RegenerateInvoiceBookingLogic.php @@ -6,10 +6,12 @@ use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Bookings\Services\FetchesBooking; use App\Classes\Modules\Bookings\Standards\Rules\CanFetchBooking; use App\Classes\Modules\Bookings\Processors\RegenerateInvoiceBookingProcessor; +use App\Classes\Modules\Bookings\Processors\RegenerateInvoiceBookingV2Processor; use App\Http\Resources\BookingResource; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use App\Classes\ValueObjects\Constants\ApprovalStatus; +use Illuminate\Support\Facades\Log; class RegenerateInvoiceBookingLogic extends AbstractControllerLogic { @@ -34,20 +36,26 @@ class RegenerateInvoiceBookingLogic extends AbstractControllerLogic /** @var RegenerateInvoiceBookingProcessor */ private $regenerateInvoiceBookingProcessor; + /** @var RegenerateInvoiceBookingV2Processor */ + private $regenerateInvoiceBookingV2Processor; + /** * RegenerateInvoiceBookingLogic constructor. * @param CanFetchBooking $canFetchBooking * @param FetchesBooking $fetchesBooking * @param RegenerateInvoiceBookingProcessor $regenerateInvoiceBookingProcessor + * @param RegenerateInvoiceBookingV2Processor $regenerateInvoiceBookingV2Processor */ public function __construct( CanFetchBooking $canFetchBooking, FetchesBooking $fetchesBooking, - RegenerateInvoiceBookingProcessor $regenerateInvoiceBookingProcessor + RegenerateInvoiceBookingProcessor $regenerateInvoiceBookingProcessor, + RegenerateInvoiceBookingV2Processor $regenerateInvoiceBookingV2Processor ) { $this->canFetchBooking = $canFetchBooking; $this->fetchesBooking = $fetchesBooking; $this->regenerateInvoiceBookingProcessor = $regenerateInvoiceBookingProcessor; + $this->regenerateInvoiceBookingV2Processor = $regenerateInvoiceBookingV2Processor; } @@ -65,13 +73,20 @@ class RegenerateInvoiceBookingLogic extends AbstractControllerLogic $booking = $this->fetchesBooking->execute( [ 'id' => $request->route('id'), - 'status' => ApprovalStatus::COMPLETED, + // 'status' => ApprovalStatus::COMPLETED, //cief todo: 90 - must have completed to avoid generate invoice inaccurately 'with_transactions' => true ] ); - $normalInvoice = $request->input('normal_invoice', false); - $this->regenerateInvoiceBookingProcessor->execute($booking, $normalInvoice); + $eInvoiceWithNormalInvoiceTemplate = $request->input('normal_invoice', false); + $eInvoiceRefund = $request->input('e_invoice_refund', false); + + // if($eInvoiceRefund){ + $this->regenerateInvoiceBookingV2Processor->execute($booking, $eInvoiceWithNormalInvoiceTemplate, $eInvoiceRefund); + // } + // else{ + // $this->regenerateInvoiceBookingProcessor->execute($booking, $eInvoiceWithNormalInvoiceTemplate); + // } return $this->resourceResponse(new BookingResource($booking)); } diff --git a/app/Classes/Modules/Bookings/Processors/RegenerateInvoiceBookingV2Processor.php b/app/Classes/Modules/Bookings/Processors/RegenerateInvoiceBookingV2Processor.php new file mode 100644 index 00000000..bbec8757 --- /dev/null +++ b/app/Classes/Modules/Bookings/Processors/RegenerateInvoiceBookingV2Processor.php @@ -0,0 +1,118 @@ +deletesTransaction = $deletesTransaction; + $this->updatesBookingStatus = $updatesBookingStatus; + $this->deletesDocument = $deletesDocument; + $this->createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor; + } + + public function execute(Booking $booking, + bool $eInvoiceWithNormalInvoiceTemplate = false, + bool $eInvoiceWithRefund = false) + { + $bookingOriginalStatus = $booking->status; + + if(!$eInvoiceWithRefund){ + $this->updatesBookingStatus->execute($booking, ApprovalStatus::APPROVED); + } + + $firstInvoice = $booking->transactions() + ->whereIn('type', [TransactionType::INVOICE]) + ->withTrashed() + ->orderBy('created_at', 'asc') + ->first(); + + Log::info('RegenerateInvoiceBookingV2Processor booking: ' . json_encode($booking->marking)); + + // get the first bill_no + if($firstInvoice){ + $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(); + if($currentInvoice){ + $currentInvoice->bill_no = $currentInvoice->bill_no ."-deleted-" . (string)(Carbon::now()->timestamp); + $currentInvoice->save(); + } + + $transactionWithSameBillNo = Transaction::where('bill_no', $firstBillNo)->withTrashed()->get(); + if ($transactionWithSameBillNo) { + foreach ($transactionWithSameBillNo as $transaction) { + $transaction->bill_no = $transaction->bill_no . "-deleted-" . Str::random(10); + $transaction->save(); + } + } + + $transaction = $booking->transactions()->whereIn('type', [TransactionType::INVOICE, TransactionType::SUPPLIER_DELIVER])->get(); + foreach ($transaction as $key => $row) { + $this->deletesTransaction->execute($row); + } + + $document = $booking->documents()->whereIn('document_type', [DocumentType::PURCHASE_ORDER, DocumentType::INVOICE, DocumentType::EINVOICE, DocumentType::DELIVER_ORDER, DocumentType::SUPPLIER_DELIVER_ORDER])->get(); + foreach ($document as $key => $row) { + $this->deletesDocument->execute($row); + } + + $this->createInvoiceTransactionProcessor->execute($booking, $firstBillNo, [ + 'generateEInvoice' => true, + 'generateEInvoiceWithNormalInvoiceTemplate' => $eInvoiceWithNormalInvoiceTemplate, + 'generateEInvoiceRefund' => $eInvoiceWithRefund, + 'bookingOriginalStatus' => $bookingOriginalStatus + ]); + } + else { + $this->createInvoiceTransactionProcessor->execute($booking, "", [ + 'generateEInvoice' => false, + 'generateEInvoiceWithNormalInvoiceTemplate' => $eInvoiceWithNormalInvoiceTemplate, + 'generateEInvoiceRefund' => $eInvoiceWithRefund, + 'bookingOriginalStatus' => $bookingOriginalStatus + ]); + } + } +} diff --git a/app/Classes/Modules/Bookings/Services/CalculatesBookingCurrencyAverageRate.php b/app/Classes/Modules/Bookings/Services/CalculatesBookingCurrencyAverageRate.php index 9cb7717e..aaa3e569 100644 --- a/app/Classes/Modules/Bookings/Services/CalculatesBookingCurrencyAverageRate.php +++ b/app/Classes/Modules/Bookings/Services/CalculatesBookingCurrencyAverageRate.php @@ -22,7 +22,7 @@ class CalculatesBookingCurrencyAverageRate } - public function execute(Booking $booking, $type){ + public function execute(Booking $booking, $type, bool $generateEInvoiceRefund = false){ $transaction = $booking->transactions() ->where('type', TransactionType::PAYMENT) @@ -37,9 +37,16 @@ class CalculatesBookingCurrencyAverageRate } 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 + $discount); + if($generateEInvoiceRefund){ + $totalPayment = $booking->fix_currency_id === 1 ? $booking->transactions()->payments()->where('status', ApprovalStatus::REFUNDED)->sum('original_amount') : + $booking->transactions()->payments()->where('status', ApprovalStatus::REFUNDED)->selectRaw('sum(amount - service_charge - tax) as sub_total')->get()->sum('sub_total'); + } + else{ + $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, $generateEInvoiceRefund) / ($totalPayment + $discount); } else if ($type == TransactionType::BILL) { @@ -47,4 +54,4 @@ class CalculatesBookingCurrencyAverageRate } } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Bookings/Services/CalculatesBookingPayableAmount.php b/app/Classes/Modules/Bookings/Services/CalculatesBookingPayableAmount.php index a068cbbe..c60debdb 100644 --- a/app/Classes/Modules/Bookings/Services/CalculatesBookingPayableAmount.php +++ b/app/Classes/Modules/Bookings/Services/CalculatesBookingPayableAmount.php @@ -11,11 +11,18 @@ use Carbon\Carbon; class CalculatesBookingPayableAmount { - public function execute(Booking $booking, int $type){ + public function execute(Booking $booking, int $type, bool $generateEInvoiceRefund = false){ + + if($generateEInvoiceRefund){ + return $type === 1 ? + $booking->transactions()->payments()->where('status', ApprovalStatus::REFUNDED) + ->selectRaw('sum(amount - service_charge - tax) as sub_total')->get()->sum('sub_total') : + $booking->transactions()->payments()->where('status', ApprovalStatus::REFUNDED)->sum('original_amount'); + } return $type === 1 ? $booking->transactions()->payments()->complete() ->selectRaw('sum(amount - service_charge - tax) as sub_total')->get()->sum('sub_total') : $booking->transactions()->payments()->complete()->sum('original_amount'); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Transactions/Processors/CreateInvoiceDocumentProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateInvoiceDocumentProcessor.php index 6e746415..06f50005 100644 --- a/app/Classes/Modules/Transactions/Processors/CreateInvoiceDocumentProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/CreateInvoiceDocumentProcessor.php @@ -44,7 +44,7 @@ class CreateInvoiceDocumentProcessor * @return void * @throws \App\Classes\Exceptions\MalformedRequestException */ - public function execute($transaction, $purchaseOrder, $supplier, $document_type, $voucherRedemption = null, $isAllowNormalInvoice = false) + public function execute($transaction, $purchaseOrder, $supplier, $document_type, $voucherRedemption = null, $generateEInvoiceWithNormalInvoiceTemplate = false, $generateEInvoiceRefund = false) { // calculate current Paid Amount $booking = $transaction->owner_type == Booking::class ? $transaction->owner : null; @@ -61,7 +61,13 @@ class CreateInvoiceDocumentProcessor if ($booking) { $bookingCreatedDate = Carbon::parse($booking->created_at); if ($bookingCreatedDate->isAfter($eInvoiceStartDate)) { - $lastPaymentTransaction = $booking->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::COMPLETED, ApprovalStatus::APPROVED])->latest()->first(); + if($generateEInvoiceRefund){ + $lastPaymentTransaction = $booking->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::REFUNDED])->latest()->first(); + } + else{ + $lastPaymentTransaction = $booking->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::COMPLETED, ApprovalStatus::APPROVED])->latest()->first(); + } + $documentDate = $lastPaymentTransaction->created_at; } @@ -83,7 +89,14 @@ class CreateInvoiceDocumentProcessor $documentDate = $lastDayOfMonth; } } - $payment = $booking->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::COMPLETED, ApprovalStatus::APPROVED])->first(); + + if($generateEInvoiceRefund){ + $payment = $booking->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::REFUNDED])->first(); + } + else{ + $payment = $booking->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::COMPLETED, ApprovalStatus::APPROVED])->first(); + } + $refundAmount = $payment->transactions()->refunds()->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->sum('amount'); $paymentAmount = $payment->amount; $currentPaidAmount = $paymentAmount - $refundAmount; @@ -92,7 +105,7 @@ class CreateInvoiceDocumentProcessor $lowercaseDocumentType = strtolower($document_type); if($document_type === DocumentType::EINVOICE){ //July 2025 workaround generate normal invoice instead of E-Invoice - if($isAllowNormalInvoice){ + if($generateEInvoiceWithNormalInvoiceTemplate){ $lowercaseDocumentType = strtolower(DocumentType::INVOICE); } } @@ -169,7 +182,7 @@ class CreateInvoiceDocumentProcessor $document = $this->createsDocument->execute($transaction, $document_object); } else{ - $document = $this->createsDocument->execute($purchaseOrder->booking, $document_object); + $document = $this->createsDocument->execute($purchaseOrder->booking ?? $booking, $document_object); } $this->createsFile->execute($document, $document_object); } diff --git a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionV2Processor.php b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionV2Processor.php new file mode 100644 index 00000000..c5f3f410 --- /dev/null +++ b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionV2Processor.php @@ -0,0 +1,303 @@ +createsTransaction = $createsTransaction; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->calculatesBookingPaidAmount = $calculatesBookingPaidAmount; + $this->calculatesBookingPayableAmount = $calculatesBookingPayableAmount; + $this->calculatesBookingTransferredAmount = $calculatesBookingTransferredAmount; + $this->calculatesBookingCurrencyAverageRate = $calculatesBookingCurrencyAverageRate; + $this->fetchesCompany = $fetchesCompany; + $this->updatesBookingStatus = $updatesBookingStatus; + $this->invoiceDocumentProcessor = $invoiceDocumentProcessor; + } + + + + /** + * @param Booking $booking + * @param String $invoiceNo + * @param array $options + * @return void + * @throws MalformedRequestException + */ + public function execute(Booking $booking, String $invoiceNo= "", array $options = []) + { + $generateEInvoice = $options['generateEInvoice'] ?? false; + $generateEInvoiceWithNormalInvoiceTemplate = $options['generateEInvoiceWithNormalInvoiceTemplate'] ?? false; + $generateEInvoiceRefund = $options['generateEInvoiceRefund'] ?? false; + $bookingOriginalStatus = $options['bookingOriginalStatus'] ?? ApprovalStatus::COMPLETED; + + if($generateEInvoiceRefund){ + $generateEInvoice = true; //cief todo: 90 - cannot have 2 flags doing the same thing + } + + if ($booking->status === ApprovalStatus::COMPLETED && !$generateEInvoiceRefund) { + return; + } + + $payable_amount = $this->calculatesBookingPayableAmount->execute($booking, $booking->fix_currency_id, $generateEInvoiceRefund); + $booking_amount = $booking->fix_amount; + + // confirm that booking amount has been fully paid + if ((float) $booking_amount > (float) $payable_amount) { + return; + } + // confirm that all payments has been transferred + if ($this->calculatesBookingTransferredAmount->execute($booking) !== $this->calculatesBookingPaidAmount->execute($booking)) { + return; + } + + if($generateEInvoiceRefund){ + $purchaseOrder = $booking->transactions() + ->where('type', TransactionType::PURCHASE_ORDER) + ->where('status', ApprovalStatus::PENDING_SUBMISSION) + ->first(); + } + else{ + $purchaseOrder = $booking->transactions() + ->where('type', TransactionType::PURCHASE_ORDER) + ->complete() + ->first(); + } + + $constants = SegmentConstant::where('reference', SegmentConstants::SERVICE_TYPE)->where('detail->id', $booking->service->id)->first(); + + if ($constants->detail->is_billable && !$purchaseOrder && !$generateEInvoiceRefund) { + return; + } + + // $transaction = $booking->transactions() + // ->where('type', TransactionType::PAYMENT) + // ->first(); + + $transaction = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->latest()->get()[0]; + $supplier = $this->fetchesCompany->execute(['id' => $transaction->receiver]); + + // Check if eInvoice implementation has started and company opted in for eInvoice + $eInvoice = false; + $eInvoiceStartDate = Carbon::parse(env('E_INVOICE_START_DATE', '2025-07-01 00:00:00')); + $bookingCreatedDate = Carbon::parse($booking->created_at); + if ($bookingCreatedDate->isAfter($eInvoiceStartDate) && $supplier->e_invoice === 1) { + $eInvoice = true; + } + $kvp = $booking->attributesKVP()->where('key', KVPKey::BOOKING_EINVOICE_ELIGIBLE)->first(); + if($kvp){ + $eInvoice = true; + } + + if($generateEInvoiceWithNormalInvoiceTemplate){ + $invoiceNo = ""; //July 2025 workaround generate normal invoice instead of E-Invoice + } + + if($invoiceNo){ + $billNumber = $invoiceNo; + } + else{ + $billNUmberPrefix = $eInvoice ? 'EINV-' : 'INV-'; + if($generateEInvoiceWithNormalInvoiceTemplate){ + $billNUmberPrefix = 'INV-'; //July 2025 workaround generate normal invoice instead of E-Invoice + } + $billNumber = $this->generatesTransactionBillNumber->execute($billNUmberPrefix); + } + + $booking_currency_average_rate = $this->calculatesBookingCurrencyAverageRate->execute($booking, TransactionType::PAYMENT, $generateEInvoiceRefund); + + if($generateEInvoiceRefund){ + $total_service_charge = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->whereIn('status', [ApprovalStatus::REFUNDED]) + ->sum('service_charge'); + + $total_tax = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->whereIn('status', [ApprovalStatus::REFUNDED]) + ->sum('tax'); + } + else{ + $total_service_charge = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]) + ->sum('service_charge'); + + $total_tax = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]) + ->sum('tax'); + } + + + + $transaction_object = new TransactionObject( + $billNumber, + TransactionType::INVOICE, + $transaction->issuer, + $transaction->receiver, + $transaction->recipient_bank_account_id, + $transaction->payment_method, + $payable_amount, + $booking_amount, + $transaction->currency_id, + $transaction->original_currency_id, + $booking_currency_average_rate, + $total_tax, + $total_service_charge, + null, + ApprovalStatus::APPROVED + ); + $invoice_transaction = $this->createsTransaction->execute($purchaseOrder->booking ?? $booking, $transaction_object); + + $voucherRedemption = $transaction->voucherRedemption; + + // purchase order + if(!$generateEInvoiceRefund){ + $this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::PURCHASE_ORDER, $voucherRedemption, $generateEInvoiceWithNormalInvoiceTemplate); + } + + // deliver order + if(!$generateEInvoiceRefund){ + $this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::DELIVER_ORDER, $voucherRedemption, $generateEInvoiceWithNormalInvoiceTemplate); + } + + // e-invoice + if ($eInvoice) + { + if($generateEInvoice){ + $this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::EINVOICE, $voucherRedemption, $generateEInvoiceWithNormalInvoiceTemplate, $generateEInvoiceRefund); + } + } + // invoice + else + { + $this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::INVOICE, $voucherRedemption, $generateEInvoiceWithNormalInvoiceTemplate, $generateEInvoiceRefund); + } + + if(!$generateEInvoiceRefund){ + $billNumber = $this->generatesTransactionBillNumber->execute('SPDO-'); + + $booking_currency_average_rate = $this->calculatesBookingCurrencyAverageRate->execute($booking, TransactionType::BILL, $generateEInvoiceRefund); + + $paymentTransaction = $booking->transactions()->payments()->where('status', ApprovalStatus::COMPLETED)->first(); + + $transaction = null; + if($paymentTransaction){ + $transaction = $paymentTransaction->transactions()->where('type', TransactionType::BILL)->first(); + } + else{ // Special handling for refund cases (When a refund is deleted via DeleteRefundTransactionLogic, a booking payment transaction is set to ApprovalStatus::APPROVED) + $temp = $booking->transactions()->payments()->where('status', ApprovalStatus::APPROVED)->first(); + // Lets check if there is a refund case + $refund = $temp->transactions()->refunds()->where('status', ApprovalStatus::APPROVED)->first(); + if($refund){ + $transaction = $temp; + } + else{ + throw new Exception("No payment found for booking '$booking->id'."); + } + } + + $transaction_object = new TransactionObject( + $billNumber, + TransactionType::SUPPLIER_DELIVER, + $transaction->issuer, + $transaction->receiver, + $transaction->recipient_bank_account_id, + $transaction->payment_method, + $payable_amount, + $booking_amount, + $transaction->currency_id, + $transaction->original_currency_id, + $booking_currency_average_rate, + $total_tax, + $total_service_charge, + null, + ApprovalStatus::APPROVED + ); + $supplier_deliver_order_transaction = $this->createsTransaction->execute($purchaseOrder->booking, $transaction_object); + + // supply deliver order + $this->invoiceDocumentProcessor->execute($supplier_deliver_order_transaction, $purchaseOrder, $supplier, DocumentType::SUPPLIER_DELIVER_ORDER, null); + } + + //if(!$generateEInvoiceRefund){ + $this->updatesBookingStatus->execute($booking, $bookingOriginalStatus); + //} + + // update perfex crm + // if(config('perfexcrm.is_enabled') == 'true'){ + // CreatePerfexCRMInvoice::dispatch($invoice_transaction, $purchaseOrder, $supplier); + // } + } +} diff --git a/resources/assets/vue/components/bookings/forms/RegenerateEInvoiceRefundComponent.vue b/resources/assets/vue/components/bookings/forms/RegenerateEInvoiceRefundComponent.vue new file mode 100644 index 00000000..75d19280 --- /dev/null +++ b/resources/assets/vue/components/bookings/forms/RegenerateEInvoiceRefundComponent.vue @@ -0,0 +1,43 @@ + + diff --git a/resources/assets/vue/components/bookings/sections/BookingDetailsSectionComponent.vue b/resources/assets/vue/components/bookings/sections/BookingDetailsSectionComponent.vue index 271826ff..bc5f3dca 100644 --- a/resources/assets/vue/components/bookings/sections/BookingDetailsSectionComponent.vue +++ b/resources/assets/vue/components/bookings/sections/BookingDetailsSectionComponent.vue @@ -5,7 +5,7 @@
-
+
@@ -133,6 +133,58 @@
+
+
+
+
+
+
+
+
+
+ +
+
+ + + +
+
+ +
+

E-Invoice (Pending)

+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+
@@ -343,6 +395,14 @@
+
+
+
Regenerate E-Invoice
(Refund)
+
+ + + +
Regenerate E-Invoice
diff --git a/resources/views/pages/pdfs/e_invoice.blade.php b/resources/views/pages/pdfs/e_invoice.blade.php index 9c7dce39..cf3069ca 100644 --- a/resources/views/pages/pdfs/e_invoice.blade.php +++ b/resources/views/pages/pdfs/e_invoice.blade.php @@ -25,7 +25,7 @@
E-Invoice
EI#: {{ $autocountId ?? 'NONE'}}
-
Ref# {{ $po_order_transaction->booking->marking }}
+
Ref# {{ $booking->marking }}
Date: {{ $document_date->toDateString() }}
 
diff --git a/resources/views/pages/pdfs/purchase_order_table.blade.php b/resources/views/pages/pdfs/purchase_order_table.blade.php index 542f1144..ce85538b 100644 --- a/resources/views/pages/pdfs/purchase_order_table.blade.php +++ b/resources/views/pages/pdfs/purchase_order_table.blade.php @@ -25,7 +25,7 @@ use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\TransactionType; - $booking = $po_order_transaction->owner; + $booking = $po_order_transaction->owner ?? $booking; $paymentSum = $booking->transactions() ->where('type', TransactionType::PAYMENT) ->where('status', ApprovalStatus::COMPLETED) @@ -36,6 +36,8 @@ $totalPayment = 0; $average_currency_rate = $transaction->currency_rate; + + $paymentSumRefund = 0; if ($paymentSum){ $average_currency_rate = $booking->transactions() ->where('type', TransactionType::PAYMENT) @@ -53,30 +55,41 @@ $totalPayment = $paymentSum - $refundedAmount - $refundedServiceCharge; } + else{ + $paymentSumRefund = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->where('status', ApprovalStatus::REFUNDED) + ->get() + ->sum(function ($transaction) { + return round($transaction->amount, 2); + }); + } ?> - @foreach ($po_order_transaction->transactionDetails as $key => $transaction_detail) - @php - $exactUnitPrice = ($currency_id) === 1 ? $transaction_detail->price : bcdiv($transaction_detail->price, $average_currency_rate, 7); - $displayUnitPrice = round($exactUnitPrice, 2); - $itemTotal = bcmul($exactUnitPrice, $transaction_detail->quantity, 5); - $displayedItemTotal = round(bcmul($displayUnitPrice, $transaction_detail->quantity, 7), 2); - $displayedSubtotal = bcadd($displayedSubtotal, $displayedItemTotal, 2); - $subtotal = bcadd($subtotal, $itemTotal, 5); - @endphp - - {{ $key + 1 }} - {{ $transaction_detail->product_code }} - {{ $transaction_detail->product_name }} - {{ $transaction_detail->quantity }} - - {{ number_format($displayUnitPrice, 2) }} - - - {{ number_format($displayedItemTotal, 2) }} - - - @endforeach + @if (!empty($po_order_transaction) && $po_order_transaction->transactionDetails) + @foreach ($po_order_transaction->transactionDetails as $key => $transaction_detail) + @php + $exactUnitPrice = ($currency_id) === 1 ? $transaction_detail->price : bcdiv($transaction_detail->price, $average_currency_rate, 7); + $displayUnitPrice = round($exactUnitPrice, 2); + $itemTotal = bcmul($exactUnitPrice, $transaction_detail->quantity, 5); + $displayedItemTotal = round(bcmul($displayUnitPrice, $transaction_detail->quantity, 7), 2); + $displayedSubtotal = bcadd($displayedSubtotal, $displayedItemTotal, 2); + $subtotal = bcadd($subtotal, $itemTotal, 5); + @endphp + + {{ $key + 1 }} + {{ $transaction_detail->product_code }} + {{ $transaction_detail->product_name }} + {{ $transaction_detail->quantity }} + + {{ number_format($displayUnitPrice, 2) }} + + + {{ number_format($displayedItemTotal, 2) }} + + + @endforeach + @endif @php @@ -101,7 +114,7 @@ ->get() ->sum(function ($transaction) { return $transaction->service_charge; - }); + }); } ?> {{ number_format($serviceCharge, 2) }} @@ -142,11 +155,11 @@ $displayedTotal = bcadd( bcadd( - bcadd($displayedSubtotal, $serviceCharge, 5), - $tax, + bcadd($displayedSubtotal, $serviceCharge, 5), + $tax, 5 - ), - $voucherDiscount, + ), + $voucherDiscount, 5 ); @@ -159,6 +172,10 @@ $discrepancy = bcsub($expectedTotal, $displayedTotal, 5); $total = $totalPayment; } + + if($paymentSumRefund){ + $total = $paymentSumRefund; + } @endphp @@ -173,4 +190,4 @@ - \ No newline at end of file + From 22cf998ae6b59e9d298b5442789fd6bab12ceb38 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Fri, 12 Sep 2025 14:38:11 +0800 Subject: [PATCH 02/11] E-Invoice - Fix transfer with full refund PO total should not be 0 --- .../forms/PurchaseOrderFormComponent.vue | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue index 697315d6..c499e6b3 100644 --- a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue @@ -143,7 +143,19 @@
Total:
-
{{(Math.round(( poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3)}}/{{(Math.round((data.amount + Number.EPSILON) * 1000) / 1000).toFixed(3)}} {{data.fixed_currency.short_code}}
+ +
+ + {{ totalFormattedPoTotal }}/ + + + {{ totalFormattedDataAmount }} {{ data.fixed_currency.short_code }} + +
@@ -267,7 +279,7 @@ return last + product.total; }, 0); }, - allowPOEditing() { + allowPOEditing() { //Condition 1 const noPaymentsMade = Math.round((this.data.paid_amount + Number.EPSILON) * 100) / 100 === 0; const noPaymentPendingVerifications = this.data.payment_history.every(payment => payment.status !== 1); @@ -281,6 +293,23 @@ const adminBeforeApproval = this.$store.getters.isAdmin && !(this.data.purchase_order.status === 2); return (noPaymentsMade && noPaymentPendingVerifications) || (paymentsMade && outstandingAmount && allPaymentApproved) || adminBeforeApproval; + }, + totalFormattedPoTotal() { + return (Math.round((this.poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3); + }, + totalFormattedDataAmount() { + if(this.data.amount === 0 && this.data.outstanding_amount === 0 && this.data.floating_amount === 0 && this.data.paid_amount === 0){ + return (Math.round((this.poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3); + } + else{ + return (Math.round((this.data.amount + Number.EPSILON) * 1000) / 1000).toFixed(3); + } + }, + totalAmountClass() { + return { + 'text-danger': this.totalFormattedPoTotal !== this.totalFormattedDataAmount, + 'text-success': this.totalFormattedPoTotal === this.totalFormattedDataAmount, + }; } }, watch: { From 0b5c736ba41fb25b000b874c927ba2fd06ef9aaf Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Fri, 12 Sep 2025 15:43:12 +0800 Subject: [PATCH 03/11] E-Invoice - Cleanup --- ...OneTimeBatchProcessEInvoicesV2CommandJob.php | 4 ++-- .../V2/ProcessPaymentReportV2CommandJob.php | 1 - .../ProcessSalesInvoiceReportV2CommandJob.php | 1 - .../BatchBookingsGenerateEInvoiceLogic.php | 17 +---------------- .../UploadPurchaseOrderLogic.php | 1 - .../ControllersLogic/DeleteTransactionLogic.php | 5 +---- 6 files changed, 4 insertions(+), 25 deletions(-) diff --git a/app/Classes/Jobs/Commands/V2/OneTimeBatchProcessEInvoicesV2CommandJob.php b/app/Classes/Jobs/Commands/V2/OneTimeBatchProcessEInvoicesV2CommandJob.php index 26783cbe..09eed529 100644 --- a/app/Classes/Jobs/Commands/V2/OneTimeBatchProcessEInvoicesV2CommandJob.php +++ b/app/Classes/Jobs/Commands/V2/OneTimeBatchProcessEInvoicesV2CommandJob.php @@ -2,7 +2,7 @@ namespace App\Classes\Jobs\Commands\V2; -use App\Classes\Modules\Bookings\Processors\RegenerateInvoiceBookingProcessor; +use App\Classes\Modules\Bookings\Processors\RegenerateInvoiceBookingV2Processor; use Carbon\Carbon; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; @@ -35,7 +35,7 @@ class OneTimeBatchProcessEInvoicesV2CommandJob implements ShouldQueue $start = new Carbon(); $isAllowNormalInvoice = true; - (App()->make(RegenerateInvoiceBookingProcessor::class))->execute($this->booking, $isAllowNormalInvoice); + (App()->make(RegenerateInvoiceBookingV2Processor::class))->execute($this->booking, $isAllowNormalInvoice); $end = new Carbon(); $elapsedTime = $start->diff($end)->format('%H:%I:%S'); diff --git a/app/Classes/Jobs/Commands/V2/ProcessPaymentReportV2CommandJob.php b/app/Classes/Jobs/Commands/V2/ProcessPaymentReportV2CommandJob.php index ed54580e..6537670d 100644 --- a/app/Classes/Jobs/Commands/V2/ProcessPaymentReportV2CommandJob.php +++ b/app/Classes/Jobs/Commands/V2/ProcessPaymentReportV2CommandJob.php @@ -5,7 +5,6 @@ namespace App\Classes\Jobs\Commands\V2; use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject; use App\Classes\Modules\Accounts\Services\CreatesKeyValuePair; use App\Classes\Modules\Accounts\Services\UpdatesKeyValuePair; -use App\Classes\Modules\Bookings\Processors\RegenerateInvoiceBookingProcessor; use App\Classes\ValueObjects\Constants\KVPKey; use Carbon\Carbon; use Illuminate\Bus\Queueable; diff --git a/app/Classes/Jobs/Commands/V2/ProcessSalesInvoiceReportV2CommandJob.php b/app/Classes/Jobs/Commands/V2/ProcessSalesInvoiceReportV2CommandJob.php index 66a4d457..aad018ba 100644 --- a/app/Classes/Jobs/Commands/V2/ProcessSalesInvoiceReportV2CommandJob.php +++ b/app/Classes/Jobs/Commands/V2/ProcessSalesInvoiceReportV2CommandJob.php @@ -5,7 +5,6 @@ namespace App\Classes\Jobs\Commands\V2; use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject; use App\Classes\Modules\Accounts\Services\CreatesKeyValuePair; use App\Classes\Modules\Accounts\Services\UpdatesKeyValuePair; -use App\Classes\Modules\Bookings\Processors\RegenerateInvoiceBookingProcessor; use App\Classes\ValueObjects\Constants\KVPKey; use Carbon\Carbon; use Illuminate\Bus\Queueable; diff --git a/app/Classes/Modules/Bookings/ControllersLogic/BatchBookingsGenerateEInvoiceLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/BatchBookingsGenerateEInvoiceLogic.php index 84cae498..00175130 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/BatchBookingsGenerateEInvoiceLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/BatchBookingsGenerateEInvoiceLogic.php @@ -7,7 +7,6 @@ use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Jobs\Commands\V2\ProcessBookingForEInvoiceV2CommandJob; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Models\Booking; -use App\Classes\Modules\Bookings\Processors\RegenerateInvoiceBookingProcessor; use App\Classes\ValueObjects\Constants\KVPKey; use Carbon\Carbon; use Illuminate\Database\Eloquent\Builder; @@ -35,20 +34,6 @@ class BatchBookingsGenerateEInvoiceLogic extends AbstractControllerLogic ]; } - /** @var RegenerateInvoiceBookingProcessor */ - private $regenerateInvoiceBookingProcessor; - - /** - * BatchBookingsGenerateEInvoiceLogic constructor. - * @param RegenerateInvoiceBookingProcessor $regenerateInvoiceBookingProcessor - */ - public function __construct( - RegenerateInvoiceBookingProcessor $regenerateInvoiceBookingProcessor - ) { - $this->regenerateInvoiceBookingProcessor = $regenerateInvoiceBookingProcessor; - } - - /** * @param Request $request * @return JsonResponse @@ -100,7 +85,7 @@ class BatchBookingsGenerateEInvoiceLogic extends AbstractControllerLogic foreach ($bookings as $booking) { //$autocountValue = optional($booking->attributesKVP->first())->value; //Log::info('Booking ID: ' . $booking->marking . ' | AUTOCOUNT_DOCNO_INVOICE: ' . $autocountValue); - // $this->regenerateInvoiceBookingProcessor->execute($booking); + // $this->regenerateInvoiceBookingV2Processor->execute($booking); ProcessBookingForEInvoiceV2CommandJob::dispatch($booking); } $this->processedCount = count($bookings); diff --git a/app/Classes/Modules/Bookings/ControllersLogic/UploadPurchaseOrderLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/UploadPurchaseOrderLogic.php index ef6124cf..bddab339 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/UploadPurchaseOrderLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/UploadPurchaseOrderLogic.php @@ -13,7 +13,6 @@ use App\Classes\Modules\Documents\Services\CreatesFiles; use App\Classes\Modules\Documents\Services\FetchesDocument; use App\Classes\Modules\Documents\Services\RejectsDocument; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; -use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; use App\Classes\Modules\Transactions\Processors\CreatePurchaseOrderTransactionProcessor; use App\Classes\Modules\Transactions\Services\FetchesTransaction; use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; diff --git a/app/Classes/Modules/Transactions/ControllersLogic/DeleteTransactionLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/DeleteTransactionLogic.php index 7995e447..42bc29fc 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/DeleteTransactionLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/DeleteTransactionLogic.php @@ -15,9 +15,6 @@ use App\Models\Document; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; - - class DeleteTransactionLogic extends AbstractControllerLogic { @@ -69,4 +66,4 @@ class DeleteTransactionLogic extends AbstractControllerLogic return $this->response([]); } -} \ No newline at end of file +} From 112d07c4c6ea58036ac3931138559a163464b888 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Fri, 12 Sep 2025 16:09:50 +0800 Subject: [PATCH 04/11] E-Invoice - Cleanup --- .../Commands/V2/ProcessBookingForEInvoiceV2CommandJob.php | 6 +++--- .../Processors/RegenerateInvoiceBookingProcessor.php | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/Classes/Jobs/Commands/V2/ProcessBookingForEInvoiceV2CommandJob.php b/app/Classes/Jobs/Commands/V2/ProcessBookingForEInvoiceV2CommandJob.php index 366bf163..c49e6a2f 100644 --- a/app/Classes/Jobs/Commands/V2/ProcessBookingForEInvoiceV2CommandJob.php +++ b/app/Classes/Jobs/Commands/V2/ProcessBookingForEInvoiceV2CommandJob.php @@ -2,7 +2,7 @@ namespace App\Classes\Jobs\Commands\V2; -use App\Classes\Modules\Bookings\Processors\RegenerateInvoiceBookingProcessor; +use App\Classes\Modules\Bookings\Processors\RegenerateInvoiceBookingV2Processor; use App\Classes\ValueObjects\Constants\DocumentType; use Carbon\Carbon; use Illuminate\Bus\Queueable; @@ -36,11 +36,11 @@ class ProcessBookingForEInvoiceV2CommandJob implements ShouldQueue $start = new Carbon(); // $documents = $this->booking->documents()->whereIn('document_type', [DocumentType::INVOICE, DocumentType::DELIVER_ORDER, DocumentType::SUPPLIER_DELIVER_ORDER])->get(); - $documents = $this->booking->documents()->whereIn('document_type', [DocumentType::EINVOICE])->get(); + $documents = $this->booking->documents()->whereIn('document_type', [DocumentType::EINVOICE, DocumentType::INVOICE])->get(); if ($documents->isEmpty()) { Log::info("Processing for E-Invoice, booking id : " . $this->booking->marking); - (App()->make(RegenerateInvoiceBookingProcessor::class))->execute($this->booking); + (App()->make(RegenerateInvoiceBookingV2Processor::class))->execute($this->booking); } else{ Log::info("NO Processing for E-Invoice, booking id : " . $this->booking->marking); diff --git a/app/Classes/Modules/Bookings/Processors/RegenerateInvoiceBookingProcessor.php b/app/Classes/Modules/Bookings/Processors/RegenerateInvoiceBookingProcessor.php index 7b392d08..f1495d82 100644 --- a/app/Classes/Modules/Bookings/Processors/RegenerateInvoiceBookingProcessor.php +++ b/app/Classes/Modules/Bookings/Processors/RegenerateInvoiceBookingProcessor.php @@ -16,6 +16,10 @@ use App\Models\Transaction; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Log; +/** + * @deprecated This class is deprecated and should not be used. + * Use `RegenerateInvoiceBookingV2Processor` instead + */ class RegenerateInvoiceBookingProcessor { /** @var DeletesTransaction */ From ee228d89e6108d99348ecbbbb243293b4f9dc772 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Fri, 12 Sep 2025 16:27:02 +0800 Subject: [PATCH 05/11] E-Invoice - Cleanup --- app/Classes/Jobs/GenerateInvoice.php | 4 ++-- .../CreatePurchaseOrderFor1688OrderProcessor.php | 8 ++++---- .../Documents/ControllersLogic/DeleteDocumentLogic.php | 7 ++----- .../UpdatePaymentTransactionStatusLogic.php | 5 +---- .../Processors/CreateInvoiceTransactionProcessor.php | 4 ++++ 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/app/Classes/Jobs/GenerateInvoice.php b/app/Classes/Jobs/GenerateInvoice.php index 83191e25..927ed00b 100644 --- a/app/Classes/Jobs/GenerateInvoice.php +++ b/app/Classes/Jobs/GenerateInvoice.php @@ -2,7 +2,7 @@ namespace App\Classes\Jobs; -use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; +use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionV2Processor; use App\Classes\Modules\Transactions\Processors\GeneratesGroupTransactionsWhiteForm; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\DocumentType; @@ -38,6 +38,6 @@ class GenerateInvoice implements ShouldQueue $this->booking->status = ApprovalStatus::APPROVED; $this->booking->save(); - (App()->make(CreateInvoiceTransactionProcessor::class))->execute($this->booking); + // (App()->make(CreateInvoiceTransactionV2Processor::class))->execute($this->booking); } } diff --git a/app/Classes/Modules/Bookings/Processors/CreatePurchaseOrderFor1688OrderProcessor.php b/app/Classes/Modules/Bookings/Processors/CreatePurchaseOrderFor1688OrderProcessor.php index fc7190cc..8a24a5ab 100644 --- a/app/Classes/Modules/Bookings/Processors/CreatePurchaseOrderFor1688OrderProcessor.php +++ b/app/Classes/Modules/Bookings/Processors/CreatePurchaseOrderFor1688OrderProcessor.php @@ -6,7 +6,7 @@ namespace App\Classes\Modules\Bookings\Processors; use App\Classes\Exceptions\MalformedRequestException; use App\Classes\Modules\Bookings\Services\Convert1688PurchaseOrderToProductList; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; -use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; +use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionV2Processor; use App\Classes\Modules\Transactions\Processors\CreatePurchaseOrderTransactionProcessor; use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; @@ -30,7 +30,7 @@ class CreatePurchaseOrderFor1688OrderProcessor /** @var UpdatesTransactionStatus */ private $updatesTransactionStatus; - /** @var CreateInvoiceTransactionProcessor */ + /** @var CreateInvoiceTransactionV2Processor */ private $createInvoiceTransactionProcessor; /** @@ -38,9 +38,9 @@ class CreatePurchaseOrderFor1688OrderProcessor * @param CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor * @param Convert1688PurchaseOrderToProductList $convert1688PurchaseOrderToProductList * @param UpdatesTransactionStatus $updatesTransactionStatus - * @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor + * @param CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor */ - public function __construct(GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor, Convert1688PurchaseOrderToProductList $convert1688PurchaseOrderToProductList, UpdatesTransactionStatus $updatesTransactionStatus, CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor) + public function __construct(GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor, Convert1688PurchaseOrderToProductList $convert1688PurchaseOrderToProductList, UpdatesTransactionStatus $updatesTransactionStatus, CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor) { $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; $this->createPurchaseOrderTransactionProcessor = $createPurchaseOrderTransactionProcessor; diff --git a/app/Classes/Modules/Documents/ControllersLogic/DeleteDocumentLogic.php b/app/Classes/Modules/Documents/ControllersLogic/DeleteDocumentLogic.php index 06419d87..264458b7 100644 --- a/app/Classes/Modules/Documents/ControllersLogic/DeleteDocumentLogic.php +++ b/app/Classes/Modules/Documents/ControllersLogic/DeleteDocumentLogic.php @@ -14,9 +14,6 @@ use App\Classes\Modules\Documents\Services\DeletesDocument; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; - - class DeleteDocumentLogic extends AbstractControllerLogic { @@ -62,9 +59,9 @@ class DeleteDocumentLogic extends AbstractControllerLogic $document = $this->fetchesDocument->execute(['id' => $request->route('id')]); $this->canDeleteDocument->passes(); - + $this->deletesDocument->execute($document); return $this->response([]); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/UpdatePaymentTransactionStatusLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/UpdatePaymentTransactionStatusLogic.php index 11f0a377..2e1a0317 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/UpdatePaymentTransactionStatusLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/UpdatePaymentTransactionStatusLogic.php @@ -14,9 +14,6 @@ use App\Models\Document; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; - - class UpdatePaymentTransactionStatusLogic extends AbstractControllerLogic { @@ -73,4 +70,4 @@ class UpdatePaymentTransactionStatusLogic extends AbstractControllerLogic return $this->response([]); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php index afacb35f..9fb5636a 100644 --- a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php @@ -25,6 +25,10 @@ use Carbon\Carbon; use Exception; use Illuminate\Support\Facades\Log; +/** + * @deprecated This class is deprecated and should not be used. + * Use `CreateInvoiceTransactionV2Processor` instead + */ class CreateInvoiceTransactionProcessor { From 8cfc7ff04801c116177c75309ada7c0f11d5e503 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sat, 13 Sep 2025 12:59:49 +0800 Subject: [PATCH 06/11] E-Invoice - Cleanup Retest --- .../ControllersLogic/ApprovePurchaseOrderLogic.php | 10 +++++----- .../CreatePaymentProofDocumentLogic.php | 11 +++++------ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php index f7d1d775..7422d6ca 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php @@ -8,7 +8,7 @@ use App\Classes\Modules\Bookings\Services\FetchesBooking; use App\Classes\Modules\Documents\Services\ApprovesDocument; use App\Classes\Modules\Documents\Services\FetchesDocument; use App\Classes\Modules\Documents\Services\RejectsDocument; -use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; +use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionV2Processor; use App\Classes\Modules\Transactions\Services\FetchesTransaction; use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; use App\Classes\ValueObjects\Constants\ApprovalStatus; @@ -35,16 +35,16 @@ class ApprovePurchaseOrderLogic extends AbstractControllerLogic /** @var UpdatesTransactionStatus */ private $updatesTransactionStatus; - /** @var CreateInvoiceTransactionProcessor */ + /** @var CreateInvoiceTransactionV2Processor */ private $createInvoiceTransactionProcessor; /** * ApprovePurchaseOrderLogic constructor. * @param FetchesBooking $fetchesBooking * @param UpdatesTransactionStatus $updatesTransactionStatus - * @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor + * @param CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor */ - public function __construct(FetchesBooking $fetchesBooking, UpdatesTransactionStatus $updatesTransactionStatus, CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor) + public function __construct(FetchesBooking $fetchesBooking, UpdatesTransactionStatus $updatesTransactionStatus, CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor) { $this->fetchesBooking = $fetchesBooking; $this->updatesTransactionStatus = $updatesTransactionStatus; @@ -72,4 +72,4 @@ class ApprovePurchaseOrderLogic extends AbstractControllerLogic return $this->response([]); } -} \ No newline at end of file +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentProofDocumentLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentProofDocumentLogic.php index 46534d77..fdaf5e75 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentProofDocumentLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentProofDocumentLogic.php @@ -11,6 +11,7 @@ use App\Classes\Modules\Documents\Services\CreatesDocument; use App\Classes\Modules\Documents\Services\CreatesFiles; use App\Classes\Modules\Transactions\Services\FetchesTransaction; use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus; +use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionV2Processor; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\CompanyType; use App\Classes\ValueObjects\Constants\DocumentType; @@ -20,8 +21,6 @@ use App\Models\Document; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; - class CreatePaymentProofDocumentLogic extends AbstractControllerLogic { @@ -48,7 +47,7 @@ class CreatePaymentProofDocumentLogic extends AbstractControllerLogic /** @var UpdatesTransactionStatus */ private $updatesTransactionStatus; - /** @var CreateInvoiceTransactionProcessor */ + /** @var CreateInvoiceTransactionV2Processor */ private $createInvoiceTransactionProcessor; /** @var SendUserPaymentProofUploadedEmail */ @@ -60,9 +59,9 @@ class CreatePaymentProofDocumentLogic extends AbstractControllerLogic * @param CreatesDocument $createsDocument * @param CreatesFiles $createsFile * @param UpdatesTransactionStatus $updatesTransactionStatus - * @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor + * @param CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor */ - public function __construct(FetchesTransaction $fetchesTransaction, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesTransactionStatus $updatesTransactionStatus, CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor, SendUserPaymentProofUploadedEmail $sendUserPaymentProofUploadedEmail) + public function __construct(FetchesTransaction $fetchesTransaction, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesTransactionStatus $updatesTransactionStatus, CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor, SendUserPaymentProofUploadedEmail $sendUserPaymentProofUploadedEmail) { $this->fetchesTransaction = $fetchesTransaction; $this->createsDocument = $createsDocument; @@ -105,4 +104,4 @@ class CreatePaymentProofDocumentLogic extends AbstractControllerLogic return $this->response([]); } -} \ No newline at end of file +} From 931a8ebd44c19ef826a1a6161648ffe5a7f29931 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sat, 13 Sep 2025 13:16:43 +0800 Subject: [PATCH 07/11] E-Invoice - Cleanup --- .../Processors/RegenerateInvoiceBookingProcessor.php | 6 +++--- database/seeds/DummyDataSeeder.php | 12 ++++++++---- routes/web.php | 12 ++++++------ 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/app/Classes/Modules/Bookings/Processors/RegenerateInvoiceBookingProcessor.php b/app/Classes/Modules/Bookings/Processors/RegenerateInvoiceBookingProcessor.php index f1495d82..8459525d 100644 --- a/app/Classes/Modules/Bookings/Processors/RegenerateInvoiceBookingProcessor.php +++ b/app/Classes/Modules/Bookings/Processors/RegenerateInvoiceBookingProcessor.php @@ -6,7 +6,7 @@ namespace App\Classes\Modules\Bookings\Processors; use App\Classes\Modules\Bookings\Services\UpdatesBookingStatus; use App\Classes\Modules\Transactions\Services\DeletesTransaction; use App\Classes\Modules\Documents\Services\DeletesDocument; -use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; +use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; //deprecated use Illuminate\Support\Str; use App\Classes\ValueObjects\Constants\DocumentType; use App\Classes\ValueObjects\Constants\ApprovalStatus; @@ -31,7 +31,7 @@ class RegenerateInvoiceBookingProcessor /** @var DeletesDocument */ private $deletesDocument; - /** @var CreateInvoiceTransactionProcessor */ + /** @var CreateInvoiceTransactionProcessor */ //deprecated private $createInvoiceTransactionProcessor; /** @@ -39,7 +39,7 @@ class RegenerateInvoiceBookingProcessor * @param DeletesTransaction $deletesTransaction * @param UpdatesBookingStatus $updatesBookingStatus * @param DeletesDocument $deletesDocument - * @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor + * @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor //deprecated */ public function __construct( DeletesTransaction $deletesTransaction, diff --git a/database/seeds/DummyDataSeeder.php b/database/seeds/DummyDataSeeder.php index 76378265..a752ee6f 100644 --- a/database/seeds/DummyDataSeeder.php +++ b/database/seeds/DummyDataSeeder.php @@ -31,7 +31,7 @@ use App\Classes\Modules\Documents\Services\CreatesDocument; use App\Classes\Modules\Documents\Services\CreatesFiles; use App\Classes\Modules\Documents\Services\RejectsDocument; use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject; -use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor; +use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionV2Processor; use App\Classes\Modules\Transactions\Processors\CreatePurchaseOrderTransactionProcessor; use App\Classes\Modules\Transactions\Processors\CreateSupplierTransactionProcessor; use App\Classes\Modules\Transactions\Services\CreatesTransaction; @@ -56,6 +56,7 @@ use App\Models\ServiceType; use App\Models\Transaction; use App\Models\User; use App\Models\Wallet; +use App\Models\Booking; use Carbon\Carbon; use Illuminate\Database\Seeder; @@ -129,7 +130,7 @@ class DummyDataSeeder extends Seeder /** @var CreatePurchaseOrderTransactionProcessor */ public $createPurchaseOrderTransactionProcessor; - /** @var CreateInvoiceTransactionProcessor */ + /** @var CreateInvoiceTransactionV2Processor */ public $createInvoiceTransactionProcessor; /** @var CreateSupplierTransactionProcessor */ @@ -163,12 +164,12 @@ class DummyDataSeeder extends Seeder * @param ApprovesDocument $approvesDocument * @param RejectsDocument $rejectsDocument * @param CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor - * @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor + * @param CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor * @param CreateSupplierTransactionProcessor $createSupplierTransactionProcessor * @param AssignSegmentProcessor $assignSegmentProcessor * @param SetsBankToDefault $setsBankToDefault */ - public function __construct(Faker $faker, CreatesUser $createsUser, CreatesCompany $createsCompany, CreatesContact $createsContact, CreatesAddress $createsAddress, AssignEmployeeProcessor $assignEmployeeProcessor, CreatesDocument $createsDocument, CreatesFiles $createsFiles, GeneratesWalletCode $generatesWalletCode, CreatesWallet $createsWallet, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdatesWalletBalance $updatesWalletBalance, CreatesBank $createsBank, GeneratesBookingMarking $generatesBookingMarking, CreatesBooking $createsBooking, FetchesBookingQuotation $fetchBookingQuotation, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor, CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor, CreateSupplierTransactionProcessor $createSupplierTransactionProcessor, AssignSegmentProcessor $assignSegmentProcessor, SetsBankToDefault $setsBankToDefault) + public function __construct(Faker $faker, CreatesUser $createsUser, CreatesCompany $createsCompany, CreatesContact $createsContact, CreatesAddress $createsAddress, AssignEmployeeProcessor $assignEmployeeProcessor, CreatesDocument $createsDocument, CreatesFiles $createsFiles, GeneratesWalletCode $generatesWalletCode, CreatesWallet $createsWallet, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdatesWalletBalance $updatesWalletBalance, CreatesBank $createsBank, GeneratesBookingMarking $generatesBookingMarking, CreatesBooking $createsBooking, FetchesBookingQuotation $fetchBookingQuotation, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor, CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor, CreateSupplierTransactionProcessor $createSupplierTransactionProcessor, AssignSegmentProcessor $assignSegmentProcessor, SetsBankToDefault $setsBankToDefault) { $this->faker = $faker; $this->createsUser = $createsUser; @@ -521,11 +522,14 @@ class DummyDataSeeder extends Seeder $configurations->getTax(), $configurations->getServiceCharge(), Carbon::now()->addMinutes(10), ApprovalStatus::PENDING_SUBMISSION, [], null); /** @var Transaction $transaction */ + /** @var Booking $booking */ $transaction = $this->createsTransaction->execute($booking, $object); if($shouldSubmit || $shouldApprove) { $object = new DocumentObject( DocumentType::CUSTOMER_PAYMENT_PROOF, ['data:image/png;base64,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'], '', ApprovalStatus::PENDING_VERIFICATION, 'payments'); + + /** @var Transaction $transaction */ /** @var Document $document */ $document = $this->createsDocument->execute($transaction, $object); $this->createsFiles->execute($document, $object); diff --git a/routes/web.php b/routes/web.php index b5cb1767..0f707244 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,8 +1,6 @@ forceDelete(); } - (App()->make(CreateInvoiceTransactionProcessor::class))->execute($booking, $bill_no); + (App()->make(CreateInvoiceTransactionV2Processor::class))->execute($booking, $bill_no); dump('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $bill_no . '. Old bill_no - ' . $deletedInvoice->bill_no); LogHelper::channel('regenerateInvoice')->info('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $bill_no . '. Old bill_no - ' . $deletedInvoice->bill_no); } else { - (App()->make(CreateInvoiceTransactionProcessor::class))->execute($booking); + (App()->make(CreateInvoiceTransactionV2Processor::class))->execute($booking); dump('regenerated new invoice. Booking Marking - ' . $booking->marking); LogHelper::channel('regenerateInvoice')->info('regenerated new invoice. Booking Marking - ' . $booking->marking); } @@ -1083,7 +1083,7 @@ Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, $booking->transactions()->whereIn('transactions.type', [TransactionType::INVOICE, TransactionType::SUPPLIER_DELIVER])->delete(); $booking->documents()->whereIn('document_type', [DocumentType::INVOICE, DocumentType::PURCHASE_ORDER, DocumentType::DELIVER_ORDER, DocumentType::SUPPLIER_DELIVER_ORDER])->delete(); - (App()->make(CreateInvoiceTransactionProcessor::class))->execute($booking, $firstBillNo); + (App()->make(CreateInvoiceTransactionV2Processor::class))->execute($booking, $firstBillNo); dump('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $firstBillNo . '. Old bill_no - ' . $currentInvoice->bill_no); LogHelper::channel('regenerateInvoice')->info('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $firstBillNo . '. Old bill_no - ' . $currentInvoice->bill_no); } @@ -1378,4 +1378,4 @@ Route::get('/preview-unfinished-payment-orders', function (Request $request) { // web route to run the logic Route::get('/run-batch-unfinished-payment-orders', function (Request $request) { return (new UnfinishedPaymentOrders())->execute($request); -}); \ No newline at end of file +}); From d5c92315cd990e0c44857bda755cc5d489893836 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sat, 13 Sep 2025 13:29:59 +0800 Subject: [PATCH 08/11] E-Invoice - Code Refactor --- .../ControllersLogic/RegenerateInvoiceBookingLogic.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/Classes/Modules/Bookings/ControllersLogic/RegenerateInvoiceBookingLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/RegenerateInvoiceBookingLogic.php index 486912a5..2c06836f 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/RegenerateInvoiceBookingLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/RegenerateInvoiceBookingLogic.php @@ -2,6 +2,7 @@ namespace App\Classes\Modules\Bookings\ControllersLogic; +use App\Classes\Exceptions\MalformedRequestException; use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Bookings\Services\FetchesBooking; use App\Classes\Modules\Bookings\Standards\Rules\CanFetchBooking; @@ -73,7 +74,7 @@ class RegenerateInvoiceBookingLogic extends AbstractControllerLogic $booking = $this->fetchesBooking->execute( [ 'id' => $request->route('id'), - // 'status' => ApprovalStatus::COMPLETED, //cief todo: 90 - must have completed to avoid generate invoice inaccurately + // 'status' => ApprovalStatus::COMPLETED, 'with_transactions' => true ] ); @@ -81,6 +82,12 @@ class RegenerateInvoiceBookingLogic extends AbstractControllerLogic $eInvoiceWithNormalInvoiceTemplate = $request->input('normal_invoice', false); $eInvoiceRefund = $request->input('e_invoice_refund', false); + if(!$eInvoiceRefund){ + if($booking->status !== ApprovalStatus::COMPLETED){ + throw new MalformedRequestException('Booking incomplete.'); + } + } + // if($eInvoiceRefund){ $this->regenerateInvoiceBookingV2Processor->execute($booking, $eInvoiceWithNormalInvoiceTemplate, $eInvoiceRefund); // } From 981ebfb4a3fa5c6d12c54da99f4bce14e0059542 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sat, 13 Sep 2025 13:40:24 +0800 Subject: [PATCH 09/11] E-Invoice - Added Comment --- .../Processors/CreateInvoiceTransactionV2Processor.php | 2 +- app/Http/Kernel.php | 2 +- resources/assets/vue/general/mixins/request.js | 2 +- routes/api.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionV2Processor.php b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionV2Processor.php index c5f3f410..f261ac11 100644 --- a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionV2Processor.php +++ b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionV2Processor.php @@ -100,7 +100,7 @@ class CreateInvoiceTransactionV2Processor $bookingOriginalStatus = $options['bookingOriginalStatus'] ?? ApprovalStatus::COMPLETED; if($generateEInvoiceRefund){ - $generateEInvoice = true; //cief todo: 90 - cannot have 2 flags doing the same thing + $generateEInvoice = true; //With or without refund, these 2 flags are meant to Generate E-Invoice, so cannot have opposite indicator } if ($booking->status === ApprovalStatus::COMPLETED && !$generateEInvoiceRefund) { diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 2d50694d..95479398 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -80,6 +80,6 @@ class Kernel extends HttpKernel 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'valid.token' => ValidateToken::class, 'token.check' => \App\Http\Middleware\TokenCheckerMiddleware::class, - 'admin' => \App\Http\Middleware\EnsureUserIsAdmin::class, //cief todo: 90 - maintenance + 'admin' => \App\Http\Middleware\EnsureUserIsAdmin::class, //cief maintenance ]; } diff --git a/resources/assets/vue/general/mixins/request.js b/resources/assets/vue/general/mixins/request.js index b4dc85a4..d1f96316 100644 --- a/resources/assets/vue/general/mixins/request.js +++ b/resources/assets/vue/general/mixins/request.js @@ -13,7 +13,7 @@ export default { let statusCode = response.status, success = response.ok; - // console.log('statusCode: ' + statusCode); //cief todo: 90 - maintenance + // console.log('statusCode: ' + statusCode); //cief maintenance if(statusCode == 503){ window.location.href = '/maintenance'; } diff --git a/routes/api.php b/routes/api.php index 4d097f7c..4f996e10 100644 --- a/routes/api.php +++ b/routes/api.php @@ -26,7 +26,7 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function Route::post('online_payment/callback', 'Billplz\CallbackBillplzController@callback')->name('online_payment.callback'); Route::group(['middleware' => 'valid.token'], function () { - Route::group(['middleware' => 'admin'], function () { //cief todo: 90 - maintenance + Route::group(['middleware' => 'admin'], function () { //cief maintenance Route::get('/storage/{fileName}/fetch', 'Documents\RenderDocumentController@fileStorageServe')->where(['fileName' => '.*'])->name('storage.document.file'); Route::post('/import/update-debtor/f614e339d7058904a831aad742e24d55', 'Imports\ImportUpdateDebtorController@import')->name('debtor.import'); From 4d36f69b3e934aa6c999502b5c4ae9f757dd8937 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Mon, 29 Sep 2025 19:33:20 +0800 Subject: [PATCH 10/11] E-Invoice - Enhancement to allow EInvoice to be generated for cases with refund --- .../views/pages/pdfs/purchase_order_table.blade.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/resources/views/pages/pdfs/purchase_order_table.blade.php b/resources/views/pages/pdfs/purchase_order_table.blade.php index ce85538b..5afe3643 100644 --- a/resources/views/pages/pdfs/purchase_order_table.blade.php +++ b/resources/views/pages/pdfs/purchase_order_table.blade.php @@ -89,6 +89,17 @@ @endforeach + @else + @if ($paymentSumRefund) + + + + CANCEL FULL ORDER + + + + + @endif @endif From 844697c885a994d36db701839a04137a501cbcee Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Thu, 2 Oct 2025 09:36:43 +0800 Subject: [PATCH 11/11] E-Invoice - Enhancement to allow EInvoice to be generated for cases with refund --- .../pages/pdfs/purchase_order_table.blade.php | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/resources/views/pages/pdfs/purchase_order_table.blade.php b/resources/views/pages/pdfs/purchase_order_table.blade.php index 5afe3643..58d2ed7e 100644 --- a/resources/views/pages/pdfs/purchase_order_table.blade.php +++ b/resources/views/pages/pdfs/purchase_order_table.blade.php @@ -105,6 +105,22 @@ @php $subtotalWithDiscount = bcsub($subtotal, $voucherDiscount, 5); + if (!$totalPayment) { + $serviceCharge = $transaction->service_charge; + } + else { + $serviceCharge = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->where('status', ApprovalStatus::COMPLETED) + ->get() + ->sum(function ($transaction) { + return $transaction->service_charge; + }); + } + if ($paymentSumRefund && $displayedSubtotal === 0){ + $subtotal = bcsub($paymentSumRefund, $serviceCharge, 5); + $displayedSubtotal = bcsub($paymentSumRefund, $serviceCharge, 2); + } @endphp @@ -114,20 +130,6 @@ Service Charges - service_charge; - } - else { - $serviceCharge = $booking->transactions() - ->where('type', TransactionType::PAYMENT) - ->where('status', ApprovalStatus::COMPLETED) - ->get() - ->sum(function ($transaction) { - return $transaction->service_charge; - }); - } - ?> {{ number_format($serviceCharge, 2) }} @if($totalPayment && $refundedServiceCharge)