From 2e8823340ea5cbe730e304eacb6696fb5b51bbb8 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 6 Sep 2023 13:49:11 +0800 Subject: [PATCH 01/14] revert fix invoice bugs --- resources/views/pages/pdfs/invoice.blade.php | 26 ++++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/resources/views/pages/pdfs/invoice.blade.php b/resources/views/pages/pdfs/invoice.blade.php index 40706ce0..db6c42c5 100644 --- a/resources/views/pages/pdfs/invoice.blade.php +++ b/resources/views/pages/pdfs/invoice.blade.php @@ -73,22 +73,17 @@ @php $subtotal = "0"; - $voucherDiscount = $voucher_redemption ? bcmul((string)$voucher_redemption->value, "-1", 5) : "0"; - $displayedSubtotal = "0"; - $exactTotal = "0"; + $voucherDiscount = $voucher_redemption ? bcmul((string)$voucher_redemption->value, "-1", 2) : "0"; + $displayedSubtotal = 0; @endphp @foreach ($po_order_transaction->transactionDetails as $key => $transaction_detail) @php - $exactUnitPrice = bcdiv($transaction_detail->price, $transaction->currency_rate, 5); + $exactUnitPrice = bcdiv($transaction_detail->price, $transaction->currency_rate, 7); $itemTotal = bcmul($exactUnitPrice, $transaction_detail->quantity, 5); - - // Round half to even for displayed item total - $displayedItemTotal = round(bcmul($exactUnitPrice, $transaction_detail->quantity, 2), 2, PHP_ROUND_HALF_EVEN); - + $displayedItemTotal = bcmul($exactUnitPrice, $transaction_detail->quantity, 2); $displayedSubtotal = bcadd($displayedSubtotal, $displayedItemTotal, 2); $subtotal = bcadd($subtotal, $itemTotal, 5); - $exactTotal = bcadd($exactTotal, $displayedItemTotal, 5); @endphp {{ $key + 1 }} @@ -135,17 +130,10 @@ @endif @php - // Calculate the totals with 5 decimal places + $displayedTotal = bcadd(bcadd(bcadd($subtotal, $transaction->service_charge, 5), $transaction->tax, 5), $voucherDiscount, 5); $expectedTotal = bcadd(bcadd(bcadd($subtotal, $transaction->service_charge, 5), $transaction->tax, 5), $voucherDiscount, 5); - - // Calculate the displayed totals with 2 decimal places - $displayedTotal = bcadd(bcadd(bcadd($displayedSubtotal, $transaction->service_charge, 2), $transaction->tax, 2), $voucherDiscount, 2); - - // Calculate the discrepancy - $discrepancy = bcsub($expectedTotal, $displayedTotal, 5); - - // Calculate the final total - $total = bcadd($expectedTotal, $discrepancy, 5); + $discrepancy = bcsub($displayedTotal, $expectedTotal, 5); + $total = bcadd(bcadd(bcadd($subtotal, $transaction->service_charge, 5), $transaction->tax, 5), $voucherDiscount, 5); @endphp From d3f9f21170e472531a3603d10c2567b3f6fb3919 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 6 Sep 2023 15:34:39 +0800 Subject: [PATCH 02/14] regenerate bulk invoice --- ...voiceTransactionProcessorWithInvoiceNo.php | 210 ++++++++++++++++++ routes/web.php | 30 ++- 2 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessorWithInvoiceNo.php diff --git a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessorWithInvoiceNo.php b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessorWithInvoiceNo.php new file mode 100644 index 00000000..27dfbe59 --- /dev/null +++ b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessorWithInvoiceNo.php @@ -0,0 +1,210 @@ +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 + * @return void + * @throws MalformedRequestException + */ + public function execute(Booking $booking, String $invoiceNo) + { + + if ($booking->status === ApprovalStatus::COMPLETED) { + return; + } + + $payable_amount = $this->calculatesBookingPayableAmount->execute($booking, $booking->fix_currency_id); + $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; + } + + $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) { + return; + } + + // $transaction = $booking->transactions() + // ->where('type', TransactionType::PAYMENT) + // ->first(); + + $transaction = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->latest()->get()[0]; + + // $billNumber = $this->generatesTransactionBillNumber->execute('INV-'); + $billNumber = $invoiceNo; + + $booking_currency_average_rate = $this->calculatesBookingCurrencyAverageRate->execute($booking, TransactionType::PAYMENT); + + $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, $transaction_object); + + $voucherRedemption = $transaction->voucherRedemption; + + $supplier = $this->fetchesCompany->execute(['id' => $transaction->receiver]); + + // purchase order + $this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::PURCHASE_ORDER, $voucherRedemption); + + // deliver order + $this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::DELIVER_ORDER, $voucherRedemption); + + // invoice + $this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::INVOICE, $voucherRedemption); + + $billNumber = $this->generatesTransactionBillNumber->execute('SPDO-'); + + $booking_currency_average_rate = $this->calculatesBookingCurrencyAverageRate->execute($booking, TransactionType::BILL); + + $transaction = $booking->transactions()->payments()->where('status', ApprovalStatus::COMPLETED)->first() + ->transactions()->where('type', TransactionType::BILL)->first(); + + $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); + + $this->updatesBookingStatus->execute($booking, ApprovalStatus::COMPLETED); + + // update perfex crm + // if(config('perfexcrm.is_enabled') == 'true'){ + // CreatePerfexCRMInvoice::dispatch($invoice_transaction, $purchaseOrder, $supplier); + // } + } +} diff --git a/routes/web.php b/routes/web.php index 7980b80a..b1188854 100644 --- a/routes/web.php +++ b/routes/web.php @@ -26,6 +26,7 @@ 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\Documents\Services\DeletesDocument; +use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessorWithInvoiceNo; use App\Classes\Modules\Transactions\Services\DeletesTransaction; /* @@ -487,7 +488,10 @@ Route::get('/payments/manual', function(){ Route::get('/invoice/fix', function(){ set_time_limit(14400); - $bookings = Booking::where('status', ApprovalStatus::COMPLETED)->whereDate('updated_at', '>=', Carbon::parse('01-01-2023'))->get(); + $bookings = Booking::where('status', ApprovalStatus::COMPLETED) + ->whereDate('updated_at', '>=', Carbon::parse('01-01-2023')) + ->take(10) // to test on development + ->get(); foreach($bookings as $booking){ $booking->transactions()->whereIn('transactions.type', [TransactionType::INVOICE, TransactionType::SUPPLIER_DELIVER])->delete(); @@ -495,7 +499,29 @@ Route::get('/invoice/fix', function(){ $booking->status = ApprovalStatus::APPROVED; $booking->save(); - (App()->make(CreateInvoiceTransactionProcessor::class))->execute($booking); + $deletedInvoice = $booking->transactions() + ->whereIn('type', [TransactionType::INVOICE]) + ->onlyTrashed() + ->orderBy('created_at', 'asc') + ->first(); + + if ($deletedInvoice) { + $bill_no = $deletedInvoice->bill_no; + + // check if bill_no ends with '-deleted' + if (str_ends_with($bill_no, '-deleted')) { + $bill_no = str_replace('-deleted', '', $bill_no); + } + + $deletedInvoice->bill_no = $bill_no . '-deleted'; + (App()->make(CreateInvoiceTransactionProcessorWithInvoiceNo::class))->execute($booking, $bill_no); + $deletedInvoice->save(); + dump('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $bill_no . '. Old bill_no - ' . $deletedInvoice->bill_no); + } else { + (App()->make(CreateInvoiceTransactionProcessor::class))->execute($booking); + dump('regenerated new invoice. Booking Marking - ' . $booking->marking); + } + } })->name('invoice.fix'); From f36fa358fe67430f4b6e1f5fb8197dbe9c9a29e4 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 6 Sep 2023 15:45:52 +0800 Subject: [PATCH 03/14] add log for regenerate invoice invoice --- config/logging.php | 5 ++++ routes/web.php | 64 ++++++++++++++++++++++++++-------------------- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/config/logging.php b/config/logging.php index 088c204e..fb872693 100644 --- a/config/logging.php +++ b/config/logging.php @@ -99,6 +99,11 @@ return [ 'emergency' => [ 'path' => storage_path('logs/laravel.log'), ], + 'regenerateInvoice' => [ + 'driver' => 'single', + 'path' => storage_path('logs/regenerateInvoice.log'), + 'level' => 'info', + ], ], ]; diff --git a/routes/web.php b/routes/web.php index b1188854..0c2cc915 100644 --- a/routes/web.php +++ b/routes/web.php @@ -28,6 +28,7 @@ use App\Classes\Modules\Bookings\Processors\CreatePurchaseOrderFor1688OrderProce use App\Classes\Modules\Documents\Services\DeletesDocument; use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessorWithInvoiceNo; use App\Classes\Modules\Transactions\Services\DeletesTransaction; +use Illuminate\Support\Facades\Log; /* |-------------------------------------------------------------------------- @@ -488,41 +489,48 @@ Route::get('/payments/manual', function(){ Route::get('/invoice/fix', function(){ set_time_limit(14400); - $bookings = Booking::where('status', ApprovalStatus::COMPLETED) + $processed_invoice = 1; + + Booking::where('status', ApprovalStatus::COMPLETED) ->whereDate('updated_at', '>=', Carbon::parse('01-01-2023')) - ->take(10) // to test on development - ->get(); + ->orderBy('id') + ->chunk(100, function ($bookings) use ($processed_invoice){ + foreach ($bookings as $booking) { - foreach($bookings as $booking){ - $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(); - $booking->status = ApprovalStatus::APPROVED; - $booking->save(); + Log::channel('regenerateInvoice')->info('Counter ' . $processed_invoice); + $processed_invoice += 1; - $deletedInvoice = $booking->transactions() - ->whereIn('type', [TransactionType::INVOICE]) - ->onlyTrashed() - ->orderBy('created_at', 'asc') - ->first(); + $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(); + $booking->status = ApprovalStatus::APPROVED; + $booking->save(); - if ($deletedInvoice) { - $bill_no = $deletedInvoice->bill_no; + $deletedInvoice = $booking->transactions() + ->whereIn('type', [TransactionType::INVOICE]) + ->onlyTrashed() + ->orderBy('created_at', 'asc') + ->first(); - // check if bill_no ends with '-deleted' - if (str_ends_with($bill_no, '-deleted')) { - $bill_no = str_replace('-deleted', '', $bill_no); + if ($deletedInvoice) { + $bill_no = $deletedInvoice->bill_no; + + // check if bill_no ends with '-deleted' + if (str_ends_with($bill_no, '-deleted')) { + $bill_no = str_replace('-deleted', '', $bill_no); + } + + $deletedInvoice->bill_no = $bill_no . '-deleted'; + $deletedInvoice->save(); + + (App()->make(CreateInvoiceTransactionProcessorWithInvoiceNo::class))->execute($booking, $bill_no); + dump('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $bill_no . '. Old bill_no - ' . $deletedInvoice->bill_no); + } else { + (App()->make(CreateInvoiceTransactionProcessor::class))->execute($booking); + dump('regenerated new invoice. Booking Marking - ' . $booking->marking); + } } - - $deletedInvoice->bill_no = $bill_no . '-deleted'; - (App()->make(CreateInvoiceTransactionProcessorWithInvoiceNo::class))->execute($booking, $bill_no); - $deletedInvoice->save(); - dump('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $bill_no . '. Old bill_no - ' . $deletedInvoice->bill_no); - } else { - (App()->make(CreateInvoiceTransactionProcessor::class))->execute($booking); - dump('regenerated new invoice. Booking Marking - ' . $booking->marking); } - - } + ); })->name('invoice.fix'); Route::get('/1688/fix/{reference}', function($reference){ From ec223133b6ab8e45af86d0ff3459c34f320b111e Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 6 Sep 2023 15:49:42 +0800 Subject: [PATCH 04/14] add log --- routes/web.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/routes/web.php b/routes/web.php index 0c2cc915..79f15462 100644 --- a/routes/web.php +++ b/routes/web.php @@ -524,9 +524,11 @@ Route::get('/invoice/fix', function(){ (App()->make(CreateInvoiceTransactionProcessorWithInvoiceNo::class))->execute($booking, $bill_no); dump('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $bill_no . '. Old bill_no - ' . $deletedInvoice->bill_no); + Log::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); dump('regenerated new invoice. Booking Marking - ' . $booking->marking); + Log::channel('regenerateInvoice')->info('regenerated new invoice. Booking Marking - ' . $booking->marking); } } } From 53489726e0a76f2a1d966bcbef6accd48620cedf Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 6 Sep 2023 16:05:06 +0800 Subject: [PATCH 05/14] fix regenerate invoice --- routes/web.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/routes/web.php b/routes/web.php index 79f15462..1d48167d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -484,8 +484,6 @@ Route::get('/payments/manual', function(){ echo ''; }); - - Route::get('/invoice/fix', function(){ set_time_limit(14400); @@ -522,6 +520,13 @@ Route::get('/invoice/fix', function(){ $deletedInvoice->bill_no = $bill_no . '-deleted'; $deletedInvoice->save(); + $existing_invoice_bill_no = Transaction::where('bill_no', $bill_no)->first(); + + if ($existing_invoice_bill_no) { + Log::channel('regenerateInvoice')->info('Delete existing bill_no: ' . json_encode($existing_invoice_bill_no)); + $existing_invoice_bill_no->forceDelete(); + } + (App()->make(CreateInvoiceTransactionProcessorWithInvoiceNo::class))->execute($booking, $bill_no); dump('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $bill_no . '. Old bill_no - ' . $deletedInvoice->bill_no); Log::channel('regenerateInvoice')->info('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $bill_no . '. Old bill_no - ' . $deletedInvoice->bill_no); From 6dac580add35e1e18612fba7630a10a6feef6700 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 6 Sep 2023 16:09:59 +0800 Subject: [PATCH 06/14] fix invoice --- routes/web.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/routes/web.php b/routes/web.php index 1d48167d..9d425a91 100644 --- a/routes/web.php +++ b/routes/web.php @@ -523,7 +523,8 @@ Route::get('/invoice/fix', function(){ $existing_invoice_bill_no = Transaction::where('bill_no', $bill_no)->first(); if ($existing_invoice_bill_no) { - Log::channel('regenerateInvoice')->info('Delete existing bill_no: ' . json_encode($existing_invoice_bill_no)); + Log::channel('regenerateInvoice')->info('Delete existing bill_no'); + Log::channel('regenerateInvoice')->info(json_encode($existing_invoice_bill_no)); $existing_invoice_bill_no->forceDelete(); } From c65780d4f1cec0d457538b1689bcd36952f29046 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 6 Sep 2023 17:56:07 +0800 Subject: [PATCH 07/14] fix invoice --- routes/web.php | 1 + 1 file changed, 1 insertion(+) diff --git a/routes/web.php b/routes/web.php index 9d425a91..bbd925ab 100644 --- a/routes/web.php +++ b/routes/web.php @@ -491,6 +491,7 @@ Route::get('/invoice/fix', function(){ Booking::where('status', ApprovalStatus::COMPLETED) ->whereDate('updated_at', '>=', Carbon::parse('01-01-2023')) + ->whereDate('created_at', '<', Carbon::parse('06-09-2023')) ->orderBy('id') ->chunk(100, function ($bookings) use ($processed_invoice){ foreach ($bookings as $booking) { From 3e54b636e0949901be7f3ed1a5902fbd340ebd4c Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 6 Sep 2023 18:08:49 +0800 Subject: [PATCH 08/14] fix invoice --- routes/web.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/routes/web.php b/routes/web.php index bbd925ab..25917dd3 100644 --- a/routes/web.php +++ b/routes/web.php @@ -491,7 +491,6 @@ Route::get('/invoice/fix', function(){ Booking::where('status', ApprovalStatus::COMPLETED) ->whereDate('updated_at', '>=', Carbon::parse('01-01-2023')) - ->whereDate('created_at', '<', Carbon::parse('06-09-2023')) ->orderBy('id') ->chunk(100, function ($bookings) use ($processed_invoice){ foreach ($bookings as $booking) { @@ -499,6 +498,13 @@ Route::get('/invoice/fix', function(){ Log::channel('regenerateInvoice')->info('Counter ' . $processed_invoice); $processed_invoice += 1; + if ($booking->transactions()->where('transactions.type', TransactionType::INVOICE) + ->first() + ->created_at + ->greaterThanOrEqualTo(Carbon::parse('2023-09-06'))) { + continue; + } + $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(); $booking->status = ApprovalStatus::APPROVED; From 4b5724f6e3d37495dacf902801a2d2ea35016f67 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 6 Sep 2023 22:30:55 +0800 Subject: [PATCH 09/14] fix invoice --- app/Console/Commands/RegenerateInvoice.php | 129 +++++++++++++++++++++ routes/web.php | 64 ---------- 2 files changed, 129 insertions(+), 64 deletions(-) create mode 100644 app/Console/Commands/RegenerateInvoice.php diff --git a/app/Console/Commands/RegenerateInvoice.php b/app/Console/Commands/RegenerateInvoice.php new file mode 100644 index 00000000..a13ba29b --- /dev/null +++ b/app/Console/Commands/RegenerateInvoice.php @@ -0,0 +1,129 @@ +createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor; + $this->createInvoiceTransactionProcessorWithInvoiceNo = $createInvoiceTransactionProcessorWithInvoiceNo; + } + + /** + * Execute the console command. + * + * @return int + */ + public function handle() + { + // Allocate sufficient memory as needed + // ini_set('memory_limit', '256M'); + + $processed_invoice = 1; + + Booking::where('status', ApprovalStatus::COMPLETED) + ->whereDate('updated_at', '>=', Carbon::parse('2023-01-01')) + ->orderBy('id') + ->chunk(100, function ($bookings) use (&$processed_invoice) { + foreach ($bookings as $booking) { + $logMessage = 'Counter ' . $processed_invoice; + $this->printAndLog($logMessage); + $processed_invoice++; + + if ( + !$booking->transactions()->where('transactions.type', TransactionType::INVOICE)->exists() + || $booking->transactions()->where('transactions.type', TransactionType::INVOICE)->first()->created_at->greaterThanOrEqualTo(Carbon::parse('2023-09-06')) + ) { + continue; + } + + // Delete transactions and documents in one query + $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(); + + $booking->status = ApprovalStatus::APPROVED; + $booking->save(); + + $deletedInvoice = $booking->transactions() + ->whereIn('type', [TransactionType::INVOICE]) + ->onlyTrashed() + ->orderBy('created_at', 'asc') + ->first(); + + if ($deletedInvoice) { + $bill_no = $deletedInvoice->bill_no; + if (str_ends_with($bill_no, '-deleted')) { + $bill_no = str_replace('-deleted', '', $bill_no); + } + + $deletedInvoice->bill_no = $bill_no . '-deleted'; + $deletedInvoice->save(); + + $existing_invoice_bill_no = Transaction::where('bill_no', $bill_no)->first(); + + if ($existing_invoice_bill_no) { + $this->printAndLog('Delete existing bill_no'); + $this->printAndLog(json_encode($existing_invoice_bill_no)); + $existing_invoice_bill_no->forceDelete(); + } + + $invoiceProcessor = App()->make(CreateInvoiceTransactionProcessorWithInvoiceNo::class); + $invoiceProcessor->execute($booking, $bill_no); + $logMessage = 'Regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $bill_no . '. Old bill_no - ' . $deletedInvoice->bill_no; + $this->printAndLog($logMessage); + } else { + $invoiceProcessor = App()->make(CreateInvoiceTransactionProcessor::class); + $invoiceProcessor->execute($booking); + $logMessage = 'Regenerated new invoice. Booking Marking - ' . $booking->marking; + $this->printAndLog($logMessage); + } + } + }); + } + + public function printAndLog($string) + { + $this->info($string); + Log::channel('regenerateInvoice')->info($string); + } +} diff --git a/routes/web.php b/routes/web.php index 25917dd3..c81383a0 100644 --- a/routes/web.php +++ b/routes/web.php @@ -484,70 +484,6 @@ Route::get('/payments/manual', function(){ echo ''; }); -Route::get('/invoice/fix', function(){ - - set_time_limit(14400); - $processed_invoice = 1; - - Booking::where('status', ApprovalStatus::COMPLETED) - ->whereDate('updated_at', '>=', Carbon::parse('01-01-2023')) - ->orderBy('id') - ->chunk(100, function ($bookings) use ($processed_invoice){ - foreach ($bookings as $booking) { - - Log::channel('regenerateInvoice')->info('Counter ' . $processed_invoice); - $processed_invoice += 1; - - if ($booking->transactions()->where('transactions.type', TransactionType::INVOICE) - ->first() - ->created_at - ->greaterThanOrEqualTo(Carbon::parse('2023-09-06'))) { - continue; - } - - $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(); - $booking->status = ApprovalStatus::APPROVED; - $booking->save(); - - $deletedInvoice = $booking->transactions() - ->whereIn('type', [TransactionType::INVOICE]) - ->onlyTrashed() - ->orderBy('created_at', 'asc') - ->first(); - - if ($deletedInvoice) { - $bill_no = $deletedInvoice->bill_no; - - // check if bill_no ends with '-deleted' - if (str_ends_with($bill_no, '-deleted')) { - $bill_no = str_replace('-deleted', '', $bill_no); - } - - $deletedInvoice->bill_no = $bill_no . '-deleted'; - $deletedInvoice->save(); - - $existing_invoice_bill_no = Transaction::where('bill_no', $bill_no)->first(); - - if ($existing_invoice_bill_no) { - Log::channel('regenerateInvoice')->info('Delete existing bill_no'); - Log::channel('regenerateInvoice')->info(json_encode($existing_invoice_bill_no)); - $existing_invoice_bill_no->forceDelete(); - } - - (App()->make(CreateInvoiceTransactionProcessorWithInvoiceNo::class))->execute($booking, $bill_no); - dump('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $bill_no . '. Old bill_no - ' . $deletedInvoice->bill_no); - Log::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); - dump('regenerated new invoice. Booking Marking - ' . $booking->marking); - Log::channel('regenerateInvoice')->info('regenerated new invoice. Booking Marking - ' . $booking->marking); - } - } - } - ); -})->name('invoice.fix'); - Route::get('/1688/fix/{reference}', function($reference){ $booking = Booking::where('marking', $reference)->first(); From 6755a5e30f70734521afda8b00e96b00c37eb6b7 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Wed, 6 Sep 2023 22:33:52 +0800 Subject: [PATCH 10/14] cron to regenerate invoice --- app/Console/Commands/RegenerateInvoice.php | 2 +- app/Console/Kernel.php | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/Console/Commands/RegenerateInvoice.php b/app/Console/Commands/RegenerateInvoice.php index a13ba29b..cf4a1751 100644 --- a/app/Console/Commands/RegenerateInvoice.php +++ b/app/Console/Commands/RegenerateInvoice.php @@ -123,7 +123,7 @@ class RegenerateInvoice extends Command public function printAndLog($string) { - $this->info($string); + // $this->info($string); Log::channel('regenerateInvoice')->info($string); } } diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index e549a23a..cb9cf060 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -38,6 +38,11 @@ class Kernel extends ConsoleKernel ->dailyAt('01:00') ->appendOutputTo(storage_path().'/logs/soft-delete-seasonal-segmant-company.log') ->withoutOverlapping(); + + $schedule->command('regenerateInvoice') + ->everyMinute() + ->appendOutputTo(storage_path().'/logs/regenerateInvoice.log') + ->withoutOverlapping(); } /** From 2e7b994deabbfaaf0a1ab76dcbc8537679cac01c Mon Sep 17 00:00:00 2001 From: edmondlang Date: Thu, 7 Sep 2023 00:19:39 +0800 Subject: [PATCH 11/14] test regenerate invoice --- routes/web.php | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/routes/web.php b/routes/web.php index c81383a0..25917dd3 100644 --- a/routes/web.php +++ b/routes/web.php @@ -484,6 +484,70 @@ Route::get('/payments/manual', function(){ echo ''; }); +Route::get('/invoice/fix', function(){ + + set_time_limit(14400); + $processed_invoice = 1; + + Booking::where('status', ApprovalStatus::COMPLETED) + ->whereDate('updated_at', '>=', Carbon::parse('01-01-2023')) + ->orderBy('id') + ->chunk(100, function ($bookings) use ($processed_invoice){ + foreach ($bookings as $booking) { + + Log::channel('regenerateInvoice')->info('Counter ' . $processed_invoice); + $processed_invoice += 1; + + if ($booking->transactions()->where('transactions.type', TransactionType::INVOICE) + ->first() + ->created_at + ->greaterThanOrEqualTo(Carbon::parse('2023-09-06'))) { + continue; + } + + $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(); + $booking->status = ApprovalStatus::APPROVED; + $booking->save(); + + $deletedInvoice = $booking->transactions() + ->whereIn('type', [TransactionType::INVOICE]) + ->onlyTrashed() + ->orderBy('created_at', 'asc') + ->first(); + + if ($deletedInvoice) { + $bill_no = $deletedInvoice->bill_no; + + // check if bill_no ends with '-deleted' + if (str_ends_with($bill_no, '-deleted')) { + $bill_no = str_replace('-deleted', '', $bill_no); + } + + $deletedInvoice->bill_no = $bill_no . '-deleted'; + $deletedInvoice->save(); + + $existing_invoice_bill_no = Transaction::where('bill_no', $bill_no)->first(); + + if ($existing_invoice_bill_no) { + Log::channel('regenerateInvoice')->info('Delete existing bill_no'); + Log::channel('regenerateInvoice')->info(json_encode($existing_invoice_bill_no)); + $existing_invoice_bill_no->forceDelete(); + } + + (App()->make(CreateInvoiceTransactionProcessorWithInvoiceNo::class))->execute($booking, $bill_no); + dump('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $bill_no . '. Old bill_no - ' . $deletedInvoice->bill_no); + Log::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); + dump('regenerated new invoice. Booking Marking - ' . $booking->marking); + Log::channel('regenerateInvoice')->info('regenerated new invoice. Booking Marking - ' . $booking->marking); + } + } + } + ); +})->name('invoice.fix'); + Route::get('/1688/fix/{reference}', function($reference){ $booking = Booking::where('marking', $reference)->first(); From d0d901d7abe859fb08d036eeccbfd2034cd64685 Mon Sep 17 00:00:00 2001 From: edmondlang Date: Thu, 7 Sep 2023 00:26:09 +0800 Subject: [PATCH 12/14] fix regenerate invoice --- routes/web.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/routes/web.php b/routes/web.php index 25917dd3..c49648e1 100644 --- a/routes/web.php +++ b/routes/web.php @@ -492,16 +492,17 @@ Route::get('/invoice/fix', function(){ Booking::where('status', ApprovalStatus::COMPLETED) ->whereDate('updated_at', '>=', Carbon::parse('01-01-2023')) ->orderBy('id') - ->chunk(100, function ($bookings) use ($processed_invoice){ + ->chunk(100, function ($bookings) use (&$processed_invoice) { foreach ($bookings as $booking) { Log::channel('regenerateInvoice')->info('Counter ' . $processed_invoice); + dump('Counter ' . $processed_invoice); $processed_invoice += 1; if ($booking->transactions()->where('transactions.type', TransactionType::INVOICE) ->first() ->created_at - ->greaterThanOrEqualTo(Carbon::parse('2023-09-06'))) { + ->greaterThanOrEqualTo(Carbon::parse('2023-09-07'))) { continue; } From b854fd5bdc5a72165ddb682543dc3329a864b32f Mon Sep 17 00:00:00 2001 From: edmondlang Date: Thu, 7 Sep 2023 00:39:21 +0800 Subject: [PATCH 13/14] fix invoice --- routes/web.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/web.php b/routes/web.php index c49648e1..a9e51a50 100644 --- a/routes/web.php +++ b/routes/web.php @@ -528,7 +528,7 @@ Route::get('/invoice/fix', function(){ $deletedInvoice->bill_no = $bill_no . '-deleted'; $deletedInvoice->save(); - $existing_invoice_bill_no = Transaction::where('bill_no', $bill_no)->first(); + $existing_invoice_bill_no = Transaction::withTrashed()->where('bill_no', $bill_no)->first(); if ($existing_invoice_bill_no) { Log::channel('regenerateInvoice')->info('Delete existing bill_no'); From 88119b4f956aaa331cef1e0a66fdc8c99744a5c4 Mon Sep 17 00:00:00 2001 From: JiaSheng Date: Tue, 12 Sep 2023 19:55:14 +0800 Subject: [PATCH 14/14] solve duplicate statement transaction created upon import bank statement --- .../Accounting/ControllersLogic/ImportBankStatementLogic.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/Classes/Modules/Accounting/ControllersLogic/ImportBankStatementLogic.php b/app/Classes/Modules/Accounting/ControllersLogic/ImportBankStatementLogic.php index 0355c554..33d9df75 100644 --- a/app/Classes/Modules/Accounting/ControllersLogic/ImportBankStatementLogic.php +++ b/app/Classes/Modules/Accounting/ControllersLogic/ImportBankStatementLogic.php @@ -98,7 +98,7 @@ class ImportBankStatementLogic extends AbstractControllerLogic $tellerId = $row[19]; $branchChannel = $row[20]; $transactionCode = $row[21]; - $endBalance = $row[22]; + $endBalance = ((float) str_replace(',', '', $row[22])); $description2 = $row[25]; $description3 = $row[26]; $description4 = $row[27]; @@ -123,11 +123,10 @@ class ImportBankStatementLogic extends AbstractControllerLogic $existingTransaction = StatementTransaction::where('transaction_ref', $transactionRef) ->where('posting_date', $postingDate) ->where('amount', $amount) - ->where('transaction_description', $transactionDescription) ->where('teller_id', $tellerId) ->where('branch_channel', $branchChannel) ->where('transaction_code', $transactionCode) - ->where('end_balance', $endBalance) + ->whereRaw("CAST(REPLACE(end_balance,',','') AS DECIMAL(15,2)) = ?",[$endBalance]) ->first(); if (!$existingTransaction) {