id = $item->id; $this->qty = $item->quantity; $this->product = $item->attributes['product']; $this->variant = $item->attributes['variant']; $this->item = $item->attributes['item']; $this->variations = $item->attributes['variations']; $this->options = $item->attributes['options']; } public function refreshStock() { $item = $this->getItem(); $this->item->fill([ 'manage_stock' => $item->manage_stock, 'in_stock' => $item->in_stock, 'qty' => $item->qty, ]); return $this; } public function getItem() { if ($this->item instanceof ProductVariant) { return ProductVariant::addSelect('id', 'in_stock', 'manage_stock', 'qty') ->where('id', $this->variant->id) ->firstOrFail(); } return Product::withName() ->addSelect('id', 'in_stock', 'manage_stock', 'qty') ->where('id', $this->product->id) ->firstOrFail(); } public function findTax(array $addresses) { return $this->product->taxClass->findTaxRate($addresses); } public function __toString() { return json_encode($this->jsonSerialize()); } public function jsonSerialize(): array { return [ 'id' => $this->id, 'qty' => $this->qty, 'product' => $this->product->clean(), 'variant' => $this->variant?->clean(), 'item' => $this->item, 'variations' => $this->variations->isNotEmpty() ? $this->variations->keyBy('position') : new stdClass, 'options' => $this->options->isNotEmpty() ? $this->options->keyBy('position') : new stdClass, 'unitPrice' => $this->unitPrice(), 'total' => $this->totalPrice(), ]; } public function unitPrice() { return $this->item->selling_price->add($this->optionsPrice()); } public function optionsPrice(): Money { return Money::inDefaultCurrency($this->calculateOptionsPrice()); } public function totalPrice() { return $this->unitPrice()->multiply($this->qty); } private function calculateOptionsPrice() { return $this->options->sum(function ($option) { return $this->sumOfTheValuesOf($option); }); } private function sumOfTheValuesOf($option) { return $option->values->sum(function ($value) { if ($value->price_type === 'fixed') { return $value->price->amount(); } return ($value->price / 100) * $this->item->selling_price->amount(); }); } }