511 lines
13 KiB
PHP
511 lines
13 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Enums\InvoicingUnit;
|
|
use App\Enums\SellUnit;
|
|
use App\Enums\WeightUnit;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
use Gloudemans\Shoppingcart\Contracts\Buyable;
|
|
use Gloudemans\Shoppingcart\CanBeBought;
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
class Product extends Model implements Buyable
|
|
{
|
|
use HasFactory;
|
|
use SoftDeletes;
|
|
use CanBeBought;
|
|
|
|
/**
|
|
* The attributes that should be cast to native types.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $casts = [
|
|
'orderable_start' => 'datetime',
|
|
'orderable_end' => 'datetime',
|
|
];
|
|
|
|
/**
|
|
* Store in protected variables instead of attributes
|
|
* Because those are not set in attributes, Laravel will not try to save it to database
|
|
*/
|
|
|
|
/**
|
|
* Base Price
|
|
*
|
|
* @var float
|
|
*/
|
|
protected $priceHt;
|
|
|
|
/**
|
|
* Base Price after discount
|
|
*
|
|
* @var float
|
|
*/
|
|
protected $discountedPriceHt;
|
|
|
|
/**
|
|
* Price VAT included
|
|
*
|
|
* @var float
|
|
*/
|
|
protected $priceTtc;
|
|
|
|
/**
|
|
* Price after discount VAT included
|
|
*
|
|
* @var float
|
|
*/
|
|
protected $discountedPriceTtc;
|
|
|
|
/**
|
|
* Discount amount
|
|
*
|
|
* @var float
|
|
*/
|
|
protected $discountAmount;
|
|
|
|
/**
|
|
* Dsicount rate
|
|
*
|
|
* @var float
|
|
*/
|
|
protected $discountRate;
|
|
|
|
/**
|
|
* Bootstrap the model and its traits.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected static function boot()
|
|
{
|
|
parent::boot();
|
|
|
|
// On data retrived from DB.
|
|
static::retrieved(function ($model) {
|
|
$model->priceHt = $model->getPriceHtAttribute();
|
|
$model->priceTtc = $model->getPriceTtcAttribute();
|
|
$model->discountAmount = $model->getDiscountAmountAttribute();
|
|
$model->discountRate = $model->getDiscountRateAttribute();
|
|
$model->discountedPriceHt = $model->getDiscountedPriceHtAttribute();
|
|
$model->discountedPriceTtc = $model->getDiscountedPriceTtcAttribute();
|
|
});
|
|
}
|
|
|
|
|
|
/**
|
|
* Price calculations
|
|
* We need : gross price (prix avant taxe et remises)
|
|
* discounted price (prix avant taxe avec remises)
|
|
* net price (prix avec taxe)
|
|
* net discounted proice (prix avec taxe et remises)
|
|
*/
|
|
|
|
/**
|
|
* Utility to bring prices as a pseudo relation
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getCalcPrices()
|
|
{
|
|
$prices = array(
|
|
'priceHt' => $this->priceHt,
|
|
'discountAmount' => $this->discountAmount,
|
|
'discountRate' => $this->discountRate,
|
|
'discountedPriceHt' => $this->discountedPriceHt,
|
|
'priceTtc' => $this->priceTtc,
|
|
'discountedPriceTtc' => $this->discountedPriceTtc,
|
|
);
|
|
return $prices;
|
|
}
|
|
|
|
/**
|
|
* Mutator method to set priceHt's value gross price
|
|
*
|
|
* @param float $value
|
|
* @return void
|
|
*/
|
|
public function setPriceHtAttribute(float $value)
|
|
{
|
|
$this->priceHt = $value;
|
|
}
|
|
|
|
/**
|
|
* Get the gross price
|
|
* Accessor method for priceHt
|
|
*
|
|
* @author Olivier Legat <olivier.legat@ldc.fr>
|
|
*
|
|
* @return float
|
|
*/
|
|
public function getPriceHtAttribute()
|
|
{
|
|
if (isset($this->priceHt)) {
|
|
return $this->priceHt;
|
|
} else {
|
|
/** Tenir compte de l'unité de facturation et de l'unité de vente (qui doit être stricte)
|
|
* si facturation KG et vente piece
|
|
* prendre le poids, convertir en KG => pre-requis l'unité de poids doit être un enum
|
|
* multiplier le $this->attributes['price'] par les KG
|
|
* sinon
|
|
* value => value
|
|
*/
|
|
if (config('bosettings.sell_unit_management') == "strict") {
|
|
$calculate = ($this->invoicing_unit == InvoicingUnit::kgm()->value
|
|
&& $this->sell_unit == SellUnit::pce()->value);
|
|
} else {
|
|
$calculate = false;
|
|
}
|
|
|
|
if ($calculate) {
|
|
// Weight converter.
|
|
$weighted_price = $this->attributes['price']
|
|
* ($this->weight * WeightUnit::convert()[$this->weight_unit]);
|
|
$this->priceHt = round($weighted_price * 1000) / 1000;
|
|
return $this->priceHt;
|
|
} else {
|
|
// No calculations, alias of db property.
|
|
$this->priceHt = $this->attributes['price'];
|
|
return $this->priceHt;
|
|
}
|
|
}//end if
|
|
}
|
|
|
|
/**
|
|
* setter for dicounted price
|
|
*
|
|
* @param float $value
|
|
* @return void
|
|
*/
|
|
public function setDiscountedPriceHtAttribute(float $value)
|
|
{
|
|
$this->discountedPriceHt = $value;
|
|
}
|
|
|
|
/**
|
|
* getter for discounted price
|
|
*
|
|
* @return float
|
|
*/
|
|
public function getDiscountedPriceHtAttribute()
|
|
{
|
|
if (isset($this->discountedPriceHt)) {
|
|
return $this->discountedPriceHt;
|
|
} else {
|
|
$discountedPriceHt = $this->priceHt - $this->discountAmount;
|
|
$roundingdiscountedPriceHt = round($discountedPriceHt * 1000) / 1000;
|
|
$this->discountedPriceHt = $roundingdiscountedPriceHt;
|
|
return $this->discountedPriceHt;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* setter for net price
|
|
*
|
|
* @param float $value
|
|
* @return void
|
|
*/
|
|
public function setPriceTtcAttribute(float $value)
|
|
{
|
|
$this->priceTtc = $value;
|
|
}
|
|
|
|
/**
|
|
* getter for net price
|
|
*
|
|
* @return float
|
|
*/
|
|
public function getPriceTtcAttribute()
|
|
{
|
|
if (isset($this->priceTtc)) {
|
|
return $this->priceTtc;
|
|
} else {
|
|
$priceTtc = $this->priceHt * ( 1 + ( $this->tax->rate / 100));
|
|
/**
|
|
* On travaille avec des centimes puis on redivise par 100 pour avoir des unités monetaires
|
|
* on augmente la précision à 3 digits, l'affichage formate les prix sur 2 décimales
|
|
*/
|
|
$roundingPriceTtc = round($priceTtc * 1000) / 1000;
|
|
$this->priceTtc = $roundingPriceTtc;
|
|
return $this->priceTtc;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* setter for net dscounted price
|
|
*
|
|
* @param float $value
|
|
* @return void
|
|
*/
|
|
public function setDiscountedPriceTtcAttribute(float $value)
|
|
{
|
|
$this->discountedPriceTtc = $value;
|
|
}
|
|
|
|
/**
|
|
* getter for net dscounted price
|
|
*
|
|
* @return float
|
|
*/
|
|
public function getDiscountedPriceTtcAttribute()
|
|
{
|
|
if (isset($this->discountedPriceTtc)) {
|
|
$showPrice = $this->discountedPriceTtc;
|
|
} else {
|
|
$discountedPriceTtc = $this->discountedPriceHt * ( 1 + ( $this->tax->rate / 100));
|
|
// On travaille avec des centimes puis on redivise par 100 pour avoir des unités monetaires.
|
|
$roundingDiscountedPriceTTC = round($discountedPriceTtc * 1000) / 1000;
|
|
$this->discountedPriceTtc = $roundingDiscountedPriceTTC;
|
|
$showPrice = $this->discountedPriceTtc;
|
|
}
|
|
// Prix transmis en fonction du setting show_prices.
|
|
if (config('bosettings.show_prices_authenticated') == "authenticated") {
|
|
{
|
|
if (Auth::guard('customer')->check()) {
|
|
return $showPrice;
|
|
}
|
|
}
|
|
}
|
|
if (config('bosettings.show_prices_guest') == "guest") {
|
|
return $showPrice;
|
|
}
|
|
return "-.--";
|
|
}
|
|
|
|
/**
|
|
* Discount calculators
|
|
*/
|
|
|
|
/**
|
|
* set discoutn amount
|
|
*
|
|
* @param float $value
|
|
* @return void
|
|
*/
|
|
public function setDiscountAmountAttribute(float $value)
|
|
{
|
|
$this->discountAmount = $value;
|
|
}
|
|
|
|
/**
|
|
* Getter for discount amount
|
|
*
|
|
* @return float
|
|
*/
|
|
public function getDiscountAmountAttribute()
|
|
{
|
|
if (isset($this->discountAmount)) {
|
|
return $this->discountAmount;
|
|
} else {
|
|
$applicablePromotion = $this->promotions->first();
|
|
if (null !== $applicablePromotion) {
|
|
$promo_type = $applicablePromotion->discount_type_id;
|
|
if ($promo_type == 1) {
|
|
$discountAmount = $applicablePromotion->discount_value;
|
|
} else {
|
|
// On augmente la précision à 3 digits, l'affichage formate les prix sur 2 décimales.
|
|
$discountAmount = $this->priceHt * ($applicablePromotion->discount_value / 100);
|
|
$discountAmount = round($discountAmount * 1000) / 1000;
|
|
}
|
|
} else {
|
|
$discountAmount = 0;
|
|
}
|
|
$this->discountAmount = $discountAmount;
|
|
return $this->discountAmount;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* set discount rate
|
|
*
|
|
* @param float $value
|
|
* @return void
|
|
*/
|
|
public function setDiscountRateAttribute(float $value)
|
|
{
|
|
$this->discountRate = $value;
|
|
}
|
|
|
|
/**
|
|
* get discount rate
|
|
*
|
|
* @return float
|
|
*/
|
|
public function getDiscountRateAttribute()
|
|
{
|
|
if (isset($this->discountRate)) {
|
|
return $this->discountRate;
|
|
} else {
|
|
$applicablePromotion = $this->promotions->first();
|
|
if (null !== $applicablePromotion) {
|
|
$promo_type = $applicablePromotion->discount_type_id;
|
|
if ($promo_type == 1) {
|
|
// On veut un pourcentage.
|
|
$discountRate = ($applicablePromotion->discount_value / $this->priceHt) * 100;
|
|
} else {
|
|
$discountRate = $applicablePromotion->discount_value;
|
|
}
|
|
} else {
|
|
$discountRate = 0;
|
|
}
|
|
$this->discountRate = $discountRate;
|
|
return $this->discountRate;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* buyablePrice attribute alias
|
|
*
|
|
* @param mixed $options
|
|
* @return float
|
|
*
|
|
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
|
|
*/
|
|
public function getBuyablePrice($options = null)
|
|
{
|
|
// @phpcs:enable
|
|
return $this->priceHt;
|
|
}
|
|
|
|
/**
|
|
* BelongsTo range relation
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
*/
|
|
public function range()
|
|
{
|
|
return $this->belongsTo('App\Models\Range', 'range_id');
|
|
}
|
|
|
|
/**
|
|
* hasMany old_slugs relation
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
*/
|
|
public function oldSlugs()
|
|
{
|
|
return $this->hasMany('App\Model\OldSlug', 'product_id');
|
|
}
|
|
|
|
/**
|
|
* hasMany stats relation
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
*/
|
|
public function stats()
|
|
{
|
|
return $this->hasMany('App\Models\Stat', 'product_id');
|
|
}
|
|
|
|
/**
|
|
* belongsToMany orders relation
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
|
*/
|
|
public function orders()
|
|
{
|
|
return $this->belongsToMany('App\Models\Order', 'orders_products', 'product_id', 'order_id')
|
|
->withPivot('quantity');
|
|
}
|
|
|
|
/**
|
|
* Pseudo relationship to additionnal product info
|
|
*
|
|
* @param string $productType
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
|
*/
|
|
public function additionnalProductInfo(string $productType)
|
|
{
|
|
return $this->$productType;
|
|
}
|
|
|
|
/**
|
|
* hasOne foodProduct relation
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
|
*/
|
|
public function foodProduct()
|
|
{
|
|
return $this->hasOne(FoodProduct::class, 'product_id');
|
|
}
|
|
|
|
/**
|
|
* hasOne anifoodProduct relation
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
|
*/
|
|
public function anifoodProduct()
|
|
{
|
|
return $this->hasOne(AnifoodProduct::class, 'product_id');
|
|
}
|
|
|
|
/**
|
|
* hasOne toolProduct relation
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
|
*/
|
|
public function toolProduct()
|
|
{
|
|
return $this->hasOne(ToolProduct::class, 'product_id');
|
|
}
|
|
|
|
/**
|
|
* hasOne garmentProduct relation
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
|
*/
|
|
public function garmentProduct()
|
|
{
|
|
return $this->hasOne(GarmentProduct::class, 'product_id');
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* belongsToMany products relation
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
|
*/
|
|
public function products()
|
|
{
|
|
return $this->belongsToMany(Product::class, 'products_products', 'product_id', 'associated_id');
|
|
}
|
|
|
|
/**
|
|
* belongsToMany promotions relation
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
|
*/
|
|
public function promotions()
|
|
{
|
|
$now = Carbon::now();
|
|
return $this->belongsToMany(Promotion::class)
|
|
->whereDate('date_start', '<=', $now)
|
|
->whereDate('date_end', '>=', $now);
|
|
}
|
|
|
|
/**
|
|
* belongsTo tax relation
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
*/
|
|
public function tax()
|
|
{
|
|
return $this->belongsTo(TaxRate::class, 'tax_rate_id');
|
|
}
|
|
|
|
/**
|
|
* belongsToMany tags relation
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
|
*/
|
|
public function tags()
|
|
{
|
|
return $this->belongsToMany(Tag::class);
|
|
}
|
|
}
|