shop.modules.cart¶
Attributes¶
Classes¶
Abstract Class for all viur-shop sub/nested modules. |
Functions¶
|
Delete carts from guest sessions to avoid orphaned carts. |
Module Contents¶
- shop.modules.cart.logger¶
- class shop.modules.cart.Cart(moduleName=None, modulePath=None, shop=None, *args, **kwargs)¶
Bases:
viur.shop.modules.abstract.ShopModuleAbstract,viur.core.prototypes.TreeAbstract Class for all viur-shop sub/nested modules.
The implementations should set moduleName as class variable, so the final module name for routing it not affected by the name of custom classes.
- Parameters:
moduleName (str)
modulePath (str)
shop (viur.shop.Shop)
- moduleName = 'cart'¶
- nodeSkelCls¶
- leafSkelCls¶
- adminInfo()¶
- Return type:
dict
- baseSkel(skelType, sub_skel=None, *args, **kwargs)¶
Extend default baseSkel() by sub_skel parameter
- Parameters:
skelType (viur.core.prototypes.tree.SkelType)
sub_skel (str | list[str] | None)
- Return type:
viur.core.skeleton.SkeletonInstance
- canView(skelType, skel)¶
- Parameters:
skelType (viur.core.prototypes.tree.SkelType)
skel (viur.core.skeleton.SkeletonInstance)
- Return type:
bool
- property current_session_cart_key: viur.core.db.Key | None¶
- Return type:
viur.core.db.Key | None
- get_current_session_cart_key(*, create_if_missing=False)¶
- Parameters:
create_if_missing (bool)
- Return type:
viur.core.db.Key | None
- property current_session_cart: viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartNodeSkel]¶
- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartNodeSkel]
- _ensure_current_session_cart()¶
- Return type:
viur.core.db.Key
- detach_session_cart()¶
Unlink the current cart from the session (and the user’s basket).
The cart entity itself is kept. Tolerates a session that has no
session_cart_key(anymore) instead of raising aKeyError.- Returns:
The key of the detached cart, or
Noneif none was set.- Return type:
viur.core.db.Key | None
- static _set_basket_txn(user_key, basket_key)¶
- Parameters:
user_key (viur.core.db.Key)
basket_key (viur.core.db.Key | None)
- Return type:
viur.core.skeleton.SkeletonInstance
- get_available_root_nodes(*args, **kwargs)¶
- Return type:
list[dict[viur.shop.types.t.Literal[name, key], str]]
- getAvailableRootNodes¶
- listRootNodes(*args, **kwargs)¶
Renders a list of all available repositories for the current user using the modules default renderer.
- Returns:
The rendered representation of the available root-nodes.
- Return type:
viur.shop.types.t.Any
- is_valid_node(node_key, root_node=False)¶
is this a valid node key for the user?
- Parameters:
node_key (viur.core.db.Key) – Key of node to check
root_node (bool) – Must this be a root node, or is any node okay?
- Return type:
bool
- get_children(parent_cart_key, **filters)¶
- Parameters:
parent_cart_key (viur.core.db.Key)
filters (viur.shop.types.t.Any)
- Return type:
viur.shop.types.t.Iterator[viur.core.skeleton.SkeletonInstance]
- get_children_from_cache(parent_cart_key)¶
- Parameters:
parent_cart_key (viur.core.db.Key)
- Return type:
list[viur.core.skeleton.SkeletonInstance]
- clear_children_cache()¶
- Return type:
None
- cart_get(cart_key, skel_type)¶
- Parameters:
cart_key (viur.core.db.Key)
skel_type (viur.core.prototypes.tree.SkelType)
- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartNodeSkel | shop.skeletons.cart.CartItemSkel] | None
- get_article(article_key, parent_cart_key, *, must_be_listed=True)¶
- Parameters:
article_key (viur.core.db.Key)
parent_cart_key (viur.core.db.Key)
must_be_listed (bool)
- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartItemSkel]
- add_or_update_article(article_key, parent_cart_key, *, quantity, quantity_mode, **kwargs)¶
- Parameters:
article_key (viur.core.db.Key)
parent_cart_key (viur.core.db.Key)
quantity (int)
quantity_mode (viur.shop.types.QuantityMode)
- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartItemSkel] | None
- copy_article_values(article_skel, skel)¶
Copy values from the article to the cart leaf
- Parameters:
article_skel (viur.shop.types.SkeletonInstance_T[shop.skeletons.article.ArticleAbstractSkel])
skel (viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartItemSkel])
- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartItemSkel]
- move_article(article_key, parent_cart_key, new_parent_cart_key)¶
- Parameters:
article_key (viur.core.db.Key)
parent_cart_key (viur.core.db.Key)
new_parent_cart_key (viur.core.db.Key)
- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartItemSkel] | None
- cart_add(*, parent_cart_key=None, cart_type=None, name=SENTINEL, customer_comment=SENTINEL, shipping_address_key=SENTINEL, shipping_key=SENTINEL, discount_key=SENTINEL, **kwargs)¶
- Parameters:
parent_cart_key (str | viur.core.db.Key)
cart_type (viur.shop.types.CartType)
name (str)
customer_comment (str)
shipping_address_key (str | viur.core.db.Key)
shipping_key (str | viur.core.db.Key)
discount_key (str | viur.core.db.Key)
- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartNodeSkel] | None
- cart_update(cart_key, *, parent_cart_key=SENTINEL, cart_type=None, name=SENTINEL, customer_comment=SENTINEL, shipping_address_key=SENTINEL, shipping_key=SENTINEL, discount_key=SENTINEL, **kwargs)¶
- Parameters:
cart_key (viur.core.db.Key)
parent_cart_key (str | viur.core.db.Key)
cart_type (viur.shop.types.CartType)
name (str)
customer_comment (str)
shipping_address_key (str | viur.core.db.Key)
shipping_key (str | viur.core.db.Key)
discount_key (str | viur.core.db.Key)
- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartNodeSkel] | None
- _cart_set_values(skel, *, parent_cart_key=SENTINEL, cart_type=None, name=SENTINEL, customer_comment=SENTINEL, shipping_address_key=SENTINEL, shipping_key=SENTINEL, discount_key=SENTINEL)¶
- Parameters:
skel (viur.core.skeleton.SkeletonInstance | shop.skeletons.cart.CartNodeSkel)
parent_cart_key (viur.core.db.Key)
cart_type (viur.shop.types.CartType)
name (str)
customer_comment (str)
shipping_address_key (str | viur.core.db.Key)
shipping_key (str | viur.core.db.Key)
discount_key (str | viur.core.db.Key)
- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartNodeSkel]
- cart_remove(cart_key)¶
Remove a cart node with its entire subtree.
The subtree is deleted bottom-up and before the node itself: leafs first, then sub-nodes, the given node last. This order keeps the tree consistent at any point in time – if the process crashes in between, no children can be left behind whose
parententrypoints to an already deleted node (orphaned entries). A repeated call simply continues the work (idempotent).Frozen carts belong to an order and cannot be removed.
This also checks upfront whether the node is locked by a
RelationalConsistency.PreventDeletionrelation (e.g. an order referencing an in-progress checkout cart that has not been frozen yet) and fails before touching any child – deleting the children first and finding out only atskel.delete()that the node itself is locked would leave the order pointing at an emptied-out cart.- Parameters:
cart_key (viur.core.db.Key) – Key of the cart node to remove.
- Raises:
errors.NotFound – If the cart node does not exist.
errors.Forbidden – If the cart node is frozen.
errors.Locked – If the cart node is referenced by a PreventDeletion relation (e.g. an order).
- Return type:
None
- _delete_children(parent_cart_key)¶
Delete all children of a cart node bottom-up and synchronously.
Leafs of parent_cart_key are deleted first, then each sub-node is processed recursively (its own children before the sub-node itself).
Deliberately does not call the inherited
deleteRecursive()of the Tree prototype: that method is@CallDeferredand only deletes the children, while the node itself is deleted synchronously by the caller right away (seeTree.delete()/cart_remove()). If that deferred task gets lost (queue purge, crash, or the task being pinned to an App Engine version that no longer exists), the node is gone but its children survive it forever – orphaned entries whose brokenparententrychain crashes price computations andupdate_relationstasks later. Cart trees are small (a handful of nodes/leafs), so there is no need to defer this work at all; running it synchronously, bottom-up and before the node itself is deleted removes the race entirely instead of just narrowing it.- Parameters:
parent_cart_key (viur.core.db.Key) – Key of the cart node whose subtree gets deleted.
- Return type:
None
- cart_clear(cart_key, *, keep_sub_carts=False)¶
- Parameters:
cart_key (viur.core.db.Key)
keep_sub_carts (bool)
- Return type:
None
- additional_add_or_update_article(skel, /, **kwargs)¶
Hook method called by
add_or_update_article()before the skeleton is saved.This method can be overridden in a subclass to implement additional API fields or make further modifications to the cart skeleton (skel). By default, it raises an exception if unexpected arguments (
kwargs) are provided and returns the unchanged skel object.- Parameters:
skel (viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartItemSkel]) – The current instance of the cart item skeleton.
kwargs – Additional optional arguments for extended implementations.
- Raises:
TooManyArgumentsException – If unexpected arguments are passed in
kwargs.- Returns:
The (potentially modified) cart item skeleton.
- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartItemSkel]
- additional_cart_add(skel, /, **kwargs)¶
Hook method called by
cart_add()before the skeleton is saved.This method can be overridden in a subclass to implement additional API fields or make further modifications to the cart skeleton (skel). By default, it raises an exception if unexpected arguments (
kwargs) are provided and returns the unchanged skel object.- Parameters:
skel (viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartNodeSkel]) – The current instance of the cart skeleton.
kwargs – Additional optional arguments for extended implementations.
- Raises:
TooManyArgumentsException – If unexpected arguments are passed in
kwargs.- Returns:
The (potentially modified) cart skeleton.
- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartNodeSkel]
- additional_cart_update(skel, /, **kwargs)¶
Hook method called by
cart_update()before the skeleton is saved.This method can be overridden in a subclass to implement additional API fields or make further modifications to the cart skeleton (skel). By default, it raises an exception if unexpected arguments (
kwargs) are provided and returns the unchanged skel object.- Parameters:
skel (viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartNodeSkel]) – The current instance of the cart skeleton.
kwargs – Additional optional arguments for extended implementations.
- Raises:
TooManyArgumentsException – If unexpected arguments are passed in
kwargs.- Returns:
The (potentially modified) cart skeleton.
- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartNodeSkel]
- freeze_cart(cart_key)¶
Freeze (lock) cart values and children items.
- Parameters:
cart_key (viur.core.db.Key) – Key of the (sub-)cart skeleton.
- Returns:
The frozen CartNode skeleton.
- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartNodeSkel]
- freeze_leaf(leaf_skel)¶
- Parameters:
leaf_skel (viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartItemSkel])
- get_discount_for_leaf(leaf_key_or_skel)¶
Collect the discounts of all cart nodes above the given leaf.
Walks the
parententrychain from the leaf up to the root node and collects thediscountrelation of every node on the way.The walk is tolerant against broken tree data: if a parent node does not exist anymore (orphaned entry) or the chain contains a cycle, the walk stops at the broken link with a warning and the discounts collected so far are returned. This keeps computed bones (e.g. the price) usable on orphaned entries instead of raising and thereby crashing deferred tasks (like
update_relations) forever.- Parameters:
leaf_key_or_skel (viur.core.db.Key | viur.core.skeleton.SkeletonInstance) – Key or skeleton of the cart leaf to start from.
- Returns:
The discount ref-skels found on the ancestor nodes.
- Return type:
list[viur.core.skeleton.SkeletonInstance]
- add_new_parent(leaf_skel, **kwargs)¶
- get_cached_cart_skel(key)¶
Read a cart node skeleton with request-local caching.
- Parameters:
key (viur.core.db.Key) – Key of the cart node to read.
- Returns:
The cached or freshly read node skeleton or
Noneif the node does not exist (anymore). Missing nodes are not cached, so a later call re-checks the datastore.- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartNodeSkel] | None
- get_closest_node(start, condition=lambda skel: ...)¶
Walk the
parententrychain upwards and return the first ancestor node that satisfies condition.The walk stops and returns
Nonewhenthe root node is reached without a match,
the current entry has no
parententry(detached entry),a parent node does not exist anymore (orphaned entry) or
the
parententrychain contains a cycle.
The latter cases are broken tree states which must not crash callers like the price computation running inside deferred tasks.
- Parameters:
start (viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartNodeSkel | shop.skeletons.cart.CartItemSkel]) – Leaf or node skeleton to start from (itself excluded).
condition (viur.shop.types.t.Callable[[viur.core.skeleton.SkeletonInstance], bool]) – Predicate evaluated for each ancestor node.
- Returns:
The closest matching ancestor node or
None.- Return type:
viur.shop.types.SkeletonInstance_T[shop.skeletons.cart.CartNodeSkel] | None
- shop.modules.cart.delete_guest_cart(session)¶
Delete carts from guest sessions to avoid orphaned carts.
Runs as
Session.on_delete()hook. Any failure is logged and swallowed: this hook must never prevent the session deletion itself. Carts that are referenced by an order, already gone or frozen are left alone.- Parameters:
session (viur.core.db.Entity)
- Return type:
None