diff --git a/app/Http/Controllers/BankIntegrationController.php b/app/Http/Controllers/BankIntegrationController.php index 9a1cd189f737..0df2848f0b19 100644 --- a/app/Http/Controllers/BankIntegrationController.php +++ b/app/Http/Controllers/BankIntegrationController.php @@ -31,7 +31,7 @@ use Illuminate\Http\Request; class BankIntegrationController extends BaseController { use MakesHash; - + protected $entity_type = BankIntegration::class; protected $entity_transformer = BankIntegrationTransformer::class; @@ -421,23 +421,23 @@ class BankIntegrationController extends BaseController } -/** + /** * Perform bulk actions on the list view. * * @return Collection * * @OA\Post( - * path="/api/v1/invoices/bulk", - * operationId="bulkInvoices", - * tags={"invoices"}, - * summary="Performs bulk actions on an array of invoices", + * path="/api/v1/bank_integrations/bulk", + * operationId="bulkBankIntegrations", + * tags={"bank_integrations"}, + * summary="Performs bulk actions on an array of bank_integrations", * description="", * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), * @OA\Parameter(ref="#/components/parameters/index"), * @OA\RequestBody( - * description="User credentials", + * description="Action paramters", * required=true, * @OA\MediaType( * mediaType="application/json", @@ -495,7 +495,7 @@ class BankIntegrationController extends BaseController /** - * Return the remote list of accounts stored on the third part provider. + * Return the remote list of accounts stored on the third party provider. * * @return Response * diff --git a/app/Http/Controllers/BankTransactionController.php b/app/Http/Controllers/BankTransactionController.php index 8f7e744e7208..6409837dc0d1 100644 --- a/app/Http/Controllers/BankTransactionController.php +++ b/app/Http/Controllers/BankTransactionController.php @@ -24,12 +24,14 @@ use App\Models\BankTransaction; use App\Repositories\BankTransactionRepository; use App\Services\Bank\BankService; use App\Transformers\BankTransactionTransformer; +use App\Utils\Traits\MakesHash; use Illuminate\Http\Request; class BankTransactionController extends BaseController { - + use MakesHash; + protected $entity_type = BankTransaction::class; protected $entity_transformer = BankTransactionTransformer::class; @@ -418,6 +420,80 @@ class BankTransactionController extends BaseController return $this->itemResponse($bank_transaction->fresh()); } + +/** + * Perform bulk actions on the list view. + * + * @return Collection + * + * @OA\Post( + * path="/api/v1/bank_integrations/bulk", + * operationId="bulkBankIntegrations", + * tags={"bank_integrations"}, + * summary="Performs bulk actions on an array of bank_integrations", + * description="", + * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), + * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/index"), + * @OA\RequestBody( + * description="Action paramters", + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * type="array", + * @OA\Items( + * type="integer", + * description="Array of hashed IDs to be bulk 'actioned", + * example="[0,1,2,3]", + * ), + * ) + * ) + * ), + * @OA\Response( + * response=200, + * description="The Bulk Action response", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + */ + public function bulk() + { + $action = request()->input('action'); + + if(!in_array($action, ['archive', 'restore', 'delete'])) + return response()->json(['message' => 'Unsupported action.'], 400); + + $ids = request()->input('ids'); + + $bank_transactions = BankTransaction::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get(); + + $bank_transactions->each(function ($bank_transaction, $key) use ($action) { + if (auth()->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()); + } + + public function getTransactions(AdminBankTransactionRequest $request) { diff --git a/app/Http/Requests/BankTransaction/AdminBankTransactionRequest.php b/app/Http/Requests/BankTransaction/AdminBankTransactionRequest.php new file mode 100644 index 000000000000..4522a8f34f2f --- /dev/null +++ b/app/Http/Requests/BankTransaction/AdminBankTransactionRequest.php @@ -0,0 +1,28 @@ +user()->isAdmin(); + } +} diff --git a/app/Http/Requests/BankTransaction/CreateBankTransactionRequest.php b/app/Http/Requests/BankTransaction/CreateBankTransactionRequest.php new file mode 100644 index 000000000000..21844aaca774 --- /dev/null +++ b/app/Http/Requests/BankTransaction/CreateBankTransactionRequest.php @@ -0,0 +1,28 @@ +user()->can('create', BankTransaction::class); + } +} diff --git a/app/Http/Requests/BankTransaction/DestroyBankTransactionRequest.php b/app/Http/Requests/BankTransaction/DestroyBankTransactionRequest.php new file mode 100644 index 000000000000..87f31514d2dd --- /dev/null +++ b/app/Http/Requests/BankTransaction/DestroyBankTransactionRequest.php @@ -0,0 +1,27 @@ +user()->can('edit', $this->bank_integration); + } +} diff --git a/app/Http/Requests/BankTransaction/EditBankTransactionRequest.php b/app/Http/Requests/BankTransaction/EditBankTransactionRequest.php new file mode 100644 index 000000000000..d40195a7e44a --- /dev/null +++ b/app/Http/Requests/BankTransaction/EditBankTransactionRequest.php @@ -0,0 +1,27 @@ +user()->can('edit', $this->bank_integration); + } +} diff --git a/app/Http/Requests/BankTransaction/ShowBankTransactionRequest.php b/app/Http/Requests/BankTransaction/ShowBankTransactionRequest.php new file mode 100644 index 000000000000..68cc4fdbb9e6 --- /dev/null +++ b/app/Http/Requests/BankTransaction/ShowBankTransactionRequest.php @@ -0,0 +1,27 @@ +user()->can('view', $this->bank_integration); + } +} diff --git a/app/Http/Requests/BankTransaction/StoreBankTransactionRequest.php b/app/Http/Requests/BankTransaction/StoreBankTransactionRequest.php new file mode 100644 index 000000000000..94af89011395 --- /dev/null +++ b/app/Http/Requests/BankTransaction/StoreBankTransactionRequest.php @@ -0,0 +1,52 @@ +user()->can('create', BankTransaction::class); + } + + public function rules() + { + + $rules = []; + + return $rules; + } + + public function prepareForValidation() + { + $input = $this->all(); + + $this->replace($input); + } + + public function messages() + { + return []; + } + +} diff --git a/app/Http/Requests/BankTransaction/UpdateBankTransactionRequest.php b/app/Http/Requests/BankTransaction/UpdateBankTransactionRequest.php new file mode 100644 index 000000000000..b18ecf224284 --- /dev/null +++ b/app/Http/Requests/BankTransaction/UpdateBankTransactionRequest.php @@ -0,0 +1,51 @@ +user()->can('edit', $this->bank_integration); + } + + public function rules() + { + /* Ensure we have a client name, and that all emails are unique*/ + $rules = []; + + return $rules; + } + + public function messages() + { + return [ ]; + } + + public function prepareForValidation() + { + $input = $this->all(); + + $this->replace($input); + } + +} diff --git a/app/Http/Requests/BankTransaction/UploadBankTransactionRequest.php b/app/Http/Requests/BankTransaction/UploadBankTransactionRequest.php new file mode 100644 index 000000000000..2a3760e2e0cf --- /dev/null +++ b/app/Http/Requests/BankTransaction/UploadBankTransactionRequest.php @@ -0,0 +1,38 @@ +user()->can('edit', $this->bank_integration); + } + + public function rules() + { + $rules = []; + + if ($this->input('documents')) { + $rules['documents'] = 'file|mimes:csv,png,ai,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx|max:2000000'; + } + + return $rules; + } +} diff --git a/routes/api.php b/routes/api.php index 80543e649816..4ed5327aa56d 100644 --- a/routes/api.php +++ b/routes/api.php @@ -15,6 +15,7 @@ use App\Http\Controllers\ActivityController; use App\Http\Controllers\Auth\ForgotPasswordController; use App\Http\Controllers\Auth\LoginController; use App\Http\Controllers\BankIntegrationController; +use App\Http\Controllers\BankTransactionController; use App\Http\Controllers\BaseController; use App\Http\Controllers\ChartController; use App\Http\Controllers\ClientController; @@ -112,6 +113,10 @@ Route::group(['middleware' => ['throttle:300,1', 'api_db', 'token_auth', 'locale Route::post('bank_integrations/remove_account/{acc_id}', [BankIntegrationController::class, 'removeAccount'])->name('bank_integrations.remove_account'); 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::post('bank_transactions/bulk', [BankTransactionController::class, 'bulk'])->name('bank_transactions.bulk'); + + Route::post('check_subdomain', [SubdomainController::class, 'index'])->name('check_subdomain'); Route::get('ping', [PingController::class, 'index'])->name('ping'); Route::get('health_check', [PingController::class, 'health'])->name('health_check'); diff --git a/tests/Feature/BankTransactionApiTest.php b/tests/Feature/BankTransactionApiTest.php new file mode 100644 index 000000000000..b5210c87bfdc --- /dev/null +++ b/tests/Feature/BankTransactionApiTest.php @@ -0,0 +1,102 @@ +makeTestData(); + + Session::start(); + + $this->faker = \Faker\Factory::create(); + + Model::reguard(); + } + + public function testBankTransactionGet() + { + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->get('/api/v1/bank_transactions/'.$this->encodePrimaryKey($this->bank_transaction->id)); + + $response->assertStatus(200); + } + + public function testBankTransactionArchived() + { + $data = [ + 'ids' => [$this->encodePrimaryKey($this->bank_transaction->id)], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/bank_transactions/bulk?action=archive', $data); + + $arr = $response->json(); + + $this->assertNotNull($arr['data'][0]['archived_at']); + } + + public function testBankTransactionRestored() + { + $data = [ + 'ids' => [$this->encodePrimaryKey($this->bank_transaction->id)], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/bank_transactions/bulk?action=restore', $data); + + $arr = $response->json(); + + $this->assertEquals(0, $arr['data'][0]['archived_at']); + } + + public function testBankTransactionDeleted() + { + $data = [ + 'ids' => [$this->encodePrimaryKey($this->bank_transaction->id)], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/bank_transactions/bulk?action=delete', $data); + + $arr = $response->json(); + + $this->assertTrue($arr['data'][0]['is_deleted']); + } +}