diff --git a/src/CoreShop/Bundle/CoreBundle/Migrations/Version20260616120000.php b/src/CoreShop/Bundle/CoreBundle/Migrations/Version20260616120000.php new file mode 100644 index 0000000000..e73f331969 --- /dev/null +++ b/src/CoreShop/Bundle/CoreBundle/Migrations/Version20260616120000.php @@ -0,0 +1,89 @@ +container->getParameter('coreshop.model.order.pimcore_class_name'), + ); + + if ($classUpdater->hasField('lastActivatedAt')) { + return; + } + + $classUpdater->insertFieldAfter('orderDate', [ + 'name' => 'lastActivatedAt', + 'title' => 'Last Activated At', + 'tooltip' => 'Timestamp the cart was last selected/activated by its customer; used to restore the last-opened cart across sessions.', + 'mandatory' => false, + 'noteditable' => true, + 'index' => true, + 'locked' => false, + 'style' => '', + 'permissions' => null, + 'fieldtype' => 'datetime', + 'relationType' => false, + 'invisible' => false, + 'visibleGridView' => false, + 'visibleSearch' => false, + 'defaultValue' => null, + 'useCurrentDate' => false, + 'queryColumnType' => 'bigint(20)', + 'columnType' => 'bigint(20)', + 'phpdocType' => '\\Carbon\\Carbon', + 'datatype' => 'data', + ]); + + $classUpdater->save(); + } + + public function down(Schema $schema): void + { + $classUpdater = new ClassUpdate( + $this->container->getParameter('coreshop.model.order.pimcore_class_name'), + ); + + if (!$classUpdater->hasField('lastActivatedAt')) { + return; + } + + $classUpdater->removeField('lastActivatedAt'); + $classUpdater->save(); + } +} diff --git a/src/CoreShop/Bundle/CoreBundle/Resources/install/pimcore/classes/CoreShopOrderBundle/CoreShopOrder.json b/src/CoreShop/Bundle/CoreBundle/Resources/install/pimcore/classes/CoreShopOrderBundle/CoreShopOrder.json index d40bbcb0b0..30ec36114a 100644 --- a/src/CoreShop/Bundle/CoreBundle/Resources/install/pimcore/classes/CoreShopOrderBundle/CoreShopOrder.json +++ b/src/CoreShop/Bundle/CoreBundle/Resources/install/pimcore/classes/CoreShopOrderBundle/CoreShopOrder.json @@ -228,6 +228,28 @@ "visibleGridView": false, "visibleSearch": false }, + { + "fieldtype": "datetime", + "queryColumnType": "bigint(20)", + "columnType": "bigint(20)", + "phpdocType": "\\Carbon\\Carbon", + "defaultValue": null, + "useCurrentDate": false, + "name": "lastActivatedAt", + "title": "Last Activated At", + "tooltip": "Timestamp the cart was last selected\/activated by its customer; used to restore the last-opened cart across sessions.", + "mandatory": false, + "noteditable": true, + "index": true, + "locked": false, + "style": "", + "permissions": null, + "datatype": "data", + "relationType": false, + "invisible": false, + "visibleGridView": false, + "visibleSearch": false + }, { "fieldtype": "language", "onlySystemLanguages": false, diff --git a/src/CoreShop/Bundle/OrderBundle/Pimcore/Repository/OrderRepository.php b/src/CoreShop/Bundle/OrderBundle/Pimcore/Repository/OrderRepository.php index b7bfffc21e..bb26d0a099 100644 --- a/src/CoreShop/Bundle/OrderBundle/Pimcore/Repository/OrderRepository.php +++ b/src/CoreShop/Bundle/OrderBundle/Pimcore/Repository/OrderRepository.php @@ -34,7 +34,7 @@ class OrderRepository extends PimcoreRepository implements OrderRepositoryInterf public function findLatestByStoreAndCustomer( StoreInterface $store, CustomerInterface $customer, - string $name = null + string $name = null, ): ?StorageListInterface { return $this->findLatestCartByStoreAndCustomer($store, $customer); } @@ -103,8 +103,9 @@ public function findLatestCartByStoreAndCustomer(StoreInterface $store, Customer { $list = $this->getList(); $list->setCondition('customer__id = ? AND store = ? AND saleState = ? ', [$customer->getId(), $store->getId(), OrderSaleStates::STATE_CART]); - $list->setOrderKey('creationDate'); - $list->setOrder('DESC'); + // Prefer the cart the customer last activated + $list->setOrderKey(['lastActivatedAt', 'creationDate']); + $list->setOrder(['DESC', 'DESC']); $list->load(); $objects = $list->getObjects(); diff --git a/src/CoreShop/Bundle/OrderBundle/Resources/config/services/cart.yml b/src/CoreShop/Bundle/OrderBundle/Resources/config/services/cart.yml index 9334d21219..3fd717d91b 100644 --- a/src/CoreShop/Bundle/OrderBundle/Resources/config/services/cart.yml +++ b/src/CoreShop/Bundle/OrderBundle/Resources/config/services/cart.yml @@ -59,7 +59,6 @@ services: tags: - { name: kernel.event_listener, event: pimcore.admin.object.list.beforeListLoad, method: checkObjectList } - CoreShop\Bundle\OrderBundle\Form\Type\CartListChoiceType: arguments: - '@CoreShop\Component\Order\Cart\CartResolver' @@ -70,3 +69,8 @@ services: arguments: - '@coreshop.repository.order' - '@CoreShop\Component\Order\Context\CartContext' + + CoreShop\Bundle\OrderBundle\StorageList\LastActivatedCartStorage: + decorates: coreshop.storage_list.storage.order + arguments: + $inner: '@.inner' diff --git a/src/CoreShop/Bundle/OrderBundle/Resources/install/pimcore/classes/CoreShopOrder.json b/src/CoreShop/Bundle/OrderBundle/Resources/install/pimcore/classes/CoreShopOrder.json index a6baee6c36..fbe484a686 100644 --- a/src/CoreShop/Bundle/OrderBundle/Resources/install/pimcore/classes/CoreShopOrder.json +++ b/src/CoreShop/Bundle/OrderBundle/Resources/install/pimcore/classes/CoreShopOrder.json @@ -228,6 +228,28 @@ "visibleGridView": false, "visibleSearch": false }, + { + "fieldtype": "datetime", + "queryColumnType": "bigint(20)", + "columnType": "bigint(20)", + "phpdocType": "\\Carbon\\Carbon", + "defaultValue": null, + "useCurrentDate": false, + "name": "lastActivatedAt", + "title": "Last Activated At", + "tooltip": "Timestamp the cart was last selected\/activated by its customer; used to restore the last-opened cart across sessions.", + "mandatory": false, + "noteditable": true, + "index": true, + "locked": false, + "style": "", + "permissions": null, + "datatype": "data", + "relationType": false, + "invisible": false, + "visibleGridView": false, + "visibleSearch": false + }, { "fieldtype": "language", "onlySystemLanguages": false, diff --git a/src/CoreShop/Bundle/OrderBundle/StorageList/LastActivatedCartStorage.php b/src/CoreShop/Bundle/OrderBundle/StorageList/LastActivatedCartStorage.php new file mode 100644 index 0000000000..af54bdd7ff --- /dev/null +++ b/src/CoreShop/Bundle/OrderBundle/StorageList/LastActivatedCartStorage.php @@ -0,0 +1,92 @@ +inner->hasForContext($context); + } + + public function getForContext(array $context): ?StorageListInterface + { + return $this->inner->getForContext($context); + } + + public function setForContext(array $context, StorageListInterface $storageList): void + { + $this->inner->setForContext($context, $storageList); + + $customer = $context['customer'] ?? null; + if (!$customer instanceof CustomerInterface) { + return; + } + + if (!$storageList instanceof ActivatableCartInterface || !$storageList instanceof OrderInterface) { + return; + } + + if ($storageList->getCustomer()?->getId() !== $customer->getId()) { + return; + } + + $storageList->setLastActivatedAt(Carbon::now()); + + $versioningEnabled = Version::isEnabled(); + Version::disable(); + + try { + $storageList->save(); + } finally { + if ($versioningEnabled) { + Version::enable(); + } + } + } + + public function removeForContext(array $context): void + { + $this->inner->removeForContext($context); + } +} diff --git a/src/CoreShop/Bundle/StorageListBundle/Core/EventListener/SessionStoreStorageListSubscriber.php b/src/CoreShop/Bundle/StorageListBundle/Core/EventListener/SessionStoreStorageListSubscriber.php index 59a68313e2..c5f729fb80 100644 --- a/src/CoreShop/Bundle/StorageListBundle/Core/EventListener/SessionStoreStorageListSubscriber.php +++ b/src/CoreShop/Bundle/StorageListBundle/Core/EventListener/SessionStoreStorageListSubscriber.php @@ -79,7 +79,7 @@ public function onKernelResponse(ResponseEvent $event): void return; } - if (0 !== $storageList->getId() && null !== $storageList->getStore()) { + if (0 !== $storageList->getId() && null !== $storageList->getId() && null !== $storageList->getStore()) { $this->storageListStorage->setForContext(['store' => $storageList->getStore()], $storageList); } } diff --git a/src/CoreShop/Component/Order/Model/ActivatableCartInterface.php b/src/CoreShop/Component/Order/Model/ActivatableCartInterface.php new file mode 100644 index 0000000000..a4baeaff0e --- /dev/null +++ b/src/CoreShop/Component/Order/Model/ActivatableCartInterface.php @@ -0,0 +1,34 @@ +getItems() ?: []); } + public function getLastActivatedAt(): ?Carbon + { + throw new ImplementedByPimcoreException(__CLASS__, __METHOD__); + } + + public function setLastActivatedAt(?Carbon $lastActivatedAt): static + { + throw new ImplementedByPimcoreException(__CLASS__, __METHOD__); + } + public function getTotalNet(): int { throw new ImplementedByPimcoreException(__CLASS__, __METHOD__);