wagnerwagner / merx

Merx is a plugin to create online shops with Kirby.
https://merx.wagnerwagner.de
102 stars 10 forks source link

same product with different attribute in cart possible? #18

Closed sigistardust closed 3 years ago

sigistardust commented 4 years ago

hello,

is it possible to add the same product to the cart twice, but with different attributes, e.g. a jacket in size 48 and a jacket in size 50. right now, the size of the first product just gets overwritten if i add the second product.

i am trying to avoid the necessity of subpages for all product variations and would rather like to use a structure field in the product blueprint since it makes it much more easier to update, especially for a large amount of products.

any help on this is appreciated!

thank you for the great work on this plugin!

alexpi commented 3 years ago

Hello @sigistardust. Did you find a solution to your problem? I am in the exact same situation.

sigistardust commented 3 years ago

hi @alexpi i actually found that splitting the variants up in different products is the better solution for me. but still, this question is very interesting to me, especially for future projects.

tobiasfabian commented 3 years ago

It would be possible to compare every attribute of a product and only merge products when every single attribute (except quantity) is the same. This would require some modifications of the $productList->updateItem() method.

The following code would result in two ProductList/Cart entries and won’t be merged.

$cart->add([
  'id' => 'jacket',
  'size' => 48,
]);
$cart->add([
  'id' => 'jacket',
  'size' => 50,
]);

What do you think?

alexpi commented 3 years ago

So, if I get this right, this modification would allow products with the same id to be added to the cart, and abollish the necessity for subpage variations?

tobiasfabian commented 3 years ago

Yes, that’s correct.

alexpi commented 3 years ago

So, should I try to modify your code to enable this functionality or are you considering adding it to the plugin?

tobiasfabian commented 3 years ago

@alexpi Today, I tried a different approach.

With the latest commit (d05dd4d0a9ee2891ff2f61dd3d84661e09ca2c52) in the develop branch I modified the Cart::add() method. The Cart::add() method now can handle one or two arguments.

You can provide a unique key as first argument and your cart item as the second argument. As long as the key is unique the items won’t be merged. So, the following would be possible.

$cart->add('jacket-48', [
  'id' => 'jacket',
  'size' => 48,
]);
$cart->add('jacket-50', [
  'id' => 'jacket',
  'size' => 50,
]);

To remove a cart item your code must be as follows.

$cart->remove('jacket-48');
sigistardust commented 3 years ago

@tobiasfabian @alexpi glad to see that you are looking for possible improvements on that! shall I leave the issue open?

alexpi commented 3 years ago

@sigistardust I haven't tried the solution yet (I will in a few days), but it seems like it will solve my use case perfectly.

tobiasfabian commented 3 years ago

@tobiasfabian @alexpi glad to see that you are looking for possible improvements on that! shall I leave the issue open?

Yes, I’ll close it as soon as I think the issue is solved.

@sigistardust I haven't tried the solution yet (I will in a few days), but it seems like it will solve my use case perfectly.

Looking forward to your feedback.

sigistardust commented 3 years ago

@tobiasfabian I tried your last solution and adding to cart works for me! i will come back after testing more with the cart update and remove.

sigistardust commented 3 years ago

@tobiasfabian could you please tell me what the easiest way is to:

thank you very much!

sigistardust commented 3 years ago

@tobiasfabian found a solution for me with the add method. looks like this inside my config.php:

'routes' => [
        [
          'method' => 'post',
          'pattern' => 'shop-api/add-to-cart',
          'action' => function() {
            try {
              $data = kirby()->request()->data();
              if (merx()->cart()->find($data['id'] . $data['size'])) {
                merx()->cart()->add($data['id'] . $data['size'], [
                  'id' => $data['id'],
                  'quantity' => merx()->cart()->find($data['id'] . $data['size'])['quantity'] + $data['quantity'],
                  'size' => $data['size'],
                ]);
              } else {
                merx()->cart()->add($data['id'] . $data['size'], [
                    'id' => $data['id'],
                    'quantity' => $data['quantity'],
                    'size' => $data['size'],
                ]);
              }
              go(page($data['id'])->url() . '/addedtoorder:yes');
            } catch (Kirby\Exception\Exception $ex) {
              return $ex->toArray();
            }
          },
        ],
    ]
alexpi commented 3 years ago

@tobiasfabian I finally got to try this. It works great! I can't find how to update a variation on the cart though.

tobiasfabian commented 3 years ago

I can't find how to update a variation on the cart though.

The latest commit (8df5d40e0f1b922f95b8fd1113500dd459d021c7) should fix this.

alexpi commented 3 years ago

Sorry, I don't understand how to use updateItem to update a variation. I have the following code:

'pattern' => 'shop-api/update-cart-item',
'method' => 'POST',
'action' => function() {
  try {
    $data = kirby()->request()->data();
    $product = kirby()->page($data['id']);

    $cart = merx()->cart();

    $cart->updateItem([
      'id' => $data['variation'],
      'quantity' => (float) ($data['quantity'] ?? 1),
    ]);

    $item = [
      'id' => $data['id'],
      'variation' => $data['variation'],
      'buildtime' => ((float) $data['quantity'] === 1) ? 'false' : buildtime($product, $data['material'], $data['variations']),
      'total' => $cart->find($data['variation'])['sum']
    ];

    return [
      'status' => 200,
      'item' => $item,
      'cart' => [
        'total' => $cart->getSum(),
        'count' => $cart->count()
      ]
    ];
  } catch (Kirby\Exception\Exception $ex) {
    return $ex->toArray();
  }
}    

When calling updateItem, I am passing the variation in order to find it in the cart, but this action also changes the product's id, which I need in order to get the original product page.

tobiasfabian commented 3 years ago

Sorry I forgot to explain the changes of the commit.

If you are working with product variants you have to use key instead of id to update the cart item.

This is how it should work.

    $cart->updateItem([
      'key' => $data['variation'],
      'quantity' => (float) ($data['quantity'] ?? 1),
    ]);