diff --git a/config/auth.php b/config/auth.php index 8cf3b05..037923d 100644 --- a/config/auth.php +++ b/config/auth.php @@ -187,6 +187,10 @@ 'documents.*.type' => ['string', 'required'], 'documents.*.back' => ['string', 'required_without:documents.*.front'], 'documents.*.front' => ['string', 'required_without:documents.*.back'], + 'employer' => ['array', 'nullable'], + 'employer.employer_name' => ['string', 'nullable'], + 'employer.company_address' => ['string', 'nullable'], + 'employer.company_registration_number' => ['string', 'nullable'], 'proof_of_address' => ['array', 'required', 'min:1'], 'proof_of_address.*.type' => ['string', 'required'], 'proof_of_address.*.back' => ['string', 'required_without:proof_of_address.*.front'], @@ -238,6 +242,22 @@ //'middleware' => ['auth:sanctum'], 'middleware' => [], + /* + |-------------------------------------------------------------------------- + | Constant + |-------------------------------------------------------------------------- + | + | This value will be used across systems where a constant instance is needed + */ + + 'proof_of_address_types' => [ + 'tenancy_contract' => 'Tenancy Contract', + 'utility_bill' => 'Utility Bill', + 'bank_statement' => 'Bank Statement', + 'credit_card_statement' => 'Credit Card Statement', + 'telephone_bill' => 'Telephone Bill', + ], + /* |-------------------------------------------------------------------------- | Repositories diff --git a/routes/api.php b/routes/api.php index b16610f..1fba9a1 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,6 +1,7 @@ name('verify-otp'); Route::middleware(config('fintech.auth.middleware'))->group(function () { - Route::get('users/user-status', [UserController::class, 'userStatus'])->name('users.user-status'); Route::apiResource('users', UserController::class); Route::post('users/{user}/restore', [UserController::class, 'restore'])->name('users.restore'); Route::post('users/{user}/reset/{field}', [UserController::class, 'reset']) @@ -74,10 +74,18 @@ Route::apiResource('audits', \Fintech\Auth\Http\Controllers\AuditController::class)->only('index', 'show', 'destroy'); - Route::apiResource('id-doc-types', \Fintech\Auth\Http\Controllers\IdDocTypeController::class); - Route::post('id-doc-types/{id_doc_type}/restore', [\Fintech\Auth\Http\Controllers\IdDocTypeController::class, 'restore'])->name('id-doc-types.restore'); + Route::apiResource('id-doc-types', IdDocTypeController::class); + Route::post('id-doc-types/{id_doc_type}/restore', [IdDocTypeController::class, 'restore'])->name('id-doc-types.restore'); //DO NOT REMOVE THIS LINE// }); }); + Route::prefix('dropdown')->name('auth.')->group(function () { + Route::get('id-doc-types', [IdDocTypeController::class, 'dropdown'])->name('id-doc-types.dropdown'); + Route::get('roles', [RoleController::class, 'dropdown'])->name('roles.dropdown'); +// Route::get('teams', [\Fintech\Auth\Http\Controllers\TeamController::class, 'dropdown'])->name('teams.dropdown'); + Route::get('users', [UserController::class, 'dropdown'])->name('users.dropdown'); + Route::get('user-statuses', [UserController::class, 'statusDropdown'])->name('user-statuses.dropdown'); + Route::get('proof-of-addresses', [UserController::class, 'proofOfAddressDropdown'])->name('user-proof-of-address.dropdown'); + }); } diff --git a/src/Http/Controllers/AuthenticatedController.php b/src/Http/Controllers/AuthenticatedController.php index f0df513..79f954f 100644 --- a/src/Http/Controllers/AuthenticatedController.php +++ b/src/Http/Controllers/AuthenticatedController.php @@ -53,7 +53,7 @@ public function login(LoginRequest $request): LoginResource|JsonResponse if ($attemptUser->wrong_password > config('fintech.auth.password_threshold', 10)) { \Fintech\Auth\Facades\Auth::user()->update($attemptUser->getKey(), [ - 'status' => UserStatus::InActive->value, + 'status' => UserStatus::Suspended->value, ]); AccountFreezed::dispatch($attemptUser); diff --git a/src/Http/Controllers/IdDocTypeController.php b/src/Http/Controllers/IdDocTypeController.php index b0683a5..7c9b7f8 100644 --- a/src/Http/Controllers/IdDocTypeController.php +++ b/src/Http/Controllers/IdDocTypeController.php @@ -7,6 +7,8 @@ use Fintech\Core\Exceptions\UpdateOperationException; use Fintech\Core\Exceptions\DeleteOperationException; use Fintech\Core\Exceptions\RestoreOperationException; +use Fintech\Core\Http\Requests\DropDownRequest; +use Fintech\Core\Http\Resources\DropDownCollection; use Fintech\Core\Traits\ApiResponseTrait; use Fintech\Auth\Facades\Auth; use Fintech\Auth\Http\Resources\IdDocTypeResource; @@ -283,4 +285,41 @@ public function import(ImportIdDocTypeRequest $request): JsonResponse return $this->failed($exception->getMessage()); } } + + /** + * @param DropDownRequest $request + * @return DropDownCollection|JsonResponse + */ + public function dropdown(DropDownRequest $request): DropDownCollection|JsonResponse + { + try { + $filters = $request->all(); + + $label = 'name'; + + $attribute = 'id'; + + if (!empty($filters['label'])) { + $label = $filters['label']; + unset($filters['label']); + } + + if (!empty($filters['attribute'])) { + $attribute = $filters['attribute']; + unset($filters['attribute']); + } + + $entries = Auth::idDocType()->list($filters)->map(function ($entry) use ($label, $attribute) { + return [ + 'label' => $entry->{$label} ?? 'name', + 'attribute' => $entry->{$attribute} ?? 'id' + ]; + }); + + return new DropDownCollection($entries); + + } catch (Exception $exception) { + return $this->failed($exception->getMessage()); + } + } } diff --git a/src/Http/Controllers/RoleController.php b/src/Http/Controllers/RoleController.php index 8f89598..840f406 100644 --- a/src/Http/Controllers/RoleController.php +++ b/src/Http/Controllers/RoleController.php @@ -16,6 +16,8 @@ use Fintech\Core\Exceptions\RestoreOperationException; use Fintech\Core\Exceptions\StoreOperationException; use Fintech\Core\Exceptions\UpdateOperationException; +use Fintech\Core\Http\Requests\DropDownRequest; +use Fintech\Core\Http\Resources\DropDownCollection; use Fintech\Core\Traits\ApiResponseTrait; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Http\JsonResponse; @@ -339,4 +341,41 @@ public function import(ImportRoleRequest $request): RoleCollection|JsonResponse return $this->failed($exception->getMessage()); } } + + /** + * @param DropDownRequest $request + * @return DropDownCollection|JsonResponse + */ + public function dropdown(DropDownRequest $request): DropDownCollection|JsonResponse + { + try { + $filters = $request->all(); + + $label = 'name'; + + $attribute = 'id'; + + if (!empty($filters['label'])) { + $label = $filters['label']; + unset($filters['label']); + } + + if (!empty($filters['attribute'])) { + $attribute = $filters['attribute']; + unset($filters['attribute']); + } + + $entries = Auth::role()->list($filters)->map(function ($entry) use ($label, $attribute) { + return [ + 'attribute' => $entry->{$attribute} ?? 'id', + 'label' => $entry->{$label} ?? 'name', + ]; + })->toArray(); + + return new DropDownCollection($entries); + + } catch (Exception $exception) { + return $this->failed($exception->getMessage()); + } + } } diff --git a/src/Http/Controllers/TeamController.php b/src/Http/Controllers/TeamController.php index d58c227..6c1922b 100644 --- a/src/Http/Controllers/TeamController.php +++ b/src/Http/Controllers/TeamController.php @@ -14,6 +14,8 @@ use Fintech\Core\Exceptions\RestoreOperationException; use Fintech\Core\Exceptions\StoreOperationException; use Fintech\Core\Exceptions\UpdateOperationException; +use Fintech\Core\Http\Requests\DropDownRequest; +use Fintech\Core\Http\Resources\DropDownCollection; use Fintech\Core\Traits\ApiResponseTrait; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Http\JsonResponse; @@ -276,4 +278,41 @@ public function import(ImportTeamRequest $request): TeamCollection|JsonResponse return $this->failed($exception->getMessage()); } } + + /** + * @param DropDownRequest $request + * @return DropDownCollection|JsonResponse + */ + public function dropdown(DropDownRequest $request): DropDownCollection|JsonResponse + { + try { + $filters = $request->all(); + + $label = 'name'; + + $attribute = 'id'; + + if (!empty($filters['label'])) { + $label = $filters['label']; + unset($filters['label']); + } + + if (!empty($filters['attribute'])) { + $attribute = $filters['attribute']; + unset($filters['attribute']); + } + + $entries = Auth::team()->list($filters)->map(function ($entry) use ($label, $attribute) { + return [ + 'label' => $entry->{$label} ?? 'name', + 'attribute' => $entry->{$attribute} ?? 'id' + ]; + }); + + return new DropDownCollection($entries); + + } catch (Exception $exception) { + return $this->failed($exception->getMessage()); + } + } } diff --git a/src/Http/Controllers/UserController.php b/src/Http/Controllers/UserController.php index e08196f..8b024ab 100644 --- a/src/Http/Controllers/UserController.php +++ b/src/Http/Controllers/UserController.php @@ -16,6 +16,8 @@ use Fintech\Core\Exceptions\RestoreOperationException; use Fintech\Core\Exceptions\StoreOperationException; use Fintech\Core\Exceptions\UpdateOperationException; +use Fintech\Core\Http\Requests\DropDownRequest; +use Fintech\Core\Http\Resources\DropDownCollection; use Fintech\Core\Traits\ApiResponseTrait; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Http\JsonResponse; @@ -266,6 +268,7 @@ public function export(IndexUserRequest $request): JsonResponse * * @lrd:end * + * @param ImportUserRequest $request * @return UserCollection|JsonResponse */ public function import(ImportUserRequest $request): UserCollection|JsonResponse @@ -291,6 +294,7 @@ public function import(ImportUserRequest $request): UserCollection|JsonResponse * @lrd:end * * @param int|string $id + * @param string $field * @param UserAuthResetRequest $request * @return JsonResponse */ @@ -326,16 +330,79 @@ public function reset(string|int $id, string $field, UserAuthResetRequest $reque } /** - * @return array + * @param DropDownRequest $request + * @return DropDownCollection|JsonResponse */ - public function userStatus(): array + public function dropdown(DropDownRequest $request): DropDownCollection|JsonResponse { - $userStatus = UserStatus::cases(); - $array = []; - foreach($userStatus as $case) { - $array[$case->value] = $case->name; + try { + $filters = $request->all(); + + $label = 'name'; + + $attribute = 'id'; + + if (!empty($filters['label'])) { + $label = $filters['label']; + unset($filters['label']); + } + + if (!empty($filters['attribute'])) { + $attribute = $filters['attribute']; + unset($filters['attribute']); + } + + $entries = Auth::user()->list($filters)->map(function ($entry) use ($label, $attribute) { + return [ + 'label' => $entry->{$label} ?? 'name', + 'attribute' => $entry->{$attribute} ?? 'id' + ]; + }); + + return new DropDownCollection($entries); + + } catch (Exception $exception) { + return $this->failed($exception->getMessage()); } - return $array; + } + /** + * @param DropDownRequest $request + * @return DropDownCollection|JsonResponse + */ + public function statusDropdown(DropDownRequest $request): DropDownCollection|JsonResponse + { + try { + $entries = collect(); + + foreach (UserStatus::toArray() as $key => $status) { + $entries->push(['label' => $status, 'attribute' => $key]); + } + + return new DropDownCollection($entries); + + } catch (Exception $exception) { + return $this->failed($exception->getMessage()); + } + } + + /** + * @param DropDownRequest $request + * @return DropDownCollection|JsonResponse + */ + public function proofOfAddressDropdown(DropDownRequest $request): DropDownCollection|JsonResponse + { + try { + $entries = collect(); + + foreach (config('fintech.auth.proof_of_address_types', []) as $key => $status) { + $entries->push(['label' => $status, 'attribute' => $key]); + } + + return new DropDownCollection($entries); + + } catch (Exception $exception) { + return $this->failed($exception->getMessage()); + } } } diff --git a/src/Http/Requests/RegistrationRequest.php b/src/Http/Requests/RegistrationRequest.php index 8002dce..f173b91 100644 --- a/src/Http/Requests/RegistrationRequest.php +++ b/src/Http/Requests/RegistrationRequest.php @@ -23,50 +23,54 @@ public function authorize(): bool public function rules(): array { $rules = config('fintech.auth.register_rules', [ - //user - 'name' => ['required', 'string', 'min:2', 'max:255'], - 'mobile' => ['required', 'string', 'min:10'], - 'email' => ['required', 'string', 'email:rfc,dns', 'min:2', 'max:255'], - 'pin' => ['required', 'string', 'min:4', 'max:16'], - 'app_version' => ['nullable', 'string'], - 'fcm_token' => ['nullable', 'string'], - 'language' => ['nullable', 'string'], - 'currency' => ['nullable', 'string'], + //user + 'name' => ['required', 'string', 'min:2', 'max:255'], + 'mobile' => ['required', 'string', 'min:10'], + 'email' => ['required', 'string', 'email:rfc,dns', 'min:2', 'max:255'], + 'pin' => ['required', 'string', 'min:4', 'max:16'], + 'app_version' => ['nullable', 'string'], + 'fcm_token' => ['nullable', 'string'], + 'language' => ['nullable', 'string'], + 'currency' => ['nullable', 'string'], - //profile - 'father_name' => ['string', 'nullable'], - 'mother_name' => ['string', 'nullable'], - 'gender' => ['string', 'nullable'], - 'marital_status' => ['string', 'nullable'], - 'occupation' => ['string', 'nullable'], - 'source_of_income' => ['string', 'nullable'], - 'id_type' => ['string', 'nullable'], - 'id_no' => ['string', 'nullable'], - 'id_issue_country' => ['string', 'nullable'], - 'id_expired_at' => ['string', 'nullable'], - 'id_issue_at' => ['string', 'nullable'], - 'photo' => ['string', 'nullable'], - 'documents' => ['array', 'required', 'min:1'], - 'documents.*.type' => ['string', 'required'], - 'documents.*.back' => ['string', 'required_without:documents.*.front'], - 'documents.*.front' => ['string', 'required_without:documents.*.back'], - 'proof_of_address' => ['array', 'required', 'min:1'], - 'proof_of_address.*.type' => ['string', 'required'], - 'proof_of_address.*.front' => ['string', 'required_without:proof_of_address.*.back'], - 'proof_of_address.*.back' => ['string', 'required_without:proof_of_address.*.front'], - 'date_of_birth' => ['date', 'nullable'], - 'permanent_address' => ['string', 'nullable'], - 'city_id' => ['integer', 'nullable'], - 'state_id' => ['integer', 'nullable'], - 'country_id' => ['integer', 'nullable'], - 'post_code' => ['string', 'nullable'], - 'present_address' => ['string', 'nullable'], - 'present_city_id' => ['integer', 'nullable'], - 'present_state_id' => ['integer', 'nullable'], - 'present_country_id' => ['integer', 'nullable'], - 'present_post_code' => ['string', 'nullable'], - 'nationality' => ['string', 'nullable'], - ]); + //profile + 'father_name' => ['string', 'nullable'], + 'mother_name' => ['string', 'nullable'], + 'gender' => ['string', 'nullable'], + 'marital_status' => ['string', 'nullable'], + 'occupation' => ['string', 'nullable'], + 'source_of_income' => ['string', 'nullable'], + 'id_type' => ['string', 'nullable'], + 'id_no' => ['string', 'nullable'], + 'id_issue_country' => ['string', 'nullable'], + 'id_expired_at' => ['string', 'nullable'], + 'id_issue_at' => ['string', 'nullable'], + 'photo' => ['string', 'nullable'], + 'documents' => ['array', 'required', 'min:1'], + 'documents.*.type' => ['string', 'required'], + 'documents.*.back' => ['string', 'required_without:documents.*.front'], + 'documents.*.front' => ['string', 'required_without:documents.*.back'], + 'employer' => ['array', 'nullable'], + 'employer.company_name' => ['string', 'nullable'], + 'employer.company_address' => ['string', 'nullable'], + 'employer.company_registration_number' => ['string', 'nullable'], + 'proof_of_address' => ['array', 'required', 'min:1'], + 'proof_of_address.*.type' => ['string', 'required'], + 'proof_of_address.*.front' => ['string', 'required_without:proof_of_address.*.back'], + 'proof_of_address.*.back' => ['string', 'required_without:proof_of_address.*.front'], + 'date_of_birth' => ['date', 'nullable'], + 'permanent_address' => ['string', 'nullable'], + 'city_id' => ['integer', 'nullable'], + 'state_id' => ['integer', 'nullable'], + 'country_id' => ['integer', 'nullable'], + 'post_code' => ['string', 'nullable'], + 'present_address' => ['string', 'nullable'], + 'present_city_id' => ['integer', 'nullable'], + 'present_state_id' => ['integer', 'nullable'], + 'present_country_id' => ['integer', 'nullable'], + 'present_post_code' => ['string', 'nullable'], + 'nationality' => ['string', 'nullable'], + ]); $rules[config('fintech.auth.auth_field', 'login_id')] = config('fintech.auth.auth_field_rules', ['required', 'string', 'min:6', 'max:255']); diff --git a/src/Http/Requests/StoreUserRequest.php b/src/Http/Requests/StoreUserRequest.php index d307e5c..58fd387 100644 --- a/src/Http/Requests/StoreUserRequest.php +++ b/src/Http/Requests/StoreUserRequest.php @@ -50,6 +50,10 @@ public function rules(): array 'documents.*.type' => ['string', 'required'], 'documents.*.back' => ['string', 'required_without:documents.*.front'], 'documents.*.front' => ['string', 'required_without:documents.*.back'], + 'employer' => ['array', 'nullable'], + 'employer.employer_name' => ['string', 'nullable'], + 'employer.company_address' => ['string', 'nullable'], + 'employer.company_registration_number' => ['string', 'nullable'], 'proof_of_address' => ['array', 'required', 'min:1'], 'proof_of_address.*.type' => ['string', 'required'], 'proof_of_address.*.front' => ['string', 'required_without:proof_of_address.*.back'], diff --git a/src/Http/Requests/UpdateUserRequest.php b/src/Http/Requests/UpdateUserRequest.php index ea97cdc..6a70959 100644 --- a/src/Http/Requests/UpdateUserRequest.php +++ b/src/Http/Requests/UpdateUserRequest.php @@ -50,6 +50,10 @@ public function rules(): array 'documents.*.type' => ['string', 'required'], 'documents.*.back' => ['string', 'required_without:documents.*.front'], 'documents.*.front' => ['string', 'required_without:documents.*.back'], + 'employer' => ['array', 'nullable'], + 'employer.company_name' => ['string', 'nullable'], + 'employer.company_address' => ['string', 'nullable'], + 'employer.company_registration_number' => ['string', 'nullable'], 'proof_of_address' => ['array', 'required', 'min:1'], 'proof_of_address.*.type' => ['string', 'required'], 'proof_of_address.*.back' => ['string', 'required_without:proof_of_address.*.front'], diff --git a/src/Http/Resources/UserCollection.php b/src/Http/Resources/UserCollection.php index be3e80e..fa3e250 100644 --- a/src/Http/Resources/UserCollection.php +++ b/src/Http/Resources/UserCollection.php @@ -2,13 +2,44 @@ namespace Fintech\Auth\Http\Resources; +use Carbon\Carbon; use Fintech\Auth\Models\Profile; use Fintech\Core\Facades\Core; use Fintech\Core\Supports\Constant; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\ResourceCollection; +use Illuminate\Support\Collection; use Spatie\MediaLibrary\MediaCollections\Models\Media; +/** + * @property mixed $roles + */ +/** + * Class UserResource + * @package Fintech\Auth\Http\Resources + * + * @property-read int $id + * @property-read string $name + * @property-read string $mobile + * @property-read string $email + * @property-read string $login_id + * @property-read string $status + * @property-read string $language + * @property-read string $currency + * @property-read string $app_version + * @property-read float $total_balance + * @property-read Collection $roles + * @property-read Profile|null $profile + * @property-read Carbon $email_verified_at + * @property-read Carbon $mobile_verified_at + * @property-read Carbon $created_at + * @property-read Carbon $updated_at + * @property mixed $parent + * @property mixed $parent_id + * @property mixed $links + * @method getKey() + * @method getFirstMediaUrl(string $string) + */ class UserCollection extends ResourceCollection { /** @@ -17,7 +48,7 @@ class UserCollection extends ResourceCollection * @param Request $request * @return array */ - public function toArray($request) + public function toArray(Request $request): array { return $this->collection->map(function ($user) { $data = [ @@ -33,12 +64,12 @@ public function toArray($request) 'language' => $user->language ?? null, 'currency' => $user->currency ?? null, 'app_version' => $user->app_version ?? null, - 'roles' => ($user->roles) ? $user->roles->pluck('name')->toArray() : [], + 'roles' => ($user->roles) ? $user->roles->toArray() : [], 'links' => $user->links, 'created_at' => $user->created_at, 'updated_at' => $user->updated_at, ]; - + unset($data['roles'][0]['links'],$data['roles'][0]['pivot'],$data['roles'][0]['permissions']); /** * @var Profile $profile */ @@ -111,7 +142,7 @@ public function with(Request $request): array ]; } - private function formatMediaCollection($collection) + private function formatMediaCollection($collection): array { $data = []; diff --git a/src/Http/Resources/UserResource.php b/src/Http/Resources/UserResource.php index d7da7e4..9d75d7a 100644 --- a/src/Http/Resources/UserResource.php +++ b/src/Http/Resources/UserResource.php @@ -30,6 +30,11 @@ * @property-read Carbon $mobile_verified_at * @property-read Carbon $created_at * @property-read Carbon $updated_at + * @property mixed $parent + * @property mixed $parent_id + * @property mixed $links + * @method getKey() + * @method getFirstMediaUrl(string $string) */ class UserResource extends JsonResource { @@ -39,7 +44,7 @@ class UserResource extends JsonResource * @param Request $request * @return array */ - public function toArray($request) + public function toArray(Request $request): array { $data = [ 'id' => $this->getKey() ?? null, @@ -54,11 +59,12 @@ public function toArray($request) 'language' => $this->language ?? null, 'currency' => $this->currency ?? null, 'app_version' => $this->app_version ?? null, - 'roles' => ($this->roles) ? $this->roles->pluck('name', 'id')->toArray() : [], + 'roles' => ($this->roles) ? $this->roles->toArray() : [], 'links' => $this->links, 'created_at' => $this->created_at, 'updated_at' => $this->updated_at, ]; + unset($data['roles'][0]['links'],$data['roles'][0]['pivot'],$data['roles'][0]['permissions']); /** * @var Profile $profile @@ -113,7 +119,7 @@ public function toArray($request) return array_merge($data, $profile_data); } - private function formatMediaCollection($collection) + private function formatMediaCollection($collection): array { $data = []; diff --git a/src/Services/ProfileService.php b/src/Services/ProfileService.php index b9e6a38..6554f15 100644 --- a/src/Services/ProfileService.php +++ b/src/Services/ProfileService.php @@ -123,6 +123,10 @@ private function formatDataFromInput($inputs, bool $forCreate = false) unset($data['nationality']); } + if (isset($inputs['employer'])) { + $data['user_profile_data']['employer'] = $inputs['employer']; + unset($data['employer']); + } return $data; }