diff --git a/app/Http/Controllers/ExpenseController.php b/app/Http/Controllers/ExpenseController.php index f7bc4e9cfd21..c70959f86e66 100644 --- a/app/Http/Controllers/ExpenseController.php +++ b/app/Http/Controllers/ExpenseController.php @@ -11,27 +11,28 @@ namespace App\Http\Controllers; -use App\Events\Expense\ExpenseWasCreated; -use App\Events\Expense\ExpenseWasUpdated; +use App\Utils\Ninja; +use App\Models\Account; +use App\Models\Expense; +use Illuminate\Http\Response; use App\Factory\ExpenseFactory; use App\Filters\ExpenseFilters; -use App\Http\Requests\Expense\CreateExpenseRequest; -use App\Http\Requests\Expense\DestroyExpenseRequest; +use App\Utils\Traits\MakesHash; +use App\Utils\Traits\Uploadable; +use App\Utils\Traits\BulkOptions; +use App\Utils\Traits\SavesDocuments; +use App\Repositories\ExpenseRepository; +use App\Transformers\ExpenseTransformer; +use App\Events\Expense\ExpenseWasCreated; +use App\Events\Expense\ExpenseWasUpdated; +use App\Http\Requests\Expense\BulkExpenseRequest; use App\Http\Requests\Expense\EditExpenseRequest; use App\Http\Requests\Expense\ShowExpenseRequest; use App\Http\Requests\Expense\StoreExpenseRequest; +use App\Http\Requests\Expense\CreateExpenseRequest; use App\Http\Requests\Expense\UpdateExpenseRequest; use App\Http\Requests\Expense\UploadExpenseRequest; -use App\Models\Account; -use App\Models\Expense; -use App\Repositories\ExpenseRepository; -use App\Transformers\ExpenseTransformer; -use App\Utils\Ninja; -use App\Utils\Traits\BulkOptions; -use App\Utils\Traits\MakesHash; -use App\Utils\Traits\SavesDocuments; -use App\Utils\Traits\Uploadable; -use Illuminate\Http\Response; +use App\Http\Requests\Expense\DestroyExpenseRequest; /** * Class ExpenseController. @@ -321,7 +322,10 @@ class ExpenseController extends BaseController */ public function create(CreateExpenseRequest $request) { - $expense = ExpenseFactory::create(auth()->user()->company()->id, auth()->user()->id); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + $expense = ExpenseFactory::create($user->company()->id, $user->id); return $this->itemResponse($expense); } @@ -366,9 +370,12 @@ class ExpenseController extends BaseController */ public function store(StoreExpenseRequest $request) { - $expense = $this->expense_repo->save($request->all(), ExpenseFactory::create(auth()->user()->company()->id, auth()->user()->id)); + /** @var \App\Models\User $user */ + $user = auth()->user(); - event(new ExpenseWasCreated($expense, $expense->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); + $expense = $this->expense_repo->save($request->all(), ExpenseFactory::create($user->company()->id, $user->id)); + + event(new ExpenseWasCreated($expense, $expense->company, Ninja::eventVars($user ? $user->id : null))); event('eloquent.created: App\Models\Expense', $expense); @@ -481,20 +488,25 @@ class ExpenseController extends BaseController * ), * ) */ - public function bulk() + public function bulk(BulkExpenseRequest $request) { - $action = request()->input('action'); + /** @var \App\Models\User $user */ + $user = auth()->user(); - $ids = request()->input('ids'); - $expenses = Expense::withTrashed()->find($this->transformKeys($ids)); + $expenses = Expense::withTrashed()->find($request->ids); - $expenses->each(function ($expense, $key) use ($action) { - if (auth()->user()->can('edit', $expense)) { - $this->expense_repo->{$action}($expense); + if($request->action == 'bulk_categorize' && $user->can('edit', $expenses->first())) { + $this->expense_repo->categorize($expenses, $request->category_id); + $expenses = collect([]); + } + + $expenses->each(function ($expense) use ($request, $user) { + if ($user->can('edit', $expense)) { + $this->expense_repo->{$request->action}($expense); } }); - return $this->listResponse(Expense::withTrashed()->whereIn('id', $this->transformKeys($ids))); + return $this->listResponse(Expense::withTrashed()->whereIn('id', $request->ids)); } /** diff --git a/app/Http/Requests/Expense/BulkExpenseRequest.php b/app/Http/Requests/Expense/BulkExpenseRequest.php index 2024ed39edde..e30ed90911bf 100644 --- a/app/Http/Requests/Expense/BulkExpenseRequest.php +++ b/app/Http/Requests/Expense/BulkExpenseRequest.php @@ -12,13 +12,10 @@ namespace App\Http\Requests\Expense; use App\Http\Requests\Request; -use App\Models\Expense; -use App\Utils\Traits\BulkOptions; +use Illuminate\Validation\Rule; class BulkExpenseRequest extends Request { - use BulkOptions; - /** * Determine if the user is authorized to make this request. * @@ -26,15 +23,7 @@ class BulkExpenseRequest extends Request */ public function authorize() { - if (! $this->has('action')) { - return false; - } - - if (! in_array($this->action, $this->getBulkOptions(), true)) { - return false; - } - - return auth()->user()->can(auth()->user()->isAdmin(), Expense::class); + return true; } /** @@ -44,13 +33,30 @@ class BulkExpenseRequest extends Request */ public function rules() { - $rules = $this->getGlobalRules(); + /** @var \App\Models\User $user */ + $user = auth()->user(); - /* We don't require IDs on bulk storing. */ - if ($this->action !== self::$STORE_METHOD) { - $rules['ids'] = ['required']; + return [ + 'ids' => ['required','bail','array', Rule::exists('expenses', 'id')->where('company_id', $user->company()->id)], + 'category_id' => ['sometimes', 'bail', Rule::exists('expense_categories', 'id')->where('company_id', $user->company()->id)], + 'action' => 'in:archive,restore,delete,bulk_categorize', + ]; + + + } + + public function prepareForValidation() + { + $input = $this->all(); + + if (isset($input['ids'])) { + $input['ids'] = $this->transformKeys($input['ids']); } - return $rules; + if (isset($input['category_id'])) { + $input['category_id'] = $this->transformKeys($input['category_id']); + } + + $this->replace($input); } } diff --git a/app/Repositories/ExpenseRepository.php b/app/Repositories/ExpenseRepository.php index 04ac88e97bdf..dd64f5833a15 100644 --- a/app/Repositories/ExpenseRepository.php +++ b/app/Repositories/ExpenseRepository.php @@ -12,13 +12,14 @@ namespace App\Repositories; -use App\Factory\ExpenseFactory; -use App\Libraries\Currency\Conversion\CurrencyApi; use App\Models\Expense; -use App\Utils\Traits\GeneratesCounter; -use Carbon\Exceptions\InvalidFormatException; -use Illuminate\Database\QueryException; use Illuminate\Support\Carbon; +use App\Factory\ExpenseFactory; +use App\Models\ExpenseCategory; +use App\Utils\Traits\GeneratesCounter; +use Illuminate\Database\QueryException; +use Carbon\Exceptions\InvalidFormatException; +use App\Libraries\Currency\Conversion\CurrencyApi; /** * ExpenseRepository. @@ -158,4 +159,25 @@ class ExpenseRepository extends BaseRepository return $expense; } + + /** + * Categorize Expenses in bulk + * + * @param Collection $expenses + * @param int $category_id + * @return void + */ + public function categorize($expenses, $category_id): void + { + $ec = ExpenseCategory::withTrashed()->find($category_id); + + $expenses->when($ec) + ->each(function ($expense) use($ec){ + + $expense->category_id = $ec->id; + $expense->save(); + + }); + } + } diff --git a/tests/Feature/ExpenseApiTest.php b/tests/Feature/ExpenseApiTest.php index ef6fadf3d019..5a8b8d7b7908 100644 --- a/tests/Feature/ExpenseApiTest.php +++ b/tests/Feature/ExpenseApiTest.php @@ -11,11 +11,12 @@ namespace Tests\Feature; -use App\Models\BankIntegration; -use App\Models\BankTransaction; use Tests\TestCase; use App\Models\Expense; use Tests\MockAccountData; +use App\Models\BankIntegration; +use App\Models\BankTransaction; +use App\Models\ExpenseCategory; use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Session; @@ -232,6 +233,42 @@ class ExpenseApiTest extends TestCase $this->assertTrue($arr['data'][0]['is_deleted']); } + public function testExpenseBulkCategorize() + { + + + $e = Expense::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + ]); + + + $ec = ExpenseCategory::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'name' => 'Test Category', + ]); + + nlog("expense category id = {$ec->hashed_id}"); + + $data = [ + 'category_id' => $ec->hashed_id, + 'action' => 'bulk_categorize', + 'ids' => [$this->encodePrimaryKey($e->id)], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/expenses/bulk', $data); + + $arr = $response->json(); + nlog($arr); + + $this->assertEquals($ec->hashed_id, $arr['data'][0]['category_id']); + } + + public function testAddingExpense() { $data = [