webmoney/backend/app/Http/Controllers/Api/BusinessSettingController.php

232 lines
8.4 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\BusinessSetting;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class BusinessSettingController extends Controller
{
/**
* Lista todas as configurações de negócio do usuário
*/
public function index(Request $request): JsonResponse
{
$userId = $request->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,
]));
}
}