How to implement a down payment / deposit option

How to configure and adapt Aimeos based shops as developer
Forum rules
Always add your Aimeos and PHP version as well as your environment (Linux/Mac/Win)
ralfk
Posts: 7
Joined: 24 Jun 2019, 12:47

How to implement a down payment / deposit option

Post by ralfk » 24 Jun 2019, 13:03

Hello all,
first of all I want to thank the developpers for the shop they created.
I'm new to aimeos and this forum and I don't know exactly if this is exactly the right place to post my question.
I'm using version 2018 of aimeos as a typo3 Extension with Typo3 8, but I think this is not a Typo3 question.

I would like to place a service or plugin or function that allowes the customer to choose between paying the whole price for all items in the basket or to make a deposit of 50% of the total amount. I'm a little stuck at the moment and would appreciate any help.

Thanks in advance, best regards

Ralf

User avatar
aimeos
Administrator
Posts: 3317
Joined: 01 Jan 1970, 00:00

Re: How to implement a down payment / deposit option

Post by aimeos » 24 Jun 2019, 17:28

A payment service decorator might be the best option for your requirement. You can implement the calcPrice() method and return a price value that is -50% of the total basket value. This negative price would be added to the basket total and thus reduces the payment amount by 50%. You only have to add two payment options, one with and one without the decorator.

More about service decorators:
https://aimeos.org/docs/Developers/Libr ... _decorator
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, Image give us a star

ralfk
Posts: 7
Joined: 24 Jun 2019, 12:47

Re: How to implement a down payment / deposit option

Post by ralfk » 25 Jun 2019, 13:56

Thanks a lot aimeos,
I'll go through the documentation and the examples.

Best regards

ralfk

ralfk
Posts: 7
Joined: 24 Jun 2019, 12:47

Re: How to implement a down payment / deposit option

Post by ralfk » 26 Jun 2019, 14:44

Hello again,
I took a look at the decorators, and the approach makes sence, I think.
Just to make sure I got it right, what I basically have to do is write the decorator,
place it in the corresponding or equivalent path of my own Typo3 extension,
create an autoload file to register the class (is my extension root OK or do I have to duplicate your autoloading mechanism?),
create or duplicate the the payment services in backend and add the decorator to them.

Did I forget anything?

Thanks in advance

ralfk

User avatar
aimeos
Administrator
Posts: 3317
Joined: 01 Jan 1970, 00:00

Re: How to implement a down payment / deposit option

Post by aimeos » 27 Jun 2019, 09:18

Usually, you don't have to care about autoloading. Only, if you use composer but don't install your own extension via composer but e.g. git
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, Image give us a star

ralfk
Posts: 7
Joined: 24 Jun 2019, 12:47

Re: How to implement a down payment / deposit option

Post by ralfk » 28 Jun 2019, 07:48

Thanks a lot aimeos,
have a nice weekend

ralfk

ralfk
Posts: 7
Joined: 24 Jun 2019, 12:47

Re: How to implement a down payment / deposit option

Post by ralfk » 05 Jul 2019, 11:58

Hello again,

I managed to get the decorator function to work, it is also adding the "deposit product" to the basket, but no matter what I do, the decorator is executed three times, once you go from basket to checkout, once you go to the payment option and last but not least when going to summary.
I already wrote a piece of code to remove the deposit before going to the summary page, but one big problem remains, no matter what payment option I choose, it always shows the deposit item in summary page.
BTW, the decorator is only added to one specific payment provider.
What am I doing wrong?

Here is the complete decorator code:

Code: Select all

<?php

/**
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
 * @copyright Metaways Infosystems GmbH, 2013
 * @copyright Aimeos (aimeos.org), 2015-2018
 * @package MShop
 * @subpackage Service
 */


namespace Aimeos\MShop\Service\Provider\Decorator;


/**
 * Decorator for service providers adding additional costs.
 *
 * @package MShop
 * @subpackage Service
 */
