From 0e9d098049bdd1d3dea45aa62fc8446f512fd04b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 20 Jan 2020 15:53:40 +1100 Subject: [PATCH] Fixes for Vendor Contacts (#3227) * bug Fixes * Working on Vendor GET route * Fixes for vendor contacts --- app/Console/Commands/CreateTestData.php | 6 - app/Filters/ExpenseFilters.php | 158 +++++++++++++++++++ app/Http/Controllers/ExpenseController.php | 171 +++++++++++---------- app/Http/Controllers/VendorController.php | 2 + app/Models/Expense.php | 2 + app/Models/Vendor.php | 3 + app/Repositories/ExpenseRepository.php | 75 +++++++++ app/Transformers/VendorTransformer.php | 1 + 8 files changed, 327 insertions(+), 91 deletions(-) create mode 100644 app/Filters/ExpenseFilters.php create mode 100644 app/Repositories/ExpenseRepository.php diff --git a/app/Console/Commands/CreateTestData.php b/app/Console/Commands/CreateTestData.php index 7dffda4c6345..88d4eebc7bf0 100644 --- a/app/Console/Commands/CreateTestData.php +++ b/app/Console/Commands/CreateTestData.php @@ -300,12 +300,6 @@ class CreateTestData extends Command 'is_primary' => 0 ]); - factory(\App\Models\Vendor::class, rand(10, 50))->create([ - 'user_id' => $client->user->id, - 'company_id' => $client->company->id - ]); - - } private function createInvoice($client) diff --git a/app/Filters/ExpenseFilters.php b/app/Filters/ExpenseFilters.php new file mode 100644 index 000000000000..3dd97a2e3abd --- /dev/null +++ b/app/Filters/ExpenseFilters.php @@ -0,0 +1,158 @@ +builder; + } + + return $this->builder->where(function ($query) use ($filter) { + $query->where('expenses.name', 'like', '%'.$filter.'%') + ->orWhere('expenses.id_number', 'like', '%'.$filter.'%') + ->orWhere('expense_contacts.first_name', 'like', '%'.$filter.'%') + ->orWhere('expense_contacts.last_name', 'like', '%'.$filter.'%') + ->orWhere('expense_contacts.email', 'like', '%'.$filter.'%') + ->orWhere('expenses.custom_value1', 'like', '%'.$filter.'%') + ->orWhere('expenses.custom_value2', 'like', '%'.$filter.'%') + ->orWhere('expenses.custom_value3', 'like', '%'.$filter.'%') + ->orWhere('expenses.custom_value4', 'like', '%'.$filter.'%'); + }); + } + + /** + * Filters the list based on the status + * archived, active, deleted + * + * @param string filter + * @return Illuminate\Database\Query\Builder + */ + public function status(string $filter = '') : Builder + { + if (strlen($filter) == 0) { + return $this->builder; + } + + $table = 'expenses'; + $filters = explode(',', $filter); + + return $this->builder->where(function ($query) use ($filters, $table) { + $query->whereNull($table . '.id'); + + if (in_array(parent::STATUS_ACTIVE, $filters)) { + $query->orWhereNull($table . '.deleted_at'); + } + + if (in_array(parent::STATUS_ARCHIVED, $filters)) { + $query->orWhere(function ($query) use ($table) { + $query->whereNotNull($table . '.deleted_at'); + + if (! in_array($table, ['users'])) { + $query->where($table . '.is_deleted', '=', 0); + } + }); + } + + if (in_array(parent::STATUS_DELETED, $filters)) { + $query->orWhere($table . '.is_deleted', '=', 1); + } + }); + } + + /** + * Sorts the list based on $sort + * + * @param string sort formatted as column|asc + * @return Illuminate\Database\Query\Builder + */ + public function sort(string $sort) : Builder + { + $sort_col = explode("|", $sort); + return $this->builder->orderBy($sort_col[0], $sort_col[1]); + } + + /** + * Returns the base query + * + * @param int company_id + * @return Illuminate\Database\Query\Builder + * @deprecated + */ + public function baseQuery(int $company_id, User $user) : Builder + { + $query = DB::table('expenses') + ->join('companies', 'companies.id', '=', 'expenses.company_id') + ->where('expenses.company_id', '=', $company_id) + //->whereRaw('(expenses.name != "" or contacts.first_name != "" or contacts.last_name != "" or contacts.email != "")') // filter out buy now invoices + ->select( + // DB::raw('COALESCE(expenses.currency_id, companies.currency_id) currency_id'), + DB::raw('COALESCE(expenses.country_id, companies.country_id) country_id'), + DB::raw("CONCAT(COALESCE(expense_contacts.first_name, ''), ' ', COALESCE(expense_contacts.last_name, '')) contact"), + 'expenses.id', + 'expenses.private_notes', + 'expenses.custom_value1', + 'expenses.custom_value2', + 'expenses.custom_value3', + 'expenses.custom_value4', + 'expenses.created_at', + 'expenses.created_at as expense_created_at', + 'expenses.deleted_at', + 'expenses.is_deleted', + 'expenses.user_id', + ); + + /** + * If the user does not have permissions to view all invoices + * limit the user to only the invoices they have created + */ + if (Gate::denies('view-list', Expense::class)) { + $query->where('expenses.user_id', '=', $user->id); + } + + + return $query; + } + + /** + * Filters the query by the users company ID + * + * @param $company_id The company Id + * @return Illuminate\Database\Query\Builder + */ + public function entityFilter() + { + + //return $this->builder->whereCompanyId(auth()->user()->company()->id); + return $this->builder->company(); + } +} diff --git a/app/Http/Controllers/ExpenseController.php b/app/Http/Controllers/ExpenseController.php index b762128f6d58..5baa771d2aba 100644 --- a/app/Http/Controllers/ExpenseController.php +++ b/app/Http/Controllers/ExpenseController.php @@ -11,16 +11,17 @@ namespace App\Http\Controllers; -use App\Filters\VendorFilters; +use App\Filters\ExpenseFilters; use App\Jobs\Entity\ActionEntity; use App\Jobs\Util\ProcessBulk; use App\Jobs\Util\UploadAvatar; use App\Models\Country; use App\Models\Currency; +use App\Models\Expense; use App\Models\Size; -use App\Models\Vendor; use App\Repositories\BaseRepository; -use App\Transformers\VendorTransformer; +use App\Repositories\ExpenseRepository; +use App\Transformers\ExpenseTransformer; use App\Utils\Traits\BulkOptions; use App\Utils\Traits\MakesHash; use App\Utils\Traits\Uploadable; @@ -29,45 +30,45 @@ use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Log; /** - * Class VendorController + * Class ExpenseController * @package App\Http\Controllers - * @covers App\Http\Controllers\VendorController + * @covers App\Http\Controllers\ExpenseController */ -class VendorController extends BaseController +class ExpenseController extends BaseController { use MakesHash; use Uploadable; use BulkOptions; - protected $entity_type = Vendor::class; + protected $entity_type = Expense::class; - protected $entity_transformer = VendorTransformer::class; + protected $entity_transformer = ExpenseTransformer::class; /** - * @var Vendorepository + * @var Expenseepository */ - protected $vendor_repo; + protected $expense_repo; /** - * VendorController constructor. - * @param VendorRepository $vendorRepo + * ExpenseController constructor. + * @param ExpenseRepository $expenseRepo */ - public function __construct(VendorRepository $vendor_repo) + public function __construct(ExpenseRepository $expense_repo) { parent::__construct(); - $this->vendor_repo = $vendor_repo; + $this->expense_repo = $expense_repo; } /** * @OA\Get( - * path="/api/v1/vendors", - * operationId="getVendors", - * tags={"vendors"}, - * summary="Gets a list of vendors", - * description="Lists vendors, search and filters allow fine grained lists to be generated. + * path="/api/v1/expenses", + * operationId="getExpenses", + * tags={"expenses"}, + * summary="Gets a list of expenses", + * description="Lists expenses, search and filters allow fine grained lists to be generated. - Query parameters can be added to performed more fine grained filtering of the vendors, these are handled by the VendorFilters class which defines the methods available", + Query parameters can be added to performed more fine grained filtering of the expenses, these are handled by the ExpenseFilters class which defines the methods available", * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), @@ -75,11 +76,11 @@ class VendorController extends BaseController * @OA\Parameter(ref="#/components/parameters/index"), * @OA\Response( * response=200, - * description="A list of vendors", + * description="A list of expenses", * @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-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\JsonContent(ref="#/components/schemas/Vendor"), + * @OA\JsonContent(ref="#/components/schemas/Expense"), * ), * @OA\Response( * response=422, @@ -95,11 +96,11 @@ class VendorController extends BaseController * ) * */ - public function index(VendorFilters $filters) + public function index(ExpenseFilters $filters) { - $vendors = Vendor::filter($filters); + $expenses = Expense::filter($filters); - return $this->listResponse($vendors); + return $this->listResponse($expenses); } /** @@ -110,9 +111,9 @@ class VendorController extends BaseController * * * @OA\Get( - * path="/api/v1/vendors/{id}", - * operationId="showVendor", - * tags={"vendors"}, + * path="/api/v1/expenses/{id}", + * operationId="showExpense", + * tags={"expenses"}, * summary="Shows a client", * description="Displays a client by id", * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), @@ -122,7 +123,7 @@ class VendorController extends BaseController * @OA\Parameter( * name="id", * in="path", - * description="The Vendor Hashed ID", + * description="The Expense Hashed ID", * example="D2J234DFA", * required=true, * @OA\Schema( @@ -132,11 +133,11 @@ class VendorController extends BaseController * ), * @OA\Response( * response=200, - * description="Returns the vendor object", + * description="Returns the expense object", * @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-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\JsonContent(ref="#/components/schemas/Vendor"), + * @OA\JsonContent(ref="#/components/schemas/Expense"), * ), * @OA\Response( * response=422, @@ -152,9 +153,9 @@ class VendorController extends BaseController * ) * */ - public function show(ShowVendorRequest $request, Vendor $vendor) + public function show(ShowExpenseRequest $request, Expense $expense) { - return $this->itemResponse($vendor); + return $this->itemResponse($expense); } /** @@ -165,9 +166,9 @@ class VendorController extends BaseController * * * @OA\Get( - * path="/api/v1/vendors/{id}/edit", - * operationId="editVendor", - * tags={"vendors"}, + * path="/api/v1/expenses/{id}/edit", + * operationId="editExpense", + * tags={"expenses"}, * summary="Shows a client for editting", * description="Displays a client by id", * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), @@ -177,7 +178,7 @@ class VendorController extends BaseController * @OA\Parameter( * name="id", * in="path", - * description="The Vendor Hashed ID", + * description="The Expense Hashed ID", * example="D2J234DFA", * required=true, * @OA\Schema( @@ -191,7 +192,7 @@ class VendorController extends BaseController * @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-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\JsonContent(ref="#/components/schemas/Vendor"), + * @OA\JsonContent(ref="#/components/schemas/Expense"), * ), * @OA\Response( * response=422, @@ -207,24 +208,24 @@ class VendorController extends BaseController * ) * */ - public function edit(EditVendorRequest $request, Vendor $vendor) + public function edit(EditExpenseRequest $request, Expense $expense) { - return $this->itemResponse($vendor); + return $this->itemResponse($expense); } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request - * @param App\Models\Vendor $vendor + * @param App\Models\Expense $expense * @return \Illuminate\Http\Response * * * * @OA\Put( - * path="/api/v1/vendors/{id}", - * operationId="updateVendor", - * tags={"vendors"}, + * path="/api/v1/expenses/{id}", + * operationId="updateExpense", + * tags={"expenses"}, * summary="Updates a client", * description="Handles the updating of a client by id", * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), @@ -234,7 +235,7 @@ class VendorController extends BaseController * @OA\Parameter( * name="id", * in="path", - * description="The Vendor Hashed ID", + * description="The Expense Hashed ID", * example="D2J234DFA", * required=true, * @OA\Schema( @@ -248,7 +249,7 @@ class VendorController extends BaseController * @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-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\JsonContent(ref="#/components/schemas/Vendor"), + * @OA\JsonContent(ref="#/components/schemas/Expense"), * ), * @OA\Response( * response=422, @@ -264,16 +265,16 @@ class VendorController extends BaseController * ) * */ - public function update(UpdateVendorRequest $request, Vendor $vendor) + public function update(UpdateExpenseRequest $request, Expense $expense) { - if($request->entityIsDeleted($vendor)) + if($request->entityIsDeleted($expense)) return $request->disallowUpdate(); - $vendor = $this->client_repo->save($request->all(), $vendor); + $expense = $this->client_repo->save($request->all(), $expense); - $this->uploadLogo($request->file('company_logo'), $vendor->company, $vendor); + $this->uploadLogo($request->file('company_logo'), $expense->company, $expense); - return $this->itemResponse($vendor->fresh()); + return $this->itemResponse($expense->fresh()); } /** @@ -284,9 +285,9 @@ class VendorController extends BaseController * * * @OA\Get( - * path="/api/v1/vendors/create", - * operationId="getVendorsCreate", - * tags={"vendors"}, + * path="/api/v1/expenses/create", + * operationId="getExpensesCreate", + * tags={"expenses"}, * summary="Gets a new blank client object", * description="Returns a blank object with default values", * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), @@ -299,7 +300,7 @@ class VendorController extends BaseController * @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-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\JsonContent(ref="#/components/schemas/Vendor"), + * @OA\JsonContent(ref="#/components/schemas/Expense"), * ), * @OA\Response( * response=422, @@ -315,11 +316,11 @@ class VendorController extends BaseController * ) * */ - public function create(CreateVendorRequest $request) + public function create(CreateExpenseRequest $request) { - $vendor = VendorFactory::create(auth()->user()->company()->id, auth()->user()->id); + $expense = ExpenseFactory::create(auth()->user()->company()->id, auth()->user()->id); - return $this->itemResponse($vendor); + return $this->itemResponse($expense); } /** @@ -331,9 +332,9 @@ class VendorController extends BaseController * * * @OA\Post( - * path="/api/v1/vendors", - * operationId="storeVendor", - * tags={"vendors"}, + * path="/api/v1/expenses", + * operationId="storeExpense", + * tags={"expenses"}, * summary="Adds a client", * description="Adds an client to a company", * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), @@ -346,7 +347,7 @@ class VendorController extends BaseController * @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-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\JsonContent(ref="#/components/schemas/Vendor"), + * @OA\JsonContent(ref="#/components/schemas/Expense"), * ), * @OA\Response( * response=422, @@ -362,15 +363,15 @@ class VendorController extends BaseController * ) * */ - public function store(StoreVendorRequest $request) + public function store(StoreExpenseRequest $request) { - $vendor = $this->client_repo->save($request->all(), VendorFactory::create(auth()->user()->company()->id, auth()->user()->id)); + $expense = $this->client_repo->save($request->all(), ExpenseFactory::create(auth()->user()->company()->id, auth()->user()->id)); - $vendor->load('contacts', 'primary_contact'); + $expense->load('contacts', 'primary_contact'); - $this->uploadLogo($request->file('company_logo'), $vendor->company, $vendor); + $this->uploadLogo($request->file('company_logo'), $expense->company, $expense); - return $this->itemResponse($vendor); + return $this->itemResponse($expense); } /** @@ -381,9 +382,9 @@ class VendorController extends BaseController * * * @OA\Delete( - * path="/api/v1/vendors/{id}", - * operationId="deleteVendor", - * tags={"vendors"}, + * path="/api/v1/expenses/{id}", + * operationId="deleteExpense", + * tags={"expenses"}, * summary="Deletes a client", * description="Handles the deletion of a client by id", * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), @@ -393,7 +394,7 @@ class VendorController extends BaseController * @OA\Parameter( * name="id", * in="path", - * description="The Vendor Hashed ID", + * description="The Expense Hashed ID", * example="D2J234DFA", * required=true, * @OA\Schema( @@ -422,10 +423,10 @@ class VendorController extends BaseController * ) * */ - public function destroy(DestroyVendorRequest $request, Vendor $vendor) + public function destroy(DestroyExpenseRequest $request, Expense $expense) { //may not need these destroy routes as we are using actions to 'archive/delete' - $vendor->delete(); + $expense->delete(); return response()->json([], 200); } @@ -433,15 +434,15 @@ class VendorController extends BaseController /** * Perform bulk actions on the list view * - * @param BulkVendorRequest $request + * @param BulkExpenseRequest $request * @return \Illuminate\Http\Response * * * @OA\Post( - * path="/api/v1/vendors/bulk", - * operationId="bulkVendors", - * tags={"vendors"}, - * summary="Performs bulk actions on an array of vendors", + * path="/api/v1/expenses/bulk", + * operationId="bulkExpenses", + * tags={"expenses"}, + * summary="Performs bulk actions on an array of expenses", * description="", * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), @@ -464,11 +465,11 @@ class VendorController extends BaseController * ), * @OA\Response( * response=200, - * description="The Vendor User response", + * description="The Expense User response", * @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-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\JsonContent(ref="#/components/schemas/Vendor"), + * @OA\JsonContent(ref="#/components/schemas/Expense"), * ), * @OA\Response( * response=422, @@ -487,15 +488,15 @@ class VendorController extends BaseController $action = request()->input('action'); $ids = request()->input('ids'); - $vendors = Vendor::withTrashed()->find($this->transformKeys($ids)); + $expenses = Expense::withTrashed()->find($this->transformKeys($ids)); - $vendors->each(function ($vendor, $key) use ($action) { - if (auth()->user()->can('edit', $vendor)) { - $this->client_repo->{$action}($vendor); + $expenses->each(function ($expense, $key) use ($action) { + if (auth()->user()->can('edit', $expense)) { + $this->client_repo->{$action}($expense); } }); - return $this->listResponse(Vendor::withTrashed()->whereIn('id', $this->transformKeys($ids))); + return $this->listResponse(Expense::withTrashed()->whereIn('id', $this->transformKeys($ids))); } /** diff --git a/app/Http/Controllers/VendorController.php b/app/Http/Controllers/VendorController.php index 3206ea74e8c6..66dd50dc0aec 100644 --- a/app/Http/Controllers/VendorController.php +++ b/app/Http/Controllers/VendorController.php @@ -20,6 +20,8 @@ use App\Models\Currency; use App\Models\Size; use App\Models\Vendor; use App\Repositories\BaseRepository; +use App\Repositories\VendorRepository; +use App\Transformers\VendorTransformer; use App\Utils\Traits\BulkOptions; use App\Utils\Traits\MakesHash; use App\Utils\Traits\Uploadable; diff --git a/app/Models/Expense.php b/app/Models/Expense.php index 4b66310ce245..a3e32694371b 100644 --- a/app/Models/Expense.php +++ b/app/Models/Expense.php @@ -11,6 +11,7 @@ namespace App\Models; +use App\Models\Filterable; use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; @@ -18,6 +19,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; class Expense extends BaseModel { use SoftDeletes; + use Filterable; protected $fillable = [ 'client_id', diff --git a/app/Models/Vendor.php b/app/Models/Vendor.php index 2a41ea6ad862..31c542211dc3 100644 --- a/app/Models/Vendor.php +++ b/app/Models/Vendor.php @@ -11,6 +11,8 @@ namespace App\Models; +use App\Models\Filterable; +use App\Models\VendorContact; use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; @@ -18,6 +20,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; class Vendor extends BaseModel { use SoftDeletes; + use Filterable; protected $fillable = [ 'name', diff --git a/app/Repositories/ExpenseRepository.php b/app/Repositories/ExpenseRepository.php new file mode 100644 index 000000000000..f6e235ead9ed --- /dev/null +++ b/app/Repositories/ExpenseRepository.php @@ -0,0 +1,75 @@ +fill($data); + + $expense->save(); + + // if ($expense->id_number == "" || !$expense->id_number) { + // $expense->id_number = $this->getNextExpenseNumber($expense); + // } //todo write tests for this and make sure that custom expense numbers also works as expected from here + + return $expense; + } + + /** + * Store expenses in bulk. + * + * @param array $expense + * @return expense|null + */ + public function create($expense): ?Expense + { + return $this->save( + $expense, + ExpenseFactory::create(auth()->user()->company()->id, auth()->user()->id) + ); + } +} diff --git a/app/Transformers/VendorTransformer.php b/app/Transformers/VendorTransformer.php index 2be36ecaa321..6e5970bba64e 100644 --- a/app/Transformers/VendorTransformer.php +++ b/app/Transformers/VendorTransformer.php @@ -16,6 +16,7 @@ use App\Models\Vendor; use App\Models\VendorContact; use App\Models\VendorGatewayToken; use App\Transformers\ActivityTransformer; +use App\Transformers\VendorContactTransformer; use App\Transformers\VendorGatewayTokenTransformer; use App\Utils\Traits\MakesHash;