Page 1 of 1

How to set price of attributes in basket base of supplier/sites

Posted: 01 Dec 2022, 17:37
by developer
How to set price of attributes in basket base of supplier/sites?
I have set price of attrbutes different for each supplie/site, But once i try to add to cart product its take default site attribute price on basket.

How I can add attributes price base on supplier/site proudct.

I have also try with siteid on attributes hiddent set on product details page.

Code: Select all

  <input type="hidden" name="<?= $enc->attr($this->formparam(['b_prod', 0, 'siteid'])) ?>" value="<?= $enc->attr($this->detailProductItem->getSiteId()) ?>">
                                    <input type="hidden" name="b_siteid" value="<?= $enc->attr($this->detailProductItem->getSiteId()) ?>">
Can anyone help me for the same?
Thanks in Advance

Re: How to set price of attributes in basket base of supplier/sites

Posted: 02 Dec 2022, 08:43
by aimeos
Can you please tell us more about your setup?

Re: How to set price of attributes in basket base of supplier/sites

Posted: 03 Dec 2022, 16:08
by developer
Here I have added my composer.json file code for check version of aimeos and other details.

Code: Select all

"php": "^7.3||^8.0",
        "composer-runtime-api": "^2.1",
        "aimeos/ai-cache": "~2021.10",
        "aimeos/ai-client-html": "2021.10.x-dev",
        "aimeos/ai-controller-frontend": "2021.10.x-dev",
        "aimeos/ai-controller-jobs": "2021.10.x-dev",
        "aimeos/ai-filesystem": "~2021.10",
        "aimeos/ai-payments": "2021.10.x-dev",
        "aimeos/aimeos-core": "2021.10.x-dev",
        "aimeos/aimeos-laravel": "2021.10.x-dev",
        "aimeoscom/ai-sites": "2021.10.x-dev",
        "aimeoscom/ai-stripe-marketplace": "2021.10.x-dev",
        
But I have stuck here, because basket product get the default first price of attribute. I want price of attributes as supplier/site set.

Might be some where this section where i need to update but its on vendor part, any other way?
\vendor\aimeos\ai-controller-frontend\controller\frontend\src\Controller\Frontend\Basket\Standard.php

Code: Select all

public function addProduct( \Aimeos\MShop\Product\Item\Iface $product,
		float $quantity = 1, array $variant = [], array $config = [], array $custom = [],
		string $stocktype = 'default', string $supplierid = null, string $siteid = null ) : Iface
	{
		$quantity = $this->call( 'checkQuantity', $product, $quantity );
		$this->call( 'checkAttributes', [$product], 'custom', array_keys( $custom ) );
		$this->call( 'checkAttributes', [$product], 'config', array_keys( $config ) );

		$prices = $product->getRefItems( 'price', 'default', 'default' );
		$hidden = $product->getRefItems( 'attribute', null, 'hidden' );

		$custAttr = $this->call( 'getOrderProductAttributes', 'custom', array_keys( $custom ), $custom );
		$confAttr = $this->call( 'getOrderProductAttributes', 'config', array_keys( $config ), [], $config );
		$hideAttr = $this->call( 'getOrderProductAttributes', 'hidden', $hidden->keys()->toArray() );

		$orderBaseProductItem = \Aimeos\MShop::create( $this->getContext(), 'order/base/product' )->create()
			->copyFrom( $product )->setQuantity( $quantity )->setStockType( $stocktype )
			->setAttributeItems( array_merge( $custAttr, $confAttr, $hideAttr ) );

		$orderBaseProductItem = $orderBaseProductItem
			->setPrice( $this->call( 'calcPrice', $orderBaseProductItem, $prices, $quantity ) );

		if( $siteid ) {
			$orderBaseProductItem->setSiteId( $siteid );
		}

		if( $supplierid )
		{
			$name = \Aimeos\MShop::create( $this->getContext(), 'supplier' )->get( $supplierid, ['text'] )->getName();
			$orderBaseProductItem->setSupplierId( $supplierid )->setSupplierName( $name );
		}

		$this->baskets[$this->type] = $this->get()->addProduct( $orderBaseProductItem );
		return $this->save();
	}
\controller\frontend\src\Controller\Frontend\Basket\Base.php

Code: Select all

protected function getOrderProductAttributes( string $type, array $ids, array $values = [], array $quantities = [] )
	{
		$list = [];

		if( !empty( $ids ) )
		{
			$manager = \Aimeos\MShop::create( $this->getContext(), 'order/base/product/attribute' );

			foreach( $this->getAttributes( $ids ) as $id => $attrItem )
			{
				$list[] = $manager->create()->copyFrom( $attrItem )->setType( $type )
					->setValue( isset( $values[$id] ) ? $values[$id] : $attrItem->getCode() )
					->setQuantity( isset( $quantities[$id] ) ? $quantities[$id] : 1 );
			}
		}

		return $list;
	}

Re: How to set price of attributes in basket base of supplier/sites

Posted: 04 Dec 2022, 10:59
by aimeos
The problem that in marketplace setups the lowest price of all vendors is used instead of the vendor attribute price when more then one vendor uses the same attribute maybe could be solved here:
https://github.com/aimeos/ai-controller ... hp#L56-L66

If we change that to:

Code: Select all

$siteId = $this->context()->locale()->getSiteId();

foreach( $orderAttributes as $orderAttrItem )
{
	if( !( $attrItem = $attrItems->get( $orderAttrItem->getAttributeId() ) ) ) {
		continue;
	}
			
	$prices = $attrItem->getRefItems( 'price', 'default', 'default' )->filter( function( $price ) use ( $orderProduct, $siteId ) {
		return $price->getSiteId() === $orderProduct->getSiteId() || $price->getSiteId() === $siteId;
	} );
			
	if( !$prices->isEmpty() )
	{
		$attrPrice = $priceManager->getLowestPrice( $prices, $orderAttrItem->getQuantity() );
		$price = $price->addItem( clone $attrPrice, $orderAttrItem->getQuantity() );
		$orderAttrItem->setPrice( $attrPrice->addItem( $attrPrice, $orderAttrItem->getQuantity() - 1 )->getValue() );
	}
}
Can you check and make a PR if it works?

Re: How to set price of attributes in basket base of supplier/sites

Posted: 05 Dec 2022, 17:24
by developer
Thanks for your support.
It working perfectly!