Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POST /cart with jwt create 2 order records #393

Closed
tophsic opened this issue Feb 12, 2019 · 6 comments · Fixed by #401
Closed

POST /cart with jwt create 2 order records #393

tophsic opened this issue Feb 12, 2019 · 6 comments · Fixed by #401
Labels

Comments

@tophsic
Copy link

tophsic commented Feb 12, 2019

I try to understand how to use API, especially with cart and order process. I am a newbie on Sylius and ShopApiPlugin.

With "sylius/shop-api-plugin": "dev-master" and "sylius/sylius": "~1.4.0", I got a failing test with following code:

<?php

declare(strict_types=1);

namespace Tests\Sylius\ShopApiPlugin\Controller;

use League\Tactician\CommandBus;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\ShopApiPlugin\Command\AddressOrder;
use Sylius\ShopApiPlugin\Command\ChoosePaymentMethod;
use Sylius\ShopApiPlugin\Command\ChooseShippingMethod;
use Sylius\ShopApiPlugin\Command\CompleteOrder;
use Sylius\ShopApiPlugin\Command\PickupCart;
use Sylius\ShopApiPlugin\Command\PutSimpleItemToCart;
use Sylius\ShopApiPlugin\Model\Address;
use Symfony\Component\HttpFoundation\Response;
use Tests\Sylius\ShopApiPlugin\Controller\Utils\ShopUserLoginTrait;

final class MyTest extends JsonApiTestCase
{
    use ShopUserLoginTrait;

    private static $acceptAndContentTypeHeader = ['CONTENT_TYPE' => 'application/json', 'ACCEPT' => 'application/json'];

    /**
     * @test
     */
    public function it_creates_new_cart_linked_to_user()
    {
        $this->loadFixturesFromFiles(['shop.yml', 'customer.yml']);

        $this->logInUser('oliver@queen.com', '123password');


        $this->client->request('GET', '/shop-api/WEB_GB/orders', [], [], static::$acceptAndContentTypeHeader);
        $response = $this->client->getResponse();
        $content = json_decode($response->getContent());

        $this->assertSame(count($content), 0);

        $this->client->request('POST', '/shop-api/WEB_GB/carts', [], [], static::$acceptAndContentTypeHeader);
        $response = $this->client->getResponse();

        $this->client->request('GET', '/shop-api/WEB_GB/orders', [], [], static::$acceptAndContentTypeHeader);
        $response = $this->client->getResponse();
        $content = json_decode($response->getContent());

        $this->assertSame(count($content), 1);
    }
}
$ vendor/bin/phpunit -c phpunit.xml tests/Controller/MyTest.php 
PHPUnit 6.5.14 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 2.5 seconds, Memory: 30.00MB

There was 1 failure:

1) Tests\Sylius\ShopApiPlugin\Controller\MyTest::it_creates_new_cart_linked_to_user
Failed asserting that 1 is identical to 0.

/app/tests/Controller/MyTest.php:48

FAILURES!
Tests: 1, Assertions: 3, Failures: 1.

Observing what happened in database, I got 2 order records:

mysql> select * from sylius_order;
+-----+---------------------+--------------------+------------+---------------------+-------------+--------+-------+-------+-----------------------+-------------+-------------------+-------+---------------------+---------------------+---------------+-------------+----------------+---------------+----------------+--------------------------------------+-------------+
| id  | shipping_address_id | billing_address_id | channel_id | promotion_coupon_id | customer_id | number | notes | state | checkout_completed_at | items_total | adjustments_total | total | created_at          | updated_at          | currency_code | locale_code | checkout_state | payment_state | shipping_state | token_value                          | customer_ip |
+-----+---------------------+--------------------+------------+---------------------+-------------+--------+-------+-------+-----------------------+-------------+-------------------+-------+---------------------+---------------------+---------------+-------------+----------------+---------------+----------------+--------------------------------------+-------------+
| 177 |                NULL |               NULL |        481 |                NULL |         126 | NULL   | NULL  | cart  | NULL                  |           0 |                 0 |     0 | 2019-02-12 20:21:47 | 2019-02-12 20:21:47 | GBP           | en_GB       | cart           | cart          | cart           | NULL                                 | NULL        |
| 178 |                NULL |               NULL |        481 |                NULL |        NULL | NULL   | NULL  | cart  | NULL                  |           0 |                 0 |     0 | 2019-02-12 20:21:47 | 2019-02-12 20:21:47 | GBP           | en_GB       | cart           | cart          | cart           | 5758b627-ce72-4e06-b458-2597c0986d62 | NULL        |
+-----+---------------------+--------------------+------------+---------------------+-------------+--------+-------+-------+-----------------------+-------------+-------------------+-------+---------------------+---------------------+---------------+-------------+----------------+---------------+----------------+--------------------------------------+-------------+
2 rows in set (0.01 sec)

