Added customer group price
This commit is contained in:
parent
33e118c581
commit
ae9ec7ce9b
|
|
@ -527,7 +527,12 @@ return [
|
|||
'checkbox' => 'Checkbox',
|
||||
'multiselect' => 'Multiselect',
|
||||
'new-option' => 'New Option',
|
||||
'is-default' => 'Is Default'
|
||||
'is-default' => 'Is Default',
|
||||
'customer-group' => 'Customer Group',
|
||||
'add-group-price' => 'Add Customer Group Price',
|
||||
'all-group' => 'All Groups',
|
||||
'fixed' => 'Fixed',
|
||||
'discount' => 'Discount',
|
||||
],
|
||||
|
||||
'attributes' => [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,162 @@
|
|||
@section('css')
|
||||
@parent
|
||||
<style>
|
||||
.table th.price, .table th.weight {
|
||||
width: 100px;
|
||||
}
|
||||
.table th.actions {
|
||||
width: 85px;
|
||||
}
|
||||
.table td.actions .icon {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.table td.actions .icon.pencil-lg-icon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
@stop
|
||||
|
||||
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.customer_group_prices.before', ['product' => $product]) !!}
|
||||
|
||||
<customer-group-price-list></customer-group-price-list>
|
||||
|
||||
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.customer_group_prices.after', ['product' => $product]) !!}
|
||||
|
||||
@push('scripts')
|
||||
@parent
|
||||
|
||||
<script type="text/x-template" id="customer-group-price-list-template">
|
||||
<div>
|
||||
<div class="table" style="margin-top: 20px; overflow-x: unset;">
|
||||
<table>
|
||||
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ __('admin::app.catalog.products.customer-group') }}</th>
|
||||
<th>{{ __('admin::app.catalog.products.qty') }}</th>
|
||||
<th>{{ __('admin::app.catalog.products.price') }}</th>
|
||||
<th class="actions"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
<customer-group-price-item v-for='(customerGroupPrice, index) in customer_group_prices' :customer-group-price="customerGroupPrice" :key="index" :index="index" @onRemoveCustomerGroupPrice="removeCustomerGroupPrice($event)"></customer-group-price-item>
|
||||
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
<button type="button" class="btn btn-lg btn-primary" style="margin-top: 20px" @click="addCustomerGroupPrice()">
|
||||
{{ __('admin::app.catalog.products.add-group-price') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="customer-group-price-item-template">
|
||||
<tr>
|
||||
<td>
|
||||
<div class="control-group">
|
||||
<select :name="[inputName + '[customer_group_id]']" v-model="customerGroupPrice.customer_group_id" class="control">
|
||||
<option value="">{{ __('admin::app.catalog.products.all-group') }}</option>
|
||||
|
||||
@foreach (app('Webkul\Customer\Repositories\CustomerGroupRepository')->all() as $customerGroup)
|
||||
<option value="{{ $customerGroup->id }}">{{ $customerGroup->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<div class="control-group" :class="[errors.has(inputName + '[qty]') ? 'has-error' : '']">
|
||||
<input type="number" v-validate="'required|min_value:0'" :name="[inputName + '[qty]']" v-model="customerGroupPrice.qty" class="control" data-vv-as=""{{ __('admin::app.catalog.products.qty') }}""/>
|
||||
<span class="control-error" v-if="errors.has(inputName + '[qty]')">@{{ errors.first(inputName + '[qty]') }}</span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<div class="control-group">
|
||||
<select :name="[inputName + '[value_type]']" v-model="customerGroupPrice.value_type" class="control">
|
||||
<option value="fixed">{{ __('admin::app.catalog.products.fixed') }}</option>
|
||||
<option value="discount">{{ __('admin::app.catalog.products.discount') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<div class="control-group" :class="[errors.has(inputName + '[value]') ? 'has-error' : '']">
|
||||
<input type="number" v-validate="'required|min_value:0'" :name="[inputName + '[value]']" v-model="customerGroupPrice.value" class="control" data-vv-as=""{{ __('admin::app.catalog.products.value') }}""/>
|
||||
<span class="control-error" v-if="errors.has(inputName + '[value]')">@{{ errors.first(inputName + '[value]') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="actions">
|
||||
<i class="icon remove-icon" @click="removeCustomerGroupPrice()"></i>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('customer-group-price-list', {
|
||||
|
||||
template: '#customer-group-price-list-template',
|
||||
|
||||
inject: ['$validator'],
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
customer_group_prices: @json($product->customer_group_prices()->get())
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
addCustomerGroupPrice: function(item, key) {
|
||||
this.customer_group_prices.push({
|
||||
customer_group_id: '',
|
||||
qty: 0,
|
||||
value_type: 'fixed',
|
||||
amount: 0
|
||||
});
|
||||
},
|
||||
|
||||
removeCustomerGroupPrice: function(customerGroupPrice) {
|
||||
let index = this.customer_group_prices.indexOf(customerGroupPrice)
|
||||
|
||||
this.customer_group_prices.splice(index, 1)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Vue.component('customer-group-price-item', {
|
||||
|
||||
template: '#customer-group-price-item-template',
|
||||
|
||||
props: ['index', 'customerGroupPrice'],
|
||||
|
||||
inject: ['$validator'],
|
||||
|
||||
mounted: function() {
|
||||
if (! this.customerGroupPrice['customer_group_id']) {
|
||||
this.customerGroupPrice['customer_group_id'] = '';
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
inputName: function () {
|
||||
if (this.customerGroupPrice.id) {
|
||||
return 'customer_group_prices[' + this.customerGroupPrice.id + ']';
|
||||
}
|
||||
|
||||
return 'customer_group_prices[customer_group_price_' + this.index + ']';
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
removeCustomerGroupPrice: function () {
|
||||
this.$emit('onRemoveCustomerGroupPrice', this.customerGroupPrice)
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
@ -144,6 +144,12 @@
|
|||
|
||||
@endforeach
|
||||
|
||||
@if ($attributeGroup->name == 'Price')
|
||||
|
||||
@include ('admin::catalog.products.accordians.customer-group-price')
|
||||
|
||||
@endif
|
||||
|
||||
{!! view_render_event('bagisto.admin.catalog.product.edit_form_accordian.' . $attributeGroup->name . '.controls.after', ['product' => $product]) !!}
|
||||
</div>
|
||||
</accordian>
|
||||
|
|
|
|||
|
|
@ -531,7 +531,7 @@ class Booking
|
|||
*/
|
||||
public function validateCartItem($item)
|
||||
{
|
||||
$price = $item->product->getTypeInstance()->getFinalPrice();
|
||||
$price = $item->product->getTypeInstance()->getFinalPrice($item->quantity);
|
||||
|
||||
if ($price == $item->base_price) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ class EventTicket extends Booking
|
|||
*/
|
||||
public function validateCartItem($item)
|
||||
{
|
||||
$price = $item->product->getTypeInstance()->getFinalPrice();
|
||||
$price = $item->product->getTypeInstance()->getFinalPrice($item->quantity);
|
||||
|
||||
$bookingProduct = $this->bookingProductRepository->findOneByField('product_id', $item->product_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ class RentalSlot extends Booking
|
|||
*/
|
||||
public function validateCartItem($item)
|
||||
{
|
||||
$price = $item->product->getTypeInstance()->getFinalPrice();
|
||||
$price = $item->product->getTypeInstance()->getFinalPrice($item->quantity);
|
||||
|
||||
$bookingProduct = $this->bookingProductRepository->findOneByField('product_id', $item->product_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -140,9 +140,11 @@ class CartRule
|
|||
public static $cartRules;
|
||||
public static $cartID;
|
||||
};
|
||||
|
||||
if ($staticCartRules::$cartID === cart()->getCart()->id && $staticCartRules::$cartRules) {
|
||||
return $staticCartRules::$cartRules;
|
||||
}
|
||||
|
||||
$staticCartRules::$cartID = cart()->getCart()->id;
|
||||
|
||||
$customerGroupId = null;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Product\Contracts;
|
||||
|
||||
interface ProductCustomerGroupPrice
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateProductCustomerGroupPricesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('product_customer_group_prices', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->integer('qty')->default(0);
|
||||
$table->string('value_type');
|
||||
$table->decimal('value', 12, 4)->default(0);
|
||||
|
||||
$table->integer('product_id')->unsigned();
|
||||
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
|
||||
|
||||
$table->integer('customer_group_id')->nullble()->unsigned();
|
||||
$table->foreign('customer_group_id')->references('id')->on('customer_groups')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('product_customer_group_prices');
|
||||
}
|
||||
}
|
||||
|
|
@ -178,6 +178,14 @@ class Product extends Model implements ProductContract
|
|||
return $this->hasMany(ProductBundleOptionProxy::modelClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the product customer group prices that owns the product.
|
||||
*/
|
||||
public function customer_group_prices()
|
||||
{
|
||||
return $this->hasMany(ProductCustomerGroupPriceProxy::modelClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $qty
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Product\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Webkul\Product\Contracts\ProductCustomerGroupPrice as ProductCustomerGroupPriceContract;
|
||||
use Webkul\Product\Models\CustomerGroup;
|
||||
|
||||
class ProductCustomerGroupPrice extends Model implements ProductCustomerGroupPriceContract
|
||||
{
|
||||
protected $fillable = [
|
||||
'qty',
|
||||
'value_type',
|
||||
'value',
|
||||
'product_id',
|
||||
'customer_group_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the product that owns the customer group price.
|
||||
*/
|
||||
public function product()
|
||||
{
|
||||
return $this->belongsTo(ProductProxy::modelClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the product that owns the customer group price.
|
||||
*/
|
||||
public function customer_group()
|
||||
{
|
||||
return $this->belongsTo(CustomerGroupProxy::modelClass());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Product\Models;
|
||||
|
||||
use Konekt\Concord\Proxies\ModelProxy;
|
||||
|
||||
class ProductCustomerGroupPriceProxy extends ModelProxy
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -21,5 +21,6 @@ class ModuleServiceProvider extends BaseModuleServiceProvider
|
|||
\Webkul\Product\Models\ProductBundleOption::class,
|
||||
\Webkul\Product\Models\ProductBundleOptionTranslation::class,
|
||||
\Webkul\Product\Models\ProductBundleOptionProduct::class,
|
||||
\Webkul\Product\Models\ProductCustomerGroupPrice::class,
|
||||
];
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Webkul\Product\Repositories;
|
||||
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Webkul\Core\Eloquent\Repository;
|
||||
|
||||
class ProductCustomerGroupPriceRepository extends Repository
|
||||
{
|
||||
/**
|
||||
* Specify Model class name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function model()
|
||||
{
|
||||
return 'Webkul\Product\Contracts\ProductCustomerGroupPrice';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param \Webkul\Product\Contracts\Product $product
|
||||
* @return void
|
||||
*/
|
||||
public function saveCustomerGroupPrices(array $data, $product)
|
||||
{
|
||||
$previousCustomerGroupPriceIds = $product->customer_group_prices()->pluck('id');
|
||||
|
||||
if (isset($data['customer_group_prices'])) {
|
||||
foreach ($data['customer_group_prices'] as $customerGroupPriceId => $row) {
|
||||
$row['customer_group_id'] = $row['customer_group_id'] == '' ? null : $row['customer_group_id'];
|
||||
|
||||
if (Str::contains($customerGroupPriceId, 'customer_group_price_')) {
|
||||
$this->create(array_merge([
|
||||
'product_id' => $product->id,
|
||||
], $row));
|
||||
} else {
|
||||
if (is_numeric($index = $previousCustomerGroupPriceIds->search($customerGroupPriceId))) {
|
||||
$previousCustomerGroupPriceIds->forget($index);
|
||||
}
|
||||
|
||||
$this->update($row, $customerGroupPriceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($previousCustomerGroupPriceIds as $customerGroupPriceId) {
|
||||
$this->delete($customerGroupPriceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ use Webkul\Product\Repositories\ProductInventoryRepository;
|
|||
use Webkul\Product\Repositories\ProductImageRepository;
|
||||
use Webkul\Product\Models\ProductAttributeValue;
|
||||
use Webkul\Product\Helpers\ProductImage;
|
||||
use Cart;
|
||||
use Webkul\Checkout\Facades\Cart;
|
||||
|
||||
abstract class AbstractType
|
||||
{
|
||||
|
|
@ -246,6 +246,8 @@ abstract class AbstractType
|
|||
$this->productInventoryRepository->saveInventories($data, $product);
|
||||
|
||||
$this->productImageRepository->uploadImages($data, $product);
|
||||
|
||||
app('Webkul\Product\Repositories\ProductCustomerGroupPriceRepository')->saveCustomerGroupPrices($data, $product);
|
||||
}
|
||||
|
||||
return $product;
|
||||
|
|
@ -449,11 +451,12 @@ abstract class AbstractType
|
|||
/**
|
||||
* Get product minimal price
|
||||
*
|
||||
* @param int $qty
|
||||
* @return float
|
||||
*/
|
||||
public function getMinimalPrice()
|
||||
public function getMinimalPrice($qty = null)
|
||||
{
|
||||
if ($this->haveSpecialPrice()) {
|
||||
if ($this->haveSpecialPrice($qty)) {
|
||||
return $this->product->special_price;
|
||||
}
|
||||
|
||||
|
|
@ -473,57 +476,148 @@ abstract class AbstractType
|
|||
/**
|
||||
* Get product minimal price
|
||||
*
|
||||
* @param int $qty
|
||||
* @return float
|
||||
*/
|
||||
public function getFinalPrice()
|
||||
public function getFinalPrice($qty = null)
|
||||
{
|
||||
return $this->getMinimalPrice();
|
||||
return $this->getMinimalPrice($qty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the product's minimal price
|
||||
*
|
||||
* @param int $qty
|
||||
* @return float
|
||||
*/
|
||||
public function getSpecialPrice()
|
||||
public function getSpecialPrice($qty = null)
|
||||
{
|
||||
return $this->haveSpecialPrice() ? $this->product->special_price : $this->product->price;
|
||||
return $this->haveSpecialPrice($qty) ? $this->product->special_price : $this->product->price;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $qty
|
||||
* @return bool
|
||||
*/
|
||||
public function haveSpecialPrice()
|
||||
public function haveSpecialPrice($qty = null)
|
||||
{
|
||||
$customerGroupPrice = $this->getCustomerGroupPrice($this->product, $qty);
|
||||
|
||||
$rulePrice = app('Webkul\CatalogRule\Helpers\CatalogRuleProductPrice')->getRulePrice($this->product);
|
||||
|
||||
if ((is_null($this->product->special_price) || ! (float) $this->product->special_price) && ! $rulePrice) {
|
||||
if ((is_null($this->product->special_price) || ! (float) $this->product->special_price)
|
||||
&& ! $rulePrice
|
||||
&& $customerGroupPrice == $this->product->price
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$haveSpecialPrice = false;
|
||||
|
||||
if (! (float) $this->product->special_price) {
|
||||
if ($rulePrice && $rulePrice->price < $this->product->price) {
|
||||
$this->product->special_price = $rulePrice->price;
|
||||
|
||||
return true;
|
||||
$haveSpecialPrice = true;
|
||||
}
|
||||
} else {
|
||||
if ($rulePrice && $rulePrice->price <= $this->product->special_price) {
|
||||
$this->product->special_price = $rulePrice->price;
|
||||
|
||||
return true;
|
||||
$haveSpecialPrice = true;
|
||||
} else {
|
||||
if (core()->isChannelDateInInterval($this->product->special_price_from, $this->product->special_price_to)) {
|
||||
return true;
|
||||
$haveSpecialPrice = true;
|
||||
} elseif ($rulePrice) {
|
||||
$this->product->special_price = $rulePrice->price;
|
||||
|
||||
return true;
|
||||
$haveSpecialPrice = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
if ($haveSpecialPrice) {
|
||||
$this->product->special_price = min($this->product->special_price, $customerGroupPrice);
|
||||
} else {
|
||||
$this->product->special_price = $customerGroupPrice;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get product group price
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getCustomerGroupPrice($product, $qty)
|
||||
{
|
||||
if (is_null($qty)) {
|
||||
$qty = 1;
|
||||
}
|
||||
|
||||
$customerGroupId = null;
|
||||
|
||||
if (Cart::getCurrentCustomer()->check()) {
|
||||
$customerGroupId = Cart::getCurrentCustomer()->user()->customer_group_id;
|
||||
} else {
|
||||
$customerGroupRepository = app('Webkul\Customer\Repositories\CustomerGroupRepository');
|
||||
|
||||
if ($customerGuestGroup = $customerGroupRepository->findOneByField('code', 'guest')) {
|
||||
$customerGroupId = $customerGuestGroup->id;
|
||||
}
|
||||
}
|
||||
|
||||
$customerGroupPrices = $product->customer_group_prices()->where(function ($query) use ($customerGroupId) {
|
||||
$query->where('customer_group_id', $customerGroupId)
|
||||
->orWhereNull('customer_group_id');
|
||||
}
|
||||
)->get();
|
||||
|
||||
if (! $customerGroupPrices->count()) {
|
||||
return $product->price;
|
||||
}
|
||||
|
||||
$lastQty = 1;
|
||||
|
||||
$lastPrice = $product->price;
|
||||
|
||||
$lastCustomerGroupId = null;
|
||||
|
||||
foreach ($customerGroupPrices as $price) {
|
||||
if ($price->customer_group_id != $customerGroupId && $price->customer_group_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($qty < $price->qty) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($price->qty < $lastQty) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($price->qty == $lastQty
|
||||
&& $lastCustomerGroupId != null
|
||||
&& $price->customer_group_id == null
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($price->value < $lastPrice) {
|
||||
if ($price->value_type == 'percentage') {
|
||||
$lastPrice = $product->price * ($price->value / 100);
|
||||
} else {
|
||||
$lastPrice = $price->value;
|
||||
}
|
||||
|
||||
$lastQty = $price->qty;
|
||||
|
||||
$lastCustomerGroupId = $price->customer_group_id;
|
||||
}
|
||||
}
|
||||
|
||||
return $lastPrice;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -685,7 +779,7 @@ abstract class AbstractType
|
|||
*/
|
||||
public function validateCartItem($item)
|
||||
{
|
||||
$price = $item->product->getTypeInstance()->getFinalPrice();
|
||||
$price = $item->product->getTypeInstance()->getFinalPrice($item->quantity);
|
||||
|
||||
if ($price == $item->base_price) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -542,7 +542,7 @@ class Configurable extends AbstractType
|
|||
*/
|
||||
public function validateCartItem($item)
|
||||
{
|
||||
$price = $item->child->product->getTypeInstance()->getFinalPrice();
|
||||
$price = $item->child->product->getTypeInstance()->getFinalPrice($item->quantity);
|
||||
|
||||
if ($price == $item->base_price) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ class Downloadable extends AbstractType
|
|||
*/
|
||||
public function validateCartItem($item)
|
||||
{
|
||||
$price = $item->product->getTypeInstance()->getFinalPrice();
|
||||
$price = $item->product->getTypeInstance()->getFinalPrice($item->quantity);
|
||||
|
||||
foreach ($item->product->downloadable_links as $link) {
|
||||
if (! in_array($link->id, $item->additional['links'])) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue