notesHistory()->with('user:id,name'); if (! auth()->user()->hasRole('admin')) { $query->where(fn ($visibility) => $visibility ->where('visibility', '<>', 'private') ->orWhere('user_id', auth()->id())); } $notes = $query->orderByDesc('is_pinned')->latest()->get(); return ApiResponse::success($notes->map(fn (Note $note) => $this->resource($note))->all()); } public function callStore(StoreCallNoteRequest $request, Call $call): JsonResponse { Gate::authorize('create', [Note::class, $call]); $note = DB::transaction(function () use ($request, $call): Note { $note = $call->notesHistory()->create([ 'user_id' => $request->user()->id, 'content' => $request->validated('content'), 'type' => $request->validated('type', 'general'), 'visibility' => $request->validated('visibility', 'team'), ]); ActivityLogger::log('call_note_created', "Call note {$note->id} created", $note, null, $note->only(['type', 'visibility', 'is_pinned'])); return $note; }); return ApiResponse::success($this->resource($note->load('user:id,name')), 201, 'یادداشت تماس ثبت شد.'); } public function store(Request $request): JsonResponse { $validated = $request->validate([ 'entity_type' => 'required|in:lead,company,deal', 'entity_id' => 'required|integer', 'content' => 'required|string|max:5000', ]); $model = EntityResolver::authorize($validated['entity_type'], $validated['entity_id'], 'update'); $note = DB::transaction(function () use ($model, $validated): Note { $note = $model->notes()->create([ 'user_id' => auth()->id(), 'content' => $validated['content'], 'type' => 'general', 'visibility' => 'team', ]); ActivityLogger::log('note_created', 'یادداشت جدید ثبت شد', $note, null, $note->only(['type', 'visibility'])); return $note; }); return ApiResponse::success($this->resource($note->load('user:id,name')), 201, 'یادداشت ثبت شد.'); } public function update(UpdateNoteRequest $request, Note $note): JsonResponse { Gate::authorize('update', $note); $updated = DB::transaction(function () use ($request, $note): Note { $before = $note->only(['type', 'visibility', 'is_pinned']); $note->fill($request->validated()); $note->edited_at = now(); $note->save(); ActivityLogger::log('call_note_edited', "Note {$note->id} edited", $note, $before, $note->only(['type', 'visibility', 'is_pinned'])); return $note; }); return ApiResponse::success($this->resource($updated->load('user:id,name')), message: 'یادداشت ویرایش شد.'); } public function destroy(Note $note): JsonResponse { Gate::authorize('delete', $note); DB::transaction(function () use ($note): void { $before = $note->only(['type', 'visibility', 'is_pinned']); $note->delete(); ActivityLogger::log('call_note_deleted', "Note {$note->id} deleted", $note, $before, ['deleted' => true]); }); return ApiResponse::success(null, message: 'یادداشت حذف شد.'); } public function pin(Note $note): JsonResponse { return $this->setPinned($note, true); } public function unpin(Note $note): JsonResponse { return $this->setPinned($note, false); } private function setPinned(Note $note, bool $pinned): JsonResponse { Gate::authorize('pin', $note); $note->update(['is_pinned' => $pinned]); ActivityLogger::log($pinned ? 'call_note_pinned' : 'call_note_unpinned', "Note {$note->id} pin changed", $note, ['is_pinned' => ! $pinned], ['is_pinned' => $pinned]); return ApiResponse::success($this->resource($note->load('user:id,name')), message: $pinned ? 'یادداشت سنجاق شد.' : 'سنجاق یادداشت برداشته شد.'); } private function resource(Note $note): array { return (new NoteResource($note))->resolve(request()); } }