nim_2 #2

Merged
nimtaurel merged 1 commits from nim_1 into master 2024-12-22 13:14:14 +00:00
40 changed files with 2193 additions and 11 deletions

View File

@ -31,7 +31,8 @@
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
"Database\\Seeders\\": "database/seeders/",
"modules\\": "modules/"
}
},
"autoload-dev": {

View File

@ -6,13 +6,13 @@ return [
\A7kz\Platform\Modules\Platform\Core\CoreModule::class,
\A7kz\Platform\Modules\Platform\Navigation\NavigationModule::class,
\A7kz\Platform\Modules\Platform\Acl\AclModule::class,
\A7kz\Platform\Modules\Platform\Home\HomeModule::class,
\modules\Home\HomeModule::class,
\A7kz\Platform\Modules\Platform\Cms\CmsModule::class,
\A7kz\Platform\Modules\Platform\DbBuilder\DbBuilderModule::class,
\A7kz\Platform\Modules\Platform\Auth\AuthModule::class,
\modules\Auth\AuthModule::class,
\A7kz\Platform\Modules\Platform\EventBus\EventBusModule::class,
\A7kz\Platform\Modules\Platform\Schedule\ScheduleModule::class,
\A7kz\Platform\Modules\Platform\UserProfile\UserProfileModule::class,
\modules\UserProfile\UserProfileModule::class,
\A7kz\Platform\Modules\Platform\Flow\FlowModule::class,
\A7kz\Platform\Modules\Platform\Segment\SegmentModule::class,
\A7kz\Platform\Modules\Platform\Company\CompanyModule::class,

View File

@ -0,0 +1,34 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace modules\Auth;
use A7kz\Platform\Modules\Module;
class AuthModule extends Module
{
protected $package = "platform";
public function rootDirectory(): string
{
return __DIR__;
}
public function commands(): array
{
return [
];
}
public function helpers(): array
{
return [
];
}
}

View File

@ -0,0 +1,20 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace App\Modules\Auth\Commands;
use A7kz\Platform\Commands\InstallCommand;
class AuthInstallCommand extends InstallCommand
{
protected $signature = 'platform.auth:install {--install} {--upgrade} {--apps}';
protected $description = 'Модуль авторизации по email';
protected $module_name = 'platform.auth';
protected $module_version = '1.0.0';
}

View File

@ -0,0 +1,57 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace App\Modules\Auth\Http\Controllers;
use A7kz\Platform\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\ConfirmsPasswords;
class ConfirmPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Confirm Password Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password confirmations and
| uses a simple trait to include the behavior. You're free to explore
| this trait and override any functions that require customization.
|
*/
use ConfirmsPasswords;
/**
* Where to redirect users when the intended url fails.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Display the password confirmation view.
*
* @return \Illuminate\View\View
*/
public function showConfirmForm()
{
return view('platform.auth::passwords.confirm');
}
}

View File

@ -0,0 +1,39 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace App\Modules\Auth\Http\Controllers;
use A7kz\Platform\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
class ForgotPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset emails and
| includes a trait which assists in sending these notifications from
| your application to your users. Feel free to explore this trait.
|
*/
use SendsPasswordResetEmails;
/**
* Display the form to request a password reset link.
*
* @return \Illuminate\View\View
*/
public function showLinkRequestForm()
{
return view('platform.auth::passwords.email');
}
}

View File

@ -0,0 +1,182 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace App\Modules\Auth\Http\Controllers;
use A7kz\Accounting\Facades\Accounting;
use A7kz\Platform\Http\Controllers\Controller;
use A7kz\Platform\Models\UniModel;
use A7kz\Platform\Modules\Platform\Acl\Facades\Acl;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function hasTooManyLoginAttempts($request){
$tries = (int)Cache::get('LOGINATTEMP_'.$request->get("username").$request->get("email"));
if($tries > 5 ){
return true;
}
return false;
}
public function setAttemp($request){
$tries = (int)Cache::get('LOGINATTEMP_'.$request->get("username").$request->get("email"));
$tries++;
Cache::put('LOGINATTEMP_'.$request->get("username").$request->get("email"), $tries, 900);
}
public function resetAttempt($request){
Cache::delete('LOGINATTEMP_'.$request->get("username").$request->get("email"));
}
public function login(Request $request)
{
$this->validateLogin($request);
$user = UniModel::model('core_users')->where('email', $request->email)
->orWhere('username', $request->email)->first();
if (!$user) {
return view('platform.auth::login', ['error' => ['email' => trans('auth.email')]]);
}
if (!Hash::check($request->password, $user->password)) {
return view('platform.auth::login', ['error' => ['password' => trans('auth.password')]]);
}
if (method_exists($this, 'hasTooManyLoginAttempts') &&
$this->hasTooManyLoginAttempts($request)) {
return view('platform.auth::login', ['error'=>['email'=>trans('Превышено допустимое количество попыток, попробуйте через 15 минут')]]);
}
if ($this->attemptLogin($request)) {
if ($request->hasSession()) {
$companyId = Acl::getLastActiveCompany(Auth::id()) ? Acl::getLastActiveCompany(Auth::id()) : Acl::getDefaultCompanyId(Auth::id());
$request->session()->put('auth.password_confirmed_at', time());
$request->session()->put('user.company_id', $companyId);
$request->session()->put('user.rights', Acl::getUserRights(Auth::id(),Acl::company_id()));
$request->session()->put('user.segment', Acl::getSegment(Acl::company_id()));
$request->session()->put('user.name', Auth::user()->name);
Accounting::session_extend($request);
$this->resetAttempt($request);
}
return $this->sendLoginResponse($request);
}
$this->setAttemp($request);
// $this->sendFailedLoginResponse($request);
return view('platform.auth::login', ['error'=>['email'=>trans('auth.failed')]]);
}
public function username()
{
$validator = Validator::make(['email' => request()->email], [
'email'=>'required|email'
]);
$field = ($validator->fails()) ? 'username' : 'email';
request()->merge([$field => request()->email]);
return $field;
}
/**
* Show the application's login form.
*
* @return \Illuminate\View\View
*/
public function showLoginForm()
{
return view('platform.auth::login');
}
/**
* Log the user out of the application.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
*/
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
if ($response = $this->loggedOut($request)) {
return $response;
}
return $request->wantsJson()
? new JsonResponse([], 204)
: redirect(lurl("/"));
}
/**
* Send the response after the user was authenticated.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
*/
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->clearLoginAttempts($request);
if ($response = $this->authenticated($request, $this->guard()->user())) {
return $response;
}
return $request->wantsJson()
? new JsonResponse([], 204)
: redirect()->intended(lurl($this->redirectPath()));
}
}

View File

