Updating cart address at login

Help for integrating the Laravel package
Forum rules
Always add your Laravel, Aimeos and PHP version as well as your environment (Linux/Mac/Win)
Spam and unrelated posts will be removed immediately!
swpierce
Posts: 53
Joined: 01 Nov 2015, 13:19

Updating cart address at login

Post by swpierce » 30 Nov 2015, 04:52

I would like to adapt the basket such that when a customer authenticates, the address in the basket is automatically updated if the customer has an address set (which they should since we require it at registration). Conversely, it'd be nice if I could add a hook such that if customer logs out, basket gets wiped.

Example scenario:
Customer in Australia is browsing as guest. We don't know they're from Canada so we are using a US address to estimate shipping.
Customer decides to log in. Clicks on basket to see if they like the order and are ready to check out. Basket still shows estimated shipping for US address because basket address didn't change when customer logged in.
Customer gets excited and rushes to checkout. Shipping is wrong.

Scenario 2 (likely to never happen but could on a shared machine):
Customer A is logged in and shopping. Abandons cart. Logs out.
Customer B later uses same machine to start shopping. All of customer A's items are still in cart. Further, Customer A's mailing info, etc. is still set in basket when Customer B clicks on basket. Minor security issue.

I was going to add the code for updating the basket to the AuthController in an authenticated() method so that it would run on successful authentication but I can't seem to figure out how to get access to the proper Aimeos objects to get the basket and update the address. I'm likely overlooking something after staring at it too long... ;)

Is there a configuration setting where we could "timeout" session stuff after a while? I can load up the cart, shut the browser, and 3 days later the stuff is still in the cart when I go back. Sometimes useful, sometimes not. Definitely not useful for a shared computer situation. A large number of our customer are in university so the shared computer thing is a bit of a hassle.

We launched today. 2 days late and without a couple key pieces we need to work on but it's live. Finally :P

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

Re: Updating cart address at login

Post by aimeos » 30 Nov 2015, 10:30

swpierce wrote:Customer in Australia is browsing as guest. We don't know they're from Canada so we are using a US address to estimate shipping.
Customer decides to log in. Clicks on basket to see if they like the order and are ready to check out. Basket still shows estimated shipping for US address because basket address didn't change when customer logged in.
Customer gets excited and rushes to checkout. Shipping is wrong.
I think now it's a bit a problem that you set a default address for each customer if they are not logged in. If you won't do this and only the first shipping option will be added by the "ServiceUpdate" basket plugin when a product is added, the customer address would be set automatically by the to the correct one by the "Autofill" plugin. When clicking on the "checkout" button, customers will see the delivery page of the checkout process where they have to choose another shipping option (e.g. Canada) because the default one (US) isn't available any more. This will also update the shipping costs automatically and the end price will be correct.
swpierce wrote:Is there a configuration setting where we could "timeout" session stuff after a while? I can load up the cart, shut the browser, and 3 days later the stuff is still in the cart when I go back.
The session timeout is a PHP setting on your server. If you use session cookies (lifetime: 0), the session is also gone if you close your browser. You can also clear the complete session on logout adding a line in your Laravel AuthController.
swpierce wrote:how to get access to the proper Aimeos objects to get the basket and update the address
You can access the Aimeos basket from Laravel with

Code: Select all

