From c17a65e7a0248ede87f38a98c8413e04ee1427b1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 21 Jan 2024 13:00:33 +1100 Subject: [PATCH 1/7] Allow filtering on multiple date ranges for invoices --- app/Filters/InvoiceFilters.php | 46 +++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/app/Filters/InvoiceFilters.php b/app/Filters/InvoiceFilters.php index 120c7ad7a2ed..0609864de918 100644 --- a/app/Filters/InvoiceFilters.php +++ b/app/Filters/InvoiceFilters.php @@ -247,24 +247,25 @@ class InvoiceFilters extends QueryFilters return $this->builder->where('due_date', '>=', $date); } + /** + * Filter by date range + * + * @param string $date_range + * @return Builder + */ public function date_range(string $date_range = ''): Builder { $parts = explode(",", $date_range); - if (count($parts) != 3) { + if (count($parts) != 2) { return $this->builder; } - - if(!in_array($parts[0], ['date','due_date'])) { - return $this->builder; - } - try { - $start_date = Carbon::parse($parts[1]); - $end_date = Carbon::parse($parts[2]); + $start_date = Carbon::parse($parts[0]); + $end_date = Carbon::parse($parts[1]); - return $this->builder->whereBetween($parts[0], [$start_date, $end_date]); + return $this->builder->whereBetween('date', [$start_date, $end_date]); } catch(\Exception $e) { return $this->builder; } @@ -272,6 +273,33 @@ class InvoiceFilters extends QueryFilters return $this->builder; } + /** + * Filter by due date range + * + * @param string $date_range + * @return Builder + */ + public function due_date_range(string $date_range = ''): Builder + { + $parts = explode(",", $date_range); + + if (count($parts) != 2) { + return $this->builder; + } + try { + + $start_date = Carbon::parse($parts[0]); + $end_date = Carbon::parse($parts[1]); + + return $this->builder->whereBetween('date', [$start_date, $end_date]); + } catch(\Exception $e) { + return $this->builder; + } + + return $this->builder; + } + + /** * Sorts the list based on $sort. * From 0c7c82bc871c41933657b3dc0cc1a913ff4d6d30 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 21 Jan 2024 13:15:44 +1100 Subject: [PATCH 2/7] Fixes for tests --- app/Filters/InvoiceFilters.php | 2 +- tests/Unit/InvoiceTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Filters/InvoiceFilters.php b/app/Filters/InvoiceFilters.php index 0609864de918..f7c11e369f54 100644 --- a/app/Filters/InvoiceFilters.php +++ b/app/Filters/InvoiceFilters.php @@ -291,7 +291,7 @@ class InvoiceFilters extends QueryFilters $start_date = Carbon::parse($parts[0]); $end_date = Carbon::parse($parts[1]); - return $this->builder->whereBetween('date', [$start_date, $end_date]); + return $this->builder->whereBetween('due_date', [$start_date, $end_date]); } catch(\Exception $e) { return $this->builder; } diff --git a/tests/Unit/InvoiceTest.php b/tests/Unit/InvoiceTest.php index d1dadb176db7..b87106079bb5 100644 --- a/tests/Unit/InvoiceTest.php +++ b/tests/Unit/InvoiceTest.php @@ -55,7 +55,7 @@ class InvoiceTest extends TestCase ->create([ 'company_id' => $this->company->id, 'user_id' => $this->user->id, - 'client_id' => $this->user->id + 'client_id' => $this->client->id ]); $this->assertNull($i->partial_due_date); @@ -64,7 +64,7 @@ class InvoiceTest extends TestCase ->create([ 'company_id' => $this->company->id, 'user_id' => $this->user->id, - 'client_id' => $this->user->id, + 'client_id' => $this->client->id, 'partial_due_date' => '2023-10-10', ]); From 1f77856829c00586f9833f7f6eff23efcf202fb0 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 21 Jan 2024 13:47:25 +1100 Subject: [PATCH 3/7] Fixes for bank transactions --- app/Http/Controllers/BankTransactionController.php | 12 +++++++----- .../BankTransaction/BulkBankTransactionRequest.php | 5 +---- .../CreateBankTransactionRequest.php | 5 ++++- app/Policies/EntityPolicy.php | 2 -- routes/api.php | 2 +- tests/Feature/BankTransactionApiTest.php | 14 ++++++++++++++ 6 files changed, 27 insertions(+), 13 deletions(-) diff --git a/app/Http/Controllers/BankTransactionController.php b/app/Http/Controllers/BankTransactionController.php index 6df1d828a717..7613bb9ce0ed 100644 --- a/app/Http/Controllers/BankTransactionController.php +++ b/app/Http/Controllers/BankTransactionController.php @@ -99,22 +99,24 @@ class BankTransactionController extends BaseController public function bulk(BulkBankTransactionRequest $request) { + /** @var \App\Models\User $user */ + $user = auth()->user(); + $action = $request->input('action'); $ids = request()->input('ids'); $bank_transactions = BankTransaction::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get(); - if ($action == 'convert_matched') { //catch this action + if ($action == 'convert_matched' && $user->can('edit', $bank_transactions->first())) { //catch this action $this->bank_transaction_repo->convert_matched($bank_transactions); } else { - $bank_transactions->each(function ($bank_transaction, $key) use ($action) { - $this->bank_transaction_repo->{$action}($bank_transaction); + $bank_transactions->each(function ($bank_transaction, $key) use ($action, $user) { + if($user->can('edit', $bank_transaction)) + $this->bank_transaction_repo->{$action}($bank_transaction); }); } - /* Need to understand which permission are required for the given bulk action ie. view / edit */ - return $this->listResponse(BankTransaction::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()); } diff --git a/app/Http/Requests/BankTransaction/BulkBankTransactionRequest.php b/app/Http/Requests/BankTransaction/BulkBankTransactionRequest.php index ae0dc087d2ef..47fadd22a7ff 100644 --- a/app/Http/Requests/BankTransaction/BulkBankTransactionRequest.php +++ b/app/Http/Requests/BankTransaction/BulkBankTransactionRequest.php @@ -22,10 +22,7 @@ class BulkBankTransactionRequest extends Request */ public function authorize(): bool { - /** @var \App\Models\User $user **/ - $user = auth()->user(); - - return $user->isAdmin(); + return true; } public function rules(): array diff --git a/app/Http/Requests/BankTransaction/CreateBankTransactionRequest.php b/app/Http/Requests/BankTransaction/CreateBankTransactionRequest.php index 00aeb899d19e..befd0db69ea5 100644 --- a/app/Http/Requests/BankTransaction/CreateBankTransactionRequest.php +++ b/app/Http/Requests/BankTransaction/CreateBankTransactionRequest.php @@ -23,6 +23,9 @@ class CreateBankTransactionRequest extends Request */ public function authorize(): bool { - return auth()->user()->can('create', BankTransaction::class); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + return $user->can('create', BankTransaction::class); } } diff --git a/app/Policies/EntityPolicy.php b/app/Policies/EntityPolicy.php index 7789726251ef..915031c24f85 100644 --- a/app/Policies/EntityPolicy.php +++ b/app/Policies/EntityPolicy.php @@ -31,8 +31,6 @@ class EntityPolicy */ public function before($user, $ability) { - //if($user->isAdmin()) - // return true; } /** diff --git a/routes/api.php b/routes/api.php index 7024c67d3131..8903843abe1f 100644 --- a/routes/api.php +++ b/routes/api.php @@ -139,7 +139,7 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale'] Route::post('bank_integrations/bulk', [BankIntegrationController::class, 'bulk'])->name('bank_integrations.bulk'); - Route::resource('bank_transactions', BankTransactionController::class); // name = (clients. index / create / show / update / destroy / edit + Route::resource('bank_transactions', BankTransactionController::class); // name = (bank_transactions. index / create / show / update / destroy / edit Route::post('bank_transactions/bulk', [BankTransactionController::class, 'bulk'])->name('bank_transactions.bulk'); Route::post('bank_transactions/match', [BankTransactionController::class, 'match'])->name('bank_transactions.match'); diff --git a/tests/Feature/BankTransactionApiTest.php b/tests/Feature/BankTransactionApiTest.php index a0a6868ac890..4ed2667684b9 100644 --- a/tests/Feature/BankTransactionApiTest.php +++ b/tests/Feature/BankTransactionApiTest.php @@ -31,6 +31,8 @@ class BankTransactionApiTest extends TestCase use DatabaseTransactions; use MockAccountData; + public $faker; + protected function setUp() :void { parent::setUp(); @@ -44,6 +46,18 @@ class BankTransactionApiTest extends TestCase Model::reguard(); } + public function testBankTransactionCreate() + { + nlog("creeeeate"); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->get('/api/v1/bank_transactions/create'); + + $response->assertStatus(200); + } + public function testBankTransactionGetClientStatus() { From 8880dd3f49587ba9cf894bf5ec2be8b1e56257e3 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 21 Jan 2024 14:21:12 +1100 Subject: [PATCH 4/7] Fixes for tests and partial_due_date output --- app/Export/CSV/ExpenseExport.php | 2 +- app/Export/CSV/InvoiceExport.php | 2 +- app/Models/Invoice.php | 4 ++-- app/Transformers/InvoiceTransformer.php | 2 +- tests/Feature/Export/ReportCsvGenerationTest.php | 2 ++ 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/Export/CSV/ExpenseExport.php b/app/Export/CSV/ExpenseExport.php index b139dd43b8af..afa55a7a36ff 100644 --- a/app/Export/CSV/ExpenseExport.php +++ b/app/Export/CSV/ExpenseExport.php @@ -78,7 +78,7 @@ class ExpenseExport extends BaseExport 'expense.net_amount' ]; - $this->input['report_keys'] = array_merge($this->input['report_keys'], $tax_keys); + $this->input['report_keys'] = array_unique(array_merge($this->input['report_keys'], $tax_keys)); $query = Expense::query() ->with('client') diff --git a/app/Export/CSV/InvoiceExport.php b/app/Export/CSV/InvoiceExport.php index 8db6664cd8c1..5ccb2daaaad1 100644 --- a/app/Export/CSV/InvoiceExport.php +++ b/app/Export/CSV/InvoiceExport.php @@ -167,7 +167,7 @@ class InvoiceExport extends BaseExport $entity['invoice.user_id'] = $invoice->user ? $invoice->user->present()->name() : ''; } - +nlog($entity); return $entity; } } diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 81acdcd0d711..df5d6241cbe0 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -80,7 +80,7 @@ use Laracasts\Presenter\PresentableTrait; * @property float $amount * @property float $balance * @property float|null $partial - * @property string|null $partial_due_date + * @property string|null|\Carbon\Carbon $partial_due_date * @property string|null $last_viewed * @property int|null $created_at * @property int|null $updated_at @@ -401,7 +401,7 @@ class Invoice extends BaseModel public function getStatusAttribute() { $due_date = $this->due_date ? Carbon::parse($this->due_date) : false; - $partial_due_date = $this->partial_due_Date ? Carbon::parse($this->partial_due_date) : false; + $partial_due_date = $this->partial_due_date ? Carbon::parse($this->partial_due_date) : false; if ($this->status_id == self::STATUS_SENT && $due_date && $due_date->gt(now())) { return self::STATUS_UNPAID; diff --git a/app/Transformers/InvoiceTransformer.php b/app/Transformers/InvoiceTransformer.php index c732fa945de1..7a50713c262f 100644 --- a/app/Transformers/InvoiceTransformer.php +++ b/app/Transformers/InvoiceTransformer.php @@ -132,7 +132,7 @@ class InvoiceTransformer extends EntityTransformer 'is_amount_discount' => (bool) ($invoice->is_amount_discount ?: false), 'footer' => $invoice->footer ?: '', 'partial' => (float) ($invoice->partial ?: 0.0), - 'partial_due_date' => ($invoice->partial_due_date && $invoice->partial_due_date != "-0001-11-30") ? $invoice->partial_due_date : '', + 'partial_due_date' => ($invoice->partial_due_date && $invoice->partial_due_date != "-0001-11-30") ? $invoice->partial_due_date->format('Y-m-d') : '', 'custom_value1' => (string) $invoice->custom_value1 ?: '', 'custom_value2' => (string) $invoice->custom_value2 ?: '', 'custom_value3' => (string) $invoice->custom_value3 ?: '', diff --git a/tests/Feature/Export/ReportCsvGenerationTest.php b/tests/Feature/Export/ReportCsvGenerationTest.php index 397e00c321de..8dfb638821a7 100644 --- a/tests/Feature/Export/ReportCsvGenerationTest.php +++ b/tests/Feature/Export/ReportCsvGenerationTest.php @@ -2207,6 +2207,8 @@ class ReportCsvGenerationTest extends TestCase $response = $this->poll($hash); $csv = $response->body(); + nlog($csv); + $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Expense Amount')); $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Expense Public Notes')); $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Expense Private Notes')); From 1dc09aab0b9d59574a97d5dbe30672adc453fed6 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 21 Jan 2024 14:35:09 +1100 Subject: [PATCH 5/7] Fixes for tests --- tests/Feature/InvoiceTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Feature/InvoiceTest.php b/tests/Feature/InvoiceTest.php index 57e8804a7416..d41a23600555 100644 --- a/tests/Feature/InvoiceTest.php +++ b/tests/Feature/InvoiceTest.php @@ -185,7 +185,7 @@ class InvoiceTest extends TestCase $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, - ])->get('/api/v1/invoices?date_range=date,1971-01-01,1971-01-03', ) + ])->get('/api/v1/invoices?date_range=1971-01-01,1971-01-03', ) ->assertStatus(200); $arr = $response->json(); From fc6c94d394563ad5a249b9c42b930659c0267170 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 21 Jan 2024 21:38:30 +1100 Subject: [PATCH 6/7] Fixes for tests --- tests/Feature/Export/ReportCsvGenerationTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/Feature/Export/ReportCsvGenerationTest.php b/tests/Feature/Export/ReportCsvGenerationTest.php index 8dfb638821a7..397e00c321de 100644 --- a/tests/Feature/Export/ReportCsvGenerationTest.php +++ b/tests/Feature/Export/ReportCsvGenerationTest.php @@ -2207,8 +2207,6 @@ class ReportCsvGenerationTest extends TestCase $response = $this->poll($hash); $csv = $response->body(); - nlog($csv); - $this->assertEquals('100', $this->getFirstValueByColumn($csv, 'Expense Amount')); $this->assertEquals('Public', $this->getFirstValueByColumn($csv, 'Expense Public Notes')); $this->assertEquals('Private', $this->getFirstValueByColumn($csv, 'Expense Private Notes')); From 990650e95bc5eb9441c29564c9cf9dd98aa4252f Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 21 Jan 2024 21:38:51 +1100 Subject: [PATCH 7/7] v5.8.14 --- VERSION.txt | 2 +- config/ninja.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index 55f6aea29818..932ec4d032a3 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.8.13 \ No newline at end of file +5.8.14 \ No newline at end of file diff --git a/config/ninja.php b/config/ninja.php index b8e0ad1c3380..78b6b97f6968 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -17,8 +17,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => env('APP_VERSION', '5.8.13'), - 'app_tag' => env('APP_TAG', '5.8.13'), + 'app_version' => env('APP_VERSION', '5.8.14'), + 'app_tag' => env('APP_TAG', '5.8.14'), 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', false),