@ -0,0 +1,285 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace App\Modules\Auth\Http\Controllers;
use A7kz\Platform\Helpers\Facade\Helper;
use A7kz\Platform\Http\Controllers\Controller;
use A7kz\Platform\Models\UniModel;
use A7kz\Platform\Modules\Platform\Acl\Facades\Acl;
use A7kz\Platform\Modules\Platform\Segment\Facades\Segment;
use Carbon\Carbon;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
class RegisterCompanyController extends Controller
{
const COWORKER_ROLE = 'coworker';
const DIRECTOR_ROLE = 'director';
const DEFAULT_COMPANY_ID = 0;
public function checkBiniinAjax(Request $request) {
$validation = Validator::make(['biniin' => $request->get('biniin')], $this->getBiniinRules());
if ($validation->fails()) {
return [
'status' => 'error',
'message' => __('Неправильно введен БИН/ИИН')
];
}
$biniin = $validation->validated()['biniin'];
$company = $this->getCompanyByBiniin($biniin);
if ($company) {
return [
'status' => 'success',
'data' => [
'biniin' => $biniin,
'name' => $company->name,
'fullname' => $company->fullname,
'companyExists' => true
]
];
}
else {
$inputData = [
'biniin' => $biniin
];
$minStat = $this->minStat($biniin);
if ($minStat['status'] == 2) {
$inputData['name'] = $minStat['data']['name'];
$inputData['fullname'] = $minStat['data']['name'];
}
return [
'status' => 'success',
'data' => array_merge($inputData, ['registerNewCompany' => true])
];
}
}
public function getCompanyByBiniin(string $biniin) {
return UniModel::model(config('platform.company.tables.company'))
->where('biniin', trim($biniin))
->first();
}
/**
* Store a new company.
*
* @param Request $request
* @return RedirectResponse
* @throws \Exception
*/
public function registerCompany(Request $request) {
if (!Auth::check()) {
return redirect(lurl("/"));
}
$userId = Auth::id();
$biniin = $this->getBiniin($request);
if ($company = $this->getCompanyByBiniin($biniin)) {
return $this->applyToCompany($company);
}
$minStat = $this->minStat($biniin);
[$name, $fullname] = $this->getNameAndFullName($request);
$company = $this->saveCompany([
'name' => $name,
'biniin' => $biniin,
'fullname' => $fullname
]);
$this->saveOrganization($minStat, $company);
Helper::company()->addUserToCompany($userId, $company->id);
Helper::company()->addUserRoleToCompany($userId, $company->id, self::COWORKER_ROLE);
Helper::company()->addUserRoleToCompany($userId, $company->id, self::DIRECTOR_ROLE);
$this->updateSession($company->id);
return redirect(lurl("/"));
}
public function minStat(string $biniin){
if (Cache::has($biniin)) {
return Cache::get($biniin);
}
$i = 0;
while($i < 3) {
try {
$i++;
$res = $this->getMinStatData($biniin);
if($res['status']){
Cache::put($biniin, $res, 10);
return $res;
}
sleep(10);
} catch (\Exception $e){
// ExceptionControl::message($e);
return ["status" => 0, "message" => "Данные не найдены"];
}
}
return ["status" => 0, "message" => "Данные не найдены"];
}
private function getMinStatData(string $biniin){
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://stat.gov.kz/api/juridicalusr/counter/gov/?bin=' . $biniin . '&lang=ru',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_MAXREDIRS => 10,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'Referer: https://stat.gov.kz/jur-search/bin'
),
));
$result = curl_exec($curl);
if (!curl_error($curl)) {
curl_close($curl);
$response = json_decode($result, 1);
if(!is_null($response)) {
if (array_key_exists("error", $response)) {
return ['status' => 0, 'message' => "Ошибка при запросе данных с stat gov kz"];
} else {
if ($response["success"] == true) {
return ['status' => 2, 'data' => $response['obj']];
} else {
if(is_null($response['obj'])){
return ["status" => 1, "message" => "Данные не найдены"];
}
}
}
}
return ["status" => 0, "message" => "Сервер занят"];
} else {
return ["status" => 0, "message" => "Данные не найдены"];
}
}
/**
* @throws \Exception
*/
private function saveCompany(array $data) {
$company = UniModel::model(config('platform.company.tables.company'));
$company->fill(array_merge($data, ['segment' => Segment::random()]));
$company->save();
return $company;
}
private function saveOrganization(array $minStat, $company) {
$data = $this->getOrganizationData($minStat, $company);
$organization = UniModel::model(config('platform.company.tables.organization'));
$organization->fill($data);
$organization->save();
}
private function getBiniin(Request $request) {
return $request->validate($this->getBiniinRules())['biniin'];
}
private function getNameAndFullName(Request $request) {
$data = $request->validate([
'name' => ['required', 'string', 'max:255'],
'fullname' => ['required', 'string', 'max:255'],
]);
return array($data['name'], $data['fullname']);
}
private function getOrganizationData(array $minStat, $company) {
if ($minStat['status'] == 2) {
$organizationData = $minStat['data'];
$organizationData['biniin'] = $organizationData['bin'];
unset($organizationData['bin']);
$organizationData['registerDate'] = Carbon::parse($organizationData['registerDate'])
->format('Y-m-d H:i:s');
unset($organizationData['id']);
}
else {
$organizationData = [
"name" => $company->name,
"biniin" => $company->biniin
];
}
$organizationData['company_id'] = $company->id;
return $organizationData;
}
public function showRegisterCompanyForm() {
return view('platform.auth::registerCompany');
}
public function applyToCompany($company) {
if ($this->issetApplication($company->id)) {
return back()
->withInput([
'name' => $company->name,
'biniin' => $company->biniin,
'fullname' => $company->name
])
->with('companyExists', true)
->withErrors(['company' => __('Your application already exists')]);
}
$addRequest = UniModel::model(config('platform.company.tables.company_request'));
$addRequest->fill([
'user_id' => Auth::id(),
'company_id' => $company->id,
]);
$addRequest->save();
$this->updateSession();
return redirect(lurl("/"));
}
private function issetApplication(int|string $companyId) {
return UniModel::model(config('platform.company.tables.company_request'))
->where('user_id', Auth::id())
->where('company_id', $companyId)
->count();
}
private function getBiniinRules(): array
{
return [
'biniin' => ['required', 'string', 'size:12', 'regex:/^[0-9]+$/']
];
}
private function updateSession(int $companyId = self::DEFAULT_COMPANY_ID): void
{
Session::put('user.company_id', $companyId);
Session::put('user.rights', Acl::getUserRights(Auth::id(), $companyId));
Session::put('user.segment', Acl::getSegment($companyId));
}
}

View File

@ -0,0 +1,111 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace App\Modules\Auth\Http\Controllers;
use A7kz\Platform\Http\Controllers\Controller;
use A7kz\Platform\Models\UniModel;
use App\Models\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* @var string
*/
protected $redirectTo = null;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
$this->redirectTo = lurl('register_company');
}
/**
* Get a validator for an incoming registration request.
*
* @param array $data
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
$usersTable = (new User())->getTable();
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'username' => ['required', 'string', 'max:255', Rule::unique($usersTable, 'username')],
'email' => ['required', 'string', 'email', 'max:255', Rule::unique($usersTable, 'email')],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return User;
*/
protected function create(array $data)
{
$user = new User();
$user->forceFill([
'name' => $data['name'],
'username' => $data['username'],
'email' => $data['email'],
'password' => bcrypt($data['password'])
]);
$user->save();
$userRole = UniModel::model('core_roles')
->where('alias', 'user')
->first();
if (!empty($userRole)) {
$userRoleModel = UniModel::model('core_user_roles');
$userRoleModel->forceFill([
'user_id' => $user->id,
'role_id' => $userRole->id
]);
$userRoleModel->save();
}
return $user;
}
public function showRegistrationForm()
{
return view('platform.auth::register');
}
}

View File