\Aimeos\Controller\Frontend\Factory::createController( $context, 'basket )->get()
If you only want to clear the basket and leave the rest of the session untouched, you can call

Code: Select all

\Aimeos\Controller\Frontend\Factory::createController( $context, 'basket )->clear()
The available methods of the basket are listed here:
https://github.com/aimeos/aimeos-core/b ... /Iface.php
swpierce wrote:We launched today. 2 days late and without a couple key pieces we need to work on but it's live. Finally :P
Cool! Can we have a look?
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, Image give us a star

swpierce
Posts: 53
Joined: 01 Nov 2015, 13:19

Re: Updating cart address at login

Post by swpierce » 30 Nov 2015, 13:26

Awesome! Thanks for the pointers. I'll start working on those "fixes" for our site.

Our site is http://planabilities.com if you want to take a look.

Thanks again for all the help in getting us up and running. Next step: writing a customer loyalty component to add to the site . The work never ends ;)

swpierce
Posts: 53
Joined: 01 Nov 2015, 13:19

Re: Updating cart address at login

Post by swpierce » 30 Nov 2015, 15:55

Trying to come up with a way around this but not having any ideas...
I think now it's a bit a problem that you set a default address for each customer if they are not logged in. If you won't do this and only the first shipping option will be added by the "ServiceUpdate" basket plugin when a product is added, the customer address would be set automatically by the to the correct one by the "Autofill" plugin. When clicking on the "checkout" button, customers will see the delivery page of the checkout process where they have to choose another shipping option (e.g. Canada) because the default one (US) isn't available any more. This will also update the shipping costs automatically and the end price will be correct.
It's a requirement that we show estimated shipping as close as possible to what it actually is. The shipping calculator API requires a postal code (and a country code if international). We're also building with an eye to the future. Eventually, the customer - via the My Account page - will be able to manage multiple addresses and select addresses from a dropdown. That's a way off but they will be able to designate a saved address as their "default" to use for billing and/or delivery. I think our initial implementation idea is faulty. Our new idea is to modify the AutoFill plugin to handle checking for addresses the way we need. We'll play around with that for a bit.
\Aimeos\Controller\Frontend\Factory
No matter what I try in the AuthController, I always get the same error:

Code: Select all

Class 'Aimeos\Controller\Frontend\Factory' not found
Here is the line of code:

Code: Select all

$basket = \Aimeos\Controller\Frontend\Factory::createController( $context, 'basket' )->get();
I can successfully get the context using:

Code: Select all

$context = App::make( '\Aimeos\Shop\Base\Context' )->get( false );
I've been using these docs to try and get access to the Aimeos objects: https://aimeos.org/docs/Laravel/Extend_Aimeos

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

Re: Updating cart address at login

Post by aimeos » 30 Nov 2015, 16:41

swpierce wrote: It's a requirement that we show estimated shipping as close as possible to what it actually is. The shipping calculator API requires a postal code (and a country code if international). Our new idea is to modify the AutoFill plugin to handle checking for addresses the way we need. We'll play around with that for a bit.
Your main problem might be the calculation depending on the weight of the products so it's no fixed shipping cost you can calculate with for your standard delivery area (US). Try to copy and modify the ServiceUpdate basket plugin to add the costs based on the API you are using. But beware: External servers may slow down every basket action a lot!
swpierce wrote:We're also building with an eye to the future. Eventually, the customer - via the My Account page - will be able to manage multiple addresses and select addresses from a dropdown. That's a way off but they will be able to designate a saved address as their "default" to use for billing and/or delivery.
Multiple delivery addresses are already available. They are managed in the address page of the checkout process and new ones are saved automatically.
swpierce wrote:No matter what I try in the AuthController, I always get the same error:

Code: Select all

Class 'Aimeos\Controller\Frontend\Factory' not found
If you are using the stable version, it's "Controller_Frontend_Factory::createController()". We've moved to PSR-4 two month ago.
swpierce wrote:I can successfully get the context using:

Code: Select all

$context = App::make( '\Aimeos\Shop\Base\Context' )->get( false );
Don't use the "false" parameter for get()! That's only for command controllers and would lead to an exception in your case.
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, Image give us a star

swpierce
Posts: 53
Joined: 01 Nov 2015, 13:19

Re: Updating cart address at login

Post by swpierce » 30 Nov 2015, 17:01

Code: Select all

Your main problem might be the calculation depending on the weight of the products so it's no fixed shipping cost you can calculate with for your standard delivery area (US). Try to copy and modify the ServiceUpdate basket plugin to add the costs based on the API you are using. But beware: External servers may slow down every basket action a lot!
Excellent! We'll take a look at the ServiceUpdate plugin and see what we can do with that. Thanks for the tip!

Code: Select all

Multiple delivery addresses are already available. They are managed in the address page of the checkout process and new ones are saved automatically.
More good news. We hadn't actually messed with multiple addresses yet. Only tested using single addresses to make sure we could launch as quickly as possible. Should be trivial to add address management to the My Account section. Does the current code support multiple billing addresses as well or just delivery addresses?

Code: Select all

If you are using the stable version, it's "Controller_Frontend_Factory::createController()". We've moved to PSR-4 two month ago.

Don't use the "false" parameter for get()! That's only for command controllers and would lead to an exception in your case.
Gotcha! You guys are awesome! :)

