public function rules()
{
return [
'table_id' => [
'numeric',
Rule::exists('tables', 'id')->where(function ($query) {
# проверка принадлежности стола и заказа к одному проекту
return $query->where('project_id', $this->project->id);
}),
Rule::unique('orders')->where(function ($query) {
# проверка доступности стола (нет ли на нем заказов в указанных статусах)
return $query->where('table_id', $this->table_id)->whereIn('status', [Order::NEW, Order::WORK, Order::PAID]);
}),
],
'user_id' => [
'nullable',
'numeric',
'exists:users,id',
new UserAssigneeToOrderRule($this->project),
],
'status' => ['string', new OrderStatusRule($this->order)],
];
}
class UserAssigneeToOrderRule implements InvokableRule
{
private Project $project;
public function __construct (Project $project) {
$this->project = $project;
}
/**
* Run the validation rule.
*
* @param string $attribute
* @param mixed $value
* @param \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail
* @return void
*/
public function __invoke($attribute, $value, $fail)
{
# @owner - может назначать на всех и на себя
# @admin - может назначать на employee и на себя
# @employee - может назначать на себя
$user = $this->project->users()->firstWhere('users.id', $value);
if (auth()->user()->isOwner() && !$user && auth()->id() != $value) {
$fail('Пользователь не принадлежит проекту');
}
if (!auth()->user()->isOwner() && !$user) {
$fail('Пользователь не принадлежит проекту');
}
if (auth()->user()->isAdmin() && (auth()->id() !== $user?->id || !$user->isEmployee())) {
$fail('Можно назначать на себя, либо на сотрудника');
}
if (auth()->user()->isEmployee() && auth()->id() !== $user?->id) {
$fail('Можно назначать только на себя');
}
}
}
class UserAssigneeToOrderRule implements InvokableRule
{
private Project $project;
public function __construct (Project $project) {
$this->project = $project;
}
public function __invoke($attribute, $value, $fail)
{
# @owner - может назначать заказ на всех сотрудников и на себя
# @admin - может назначать на @employee и на себя
# @employee - может назначать на себя
# привязан ли назначаемый сотрудник к проекту (есть связь в таблице project_user)
$user = $this->project->users()->firstWhere('users.id', $value);
if (auth()->user()->isOwner()) {
# если не на себя или нет связанных пользователей (@admin или @employee)
if (!(auth()->id() == $value || $user)) {
$fail('Пользователь не принадлежит проекту');
}
} else if (auth()->user()->isAdmin()) {
# если не на себя или не на сотрудника в роли пользователя от @employee
if (!(auth()->id() === $user?->id || $user?->isEmployee())) {
$fail('Можно назначать на себя, либо на сотрудника');
}
} else if (auth()->user()->isEmployee()) {
# если не на себя
if (!(auth()->id() === $user?->id)) {
$fail('Можно назначать только на себя');
}
}
}
}