- Add business_settings table for Markup configuration - Add product_sheets table for product technical sheets (CMV) - Add product_sheet_items table for cost components - Create BusinessSetting model with calculateMarkup() method - Create ProductSheet model with recalculateCmv() method - Create ProductSheetItem model for cost breakdown - Add BusinessSettingController with CRUD + simulate-price endpoint - Add ProductSheetController with CRUD + items management + duplicate - Add Business page with 3 tabs (Settings, Products, Calculator) - Add BusinessSettingsTab component with markup cards - Add ProductSheetsTab component with product grid - Add PriceCalculatorTab component with interactive simulator - Add i18n translations in ES, PT-BR, EN - Multi-currency support (EUR, BRL, USD)
140 lines
3.2 KiB
PHP
140 lines
3.2 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
|
|
class ProductSheet extends Model
|
|
{
|
|
use HasFactory;
|
|
|
|
protected $fillable = [
|
|
'user_id',
|
|
'business_setting_id',
|
|
'name',
|
|
'sku',
|
|
'description',
|
|
'category',
|
|
'currency',
|
|
'cmv_total',
|
|
'sale_price',
|
|
'markup_used',
|
|
'contribution_margin',
|
|
'is_active',
|
|
];
|
|
|
|
protected $casts = [
|
|
'cmv_total' => 'decimal:2',
|
|
'sale_price' => 'decimal:2',
|
|
'markup_used' => 'decimal:4',
|
|
'contribution_margin' => 'decimal:2',
|
|
'is_active' => 'boolean',
|
|
];
|
|
|
|
/**
|
|
* Relacionamento com usuário
|
|
*/
|
|
public function user(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class);
|
|
}
|
|
|
|
/**
|
|
* Relacionamento com configuração de negócio
|
|
*/
|
|
public function businessSetting(): BelongsTo
|
|
{
|
|
return $this->belongsTo(BusinessSetting::class);
|
|
}
|
|
|
|
/**
|
|
* Itens/componentes de custo desta ficha técnica
|
|
*/
|
|
public function items(): HasMany
|
|
{
|
|
return $this->hasMany(ProductSheetItem::class)->orderBy('sort_order');
|
|
}
|
|
|
|
/**
|
|
* Recalcula o CMV total baseado nos itens
|
|
*
|
|
* @return float
|
|
*/
|
|
public function recalculateCmv(): float
|
|
{
|
|
$this->cmv_total = $this->items()->sum('unit_cost');
|
|
$this->save();
|
|
|
|
return $this->cmv_total;
|
|
}
|
|
|
|
/**
|
|
* Calcula e atualiza o preço de venda usando o Markup da configuração
|
|
*
|
|
* @param BusinessSetting|null $businessSetting
|
|
* @return float
|
|
*/
|
|
public function calculateSalePrice(?BusinessSetting $businessSetting = null): float
|
|
{
|
|
$setting = $businessSetting ?? $this->businessSetting;
|
|
|
|
if (!$setting) {
|
|
return 0;
|
|
}
|
|
|
|
$markup = $setting->markup_factor ?? $setting->calculateMarkup();
|
|
|
|
if ($markup <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
$this->markup_used = $markup;
|
|
$this->sale_price = round($this->cmv_total * $markup, 2);
|
|
$this->contribution_margin = $this->sale_price - $this->cmv_total;
|
|
$this->save();
|
|
|
|
return $this->sale_price;
|
|
}
|
|
|
|
/**
|
|
* Retorna a margem de contribuição percentual
|
|
*
|
|
* @return float
|
|
*/
|
|
public function getContributionMarginPercentAttribute(): float
|
|
{
|
|
if ($this->sale_price <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
return round(($this->contribution_margin / $this->sale_price) * 100, 2);
|
|
}
|
|
|
|
/**
|
|
* Scope para buscar fichas do usuário
|
|
*/
|
|
public function scopeOfUser($query, $userId)
|
|
{
|
|
return $query->where('user_id', $userId);
|
|
}
|
|
|
|
/**
|
|
* Scope para buscar apenas fichas ativas
|
|
*/
|
|
public function scopeActive($query)
|
|
{
|
|
return $query->where('is_active', true);
|
|
}
|
|
|
|
/**
|
|
* Scope para buscar por categoria
|
|
*/
|
|
public function scopeByCategory($query, $category)
|
|
{
|
|
return $query->where('category', $category);
|
|
}
|
|
}
|