user()->id; $settings = BusinessSetting::ofUser($userId) ->orderBy('is_active', 'desc') ->orderBy('name') ->get() ->map(function ($setting) { return array_merge($setting->toArray(), [ 'fixed_expenses_rate' => $setting->fixed_expenses_rate, 'total_variable_costs' => $setting->total_variable_costs, 'markup_breakdown' => $setting->markup_breakdown, ]); }); return response()->json($settings); } /** * Cria uma nova configuração de negócio */ public function store(Request $request): JsonResponse { $validator = Validator::make($request->all(), [ 'name' => 'required|string|max:255', 'currency' => 'required|string|size:3', 'business_type' => 'sometimes|in:products,services,both', 'employees_count' => 'sometimes|integer|min:1', 'hours_per_week' => 'sometimes|numeric|min:1|max:168', 'working_days_per_week' => 'sometimes|integer|min:1|max:7', 'working_days_per_month' => 'sometimes|integer|min:1|max:31', 'productivity_rate' => 'sometimes|numeric|min:1|max:100', 'monthly_revenue' => 'required|numeric|min:0', 'fixed_expenses' => 'required|numeric|min:0', 'tax_rate' => 'required|numeric|min:0|max:100', 'price_includes_tax' => 'sometimes|boolean', 'vat_rate' => 'sometimes|numeric|min:0|max:100', 'sales_commission' => 'required|numeric|min:0|max:100', 'card_fee' => 'required|numeric|min:0|max:100', 'other_variable_costs' => 'nullable|numeric|min:0|max:100', 'investment_rate' => 'required|numeric|min:0|max:100', 'profit_margin' => 'required|numeric|min:0|max:100', ]); if ($validator->fails()) { return response()->json(['errors' => $validator->errors()], 422); } $data = $validator->validated(); $data['user_id'] = $request->user()->id; $data['other_variable_costs'] = $data['other_variable_costs'] ?? 0; $setting = BusinessSetting::create($data); // Calcular e salvar o markup $setting->recalculateMarkup(); // Recarregar com os dados calculados $setting->refresh(); return response()->json(array_merge($setting->toArray(), [ 'fixed_expenses_rate' => $setting->fixed_expenses_rate, 'total_variable_costs' => $setting->total_variable_costs, 'markup_breakdown' => $setting->markup_breakdown, ]), 201); } /** * Exibe uma configuração específica */ public function show(Request $request, $id): JsonResponse { $setting = BusinessSetting::ofUser($request->user()->id) ->with('productSheets') ->findOrFail($id); return response()->json(array_merge($setting->toArray(), [ 'fixed_expenses_rate' => $setting->fixed_expenses_rate, 'total_variable_costs' => $setting->total_variable_costs, 'markup_breakdown' => $setting->markup_breakdown, ])); } /** * Atualiza uma configuração */ public function update(Request $request, $id): JsonResponse { $setting = BusinessSetting::ofUser($request->user()->id)->findOrFail($id); $validator = Validator::make($request->all(), [ 'name' => 'sometimes|string|max:255', 'currency' => 'sometimes|string|size:3', 'business_type' => 'sometimes|in:products,services,both', 'employees_count' => 'sometimes|integer|min:1', 'hours_per_week' => 'sometimes|numeric|min:1|max:168', 'working_days_per_week' => 'sometimes|integer|min:1|max:7', 'working_days_per_month' => 'sometimes|integer|min:1|max:31', 'productivity_rate' => 'sometimes|numeric|min:1|max:100', 'monthly_revenue' => 'sometimes|numeric|min:0', 'fixed_expenses' => 'sometimes|numeric|min:0', 'tax_rate' => 'sometimes|numeric|min:0|max:100', 'price_includes_tax' => 'sometimes|boolean', 'vat_rate' => 'sometimes|numeric|min:0|max:100', 'sales_commission' => 'sometimes|numeric|min:0|max:100', 'card_fee' => 'sometimes|numeric|min:0|max:100', 'other_variable_costs' => 'sometimes|numeric|min:0|max:100', 'investment_rate' => 'sometimes|numeric|min:0|max:100', 'profit_margin' => 'sometimes|numeric|min:0|max:100', 'is_active' => 'sometimes|boolean', ]); if ($validator->fails()) { return response()->json(['errors' => $validator->errors()], 422); } $setting->update($validator->validated()); // Recalcular markup $setting->recalculateMarkup(); $setting->refresh(); return response()->json(array_merge($setting->toArray(), [ 'fixed_expenses_rate' => $setting->fixed_expenses_rate, 'total_variable_costs' => $setting->total_variable_costs, 'markup_breakdown' => $setting->markup_breakdown, ])); } /** * Remove uma configuração */ public function destroy(Request $request, $id): JsonResponse { $setting = BusinessSetting::ofUser($request->user()->id)->findOrFail($id); // Verificar se há fichas técnicas vinculadas if ($setting->productSheets()->count() > 0) { return response()->json([ 'message' => 'Não é possível excluir: existem fichas técnicas vinculadas a esta configuração.' ], 422); } $setting->delete(); return response()->json(['message' => 'Configuração excluída com sucesso']); } /** * Recalcula o markup de uma configuração */ public function recalculateMarkup(Request $request, $id): JsonResponse { $setting = BusinessSetting::ofUser($request->user()->id)->findOrFail($id); $markup = $setting->recalculateMarkup(); return response()->json([ 'markup_factor' => $markup, 'markup_breakdown' => $setting->markup_breakdown, ]); } /** * Simula um preço de venda dado um CMV */ public function simulatePrice(Request $request, $id): JsonResponse { $setting = BusinessSetting::ofUser($request->user()->id)->findOrFail($id); $validator = Validator::make($request->all(), [ 'cmv' => 'required|numeric|min:0', ]); if ($validator->fails()) { return response()->json(['errors' => $validator->errors()], 422); } $cmv = $request->cmv; $salePrice = $setting->calculateSalePrice($cmv); $contributionMargin = $salePrice - $cmv; $contributionMarginPercent = $salePrice > 0 ? round(($contributionMargin / $salePrice) * 100, 2) : 0; return response()->json([ 'cmv' => $cmv, 'markup_factor' => $setting->markup_factor, 'sale_price' => $salePrice, 'contribution_margin' => $contributionMargin, 'contribution_margin_percent' => $contributionMarginPercent, 'currency' => $setting->currency, 'breakdown' => $setting->markup_breakdown, ]); } /** * Retorna a configuração ativa padrão do usuário */ public function getDefault(Request $request): JsonResponse { $setting = BusinessSetting::ofUser($request->user()->id) ->active() ->first(); if (!$setting) { return response()->json(['message' => 'Nenhuma configuração ativa encontrada'], 404); } return response()->json(array_merge($setting->toArray(), [ 'fixed_expenses_rate' => $setting->fixed_expenses_rate, 'total_variable_costs' => $setting->total_variable_costs, 'markup_breakdown' => $setting->markup_breakdown, ])); } }