swpierce
Posts: 53
Joined: 01 Nov 2015, 13:19

Re: Updating cart address at login

Post by swpierce » 30 Nov 2015, 18:20

OK. Got the cart clearing thing to work on logout. One little annoyance I can't figure out...

If, after logout, I redirect to /list, the mini basket still shows product. Clicking on the mini basket to go to the standard basket confirms the basket is empty.

Similarly, if I redirect to /basket after logout, you can see the basket is empty.

I've been looking at the code in Client\Html\Basket\Mini\Default but I'm not sure how to fix the issue. I'm guessing the issue is that the _setViewParam method is simply returning $this->_cache because it's still set. Is there an easy way to kick the mini basket so it knows the standard basket got wiped? Do we need to adapt the default mini basket implementation?

Thanks!

nos3
Posts: 86
Joined: 01 Sep 2015, 13:26

Re: Updating cart address at login

Post by nos3 » 30 Nov 2015, 22:59

swpierce wrote:Should be trivial to add address management to the My Account section. Does the current code support multiple billing addresses as well or just delivery addresses?
The core library supported multiple billing addresses years ago but we had experienced difficulties because all external systems support only one and have not been able to cope with more than one. Therefore, we've removed that and integrated the billing address in the customer item.
swpierce wrote:Gotcha! You guys are awesome! :)
Don't forget the girls! ;-)


Norbert

nos3
Posts: 86
Joined: 01 Sep 2015, 13:26

Re: Updating cart address at login

Post by nos3 » 30 Nov 2015, 23:03

swpierce wrote: If, after logout, I redirect to /list, the mini basket still shows product. Clicking on the mini basket to go to the standard basket confirms the basket is empty.
The mini basket is cached in the session for performance reasons:
https://github.com/aimeos/aimeos-core/b ... t/Base.php

The simplest way is to discard the session completely. This will also wipe out the cached basket.

swpierce
Posts: 53
Joined: 01 Nov 2015, 13:19

Re: Updating cart address at login

Post by swpierce » 01 Dec 2015, 01:34

The mini basket is cached in the session for performance reasons:
https://github.com/aimeos/aimeos-core/b ... t/Base.php

The simplest way is to discard the session completely. This will also wipe out the cached basket.
I figured that out after a walk around the neighborhood. Works for logout. I still have an issue with login, though.

After successful login, I update the address in the cart if needed. I then grab the delivery service item and get the correct shipping. Works great. Post-login redirects to the basket view. Basket shows updated shipping but mini-basket still shows values from prior to logging in.

At the end of the authenticated method, I'm doing this:

Code: Select all

$params = app( '\Aimeos\Shop\Base\Page' )->getSections( 'basket-index' );
return \View::make('shop::basket.index', $params);
How can I force the mini basket to refresh if the standard basket refreshes? The code I'm using to re-calc the shipping at login is:

Code: Select all

            $serviceManager = \MShop_Factory::createManager( $context, 'service' );
            
            $search = $serviceManager->createSearch( true );
            
            $search->setConditions( $search->compare( '==', 'service.code', 'usps' ) );
            
            $result = $serviceManager->searchItems( $search, array( 'media', 'price', 'text' ) );
            
            foreach( $result as $item )
            {
                $provider = $serviceManager->getProvider( $item );
                if( $provider->isAvailable( $basket ) === true )
                {
                    $orderServiceManager = \MShop_Factory::createManager( $context, 'order/base/service' );
                    $orderServiceItem = $orderServiceManager->createItem();
                    $orderServiceItem->copyFrom( $item );
                    $orderServiceItem->setPrice( $provider->calcPrice( $basket ) );

                    $basket->setService( $orderServiceItem, \MShop_Order_Item_Base_Address_Abstract::TYPE_DELIVERY );
                }
            }
Of course, it only runs if I change the address. If I don't change the address, no need to recalculate shipping

Post Reply