diff --git a/app/Classes/Modules/Accounting/Processors/CreateBankStatementTransactionOwnersProcessor.php b/app/Classes/Modules/Accounting/Processors/CreateBankStatementTransactionOwnersProcessor.php index 90dd7048..a3c876d7 100644 --- a/app/Classes/Modules/Accounting/Processors/CreateBankStatementTransactionOwnersProcessor.php +++ b/app/Classes/Modules/Accounting/Processors/CreateBankStatementTransactionOwnersProcessor.php @@ -30,11 +30,12 @@ class CreateBankStatementTransactionOwnersProcessor // $transactions = StatementTransaction::whereDoesntHave('owners')->where('amount', '<', 0)->get(); foreach ($transactions as $transaction) { + $keywords = array_filter(explode(" ", $transaction->transaction_description . " " . $transaction->transaction_description_2)); if($transaction->amount > 0){ // Exchange Sales - $creditTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::PAYMENT, Booking::class, PaymentMethodType::WALLET, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + $creditTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::PAYMENT, Booking::class, PaymentMethodType::WALLET, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED], $keywords); foreach ($creditTransactions as $creditTransaction) { $transaction->owners()->firstOrCreate([ 'type' => StatementTransactionOwnerType::SALES, @@ -47,7 +48,7 @@ class CreateBankStatementTransactionOwnersProcessor // Shipping Portal Sales - $creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date), 2); + $creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date, 1), 2); foreach ($creditTransactions as $creditTransaction) { if($creditTransaction['owner_type'] === Wallet::class) continue; $transaction->owners()->firstOrCreate([ @@ -60,7 +61,7 @@ class CreateBankStatementTransactionOwnersProcessor } // Exchange Wallet Top Up - $creditTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::TOP_UP, Wallet::class, null, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + $creditTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::TOP_UP, Wallet::class, null, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED], $keywords); foreach ($creditTransactions as $creditTransaction) { $transaction->owners()->firstOrCreate([ 'type' => StatementTransactionOwnerType::WALLET_TOP_UP, @@ -71,7 +72,7 @@ class CreateBankStatementTransactionOwnersProcessor ]); } - $creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date), 5); + $creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date, 1), 5); foreach ($creditTransactions as $creditTransaction) { $transaction->owners()->firstOrCreate([ 'type' => StatementTransactionOwnerType::WALLET_TOP_UP, @@ -131,7 +132,7 @@ class CreateBankStatementTransactionOwnersProcessor } // Exchange Wallet Withdrawal - $debitTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::DEBIT_NOTE, Wallet::class, null, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + $debitTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::DEBIT_NOTE, Wallet::class, null, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED], $keywords); foreach ($debitTransactions as $debitTransaction) { $transaction->owners()->firstOrCreate([ 'type' => StatementTransactionOwnerType::WALLET_WITHDRAWAL, @@ -189,7 +190,8 @@ class CreateBankStatementTransactionOwnersProcessor } } - private function getTransactions($date, $amount, $type, $ownerType, $paymentMethod, $statuses, $model = Transaction::class) { + private function getTransactions($date, $amount, $type, $ownerType, $paymentMethod, $statuses, $keywords, $model = Transaction::class) { + $dateRange = $this->getDateRange($date, 4); $query = $model::whereIn('status', $statuses) ->where(function ($query) use ($ownerType, $paymentMethod, $type) { if ($ownerType) { @@ -204,9 +206,65 @@ class CreateBankStatementTransactionOwnersProcessor $query->where('type', $type); } }) - ->whereDate('created_at', $date->format('Y-m-d')) - ->where('amount', '>', ($amount - 0.01)) - ->where('amount', '<', ($amount + 0.01)); + ->whereDate('created_at', '>=', $dateRange['start_date']) + ->whereDate('created_at', '<=', $dateRange['end_date']) + ->where('amount', '>', ($amount - 0.05)) + ->where('amount', '<', ($amount + 0.05)); + + if ($query->count() > 1) { + $transactions = clone $query; + + $transactions->whereDate('created_at', $date->format('Y-m-d')); + + if ($transactions->count() === 1) { + return $transactions->get(); + } + + $transactions = clone $query; + + if ($ownerType === Booking::class) { + $transactions = $transactions->whereHasMorph('owner', [Booking::class], function ($q1) use ($keywords) { + return $q1->whereHas('company', function ($company) use ($keywords) { + return $company->where(function ($q2) use ($keywords) { + foreach($keywords as $keyword) { + $q2->orWhere('name', 'LIKE', '%'.$keyword.'%'); + } + $q2->orWhereHas('contacts', function ($contact) use($keywords) { + return $contact->where(function ($q3) use($keywords) { + foreach($keywords as $keyword) { + $q3->orWhere('reference', 'LIKE', '%'.$keyword.'%'); + } + }); + }); + }); + }); + }); + } + + + if ($ownerType === Wallet::class) { + $transactions = $transactions->whereHasMorph('owner', [Wallet::class], function ($q1) use ($keywords) { + return $q1->whereHasMorph('owner', [Company::class], function ($company) use($keywords) { + return $company->where(function ($q2) use ($keywords) { + foreach($keywords as $keyword) { + $q2->orWhere('name', 'LIKE', '%'.$keyword.'%'); + } + $q2->orWhereHas('contacts', function ($contact) use($keywords) { + return $contact->where(function ($q3) use($keywords) { + foreach($keywords as $keyword) { + $q3->orWhere('reference', 'LIKE', '%'.$keyword.'%'); + } + }); + }); + }); + }); + }); + } + + if ($transactions->count() === 1) { + return $transactions->get(); + } + } return $query->get(); } @@ -237,15 +295,15 @@ class CreateBankStatementTransactionOwnersProcessor } } - private function getDateRange(string $dateStr) { + private function getDateRange(string $dateStr, int $range) { // Create a DateTime object from the input string $date = strtotime($dateStr); // Get the first day of the month - $today = date('Y-m-d', strtotime('-1 day', $date)); + $today = date('Y-m-d', strtotime('-' . $range . ' day', $date)); // Get the first day of the next month - $nextDay = date('Y-m-d', strtotime('+1 day', $date)); + $nextDay = date('Y-m-d', strtotime('+' . $range . ' day', $date)); return [ 'start_date' => $today, diff --git a/app/Classes/Modules/Transactions/Services/GeneratesTransactionBillNumber.php b/app/Classes/Modules/Transactions/Services/GeneratesTransactionBillNumber.php index 4505707e..943da696 100644 --- a/app/Classes/Modules/Transactions/Services/GeneratesTransactionBillNumber.php +++ b/app/Classes/Modules/Transactions/Services/GeneratesTransactionBillNumber.php @@ -3,6 +3,7 @@ namespace App\Classes\Modules\Transactions\Services; +use App\Classes\Exceptions\InternalServerErrorException; use Carbon\Carbon; class GeneratesTransactionBillNumber @@ -27,14 +28,21 @@ class GeneratesTransactionBillNumber * @return string */ public function execute(string $prefix, ?Carbon $date = null): string { - if(!$date){ - $date = carbon::now(); + if (!$date) { + $date = Carbon::now(); } - $billNumber = $prefix.$date->format('Y').$date->format('m').'-'.mt_rand(10000, 99999); - - return !$this->checksIfTransactionBillNumberExists->execute($billNumber) ? $billNumber : self::execute($prefix); + $attempt = 0; + while ($attempt < 10) { // Retry up to 10 times + $billNumber = $prefix . $date->format('Y') . $date->format('m') . '-' . microtime(true); + if (!$this->checksIfTransactionBillNumberExists->execute($billNumber)) { + return $billNumber; + } + $attempt++; + } + throw new InternalServerErrorException("Unable to generate unique bill number after {$attempt} attempts."); } -} \ No newline at end of file + +} diff --git a/app/Console/Commands/DeleteOrderCommand.php b/app/Console/Commands/DeleteOrderCommand.php index 849a0106..9bcefe47 100644 --- a/app/Console/Commands/DeleteOrderCommand.php +++ b/app/Console/Commands/DeleteOrderCommand.php @@ -41,8 +41,8 @@ class DeleteOrderCommand extends Command */ public function handle() { - // $bookings_reference = $this->argument('bookings_reference'); - $bookings_reference = '28546,38599,44487,71086,70133,58580,42831,96028,41188,33894,95877,86732,31894,50962,44215,92894,40968,30303,89762,74693,45271,27169'; + $bookings_reference = $this->argument('bookings_reference'); + // $bookings_reference = '28546,38599,44487,71086,70133,58580,42831,96028,41188,33894,95877,86732,31894,50962,44215,92894,40968,30303,89762,74693,45271,27169'; $bookings_reference = explode(',', $bookings_reference); $start = new Carbon(); diff --git a/app/Http/Resources/BankResource.php b/app/Http/Resources/BankResource.php index 35fec923..f3de3038 100644 --- a/app/Http/Resources/BankResource.php +++ b/app/Http/Resources/BankResource.php @@ -21,6 +21,7 @@ class BankResource extends JsonResource 'reference' => $this->reference, 'bank_name' => $this->bank_name, 'bank_branch' => $this->bank_branch, + 'swift' => $this->swift, 'holder_name' => $this->holder_name, 'account_no' => $this->account_no, 'country_id' => $this->country_id, diff --git a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue index cd71d214..f03e4366 100644 --- a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue +++ b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationComponent.vue @@ -76,7 +76,7 @@