Maybe I misused ShopApiPlugin but it is not clear for me how I create a cart and associate it with logged user.

Thank you for your help.

@tophsic
Copy link
Author

tophsic commented Feb 13, 2019

In my test, I totally missed the checkout process! I forgot to tell I am also a newbie on e-commerce standards!

However, is it normal I got 2 order records after a POST request on /cart/{token} resource provided with a JWT token? One with customer_id and the other one with token_value.

@mamazu
Copy link
Member

mamazu commented Feb 13, 2019

Normally an order only exists without a customer. Only when completing the checkout the cart gets assigned to a customer by their email or if they are logged in by the logged in customer's email.

@tophsic tophsic changed the title Cart and Order process question POST /cart with jwt create 2 order records Feb 13, 2019
@tophsic
Copy link
Author

tophsic commented Feb 13, 2019

See my test on commit TheRealCodeKraft/ShopApiPlugin@7a74f95 and corresponding failing build https://travis-ci.org/TheRealCodeKraft/ShopApiPlugin/jobs/492914339.

        $this->loadFixturesFromFiles(['shop.yml', 'customer.yml']);

        $this->logInUser('oliver@queen.com', '123password');

        $this->client->request('POST', '/shop-api/WEB_GB/carts', [], [], static::$acceptAndContentTypeHeader);
        $response = $this->client->getResponse();

        $orderRepository = $this->get('sylius.repository.order');
        $count = $orderRepository->count([]);

        $this->assertSame(1, $count, 'Only one cart should be created');

@lchrusciel lchrusciel added the Bug label Feb 15, 2019
@lchrusciel
Copy link
Member

Thanks for reporting. You have used the wrong endpoint for orders list, as you should use cart endpoints, instead of order. The order is the cart that has been already placed.

Nevertheless, there should be only one cart in the database, but it will require further investigation.

@mamazu
Copy link
Member

mamazu commented Feb 16, 2019

So after some debugging I found that the add method on the order repository is only called once and this propagates down to the flush method that only flushes one entity. In the state machine there is also no transition defined I haven't got a debugger defined so I couldn't look into the step by step definition. So in the shop-api there is no different behavior for logged in or anonymous users when picking up the cart. @kortwotze maybe has some more information as we have already notices something being off.

@mamazu
Copy link
Member

mamazu commented Feb 16, 2019

It just struck me like a lightning. It's the UserCartRecalculationListener. This listener is run for every authenticated request. The content of this listener is to recalculate the cart (this has caused problems in our shop as well so we deactivated it). It creates a cart if no cart exists. This is why the one cart (created by the Handler has a token but no customer) and the other cart created by the listener has a customer but no token.

@mamazu mamazu mentioned this issue Feb 16, 2019
lchrusciel added a commit that referenced this issue Mar 7, 2019
This PR was merged into the 1.0-dev branch.

Discussion
----------

This fixes #393 

In this pull request I introduced a new Request and Command object for picking up a cart of a customer that is logged in. This way I registered a new handler. The `PickupLoggedInCart` Command and Request object inherit from the "non logged in"-version.

Commits
-------

433ec63 Fix for the duplicate cart
ab94312 Codestyle
42ae068 Refactored it
164b3d2 Reverted to simpler fix
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants