companies and advisories modules added

master
Константин 2023-07-31 12:39:47 +03:00
parent fcfc985671
commit 4d7e3a5583
71 changed files with 3300 additions and 22 deletions

View File

@ -0,0 +1,72 @@
<?php
namespace App\Http\Controllers\Api\Advisories;
use App\Http\Controllers\Controller;
use App\Models\Advisories\Advisory;
use App\Services\Filters\FiltersService;
use App\Transformers\Advisories\AdvisoryTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class AdvisoriesController extends Controller {
protected Advisory $model;
public function __construct(Advisory $model) {
$this->model = $model;
}
public function index(Request $request): JsonResponse {
$query = $this->model->query();
$paginator = $query->paginate(config('app.pagination_limit'));
return fractal($paginator, new AdvisoryTransformer())->respond();
}
public function show(Request $request, $id): JsonResponse {
$query = $this->model->query();
$model = ($id === 'main') ? $query->where(['is_main' => 1])->firstOrFail() : $query->byUuid($id)->firstOrFail();
return fractal($model, new AdvisoryTransformer())->respond();
}
public function siblings(Request $request, $id): JsonResponse {
$filters = collect($request->has('filters') ? json_decode($request->get('filters'), true) : []);
$query = $this->model->query();
$model = ($id === 'main') ? $query->where(['is_main' => 1])->firstOrFail() : $query->byUuid($id)->firstOrFail();
$query = $model->siblings();
$service = FiltersService::getService('advisories');
$service->applyFilters($query, $filters);
$paginator = $query->paginate(config('app.pagination_limit'));
return fractal($paginator, new AdvisoryTransformer())->respond();
}
public function store(Request $request): JsonResponse {
$this->validate($request, [
'parent' => 'required|exists:advisories,uuid',
'title' => 'required',
'number' => 'required',
'type' => 'required'
]);
$model = $this->model->create($request->all());
return fractal($model, new AdvisoryTransformer())->respond(201);
}
public function update(Request $request, $uuid): JsonResponse {
$model = $this->model->byUuid($uuid)->firstOrFail();
$this->validate($request, [
'title' => 'required',
'number' => 'required',
'type' => 'required'
]);
$model->update($request->all());
return fractal($model->fresh(), new AdvisoryTransformer())->respond();
}
public function destroy(Request $request, $uuid): JsonResponse {
$model = $this->model->byUuid($uuid)->firstOrFail();
$model->delete();
return response()->json(null, 204);
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace App\Http\Controllers\Api\Advisories;
use App\Http\Controllers\Controller;
use App\Models\Advisories\AdvisoryCompany;
use App\Transformers\Advisories\AdvisoryCompanyTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class AdvisoryCompaniesController extends Controller {
protected AdvisoryCompany $model;
public function __construct(AdvisoryCompany $model) {
$this->model = $model;
}
public function index(Request $request): JsonResponse {
$query = $this->model->query();
$paginator = $query->paginate(config('app.pagination_limit'));
return fractal($paginator, new AdvisoryCompanyTransformer())->respond();
}
public function show(Request $request, $id): JsonResponse {
$model = $this->model->byUuid($id)->firstOrFail();
return fractal($model, new AdvisoryCompanyTransformer())->respond();
}
public function store(Request $request): void {
}
public function update(Request $request, $uuid): void {
}
public function destroy(Request $request, $uuid): JsonResponse {
$model = $this->model->byUuid($uuid)->firstOrFail();
$model->advisoryMembers()->delete();
$model->delete();
return response()->json(null, 204);
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace App\Http\Controllers\Api\Advisories;
use App\Http\Controllers\Controller;
use App\Models\Advisories\AdvisoryMember;
use App\Transformers\Advisories\AdvisoryMemberTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class AdvisoryMembersController extends Controller {
protected AdvisoryMember $model;
public function __construct(AdvisoryMember $model) {
$this->model = $model;
}
public function index(Request $request): JsonResponse {
$query = $this->model->query();
$paginator = $query->paginate(config('app.pagination_limit'));
return fractal($paginator, new AdvisoryMemberTransformer())->respond();
}
public function show(Request $request, $id): JsonResponse {
$model = $this->model->byUuid($id)->firstOrFail();
return fractal($model, new AdvisoryMemberTransformer())->respond();
}
public function store(Request $request): void {
}
public function update(Request $request, $uuid): void {
}
public function destroy(Request $request, $uuid): JsonResponse {
$model = $this->model->byUuid($uuid)->firstOrFail();
$model->delete();
return response()->json(null, 204);
}
}

View File

@ -30,6 +30,12 @@ class UploadFileController extends Controller {
'type' => 'image',
'extension' => 'png',
],
/*
'image/svg+xml' => [
'type' => 'image',
'extension' => 'svg'
],
*/
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => [
'type' => 'document',
'extension' => 'xlsx'

View File

@ -0,0 +1,81 @@
<?php
namespace App\Http\Controllers\Api\Companies;
use App\Http\Controllers\Controller;
use App\Models\Companies\Company;
use App\Services\DaDataService;
use App\Transformers\Companies\CompanyTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CompaniesController extends Controller {
protected Company $model;
public function __construct(Company $model) {
$this->model = $model;
}
public function index(Request $request): JsonResponse {
$filters = collect(json_decode($request->get('filters'), true) ?? []);
$query = $this->model->query()->orderBy('updated_at', 'desc');
if ($val = $filters->get('search')) {
$query->where(function($query) use($val) {
$query->where('name', 'like', "%{$val}%")->orWhere('full_name', 'like', "%{$val}%")->orWhere('inn', 'like', "%{$val}%");
});
}
if ($val = $filters->get('type')) $query->whereHas('types', function($query) use($val) {
$query->where(['name' => $val]);
});
$paginator = $query->paginate(config('app.pagination_limit'));
return fractal($paginator, new CompanyTransformer())->respond();
}
public function show($id): JsonResponse {
$query = ($id === 'main') ? $this->model->where(['is_main' => 1]) : $this->model->byUuid($id);
return fractal($query->firstOrFail(), new CompanyTransformer())->respond();
}
public function store(Request $request): JsonResponse {
$this->validate($request, [
'inn' => 'required',
'name' => 'required',
'address' => 'required',
]);
$model = $this->model->getByData($request->all());
return fractal($model, new CompanyTransformer())->respond(201);
}
public function update(Request $request, $uuid): JsonResponse {
$model = $this->model->byUuid($uuid)->firstOrFail();
$this->validate($request, [
'name' => 'required',
'address' => 'required',
]);
$model->update(['name' => $request->get('name')]);
$address = [
'full' => $request->get('address')
];
$model->legalAddress->update($address);
$model->actualAddress->update($address);
foreach(['phone', 'email'] as $key) {
if ($request->has($key)) {
$model->$key->update(['value' => $request->get($key)]);
}
}
return fractal($model->fresh(), new CompanyTransformer())->respond();
}
public function destroy(Request $request, $uuid): JsonResponse {
$model = $this->model->byUuid($uuid)->firstOrFail();
$model->delete();
return response()->json(null, 204);
}
public function getDataByInn(Request $request, $inn) {
return (new DaDataService($inn))->getCompanyData();
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace App\Http\Controllers\Api\Companies;
use App\Http\Controllers\Controller;
use App\Models\Companies\Department;
use App\Transformers\Companies\DepartmentTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class DepartmentsController extends Controller {
protected Department $model;
public function __construct(Department $model) {
$this->model = $model;
}
public function index(Request $request): JsonResponse {
$query = $this->model->query();
$paginator = $query->paginate(config('app.pagination_limit'));
return fractal($paginator, new DepartmentTransformer())->respond();
}
public function show($id): JsonResponse {
$model = $this->model->byUuid($id)->firstOrFail();
return fractal($model, new DepartmentTransformer())->respond();
}
public function my(Request $request): JsonResponse {
return fractal($request->user()->selectedMember->department, new DepartmentTransformer())->respond();
}
public function destroy(Request $request, $uuid): JsonResponse {
$model = $this->model->byUuid($uuid)->firstOrFail();
$model->delete();
return response()->json(null, 204);
}
}

View File

@ -0,0 +1,70 @@
<?php
namespace App\Http\Controllers\Api\Companies;
use App\Http\Controllers\Controller;
use App\Models\Companies\Company;
use App\Models\Companies\CompanyMember;
use App\Models\Companies\Department;
use App\Models\User;
use App\Services\Filters\FiltersService;
use App\Transformers\Companies\CompanyMemberTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class MembersController extends Controller {
protected CompanyMember $model;
public function __construct(CompanyMember $model) {
$this->model = $model;
}
public function index(Request $request): JsonResponse {
$filters = collect($request->has('filters') ? json_decode($request->get('filters'), true) : [])->filter(function($val) {return $val;});
$query = $this->model->query();
$service = FiltersService::getService('companyMembers');
$service->applyFilters($query, $filters);
$paginator = $query->paginate(2);
return fractal($paginator, new CompanyMemberTransformer())->respond();
}
public function show($id): JsonResponse {
$model = $this->model->byUuid($id)->firstOrFail();
return fractal($model, new CompanyMemberTransformer())->respond();
}
public function store(Request $request): JsonResponse {
$this->validate($request, [
'name' => 'required',
'position' => 'required',
'company' => 'required|exists:companies,uuid',
]);
$user = User::getByData($request->only('name', 'email', 'phone'));
$company = Company::byUuid($request->get('company'))->first();
$department = Department::byUuid($request->get('department'));
$model = $company->addMember($user, $request->get('position'), $department->id ?? null, $request->get('rank'));
return fractal($model, new CompanyMemberTransformer())->respond(201);
}
public function update(Request $request, $uuid): JsonResponse {
$this->validate($request, [
'name' => 'required'
]);
$model = $this->model->byUuid($uuid)->firstOrFail();
foreach (['name', 'phone'] as $key) {
if ($request->has($key)) {
$model->user->update([$key => $request->get($key)]);
}
}
$model->update($request->all());
return fractal($model->fresh(), new CompanyMemberTransformer())->respond();
}
public function destroy(Request $request, $uuid): JsonResponse {
$model = $this->model->byUuid($uuid)->firstOrFail();
$model->delete();
return response()->json(null, 204);
}
}

View File

@ -0,0 +1,162 @@
<?php
namespace App\Models\Advisories;
use App\Models\Asset;
use App\Models\Companies\Company;
use App\Models\Companies\CompanyMember;
use App\Support\HasObjectsTrait;
use App\Support\RelationValuesTrait;
use App\Support\UuidScopeTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Collection;
class Advisory extends Model {
use UuidScopeTrait, SoftDeletes, RelationValuesTrait, HasObjectsTrait;
protected $dates = [
];
protected $fillable = [
'uuid',
'parent_id',
'logo_id',
'document_id',
'type',
'name',
'title',
'number',
'email',
'phone',
'director_name',
'secretary_name',
'is_main'
];
protected $hidden = [
'id'
];
public function logo(): BelongsTo {
return $this->belongsTo(Asset::class);
}
public function document(): BelongsTo {
return $this->belongsTo(Asset::class);
}
public function advisoryCompanies(): HasMany {
return $this->hasMany(AdvisoryCompany::class);
}
public function companies(): BelongsToMany {
return $this->belongsToMany(Company::class, 'advisory_companies');
}
public function members(): HasMany {
return $this->hasMany(AdvisoryMember::class);
}
public function companyMembers(): BelongsToMany {
return $this->belongsToMany(CompanyMember::class, 'advisory_members')->wherePivotNull('deleted_at');
}
public function parent(): BelongsTo {
return $this->belongsTo(self::class, 'parent_id');
}
public function children(): HasMany {
return $this->hasMany(self::class, 'parent_id');
}
public function siblings(): HasMany {
return $this->hasMany(Advisory::class, 'parent_id', 'parent_id')->where('id', '!=', $this->id);
}
public function getParsedTypeAttribute(): array {
return ['name' => $this->type, 'title' => AdvisoryType::TITLES[$this->type] ?? null];
}
public function getCaptionAttribute(): string {
return "{$this->number} «{$this->title}»";
}
public function getPathTitleAttribute(): string {
$advisory = $this;
$result = [$advisory->number];
while ($advisory = $advisory->parent) $result[] = $advisory->number;
return implode(' / ', $result);
}
/*
public function getSecretaryAttribute() {
return $this->companyMembers()->wherePivot('rank', '=', AdvisoryMemberRank::SECRETARY)->first();
}
*/
public function getSecretaryAssistantsAttribute(): Collection {
return $this->companyMembers()->wherePivot('rank', '=', AdvisoryMemberRank::SECRETARY_ASSISTANT)->get();
}
public function getSecretaryAndAssistantsAttribute(): Collection {
return $this->companyMembers()->wherePivotIn('rank', [AdvisoryMemberRank::SECRETARY, AdvisoryMemberRank::SECRETARY_ASSISTANT])->get();
}
public function getChairmanAttribute() {
return $this->companyMembers()->wherePivot('rank', '=', AdvisoryMemberRank::CHAIRMAN)->first();
}
public function getChairmanVicesAttribute(): Collection {
return $this->companyMembers()->wherePivot('rank', '=', AdvisoryMemberRank::VICE_CHAIRMAN)->get();
}
public function getOrdinaryMembersAttribute(): Collection {
return $this->companyMembers()->wherePivot('rank', '=', AdvisoryMemberRank::ORDINARY)->get();
}
public function setLogo($val) {
$asset = Asset::byUuid($val)->first();
$this->update(['logo_id' => $asset->id ?? null]);
}
public function setDocument($val) {
$asset = Asset::byUuid($val)->first();
$this->update(['document_id' => $asset->id ?? null]);
}
public function addMember(CompanyMember $companyMember, $rank = null): Model {
$member = $this->members()->firstOrCreate(['company_member_id' => $companyMember->id]);
$member->update(['rank' => $rank ?? AdvisoryMemberRank::ORDINARY]);
return $member;
}
public function syncMembers(Collection $companyMembers, $rank, ?Company $company = null) {
$exists = $companyMembers->map(function(CompanyMember $companyMember) use($rank) {
return $this->members()->firstOrCreate(['company_member_id' => $companyMember->id, 'rank' => $rank]);
});
$this->deleteDisappearedMembers($exists, $rank, $company);
}
public function deleteDisappearedMembers(Collection $exists, $rank, ?Company $company) {
$query = $this->members()->where(['rank' => $rank])->whereNotIn('id', $exists->pluck('id')->all());
if ($company && in_array($rank, [AdvisoryMemberRank::ORDINARY, AdvisoryMemberRank::VOTER])) $query->whereHas('companyMember', function($query) use($company) {
$query->where(['company_id' => $company->id]);
});
$query->delete();
}
public static function main() {
return self::query()->where(['is_main' => 1])->first();
}
public static function root() {
return self::query()->where(['parent_id' => 0])->get();
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace App\Models\Advisories;
use App\Models\Companies\Company;
use App\Support\RelationValuesTrait;
use App\Support\UuidScopeTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class AdvisoryCompany extends Model {
use UuidScopeTrait, RelationValuesTrait;
protected $dates = [
];
protected $fillable = [
'uuid',
'advisory_id',
'company_id'
];
protected $hidden = [
'id'
];
public function advisory(): BelongsTo {
return $this->belongsTo(Advisory::class);
}
public function company(): BelongsTo {
return $this->belongsTo(Company::class);
}
public function advisoryMembers() {
return $this->advisory->members()->whereHas('companyMember', function($query) {
$query->where(['company_id' => $this->company_id]);
});
}
public function companyMembers(): BelongsToMany {
return $this->advisory->companyMembers()->where(['company_id' => $this->company_id]);
}
public function getTitleAttribute(): string {
return "Член {$this->advisory->number} {$this->company->name}";
}
public function getSubtitleAttribute(): string {
return "Член {$this->advisory->number}";
}
public function getVoterAttribute(): ?Model {
return $this->advisoryMembers()->where(['rank' => AdvisoryMemberRank::VOTER])->first();
}
public function getCompanyMembers($rank): BelongsToMany {
return $this->companyMembers()->wherePivot('rank', '=', $rank);
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace App\Models\Advisories;
use App\Models\Companies\CompanyMember;
use App\Support\RelationValuesTrait;
use App\Support\UuidScopeTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
class AdvisoryMember extends Model {
use UuidScopeTrait, SoftDeletes, RelationValuesTrait;
protected $dates = [
];
protected $fillable = [
'uuid',
'advisory_id',
'company_member_id',
'rank'
];
protected $hidden = [
'id'
];
public function advisory(): BelongsTo {
return $this->belongsTo(Advisory::class);
}
public function companyMember(): BelongsTo {
return $this->belongsTo(CompanyMember::class);
}
public function getTitleAttribute(): string {
$rank = AdvisoryMemberRank::CATEGORIES[$this->rank] ?? 'Член';
return "{$rank} {$this->advisory->number} {$this->companyMember->company->name}";
}
public function getParsedRankAttribute(): array {
return ['name' => AdvisoryMemberRank::NAMES[$this->rank] ?? null, 'title' => AdvisoryMemberRank::TITLES[$this->rank] ?? null, 'level' => $this->rank];
}
public function getAdvisoryCompanyAttribute(): ?Model {
return ($this->advisory && $this->companyMember) ? $this->advisory->advisoryCompanies()->where(['company_id' => $this->companyMember->company_id])->first() : null;
}
public function setRank($rank = null) {
$this->update(['rank' => $rank ?? AdvisoryMemberRank::ORDINARY]);
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace App\Models\Advisories;
class AdvisoryMemberRank {
public const ORDINARY = 0;
public const VOTER = 5;
public const SECRETARY_ASSISTANT = 10;
public const SECRETARY = 15;
public const VICE_CHAIRMAN = 20;
public const CHAIRMAN = 25;
public const TITLES = [
self::ORDINARY => 'Член',
self::VOTER => 'Член с правом голоса',
self::SECRETARY_ASSISTANT => 'Помощник секретаря',
self::SECRETARY => 'Секретарь',
self::VICE_CHAIRMAN => 'Заместитель руководителя',
self::CHAIRMAN => 'Руководитель'
];
public const NAMES = [
self::ORDINARY => 'ordinary',
self::VOTER => 'voter',
self::SECRETARY_ASSISTANT => 'secretary-assistant',
self::SECRETARY => 'secretary',
self::VICE_CHAIRMAN => 'vice-chairman',
self::CHAIRMAN => 'chairman'
];
public const CATEGORIES = [
self::ORDINARY => 'Член',
self::VOTER => 'Член',
self::SECRETARY_ASSISTANT => 'Секретариат',
self::SECRETARY => 'Секретариат',
self::VICE_CHAIRMAN => 'Руководство',
self::CHAIRMAN => 'Руководство'
];
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Models\Advisories;
class AdvisoryType {
public const COMMITTEE = 'committee';
public const WORKGROUP = 'workgroup';
public const TITLES = [
self::COMMITTEE => 'Комитет',
self::WORKGROUP => 'Рабочая группа'
];
}

View File

@ -0,0 +1,57 @@
<?php
namespace App\Models\Companies;
use App\Support\RelationValuesTrait;
use App\Support\UuidScopeTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
class Address extends Model {
use UuidScopeTrait, SoftDeletes, RelationValuesTrait;
protected $table = 'company_addresses';
protected $dates = [
'deleted_at',
];
protected $fillable = [
'uuid',
'company_id',
'type',
'full',
'postcode',
'country',
'region',
'city',
'district',
'street',
'house',
'block',
'office'
];
protected $hidden = [
];
public static string $TYPE_LEGAL = 'legal';
public static string $TYPE_ACTUAL = 'actual';
public function company(): BelongsTo {
return $this->belongsTo(Company::class);
}
public function setFullAddress($val) {
$address = ['full' => $val, 'postcode' => '', 'country' => '', 'region' => '', 'city' => '',
'district' => '', 'street' => '', 'house' => '', 'block' => '', 'office' => ''];
$this->update($address);
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\Models\Companies;
use App\Support\RelationValuesTrait;
use App\Support\UuidScopeTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
class BankDetails extends Model {
use HasFactory, UuidScopeTrait, SoftDeletes, RelationValuesTrait;
protected $table = 'company_bank_details';
protected $dates = [
'deleted_at'
];
protected $fillable = [
'uuid',
'company_id',
'bik',
'bank',
'address',
'checking_account',
'correspondent_account'
];
protected $hidden = [
];
public function company(): BelongsTo {
return $this->belongsTo(Company::class);
}
}

View File

@ -0,0 +1,220 @@
<?php
namespace App\Models\Companies;
use App\Models\Advisories\AdvisoryCompany;
use App\Models\Asset;
use App\Models\User;
use App\Services\DaDataService;
use App\Support\RelationValuesTrait;
use App\Support\UuidScopeTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
class Company extends Model {
use UuidScopeTrait, SoftDeletes, RelationValuesTrait;
protected $dates = [
'tax_registration_date',
'deleted_at'
];
protected $fillable = [
'uuid',
'logo_id',
'name',
'full_name',
'inn',
'kpp',
'ogrn',
'okpo',
'okved',
'okato',
'tax_registration_date',
'is_main'
];
protected $hidden = [
'id',
'deleted_at',
'updated_at',
'pivot'
];
public function logo(): BelongsTo {
return $this->belongsTo(Asset::class);
}
public function types(): HasMany {
return $this->hasMany(CompanyType::class);
}
public function departments(): HasMany {
return $this->hasMany(Department::class);
}
public function members(): HasMany {
return $this->hasMany(CompanyMember::class);
}
public function rootMembers(): HasMany {
return $this->members()->whereNull('department_id');
}
public function management(): HasMany {
return $this->members()->whereIn('status', [CompanyMemberRank::VICE, CompanyMemberRank::CHIEF]);
}
public function vices(): HasMany {
return $this->members()->where(['status' => CompanyMemberRank::VICE]);
}
public function employees(): HasMany {
return $this->members()->where(['status' => CompanyMemberRank::EMPLOYEE]);
}
public function addresses(): HasMany {
return $this->hasMany(Address::class);
}
public function bankDetails(): HasOne {
return $this->hasOne(BankDetails::class);
}
public function contacts(): HasMany {
return $this->hasMany(Contact::class);
}
public function phones(): HasMany {
return $this->contacts()->where(['type' => ContactType::PHONE]);
}
public function emails(): HasMany {
return $this->contacts()->where(['type' => ContactType::EMAIL]);
}
public function advisoryCompanies(): HasMany {
return $this->hasMany(AdvisoryCompany::class);
}
public function scopeByTypes($query, $types) {
return $query->whereHas('types', function($query) use($types) {
$query->whereIn('name', is_array($types) ? $types : [$types]);
});
}
public function getLegalAddressAttribute(): Model {
return $this->addresses()->firstOrCreate(['type' => Address::$TYPE_LEGAL]);
}
public function getActualAddressAttribute(): Model {
return $this->addresses()->firstOrCreate(['type' => Address::$TYPE_ACTUAL]);
}
public function getPhoneAttribute(): Model {
return $this->phones()->firstOrCreate(['type' => ContactType::PHONE]);
}
public function getEmailAttribute(): Model {
return $this->emails()->firstOrCreate(['type' => ContactType::EMAIL]);
}
public function getRootDepartmentAttribute(): Model {
$res = $this->departments()->whereNull('parent_id')->firstOrCreate(['name' => 'root']);
if (!$res->title) $res->update(['title' => 'Дирекция']);
return $res;
}
public function getRepresentativeMemberAttribute() {
return $this->members()->where(['representative' => true])->first();
}
public function getResponsibleMemberAttribute() {
return $this->members()->orderBy('representative', 'desc')->first();
}
public static function getByData($data) {
$result = false;
if (!empty($data['inn'])) {
$result = self::firstOrCreate(['inn' => $data['inn']]);
(new DaDataService($data['inn']))->saveToCompany($result);
if ($val = $data['name'] ?? null) $result->update(['name' => $val, 'full_name' => $val]);
if (($val = $data['address'] ?? null) && $result->legalAddress->full !== $val) $result->setAddress($val);
if ($val = $data['phone'] ?? null) $result->setPhone($val);
if ($val = $data['email'] ?? null) $result->setEmail($val);
if ($val = $data['contacts'] ?? null) $result->setContacts($val);
if ($val = $data['types'] ?? null) $result->setTypes($val);
if ($val = $data['logo'] ?? null) $result->setLogo($val);
if (!$result->name && !is_numeric($result->inn)) $result->update(['name' => $result->inn, 'full_name' => $result->inn]);
}
return $result;
}
public function addMember(User $user, $position, $departmentId = null, $rank = null): Model {
if ($member = $this->members()->where(['user_id' => $user->id, 'position' => $position])->first()) {
if ($departmentId) $member->update(['department_id' => $departmentId]);
if (!is_null($rank)) $member->update(['rank' => $rank]);
} elseif ($member = $this->members()->create(['user_id' => $user->id, 'position' => $position])) {
$member->update(['department_id' => $departmentId ?? $this->rootDepartment->id ?? null, 'rank' => $rank ?? CompanyMemberRank::EMPLOYEE]);
}
return $member;
}
public function isMember(CompanyMember $member): bool {
return $this->members()->where('id', $member->id)->exists();
}
public function findDepartments($search): Collection {
return $this->departments()->where('title', 'like', "%{$search}%")->get();
}
public function findMembers($search): Collection {
return $this->members()->where('position', 'like', "%{$search}%")->orWhereHas('user', function($query) use($search) {
$query->where('name', 'like', "%{$search}%");
})->get();
}
public function setTypes(array $types) {
$exists = collect($types)->map(function($item) {
$name = (is_string($item)) ? $item : $item['id'] ?? null;
return $name ? $this->types()->firstOrCreate(['name' => $name]) : null;
});
$this->types()->whereNotIn('name', $exists->pluck('name')->all())->delete();
}
public function setLogo($val) {
$asset = Asset::byUuid($val)->first();
$this->update(['logo_id' => $asset->id ?? null]);
}
public function setAddress($val) {
$this->legalAddress->setFullAddress($val);
$this->actualAddress->setFullAddress($val);
}
public function setEmail($val): ?Model {
$this->emails()->delete();
return $val ? $this->contacts()->create(['type' => ContactType::EMAIL, 'value' => $val]) : null;
}
public function setPhone($val): ?Model {
$this->phones()->delete();
return $val ? $this->contacts()->create(['type' => ContactType::PHONE, 'value' => $val]) : null;
}
public function setContacts($val) {
$this->contacts()->firstOrCreate(['type' => ContactType::MIXED, 'value' => $val]);
collect(explode(';', $val))->each(function($contact) {
$type = (Str::contains($contact, '@')) ? ContactType::EMAIL : ContactType::PHONE;
$this->contacts()->firstOrCreate(['type' => $type, 'value' => trim($contact)]);
});
}
public function getPermissions(User $user): array {
$result = ['view' => false, 'edit' => false];
if ($user->isAdmin) $result = ['view' => true, 'edit' => true];
elseif ($user->isCompanyMember($this)) {
$result['view'] = true;
if ($this->members()->where(['user_id' => $user->id, 'representative' => 1])->exists()) $result['edit'] = true;
}
return $result;
}
}

View File

@ -0,0 +1,115 @@
<?php
namespace App\Models\Companies;
use App\Models\Advisories\AdvisoryMember;
use App\Models\User;
use App\Support\RelationValuesTrait;
use App\Support\UuidScopeTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Auth;
class CompanyMember extends Model {
use UuidScopeTrait, SoftDeletes, RelationValuesTrait;
protected $dates = [
'deleted_at',
];
protected $fillable = [
'uuid',
'user_id',
'company_id',
'department_id',
'rank',
'role',
'position',
'room',
'intercom',
'selected'
];
protected $hidden = [
'id'
];
public function company(): BelongsTo {
return $this->belongsTo(Company::class);
}
public function user(): BelongsTo {
return $this->belongsTo(User::class);
}
public function department(): BelongsTo {
return $this->belongsTo(Department::class);
}
public function advisoryMembership(): HasMany {
return $this->hasMany(AdvisoryMember::class);
}
public function getIsMeAttribute(): ?bool {
return ($user = Auth::user()) ? ($user->id === $this->user_id) : null;
}
public function getSubordinatesAttribute() {
$query = $this->department ? $this->department->members() : $this->company->members()->whereNull('department_id');
return $query->where('role', '<', $this->role)->get();
}
public function getSuperiorsAttribute() {
$query = $this->department ? $this->department->members() : $this->company->members()->whereNull('department_id');
return $query->where('role', '>', $this->role)->get();
}
public function getIsChiefAttribute(): bool {
return $this->role === CompanyMemberRank::CHIEF;
}
public function getIsViceAttribute(): bool {
return $this->role === CompanyMemberRank::VICE;
}
public function getIsManagementAttribute(): bool {
return in_array($this->role, [CompanyMemberRank::VICE, CompanyMemberRank::CHIEF]);
}
public function getParsedRankAttribute(): array {
return [
'name' => CompanyMemberRank::NAMES[$this->rank] ?? null,
'title' => CompanyMemberRank::TITLES[$this->rank] ?? null,
'level' => $this->rank
];
}
public function getParsedRoleAttribute(): array {
return ['name' => $this->role, 'title' => CompanyMemberRole::TITLES[$this->role] ?? null];
}
public function isSubordinateFor(User $user): bool {
$members = $user->membership()->where(['company_id' => $this->company_id])->where('rank', '>', CompanyMemberRank::EMPLOYEE)->get();
foreach ($members->all() as $member) {
if ($this->department->isMember($member)) return ($member->rank > $this->rank);
elseif ($member->department->level < $this->department->level) return $member->department->isParentFor($this->department);
}
return false;
}
public function setRank($rank): bool {
if (!empty(CompanyMemberRank::TITLES[$rank])) {
if (($rank === CompanyMemberRank::CHIEF) && ($chief = $this->department->chief)) $chief->setRank(CompanyMemberRank::EMPLOYEE);
return $this->update(['rank' => $rank]);
}
return false;
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Models\Companies;
class CompanyMemberRank {
public const EMPLOYEE = 0;
public const VICE = 5;
public const CHIEF = 10;
public const TITLES = [
self::CHIEF => 'Руководитель структурного подразделения',
self::VICE => 'Заместитель руководителя структурного подразделения',
self::EMPLOYEE => 'Сотрудник структурного подразделения'
];
public const NAMES = [
self::EMPLOYEE => 'employee',
self::VICE => 'vice',
self::CHIEF => 'chief'
];
}

View File

@ -0,0 +1,15 @@
<?php
namespace App\Models\Companies;
class CompanyMemberRole {
public const ORDINARY = 'ordinary';
public const MODERATOR = 'moderator';
public const ADMINISTRATOR = 'administrator';
public const TITLES = [
self::ORDINARY => 'Пользователь',
self::MODERATOR => 'Редактор',
self::ADMINISTRATOR => 'Администратор'
];
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\Models\Companies;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class CompanyType extends Model {
public const APPLICANT = 'applicant';
public const PRODUCER = 'producer';
public const TITLES = [
self::APPLICANT => 'Заявитель',
self::PRODUCER => 'Изготовитель продукции'
];
protected $dates = [
];
protected $fillable = [
'company_id',
'name'
];
protected $hidden = [
];
public function company(): BelongsTo {
return $this->belongsTo(Company::class);
}
public function getTitleAttribute(): ?string {
return self::TITLES[$this->name] ?? null;
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace App\Models\Companies;
use App\Support\RelationValuesTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Contact extends Model {
use RelationValuesTrait;
protected $table = 'company_contacts';
protected $dates = [
];
protected $fillable = [
'company_id',
'type',
'value'
];
protected $hidden = [
];
public function company(): BelongsTo {
return $this->belongsTo(Company::class);
}
public function getParsedTypeAttribute(): array {
return ['name' => $this->type, 'title' => ContactType::TITLES[$this->type] ?? null];
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace App\Models\Companies;
class ContactType {
public const PHONE = 'phone';
public const EMAIL = 'email';
public const SITE = 'site';
public const FAX = 'fax';
public const MIXED = 'mixed';
public const TITLES = [
self::PHONE => 'телефон',
self::EMAIL => 'электронная почта',
self::SITE => 'сайт',
self::FAX => 'факс',
self::MIXED => 'смешанное'
];
}

View File

@ -0,0 +1,89 @@
<?php
namespace App\Models\Companies;
use App\Models\User;
use App\Support\RelationValuesTrait;
use App\Support\UuidScopeTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
class Department extends Model {
use UuidScopeTrait, SoftDeletes, RelationValuesTrait;
protected $table = 'company_departments';
protected $dates = [
];
protected $fillable = [
'uuid',
'company_id',
'parent_id',
'name',
'title',
'level'
];
protected $hidden = [
];
public function company(): BelongsTo {
return $this->belongsTo(Company::class);
}
public function parent(): BelongsTo {
return $this->belongsTo(self::class, 'parent_id');
}
public function children(): HasMany {
return $this->hasMany(self::class, 'parent_id');
}
public function members(): HasMany {
return $this->hasMany(CompanyMember::class);
}
public function management(): HasMany {
return $this->members()->whereIn('rank', [CompanyMemberRank::VICE, CompanyMemberRank::CHIEF]);
}
public function vices(): HasMany {
return $this->members()->where(['rank' => CompanyMemberRank::VICE]);
}
public function employees(): HasMany {
return $this->members()->where(['rank' => CompanyMemberRank::EMPLOYEE]);
}
public function getChiefAttribute() {
return $this->members()->where(['rank' => CompanyMemberRank::CHIEF])->first();
}
public function addChildren($name, $title): ?Department {
$result = null;
if (($name = trim($name)) && ($title = trim($title))) {
$result = $this->company->departments()->firstOrCreate(['name' => $name]);
$result->update(['title' => $title, 'parent_id' => $this->id, 'level' => ++$this->level]);
}
return $result;
}
public function addMember(User $user, $position = null): Model {
return $this->members()->firstOrCreate(['company_id' => $this->company_id, 'user_id' => $user->id, 'position' => $position]);
}
public function isMember(CompanyMember $member): bool {
return $this->members()->where(['id' => $member->id])->exists();
}
public function isParentFor(Department $department): bool {
while ($parent = $department->parent) {
if ($parent->id === $this->id) return true;
$department = $department->parent;
}
return false;
}
}

View File

@ -6,10 +6,12 @@ class PageType {
public const CONTENT = 'content';
public const PUBLICATIONS = 'publications';
public const REGISTRY = 'registry';
public const TK_STRUCTURE = 'tk-structure';
public const TITLES = [
self::CONTENT => 'Контентная страница',
self::PUBLICATIONS => 'Страница публикаций',
self::REGISTRY => 'Страница реестра'
self::REGISTRY => 'Страница реестра',
self::TK_STRUCTURE => 'Структура ТК'
];
}

View File

@ -70,6 +70,9 @@ class User extends Authenticatable {
return $this->hasRole('Administrator');
}
public function getIsPrivilegedAttribute() {
return $this->isAdmin;
}
public static function getByData($data, $triggerEvent = false) {

View File

@ -2,7 +2,16 @@
namespace App\Providers;
use App\Models\Advisories\Advisory;
use App\Models\Advisories\AdvisoryCompany;
use App\Models\Advisories\AdvisoryMember;
use App\Models\Asset;
use App\Models\Companies\Address;
use App\Models\Companies\BankDetails;
use App\Models\Companies\Company;
use App\Models\Companies\CompanyMember;
use App\Models\Companies\Contact;
use App\Models\Companies\Department;
use App\Models\Dictionaries\Dictionary;
use App\Models\Dictionaries\DictionaryItem;
use App\Models\Objects\Field;
@ -64,7 +73,18 @@ class AppServiceProvider extends ServiceProvider
'registry' => Registry::class,
'registry-category' => Category::class,
'registry-entry' => Entry::class
'registry-entry' => Entry::class,
'company' => Company::class,
'company-address' => Address::class,
'company-member' => CompanyMember::class,
'company-contact' => Contact::class,
'company-department' => Department::class,
'bank-details' => BankDetails::class,
'advisory' => Advisory::class,
'advisory-member' => AdvisoryMember::class,
'advisory-company' => AdvisoryCompany::class
]);
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace App\Services\Filters\Companies;
class CompanyFiltersServices {
public static array $services = [
'companyMembers' => CompanyMemberFilters::class
];
}

View File

@ -0,0 +1,58 @@
<?php
namespace App\Services\Filters\Companies;
use App\Models\Companies\CompanyMember;
use App\Services\Filters\FiltersService;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
class CompanyMemberFilters extends FiltersService {
public function get(Collection $filters): array {
$groups = [
[
'name' => 'common',
'title' => 'Общие параметры',
'fields' => $this->nativeFields($filters)
]
];
$query = CompanyMember::query();
$this->applyFilters($query, $filters);
return ['groups' => ['data' => $groups], 'total' => $query->count()];
}
public function nativeFields(Collection $filters): array {
return [
];
}
public function applyFilters(Builder $query, Collection $filters) {
$this->applyNativeFilters($query, $filters);
$this->applyPermissionsFilters($query);
}
public function applyNativeFilters(Builder $query, Collection $filters) {
$filters->each(function($value, $prop) use($query) {
$this->applyNativeFilter($query, $prop, $value);
});
}
public function applyNativeFilter(Builder $query, $prop, $value) {
if ($value) {
if ($prop === 'search') $this->applySearchFilter($query, $value, ['position', 'room', 'intercom', ['user' => ['name', 'email', 'phone']], ['department' => ['title']]]);
elseif ($prop === 'company') $this->applyCompanyFilter($query, $value);
}
}
public function applyCompanyFilter(Builder $query, $value) {
$query->whereHas('company', function($query) use($value) {
($value === 'main') ? $query->where(['is_main' => 1]) : $query->whereIn('uuid', is_array($value) ? $value : [$value]);
});
}
public function applyPermissionsFilters(Builder $query) {
}
}

View File

@ -2,6 +2,7 @@
namespace App\Services\Filters;
use App\Services\Filters\Companies\CompanyFiltersServices;
use App\Services\Filters\Registries\RegistryFiltersServices;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
@ -9,7 +10,8 @@ use Illuminate\Support\Facades\Date;
class FiltersService {
public static array $services = [
RegistryFiltersServices::class
RegistryFiltersServices::class,
CompanyFiltersServices::class
];

View File

@ -0,0 +1,53 @@
<?php
namespace App\Services\Forms\Advisories;
use App\Models\Advisories\Advisory;
use App\Models\Companies\Company;
use App\Models\Objects\FieldType;
use App\Services\Forms\FormsService;
use App\Transformers\Advisories\AdvisoryTransformer;
use App\Transformers\Companies\CompanyTransformer;
use Illuminate\Http\JsonResponse;
class AdvisoryCompaniesForms extends FormsService {
public array $formTitles = ['create' => 'Добавление организаций-участников', 'update' => 'Редактирование организаций-участников'];
public function form(?string $id = null, array $data = []): array {
$model = Advisory::byUuid($id)->first();
$groups = [
['name' => 'common', 'fields' => $this->commonGroupFields($model)]
];
return ['title' => $this->formTitle($model), 'data' => $groups];
}
public function commonGroupFields(?Advisory $model): array {
$fields = [
[
'name' => 'companies',
'title' => 'Организации-участники',
'type' => FieldType::RELATION,
'multiple' => true,
'options' => fractal(Company::all(), new CompanyTransformer()),
'value' => $model ? fractal($model->companies, new CompanyTransformer()) : null
]
];
return ['data' => $fields];
}
public function store(array $data): ?JsonResponse {
}
public function update(string $id, array $data): ?JsonResponse {
$model = Advisory::byUuid($id)->firstOrFail();
$exists = Company::byUuids($data['companies'] ?? [])->get()->map(function($company) use($model) {
return $model->advisoryCompanies()->firstOrCreate(['company_id' => $company->id]);
});
$model->advisoryCompanies()->whereNotIn('id', $exists->pluck('id')->all())->delete();
return fractal($model->fresh(), new AdvisoryTransformer())->respond();
}
}

View File

@ -0,0 +1,64 @@
<?php
namespace App\Services\Forms\Advisories;
use App\Models\Advisories\AdvisoryCompany;
use App\Models\Advisories\AdvisoryMemberRank;
use App\Models\Companies\CompanyMember;
use App\Models\Objects\FieldType;
use App\Services\Forms\FormsService;
use App\Transformers\Advisories\AdvisoryCompanyTransformer;
use App\Transformers\Companies\CompanyMemberTransformer;
use Illuminate\Http\JsonResponse;
class AdvisoryCompanyMembersForms extends FormsService {
public array $formTitles = ['create' => '', 'update' => 'Добавление сотрудников-участников'];
public function form(?string $id = null, array $data = []): array {
$model = AdvisoryCompany::byUuid($id)->first();
$groups = [
['name' => 'common', 'fields' => $this->commonGroupFields($model)]
];
return ['title' => $this->formTitle($model), 'data' => $groups];
}
public function commonGroupFields(?AdvisoryCompany $model): array {
$fields = [
[
'name' => 'voter',
'title' => 'Сотрудник с правом голоса',
'type' => FieldType::RELATION,
'required' => true,
'options' => $model ? fractal($model->company->members, new CompanyMemberTransformer()) : null,
'value' => $model ? fractal($model->getCompanyMembers(AdvisoryMemberRank::VOTER)->get(), new CompanyMemberTransformer()) : null
],
[
'name' => 'members',
'title' => 'Сотрудники',
'type' => FieldType::RELATION,
'multiple' => true,
'options' => $model ? fractal($model->company->members, new CompanyMemberTransformer()) : null,
'value' => $model ? fractal($model->getCompanyMembers(AdvisoryMemberRank::ORDINARY)->get(), new CompanyMemberTransformer()) : null
]
];
return ['data' => $fields];
}
public function store(array $data): void {
}
public function update(string $id, array $data): ?JsonResponse {
$model = AdvisoryCompany::byUuid($id)->firstOrFail();
$voter = $data['voter'] ?? null;
$members = collect($data['members'] ?? [])->filter(function($member_id) use($voter) {
return $member_id !== $voter;
})->all();
$model->advisory->syncMembers(CompanyMember::byUuids($members)->get(), AdvisoryMemberRank::ORDINARY, $model->company);
$model->advisory->syncMembers(CompanyMember::byUuids([$voter])->get(), AdvisoryMemberRank::VOTER, $model->company);
return fractal($model->fresh(), new AdvisoryCompanyTransformer())->respond();
}
}

View File

@ -0,0 +1,188 @@
<?php
namespace App\Services\Forms\Advisories;
use App\Models\Advisories\Advisory;
use App\Models\Advisories\AdvisoryMemberRank;
use App\Models\Advisories\AdvisoryType;
use App\Models\Companies\CompanyMember;
use App\Models\Objects\FieldType;
use App\Services\Forms\FormsService;
use App\Transformers\Advisories\AdvisoryTransformer;
use App\Transformers\Assets\AssetTransformer;
use App\Transformers\Companies\CompanyMemberTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Str;
class AdvisoryForms extends FormsService {
public array $formTitles = ['create' => 'Добавление подразделения', 'update' => 'Редактирование подразделения'];
public function form(?string $id = null, array $data = []): array {
$model = Advisory::byUuid($id)->first();
return [
'title' => $this->formTitle($model),
'frames' => [
['title' => 'Общие сведения', 'groups' => $this->form1Groups($model)],
// ['title' => 'Руководство', 'groups' => $this->form2Groups($model)]
]
];
}
public function form1Groups(?Advisory $model): array {
$groups = [
['name' => 'common', 'title' => '', 'fields' => $this->commonGroupFields($model)]
];
return ['data' => $groups];
}
public function form2Groups(?Advisory $model): array {
$groups = [
['name' => 'management', 'title' => '', 'fields' => $this->managementGroupFields($model)]
];
return ['data' => $groups];
}
public function commonGroupFields(?Advisory $model): array {
$fields = [
[
'name' => 'type',
'title' => 'Тип подразделения',
'type' => FieldType::RELATION,
'required' => true,
'appearance' => 'radio',
'options' => $this->getRelationItems(AdvisoryType::TITLES),
'value' => $this->getRelationValue(AdvisoryType::TITLES, $model->type ?? null)
],
[
'name' => 'title',
'title' => 'Название подразделения',
'type' => FieldType::TEXT,
'required' => true,
'value' => $model->title ?? null
],
[
'name' => 'number',
'title' => 'Обозначение подразделения',
'type' => FieldType::STRING,
'required' => true,
'value' => $model->number ?? null
],
[
'name' => 'email',
'title' => 'Электронная почта',
'type' => FieldType::STRING,
'value' => $model->email ?? null
],
[
'name' => 'phone',
'title' => 'Телефон',
'type' => FieldType::STRING,
'value' => $model->phone ?? null
],
[
'name' => 'director_name',
'title' => 'Руководитель',
'type' => FieldType::STRING,
'value' => $model->director_name ?? null
],
[
'name' => 'secretary_name',
'title' => 'Секретарь',
'type' => FieldType::STRING,
'value' => $model->secretary_name ?? null
],
[
'name' => 'document',
'title' => 'Списочный состав',
'type' => FieldType::DOCUMENT,
'value' => ($model->document ?? null) ? fractal($model->document, new AssetTransformer()) : null
],
/*
[
'name' => 'logo',
'title' => 'Логотип',
'type' => FieldType::IMAGE,
'value' => ($model->logo ?? null) ? fractal($model->logo, new AssetTransformer()) : null
]
*/
];
return ['data' => $fields];
}
public function managementGroupFields(?Advisory $model): array {
$fields = [
[
'name' => 'chairman',
'title' => 'Руководитель',
'type' => FieldType::RELATION,
//'required' => true,
'options' => fractal(CompanyMember::all(), new CompanyMemberTransformer()),
'value' => ($val = $model->chairman ?? null) ? fractal($val, new CompanyMemberTransformer()) : null
],
[
'name' => 'vices',
'title' => 'Заместители',
'type' => FieldType::RELATION,
'multiple' => true,
'options' => fractal(CompanyMember::all(), new CompanyMemberTransformer()),
'value' => $model ? fractal($model->chairmanVices, new CompanyMemberTransformer()) : null
],
[
'name' => 'secretary',
'title' => 'Ответственный секретарь',
'type' => FieldType::RELATION,
//'required' => true,
'options' => fractal(CompanyMember::all(), new CompanyMemberTransformer()),
'value' => ($val = $model->secretary ?? null) ? fractal($val, new CompanyMemberTransformer()) : null
],
[
'name' => 'assistants',
'title' => 'Помощники секретаря',
'type' => FieldType::RELATION,
'multiple' => true,
'options' => fractal(CompanyMember::all(), new CompanyMemberTransformer()),
'value' => $model ? fractal($model->secretaryAssistants, new CompanyMemberTransformer()) : null
]
];
return ['data' => $fields];
}
public function store(array $data): JsonResponse {
$parent = Advisory::byUuid($data['parent'] ?? null)->firstOrFail();
$model = $parent->children()->create();
$this->updateData($model, $data);
return fractal($model, new AdvisoryTransformer())->respond(201);
}
public function update(string $id, array $data): JsonResponse {
$model = Advisory::byUuid($id)->firstOrFail();
$this->updateData($model, $data);
return fractal($model->fresh(), new AdvisoryTransformer())->respond();
}
public function updateData(Advisory $model, $data) {
$data['name'] = $this->makeName($data);
$model->update(collect($data)->only('type', 'name', 'title', 'number', 'email', 'phone', 'director_name', 'secretary_name')->all());
$this->syncMembers($model, $data);
$model->setLogo($data['logo'] ?? null);
$model->setDocument($data['document'] ?? null);
}
public function makeName($data): string {
$val = $data['number'] ?? $data['title'] ?? '';
return Str::lower(Str::replace(' ', '', Str::transliterate($val)));
}
public function syncMembers(Advisory $model, $data) {
$ranksByFields = ['chairman' => AdvisoryMemberRank::CHAIRMAN, 'vices' => AdvisoryMemberRank::VICE_CHAIRMAN,
'secretary' => AdvisoryMemberRank::SECRETARY, 'assistants' => AdvisoryMemberRank::SECRETARY_ASSISTANT, 'ordinary' => AdvisoryMemberRank::ORDINARY];
collect($ranksByFields)->each(function($rank, $field) use($model, $data) {
if (array_key_exists($field, $data)) $model->syncMembers(CompanyMember::byUuids($data[$field])->get(), $rank);
});
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace App\Services\Forms\Advisories;
class AdvisoryFormsServices {
public static array $services = [
'advisoryCompanies' => AdvisoryCompaniesForms::class,
'advisoryCompanyMembers' => AdvisoryCompanyMembersForms::class,
'advisory' => AdvisoryForms::class,
'advisoryInfo' => AdvisoryInfoForms::class,
'advisoryGroup' => AdvisoryGroupForms::class
];
}

View File

@ -0,0 +1,71 @@
<?php
namespace App\Services\Forms\Advisories;
use App\Models\Advisories\Advisory;
use App\Models\Advisories\AdvisoryMemberRank;
use App\Models\Advisories\AdvisoryType;
use App\Models\Companies\CompanyMember;
use App\Models\Objects\FieldType;
use App\Services\Forms\FormsService;
use App\Transformers\Advisories\AdvisoryTransformer;
use App\Transformers\Assets\AssetTransformer;
use App\Transformers\Companies\CompanyMemberTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Str;
class AdvisoryGroupForms extends FormsService {
public array $formTitles = ['create' => 'Добавление направления', 'update' => 'Редактирование направления'];
public function form(?string $id = null, array $data = []): array {
$model = Advisory::byUuid($id)->first();
return [
'title' => $this->formTitle($model),
'frames' => [
['title' => 'Общие сведения', 'groups' => $this->form1Groups($model)]
]
];
}
public function form1Groups(?Advisory $model): array {
$groups = [
['name' => 'common', 'title' => '', 'fields' => $this->commonGroupFields($model)]
];
return ['data' => $groups];
}
public function commonGroupFields(?Advisory $model): array {
$fields = [
[
'name' => 'title',
'title' => 'Название подразделения',
'type' => FieldType::TEXT,
'required' => true,
'value' => $model->title ?? null
]
];
return ['data' => $fields];
}
public function store(array $data): JsonResponse {
$parent = Advisory::byUuid($data['parent'] ?? null)->firstOrFail();
$data['name'] = $this->makeName($data);
$model = $parent->children()->create(collect($data)->only('name', 'title')->all());
$model->setLogo($data['logo'] ?? null);
return fractal($model, new AdvisoryTransformer())->respond(201);
}
public function update(string $id, array $data): JsonResponse {
$model = Advisory::byUuid($id)->firstOrFail();
$data['name'] = $this->makeName($data);
$model->update(collect($data)->only('name', 'title')->all());
$model->setLogo($data['logo'] ?? null);
return fractal($model->fresh(), new AdvisoryTransformer())->respond();
}
public function makeName($data): string {
return Str::slug(Str::transliterate($data['title'] ?? ''));
}
}

View File

@ -0,0 +1,92 @@
<?php
namespace App\Services\Forms\Advisories;
use App\Models\Advisories\Advisory;
use App\Models\Objects\FieldType;
use App\Services\Forms\FormsService;
use App\Transformers\Companies\CompanyMemberTransformer;
class AdvisoryInfoForms extends FormsService {
public array $formTitles = ['create' => '', 'update' => 'Профиль подкомитета'];
public function form(?string $id = null, array $data = []): array {
$model = Advisory::byUuid($id)->first();
$groups = [
['name' => 'contacts', 'title' => 'Контакты', 'fields' => $this->contactsGroupFields($model)],
['name' => 'management', 'title' => 'Руководители и секретариат', 'fields' => $this->managementGroupFields($model)]
];
return ['title' => $this->formTitle($model), 'btnSaveHidden' => true, 'data' => $groups];
}
public function contactsGroupFields(?Advisory $model): array {
$fields = [
[
'name' => 'caption',
'title' => 'Наименование',
'type' => FieldType::STRING,
'readonly' => true,
'value' => $model->caption ?? null
],
[
'name' => 'email',
'title' => 'Электронная почта',
'type' => FieldType::STRING,
'readonly' => true,
'value' => $model->email ?? null
],
[
'name' => 'phone',
'title' => 'Телефон',
'type' => FieldType::STRING,
'readonly' => true,
'value' => $model->phone ?? null
]
];
return ['data' => $fields];
}
public function managementGroupFields(?Advisory $model): array {
$fields = [
[
'name' => 'chairman',
'title' => 'Руководитель',
'type' => FieldType::RELATION,
'readonly' => true,
'value' => ($val = $model->chairman ?? null) ? fractal($val, new CompanyMemberTransformer()) : null
],
[
'name' => 'vices',
'title' => 'Заместители',
'type' => FieldType::RELATION,
'readonly' => true,
'value' => $model ? fractal($model->chairmanVices, new CompanyMemberTransformer()) : null
],
[
'name' => 'secretary',
'title' => 'Ответственный секретарь',
'type' => FieldType::RELATION,
'readonly' => true,
'value' => ($val = $model->secretary ?? null) ? fractal($val, new CompanyMemberTransformer()) : null
],
[
'name' => 'assistants',
'title' => 'Помощники секретаря',
'type' => FieldType::RELATION,
'readonly' => true,
'value' => $model ? fractal($model->secretaryAssistants, new CompanyMemberTransformer()) : null
]
];
return ['data' => $fields];
}
public function store(array $data): void {
}
public function update(string $id, array $data): void {
}
}

View File

@ -0,0 +1,91 @@
<?php
namespace App\Services\Forms\Companies;
use App\Models\Companies\Company;
use App\Models\Objects\FieldType;
use App\Services\Forms\FormsService;
use App\Transformers\Assets\AssetTransformer;
use App\Transformers\Companies\CompanyTransformer;
use Illuminate\Http\JsonResponse;
class CompanyForms extends FormsService {
public array $formTitles = ['create' => 'Создание новой организации', 'update' => 'Редактирование организации'];
public function form(?string $id = null, array $data = []): array {
$model = Company::byUuid($id)->first();
$groups = [
['name' => 'common', 'fields' => $this->commonGroupFields($model)]
];
return ['title' => $this->formTitle($model), 'data' => $groups];
}
public function commonGroupFields(?Company $model): array {
$fields = [
[
'name' => 'inn',
'title' => 'ИНН',
'type' => FieldType::STRING,
'required' => true,
'readonly' => !!$model,
'value' => $model->inn ?? null
],
[
'name' => 'name',
'title' => 'Наименование организации',
'type' => FieldType::STRING,
'required' => true,
'value' => $model->name ?? null
],
[
'name' => 'address',
'title' => 'Юридический адрес',
'type' => FieldType::STRING,
'required' => true,
'value' => $model->legalAddress->full ?? null
],
[
'name' => 'phone',
'title' => 'Телефон',
'type' => FieldType::STRING,
'required' => false,
'value' => $model->phone->value ?? null
],
[
'name' => 'email',
'title' => 'Email',
'type' => FieldType::STRING,
'required' => false,
'value' => $model->email->value ?? null
],
[
'name' => 'logo',
'title' => 'Логотип',
'type' => FieldType::IMAGE,
'value' => ($model->logo ?? null) ? fractal($model->logo, new AssetTransformer()) : null
]
];
return ['data' => $fields];
}
public function store(array $data): ?JsonResponse {
if (!empty($data['inn']) && ($model = Company::getByData($data))) {
return fractal($model, new CompanyTransformer())->respond();
}
}
public function update(string $id, array $data): ?JsonResponse {
$model = Company::byUuid($id)->firstOrFail();
if ($val = trim($data['name'] ?? null)) $model->update(['name' => $val]);
if ($val = trim($data['address'] ?? null)) $model->setAddress($val);
if ($val = trim($data['phone'] ?? null)) $model->setPhone($val);
if ($val = trim($data['email'] ?? null)) $model->setEmail($val);
$model->setTypes($data['types'] ?? []);
$model->setLogo($data['logo'] ?? null);
return fractal($model->fresh(), new CompanyTransformer())->respond();
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace App\Services\Forms\Companies;
class CompanyFormsServices {
public static array $services = [
'company' => CompanyForms::class,
'companyMember' => CompanyMemberForms::class,
'department' => DepartmentForms::class
];
}

View File

@ -0,0 +1,147 @@
<?php
namespace App\Services\Forms\Companies;
use App\Models\Companies\CompanyMember;
use App\Models\Companies\CompanyMemberRank;
use App\Models\Companies\CompanyMemberRole;
use App\Models\Companies\Department;
use App\Models\Objects\FieldType;
use App\Models\Pages\Page;
use App\Models\User;
use App\Services\Forms\FormsService;
use App\Transformers\Companies\CompanyMemberTransformer;
use App\Transformers\Companies\DepartmentTransformer;
use App\Transformers\Pages\PageTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
class CompanyMemberForms extends FormsService {
public array $formTitles = ['create' => 'Добавление сотрудника организации', 'update' => 'Редактирование сотрудника'];
public function form(?string $id = null, array $data = []): array {
$model = CompanyMember::byUuid($id)->first();
$groups = [
[
'name' => 'common',
'fields' => $this->commonGroupFields($model),
'dynamic' => [
['field' => 'role', 'hide' => ['pages']],
['field' => 'role', 'value' => CompanyMemberRole::MODERATOR, 'show' => ['pages']]
]
]
];
return ['title' => $this->formTitle($model), 'data' => $groups];
}
public function commonGroupFields(?CompanyMember $model): array {
$fields = [
[
'name' => 'email',
'title' => 'Email',
'type' => FieldType::STRING,
'required' => true,
'readonly' => !!$model && !Auth::user()->isPrivileged,
'value' => $model->user->email ?? null
],
[
'name' => 'name',
'title' => 'ФИО',
'type' => FieldType::TEXT,
'required' => true,
'value' => $model->user->name ?? null
],
[
'name' => 'position',
'title' => 'Должность',
'type' => FieldType::TEXT,
'required' => true,
'value' => $model->position ?? null
],
[
'name' => 'phone',
'title' => 'Телефон',
'type' => FieldType::STRING,
'value' => $model->user->phone ?? null
],
[
'name' => 'room',
'title' => 'Кабинет',
'type' => FieldType::STRING,
'value' => $model->room ?? null
],
[
'name' => 'intercom',
'title' => 'Внутренний телефон',
'type' => FieldType::STRING,
'value' => $model->intercom ?? null
],
[
'name' => 'role',
'title' => 'Роль',
'type' => FieldType::RELATION,
'required' => true,
'appearance' => 'radio',
'options' => $this->getRelationItems(CompanyMemberRole::TITLES),
'value' => $this->getRelationValue(CompanyMemberRole::TITLES, $model->role ?? null)
],
[
'name' => 'pages',
'title' => 'Разделы сайта',
'type' => FieldType::RELATION,
'multiple' => true,
'options' => fractal(Page::all(), new PageTransformer()),
'value' => null
]
/*
[
'name' => 'rank',
'title' => 'Ранг сотрудника',
'type' => FieldType::RELATION,
'required' => true,
'appearance' => 'radio',
'options' => $this->getRelationItems(CompanyMemberRank::TITLES),
'value' => $model ? $model->parsedRank + ['id' => $model->rank] : null
],
[
'name' => 'representative',
'title' => 'Назначить администратором',
'type' => FieldType::BOOLEAN,
'value' => $model->representative ?? null
]
*/
];
/*
if ($model) $fields[] = [
'name' => 'department',
'title' => 'Отдел',
'type' => FieldType::RELATION,
'options' => fractal($model->company->departments ?? [], new DepartmentTransformer()),
'value' => $model ? fractal($model->department, new DepartmentTransformer()) : null
];
*/
return ['data' => $fields];
}
public function store(array $data): ?JsonResponse {
if (($department = Department::byUuid($data['department'] ?? null)->first()) && ($user = User::getByData(collect($data)->except('role')->all(), true))) {
$model = $department->addMember($user, $data['position'] ?? null);
$model->update(['position' => $data['position'] ?? null, 'role' => $data['role'] ?? null, 'room' => $data['room'] ?? null, 'intercom' => $data['intercom'] ?? null]);
return fractal($model, new CompanyMemberTransformer())->respond();
}
}
public function update(string $id, array $data): ?JsonResponse {
$model = CompanyMember::byUuid($id)->firstOrFail();
$model->update(['position' => $data['position'] ?? null, 'role' => $data['role'] ?? null, 'room' => $data['room'] ?? null, 'intercom' => $data['intercom'] ?? null]);
if ($department = Department::byUuid($data['department'] ?? null)->first()) $model->update(['department_id' => $department->id]);
$model->user->update(['name' => $data['name'] ?? null, 'phone' => $data['phone'] ?? null]);
if (($email = $data['email'] ?? null) && !User::query()->where(['email' => $email])->exists()) $model->user->update(['email' => $data['email']]);
return fractal($model->fresh(), new CompanyMemberTransformer())->respond();
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace App\Services\Forms\Companies;
use App\Models\Companies\Department;
use App\Models\Objects\FieldType;
use App\Services\Forms\FormsService;
use App\Transformers\Companies\DepartmentTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Str;
class DepartmentForms extends FormsService {
public array $formTitles = ['create' => 'Создание подразделение организации', 'update' => 'Редактирование подразделения'];
public function form(?string $id = null, array $data = []): array {
$model = Department::byUuid($id)->first();
$groups = [
['name' => 'common', 'fields' => $this->commonGroupFields($model)]
];
return ['title' => $this->formTitle($model), 'data' => $groups];
}
public function commonGroupFields(?Department $model): array {
$fields = [
[
'name' => 'title',
'title' => 'Название подразделения',
'type' => FieldType::STRING,
'required' => true,
'value' => $model->title ?? null
]
];
return ['data' => $fields];
}
public function store(array $data): ?JsonResponse {
$parent = Department::byUuid($data['department'] ?? null)->firstOrFail();
if ($title = trim($data['title'] ?? null)) {
$model = $parent->addChildren(Str::transliterate($title), $title);
return fractal($model, new DepartmentTransformer())->respond();
}
}
public function update(string $id, array $data): ?JsonResponse {
$model = Department::byUuid($id)->firstOrFail();
if ($val = trim($data['title'] ?? null)) {
$model->update(['title' => $val]);
if ($model->name !== 'root') $model->update(['name' => Str::transliterate($val)]);
}
return fractal($model, new DepartmentTransformer())->respond();
}
}

View File

@ -2,6 +2,8 @@
namespace App\Services\Forms;
use App\Services\Forms\Advisories\AdvisoryFormsServices;
use App\Services\Forms\Companies\CompanyFormsServices;
use App\Services\Forms\Feedback\FeedbackFormsServices;
use App\Services\Forms\Pages\PageFormsServices;
use App\Services\Forms\Publications\PublicationFormsServices;
@ -17,6 +19,8 @@ class FormsService {
RegistryFormsServices::class,
UserFormsServices::class,
FeedbackFormsServices::class,
AdvisoryFormsServices::class,
CompanyFormsServices::class
];
public function __construct() {

View File

@ -1,12 +0,0 @@
<?php
namespace App\Support;
use App\Models\Processes\Participant;
use Illuminate\Database\Eloquent\Relations\MorphMany;
trait ParticipatableTrait {
public function participation(): MorphMany {
return $this->morphMany(Participant::class, 'participatable');
}
}

View File

@ -0,0 +1,53 @@
<?php
namespace App\Transformers\Advisories;
use App\Models\Advisories\AdvisoryCompany;
use App\Models\Advisories\AdvisoryMemberRank;
use App\Services\PermissionsService;
use App\Transformers\Companies\CompanyMemberTransformer;
use App\Transformers\Companies\CompanyTransformer;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item;
use League\Fractal\Resource\Primitive;
use League\Fractal\TransformerAbstract;
class AdvisoryCompanyTransformer extends TransformerAbstract {
protected array $defaultIncludes = [];
protected array $availableIncludes = [
'advisory', 'company', 'voter', 'advisoryMembers', 'companyMembers', 'permissions'
];
public function transform(AdvisoryCompany $model): array {
return [
'id' => $model->uuid,
'title' => $model->title
];
}
public function includeAdvisory(AdvisoryCompany $model): ?Item {
return $model->advisory ? $this->item($model->advisory, new AdvisoryTransformer()) : null;
}
public function includeCompany(AdvisoryCompany $model): ?Item {
return $model->company ? $this->item($model->company, new CompanyTransformer()) : null;
}
public function includeVoter(AdvisoryCompany $model): ?Item {
return $model->voter ? $this->item($model->voter, new AdvisoryMemberTransformer()) : null;
}
public function includeAdvisoryMembers(AdvisoryCompany $model): Collection {
return $this->collection($model->advisoryMembers()->whereIn('rank', [AdvisoryMemberRank::ORDINARY, AdvisoryMemberRank::VOTER])->get(), new AdvisoryMemberTransformer());
}
public function includeCompanyMembers(AdvisoryCompany $model): Collection {
return $this->collection($model->companyMembers, new CompanyMemberTransformer());
}
public function includePermissions(AdvisoryCompany $model): Primitive {
return $this->primitive((new PermissionsService($model))->get());
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace App\Transformers\Advisories;
use App\Models\Advisories\AdvisoryMember;
use App\Transformers\Companies\CompanyMemberTransformer;
use League\Fractal\Resource\Item;
use League\Fractal\TransformerAbstract;
class AdvisoryMemberTransformer extends TransformerAbstract {
protected array $defaultIncludes = [];
protected array $availableIncludes = [
'advisory', 'companyMember'
];
public function transform(AdvisoryMember $model): array {
return [
'id' => $model->uuid,
'rank' => $model->parsedRank,
'title' => $model->title
];
}
public function includeAdvisory(AdvisoryMember $model): ?Item {
return $model->advisory ? $this->item($model->advisory, new AdvisoryTransformer()) : null;
}
public function includeCompanyMember(AdvisoryMember $model): ?Item {
return $model->companyMember ? $this->item($model->companyMember, new CompanyMemberTransformer()) : null;
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace App\Transformers\Advisories;
use App\Models\Advisories\Advisory;
use App\Services\PermissionsService;
use App\Transformers\Assets\AssetTransformer;
use App\Transformers\Companies\CompanyMemberTransformer;
use App\Transformers\Companies\CompanyTransformer;
use App\Transformers\Objects\ObjectTransformer;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item;
use League\Fractal\Resource\Primitive;
use League\Fractal\TransformerAbstract;
class AdvisoryTransformer extends TransformerAbstract {
protected array $defaultIncludes = [];
protected array $availableIncludes = [
'logo', 'document', 'companies', 'advisoryCompanies', 'members', 'secretary', 'parent', 'children', 'object', 'permissions'
];
public function transform(Advisory $model): array {
return [
'id' => $model->uuid,
'type' => $model->parsedType,
'name' => $model->name,
'title' => $model->title,
'number' => $model->number,
'email' => $model->email,
'phone' => $model->phone,
'director_name' => $model->director_name,
'secretary_name' => $model->secretary_name,
'is_main' => boolval($model->is_main),
'caption' => $model->caption
];
}
public function includeLogo(Advisory $model): ?Item {
return $model->logo ? $this->item($model->logo, new AssetTransformer()) : null;
}
public function includeDocument(Advisory $model): ?Item {
return $model->document ? $this->item($model->document, new AssetTransformer()) : null;
}
public function includeCompanies(Advisory $model): Collection {
return $this->collection($model->companies, new CompanyTransformer());
}
public function includeAdvisoryCompanies(Advisory $model): Collection {
return $this->collection($model->advisoryCompanies, new AdvisoryCompanyTransformer());
}
public function includeMembers(Advisory $model): Collection {
return $this->collection($model->members, new AdvisoryMemberTransformer());
}
public function includeSecretary(Advisory $model): ?Item {
return $model->secretary ? $this->item($model->secretary, new CompanyMemberTransformer()) : null;
}
public function includeParent(Advisory $model): ?Item {
return $model->parent ? $this->item($model->parent, new AdvisoryTransformer()) : null;
}
public function includeChildren(Advisory $model): Collection {
return $this->collection($model->children, new AdvisoryTransformer());
}
public function includeObject(Advisory $model): ?Item {
return $model->object ? $this->item($model->object, new ObjectTransformer()) : null;
}
public function includePermissions(Advisory $model): Primitive {
return $this->primitive((new PermissionsService($model))->get());
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\Transformers\Companies;
use App\Models\Companies\Address;
use League\Fractal\Resource\Item;
use League\Fractal\TransformerAbstract;
class AddressTransformer extends TransformerAbstract {
protected array $defaultIncludes = [];
protected array $availableIncludes = [
'company'
];
public function transform(Address $model): array {
return [
'id' => $model->uuid,
'type' => $model->type,
'full' => $model->full,
'postcode' => $model->postcode,
'country' => $model->country,
'region' => $model->region,
'city' => $model->city,
'district' => $model->district,
'street' => $model->street,
'house' => $model->house,
'block' => $model->block,
'office' => $model->office
];
}
public function includeCompany(Address $model): ?Item {
return $model->company ? $this->item($model->company, new CompanyTransformer()) : null;
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace App\Transformers\Companies;
use App\Models\Companies\BankDetails;
use League\Fractal\Resource\Item;
use League\Fractal\TransformerAbstract;
class BankDetailsTransformer extends TransformerAbstract {
protected array $defaultIncludes = [
];
protected array $availableIncludes = [
'company'
];
public function transform(BankDetails $model): array {
return [
'id' => $model->uuid,
'bik' => $model->bik,
'bank' => $model->bank,
'address' => $model->address,
'checking_account' => $model->checking_account,
'correspondent_account' => $model->correspondent_account
];
}
public function includeCompany(BankDetails $model): ?Item {
return $model->company ? $this->item($model->company, new CompanyTransformer()) : null;
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace App\Transformers\Companies;
use App\Models\Companies\CompanyMember;
use App\Transformers\Advisories\AdvisoryMemberTransformer;
use App\Transformers\Users\UserTransformer;
use Illuminate\Support\Facades\Auth;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item;
use League\Fractal\Resource\Primitive;
use League\Fractal\TransformerAbstract;
class CompanyMemberTransformer extends TransformerAbstract {
protected array $defaultIncludes = [
];
protected array $availableIncludes = [
'user', 'company', 'department', 'advisoryMembership', 'isSubordinate'
];
public function transform(CompanyMember $model): array {
return [
'id' => $model->uuid,
'position' => $model->position,
'rank' => $model->parsedRank,
'role' => $model->parsedRole,
'caption' => $model->user->name,
'subtitle' => "{$model->company->name}, {$model->position}",
'room' => $model->room,
'intercom' => $model->intercom
];
}
public function includeUser(CompanyMember $model): ?Item {
return $model->user ? $this->item($model->user, new UserTransformer()) : null;
}
public function includeCompany(CompanyMember $model): ?Item {
return $model->company ? $this->item($model->company, new CompanyTransformer()) : null;
}
public function includeDepartment(CompanyMember $model): ?Item {
return $model->department ? $this->item($model->department, new DepartmentTransformer()) : null;
}
public function includeAdvisoryMembership(CompanyMember $model): Collection {
return $this->collection($model->advisoryMembership, new AdvisoryMemberTransformer());
}
public function includeIsSubordinate(CompanyMember $model): ?Primitive {
return $this->primitive($model->isSubordinateFor(Auth::user()));
}
}

View File

@ -0,0 +1,100 @@
<?php
namespace App\Transformers\Companies;
use App\Models\Companies\Company;
use App\Services\PermissionsService;
use App\Transformers\Advisories\AdvisoryCompanyTransformer;
use App\Transformers\Assets\AssetTransformer;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item;
use League\Fractal\Resource\Primitive;
use League\Fractal\TransformerAbstract;
class CompanyTransformer extends TransformerAbstract {
protected array $defaultIncludes = [];
protected array $availableIncludes = [
'logo', 'types', 'departments', 'rootDepartment', 'members', 'rootMembers', 'representativeMember',
'addresses', 'legalAddress', 'actualAddress', 'bankDetails', 'contacts', 'phones', 'emails', 'permissions',
'advisoryCompanies'
];
public function transform(Company $model): array {
return [
'id' => $model->uuid,
'name' => $model->name,
'full_name' => $model->full_name,
'inn' => $model->inn,
'kpp' => $model->kpp,
'ogrn' => $model->ogrn,
'okved' => $model->okved,
'okato' => $model->okato,
'tax_registration_date' => $model->tax_registration_date ? $model->tax_registration_date->toIso8601String() : null
];
}
public function includeLogo(Company $model): ?Item {
return $model->logo ? $this->item($model->logo, new AssetTransformer()) : null;
}
public function includeTypes(Company $model): Collection {
return $this->collection($model->types, new CompanyTypeTransformer());
}
public function includeDepartments(Company $model): Collection {
return $this->collection($model->departments, new DepartmentTransformer());
}
public function includeRootDepartment(Company $model): ?Item {
return $model->rootDepartment ? $this->item($model->rootDepartment, new DepartmentTransformer()) : null;
}
public function includeMembers(Company $model): Collection {
return $this->collection($model->members, new CompanyMemberTransformer());
}
public function includeRootMembers(Company $model): Collection {
return $this->collection($model->rootMembers, new CompanyMemberTransformer());
}
public function includeRepresentativeMember(Company $model): ?Item {
return $model->representativeMember ? $this->item($model->representativeMember, new CompanyMemberTransformer()) : null;
}
public function includeAddresses(Company $model): Collection {
return $this->collection($model->addresses, new AddressTransformer());
}
public function includeLegalAddress(Company $model): Item {
return $this->item($model->legalAddress, new AddressTransformer());
}
public function includeActualAddress(Company $model): Item {
return $this->item($model->actualAddress, new AddressTransformer());
}
public function includeBankDetails(Company $model): Item {
return $this->item($model->bankDetails, new BankDetailsTransformer());
}
public function includeContacts(Company $model): Collection {
return $this->collection($model->contacts, new ContactTransformer());
}
public function includePhones(Company $model): Collection {
return $this->collection($model->phones, new ContactTransformer());
}
public function includeEmails(Company $model): Collection {
return $this->collection($model->emails, new ContactTransformer());
}
public function includePermissions(Company $model): Primitive {
return $this->primitive((new PermissionsService($model))->get());
}
public function includeAdvisoryCompanies(Company $model): Collection {
return $this->collection($model->advisoryCompanies, new AdvisoryCompanyTransformer());
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace App\Transformers\Companies;
use App\Models\Companies\CompanyType;
use League\Fractal\Resource\Item;
use League\Fractal\TransformerAbstract;
class CompanyTypeTransformer extends TransformerAbstract {
protected array $defaultIncludes = [
];
protected array $availableIncludes = [
'company'
];
public function transform(CompanyType $model): array {
return [
'id' => $model->name,
'name' => $model->name,
'title' => $model->title
];
}
public function includeCompany(CompanyType $model): ?Item {
return $model->company ? $this->item($model->company, new CompanyTransformer()) : null;
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Transformers\Companies;
use App\Models\Companies\Contact;
use League\Fractal\Resource\Item;
use League\Fractal\TransformerAbstract;
class ContactTransformer extends TransformerAbstract {
protected array $defaultIncludes = [
];
protected array $availableIncludes = [
'company'
];
public function transform(Contact $model): array {
return [
'type' => $model->parsedType,
'value' => $model->value
];
}
public function includeCompany(Contact $model): ?Item {
return $model->company ? $this->item($model->company, new CompanyTransformer()) : null;
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace App\Transformers\Companies;
use App\Models\Companies\Department;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\Item;
use League\Fractal\TransformerAbstract;
class DepartmentTransformer extends TransformerAbstract {
protected array $defaultIncludes = [];
protected array $availableIncludes = [
'company', 'parent', 'children', 'members'
];
public function transform(Department $model): array {
return [
'id' => $model->uuid,
'name' => $model->name,
'title' => $model->title
];
}
public function includeCompany(Department $model): ?Item {
return $model->company ? $this->item($model->company, new CompanyTransformer()) : null;
}
public function includeParent(Department $model): ?Item {
return $model->parent ? $this->item($model->parent, new DepartmentTransformer()) : null;
}
public function includeChildren(Department $model): Collection {
return $this->collection($model->children, new DepartmentTransformer());
}
public function includeMembers(Department $model): Collection {
return $this->collection($model->members, new CompanyMemberTransformer());
}
}

View File

@ -0,0 +1,44 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCompaniesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('companies', function (Blueprint $table) {
$table->id();
$table->char('uuid', 36)->index()->unique();
$table->integer('logo_id')->nullable();
$table->string('name')->nullable();
$table->string('full_name', 500)->nullable();
$table->string('inn')->index()->unique();
$table->string('kpp', 20)->nullable();
$table->string('ogrn', 20)->nullable();
$table->string('okpo', 20)->nullable();
$table->string('okved', 20)->nullable();
$table->string('okato', 20)->nullable();
$table->timestamp('tax_registration_date')->nullable();
$table->boolean('is_main')->index()->default(0);
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('companies');
}
}

View File

@ -0,0 +1,43 @@
<?php
use App\Models\Companies\CompanyMemberRank;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCompanyMembersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('company_members', function (Blueprint $table) {
$table->id();
$table->char('uuid', 36)->index()->unique();
$table->integer('user_id')->index()->nullable();
$table->integer('company_id')->index()->nullable();
$table->integer('department_id')->index()->nullable();
$table->smallInteger('rank')->index()->default(CompanyMemberRank::EMPLOYEE);
$table->string('role')->index()->nullable();
$table->string('position')->index()->nullable();
$table->string('room')->index()->nullable();
$table->string('intercom')->index()->nullable();
$table->boolean('selected')->index()->default(0);
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('company_members');
}
}

View File

@ -0,0 +1,45 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCompanyAddressesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('company_addresses', function (Blueprint $table) {
$table->id();
$table->char('uuid', 36)->index()->unique();
$table->integer('company_id')->index();
$table->string('type')->index();
$table->string('full', 500)->nullable();
$table->string('postcode')->nullable();
$table->string('country')->nullable();
$table->string('region')->nullable();
$table->string('city')->nullable();
$table->string('district')->nullable();
$table->string('street')->nullable();
$table->string('house')->nullable();
$table->string('block')->nullable();
$table->string('office')->nullable();
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('company_addresses');
}
}

View File

@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCompanyBankDetailsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('company_bank_details', function (Blueprint $table) {
$table->id();
$table->char('uuid', 36)->index()->unique();
$table->integer('company_id')->index();
$table->string('bik')->nullable();
$table->string('bank')->nullable();
$table->string('address')->nullable();
$table->string('checking_account')->nullable();
$table->string('correspondent_account')->nullable();
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('company_bank_details');
}
}

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCompanyContactsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('company_contacts', function (Blueprint $table) {
$table->id();
$table->integer('company_id')->index();
$table->string('type', 20)->index();
$table->string('value')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('company_contacts');
}
}

View File

@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCompanyDepartmentsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('company_departments', function (Blueprint $table) {
$table->id();
$table->char('uuid', 36)->index()->unique();
$table->integer('company_id')->nullable()->index();
$table->integer('parent_id')->nullable()->index();
$table->string('name')->index()->nullable();
$table->string('title')->index()->nullable();
$table->smallInteger('level')->index()->default(0);
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('company_departments');
}
}

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCompanyTypesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('company_types', function (Blueprint $table) {
$table->id();
$table->integer('company_id')->index()->nullable();
$table->string('name')->index()->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('company_types');
}
}

View File

@ -0,0 +1,45 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateAdvisoriesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('advisories', function (Blueprint $table) {
$table->id();
$table->char('uuid', 36)->index()->unique();
$table->integer('parent_id')->index()->default(0);
$table->integer('logo_id')->nullable();
$table->integer('document_id')->nullable();
$table->string('type')->index()->nullable();
$table->string('name')->index()->nullable();
$table->string('title')->index()->nullable();
$table->string('number')->index()->nullable();
$table->string('email')->index()->nullable();
$table->string('phone')->index()->nullable();
$table->string('director_name')->index()->nullable();
$table->string('secretary_name')->index()->nullable();
$table->boolean('is_main')->index()->default(0);
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('advisories');
}
}

View File

@ -0,0 +1,37 @@
<?php
use App\Models\Advisories\AdvisoryMemberRank;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateAdvisoryMembersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('advisory_members', function (Blueprint $table) {
$table->id();
$table->char('uuid', 36)->index()->unique();
$table->integer('advisory_id')->index()->nullable();
$table->integer('company_member_id')->index()->nullable();
$table->integer('rank')->index()->default(AdvisoryMemberRank::ORDINARY);
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('advisory_members');
}
}

View File

@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateAdvisoryCompaniesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('advisory_companies', function (Blueprint $table) {
$table->id();
$table->char('uuid', 36)->index()->unique();
$table->integer('advisory_id')->index()->nullable();
$table->integer('company_id')->index()->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('advisory_companies');
}
}

View File

@ -0,0 +1,83 @@
<?php
namespace Database\Seeders\Advisories;
use App\Imports\AdvisoryMembersImport;
use App\Models\Advisories\Advisory;
use App\Models\Advisories\AdvisoryType;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Storage;
use Maatwebsite\Excel\Facades\Excel;
class AdvisoriesTableSeeder extends Seeder {
public array $advisories = [
'tk465' => [
'number' => 'ТК 465',
'title' => 'Строительство',
'type' => AdvisoryType::COMMITTEE,
'is_main' => true,
//'members' => ['import' => 'import/advisories/tk465_members.xlsx'],
'children' => [
'group1' => [
'title' => 'Организационно-методические и общетехнические вопросы в строительстве',
'children' => [
'pk2' => [
'title' => 'Проектирование. Основные положения нормирования',
'number' => 'ПК 2',
'type' => AdvisoryType::COMMITTEE
],
'pk4' => [
'title' => 'Обследование и мониторинг технического состояния зданий и сооружений. Ремонт, восстановление и усиление конструкций зданий и сооружений',
'number' => 'ПК 4',
'type' => AdvisoryType::COMMITTEE
],
'pk6' => [
'title' => 'Пожаробезопасность в строительстве',
'number' => 'ПК 6',
'type' => AdvisoryType::COMMITTEE
]
]
],
'group2' => [
'title' => 'Здания и сооружения',
'children' => [
'pk10' => [
'title' => 'Жилые, общественные и производственные здания и сооружения',
'number' => 'ПК 2',
'type' => AdvisoryType::COMMITTEE
]
]
],
'group3' => [
'title' => 'Наружные и внутренние инженерные сети и оборудование',
'children' => []
],
'group4' => [
'title' => 'Строительные конструкции и основания',
'children' => []
]
]
]
];
public function run() {
collect($this->advisories)->each(function($data, $name) {
$this->importAdvisory($name, $data);
});
}
public function importAdvisory($name, $data, $parent = null) {
$query = $parent ? $parent->children() : Advisory::query();
$advisory = $query->firstOrCreate(['name' => $name]);
$advisory->update(collect($data)->except('members', 'children')->all());
$this->importAdvisoryMembers($advisory, $data['members'] ?? []);
collect($data['children'] ?? [])->each(function($data, $name) use($advisory) {
$this->importAdvisory($name, $data, $advisory);
});
}
public function importAdvisoryMembers(Advisory $advisory, $data) {
if ($path = $data['import'] ?? null) Excel::import(new AdvisoryMembersImport($advisory), Storage::path($path));
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace Database\Seeders\Advisories;
use Illuminate\Database\Seeder;
class AdvisoriesTablesSeeder extends Seeder {
public function run() {
$this->call(AdvisoriesTableSeeder::class);
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace Database\Seeders\Companies;
use App\Imports\CompaniesImport;
use App\Models\Companies\Company;
use App\Models\Companies\CompanyMemberRank;
use App\Models\Companies\Department;
use App\Models\User;
use App\Services\DaDataService;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Storage;
use Maatwebsite\Excel\Facades\Excel;
class CompaniesTableSeeder extends Seeder {
public array $companies = [
'7736151499' => [
'is_main' => 1,
'members' => [
'test1@testnir.ru' => ['name' => 'Иванов Иван Иванович', 'position' => 'Генеральный директор', 'rank' => CompanyMemberRank::CHIEF],
'test2@testnir.ru' => ['name' => 'Петров Петр Петрович', 'position' => 'Заместитель генерального директора', 'rank' => CompanyMemberRank::VICE]
]
]
];
public string $import = '';
public function run() {
collect($this->companies)->each(function($data, $inn) {
$company = Company::query()->firstOrCreate(['inn' => $inn]);
(new DaDataService($inn))->saveToCompany($company);
$company->update(collect($data)->except('departments', 'members', 'phone', 'email')->all());
$company->setEmail($data['email'] ?? null);
$company->setPhone($data['phone'] ?? null);
$this->syncMembers($company->rootDepartment, $data['members'] ?? []);
$this->syncDepartments($company->rootDepartment, $data['departments'] ?? []);
});
if ($this->import && Storage::exists($this->import)) Excel::import(new CompaniesImport(), Storage::path($this->import));
}
public function syncDepartments(Department $parent, $data) {
collect($data)->each(function($data, $name) use($parent) {
if ($department = $parent->addChildren($name, $data['title'] ?? null)) {
$this->syncMembers($department, $data['members'] ?? []);
$this->syncDepartments($department, $data['departments'] ?? []);
}
});
}
public function syncMembers(Department $department, $data) {
collect($data)->each(function($data, $email) use($department) {
$user = User::getByData(['email' => $email, 'name' => $data['name'] ?? '']);
$member = $department->addMember($user, $data['position'] ?? '');
$member->update(['rank' => $data['rank'] ?? CompanyMemberRank::EMPLOYEE]);
});
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace Database\Seeders\Companies;
use Illuminate\Database\Seeder;
class CompaniesTablesSeeder extends Seeder {
public function run() {
$this->call(CompaniesTableSeeder::class);
}
}

View File

@ -2,6 +2,8 @@
namespace Database\Seeders;
use Database\Seeders\Advisories\AdvisoriesTablesSeeder;
use Database\Seeders\Companies\CompaniesTablesSeeder;
use Database\Seeders\Dictionaries\DictionariesTablesSeeder;
use Database\Seeders\Objects\ObjectsTablesSeeder;
use Database\Seeders\Pages\PagesTableSeeder;
@ -17,5 +19,7 @@ class DatabaseSeeder extends Seeder {
$this->call(ObjectsTablesSeeder::class);
$this->call(DictionariesTablesSeeder::class);
$this->call(PagesTableSeeder::class);
$this->call(CompaniesTablesSeeder::class);
$this->call(AdvisoriesTablesSeeder::class);
}
}

View File

@ -35,7 +35,7 @@ class DictionariesTableSeeder extends Seeder {
],
'activities' => [
'title' => 'Направления деятельности',
'items' => ['products' => 'Продукция', 'services' => 'Работы и услуги', 'management' => 'СМК']
'items' => ['products' => 'Продукция в строительстве', 'services' => 'Работы и услуги', 'management' => 'СМК']
],
'research-types' => [
'title' => 'Виды исследовательских работ',

View File

@ -175,7 +175,7 @@ class FieldsTableSeeder extends Seeder {
'required' => true
],
'activities' => [
'title' => 'Виды деятельности',
'title' => 'Объект сертификации',
'type' => FieldType::RELATION,
'required' => true,
'multiple' => true,

View File

@ -73,7 +73,7 @@ class PagesTableSeeder extends Seeder
'children' => [
'Руководство' => [],
'Секретариат' => [],
'Структура' => [],
'Структура' => ['type' => PageType::TK_STRUCTURE],
'Состав' => [],
'Документы' => ['type' => PageType::REGISTRY, 'registry_type' => RegistryType::CATEGORIZED],
'АИС ТК 465 «Строительство»' => [],
@ -95,14 +95,14 @@ class PagesTableSeeder extends Seeder
'Добровольная сертификация' => [
'children' => [
'О системе' => [],
'Основополагающие документы' => [],
'Решения ЦОС' => [],
'Руководящие документы' => [],
'Основополагающие документы' => ['type' => PageType::REGISTRY, 'registry_type' => RegistryType::CATEGORIZED],
'Решения ЦОС' => ['type' => PageType::REGISTRY, 'registry_type' => RegistryType::SIMPLE],
'Руководящие документы' => ['type' => PageType::REGISTRY, 'registry_type' => RegistryType::SIMPLE],
'Реестр органов по сертификации' => ['type' => PageType::REGISTRY, 'registry_type' => RegistryType::CERTIFIERS],
'Реестр испытательных лабораторий' => ['type' => PageType::REGISTRY, 'registry_type' => RegistryType::LABORATORIES],
'Реестр экспертов' => ['type' => PageType::REGISTRY, 'registry_type' => RegistryType::EXPERTS],
'Реестр сертификатов соответствия' => ['type' => PageType::REGISTRY, 'registry_type' => RegistryType::CERTIFICATES],
'Бланки документов' => [],
'Бланки документов' => ['type' => PageType::REGISTRY, 'registry_type' => RegistryType::SIMPLE],
]
],
'Международная деятельность' => [

View File

@ -78,4 +78,14 @@ Route::group(['middleware' => ['auth:api']], function() {
Route::put('publications/published/{id}', 'Api\Publications\PublicationsController@published');
Route::delete('publications/{id}', 'Api\Publications\PublicationsController@destroy');
Route::apiResource('companies', 'Api\Companies\CompaniesController');
Route::apiResource('members', 'Api\Companies\MembersController');
Route::apiResource('departments', 'Api\Companies\DepartmentsController');
Route::apiResource('advisories', 'Api\Advisories\AdvisoriesController');
Route::get('advisories/{id}/siblings', 'Api\Advisories\AdvisoriesController@siblings');
Route::apiResource('advisory-companies', 'Api\Advisories\AdvisoryCompaniesController');
Route::apiResource('advisory-members', 'Api\Advisories\AdvisoryMembersController');
});

File diff suppressed because one or more lines are too long