diff --git a/app/Console/Commands/DemoMode.php b/app/Console/Commands/DemoMode.php index 4f6600f5acf8..8a5070a1f9bb 100644 --- a/app/Console/Commands/DemoMode.php +++ b/app/Console/Commands/DemoMode.php @@ -17,6 +17,7 @@ use App\Factory\InvoiceFactory; use App\Factory\InvoiceItemFactory; use App\Helpers\Invoice\InvoiceSum; use App\Jobs\Company\CreateCompanyPaymentTerms; +use App\Jobs\Company\CreateCompanyTaskStatuses; use App\Jobs\Ninja\CompanySizeCheck; use App\Jobs\Util\VersionCheck; use App\Models\Account; @@ -175,6 +176,7 @@ class DemoMode extends Command } CreateCompanyPaymentTerms::dispatchNow($company, $user); + CreateCompanyTaskStatuses::dispatchNow($company, $user); $company_token = new CompanyToken; $company_token->user_id = $user->id; diff --git a/app/Factory/TaskStatusFactory.php b/app/Factory/TaskStatusFactory.php new file mode 100644 index 000000000000..bead18ebb760 --- /dev/null +++ b/app/Factory/TaskStatusFactory.php @@ -0,0 +1,27 @@ +user_id = $user_id; + $task_status->company_id = $company_id; + $task_status->name = ''; + + return $task_status; + } +} diff --git a/app/Http/Controllers/CompanyController.php b/app/Http/Controllers/CompanyController.php index a2cad28cc1ce..a023f7e63fa3 100644 --- a/app/Http/Controllers/CompanyController.php +++ b/app/Http/Controllers/CompanyController.php @@ -23,6 +23,7 @@ use App\Http\Requests\Company\UpdateCompanyRequest; use App\Http\Requests\SignupRequest; use App\Jobs\Company\CreateCompany; use App\Jobs\Company\CreateCompanyPaymentTerms; +use App\Jobs\Company\CreateCompanyTaskStatuses; use App\Jobs\Company\CreateCompanyToken; use App\Jobs\Ninja\RefundCancelledAccount; use App\Jobs\RegisterNewAccount; @@ -205,6 +206,7 @@ class CompanyController extends BaseController $company = CreateCompany::dispatchNow($request->all(), auth()->user()->company()->account); CreateCompanyPaymentTerms::dispatchNow($company, auth()->user()); + CreateCompanyTaskStatuses::dispatchNow($company, auth()->user()); $company = $this->company_repo->save($request->all(), $company); diff --git a/app/Http/Controllers/OpenAPI/TaskStatusSchema.php b/app/Http/Controllers/OpenAPI/TaskStatusSchema.php new file mode 100644 index 000000000000..6cfaa811f979 --- /dev/null +++ b/app/Http/Controllers/OpenAPI/TaskStatusSchema.php @@ -0,0 +1,12 @@ +task_status_repo = $task_status_repo; + } + + /** + * @OA\Get( + * path="/api/v1/task_status", + * operationId="getTaskStatuss", + * tags={"task_status"}, + * summary="Gets a list of task statuses", + * description="Lists task statuses", + * @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/include"), + * @OA\Parameter(ref="#/components/parameters/index"), + * @OA\Response( + * response=200, + * description="A list of task statuses", + * @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\JsonContent(ref="#/components/schemas/TaskStatus"), + * ), + * @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 index() + { + $task_status = TaskStatus::whereCompanyId(auth()->user()->company()->id)->orWhere('company_id', null); + + return $this->listResponse($task_status); + } + + /** + * Show the form for creating a new resource. + * + * @param \App\Http\Requests\TaskStatus\CreateTaskStatusRequest $request The request + * + * @return \Illuminate\Http\Response + * + * + * + * @OA\Get( + * path="/api/v1/task_statuses/create", + * operationId="getTaskStatussCreate", + * tags={"task_status"}, + * summary="Gets a new blank TaskStatus object", + * description="Returns a blank object with default values", + * @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/include"), + * @OA\Response( + * response=200, + * description="A blank TaskStatus object", + * @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\JsonContent(ref="#/components/schemas/TaskStatus"), + * ), + * @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 create(CreateTaskStatusRequest $request) + { + $task_status = TaskStatusFactory::create(auth()->user()->company()->id, auth()->user()->id); + + return $this->itemResponse($task_status); + } + + /** + * Store a newly created resource in storage. + * + * @param \App\Http\Requests\TaskStatus\StoreTaskStatusRequest $request The request + * + * @return \Illuminate\Http\Response + * + * + * + * @OA\Post( + * path="/api/v1/task_status", + * operationId="storeTaskStatus", + * tags={"task_status"}, + * summary="Adds a TaskStatus", + * description="Adds a TaskStatusto the system", + * @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/include"), + * @OA\RequestBody( + * description="The task_status request", + * required=true, + * @OA\JsonContent(ref="#/components/schemas/TaskStatus"), + * ), + * @OA\Response( + * response=200, + * description="Returns the saved TaskStatus object", + * @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\JsonContent(ref="#/components/schemas/TaskStatus"), + * ), + * @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 store(StoreTaskStatusRequest $request) + { + $task_status = TaskStatusFactory::create(auth()->user()->company()->id, auth()->user()->id); + $task_status->fill($request->all()); + $task_status->save(); + + return $this->itemResponse($task_status->fresh()); + } + + /** + * @OA\Get( + * path="/api/v1/task_statuses/{id}", + * operationId="showTaskStatus", + * tags={"task_status"}, + * summary="Shows a TaskStatus Term", + * description="Displays an TaskStatusby id", + * @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/include"), + * @OA\Parameter( + * name="id", + * in="path", + * description="The TaskStatusHashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns the TaskStatusobject", + * @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\JsonContent(ref="#/components/schemas/TaskStatus"), + * ), + * @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 show(ShowTaskStatusRequest $request, TaskStatus $task_status) + { + return $this->itemResponse($task_status); + } + + /** + * @OA\Get( + * path="/api/v1/task_statuses/{id}/edit", + * operationId="editTaskStatuss", + * tags={"task_status"}, + * summary="Shows an TaskStatusfor editting", + * description="Displays an TaskStatusby id", + * @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/include"), + * @OA\Parameter( + * name="id", + * in="path", + * description="The TaskStatusHashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns the TaskStatus object", + * @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\JsonContent(ref="#/components/schemas/TaskStatus"), + * ), + * @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 edit(EditTaskStatusRequest $request, TaskStatus $payment) + { + return $this->itemResponse($payment); + } + + /** + * Update the specified resource in storage. + * + * @param \App\Http\Requests\TaskStatus\UpdateTaskStatusRequest $request The request + * @param \App\Models\TaskStatus $task_status The payment term + * + * @return \Illuminate\Http\Response + * + * + * @OA\Put( + * path="/api/v1/task_statuses/{id}", + * operationId="updateTaskStatus", + * tags={"task_status"}, + * summary="Updates a TaskStatus Term", + * description="Handles the updating of an TaskStatus Termby id", + * @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/include"), + * @OA\Parameter( + * name="id", + * in="path", + * description="The TaskStatusHashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns the TaskStatusobject", + * @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\JsonContent(ref="#/components/schemas/TaskStatus"), + * ), + * @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 update(UpdateTaskStatusRequest $request, TaskStatus $task_status) + { + $task_status->fill($request->all()); + $task_status->save(); + + return $this->itemResponse($task_status->fresh()); + } + + /** + * Remove the specified resource from storage. + * + * @param \App\Http\Requests\TaskStatus\DestroyTaskStatusRequest $request + * @param \App\Models\TaskStatus $task_status + * + * @return \Illuminate\Http\Response + * + * + * @OA\Delete( + * path="/api/v1/task_statuses/{id}", + * operationId="deleteTaskStatus", + * tags={"task_statuss"}, + * summary="Deletes a TaskStatus Term", + * description="Handles the deletion of an TaskStatus by id", + * @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/include"), + * @OA\Parameter( + * name="id", + * in="path", + * description="The TaskStatusHashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns a HTTP status", + * @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 destroy(DestroyTaskStatusRequest $request, TaskStatus $task_status) + { + $task_status->delete(); + + return response()->json([], 200); + } + + /** + * Perform bulk actions on the list view. + * + * @return Collection + * + * + * @OA\Post( + * path="/api/v1/task_statuses/bulk", + * operationId="bulkTaskStatuss", + * tags={"task_status"}, + * summary="Performs bulk actions on an array of task statuses", + * 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="TaskStatus Ter,s", + * 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 TaskStatus Terms 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\JsonContent(ref="#/components/schemas/TaskStatus"), + * ), + * @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'); + + $ids = request()->input('ids'); + + $task_status = TaskStatus::withTrashed()->company()->find($this->transformKeys($ids)); + + $task_status->each(function ($task_status, $key) use ($action) { + if (auth()->user()->can('edit', $task_status)) { + $this->task_status_repo->{$action}($task_status); + } + }); + + return $this->listResponse(TaskStatus::withTrashed()->whereIn('id', $this->transformKeys($ids))); + } +} diff --git a/app/Http/Requests/TaskStatus/ActionTaskStatusRequest.php b/app/Http/Requests/TaskStatus/ActionTaskStatusRequest.php new file mode 100644 index 000000000000..379417df8d08 --- /dev/null +++ b/app/Http/Requests/TaskStatus/ActionTaskStatusRequest.php @@ -0,0 +1,28 @@ +user()->isAdmin(); + } +} diff --git a/app/Http/Requests/TaskStatus/CreateTaskStatusRequest.php b/app/Http/Requests/TaskStatus/CreateTaskStatusRequest.php new file mode 100644 index 000000000000..42850061ecff --- /dev/null +++ b/app/Http/Requests/TaskStatus/CreateTaskStatusRequest.php @@ -0,0 +1,28 @@ +user()->isAdmin(); + } +} diff --git a/app/Http/Requests/TaskStatus/DestroyTaskStatusRequest.php b/app/Http/Requests/TaskStatus/DestroyTaskStatusRequest.php new file mode 100644 index 000000000000..37cceac60e45 --- /dev/null +++ b/app/Http/Requests/TaskStatus/DestroyTaskStatusRequest.php @@ -0,0 +1,28 @@ +user()->isAdmin(); + } +} diff --git a/app/Http/Requests/TaskStatus/EditTaskStatusRequest.php b/app/Http/Requests/TaskStatus/EditTaskStatusRequest.php new file mode 100644 index 000000000000..f47d92f4cd5e --- /dev/null +++ b/app/Http/Requests/TaskStatus/EditTaskStatusRequest.php @@ -0,0 +1,44 @@ +user()->isAdmin(); + } + + public function rules() + { + $rules = []; + + return $rules; + } + + protected function prepareForValidation() + { + $input = $this->all(); + + //$input['id'] = $this->encodePrimaryKey($input['id']); + + $this->replace($input); + } +} diff --git a/app/Http/Requests/TaskStatus/ShowTaskStatusRequest.php b/app/Http/Requests/TaskStatus/ShowTaskStatusRequest.php new file mode 100644 index 000000000000..9037c2628abb --- /dev/null +++ b/app/Http/Requests/TaskStatus/ShowTaskStatusRequest.php @@ -0,0 +1,28 @@ +user()->isAdmin(); + } +} diff --git a/app/Http/Requests/TaskStatus/StoreTaskStatusRequest.php b/app/Http/Requests/TaskStatus/StoreTaskStatusRequest.php new file mode 100644 index 000000000000..9ecfc444ec34 --- /dev/null +++ b/app/Http/Requests/TaskStatus/StoreTaskStatusRequest.php @@ -0,0 +1,47 @@ +user()->isAdmin(); + } + + protected function prepareForValidation() + { + $input = $this->all(); + + $this->replace($input); + } + + public function rules() + { + $rules = []; + + $rules['name'] ='required|unique:task_statuses,name,null,null,company_id,'.auth()->user()->companyId(); + + return $rules; + } +} diff --git a/app/Http/Requests/TaskStatus/UpdateTaskStatusRequest.php b/app/Http/Requests/TaskStatus/UpdateTaskStatusRequest.php new file mode 100644 index 000000000000..17587dd8175f --- /dev/null +++ b/app/Http/Requests/TaskStatus/UpdateTaskStatusRequest.php @@ -0,0 +1,48 @@ +user()->isAdmin(); + } + + public function rules() + { + $rules = []; + + if ($this->input('name')) + $rules['name'] = 'unique:task_statuses,name,'.$this->id.',id,company_id,'.$this->task_status->company_id; + + return $rules; + } + + // protected function prepareForValidation() + // { + // $input = $this->all(); + + // $this->replace($input); + // } +} diff --git a/app/Jobs/Account/CreateAccount.php b/app/Jobs/Account/CreateAccount.php index 70b9d1be080a..1f69e0e60ebd 100644 --- a/app/Jobs/Account/CreateAccount.php +++ b/app/Jobs/Account/CreateAccount.php @@ -15,6 +15,7 @@ use App\DataMapper\Analytics\AccountCreated as AnalyticsAccountCreated; use App\Events\Account\AccountCreated; use App\Jobs\Company\CreateCompany; use App\Jobs\Company\CreateCompanyPaymentTerms; +use App\Jobs\Company\CreateCompanyTaskStatuses; use App\Jobs\Company\CreateCompanyToken; use App\Jobs\User\CreateUser; use App\Models\Account; @@ -74,6 +75,7 @@ class CreateAccount $spaa9f78 = CreateUser::dispatchNow($this->request, $sp794f3f, $sp035a66, true); CreateCompanyPaymentTerms::dispatchNow($sp035a66, $spaa9f78); + CreateCompanyTaskStatuses::dispatchNow($sp035a66, $spaa9f78); if ($spaa9f78) { auth()->login($spaa9f78, false); diff --git a/app/Jobs/Company/CreateCompanyTaskStatuses.php b/app/Jobs/Company/CreateCompanyTaskStatuses.php new file mode 100644 index 000000000000..04814e173515 --- /dev/null +++ b/app/Jobs/Company/CreateCompanyTaskStatuses.php @@ -0,0 +1,61 @@ +company = $company; + + $this->user = $user; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + $task_statuses = [ + ['name' => ctrans('texts.backlog'), 'company_id' => $this->company->id, 'user_id' => $this->user->id, 'created_at' => now(), 'updated_at' => now()], + ['name' => ctrans('texts.ready_to_do'), 'company_id' => $this->company->id, 'user_id' => $this->user->id, 'created_at' => now(), 'updated_at' => now()], + ['name' => ctrans('texts.in_progress'), 'company_id' => $this->company->id, 'user_id' => $this->user->id, 'created_at' => now(), 'updated_at' => now()], + ['name' => ctrans('texts.done'), 'company_id' => $this->company->id, 'user_id' => $this->user->id, 'created_at' => now(), 'updated_at' => now()], + + ]; + + TaskStatus::insert($task_statuses); + } +} diff --git a/app/Models/TaskStatus.php b/app/Models/TaskStatus.php new file mode 100644 index 000000000000..c90ab601978a --- /dev/null +++ b/app/Models/TaskStatus.php @@ -0,0 +1,34 @@ +isAdmin() || $user->hasPermission('create_all'); + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index d0c8d2978134..f8517417a310 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -31,6 +31,7 @@ use App\Models\Quote; use App\Models\RecurringInvoice; use App\Models\RecurringQuote; use App\Models\Task; +use App\Models\TaskStatus; use App\Models\TaxRate; use App\Models\User; use App\Models\Vendor; @@ -55,6 +56,7 @@ use App\Policies\QuotePolicy; use App\Policies\RecurringInvoicePolicy; use App\Policies\RecurringQuotePolicy; use App\Policies\TaskPolicy; +use App\Policies\TaskStatusPolicy; use App\Policies\TaxRatePolicy; use App\Policies\UserPolicy; use App\Policies\VendorPolicy; @@ -92,6 +94,7 @@ class AuthServiceProvider extends ServiceProvider RecurringQuote::class => RecurringQuotePolicy::class, Webhook::class => WebhookPolicy::class, Task::class => TaskPolicy::class, + TaskStatus::class => TaskStatusPolicy::class, TaxRate::class => TaxRatePolicy::class, User::class => UserPolicy::class, Vendor::class => VendorPolicy::class, diff --git a/app/Repositories/TaskStatusRepository.php b/app/Repositories/TaskStatusRepository.php new file mode 100644 index 000000000000..7b71ea14af2a --- /dev/null +++ b/app/Repositories/TaskStatusRepository.php @@ -0,0 +1,19 @@ + (string) $this->encodePrimaryKey($task_status->id), + 'name' => (string) $task_status->name, + 'is_deleted' => (bool) $task_status->is_deleted, + 'created_at' => (int) $task_status->created_at, + 'updated_at' => (int) $task_status->updated_at, + 'archived_at' => (int) $task_status->deleted_at, + ]; + } +} diff --git a/app/Utils/HtmlEngine.php b/app/Utils/HtmlEngine.php index 2075ace404bc..6befe6d676db 100644 --- a/app/Utils/HtmlEngine.php +++ b/app/Utils/HtmlEngine.php @@ -365,6 +365,8 @@ class HtmlEngine $arrKeysLength = array_map('strlen', array_keys($data)); array_multisort($arrKeysLength, SORT_DESC, $data); +//info(print_r($data,1)); + return $data; } diff --git a/database/factories/TaskStatusFactory.php b/database/factories/TaskStatusFactory.php new file mode 100644 index 000000000000..02f49d3e0dd3 --- /dev/null +++ b/database/factories/TaskStatusFactory.php @@ -0,0 +1,38 @@ + $this->faker->text(7), + ]; + } +} \ No newline at end of file diff --git a/database/migrations/2020_10_19_101823_project_name_unique_removal.php b/database/migrations/2020_10_19_101823_project_name_unique_removal.php index 970e6a14bb89..de411b87d721 100644 --- a/database/migrations/2020_10_19_101823_project_name_unique_removal.php +++ b/database/migrations/2020_10_19_101823_project_name_unique_removal.php @@ -30,6 +30,20 @@ class ProjectNameUniqueRemoval extends Migration $table->boolean('invoice_expense_documents')->default(false); }); + Schema::create('task_statuses', function (Blueprint $table) { + $table->increments('id'); + $table->string('name')->nullable(); + $table->unsignedInteger('company_id')->nullable(); + $table->unsignedInteger('user_id')->nullable(); + $table->boolean('is_deleted')->default(0); + $table->timestamps(6); + $table->softDeletes('deleted_at', 6); + + $table->index(['company_id', 'deleted_at']); + + $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade')->onUpdate('cascade'); + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade'); + }); } /** diff --git a/routes/api.php b/routes/api.php index 711dcc25088e..94c0c395e355 100644 --- a/routes/api.php +++ b/routes/api.php @@ -77,6 +77,10 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a Route::post('tasks/bulk', 'TaskController@bulk')->name('tasks.bulk'); + Route::resource('task_statuses', 'TaskStatusController'); // name = (task_statuses. index / create / show / update / destroy / edit + + Route::post('task_statuses/bulk', 'TaskStatusController@bulk')->name('task_statuses.bulk'); + Route::resource('projects', 'ProjectController'); // name = (projects. index / create / show / update / destroy / edit Route::post('projects/bulk', 'ProjectController@bulk')->name('projects.bulk'); diff --git a/tests/Feature/TaskStatusApiTest.php b/tests/Feature/TaskStatusApiTest.php new file mode 100644 index 000000000000..dc87c43cbec7 --- /dev/null +++ b/tests/Feature/TaskStatusApiTest.php @@ -0,0 +1,151 @@ +makeTestData(); + + Session::start(); + + $this->faker = \Faker\Factory::create(); + + Model::reguard(); + } + + public function testTaskStatusPost() + { + $data = [ + 'name' => $this->faker->firstName, + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/task_statuses', $data); + + $response->assertStatus(200); + } + + public function testTaskStatusPut() + { + $data = [ + 'name' => $this->faker->firstName, + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->put('/api/v1/task_statuses/'.$this->encodePrimaryKey($this->task_status->id), $data); + + $response->assertStatus(200); + } + + public function testTaskStatusGet() + { + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->get('/api/v1/task_statuses/'.$this->encodePrimaryKey($this->task_status->id)); + + $response->assertStatus(200); + } + + public function testTaskStatusNotArchived() + { + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->get('/api/v1/task_statuses/'.$this->encodePrimaryKey($this->task_status->id)); + + $arr = $response->json(); + + $this->assertEquals(0, $arr['data']['archived_at']); + } + + public function testTaskStatusArchived() + { + $data = [ + 'ids' => [$this->encodePrimaryKey($this->task_status->id)], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/task_statuses/bulk?action=archive', $data); + + $arr = $response->json(); + + $this->assertNotNull($arr['data'][0]['archived_at']); + } + + public function testTaskStatusRestored() + { + $data = [ + 'ids' => [$this->encodePrimaryKey($this->task_status->id)], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/task_statuses/bulk?action=restore', $data); + + $arr = $response->json(); + + $this->assertEquals(0, $arr['data'][0]['archived_at']); + } + + public function testTaskStatusDeleted() + { + $data = [ + 'ids' => [$this->encodePrimaryKey($this->task_status->id)], + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/task_statuses/bulk?action=delete', $data); + + $arr = $response->json(); + + $this->assertTrue($arr['data'][0]['is_deleted']); + } +} diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index c6f2f659ce07..d8e945c8566d 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -42,6 +42,7 @@ use App\Models\Quote; use App\Models\QuoteInvitation; use App\Models\RecurringInvoice; use App\Models\Task; +use App\Models\TaskStatus; use App\Models\User; use App\Models\Vendor; use App\Models\VendorContact; @@ -81,6 +82,8 @@ trait MockAccountData public $task; + public $task_status; + public $expense_category; public $cu; @@ -237,6 +240,11 @@ trait MockAccountData 'company_id' => $this->company->id, ]); + $this->task_status = TaskStatus::factory()->create([ + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + ]); + $gs = new GroupSetting; $gs->name = 'Test'; $gs->company_id = $this->client->company_id;