diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php index 8f4b68e9d826..830b17043088 100644 --- a/app/DataMapper/CompanySettings.php +++ b/app/DataMapper/CompanySettings.php @@ -195,9 +195,6 @@ class CompanySettings extends BaseSettings { public $client_online_payment_notification = true; //@todo implement in notifications public $client_manual_payment_notification = true; //@todo implement in notifications - public $system_notifications_slack = ''; - public $system_notifications_email = ''; - /* Company Meta data that we can use to build sub companies*/ public $name = ''; @@ -225,8 +222,6 @@ class CompanySettings extends BaseSettings { public $pdf_variables = []; public static $casts = [ - 'system_notifications_slack' => 'string', - 'system_notifications_email' => 'string', 'portal_design_id' => 'string', 'late_fee_endless_percent' => 'float', 'late_fee_endless_amount' => 'float', diff --git a/app/Factory/DesignFactory.php b/app/Factory/DesignFactory.php new file mode 100644 index 000000000000..5b62958d0041 --- /dev/null +++ b/app/Factory/DesignFactory.php @@ -0,0 +1,31 @@ +user_id = $user_id; + $design->company_id = $company_id; + $design->is_deleted = false; + $design->is_active = true; + $design->is_custom = true; + $design->name = ''; + $design->design = ''; + + return $design; + } +} diff --git a/app/Filters/DesignFilters.php b/app/Filters/DesignFilters.php new file mode 100644 index 000000000000..058979bfac83 --- /dev/null +++ b/app/Filters/DesignFilters.php @@ -0,0 +1,144 @@ +builder; + } + + return $this->builder->where(function ($query) use ($filter) { + $query->where('designs.name', '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 = 'designs'; + $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('designs') + ->join('companies', 'companies.id', '=', 'designs.company_id') + ->where('designs.company_id', '=', $company_id) + //->whereRaw('(designs.name != "" or contacts.first_name != "" or contacts.last_name != "" or contacts.email != "")') // filter out buy now invoices + ->select( + 'designs.id', + 'designs.name', + 'designs.design', + 'designs.created_at', + 'designs.created_at as design_created_at', + 'designs.deleted_at', + 'designs.is_deleted', + 'designs.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', Design::class)) { + $query->where('designs.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/DesignController.php b/app/Http/Controllers/DesignController.php new file mode 100644 index 000000000000..3881467892de --- /dev/null +++ b/app/Http/Controllers/DesignController.php @@ -0,0 +1,490 @@ +listResponse($designs); + } + + /** + * Display the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + * + * + * @OA\Get( + * path="/api/v1/designs/{id}", + * operationId="showDesign", + * tags={"designs"}, + * summary="Shows a design", + * description="Displays a design 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 Design Hashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * 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/Design"), + * ), + * @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(ShowDesignRequest $request, Design $design) + { + return $this->itemResponse($design); + } + + /** + * Show the form for editing the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + * + * + * @OA\Get( + * path="/api/v1/designs/{id}/edit", + * operationId="editDesign", + * tags={"designs"}, + * summary="Shows a design for editting", + * description="Displays a design 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 Design Hashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns the design 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/Design"), + * ), + * @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(EditDesignRequest $request, Design $design) + { + return $this->itemResponse($design); + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param App\Models\Design $design + * @return \Illuminate\Http\Response + * + * + * + * @OA\Put( + * path="/api/v1/designs/{id}", + * operationId="updateDesign", + * tags={"designs"}, + * summary="Updates a design", + * description="Handles the updating of a design 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 Design Hashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns the design 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/Design"), + * ), + * @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(UpdateDesignRequest $request, Design $design) + { + if($request->entityIsDeleted($design)) + return $request->disallowUpdate(); + + $design->fill($request->all()); + $design->save(); + + return $this->itemResponse($design->fresh()); + } + + /** + * Show the form for creating a new resource. + * + * @return \Illuminate\Http\Response + * + * + * + * @OA\Get( + * path="/api/v1/designs/create", + * operationId="getDesignsCreate", + * tags={"designs"}, + * summary="Gets a new blank design 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 design 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/Design"), + * ), + * @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(CreateDesignRequest $request) + { + $design = DesignFactory::create(auth()->user()->company()->id, auth()->user()->id); + + return $this->itemResponse($design); + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + * + * + * + * @OA\Post( + * path="/api/v1/designs", + * operationId="storeDesign", + * tags={"designs"}, + * summary="Adds a design", + * description="Adds an design to a company", + * @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="Returns the saved design 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/Design"), + * ), + * @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(StoreDesignRequest $request) + { + $design = DesignFactory::create(auth()->user()->company()->id, auth()->user()->id); + $design->fill($request->all()); + $design->save(); + + return $this->itemResponse($design->fresh()); + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + * + * + * @OA\Delete( + * path="/api/v1/designs/{id}", + * operationId="deleteDesign", + * tags={"designs"}, + * summary="Deletes a design", + * description="Handles the deletion of a design 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 Design Hashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns a HTTP status", + * @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\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(DestroyDesignRequest $request, Design $design) + { + //may not need these destroy routes as we are using actions to 'archive/delete' + $design->is_deleted = true; + $design->delete(); + $design->save(); + + return response()->json([], 200); + } + + /** + * Perform bulk actions on the list view + * + * @param BulkDesignRequest $request + * @return \Illuminate\Http\Response + * + * + * @OA\Post( + * path="/api/v1/designs/bulk", + * operationId="bulkDesigns", + * tags={"designs"}, + * summary="Performs bulk actions on an array of designs", + * 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", + * 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 Design 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/Design"), + * ), + * @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'); + $designs = Design::withTrashed()->find($this->transformKeys($ids)); + + $designs->each(function ($design, $key) use ($action) { + if (auth()->user()->can('edit', $design)) { + //$this->design_repo->{$action}($design);@todo + } + }); + + return $this->listResponse(Design::withTrashed()->whereIn('id', $this->transformKeys($ids))); + } + + +} diff --git a/app/Http/Controllers/OpenAPI/DesignSchema.php b/app/Http/Controllers/OpenAPI/DesignSchema.php new file mode 100644 index 000000000000..ecfde1bc3cc9 --- /dev/null +++ b/app/Http/Controllers/OpenAPI/DesignSchema.php @@ -0,0 +1,16 @@ +", description="The design HTML"), + * @OA\Property(property="is_custom", type="boolean", example=true, description="Flag to determine if the design is a custom user design"), + * @OA\Property(property="is_active", type="boolean", example=true, description="Flag to determine if the design is available for use"), + * @OA\Property(property="is_deleted", type="boolean", example=true, description="Flag to determine if the design is deleted"), + * @OA\Property(property="created_at", type="number", format="integer", example="134341234234", description="Timestamp"), + * @OA\Property(property="updated_at", type="number", format="integer", example="134341234234", description="Timestamp"), + * @OA\Property(property="deleted_at", type="number", format="integer", example="134341234234", description="Timestamp"), + * ) + */ diff --git a/app/Http/Requests/Design/CreateDesignRequest.php b/app/Http/Requests/Design/CreateDesignRequest.php new file mode 100644 index 000000000000..9865821437d2 --- /dev/null +++ b/app/Http/Requests/Design/CreateDesignRequest.php @@ -0,0 +1,29 @@ +user()->isAdmin(); + } +} diff --git a/app/Http/Requests/Design/DestroyDesignRequest.php b/app/Http/Requests/Design/DestroyDesignRequest.php new file mode 100644 index 000000000000..4a357e4cedb5 --- /dev/null +++ b/app/Http/Requests/Design/DestroyDesignRequest.php @@ -0,0 +1,28 @@ +user()->isAdmin(); + } +} diff --git a/app/Http/Requests/Design/EditDesignRequest.php b/app/Http/Requests/Design/EditDesignRequest.php new file mode 100644 index 000000000000..8d1a480d3fe1 --- /dev/null +++ b/app/Http/Requests/Design/EditDesignRequest.php @@ -0,0 +1,39 @@ +user()->isAdmin(); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + // + ]; + } +} diff --git a/app/Http/Requests/Design/ShowDesignRequest.php b/app/Http/Requests/Design/ShowDesignRequest.php new file mode 100644 index 000000000000..54fb4d072944 --- /dev/null +++ b/app/Http/Requests/Design/ShowDesignRequest.php @@ -0,0 +1,39 @@ +user()->isAdmin(); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + // + ]; + } +} diff --git a/app/Http/Requests/Design/StoreDesignRequest.php b/app/Http/Requests/Design/StoreDesignRequest.php new file mode 100644 index 000000000000..8a12e2dd75a1 --- /dev/null +++ b/app/Http/Requests/Design/StoreDesignRequest.php @@ -0,0 +1,38 @@ +user()->isAdmin(); + } + + public function rules() + { + return [ + //'name' => 'required', + 'name' => 'required|unique:designs,name,null,null,company_id,'.auth()->user()->companyId(), + 'design' => 'required', + ]; + } +} diff --git a/app/Http/Requests/Design/UpdateDesignRequest.php b/app/Http/Requests/Design/UpdateDesignRequest.php new file mode 100644 index 000000000000..5fee92d8b641 --- /dev/null +++ b/app/Http/Requests/Design/UpdateDesignRequest.php @@ -0,0 +1,39 @@ +user()->isAdmin(); + } + + public function rules() + { + return [ + // 'name' => 'unique:designs,name,'.$this->designs->name.',id,company_id,'.auth()->user()->companyId(), + ]; + } +} diff --git a/app/Models/Company.php b/app/Models/Company.php index b3c13f2edb7c..3197636c63e6 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -75,9 +75,11 @@ class Company extends BaseModel 'show_product_details', 'first_day_of_week', 'first_month_of_year', - + 'slack_webhook_url', + 'google_analytics_url', ]; + protected $hidden = [ 'id', 'db', diff --git a/app/Models/Design.php b/app/Models/Design.php index 2c163f2810d5..23733ebd62ea 100644 --- a/app/Models/Design.php +++ b/app/Models/Design.php @@ -11,18 +11,29 @@ namespace App\Models; +use App\Models\Filterable; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class Design extends BaseModel { + use Filterable; + use SoftDeletes; + protected $casts = [ 'design' => 'object', + 'deleted_at' => 'timestamp', 'updated_at' => 'timestamp', 'created_at' => 'timestamp', ]; + protected $fillable = [ + 'name', + 'design', + 'is_active', + ]; + public function company() { return $this->belongsTo(Company::class); diff --git a/app/Models/User.php b/app/Models/User.php index 1f3b617f8636..70be762922e9 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -300,13 +300,9 @@ class User extends Authenticatable implements MustVerifyEmail public function routeNotificationForSlack($notification) { - //todo need to return the company channel here for hosted users - //else the env variable for selfhosted - if(config('ninja.environment') == 'selfhosted') - return config('ninja.notification.slack'); if($this->company()) - return $this->company()->settings->system_notifications_slack; + return $this->company()->slack_webhook_url; } diff --git a/app/Policies/DesignPolicy.php b/app/Policies/DesignPolicy.php new file mode 100644 index 000000000000..d9e43f3d4e74 --- /dev/null +++ b/app/Policies/DesignPolicy.php @@ -0,0 +1,16 @@ +isAdmin() || $user->hasPermission('create_all'); + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index f8ce881292f3..ff18b59beab3 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -16,6 +16,7 @@ use App\Models\Client; use App\Models\Company; use App\Models\CompanyGateway; use App\Models\Credit; +use App\Models\Design; use App\Models\Expense; use App\Models\GroupSetting; use App\Models\Invoice; @@ -32,6 +33,7 @@ use App\Policies\ClientPolicy; use App\Policies\CompanyGatewayPolicy; use App\Policies\CompanyPolicy; use App\Policies\CreditPolicy; +use App\Policies\DesignPolicy; use App\Policies\ExpensePolicy; use App\Policies\GroupSettingPolicy; use App\Policies\InvoicePolicy; @@ -58,6 +60,7 @@ class AuthServiceProvider extends ServiceProvider Activity::class => ActivityPolicy::class, Client::class => ClientPolicy::class, Company::class => CompanyPolicy::class, + Design::class => DesignPolicy::class, Product::class => ProductPolicy::class, Invoice::class => InvoicePolicy::class, Credit::class => CreditPolicy::class, diff --git a/app/Transformers/DesignTransformer.php b/app/Transformers/DesignTransformer.php index 8602811c9603..c46f24828eb0 100644 --- a/app/Transformers/DesignTransformer.php +++ b/app/Transformers/DesignTransformer.php @@ -51,6 +51,7 @@ class DesignTransformer extends EntityTransformer 'updated_at' => (int)$design->updated_at, 'archived_at' => (int)$design->deleted_at, 'created_at' => (int)$design->created_at, + 'is_deleted' => (bool)$design->is_deleted, ]; } diff --git a/database/migrations/2014_10_13_000000_create_users_table.php b/database/migrations/2014_10_13_000000_create_users_table.php index 8aedd8bd5b9b..88c3843d9d82 100644 --- a/database/migrations/2014_10_13_000000_create_users_table.php +++ b/database/migrations/2014_10_13_000000_create_users_table.php @@ -67,7 +67,7 @@ class CreateUsersTable extends Migration $table->string('decimal_separator'); $table->string('code'); $table->boolean('swap_currency_symbol')->default(false); - $table->decimal('exchange_rate', 6, 6)->default(1); + $table->decimal('exchange_rate', 13, 6)->default(1); }); @@ -175,6 +175,9 @@ class CreateUsersTable extends Migration $table->mediumText('custom_fields'); $table->mediumText('settings'); + $table->string('slack_webhook_url'); + $table->string('google_analytics_url'); + $table->timestamps(6); //$table->softDeletes('deleted_at', 6); @@ -1375,6 +1378,7 @@ class CreateUsersTable extends Migration $table->boolean('is_custom')->default(true); $table->boolean('is_active')->default(true); $table->mediumText('design')->nullable(); + $table->boolean('is_deleted')->default(false); $table->timestamps(6); $table->softDeletes('deleted_at', 6); $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade')->onUpdate('cascade'); diff --git a/routes/api.php b/routes/api.php index 4666e046ef70..0b68bcaf477b 100644 --- a/routes/api.php +++ b/routes/api.php @@ -88,6 +88,8 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a Route::post('migrate', 'MigrationController@index')->name('migrate.start'); + Route::resource('designs', 'DesignController');// name = (payments. index / create / show / update / destroy / edit + // Route::resource('users', 'UserController')->middleware('password_protected'); // name = (users. index / create / show / update / destroy / edit Route::get('users', 'UserController@index'); Route::put('users/{user}', 'UserController@update')->middleware('password_protected'); diff --git a/tests/Feature/DesignApiTest.php b/tests/Feature/DesignApiTest.php new file mode 100644 index 000000000000..3b758356bc04 --- /dev/null +++ b/tests/Feature/DesignApiTest.php @@ -0,0 +1,132 @@ +makeTestData(); + + Session::start(); + + $this->faker = \Faker\Factory::create(); + + Model::reguard(); + + } + + + public function testDesignPost() + { + $data = [ + 'name' => $this->faker->firstName, + 'design' => 'withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token + ])->post('/api/v1/designs', $data); + + + $response->assertStatus(200); + + $arr = $response->json(); + + $this->id = $arr['data']['id']; + + $this->assertEquals($data['name'], $arr['data']['name']); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token + ])->get('/api/v1/designs'); + + $response->assertStatus(200); + + $arr = $response->json(); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token + ])->get('/api/v1/designs/'.$this->id); + + $response->assertStatus(200); + + $arr = $response->json(); + + $this->assertEquals($this->id, $arr['data']['id']); + + $data = [ + 'name' => $this->faker->firstName, + 'design' => 'changed' + ]; + + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token + ])->put('/api/v1/designs/'.$this->id, $data); + + $response->assertStatus(200); + + $arr = $response->json(); + + $this->assertEquals($data['name'], $arr['data']['name']); + $this->assertEquals($data['design'], $arr['data']['design']); + + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token + ])->delete('/api/v1/designs/'.$this->id, $data); + + + $response->assertStatus(200); + + $arr = $response->json(); + + $design = Design::whereId($this->decodePrimaryKey($this->id))->withTrashed()->first(); + + $this->assertTrue((bool)$design->is_deleted); + $this->assertGreaterThan(0, $design->deleted_at); + + } + + + + +} \ No newline at end of file