¨4.0.1¨
This commit is contained in:
@@ -9,6 +9,7 @@ use Modules\Support\State;
|
||||
use Modules\Support\Country;
|
||||
use Modules\Media\Entities\File;
|
||||
use Modules\Tax\Entities\TaxRate;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Collection;
|
||||
use Modules\Order\OrderCollection;
|
||||
use Modules\Coupon\Entities\Coupon;
|
||||
@@ -46,26 +47,31 @@ class Order extends Model
|
||||
*/
|
||||
protected $dates = ['start_date', 'end_date', 'deleted_at'];
|
||||
|
||||
|
||||
public static function totalSales()
|
||||
{
|
||||
return Money::inDefaultCurrency(self::withoutCanceledOrders()->sum('total'));
|
||||
}
|
||||
|
||||
|
||||
public function status()
|
||||
{
|
||||
return trans("order::statuses.{$this->status}");
|
||||
}
|
||||
|
||||
|
||||
public function hasShippingMethod()
|
||||
{
|
||||
return !is_null($this->shipping_method);
|
||||
}
|
||||
|
||||
|
||||
public function hasCoupon()
|
||||
{
|
||||
return !is_null($this->coupon);
|
||||
}
|
||||
|
||||
|
||||
public function totalTax()
|
||||
{
|
||||
$total = 0;
|
||||
@@ -81,11 +87,23 @@ class Order extends Model
|
||||
return Money::inDefaultCurrency($total);
|
||||
}
|
||||
|
||||
|
||||
public function hasTax()
|
||||
{
|
||||
return $this->taxes->isNotEmpty();
|
||||
}
|
||||
|
||||
|
||||
public function taxes()
|
||||
{
|
||||
return $this->belongsToMany(TaxRate::class, 'order_taxes')
|
||||
->using(OrderTax::class)
|
||||
->as('order_tax')
|
||||
->withPivot('amount')
|
||||
->withTrashed();
|
||||
}
|
||||
|
||||
|
||||
public function salesAnalytics()
|
||||
{
|
||||
return $this->normalizeOrders($this->ordersByWeekDay())->mapWithKeys(function ($orders, $weekDay) {
|
||||
@@ -93,6 +111,198 @@ class Order extends Model
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public function coupon()
|
||||
{
|
||||
return $this->belongsTo(Coupon::class)->withTrashed();
|
||||
}
|
||||
|
||||
|
||||
public function getSubTotalAttribute($subTotal)
|
||||
{
|
||||
return Money::inDefaultCurrency($subTotal);
|
||||
}
|
||||
|
||||
|
||||
public function getShippingCostAttribute($shippingCost)
|
||||
{
|
||||
return Money::inDefaultCurrency($shippingCost);
|
||||
}
|
||||
|
||||
|
||||
public function getDiscountAttribute($discount)
|
||||
{
|
||||
return Money::inDefaultCurrency($discount);
|
||||
}
|
||||
|
||||
|
||||
public function getTaxAttribute($tax)
|
||||
{
|
||||
return Money::inDefaultCurrency($tax);
|
||||
}
|
||||
|
||||
|
||||
public function getTotalAttribute($total)
|
||||
{
|
||||
return Money::inDefaultCurrency($total);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the order's shipping method.
|
||||
*
|
||||
* @param string $shippingMethod
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getShippingMethodAttribute($shippingMethod)
|
||||
{
|
||||
return ShippingMethod::get($shippingMethod)->label ?? null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the order's payment method.
|
||||
*
|
||||
* @param string $paymentMethod
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPaymentMethodAttribute($paymentMethod)
|
||||
{
|
||||
return Gateway::get($paymentMethod)->label ?? '';
|
||||
}
|
||||
|
||||
|
||||
public function getCustomerFullNameAttribute()
|
||||
{
|
||||
return "{$this->customer_first_name} {$this->customer_last_name}";
|
||||
}
|
||||
|
||||
|
||||
public function getBillingFullNameAttribute()
|
||||
{
|
||||
return "{$this->billing_first_name} {$this->billing_last_name}";
|
||||
}
|
||||
|
||||
|
||||
public function getShippingFullNameAttribute()
|
||||
{
|
||||
return "{$this->shipping_first_name} {$this->shipping_last_name}";
|
||||
}
|
||||
|
||||
|
||||
public function getBillingCountryNameAttribute()
|
||||
{
|
||||
return Country::name($this->billing_country);
|
||||
}
|
||||
|
||||
|
||||
public function getShippingCountryNameAttribute()
|
||||
{
|
||||
return Country::name($this->shipping_country);
|
||||
}
|
||||
|
||||
|
||||
public function getBillingStateNameAttribute()
|
||||
{
|
||||
return State::name($this->billing_country, $this->billing_state);
|
||||
}
|
||||
|
||||
|
||||
public function getShippingStateNameAttribute()
|
||||
{
|
||||
return State::name($this->shipping_country, $this->shipping_state);
|
||||
}
|
||||
|
||||
|
||||
public function scopeWithoutCanceledOrders($query)
|
||||
{
|
||||
return $query->whereNotIn('status', [self::CANCELED, self::REFUNDED]);
|
||||
}
|
||||
|
||||
|
||||
public function storeProducts(CartItem $cartItem)
|
||||
{
|
||||
$orderProduct = $this->products()->create([
|
||||
'product_id' => $cartItem->product->id,
|
||||
'product_variant_id' => $cartItem->variant?->id,
|
||||
'unit_price' => $cartItem->unitPrice()->amount(),
|
||||
'qty' => $cartItem->qty,
|
||||
'line_total' => $cartItem->totalPrice()->amount(),
|
||||
]);
|
||||
|
||||
$orderProduct->storeVariations($cartItem->variations);
|
||||
$orderProduct->storeOptions($cartItem->options);
|
||||
}
|
||||
|
||||
|
||||
public function products()
|
||||
{
|
||||
return $this->hasMany(OrderProduct::class);
|
||||
}
|
||||
|
||||
|
||||
public function storeDownloads(CartItem $cartItem)
|
||||
{
|
||||
$cartItem->product->downloads->each(function (File $file) {
|
||||
$this->downloads()->create(['file_id' => $file->id]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public function downloads()
|
||||
{
|
||||
return $this->hasMany(OrderDownload::class);
|
||||
}
|
||||
|
||||
|
||||
public function attachTax(CartTax $cartTax)
|
||||
{
|
||||
$this->taxes()->attach($cartTax->id(), ['amount' => $cartTax->amount()->amount()]);
|
||||
}
|
||||
|
||||
|
||||
public function storeTransaction($response)
|
||||
{
|
||||
if (!$response instanceof HasTransactionReference) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->transaction()->create([
|
||||
'transaction_id' => $response->getTransactionReference(),
|
||||
'payment_method' => $this->attributes['payment_method'],
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
public function transaction()
|
||||
{
|
||||
return $this->hasOne(Transaction::class)->withTrashed();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get table data for the resource
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function table()
|
||||
{
|
||||
$query = $this->newQuery()->select(['id', 'customer_first_name', 'customer_last_name', 'customer_email', 'currency', 'total', 'status', 'created_at']);
|
||||
|
||||
return new OrderTable($query);
|
||||
}
|
||||
|
||||
|
||||
private function normalizeOrders($orders)
|
||||
{
|
||||
return Collection::times(7)->map(function ($dayOfWeek) use ($orders) {
|
||||
return new OrderCollection($orders[$dayOfWeek] ?? []);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private function ordersByWeekDay()
|
||||
{
|
||||
return self::select('total', 'created_at')
|
||||
@@ -106,12 +316,6 @@ class Order extends Model
|
||||
});
|
||||
}
|
||||
|
||||
private function normalizeOrders($orders)
|
||||
{
|
||||
return Collection::times(7)->map(function ($dayOfWeek) use ($orders) {
|
||||
return new OrderCollection($orders[$dayOfWeek] ?? []);
|
||||
});
|
||||
}
|
||||
|
||||
private function dataForChart(OrderCollection $orders)
|
||||
{
|
||||
@@ -120,170 +324,4 @@ class Order extends Model
|
||||
'total_orders' => $orders->count(),
|
||||
];
|
||||
}
|
||||
|
||||
public function products()
|
||||
{
|
||||
return $this->hasMany(OrderProduct::class);
|
||||
}
|
||||
|
||||
public function downloads()
|
||||
{
|
||||
return $this->hasMany(OrderDownload::class);
|
||||
}
|
||||
|
||||
public function coupon()
|
||||
{
|
||||
return $this->belongsTo(Coupon::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function taxes()
|
||||
{
|
||||
return $this->belongsToMany(TaxRate::class, 'order_taxes')
|
||||
->using(OrderTax::class)
|
||||
->as('order_tax')
|
||||
->withPivot('amount')
|
||||
->withTrashed();
|
||||
}
|
||||
|
||||
public function transaction()
|
||||
{
|
||||
return $this->hasOne(Transaction::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function getSubTotalAttribute($subTotal)
|
||||
{
|
||||
return Money::inDefaultCurrency($subTotal);
|
||||
}
|
||||
|
||||
public function getShippingCostAttribute($shippingCost)
|
||||
{
|
||||
return Money::inDefaultCurrency($shippingCost);
|
||||
}
|
||||
|
||||
public function getDiscountAttribute($discount)
|
||||
{
|
||||
return Money::inDefaultCurrency($discount);
|
||||
}
|
||||
|
||||
public function getTaxAttribute($tax)
|
||||
{
|
||||
return Money::inDefaultCurrency($tax);
|
||||
}
|
||||
|
||||
public function getTotalAttribute($total)
|
||||
{
|
||||
return Money::inDefaultCurrency($total);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the order's shipping method.
|
||||
*
|
||||
* @param string $shippingMethod
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getShippingMethodAttribute($shippingMethod)
|
||||
{
|
||||
return ShippingMethod::get($shippingMethod)->label ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the order's payment method.
|
||||
*
|
||||
* @param string $paymentMethod
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPaymentMethodAttribute($paymentMethod)
|
||||
{
|
||||
return Gateway::get($paymentMethod)->label ?? '';
|
||||
}
|
||||
|
||||
public function getCustomerFullNameAttribute()
|
||||
{
|
||||
return "{$this->customer_first_name} {$this->customer_last_name}";
|
||||
}
|
||||
|
||||
public function getBillingFullNameAttribute()
|
||||
{
|
||||
return "{$this->billing_first_name} {$this->billing_last_name}";
|
||||
}
|
||||
|
||||
public function getShippingFullNameAttribute()
|
||||
{
|
||||
return "{$this->shipping_first_name} {$this->shipping_last_name}";
|
||||
}
|
||||
|
||||
public function getBillingCountryNameAttribute()
|
||||
{
|
||||
return Country::name($this->billing_country);
|
||||
}
|
||||
|
||||
public function getShippingCountryNameAttribute()
|
||||
{
|
||||
return Country::name($this->shipping_country);
|
||||
}
|
||||
|
||||
public function getBillingStateNameAttribute()
|
||||
{
|
||||
return State::name($this->billing_country, $this->billing_state);
|
||||
}
|
||||
|
||||
public function getShippingStateNameAttribute()
|
||||
{
|
||||
return State::name($this->shipping_country, $this->shipping_state);
|
||||
}
|
||||
|
||||
public function scopeWithoutCanceledOrders($query)
|
||||
{
|
||||
return $query->whereNotIn('status', [self::CANCELED, self::REFUNDED]);
|
||||
}
|
||||
|
||||
public function storeProducts(CartItem $cartItem)
|
||||
{
|
||||
$orderProduct = $this->products()->create([
|
||||
'product_id' => $cartItem->product->id,
|
||||
'unit_price' => $cartItem->unitPrice()->amount(),
|
||||
'qty' => $cartItem->qty,
|
||||
'line_total' => $cartItem->total()->amount(),
|
||||
]);
|
||||
|
||||
$orderProduct->storeOptions($cartItem->options);
|
||||
}
|
||||
|
||||
public function storeDownloads(CartItem $cartItem)
|
||||
{
|
||||
$cartItem->product->downloads->each(function (File $file) {
|
||||
$this->downloads()->create(['file_id' => $file->id]);
|
||||
});
|
||||
}
|
||||
|
||||
public function attachTax(CartTax $cartTax)
|
||||
{
|
||||
$this->taxes()->attach($cartTax->id(), ['amount' => $cartTax->amount()->amount()]);
|
||||
}
|
||||
|
||||
public function storeTransaction($response)
|
||||
{
|
||||
if (!$response instanceof HasTransactionReference) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->transaction()->create([
|
||||
'transaction_id' => $response->getTransactionReference(),
|
||||
'payment_method' => $this->attributes['payment_method'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table data for the resource
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function table()
|
||||
{
|
||||
$query = $this->newQuery()->select(['id', 'customer_first_name', 'customer_last_name', 'customer_email', 'currency', 'total', 'status', 'created_at']);
|
||||
|
||||
return new OrderTable($query);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,16 +28,19 @@ class OrderDownload extends Model
|
||||
*/
|
||||
protected $fillable = ['file_id'];
|
||||
|
||||
|
||||
public function getRealPathAttribute()
|
||||
{
|
||||
return $this->file->realPath();
|
||||
}
|
||||
|
||||
|
||||
public function getFilenameAttribute()
|
||||
{
|
||||
return $this->file->file_name;
|
||||
}
|
||||
|
||||
|
||||
public function file()
|
||||
{
|
||||
return $this->belongsTo(File::class);
|
||||
|
||||
@@ -5,6 +5,8 @@ namespace Modules\Order\Entities;
|
||||
use Modules\Support\Money;
|
||||
use Modules\Support\Eloquent\Model;
|
||||
use Modules\Product\Entities\Product;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
|
||||
class OrderProduct extends Model
|
||||
{
|
||||
@@ -20,7 +22,7 @@ class OrderProduct extends Model
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $with = ['product', 'options'];
|
||||
protected $with = ['product', 'options', 'variations'];
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
@@ -29,16 +31,25 @@ class OrderProduct extends Model
|
||||
*/
|
||||
protected $guarded = [];
|
||||
|
||||
|
||||
public function url()
|
||||
{
|
||||
return route('products.show', ['slug' => $this->product->slug]);
|
||||
}
|
||||
|
||||
|
||||
public function hasAnyOption()
|
||||
{
|
||||
return $this->options->isNotEmpty();
|
||||
}
|
||||
|
||||
|
||||
public function hasAnyVariation()
|
||||
{
|
||||
return $this->variations->isNotEmpty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if order product has been deleted.
|
||||
*
|
||||
@@ -49,10 +60,40 @@ class OrderProduct extends Model
|
||||
return $this->product->trashed();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store order product's variations.
|
||||
*
|
||||
* @param Collection $variations
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function storeVariations($variations)
|
||||
{
|
||||
$variations->each(function ($variation) {
|
||||
$orderProductVariation = $this->variations()->create([
|
||||
'order_product_id' => $this->id,
|
||||
'variation_id' => $variation->id,
|
||||
'type' => $variation->type,
|
||||
'value' => $variation->values->first()->label,
|
||||
]);
|
||||
|
||||
$orderProductVariation->storeValues($variation->values);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public function variations()
|
||||
{
|
||||
return $this->hasMany(OrderProductVariation::class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store order product's options.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Collection $options
|
||||
* @param Collection $options
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function storeOptions($options)
|
||||
@@ -68,6 +109,13 @@ class OrderProduct extends Model
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public function options()
|
||||
{
|
||||
return $this->hasMany(OrderProductOption::class);
|
||||
}
|
||||
|
||||
|
||||
public function product()
|
||||
{
|
||||
return $this->belongsTo(Product::class)
|
||||
@@ -75,10 +123,6 @@ class OrderProduct extends Model
|
||||
->withTrashed();
|
||||
}
|
||||
|
||||
public function options()
|
||||
{
|
||||
return $this->hasMany(OrderProductOption::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the order product's name.
|
||||
@@ -90,6 +134,7 @@ class OrderProduct extends Model
|
||||
return $this->product->name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the order product's slug.
|
||||
*
|
||||
@@ -100,13 +145,26 @@ class OrderProduct extends Model
|
||||
return $this->product->slug;
|
||||
}
|
||||
|
||||
|
||||
public function getUnitPriceAttribute($unitPrice)
|
||||
{
|
||||
return Money::inDefaultCurrency($unitPrice);
|
||||
}
|
||||
|
||||
|
||||
public function getLineTotalAttribute($total)
|
||||
{
|
||||
return Money::inDefaultCurrency($total);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the order product's SKU.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSkuAttribute()
|
||||
{
|
||||
return $this->product_variant ? $this->product_variant->sku : $this->product->sku;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,28 +29,25 @@ class OrderProductOption extends Model
|
||||
*/
|
||||
protected $guarded = [];
|
||||
|
||||
|
||||
public function option()
|
||||
{
|
||||
return $this->belongsTo(Option::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function values()
|
||||
{
|
||||
return $this->belongsToMany(OptionValue::class, 'order_product_option_values')
|
||||
->using(OrderProductOptionValue::class)
|
||||
->withPivot('price');
|
||||
}
|
||||
|
||||
public function getNameAttribute()
|
||||
{
|
||||
return $this->option->name;
|
||||
}
|
||||
|
||||
|
||||
public function isFieldType()
|
||||
{
|
||||
return $this->option->isFieldType();
|
||||
}
|
||||
|
||||
|
||||
public function storeValues($product, $values)
|
||||
{
|
||||
$values = $values->mapWithKeys(function (OptionValue $value) use ($product) {
|
||||
@@ -61,4 +58,12 @@ class OrderProductOption extends Model
|
||||
|
||||
$this->values()->attach($values->all());
|
||||
}
|
||||
|
||||
|
||||
public function values()
|
||||
{
|
||||
return $this->belongsToMany(OptionValue::class, 'order_product_option_values')
|
||||
->using(OrderProductOptionValue::class)
|
||||
->withPivot('price');
|
||||
}
|
||||
}
|
||||
|
||||
56
Modules/Order/Entities/OrderProductVariation.php
Normal file
56
Modules/Order/Entities/OrderProductVariation.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Order\Entities;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Modules\Variation\Entities\Variation;
|
||||
use Modules\Variation\Entities\VariationValue;
|
||||
|
||||
class OrderProductVariation extends Model
|
||||
{
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* The relations to eager load on every query.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $with = ['variation', 'values'];
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $guarded = [];
|
||||
|
||||
|
||||
public function variation()
|
||||
{
|
||||
return $this->belongsTo(Variation::class)->withTrashed();
|
||||
}
|
||||
|
||||
|
||||
public function getNameAttribute()
|
||||
{
|
||||
return $this->variation->name;
|
||||
}
|
||||
|
||||
|
||||
public function storeValues($values)
|
||||
{
|
||||
$this->values()->attach($values->pluck('id'));
|
||||
}
|
||||
|
||||
|
||||
public function values()
|
||||
{
|
||||
return $this->belongsToMany(VariationValue::class, 'order_product_variation_values')
|
||||
->using(OrderProductVariationValue::class);
|
||||
}
|
||||
}
|
||||
10
Modules/Order/Entities/OrderProductVariationValue.php
Normal file
10
Modules/Order/Entities/OrderProductVariationValue.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Order\Entities;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\Pivot;
|
||||
|
||||
class OrderProductVariationValue extends Pivot
|
||||
{
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user