* * @version 1.0.0 */ class SaleDetail extends Model { protected $fillable = [ 'sale_id', 'inventory_id', 'bundle_id', 'bundle_sale_group', 'warehouse_id', 'unit_of_measure_id', 'unit_quantity', 'product_name', 'quantity', 'unit_price', 'subtotal', 'discount_percentage', 'discount_amount', ]; protected $casts = [ 'quantity' => 'decimal:3', 'unit_quantity' => 'decimal:3', 'unit_price' => 'decimal:2', 'subtotal' => 'decimal:2', 'discount_percentage' => 'decimal:2', 'discount_amount' => 'decimal:2', ]; public function warehouse() { return $this->belongsTo(Warehouse::class); } public function sale() { return $this->belongsTo(Sale::class); } public function inventory() { return $this->belongsTo(Inventory::class); } public function unitOfMeasure() { return $this->belongsTo(UnitOfMeasurement::class); } public function serials() { return $this->hasMany(InventorySerial::class, 'sale_detail_id'); } /** * Obtener números de serie vendidos */ public function getSerialNumbersAttribute(): array { return $this->serials()->pluck('serial_number')->toArray(); } /** * Devoluciones de este detalle */ public function returnDetails() { return $this->hasMany(ReturnDetail::class); } /** * Cantidad total devuelta */ public function getQuantityReturnedAttribute(): int { return $this->returnDetails()->sum('quantity_returned'); } /** * Cantidad restante (no devuelta) */ public function getQuantityRemainingAttribute(): int { return $this->quantity - $this->getQuantityReturnedAttribute(); } /** * Verificar si se puede devolver más */ public function canReturn(): bool { return $this->getQuantityRemainingAttribute() > 0; } /** * Cantidad máxima que se puede devolver */ public function getMaxReturnableQuantityAttribute(): int { return $this->getQuantityRemainingAttribute(); } /** * Bundle al que pertenece este sale_detail (si es componente de un kit) */ public function bundle() { return $this->belongsTo(Bundle::class); } /** * Verificar si este sale_detail es parte de un kit */ public function isPartOfBundle(): bool { return ! is_null($this->bundle_id); } /** * Obtener todos los sale_details del mismo kit vendido * (todos los componentes con el mismo bundle_sale_group) */ public function bundleComponents() { if (! $this->isPartOfBundle()) { return collect([]); } return SaleDetail::where('sale_id', $this->sale_id) ->where('bundle_sale_group', $this->bundle_sale_group) ->get(); } }