Add bulk categorization:

This commit is contained in:
David Bomba 2023-11-03 11:07:05 +11:00
parent d26e5f05c3
commit 79e9c516fd
4 changed files with 127 additions and 50 deletions

View File

@ -11,27 +11,28 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Events\Expense\ExpenseWasCreated; use App\Utils\Ninja;
use App\Events\Expense\ExpenseWasUpdated; use App\Models\Account;
use App\Models\Expense;
use Illuminate\Http\Response;
use App\Factory\ExpenseFactory; use App\Factory\ExpenseFactory;
use App\Filters\ExpenseFilters; use App\Filters\ExpenseFilters;
use App\Http\Requests\Expense\CreateExpenseRequest; use App\Utils\Traits\MakesHash;
use App\Http\Requests\Expense\DestroyExpenseRequest; 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\EditExpenseRequest;
use App\Http\Requests\Expense\ShowExpenseRequest; use App\Http\Requests\Expense\ShowExpenseRequest;
use App\Http\Requests\Expense\StoreExpenseRequest; use App\Http\Requests\Expense\StoreExpenseRequest;
use App\Http\Requests\Expense\CreateExpenseRequest;
use App\Http\Requests\Expense\UpdateExpenseRequest; use App\Http\Requests\Expense\UpdateExpenseRequest;
use App\Http\Requests\Expense\UploadExpenseRequest; use App\Http\Requests\Expense\UploadExpenseRequest;
use App\Models\Account; use App\Http\Requests\Expense\DestroyExpenseRequest;
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;
/** /**
* Class ExpenseController. * Class ExpenseController.
@ -321,7 +322,10 @@ class ExpenseController extends BaseController
*/ */
public function create(CreateExpenseRequest $request) 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); return $this->itemResponse($expense);
} }
@ -366,9 +370,12 @@ class ExpenseController extends BaseController
*/ */
public function store(StoreExpenseRequest $request) 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); 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($request->ids);
$expenses = Expense::withTrashed()->find($this->transformKeys($ids));
$expenses->each(function ($expense, $key) use ($action) { if($request->action == 'bulk_categorize' && $user->can('edit', $expenses->first())) {
if (auth()->user()->can('edit', $expense)) { $this->expense_repo->categorize($expenses, $request->category_id);
$this->expense_repo->{$action}($expense); $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));
} }
/** /**

View File

@ -12,13 +12,10 @@
namespace App\Http\Requests\Expense; namespace App\Http\Requests\Expense;
use App\Http\Requests\Request; use App\Http\Requests\Request;
use App\Models\Expense; use Illuminate\Validation\Rule;
use App\Utils\Traits\BulkOptions;
class BulkExpenseRequest extends Request class BulkExpenseRequest extends Request
{ {
use BulkOptions;
/** /**
* Determine if the user is authorized to make this request. * Determine if the user is authorized to make this request.
* *
@ -26,15 +23,7 @@ class BulkExpenseRequest extends Request
*/ */
public function authorize() public function authorize()
{ {
if (! $this->has('action')) { return true;
return false;
}
if (! in_array($this->action, $this->getBulkOptions(), true)) {
return false;
}
return auth()->user()->can(auth()->user()->isAdmin(), Expense::class);
} }
/** /**
@ -44,13 +33,30 @@ class BulkExpenseRequest extends Request
*/ */
public function rules() public function rules()
{ {
$rules = $this->getGlobalRules(); /** @var \App\Models\User $user */
$user = auth()->user();
/* We don't require IDs on bulk storing. */ return [
if ($this->action !== self::$STORE_METHOD) { 'ids' => ['required','bail','array', Rule::exists('expenses', 'id')->where('company_id', $user->company()->id)],
$rules['ids'] = ['required']; '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);
} }
} }

View File

@ -12,13 +12,14 @@
namespace App\Repositories; namespace App\Repositories;
use App\Factory\ExpenseFactory;
use App\Libraries\Currency\Conversion\CurrencyApi;
use App\Models\Expense; use App\Models\Expense;
use App\Utils\Traits\GeneratesCounter;
use Carbon\Exceptions\InvalidFormatException;
use Illuminate\Database\QueryException;
use Illuminate\Support\Carbon; 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. * ExpenseRepository.
@ -158,4 +159,25 @@ class ExpenseRepository extends BaseRepository
return $expense; 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();
});
}
} }

View File

@ -11,11 +11,12 @@
namespace Tests\Feature; namespace Tests\Feature;
use App\Models\BankIntegration;
use App\Models\BankTransaction;
use Tests\TestCase; use Tests\TestCase;
use App\Models\Expense; use App\Models\Expense;
use Tests\MockAccountData; use Tests\MockAccountData;
use App\Models\BankIntegration;
use App\Models\BankTransaction;
use App\Models\ExpenseCategory;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Session;
@ -232,6 +233,42 @@ class ExpenseApiTest extends TestCase
$this->assertTrue($arr['data'][0]['is_deleted']); $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() public function testAddingExpense()
{ {
$data = [ $data = [