webmoney/backend/app/Models/ProductSheet.php
CnxiFly Dev 84d9d7d187 feat(business): add Business section with Markup pricing v1.28.0
- 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)
2025-12-14 07:44:18 +01:00

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);
}
}