class Deposit
	extends \Aimeos\MShop\Service\Provider\Decorator\Base
	implements \Aimeos\MShop\Service\Provider\Decorator\Iface
{
	private $beConfig = array(
		'deposit.percent' => array(
			'code' => 'deposit.percent',
			'internalcode' => 'deposit.percent',
			'label' => 'deposit: Decimal percent value',
			'type' => 'number',
			'internaltype' => 'float',
			'default' => 0,
			'required' => true,
		),
	);


	/**
	 * Checks the backend configuration attributes for validity.
	 *
	 * @param array $attributes Attributes added by the shop owner in the administraton interface
	 * @return array An array with the attribute keys as key and an error message as values for all attributes that are
	 * 	known by the provider but aren't valid
	 */
	public function checkConfigBE( array $attributes )
	{
		$error = $this->getProvider()->checkConfigBE( $attributes );
		$error += $this->checkConfig( $this->beConfig, $attributes );

		return $error;
	}


	/**
	 * Returns the configuration attribute definitions of the provider to generate a list of available fields and
	 * rules for the value of each field in the administration interface.
	 *
	 * @return array List of attribute definitions implementing \Aimeos\MW\Common\Critera\Attribute\Iface
	 */
	public function getConfigBE()
	{
		return array_merge( $this->getProvider()->getConfigBE(), $this->getConfigItems( $this->beConfig ) );
	}


	/**
	 * Returns the price when using the provider.
	 * Usually, this is the lowest price that is available in the service item but can also be a calculated based on
	 * the basket content, e.g. 2% of the value as transaction cost.
	 *
	 * @param \Aimeos\MShop\Order\Item\Base\Iface $basket Basket object
	 * @return \Aimeos\MShop\Price\Item\Iface Price item containing the price, shipping, rebate
	 */
	public function calcPrice( \Aimeos\MShop\Order\Item\Base\Iface $basket )
	{
		$config = $this->getServiceItem()->getConfig();

		if( !isset( $config['deposit.percent'] ) ) {
			throw new \Aimeos\MShop\Service\Exception( sprintf( 'Missing configuration "%1$s"', 'deposit.percent' ) );
		}

		if(is_array($basket->getProducts()) && !empty($basket->getProducts())){
			$itemPositions = array();
			foreach($basket->getProducts() as $p => $basketItem){
				if($basketItem->getProductId() == 143){
					$itemPositions[] = $p;
				}
			}
			
			if(is_array($itemPositions) && !empty($itemPositions)){
				foreach($itemPositions as $i => $position)
					$basket->deleteProduct($position);
			}

			$price = $basket->getPrice();			
		}
		
		$value = $basket->getPrice()->getValue() * $config['deposit.percent'] / 100;

		
		$productManager = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'product' );
		$product = $productManager->getItem( 143, array( 'text', 'media', 'price' ) );
		
		$prices = $product->getRefItems( 'price', 'default', 'default' );
		if(is_array($prices) && !empty($prices)){
			foreach($prices as $p){
				$productPrice = $p;
				break;
			}
			$productPrice->setValue(-$value);
			$productPrice->setRebate($value);	
			$orderProduct = \Aimeos\MShop\Factory::createManager( $this->getContext(), 'order/base/product' )->createItem();
			$orderProduct->copyFrom( $product );
			$orderProduct->setPrice($productPrice);

			$basket->addProduct( $orderProduct );
			$price = $basket->getPrice();
		}

		return $price;
	}
}


Thanks in advance.

Best regards

ralfk
Last edited by ralfk on 05 Jul 2019, 12:52, edited 1 time in total.

User avatar
aimeos
Administrator
Posts: 3317
Joined: 01 Jan 1970, 00:00

Re: How to implement a down payment / deposit option

Post by aimeos » 05 Jul 2019, 12:30

It's normal that the decorator is called more than once because it's checked at multiple occurences. You should not add a "deposit" product because you have no chance to remove that again. Instead, set the price value of the payment option to a negative value.
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, Image give us a star

ralfk
Posts: 7
Joined: 24 Jun 2019, 12:47

Re: How to implement a down payment / deposit option

Post by ralfk » 05 Jul 2019, 14:08

Hello again,

OK, the extra product is out, I reduced everything to this:

Code: Select all

$config = $this->getServiceItem()->getConfig();

if( !isset( $config['deposit.percent'] ) ) {
	throw new \Aimeos\MShop\Service\Exception( sprintf( 'Missing configuration "%1$s"', 'deposit.percent' ) );
}
$price = $basket->getPrice();
$value = $basket->getPrice()->getValue() * $config['deposit.percent'] / 100;
$price->setRebate( $price->getRebate() + $value );
$price->setCosts( $price->getCosts() - $value );


return $price;
just to test, it is basically the reduction decorator.

I have an article worth 449 €, I checked the the deposit payment option with paypal, was redirected to paypal, and paypal asked me to pay 673.50 €, which is 3 times 50% of the article value.

There must be something wrong.
Is there a way to check if the payment option "was clicked"?
Something like if(isset($paymentOption) && $paymentOption == 'deposit')

Thanks again,

Ralf

User avatar
aimeos
Administrator
Posts: 3317
Joined: 01 Jan 1970, 00:00

Re: How to implement a down payment / deposit option

Post by aimeos » 06 Jul 2019, 12:06

Objects are references in PHP and if you update the price of the basket, it will add up. You can either use "clone" or create a new price item you return using:

Code: Select all

$priceItem = \Aimeos\MShop::create( $this->getContext(), 'price' )->createItem();
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, Image give us a star

Post Reply