@ -0,0 +1,54 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace App\Modules\Auth\Http\Controllers;
use A7kz\Platform\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request;
class ResetPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords;
/**
* Where to redirect users after resetting their password.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Display the password reset view for the given token.
*
* If no token is present, display the link request form.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function showResetForm($lang, $token, Request $request)
{
return view('platform.auth::passwords.reset')->with(
['token' => $token, 'email' => $request->email]
);
}
}

View File

@ -0,0 +1,63 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace App\Modules\Auth\Http\Controllers;
use A7kz\Platform\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\VerifiesEmails;
use Illuminate\Http\Request;
class VerificationController extends Controller
{
/*
|--------------------------------------------------------------------------
| Email Verification Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling email verification for any
| user that recently registered with the application. Emails may also
| be re-sent if the user didn't receive the original email message.
|
*/
use VerifiesEmails;
/**
* Where to redirect users after verification.
*
* @var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('signed')->only('verify');
$this->middleware('throttle:6,1')->only('verify', 'resend');
}
/**
* Show the email verification notice.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
*/
public function show(Request $request)
{
return $request->user()->hasVerifiedEmail()
? redirect($this->redirectPath())
: view('platform.auth::verify');
}
}

View File

@ -0,0 +1,5 @@
<?php
return [
'enabled' => true,
'views' => true,
];

View File

@ -0,0 +1,34 @@
<?php
Route::get("/login", [App\Modules\Auth\Http\Controllers\LoginController::class,'showLoginForm'])->name('loginForm');
Route::post("/login", [App\Modules\Auth\Http\Controllers\LoginController::class,'login'])->name('login');
Route::any("/logout", [App\Modules\Auth\Http\Controllers\LoginController::class,'logout'])->name("logout");
Route::get('/register',[App\Modules\Auth\Http\Controllers\RegisterController::class,'showRegistrationForm'])->name('registerForm');
Route::post('/register',[App\Modules\Auth\Http\Controllers\RegisterController::class,'register'])->name('register');
Route::group([
'middleware' => ['auth', 'web'],
], function () {
Route::get('register_company/',[App\Modules\Auth\Http\Controllers\RegisterCompanyController::class,'showRegisterCompanyForm'])
->name('registerCompanyForm');
Route::post('register_company/',[App\Modules\Auth\Http\Controllers\RegisterCompanyController::class,'registerCompany'])
->name('registerCompany');
Route::post('register_company/check_biniin_ajax',[App\Modules\Auth\Http\Controllers\RegisterCompanyController::class,'checkBiniinAjax'])
->name('checkBiniinAjax');
});
Route::get('/password/reset', [App\Modules\Auth\Http\Controllers\ForgotPasswordController::class,'showLinkRequestForm'])->name('password.request');
Route::post('/password/email',[App\Modules\Auth\Http\Controllers\ForgotPasswordController::class,'sendResetLinkEmail'])->name('password.email');
Route::get('/password/reset/{token}',[App\Modules\Auth\Http\Controllers\ResetPasswordController::class,'showResetForm'])->name('password.reset');
Route::post('/password/reset',[App\Modules\Auth\Http\Controllers\ResetPasswordController::class,'reset'])->name('password.update');
Route::get('password/confirm',[App\Modules\Auth\Http\Controllers\ConfirmPasswordController::class,'showConfirmForm'])->name('password.confirm');
Route::post('password/confirm',[App\Modules\Auth\Http\Controllers\ConfirmPasswordController::class,'confirm']);
Route::get('email/verify',[App\Modules\Auth\Http\Controllers\VerificationController::class,'show'])->name('verification.notice');
Route::get('email/verify/{id}/{hash}',[App\Modules\Auth\Http\Controllers\VerificationController::class,'verify'])->name('verification.verify');
Route::post('email/resend',[App\Modules\Auth\Http\Controllers\VerificationController::class,'resend'])->name('verification.resend');

View File

@ -0,0 +1,92 @@
@extends('layouts.app')
@section('content')
<div class="log-reg-container">
<div class="log-reg-content">
<div class="d-flex justify-content-between">
{{-- <a href="/" class="btn btn-light"><i class="bi bi-chevron-left me-1"></i> На главную</a>--}}
<div class="item-nav-lang">
<div class="dropdown">
<span class="dropdown-trigger" data-bs-toggle="dropdown">
<i class="bi bi-translate"></i>
{{__(app()->getLocale())}}
</span>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
@if(app()->getLocale() != \A7kz\Platform\Enums\Languages::Ru)
<li><a class="dropdown-item"
href="{{ \A7kz\Platform\Modules\Platform\Translate\Helpers\TranslateHelper::changeUrlLanguage(\A7kz\Platform\Enums\Languages::Ru) }}"><span>@lang('ru')</span></a>
</li>
@endif
@if(app()->getLocale() != \A7kz\Platform\Enums\Languages::Kz)
<li><a class="dropdown-item"
href="{{ \A7kz\Platform\Modules\Platform\Translate\Helpers\TranslateHelper::changeUrlLanguage(\A7kz\Platform\Enums\Languages::Kz) }}"><span>@lang('kz')</span></a>
</li>
@endif
</ul>
</div>
</div>
{{-- <img src="{{asset('img/logo.svg')}}" alt="logo" class="logo-log">--}}
<div class="main-logo main-logo-login"><span style="font-weight: 600">ERP.ESEP</span><br><p>{{ __('ОБЛАЧНАЯ БУХГАЛТЕРИЯ') }}</p></div>
</div>
{{-- <span>{{ __('Login') }}</span>--}}
<form method="POST" action="{{ lurl('login') }}">
@csrf
<div class="form-group">
<label for="email" class="form-label">{{ __('Логин') }}</label>
<input id="email" type="text" name="email" value="{{ old('email') }}"
class="form-control @if(isset($error['email']) || isset($error['username'])) is-invalid @endif"
required autocomplete="email" autofocus>
@if(isset($error['email']))
<div class="invalid-feedback form-text text-danger"
role="alert">{{ $error['email'] }}</div>
@endif
@if(isset($error['username']))
<div class="invalid-feedback form-text text-danger"
role="alert">{{ $error['username'] }}</div>
@endif
</div>
<div class="form-group">
<label for="password" class="form-label">{{ __('Password') }}</label>
<input id="password" type="password" class="form-control @if(isset($error['password'])) is-invalid @endif"
name="password" required autocomplete="current-password">
@if(isset($error['password']))
<div class="invalid-feedback form-text text-danger" role="alert">{{ $error['password'] }}</div>
@endif
</div>
<div class="mb-3 form-check">
<input class="form-check-input" type="checkbox" name="remember"
id="remember" {{ old('remember') ? 'checked' : '' }}>
<label class="form-check-label" for="remember"> {{ __('Remember Me') }}</label>
</div>
<div class="d-flex align-items-center justify-content-center">
<button type="submit" class="btn btn-success">
{{ __('Войти') }}
</button>
@if (Route::has('password.request'))
<a class="btn btn-link" href="{{ lurl('/password/reset') }}">
{{ __('Forgot Your Password?') }}
</a>
@endif
</div>
</form>
<div class="contact-us-wrapper d-flex flex-column justify-content-center align-items-center">
<div class="phone-cont d-flex flex-column align-items-center mb-1">
<p><i class="bi bi-telephone-fill"></i> +7 7172 97-20-76</p>
<p>8 800 004-04-33 <span>({{ __('звонок бесплатный') }})</span></p>
</div>
<div class="line"></div>
<div class="d-flex flex-row justify-content-between" style="column-gap: 10px">
<div class="d-flex flex-column align-items-start justify-content-start">
<p><i class="bi bi-envelope-fill"></i> support@esep.kz</p>
</div>
<div class="d-flex flex-column align-items-end justify-content-center">
<p><i class="bi bi-clock-fill"></i> {{ __('Часы работы') }}</p>
<p>{{ __('ПН—ПТ') }} 9:00—18:00</p>
</div>
</div>
</div>
</div>
</div>
@endsection

View File

@ -0,0 +1,49 @@
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Confirm Password') }}</div>
<div class="card-body">
{{ __('Please confirm your password before continuing.') }}
<form method="POST" action="{{ lurl('password/confirm') }}">
@csrf
<div class="row mb-3">
<label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Confirm Password') }}
</button>
@if (Route::has('password.request'))
<a class="btn btn-link" href="{{ lurl('/password/reset') }}">
{{ __('Forgot Your Password?') }}
</a>
@endif
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection

View File

@ -0,0 +1,47 @@
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Reset Password') }}</div>
<div class="card-body">
@if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
@endif
<form method="POST" action="{{ lurl('password/email') }}">
@csrf
<div class="row mb-3">
<label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-0">
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Send Password Reset Link') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection

View File

@ -0,0 +1,65 @@
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Reset Password') }}</div>
<div class="card-body">
<form method="POST" action="{{ lurl('/password/reset') }}">
@csrf
<input type="hidden" name="token" value="{{ $token }}">
<div class="row mb-3">
<label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
<div class="col-md-6">
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ $email ?? old('email') }}" required autocomplete="email" autofocus>
@error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-3">
<label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
<div class="col-md-6">
<input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">
@error('password')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-3">
<label for="password-confirm" class="col-md-4 col-form-label text-md-end">{{ __('Confirm Password') }}</label>
<div class="col-md-6">
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
</div>
</div>
<div class="row mb-0">
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Reset Password') }}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection

View File

@ -0,0 +1,95 @@
@extends('layouts.app')
@section('content')
<div class="log-reg-container">
<div class="log-reg-content">
<div class="d-flex justify-content-between">
{{-- <a href="/" class="btn btn-light"><i class="bi bi-chevron-left me-1"></i> На главную</a>--}}
<div class="item-nav-lang">
<div class="dropdown">
<span class="dropdown-trigger" data-bs-toggle="dropdown">
<i class="bi bi-translate"></i>
{{__(app()->getLocale())}}
</span>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
@if(app()->getLocale() != \A7kz\Platform\Enums\Languages::Ru)
<li><a class="dropdown-item"
href="{{ \A7kz\Platform\Modules\Platform\Translate\Helpers\TranslateHelper::changeUrlLanguage(\A7kz\Platform\Enums\Languages::Ru) }}"><span>@lang('ru')</span></a>
</li>
@endif
@if(app()->getLocale() != \A7kz\Platform\Enums\Languages::Kz)
<li><a class="dropdown-item"
href="{{ \A7kz\Platform\Modules\Platform\Translate\Helpers\TranslateHelper::changeUrlLanguage(\A7kz\Platform\Enums\Languages::Kz) }}"><span>@lang('kz')</span></a>
</li>
@endif
@if(app()->getLocale() != \A7kz\Platform\Enums\Languages::En)
<li><a class="dropdown-item"
href="{{ \A7kz\Platform\Modules\Platform\Translate\Helpers\TranslateHelper::changeUrlLanguage(\A7kz\Platform\Enums\Languages::En) }}"><span>@lang('en')</span></a>
</li>
@endif
</ul>
</div>
</div>
{{-- <img src="{{asset('img/logo.svg')}}" alt="logo" class="logo-log">--}}
<h5>ПланФакт - УЧЕТ</h5>
</div>
{{-- <span>{{ __('Register') }}</span>--}}
{{-- <form method="POST" action="{{ lurl('/register') }}">--}}
@csrf
<div class="form-group">
<label for="name" class="col-form-label">{{ __('Name') }}</label>
<input id="name" type="text" class="form-control @error('name') is-invalid @enderror"
name="name" value="{{ old('name') }}" required autocomplete="name" autofocus>
@error('name')
<div class="invalid-feedback form-text text-danger" role="alert">{{ $message }}</div>
@enderror
</div>
<div class="form-group">
<label for="email" class="col-form-label">{{ __('Email Address') }}</label>
<input id="email" type="email" class="form-control @error('email') is-invalid @enderror"
name="email" value="{{ old('email') }}" required autocomplete="email">
@error('email')
<div class="invalid-feedback form-text text-danger" role="alert">{{ $message }}</div>
@enderror
</div>
<div class="form-group">
<label for="username" class="col-form-label">{{ __('Username') }}</label>
<input id="username" type="text" class="form-control @error('username') is-invalid @enderror"
name="username" value="{{ old('username') }}" required autocomplete="username" autofocus>
@error('username')
<div class="invalid-feedback form-text text-danger" role="alert">{{ $message }}</div>
@enderror
</div>
<div class="form-group">
<label for="password" class="col-form-label">{{ __('Password') }}</label>
<input id="password" type="password"
class="form-control @error('password') is-invalid @enderror" name="password" required
autocomplete="new-password">
@error('password')
<div class="invalid-feedback form-text text-danger" role="alert">{{ $message }}</div>
@enderror
</div>
<div class="form-group">
<label for="password-confirm" class="col-form-label">{{ __('Confirm Password') }}</label>
<input id="password-confirm" type="password" class="form-control" name="password_confirmation"
required autocomplete="new-password">
</div>
<button type="submit" class="btn btn-success mt-4">
{{ __('Register') }}
</button>
</form>
@if (Route::has('login'))
<div class="log-reg-bottom">
<span>Уже есть аккаунт?</span>
<a href="{{ lurl('/login') }}">{{ __('Login') }}</a>
</div>
@endif
</div>
</div>
@endsection

View File

@ -0,0 +1,129 @@
@extends('layouts.app')
@section('content')
@include('ajax-loader')
<div class="log-reg-container">
<div class="card">
<a href="/" class="btn btn-primary return"><i class="bi bi-arrow-left me-1"></i> Вернуться назад</a>
<div class="card-header">
<span>{{ __('Register Company') }}</span>
<img src="{{asset('img/logo-white.png')}}" alt="logo" class="logo-log">
</div>
<div class="card-body">
<form id="register-company-form" method="POST" action="{{ lurl('register_company/') }}">
@csrf
<div class="form-group">
<label for="biniin" class="col-form-label">{{ __('BIN/IIN') }}</label>
<input id="biniin" type="text" class="form-control @error('biniin') is-invalid @enderror"
name="biniin" value="{{ old('biniin') }}" required autocomplete="biniin" autofocus
oninput="checkBiniinLength(event)"
>
@error('biniin')
<div class="invalid-feedback form-text text-danger" role="alert">{{ $message }}</div>
@enderror
</div>
<div class="form-group" id="name-group" hidden>
<label for="name" class="col-form-label">{{ __('Name') }}</label>
<input id="name" type="text" class="form-control @error('name') is-invalid @enderror"
name="name" value="{{ old('name') }}" required
autocomplete="name" autofocus>
@error('name')
<div class="invalid-feedback form-text text-danger" role="alert">{{ $message }}</div>
@enderror
</div>
<div class="form-group" id="fullname-group" hidden>
<label for="fullname" class="col-form-label">{{ __('Full name') }}</label>
<input id="fullname" type="text" class="form-control @error('fullname') is-invalid @enderror"
name="fullname" value="{{ old('fullname') }}" required
autocomplete="fullname" autofocus>
@error('fullname')
<div class="invalid-feedback form-text text-danger" role="alert">{{ $message }}</div>
@enderror
</div>
<button type="submit" class="btn btn-light mt-4" id="submit-button" style="visibility: hidden">
{{ __('Register Company') }}
</button>
</form>
</div>
</div>
</div>
@endsection
@push('scripts-bottom')
<script>
document.getElementById("ajax-loader-on").click();
function checkBiniinLength(event) {
console.log(event.target.value)
let valueLength = event.target.value.length;
if (valueLength === 12) {
let form = document.getElementById('register-company-form');
binAjax(form.querySelectorAll('input[name="biniin"]')[0].value);
}
}
function binAjax(biniin) {
$.ajax({
method:'post',
type:'post',
dataType: 'json',
data: {
'biniin': biniin
},
url: '{{lurl('register_company/check_biniin_ajax')}}',
success: function(response){
if (response.status === 'error') {
alert(response.message);
}
else {
setDataToForm(response.data)
}
},
error: function(){
alert("Ошибка сервера");
}
});
}
function setDataToForm(data) {
let form = document.getElementById('register-company-form');
let biniinField = form.querySelectorAll('#biniin')[0];
let nameField = form.querySelectorAll('#name')[0];
let fullnameField = form.querySelectorAll('#fullname')[0];
let submitButton = form.querySelectorAll('#submit-button')[0];
document.getElementById('name-group').removeAttribute('hidden');
document.getElementById('fullname-group').removeAttribute('hidden');
submitButton.removeAttribute('hidden');
biniinField.value = data.biniin;
if ('name' in data) {
nameField.value = data.name;
fullnameField.value = data.fullname;
}
else {
nameField.value = '';
fullnameField.value = '';
}
if ('companyExists' in data) {
nameField.setAttribute('disabled', true);
fullnameField.setAttribute('disabled', true);
submitButton.innerHTML = '{{ __('Add Request') }}';
}
else {
nameField.removeAttribute('disabled');
fullnameField.removeAttribute('disabled');
submitButton.innerHTML = '{{ __('Register Company') }}';
}
submitButton.removeAttribute('style');
}
</script>
@endpush

View File

@ -0,0 +1,28 @@
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Verify Your Email Address') }}</div>
<div class="card-body">
@if (session('resent'))
<div class="alert alert-success" role="alert">
{{ __('A fresh verification link has been sent to your email address.') }}
</div>
@endif
{{ __('Before proceeding, please check your email for a verification link.') }}
{{ __('If you did not receive the email') }},
<form class="d-inline" method="POST" action="{{ lurl('email/resend') }}">
@csrf
<button type="submit" class="btn btn-link p-0 m-0 align-baseline">{{ __('click here to request another') }}</button>.
</form>
</div>
</div>
</div>
</div>
</div>
@endsection

View File

@ -0,0 +1,32 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace App\Modules\Home\Applications;
use A7kz\Platform\Models\UniModel;
use A7kz\Platform\Modules\Platform\Acl\Facades\Acl;
use A7kz\Platform\Modules\Platform\Core\Services\Application\BaseApplication;
use Illuminate\Support\Facades\Auth;
class Home extends BaseApplication
{
public function __construct($config)
{
parent::__construct($config);
}
public function default()
{
if(Auth::check()){
return redirect(lurl('app/accounting.main'));
} else {
return redirect(lurl('login'));
}
}
}

View File

@ -0,0 +1,44 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace App\Modules\Home\Commands;
use A7kz\Platform\Commands\InstallCommand;
use A7kz\Platform\Modules\Platform\Acl\Facades\Acl;
use A7kz\Platform\Modules\Platform\Core\Facades\Core;
class HomeInstallCommand extends InstallCommand
{
protected $signature = "home:install {--install} {--upgrade} {--apps}";
protected $description = "Главная страница";
protected $module_name = "home";
protected $module_version = "1.0.0";
public function seeds()
{
Acl::addRoleAction("guest","app.home");
Acl::addRoleAction("user","app.home");
}
public function apps()
{
Core::registerApp(
"app.home",
json_encode([
"name"=>"app.home",
"title"=>"Home",
"type"=>"custom",
"class"=>"App.Modules.Home.Applications.Home",
"module"=>"App.Modules.Home"
]),
"Главная страница",
'[]'
);
}
}

View File

@ -0,0 +1,29 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace modules\Home;
use A7kz\Platform\Modules\Module;
use A7kz\Platform\Modules\Platform\Home\Commands\HomeInstallCommand;
class HomeModule extends Module
{
protected $package = "platform";
public function rootDirectory(): string
{
return __DIR__;
}
public function commands(): array
{
return [
HomeInstallCommand::class
];
}
}

View File

@ -0,0 +1,9 @@
<?php
return [
'enabled'=>true,
'storage' => [
'driver' => 'local',
'root' => storage_path('app/home')
]
];

View File

