input('settings'); return response()->json( CompanySetting::getSettings($wanted, $request->header('company')) ); } /** * Write a batch of preferences, upserting option by option. * * One of them is guarded: the trading currency is frozen as soon as the * company has anything on its books, and an attempt to move it is refused * with a plain 200 carrying `success: false` — no status code, no error * bag. The comparison against the stored value is strict, so submitting * the current currency as a number when the store holds it as a string * counts as a change and trips the guard. */ public function update(UpdateSettingsRequest $request): JsonResponse { $company = Company::query()->find($request->header('company')); $this->authorize('manage company', $company); $submitted = $request->input('settings'); if ($this->movesCurrency($submitted, $company) && $company->hasTransactions()) { return response()->json([ 'success' => false, 'message' => 'Cannot update company currency after transactions are created.', ]); } CompanySetting::setSettings($submitted, $request->header('company')); return response()->json([ 'success' => true, ]); } /** * Whether the company has anything on its books yet — the flag the SPA * uses to grey out the currency selector before the write is attempted. */ public function checkTransactions(Request $request): JsonResponse { $company = Company::query()->find($request->header('company')); $this->authorize('manage company', $company); return response()->json([ 'has_transactions' => $company->hasTransactions(), ]); } /** * Hand the active company to one of its members. * * The target has to be a member already; a stranger is turned away with a * 200 carrying `success: false`, in the same shape as the currency guard. * On success the owner column moves and the target's roles in this company * are replaced by `owner` alone. Nothing is taken away from the outgoing * owner beyond the column itself — their role assignments stay, and with * them everything those roles allow. */ public function transferOwnership(Request $request, User $user): JsonResponse { $company = Company::query()->find($request->header('company')); $this->authorize('transfer company ownership', $company); if (! $user->hasCompany($company->id)) { return response()->json([ 'success' => false, 'message' => 'User does not belong to this company.', ]); } $company->update(['owner_id' => $user->id]); BouncerFacade::scope()->to($company->id); BouncerFacade::sync($user)->roles(['owner']); return response()->json([ 'success' => true, ]); } /** * Whether the submitted batch carries a currency different from the one on * file. A batch without a currency key never trips the guard, even when * the company is trading. */ private function movesCurrency(mixed $submitted, Company $company): bool { if (! Arr::exists($submitted, 'currency')) { return false; } return CompanySetting::getSetting('currency', $company->id) !== $submitted['currency']; } }