diff --git a/app/Http/Controllers/ExpenseController.php b/app/Http/Controllers/ExpenseController.php index 5b88ab9ea3ff..626399415b25 100644 --- a/app/Http/Controllers/ExpenseController.php +++ b/app/Http/Controllers/ExpenseController.php @@ -49,7 +49,7 @@ class ExpenseController extends BaseController protected $entity_transformer = ExpenseTransformer::class; /** - * @var Expenseepository + * @var ExpensRepository */ protected $expense_repo; diff --git a/app/Jobs/Bank/MatchBankTransactions.php b/app/Jobs/Bank/MatchBankTransactions.php index 42a03df4925c..1a18fc72db18 100644 --- a/app/Jobs/Bank/MatchBankTransactions.php +++ b/app/Jobs/Bank/MatchBankTransactions.php @@ -104,8 +104,6 @@ class MatchBankTransactions implements ShouldQueue } foreach ($this->input as $input) { - nlog($input); - if (array_key_exists('invoice_ids', $input) && strlen($input['invoice_ids']) >= 1) { $this->matchInvoicePayment($input); } elseif (array_key_exists('payment_id', $input) && strlen($input['payment_id']) >= 1) { @@ -164,7 +162,7 @@ class MatchBankTransactions implements ShouldQueue $expense->transaction_id = $this->bt->id; $expense->save(); - $this->bt->expense_id = $expense->id; + $this->bt->expense_id = $this->coalesceExpenses($expense->hashed_id); $this->bt->status_id = BankTransaction::STATUS_CONVERTED; $this->bt->vendor_id = $expense->vendor_id; $this->bt->ninja_category_id = $expense->category_id; @@ -176,6 +174,15 @@ class MatchBankTransactions implements ShouldQueue return $this; } + private function coalesceExpenses($expense): string + { + + if(!$this->bt->expense_id || strlen($this->bt->expense_id) < 1) + return $expense; + + return collect(explode(",", $this->bt->expense_id))->push($expense)->implode(","); + } + private function linkPayment($input) { $this->bt = BankTransaction::find($input['id']); @@ -209,7 +216,10 @@ class MatchBankTransactions implements ShouldQueue return $this; } - $_invoices = Invoice::withTrashed()->find($this->getInvoices($input['invoice_ids'])); + $_invoices = Invoice::query() + ->withTrashed() + ->where('company_id', $this->bt->company_id) + ->where('id',$this->getInvoices($input['invoice_ids'])); $amount = $this->bt->amount; @@ -249,7 +259,7 @@ class MatchBankTransactions implements ShouldQueue $expense->should_be_invoiced = $this->company->mark_expenses_invoiceable; $expense->save(); - $this->bt->expense_id = $expense->id; + $this->bt->expense_id = $expense->hashed_id; if (array_key_exists('vendor_id', $input)) { $this->bt->vendor_id = $input['vendor_id']; diff --git a/app/Jobs/Company/CompanyImport.php b/app/Jobs/Company/CompanyImport.php index 3c5ca9d8707d..52049d9dc29c 100644 --- a/app/Jobs/Company/CompanyImport.php +++ b/app/Jobs/Company/CompanyImport.php @@ -1566,6 +1566,11 @@ class CompanyImport implements ShouldQueue return $this->encodePrimaryKey($encodeable); })->implode(","); + $obj_array['expense_id'] = collect(explode(",", $obj_array['expense_id']))->map(function ($id) { + return $this->transformId('expenses', $id); + })->map(function ($encodeable) { + return $this->encodePrimaryKey($encodeable); + })->implode(","); $new_obj->fill($obj_array); $new_obj->save(['timestamps' => false]); diff --git a/app/Jobs/Cron/UpdateCalculatedFields.php b/app/Jobs/Cron/UpdateCalculatedFields.php index 7b7664e92615..ba2ab9717c57 100644 --- a/app/Jobs/Cron/UpdateCalculatedFields.php +++ b/app/Jobs/Cron/UpdateCalculatedFields.php @@ -82,11 +82,10 @@ class UpdateCalculatedFields $duration += $end_time - $start_time; } - - return round(($duration/60/60), 0); - + }); + return round(($duration/60/60), 0); } } diff --git a/app/Models/BankTransaction.php b/app/Models/BankTransaction.php index b38ca5f52f46..cd74bd400f81 100644 --- a/app/Models/BankTransaction.php +++ b/app/Models/BankTransaction.php @@ -133,6 +133,23 @@ class BankTransaction extends BaseModel return $collection; } + public function getExpenseIds() + { + $collection = collect(); + + $expenses = explode(",", $this->expense_id); + + if (count($expenses) >= 1) { + foreach ($expenses as $expense) { + if (is_string($expense) && strlen($expense) > 1) { + $collection->push($this->decodePrimaryKey($expense)); + } + } + } + + return $collection; + } + public function getEntityType() { return self::class; diff --git a/app/Repositories/ExpenseRepository.php b/app/Repositories/ExpenseRepository.php index 3d7c2a08285c..b1eb36d05a5b 100644 --- a/app/Repositories/ExpenseRepository.php +++ b/app/Repositories/ExpenseRepository.php @@ -99,6 +99,20 @@ class ExpenseRepository extends BaseRepository return $expense; } + + public function delete($expense) :Expense + { + if ($expense->transaction_id) { + $expense->transaction_id = null; + $expense->saveQuietly(); + } + + parent::delete($expense); + + return $expense; + } + + /** * Handle race conditions when creating expense numbers * diff --git a/app/Services/Bank/ProcessBankRules.php b/app/Services/Bank/ProcessBankRules.php index 54277d5f693d..ef3791ee5b3d 100644 --- a/app/Services/Bank/ProcessBankRules.php +++ b/app/Services/Bank/ProcessBankRules.php @@ -123,7 +123,7 @@ class ProcessBankRules extends AbstractService $expense->should_be_invoiced = $this->bank_transaction->company->mark_expenses_invoiceable; $expense->save(); - $this->bank_transaction->expense_id = $expense->id; + $this->bank_transaction->expense_id = $expense->hashed_id; $this->bank_transaction->status_id = BankTransaction::STATUS_CONVERTED; $this->bank_transaction->save(); diff --git a/app/Transformers/BankTransactionTransformer.php b/app/Transformers/BankTransactionTransformer.php index 515ba5c4b7d6..60f7f867ca0f 100644 --- a/app/Transformers/BankTransactionTransformer.php +++ b/app/Transformers/BankTransactionTransformer.php @@ -41,7 +41,7 @@ class BankTransactionTransformer extends EntityTransformer ]; /** - * @param BankTransaction $bank_integration + * @param BankTransaction $bank_transaction * @return array */ public function transform(BankTransaction $bank_transaction) @@ -63,7 +63,7 @@ class BankTransactionTransformer extends EntityTransformer 'description' => (string) $bank_transaction->description ?: '', 'base_type' => (string) $bank_transaction->base_type ?: '', 'invoice_ids' => (string) $bank_transaction->invoice_ids ?: '', - 'expense_id'=> (string) $this->encodePrimaryKey($bank_transaction->expense_id) ?: '', + 'expense_id'=> (string) $bank_transaction->expense_id ?: '', 'payment_id'=> (string) $this->encodePrimaryKey($bank_transaction->payment_id) ?: '', 'vendor_id'=> (string) $this->encodePrimaryKey($bank_transaction->vendor_id) ?: '', 'bank_transaction_rule_id' => (string) $this->encodePrimaryKey($bank_transaction->bank_transaction_rule_id) ?: '', diff --git a/database/migrations/2023_03_24_054758_add_client_is_exempt_from_taxes.php b/database/migrations/2023_03_24_054758_add_client_is_exempt_from_taxes.php index 2dfb7e51114c..b67416549b8a 100644 --- a/database/migrations/2023_03_24_054758_add_client_is_exempt_from_taxes.php +++ b/database/migrations/2023_03_24_054758_add_client_is_exempt_from_taxes.php @@ -1,14 +1,17 @@ unsignedInteger('current_hours')->nullable(); }); + Schema::table('bank_transactions', function(Illuminate\Database\Schema\Blueprint $table) { + $table->text('expense_id')->default('')->change(); + }); + + BankTransaction::withTrashed() + ->whereNotNull('expense_id') + ->cursor() + ->each(function ($transaction) { + $transaction->expense_id = $this->encodePrimaryKey($transaction->expense_id); + $transaction->save(); + }); Company::query() ->cursor() diff --git a/tests/Feature/Bank/BankTransactionTest.php b/tests/Feature/Bank/BankTransactionTest.php index a2c6157b28b2..96cce05ae155 100644 --- a/tests/Feature/Bank/BankTransactionTest.php +++ b/tests/Feature/Bank/BankTransactionTest.php @@ -112,7 +112,7 @@ class BankTransactionTest extends TestCase $response->assertStatus(200); $this->assertEquals($this->expense->refresh()->transaction_id, $bt->id); - $this->assertEquals($bt->refresh()->expense_id, $this->expense->id); + $this->assertEquals($this->expense->hashed_id, $bt->refresh()->expense_id); $this->assertEquals($this->vendor->id, $bt->vendor_id); $this->assertEquals(BankTransaction::STATUS_CONVERTED, $bt->status_id); } diff --git a/tests/Feature/ExpenseApiTest.php b/tests/Feature/ExpenseApiTest.php index 23877f7c0d99..a23a3c32086c 100644 --- a/tests/Feature/ExpenseApiTest.php +++ b/tests/Feature/ExpenseApiTest.php @@ -11,12 +11,13 @@ namespace Tests\Feature; +use Tests\TestCase; +use App\Models\Expense; +use Tests\MockAccountData; use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; -use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\Session; -use Tests\MockAccountData; -use Tests\TestCase; +use Illuminate\Foundation\Testing\DatabaseTransactions; /** * @test @@ -41,6 +42,22 @@ class ExpenseApiTest extends TestCase Model::reguard(); } + public function testTransactionIdClearedOnDelete() + { + $e = Expense::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'transaction_id' => '123', + ]); + + $this->assertNotNull($e->transaction_id); + + $expense_repo = app('App\Repositories\ExpenseRepository'); + $e = $expense_repo->delete($e); + + $this->assertNull($e->transaction_id); + } + public function testExpenseGetClientStatus() { $response = $this->withHeaders([