@ -0,0 +1,166 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace App\Modules\UserProfile\Applications;
use A7kz\Accounting\Facades\Accounting;
use A7kz\Platform\Models\UniModel;
use A7kz\Platform\Modules\Platform\Acl\Facades\Acl;
use A7kz\Platform\Modules\Platform\Core\Services\Application\BaseApplication;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Validator;
class UserProfileApplication extends BaseApplication
{
public function __construct($config)
{
parent::__construct($config);
}
public function default()
{
return view('platform.user_profile::profile', ['user'=>Auth::user()])->render();
}
public function action_changecompany(){
$isAdmin = false;
if (Acl::isHasRole('admin')) {
$isAdmin = true;
}
$company = UniModel::model('core_company_users')
->where("company_id", Request::get('pk'))
->where("user_id", Auth::id());
$hasAccess = $company->count();
if(!$isAdmin && !$hasAccess){
return redirect($this->getPath());
}
UniModel::model('core_company_users')
->where("user_id", Auth::id())->update(['is_last_company' => false]);
$company->update(['is_last_company' => true]);
Request::session()->put('user.rights', Acl::getUserRights(Auth::id(),Request::get('pk')));
Request::session()->put('user.company_id', Request::get('pk'));
$organization = Accounting::organization(Acl::company_id());
if(is_null($organization)){
$company = Acl::activeCompany();
$organization = UniModel::model("acc_organizations", Acl::connection());
$organization->id = Acl::company_id();
$organization->biniin = $company->biniin;
$organization->name_ru = $company->name;
$organization->name_kz = $company->name;
$organization->code_gu = "0";
$organization->fullname_ru = $company->fullname;
$organization->fullname_kz = $company->fullname;
$organization->taxation_id = 1;
$organization->organization_type = 'OSH'; // Школа
$organization->company_id = Acl::company_id();
$organization->save();
}
$orgdata = [
'name_kz' => $organization->name_kz ?? '',
'name_ru' => $organization->name_ru ?? '',
'biniin' => $organization->biniin ?? '',
'calc_via_id' => $organization->calc_via_id ?? '',
'code_gu' => $organization->code_gu ?? '',
'organization_type' => $organization->organization_type ?? '',
];
Request::session()->put('organization', $orgdata);
Request::session()->reflash();
Request::session()->put('user.grid_filters', []);
Request::session()->put('user.tabs', null);
return redirect($this->getPath());
}
public function action_edit(){
$user = Auth::user();
$request = Request::all();
if (Request::has('submit')) {
$rules = [
'name' => ['required', 'string', 'max:255'],
'phone' => ['required', 'string', 'max:255'],
'about' => ['nullable', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255'],
'profile_image' => ['nullable', 'image', 'mimes:jpg,png,jpeg', 'max:2048']
];
$validator = Validator::make(Request::all(), $rules);
if ($validator->fails()) {
$errors = $validator->errors();
foreach ($rules as $field => $rule) {
if ($errors->has($field)) {
switch ($field) {
case 'name':
$this->set_message('Неправильно заполнено поле "Имя"', 'error');
break;
case 'phone':
$this->set_message('Неправильно заполнено поле "Телефон"', 'error');
break;
case 'about':
$this->set_message('Неправильно заполнено поле "О себе"', 'error');
break;
case 'profile_image':
$this->set_message('Неправильный формат картинки', 'error');
break;
case 'email':
$this->set_message('Неправильно заполнено поле "Почта"', 'error');
break;
}
}
}
return view('platform.user_profile::user_edit', [
'user' => Auth::user(),
'app' => $this
])->render();
}
$profile_image = '';
if (Request::hasFile('profile_image')) {
$imagePath = 'profile_images/' . auth()->user()->profile_image;
if (File::exists($imagePath)) {
File::delete($imagePath);
}
$profile_image = $request['profile_image']->store('profile_images', 'public');
}
$user->name = $request['name'];
$user->phone = $request['phone'];
$user->about = $request['about'];
$user->email = $request['email'];
$user->profile_image = $profile_image ?? auth()->user()->profile_image;
if (!empty($request['new_password'])) {
if (!Hash::check($request['current_password'], $user->password)) {
$this->set_message('Неверный текущий пароль', 'error');
return view('platform.user_profile::user_edit', [
'user' => Auth::user(),
'app' => $this
])->render();
}
$user->password = Hash::make($request['new_password']);
}
$user->save();
$this->set_message('Данные сохранены', 'success', false);
}
return view('platform.user_profile::user_edit', [
'user' => Auth::user(),
'app' => $this
])->render();
}
}

View File

@ -0,0 +1,66 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace App\Modules\UserProfile\Commands;
use A7kz\Platform\Commands\InstallCommand;
use A7kz\Platform\Helpers\Facade\Helper;
use A7kz\Platform\Modules\Platform\Acl\Facades\Acl;
use A7kz\Platform\Modules\Platform\Core\Facades\Core;
class UserProfileInstallCommand extends InstallCommand
{
protected $signature = 'user.profile:install {--install} {--upgrade} {--apps}';
protected $description = 'Модуль профиль пользователя';
protected $module_name = 'user.profile';
protected $module_version = '1.0.1';
public function seeds(){
$json = \Storage::disk('a7platform')->get('user/profile.json');
$app = json_decode($json, 1);
$app['class'] = "App.Modules.UserProfile.Applications.UserProfileApplication";
$json = json_encode($app);
Core::registerApp(
"user.profile",
$json,
"Профиль пользователя",
'[]'
);
Acl::addRoleAction("user","user.profile");
Acl::addRoleAction("user","user.profile","edit");
Acl::addRoleAction("user","user.profile","changecompany");
}
public function apps()
{
$this->seeds();
}
public function upgrade()
{
$module = Helper::install()->module($this->module_name);
if(!is_null($module) && !$module->lock_version) {
switch ($module->module_version){
case "1.0.0":
Acl::addRoleAction("user","user.profile","changecompany");
$this->output->writeln($this->description.": v1.0.1");
Helper::install()->installModule($module->module_name,'1.0.1');
Helper::install()->setHistory($module->module_name, $module->module_version,'1.0.1', 'Переключение между организациями');
$module->refresh();
break;
default:
break;
}
}
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
* Copyright (c) 2023.
*
* A.Сапаргалиев
* ТОО "Дизайн лаборатория А7"
* Астана
*/
namespace modules\UserProfile;
use A7kz\Platform\Modules\Module;
class UserProfileModule extends Module
{
protected $package = "platform";
public function rootDirectory(): string
{
return __DIR__;
}
public function commands(): array
{
return [
];
}
public function helpers(): array
{
return [
];
}
}

View File

@ -0,0 +1,5 @@
<?php
return [
'enabled' => true,
'views' => true,
];

View File

@ -0,0 +1,34 @@
<?php
use \A7kz\Platform\Modules\Platform\Acl\Facades\Acl;
?>
@if(Auth::check() && Acl::company_id())
<?php
$active = Acl::activeCompany();
?>
<div class="card mb-3 mb-xl-0">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between mb-3">
<h5 class="m-0">{{$active->name}}</h5>
<a class="btn btn-light">@lang("Редактировать")</a>
</div>
<ul class="list-group">
<li class="list-group-item d-flex align-items-center justify-content-between"><b>@lang('БИН/ИИН')</b>
<span>{{$active->biniin}}</span></li>
<li class="list-group-item d-flex align-items-center justify-content-between">
<b>@lang('Сегмент данных')</b> <span>{{$active->segment}}</span></li>
@if(Acl::isHasRole("director"))
<li class="list-group-item d-flex align-items-center justify-content-between"><a
href="{{lurl("/app/company.requests")}}" class="btn btn-primary">Заявки на добавления</a>
</li>
@endif
</ul>
<div class="d-flex justify-content-end mt-3">
<button type="button" class="btn btn-outline-orange" onclick="$('#companyListDiv').show()">
@lang("Выбрать/Добавить другую организацию")
</button>
</div>
</div>
</div>
@endif

View File

@ -0,0 +1,93 @@
<?php
use \A7kz\Platform\Modules\Platform\Acl\Facades\Acl;
use A7kz\Platform\Models\UniModel;
?>
@if(Auth::check() && Acl::company_id())
<?php
$orgs = [];
$isAdmin = Acl::isHasRole('admin');
if ($isAdmin) {
$companies = UniModel::model('core_companies')->get();
} else {
$companies = Acl::myCompanies();
}
$orgs_rows = \A7kz\Accounting\Facades\Accounting::my_organizations(\Illuminate\Support\Facades\Request::get('filter'));
foreach ($orgs_rows as $orgs_row){
$orgs[$orgs_row->id] = $orgs_row;
}
$active = Acl::activeCompany();
?>
<div class="card" id="companyListDiv" @if(!\Illuminate\Support\Facades\Request::has('filter')) style="display: none; min-width: 505px" @endif >
<div class="card-header-custom row d-flex justify-content-start align-items-center" style="column-gap: 0.5rem">
<div class="col-3 col-lg-1"><button class="btn btn-light filter-trigger">Фильтр</button></div><div class="card-title col-8 col-lg-10 d-flex justify-content-start align-items-center px-0">@lang("Мои организации") <button type="button" class="companylist-close" onclick="$('#companyListDiv').hide()"><i class="bi bi-x"></i></button></div>
</div>
<div class="card" id="filter_block" style="border: none; box-shadow: none; display: none">
<div class="card-body">
<form method="get" id="company_list_filter">
<div class="row d-flex flex-row justify-content-between align-items-center" style="font-size: 0.8rem">
<div class="form-group col-3">
<label>БИН/ИИН</label>
<input type="text" class="form-control" name="filter[bin]" id="biniin" value="{{\Illuminate\Support\Facades\Request::get('filter')['bin'] ?? ''}}">
</div>
<div class="form-group col-3">
<label>Код ГУ</label>
<input type="text" class="form-control" name="filter[code_gu]" id="code_gu" value="{{\Illuminate\Support\Facades\Request::get('filter')['code_gu'] ?? ''}}">
</div>
<div class="form-group col-6">
<label>Наименование</label>
<input type="text" class="form-control" name="filter[name]" id="org_name" value="{{\Illuminate\Support\Facades\Request::get('filter')['name'] ?? ''}}">
</div>
<div class="form-group">
<button type="submit" class="btn btn-success" id="filter_submit"><i class="bi bi-search"></i>Искать</button>
<button type="submit" class="btn btn-danger" id="filter_reset" onclick="resetForm()"><i class="bi bi-x-circle"></i>Сброс</button>
</div>
</div>
</form>
</div>
</div>
<div class="card-body">
<table class="table table-striped">
@foreach($companies as $company)
@if((empty($active) || $active->id != $company->id) && isset($orgs[$company->id]))
<tr>
<td>{{$company->biniin}}</td>
<td>{{$orgs[$company->id]->code_gu ?? ''}}</td>
<td>{{ $orgs[$company->id]->{'name_'.app()->getLocale()} ?? $company->name}}</td>
<td>
<a href="{{lurl('/app/user.profile/changecompany')."?pk=".$company->id}}"
class="btn btn-success">@lang("Выбрать")</a>
</td>
</tr>
@endif
@endforeach
</table>
</div>
<div class="card-footer">
<a href="{{lurl('/register_company')}}" class="btn btn-light">@lang("Добавить новую")</a>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">@lang("Отмена")</button>
</div>
</div>
@else
<div class="card mb-4 mb-lg-0">
<div class="card-body p-3">
<div class="h5">@lang('Организация')</div>
<div>
<div class="d-flex mb-2">
<a class="btn btn-primary">@lang("Добавить организацию")</a>
</div>
</div>
</div>
</div>
@endif
<script>
function resetForm() {
$('#code_gu').val('');
$('#biniin').val('');
$('#org_name').val('');
}
</script>

View File

@ -0,0 +1,32 @@
<div class="card mb-4 mb-md-0">
<div class="card-body">
<p class="mb-4">@lang('Мои сообщения')
</p>
<p class="mb-1" style="font-size: .77rem;">Web Design</p>
<div class="progress rounded" style="height: 5px;">
<div class="progress-bar" role="progressbar" style="width: 80%" aria-valuenow="80"
aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="mt-4 mb-1" style="font-size: .77rem;">Website Markup</p>
<div class="progress rounded" style="height: 5px;">
<div class="progress-bar" role="progressbar" style="width: 72%" aria-valuenow="72"
aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="mt-4 mb-1" style="font-size: .77rem;">One Page</p>
<div class="progress rounded" style="height: 5px;">
<div class="progress-bar" role="progressbar" style="width: 89%" aria-valuenow="89"
aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="mt-4 mb-1" style="font-size: .77rem;">Mobile Template</p>
<div class="progress rounded" style="height: 5px;">
<div class="progress-bar" role="progressbar" style="width: 55%" aria-valuenow="55"
aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="mt-4 mb-1" style="font-size: .77rem;">Backend API</p>
<div class="progress rounded mb-2" style="height: 5px;">
<div class="progress-bar" role="progressbar" style="width: 66%" aria-valuenow="66"
aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</div>
<br>

View File

@ -0,0 +1,68 @@
<div class="row">
<div class="col-12 col-md-6">
@include('platform.user_profile::user',['name'=>$user->name, 'about'=>$user->about])
</div>
<div class="col-12 col-md-6">
@if(config('platform.company.enabled'))
@include('platform.user_profile::company')
@endif
</div>
<div class="col-12 col-md-12">
@if(config('platform.company.enabled'))
@include('platform.user_profile::companylist')
@endif
</div>
</div>
{{--<?php--}}
{{--$roles = \A7kz\Platform\Models\UniModel::model('core_roles')->get();--}}
{{--$rows = \A7kz\Platform\Models\UniModel::model('core_applications')->get(['name','description']);--}}
{{--$applications = [];--}}
{{--foreach ($rows as $row){--}}
{{-- $applications[$row->name] = $row->description;--}}
{{--}--}}
{{--$actions = [--}}
{{-- 'default'=>'Просмотр списка значений',--}}
{{-- 'add'=>'Создание записи',--}}
{{-- 'edit' =>'Редактирование записи',--}}
{{-- 'delete'=>'Удаление записи',--}}
{{-- 'show' => 'Просмотр записи',--}}
{{-- 'open'=>'Открыть документ',--}}
{{-- 'edit_tree' => 'Редактировать дерево',--}}
{{-- 'terminate_document_impact' => 'Прекращение документа',--}}
{{-- 'stop_deductions' => 'прекратить отчисления',--}}
{{-- 'excel' => 'Генерация excel документа',--}}
{{-- 'report' => 'Отчет',--}}
{{-- 'print' => 'Версия для печати',--}}
{{-- 'lock' => 'Блокировка',--}}
{{-- 'generate' => 'Сгенерировать',--}}
{{-- 'accept' => 'Применить',--}}
{{-- 'decline' => 'Отклонить',--}}
{{-- 'save' => 'Сохранить запись',--}}
{{--]--}}
{{--?>--}}
{{--<div class="row">--}}
{{-- <div class="col-12">--}}
{{-- <table class="table">--}}
{{-- <tr>--}}
{{-- <th>Роль</th><th>Приложение</th><th>Доступное действие</th>--}}
{{-- </tr>--}}
{{-- @foreach ($roles as $role)--}}
{{-- <?php--}}
{{-- $apps = json_decode($role->actions, true);--}}
{{-- ?>--}}
{{-- @foreach($apps as $app_code=>$app)--}}
{{-- @foreach($app as $action=>$v)--}}
{{-- <tr>--}}
{{-- <td>{{$role->name}}</td><td>{{$applications[$app_code] ?? $app_code}}</td><td>{{$actions[$action] ?? $action}}</td>--}}
{{-- </tr>--}}
{{-- @endforeach--}}
{{-- @endforeach--}}
{{-- @endforeach--}}
{{-- </table>--}}
{{-- </div>--}}
{{--</div>--}}

View File

@ -0,0 +1,32 @@
<div class="card mb-4 mb-md-0">
<div class="card-body">
<p class="mb-4">@lang("Мои задачи")
</p>
<p class="mb-1" style="font-size: .77rem;">Web Design</p>
<div class="progress rounded" style="height: 5px;">
<div class="progress-bar" role="progressbar" style="width: 80%" aria-valuenow="80"
aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="mt-4 mb-1" style="font-size: .77rem;">Website Markup</p>
<div class="progress rounded" style="height: 5px;">
<div class="progress-bar" role="progressbar" style="width: 72%" aria-valuenow="72"
aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="mt-4 mb-1" style="font-size: .77rem;">One Page</p>
<div class="progress rounded" style="height: 5px;">
<div class="progress-bar" role="progressbar" style="width: 89%" aria-valuenow="89"
aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="mt-4 mb-1" style="font-size: .77rem;">Mobile Template</p>
<div class="progress rounded" style="height: 5px;">
<div class="progress-bar" role="progressbar" style="width: 55%" aria-valuenow="55"
aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p class="mt-4 mb-1" style="font-size: .77rem;">Backend API</p>
<div class="progress rounded mb-2" style="height: 5px;">
<div class="progress-bar" role="progressbar" style="width: 66%" aria-valuenow="66"
aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</div>
<br>

View File

@ -0,0 +1,28 @@
<div class="row">
<div class="col">
<div class="card mb-4">
<div class="card-body">
@php($profile_image = auth()->user()->profile_image)
<div class="d-flex">
<div class="profile-img">
<img src="@if($profile_image == null) {{asset("img/avatar.png") }} @else {{ asset("storage/$profile_image") }} @endif" id="image_preview_container" alt="profile_image">
</div>
<div class="ms-3">
<h5 class="mb-0">{{$name}}</h5>
<p class="text-muted mb-3">{{$about}}</p>
<div class="form-group mb-2">
<label>@lang("Электронная почта")</label>
<p class="text-muted m-0">{{$user->email}} @if(is_null($user->email_verified_at)) <a href="#" class="btn btn-outline-primary">@lang("Подтвердить")</a> @endif</p>
</div>
<div class="form-group mb-2">
<label>@lang("Телефон")</label>
<p class="text-muted m-0">{{$user->phone}} @if(is_null($user->phone_verified_at)) <a href="#" class="btn btn-outline-primary">@lang("Подтвердить")</a> @endif</p>
</div>
<a href="{{lurl('app/user.profile/edit')."?pk=".$user->id}}" class="btn btn-light">@lang("Редактировать")</a>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,94 @@
{!! $app->show_message() !!}
<style>
.bi-key:before {
content: "\f44f";
transform: rotate(135deg);
font-size: 20px;
}
</style>
<x-component name="Tabs" />
<form method="POST" enctype="multipart/form-data" id="profile_setup_frm" action="{{lurl('app/user.profile/edit')}}">
<div class="global-actions">
<div class="left-content">
<h4 class="global-title">{{__("Настройки пользователя")}}</h4>
</div>
<div class="right-content">
<button name="submit" value="save" class="btn btn-success" type="submit"><i class="bi bi-save"></i>{{__(" Сохранить")}}</button>
<button name="back" value="back" class="btn btn-primary" id="back_btn" type="button"><i class="bi bi-back"></i>{{__(" Закрыть")}}</button>
</div>
</div>
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-2 d-flex align-items-center justify-content-center">
<div class="d-flex flex-column align-items-center text-center">
@php($profile_image = auth()->user()->profile_image)
<label class="img-profile-edit">
<img src="@if($profile_image == null) {{ asset("img/avatar.png") }} @else {{ asset("storage/$profile_image") }} @endif" id="image_preview_container">
<input type="file" name="profile_image" id="profile_image" class="d-none">
</label>
</div>
</div>
@csrf
<div class="col-md-10 mt-3">
<div class="d-flex justify-content-center align-items-center flex-column">
<label class="labels"><span style="width: 20px; height: 20px; background-color: #E58F65; color: white; border-radius: 50%; padding: 5px 7px"><i class="bi bi-pen"></i></span>{{__(" Редактировать профиль")}}</label>
</div>
<div class="row mt-3">
<div class="col-md-6 mb-3">
<label class="labels">{{__("Имя")}}</label>
<input type="text" name="name" class="form-control" placeholder="first name" value="{{ auth()->user()->name }}">
</div>
<div class="col-md-6 mb-3">
<label class="labels"> {{__("Почта")}}</label>
<input type="text" name="email" class="form-control" value="{{ auth()->user()->email }}" placeholder="Email">
</div>
</div>
<div class="row mt-2">
<div class="col-md-6 mb-3">
<label class="labels">{{__("Телефон")}}</label>
<input type="text" name="phone" id="phone" class="form-control mobile" placeholder="" value="{{ auth()->user()->phone }}">
</div>
<div class="col-md-6 mb-3">
<label class="labels">{{__("О себе")}}</label>
<input type="text" name="about" class="form-control" value="{{ auth()->user()->about }}" placeholder="About">
</div>
</div>
<div class="d-flex justify-content-center align-items-center flex-column mt-3">
<label class="labels"><span style="width: 20px; height: 20px; background-color: #E58F65; color: white; border-radius: 50%; padding: 7px 5px 3px 5px"><i class="bi bi-key"></i></span>{{__(" Сменить пароль")}}</label>
</div>
<div class="row mt-2">
<div class="col-md-6 mb-3">
<label for="current_password" class="col-form-label">{{ __('Текущий пароль') }}</label>
<input id="current_password" type="password" class="form-control" name="current_password" autocomplete="off-current-password">
</div>
<div class="col-md-6 mb-3">
<label for="new_password" class="col-form-label">{{ __('Новый пароль') }}</label>
<input id="new_password" type="password" class="form-control" name="new_password" autocomplete="new-password">
</div>
</div>
</div>
</div>
</div>
</div>
</form>
<x-component name="Js.After" :params="['app'=>$app]" />
<script>
$(document).ready(function(){
$("#profile_image").change(function(){
let reader = new FileReader();
reader.onload = (e) => {
$("#image_preview_container").attr('src', e.target.result);
}
reader.readAsDataURL(this.files[0]);
})
document.getElementById('back_btn').addEventListener('click', function() {
let current_url = window.location.href;
window.location.href = current_url.replace('/edit', '');
});
})
</script>

View File

@ -0,0 +1,26 @@
<div class="row">
<div class="col-md-12">
<div class="card mb-4">
<div class="card-body">
<div class="row">
<div class="form-group">
<label>@lang("Электронная почта")</label>
<div>
<p class="text-muted mb-0">{{$user->email}} @if(!!is_null($user->email_verified_at))<span class="badge-outline success">Подтвержден</span>@else <a href="#" class="btn btn-outline-primary">@lang("Подтвердить")</a> @endif</p>
</div>
</div>
</div>
<hr>
<div class="row">
<div class="form-group">
<label>@lang("Телефон")</label>
<div>
<p class="text-muted mb-0">{{$user->phone}} @if(!!is_null($user->phone_verified_at))<span class="badge-outline success">Подтвержден</span>@else <a href="#" class="btn btn-outline-primary">@lang("Подтвердить")</a> @endif</p>
</div>
</div>
</div>
<hr>
</div>
</div>
</div>
</div>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -10,13 +10,13 @@
background-color: white;
transition: .3s all ease;
box-shadow: $box-shadow;
.container {
.nav-container {
display: flex;
flex-wrap: inherit;
align-items: center;
justify-content: space-between;
padding-left: 0;
margin-left: 1rem;
padding: 0;
margin: 0 1rem;
.left-cont {
display: flex !important;
justify-content: center;

View File

@ -32,7 +32,7 @@
@include('platform.navigation::sidebar')
<main class="main-container">
<header class="navbar">
<div class="container py-1">
<div class="nav-container py-1">
<div class="left-cont d-flex">
<i class="bi bi-list menu-trigger"></i>
<a class="navbar-brand">
@ -103,7 +103,7 @@
@endguest
</div>
</header>
<p>ляля</p>
@yield('content')
</main>
</div>
</div>