shop ==== .. py:module:: shop .. autoapi-nested-parse:: ViUR-Shop – A modular e-commerce extension for the ViUR framework. This package provides core components and modules for integrating e-commerce functionality into ViUR-based projects. It includes handling of shopping carts, orders, payment and shipping providers, and is designed to be highly extensible and customizable. Components included: - `shop`: The main module class that connects routing and core logic. - `cart`: Logic and utilities for managing shopping carts. - `order`: Models and logic for order processing. - `providers`: Registration system for pluggable payment and shipping providers. - `utils`: Shared utilities used throughout the shop package. .. note:: This package is intended for use with the ViUR framework. Only a single shop instance per project is currently supported. Submodules ---------- .. toctree:: :maxdepth: 1 /viur/shop/globals/index /viur/shop/modules/index /viur/shop/payment_providers/index /viur/shop/services/index /viur/shop/shop/index /viur/shop/skeletons/index /viur/shop/types/index /viur/shop/types_global/index /viur/shop/version/index Attributes ---------- .. autoapisummary:: shop.SHOP_LOGGER shop.SHOP_INSTANCE shop.SHOP_INSTANCE_VI shop.SENTINEL shop.DEBUG_DISCOUNTS shop.MAX_FETCH_LIMIT shop.SkeletonCls_co Exceptions ---------- .. autoapisummary:: shop.ConfigurationError shop.DispatchError shop.IllegalOperationError shop.InvalidStateError shop.ViURShopException Classes ------- .. autoapisummary:: shop.GlobalVar shop.Sentinel shop.GlobalVar shop.Sentinel shop.PaymentProviderAbstract shop.AmazonPay shop.Invoice shop.PrePayment shop.Prepayment shop.AddressSkel shop.ArticleAbstractSkel shop.CartNodeSkel shop.CartItemSkel shop.DiscountSkel shop.DiscountConditionSkel shop.OrderSkel shop.ShippingSkel shop.ShippingConfigSkel shop.ShippingPreconditionRelSkel shop.VatSkel shop.VatRateSkel shop.SkeletonInstance_T shop.ClientError shop.Supplier shop.DiscountConditionScope shop.ConditionValidator shop.DiscountValidator shop.AddressType shop.ApplicationDomain shop.ArticleAvailability shop.CartType shop.CodeType shop.ConditionOperator shop.CustomerGroup shop.CustomerType shop.DiscountType shop.DiscountValidationContext shop.OrderState shop.QuantityMode shop.Salutation shop.ShippingStatus shop.VatRateCategory shop.Error shop.ErrorResponse shop.InvalidArgumentException shop.InvalidKeyException shop.MissingArgumentsException shop.TooManyArgumentsException shop.ViURShopHttpException shop.Price shop.ExtendedCustomJsonEncoder shop.JsonResponse shop.OrderViewResult shop.PaymentProviderResult shop.StatusError shop.PaymentTransaction shop.PaymentTransactionSpecific Functions --------- .. autoapisummary:: shop.error_handler Package Contents ---------------- .. py:class:: GlobalVar(name, default = _SENTINEL) Bases: :py:obj:`Generic`\ [\ :py:obj:`_T`\ ] A generic container for storing a global-like variable with optional default fallback. This class allows safe setting and retrieval of values, with optional fallbacks and error handling if no value is set. Initialize a GlobalVar instance. :param name: The name of the global variable. :param default: Optional default value. If not provided, accessing the value via :meth:`get` will raise a LookupError if unset. .. py:attribute:: name .. py:attribute:: value .. py:method:: set(value) Set the value of the variable. :param value: The value to assign to the global variable. .. py:method:: get(default = _SENTINEL) Retrieve the stored value. If no value was explicitly set, returns the provided fallback, or raises a LookupError if neither a value nor fallback exists. :param default: Optional fallback value to return if no value is set. :return: The stored value or the provided default. :raises LookupError: If no value is set and no default is provided. .. py:method:: __repr__() Return a string representation of the GlobalVar instance. :return: A string representation showing the name and value. .. py:class:: Sentinel A unique sentinel class used as a special marker value. An instance of this class can be used to indicate, for example, a unique default value or a special state that is distinct from normal values. Attributes ---------- - The representation is ```` for improved readability during debugging. - The boolean evaluation is ``False``, so the sentinel behaves as falsey in conditions like ``if sentinel:``. .. py:method:: __repr__() .. py:method:: __bool__() .. py:class:: GlobalVar(name, default = _SENTINEL) Bases: :py:obj:`Generic`\ [\ :py:obj:`_T`\ ] A generic container for storing a global-like variable with optional default fallback. This class allows safe setting and retrieval of values, with optional fallbacks and error handling if no value is set. Initialize a GlobalVar instance. :param name: The name of the global variable. :param default: Optional default value. If not provided, accessing the value via :meth:`get` will raise a LookupError if unset. .. py:attribute:: name .. py:attribute:: value .. py:method:: set(value) Set the value of the variable. :param value: The value to assign to the global variable. .. py:method:: get(default = _SENTINEL) Retrieve the stored value. If no value was explicitly set, returns the provided fallback, or raises a LookupError if neither a value nor fallback exists. :param default: Optional fallback value to return if no value is set. :return: The stored value or the provided default. :raises LookupError: If no value is set and no default is provided. .. py:method:: __repr__() Return a string representation of the GlobalVar instance. :return: A string representation showing the name and value. .. py:class:: Sentinel A unique sentinel class used as a special marker value. An instance of this class can be used to indicate, for example, a unique default value or a special state that is distinct from normal values. Attributes ---------- - The representation is ```` for improved readability during debugging. - The boolean evaluation is ``False``, so the sentinel behaves as falsey in conditions like ``if sentinel:``. .. py:method:: __repr__() .. py:method:: __bool__() .. py:data:: SHOP_LOGGER :type: logging.Logger viur-shop base logger instance .. py:data:: SHOP_INSTANCE :type: shop.types_global.GlobalVar[shop.shop.Shop] The shop instance bound to the default html renderer .. py:data:: SHOP_INSTANCE_VI :type: shop.types_global.GlobalVar[shop.shop.Shop] The shop instance bound to the vi renderer .. py:data:: SENTINEL :type: Final[shop.types_global.Sentinel] Unique sentinel object used to detect if a value was explicitly set or not .. py:data:: DEBUG_DISCOUNTS :type: shop.types_global.GlobalVar[bool] Print detailed discount evaluation for debugging .. py:data:: MAX_FETCH_LIMIT :type: int :value: 100 Limit used if all entries should be fetched, but it needs to be limited because it's ViUR. .. py:class:: PaymentProviderAbstract(*, image_path = None, is_available = None) Bases: :py:obj:`viur.core.prototypes.instanced_module.InstancedModule`, :py:obj:`viur.core.Module`, :py:obj:`abc.ABC` Abstract base class for all payment providers in the ViUR Shop. Provides a standardized interface for implementing different payment methods, including methods for checkout, charging, and handling payment states. Subclasses must implement the required methods to integrate specific payment providers. .. py:attribute:: shop :type: shop.shop.Shop :value: None Reference to the main :class:`Shop` instance. .. py:attribute:: image_path :value: None .. py:property:: name :type: str :abstractmethod: Define the internal name of the payment provider .. py:property:: title :type: viur.core.translate Define the external title of the payment provider .. py:property:: description :type: viur.core.translate Define the description of the payment provider .. py:method:: is_available(order_skel) Decide whether the payment provider is available. .. py:method:: can_checkout(order_skel) Check if a checkout process can be started An empty list means not error, a list with errors rejects the checkout start. .. py:method:: checkout(order_skel) :abstractmethod: .. py:method:: get_checkout_start_data(order_skel) .. py:method:: can_order(order_skel) .. py:method:: charge() :abstractmethod: .. py:method:: check_payment_state(order_skel) :abstractmethod: Check the payment state from the PaymentProvider API/service Access :attr:`OrderSkel.is_paid` to get the payment state of an order. .. py:method:: check_payment_deferred(order_key) Check the status for a payment deferred .. py:method:: return_handler() :abstractmethod: Frontend Endpoint where the might be redirected to by the payment provider during the payment flow .. py:method:: webhook() :abstractmethod: API Endpoint (Webhook) to listen for events from payment provider .. py:method:: get_debug_information() :abstractmethod: Provide information about the payment of an order. Only for debugging purposes. It's not an API endpoint. .. py:method:: _append_payment_to_order_skel(order_skel, payment = None) Append payment data to an order Append payment_provider name and creationdate by default. Write safely in a transaction. .. py:method:: serialize_for_api(order_skel) Serialize this Payment Provider for the API Used by :meth:`Order.get_payment_providers` and :meth:`Order.payment_providers_list` Can be subclasses to expose more information via API. .. py:method:: model_to_dict(obj) :classmethod: Convert any nested model to a JSON-compatible representation .. py:class:: AmazonPay(*, mws_access_key, mws_secret_key, merchant_id, client_id, client_secret, region = 'de', currency_code = 'EUR', sandbox = False, language = 'en', **kwargs) Bases: :py:obj:`shop.payment_providers.PaymentProviderAbstract` Amazon Pay integration for the ViUR Shop. Handles the checkout process using Amazon Pay, including authorization and payment capture. Requires Amazon MWS credentials and configuration parameters. :param mws_access_key: Amazon MWS access key. :param mws_secret_key: Amazon MWS secret key. :param merchant_id: Amazon merchant ID. :param client_id: Amazon client ID. :param client_secret: Amazon client secret. :param region: Region code (default: 'de'). :param currency_code: Currency code (default: 'EUR'). :param sandbox: Use sandbox environment (default: False). :param language: Language code (default: 'en'). .. py:attribute:: name :type: Final[str] :value: 'amazonpay' Define the internal name of the payment provider .. py:attribute:: mws_access_key .. py:attribute:: mws_secret_key .. py:attribute:: merchant_id .. py:attribute:: client_id .. py:attribute:: client_secret .. py:attribute:: sandbox :value: False .. py:attribute:: language :value: 'en' .. py:method:: checkout(order_skel) .. py:method:: get_checkout_start_data(order_skel) .. py:method:: charge() .. py:method:: check_payment_state(order_skel) Check the payment state from the PaymentProvider API/service Access :attr:`OrderSkel.is_paid` to get the payment state of an order. .. py:method:: return_handler() Frontend Endpoint where the might be redirected to by the payment provider during the payment flow .. py:method:: webhook() API Endpoint (Webhook) to listen for events from payment provider .. py:method:: get_debug_information() Provide information about the payment of an order. Only for debugging purposes. It's not an API endpoint. .. py:class:: Invoice(*, image_path = None, is_available = None) Bases: :py:obj:`shop.payment_providers.PaymentProviderAbstract` Invoice payment method for the ViUR Shop. Allows customers to place orders with the agreement to pay later via invoice. The order can be marked as ready to ship (RTS) immediately but is not considered paid. Note: Payment processing (the customer pays this order in the next x days) and verification are handled externally and not within this module. .. py:attribute:: name :type: Final[str] :value: 'invoice' Define the internal name of the payment provider .. py:method:: checkout(order_skel) .. py:method:: charge() .. py:method:: check_payment_state(order_skel) Check the payment state from the PaymentProvider API/service Access :attr:`OrderSkel.is_paid` to get the payment state of an order. .. py:method:: return_handler() Frontend Endpoint where the might be redirected to by the payment provider during the payment flow .. py:method:: webhook() API Endpoint (Webhook) to listen for events from payment provider .. py:method:: get_debug_information() Provide information about the payment of an order. Only for debugging purposes. It's not an API endpoint. .. py:class:: PrePayment(*, image_path = None, is_available = None) Bases: :py:obj:`Prepayment` Prepayment method for the ViUR Shop. Allows customers to place orders with the agreement to pay in advance. The order is marked as ready to ship (RTS) once payment is received. The customer pays this order in the next x days, shipping will wait. Note: Payment receipt verification (The customer pays this order in the next x days, shipping will wait) is handled externally and not within this module. .. py:class:: Prepayment(*, image_path = None, is_available = None) Bases: :py:obj:`shop.payment_providers.PaymentProviderAbstract` Prepayment method for the ViUR Shop. Allows customers to place orders with the agreement to pay in advance. The order is marked as ready to ship (RTS) once payment is received. The customer pays this order in the next x days, shipping will wait. Note: Payment receipt verification (The customer pays this order in the next x days, shipping will wait) is handled externally and not within this module. .. py:attribute:: name :type: Final[str] :value: 'prepayment' Define the internal name of the payment provider .. py:method:: checkout(order_skel) .. py:method:: charge() .. py:method:: check_payment_state(order_skel) Check the payment state from the PaymentProvider API/service Access :attr:`OrderSkel.is_paid` to get the payment state of an order. .. py:method:: return_handler() Frontend Endpoint where the might be redirected to by the payment provider during the payment flow .. py:method:: webhook() API Endpoint (Webhook) to listen for events from payment provider .. py:method:: get_debug_information() Provide information about the payment of an order. Only for debugging purposes. It's not an API endpoint. .. py:class:: AddressSkel Bases: :py:obj:`viur.core.skeleton.Skeleton` .. py:attribute:: kindName :value: '{{viur_shop_modulename}}_address' .. py:attribute:: name .. py:attribute:: customer_type .. py:attribute:: salutation .. py:attribute:: company_name .. py:attribute:: firstname .. py:attribute:: lastname .. py:attribute:: street_name .. py:attribute:: street_number .. py:attribute:: address_addition .. py:attribute:: zip_code .. py:attribute:: city .. py:attribute:: country .. py:attribute:: customer .. py:attribute:: email Kopieren von User oder Eingabe von Nutzer bei Gast .. py:attribute:: phone .. py:attribute:: birthdate .. py:attribute:: is_default .. py:attribute:: address_type .. py:attribute:: cloned_from .. py:class:: ArticleAbstractSkel Bases: :py:obj:`viur.core.skeleton.BaseSkeleton` Abstract skeleton class which the project has to implement for the article skeletons All members in this abstract skeleton has to be prefixed with `shop_` to avoid name collisions with bones in the project skeleton .. py:property:: shop_name :type: StringBone | TextBone :abstractmethod: Name of the article in the shop .. py:property:: shop_description :type: TextBone :abstractmethod: .. py:property:: shop_price_retail :type: NumericBone :abstractmethod: .. py:property:: shop_price_recommended :type: NumericBone :abstractmethod: .. py:property:: shop_availability :type: SelectBone :abstractmethod: .. py:property:: shop_listed :type: BooleanBone :abstractmethod: .. py:property:: shop_image :type: FileBone :abstractmethod: References a FileSkel .. py:property:: shop_art_no_or_gtin :type: StringBone :abstractmethod: .. py:attribute:: shop_vat_rate_category .. py:property:: shop_shipping_config :type: RelationalBone :abstractmethod: References a ShippingConfigSkel .. py:property:: shop_is_weee :type: BooleanBone :abstractmethod: Waste Electrical and Electronic Equipment Directive (WEEE Directive) .. py:property:: shop_is_low_price :type: BooleanBone :abstractmethod: shop_price_retail != shop_price_recommended .. py:attribute:: shop_view_url URL to the article page (view) .. py:property:: shop_price_ :type: viur.shop.types.Price .. py:attribute:: shop_price .. py:attribute:: shop_shipping Calculated, cheapest shipping for this article .. py:method:: setSystemInitialized() :classmethod: .. py:class:: CartNodeSkel Bases: :py:obj:`viur.core.prototypes.tree.TreeSkel` .. py:attribute:: kindName :value: '{{viur_shop_modulename}}_cart_node' .. py:attribute:: subSkels .. py:attribute:: is_root_node .. py:attribute:: total .. py:attribute:: total_raw .. py:attribute:: total_discount_price .. py:attribute:: vat .. py:attribute:: total_quantity .. py:attribute:: shipping_address .. py:attribute:: customer_comment .. py:attribute:: name .. py:attribute:: cart_type .. py:attribute:: shipping .. py:attribute:: shipping_status Versand bei Warenkorb der einer Bestellung zugehört .. py:attribute:: discount .. py:attribute:: project_data .. py:attribute:: is_frozen .. py:attribute:: frozen_values .. py:method:: refresh_shipping_address(skel) :classmethod: Shorthand to refresh the shipping_address of an CartNodeSkel Due to race-condition and timing issues, the dest values are not always set correctly. This refresh fixes this. .. py:method:: read(skel, *args, **kwargs) :classmethod: .. py:class:: CartItemSkel Bases: :py:obj:`viur.core.prototypes.tree.TreeSkel` .. py:attribute:: kindName :value: '{{viur_shop_modulename}}_cart_leaf' .. py:attribute:: article .. py:attribute:: quantity .. py:attribute:: project_data .. py:attribute:: shop_name .. py:attribute:: shop_description .. py:attribute:: shop_price_retail .. py:attribute:: shop_price_recommended .. py:attribute:: shop_availability .. py:attribute:: shop_listed .. py:attribute:: shop_image .. py:attribute:: shop_art_no_or_gtin .. py:attribute:: shop_vat_rate_category .. py:attribute:: shop_shipping_config .. py:attribute:: shop_is_weee .. py:attribute:: shop_is_low_price .. py:property:: article_skel :type: viur.core.skeleton.SkeletonInstance .. py:property:: article_skel_full :type: viur.shop.types.SkeletonInstance_T[shop.skeletons.article.ArticleAbstractSkel] .. py:method:: get_article_cache() :classmethod: .. py:property:: parent_skel :type: viur.core.skeleton.SkeletonInstance .. py:property:: price_ :type: viur.shop.types.Price .. py:attribute:: price .. py:attribute:: shipping .. py:attribute:: is_frozen .. py:attribute:: frozen_values .. py:class:: DiscountSkel Bases: :py:obj:`viur.core.skeleton.Skeleton` .. py:attribute:: kindName :value: '{{viur_shop_modulename}}_discount' .. py:attribute:: interBoneValidations .. py:attribute:: name .. py:attribute:: description .. py:attribute:: discount_type .. py:attribute:: absolute .. py:attribute:: percentage .. py:attribute:: free_article .. py:attribute:: condition .. py:attribute:: condition_operator .. py:attribute:: activate_automatically .. py:class:: DiscountConditionSkel Bases: :py:obj:`viur.core.skeleton.Skeleton` .. py:attribute:: kindName :value: '{{viur_shop_modulename}}_discount_condition' .. py:attribute:: interBoneValidations .. py:attribute:: name .. py:attribute:: description .. py:attribute:: code_type .. py:attribute:: application_domain Anwendungsbereich .. py:attribute:: quantity_volume .. py:attribute:: quantity_used Wie oft wurde der code Bereits verwendet? .. py:attribute:: individual_codes_amount .. py:attribute:: scope_code .. py:attribute:: individual_codes_prefix .. py:attribute:: scope_minimum_order_value .. py:attribute:: scope_date_start .. py:attribute:: scope_date_end .. py:attribute:: scope_language .. py:attribute:: scope_country .. py:attribute:: scope_minimum_quantity Minimale Anzahl für Staffelrabatte (in Kombination mit application_domain) für Artikel oder kompletten Warenkorb .. py:attribute:: scope_customer_group .. py:attribute:: scope_combinable_other_discount Kombinierbar mit anderen Rabatten .. py:attribute:: scope_combinable_low_price Kombinierbar prüfen mit shop_is_low_price .. py:attribute:: scope_article .. py:attribute:: is_subcode .. py:attribute:: parent_code .. py:class:: OrderSkel Bases: :py:obj:`viur.core.skeleton.Skeleton` .. py:attribute:: kindName :value: '{{viur_shop_modulename}}_order' .. py:attribute:: billing_address .. py:attribute:: customer .. py:attribute:: cart .. py:attribute:: total Kopie der total vom gesamten Warenkorb .. py:attribute:: order_uid Bestellnummer .. py:attribute:: payment_provider .. py:attribute:: is_ordered .. py:attribute:: is_paid .. py:attribute:: is_rts .. py:attribute:: is_checkout_in_progress .. py:attribute:: state .. py:attribute:: email .. deprecated:: 0.1.0.dev36 Use :py:attr:`shop.skeleton.AddressSkel.email` instead. .. py:attribute:: phone .. deprecated:: 0.1.0.dev36 Use :py:attr:`shop.skeleton.AddressSkel.phone` instead. .. py:attribute:: project_data Zusätzliche Daten vom Projekt für eine Bestellung. Ggf. überlegen ob einzelne Bones durch Skeleton Modifizierung besser sind. .. py:attribute:: payment .. py:method:: refresh_cart(skel) :classmethod: Shorthand to refresh the cart of an OrderSkel Due to race-condition and timing issues, the dest values are not always set correctly. This refresh fixes this. .. py:method:: refresh_billing_address(skel) :classmethod: Shorthand to refresh the billing_address of an OrderSkel Due to race-condition and timing issues, the dest values are not always set correctly. This refresh fixes this. .. py:method:: read(skel, *args, **kwargs) :classmethod: .. py:class:: ShippingSkel Bases: :py:obj:`viur.core.skeleton.Skeleton` .. py:attribute:: kindName :value: '{{viur_shop_modulename}}_shipping' .. py:attribute:: name DHL Standard, DHL Express, DPD-Shop, ... .. py:attribute:: description "Sie brauchen ein DHL-Kundenkonto" "Du bist auf einer Insel" ... .. py:attribute:: shipping_cost .. py:attribute:: art_no .. py:attribute:: supplier .. py:attribute:: delivery_time_min Tag(e) .. py:attribute:: delivery_time_max Tag(e) .. py:attribute:: delivery_time_range .. py:class:: ShippingConfigSkel Bases: :py:obj:`viur.core.skeleton.Skeleton` .. py:attribute:: kindName :value: '{{viur_shop_modulename}}_shipping_config' .. py:attribute:: name .. py:attribute:: shipping .. py:method:: read(skel, *args, **kwargs) :classmethod: .. py:class:: ShippingPreconditionRelSkel Bases: :py:obj:`viur.core.skeleton.RelSkel` .. py:attribute:: minimum_order_value .. py:attribute:: country .. py:attribute:: zip_code .. py:class:: VatSkel Bases: :py:obj:`viur.core.skeleton.RelSkel` .. py:attribute:: category .. py:attribute:: percentage Vat rate (percentage) .. py:class:: VatRateSkel Bases: :py:obj:`viur.core.skeleton.Skeleton` .. py:attribute:: kindName :value: '{{viur_shop_modulename}}_vat_rate' .. py:attribute:: name .. py:attribute:: country .. py:attribute:: configuration .. py:data:: SkeletonCls_co .. py:class:: SkeletonInstance_T Bases: :py:obj:`viur.core.skeleton.SkeletonInstance`, :py:obj:`Generic`\ [\ :py:obj:`SkeletonCls_co`\ ] This types trys to say to which SkeletonCls a SkeletonInstance belongs or in other words, it does what the viur-core failed to do. .. py:class:: ClientError Class to store information about client error .. py:attribute:: message :type: str .. py:attribute:: causes_failure :type: bool :value: True .. py:method:: has_failing_error(errors) :classmethod: Check if a list of ``ClientError``s has as error that cause failing. .. py:class:: Supplier Supplier definition .. py:attribute:: key :type: str Internal identifier .. py:attribute:: name :type: str | viur.core.i18n.translate Public name .. py:class:: DiscountConditionScope(*, cart_skel = SENTINEL, article_skel = SENTINEL, discount_skel = SENTINEL, code = SENTINEL, condition_skel, context) Bases: :py:obj:`abc.ABC` Validator that validates a specific discount condition scope. The scope is usually defined by one bone in the :class:`DiscountConditionSkel`. A scope is fulfilled if the precondition and the main condition are fulfilled. It is not fulfilled if the precondition is fulfilled but the main condition is not. If the precondition is not fulfilled, the scope is ignored (regardless of the main condition). .. py:attribute:: cart_skel .. py:attribute:: article_skel .. py:attribute:: discount_skel .. py:attribute:: condition_skel .. py:attribute:: code .. py:attribute:: context .. py:method:: precondition() Validates the precondition for this scope. Usually this means the related bone in the :class:`DiscountConditionSkel` has a value defined. Unfulfilled preconditions make :class:``DiscountConditionScope`` no longer necessary. .. py:attribute:: allowed_contexts :type: Final[list[DiscountValidationContext]] contexts in which this scope should be checked .. py:method:: __call__() :abstractmethod: The (main) condition of this scope. This check could be, for example, that: - A bone of an ``ArticleAbstractSkel`` has the value from the value range of a scope bone in the :class:`DiscountConditionSkel`. - The context (e.g. language) matches the value range of a scope bone. .. py:property:: is_applicable :type: bool Cached and evaluated precondition .. py:property:: is_fulfilled :type: bool Cached and evaluated condition .. py:method:: __repr__() Represent the scope as a string .. py:class:: ConditionValidator Validator that validates a specific discount condition (with many scopes). It validates a complete :class:`DiscountConditionSkel`. .. py:attribute:: scopes :type: list[Type[DiscountConditionScope]] :value: [] .. py:attribute:: scope_instances :type: list[DiscountConditionScope] :value: [] .. py:attribute:: cart_skel :value: None .. py:attribute:: article_skel :value: None .. py:attribute:: discount_skel :value: None .. py:attribute:: condition_skel :value: None .. py:attribute:: context :value: None .. py:method:: __call__(*, cart_skel = SENTINEL, article_skel = SENTINEL, discount_skel = SENTINEL, code = SENTINEL, condition_skel, context) .. py:property:: applicable_scopes :type: list[DiscountConditionScope] .. py:property:: is_fulfilled :type: bool .. py:method:: __repr__() .. py:method:: register(scope) :classmethod: .. py:class:: DiscountValidator Validator that validates a specific discount (with many conditions). It validates a complete :class:`DiscountSkel`. .. py:attribute:: condition_validator_instances :type: list[ConditionValidator] :value: [] .. py:attribute:: cart_skel :value: None .. py:attribute:: article_skel :value: None .. py:attribute:: discount_skel :value: None .. py:attribute:: condition_skels :value: [] .. py:attribute:: context :value: None .. py:method:: __call__(*, cart_skel = SENTINEL, article_skel = SENTINEL, discount_skel = SENTINEL, code = SENTINEL, context = SENTINEL) .. py:property:: is_fulfilled :type: bool .. py:property:: application_domain :type: ApplicationDomain .. py:method:: __repr__() .. py:class:: AddressType(*args, **kwds) Bases: :py:obj:`enum.Enum` Specifies whether an address is used for billing or shipping. .. py:attribute:: BILLING :value: 'billing' .. py:attribute:: SHIPPING :value: 'shipping' .. py:class:: ApplicationDomain(*args, **kwds) Bases: :py:obj:`enum.Enum` Specifies where a discount or rule applies — in basket, article, or globally. .. py:attribute:: BASKET :value: 'basket' .. py:attribute:: ARTICLE :value: 'article' .. py:attribute:: ALL :value: 'all' not care / both(all) / None .. py:class:: ArticleAvailability(*args, **kwds) Bases: :py:obj:`enum.Enum` Defines the stock availability status of an article. .. py:attribute:: IN_STOCK :value: 'instock' .. py:attribute:: OUT_OF_STOCK :value: 'outofstock' .. py:attribute:: LIMITED :value: 'limited' .. py:attribute:: DISCONTINUED :value: 'discontinued' .. py:attribute:: PREORDER :value: 'preorder' .. py:class:: CartType(*args, **kwds) Bases: :py:obj:`enum.Enum` Distinguishes between different cart types, such as wishlist and active basket. .. py:attribute:: WISHLIST :value: 'wishlist' .. py:attribute:: BASKET :value: 'basket' .. py:class:: CodeType(*args, **kwds) Bases: :py:obj:`enum.Enum` Defines how discount or voucher codes are applied and managed. .. py:attribute:: NONE :value: 'none' .. py:attribute:: INDIVIDUAL :value: 'individual' .. py:attribute:: UNIVERSAL :value: 'universal' .. py:class:: ConditionOperator(*args, **kwds) Bases: :py:obj:`enum.Enum` Defines whether all or at least one discount condition must be satisfied. .. py:attribute:: ONE_OF :value: 'one_of' One condition must be satisfied .. py:attribute:: ALL :value: 'all' All conditions must be satisfied .. py:class:: CustomerGroup(*args, **kwds) Bases: :py:obj:`enum.Enum` Defines customer segmentation for applying conditions like first-time buyer. .. py:attribute:: ALL :value: 'all' alle Kunden .. py:attribute:: FIRST_ORDER :value: 'first_order' Erstbestellung .. py:attribute:: FOLLOW_UP_ORDER :value: 'follow_up_order' Folgebestellung "Stammkunden" (mind. eine Bestellung) .. py:class:: CustomerType(*args, **kwds) Bases: :py:obj:`enum.Enum` Specifies whether a customer is a private individual or a business. .. py:attribute:: PRIVATE :value: 'private' .. py:attribute:: BUSINESS :value: 'business' .. py:class:: DiscountType(*args, **kwds) Bases: :py:obj:`enum.Enum` Specifies the kind of discount applied, e.g., percentage or free shipping. .. py:attribute:: PERCENTAGE :value: 'percentage' percentage .. py:attribute:: ABSOLUTE :value: 'absolute' absolute .. py:attribute:: FREE_ARTICLE :value: 'free_article' free-article (and cart easter egg) .. py:attribute:: FREE_SHIPPING :value: 'free_shipping' free-shipping .. py:class:: DiscountValidationContext Bases: :py:obj:`enum.IntEnum` Describes the evaluation context for checking discount conditions. Context in which a :class:`DiscountConditionScope` can be checked. Initialize self. See help(type(self)) for accurate signature. .. py:attribute:: NORMAL Normal context, in real time e.g. for an article .. py:attribute:: AUTOMATICALLY_PREVALIDATE Pre-Validate automatically discount for caching .. py:attribute:: AUTOMATICALLY_LIVE Validate automatically discount in real time .. py:class:: OrderState(*args, **kwds) Bases: :py:obj:`enum.Enum` Represents the current processing state of an order. .. py:attribute:: ORDERED :value: 'ordered' Customer completed this order and clicked on buy .. py:attribute:: CHECKOUT_IN_PROGRESS :value: 'checkout_in_progress' Customer started the checkout .. py:attribute:: PAID :value: 'paid' Payment completed .. py:attribute:: RTS :value: 'rts' Ready To Send (but must not be paid) .. py:class:: QuantityMode(*args, **kwds) Bases: :py:obj:`enum.Enum` Specifies how item quantities in the cart should be modified. .. py:attribute:: REPLACE :value: 'replace' Use the provided quantity as new value .. py:attribute:: INCREASE :value: 'increase' Adds the provided quantity to the current value .. py:attribute:: DECREASE :value: 'decrease' Subtract the provided quantity from the current value .. py:class:: Salutation(*args, **kwds) Bases: :py:obj:`enum.Enum` Represents the salutation used when addressing a customer. .. py:attribute:: FEMALE :value: 'female' .. py:attribute:: MALE :value: 'male' .. py:attribute:: OTHER :value: 'other' .. py:class:: ShippingStatus(*args, **kwds) Bases: :py:obj:`enum.Enum` Defines how a shipping method was selected (e.g., by user or cheapest option). .. py:attribute:: USER :value: 'user' Shipping selected by a user .. py:attribute:: CHEAPEST :value: 'cheapest' Cheapest shipping selected .. py:attribute:: MOST_EXPENSIVE :value: 'most_expensive' Most expensive shipping selected .. py:class:: VatRateCategory Bases: :py:obj:`enum.StrEnum` Categorizes different VAT rate categories in the EU applied to goods and services. Initialize self. See help(type(self)) for accurate signature. .. py:attribute:: STANDARD :value: 'standard' Applies to most goods and services, with a minimum rate of 15% mandated by the EU. .. py:attribute:: REDUCED :value: 'reduced' Applies to specific goods and services (e.g., food, books), typically at rates above 5%. .. py:attribute:: SUPER_REDUCED :value: 'super_reduced' Special cases with rates below 5%, applied to essential goods or services in some countries. .. py:attribute:: ZERO :value: 'zero' Applies to specific goods and services with no VAT charged, such as exports or essential items. .. py:class:: Error(*, code, message, customer_message, exception, details = None) Represents a single error .. py:attribute:: code .. py:attribute:: message .. py:attribute:: customer_message .. py:attribute:: exception .. py:attribute:: details :value: None .. py:method:: as_json() .. py:class:: ErrorResponse(*, errors = (), status_code = None) API Error Response from errors. Represents an amount of one or multiple error(s), occurred during a request. .. py:attribute:: status_code :value: 500 .. py:attribute:: errors :value: [] .. py:method:: as_json() .. py:method:: __str__() .. py:method:: from_exception(*, exception) :classmethod: .. py:function:: error_handler(func = None) API Error Handler Decorator that handles errors and returns the method/function response otherwise. .. py:exception:: ConfigurationError Bases: :py:obj:`ViURShopException` Exception raised when a configuration is invalid or incomplete. This may occur if required settings are missing, have incorrect values, or cause conflicts that prevent proper operation. Settings may also be required in the form of a skeleton, such as ``VatSkel``. Initialize self. See help(type(self)) for accurate signature. .. py:exception:: DispatchError(msg, hook, *args) Bases: :py:obj:`ViURShopException` Exception raised when dispatch fails (e.g. a Hook). Create a new DispatchError. :param msg: Error message :param hook: The hook tried to dispatch .. py:attribute:: hook :type: viur.shop.services.Hook .. py:exception:: IllegalOperationError Bases: :py:obj:`ViURShopException` Exception raised when an operation is not permitted in the current context. This usually signals that the requested action violates business rules, security constraints, or logical limitations of the system. Initialize self. See help(type(self)) for accurate signature. .. py:class:: InvalidArgumentException(argument_name, argument_value = _SENTINEL, descr_appendix = '') Bases: :py:obj:`ViURShopHttpException` Exception raised when a function receives an invalid value for an argument. **HTTP response status code:** ``460 Invalid Parameter`` Create a new TooManyArgumentsException. :param argument_name: Names of the invalid argument passed to the function. :param argument_value: Value of the invalid argument passed to the function. :param descr_appendix: Optional description for this error. .. py:attribute:: argument_name .. py:attribute:: argument_value .. py:attribute:: descr_appendix :value: '' .. py:class:: InvalidKeyException(key, argument_name = 'key') Bases: :py:obj:`ViURShopHttpException` Base of all ViUR Shop HTTP exceptions .. py:attribute:: key .. py:attribute:: argument_name :value: 'key' .. py:exception:: InvalidStateError Bases: :py:obj:`ViURShopException` Exception raised when an object or resource (for the requested operation) is in a state that should not occur or is not permitted for this operation. Initialize self. See help(type(self)) for accurate signature. .. py:class:: MissingArgumentsException(func_name, *argument_names, one_of = False) Bases: :py:obj:`ViURShopHttpException` Exception raised when one or more required arguments are missing in a function call. **HTTP response status code:** ``463 Missing Arguments`` Create a new MissingArgumentsException. :param func_nam: The name of the function where the error occurred. :param argument_name: Names of the unexpected arguments passed to the function. :param one_of: If True, indicates that at least one of the listed arguments is required (logical OR). If False, all listed arguments are required (logical AND). .. py:attribute:: func_name .. py:attribute:: argument_names :type: tuple[str, Ellipsis] :value: () .. py:attribute:: one_of :type: bool :value: False .. py:class:: TooManyArgumentsException(func_name, *argument_names) Bases: :py:obj:`ViURShopHttpException` Exception raised when a function receives unknown or excessive arguments. **HTTP response status code:** ``462 Too Many Arguments`` Create a new TooManyArgumentsException. :param func_nam: The name of the function where the error occurred. :param argument_names: Names of the unexpected arguments passed to the function. .. py:attribute:: func_name .. py:attribute:: argument_names :type: tuple[str, Ellipsis] :value: () .. py:exception:: ViURShopException Bases: :py:obj:`Exception` Base of all ViUR Shop exceptions Initialize self. See help(type(self)) for accurate signature. .. py:class:: ViURShopHttpException Bases: :py:obj:`viur.core.errors.HTTPException` Base of all ViUR Shop HTTP exceptions .. py:class:: Price(src_object) Represents the pricing logic and applicable discounts for an article or cart item. This class handles price calculation for shop articles, taking into account the current discounts, whether the item is in the cart, VAT, and other relevant conditions. It supports retail and recommended prices (gross/net), discount combinations, and tracks savings both in value and percentage. It also provides a method to return all pricing data as a dictionary for serialization. Initialize a Price object based on an article or cart item skeleton. Sets up the article reference, detects cart state, and loads applicable discounts. :param src_object: Either an article skeleton or a cart item skeleton. :raises TypeError: If `src_object` is not a supported type. :raises InvalidStateError: If the article skeleton has already run renderPreparation. .. py:attribute:: cart_discounts :type: list[viur.core.skeleton.SkeletonInstance] :value: [] .. py:attribute:: article_discount :type: viur.core.skeleton.SkeletonInstance :value: None .. py:attribute:: is_in_cart :value: None .. py:attribute:: article_skel :value: None .. py:attribute:: cart_leaf :value: None .. py:property:: retail :type: float Returns the retail (normal) gross price of the article. :return: Gross retail price as float. .. py:property:: retail_net :type: float Calculates the net value from the retail price based on VAT. :return: Retail price without VAT. .. py:property:: recommended :type: float Returns the recommended retail price (RRP) as set in the article. :return: Recommended gross price. .. py:property:: recommended_net :type: float Returns the net version of the recommended price. :return: Net recommended price. .. py:property:: saved :type: float Calculates how much is saved compared to the retail price. :return: Absolute savings in currency units. .. py:property:: saved_net :type: float Calculates the net value of the saved amount. :return: Net savings amount. .. py:property:: saved_percentage :type: float Returns how much the customer saves as a percentage of the retail price. :return: Savings percentage (0.0 - 1.0). .. py:method:: current() Computes the final current price after applying all applicable discounts. :return: Final discounted price. .. py:property:: current_net :type: float Returns the net value of the current (discounted) price. :return: Current price without VAT. .. py:method:: shop_current_discount(article_skel) Find the best automatic (permanent) discount currently available for the article. :param article_skel: The article skeleton to check. :return: Tuple of (discounted price, discount skeleton) or None if no discounts apply. .. py:method:: choose_best_discount_set() Find the best combination of applicable cart discounts for the article. :return: Tuple of (best price, list of discount skeletons applied). .. py:method:: vat_rate_percentage() Returns the VAT rate as a float for this article (e.g. 0.19 for 19 %). :return: VAT rate as float between 0.0 and 1.0. .. py:property:: vat_included :type: float Calculates the VAT amount included in the current price. :return: Included VAT value. .. py:method:: _shipping_address() Returns the shipping address for the closest cart node. .. py:method:: to_dict() Serializes the relevant pricing fields to a dictionary, suitable for frontend or API use. :return: Dictionary with pricing information and discounts. .. py:method:: apply_discount(discount_skel, article_price) :staticmethod: Applies a given discount to a given article price. :param discount_skel: Discount skeleton to apply. :param article_price: Base price of the article. :return: New price after applying the discount. :raises NotImplementedError: If the discount type is not supported. .. py:method:: gross_to_net(gross_value, vat_value) :staticmethod: Converts a gross price to net using the given VAT rate. :param gross_value: Gross price. :param vat_value: VAT rate (0.0 - 1.0). :return: Net price. :raises ValueError: If VAT value is out of range. .. py:method:: gross_to_vat(gross_value, vat_value) :staticmethod: Extracts the VAT amount from a gross value. :param gross_value: Gross price. :param vat_value: VAT rate (0.0 - 1.0). :return: VAT amount. :raises ValueError: If VAT value is out of range. .. py:method:: get_or_create(src_object) :classmethod: Returns a cached or newly created Price object for the given article or cart item. Caches the result in the current request context for reuse. :param src_object: Source article or cart item skeleton. :return: Price instance. .. py:method:: get_cache() :classmethod: Request-local price cache to avoid recalculating prices during one request lifecycle. :return: Dictionary keyed by skeleton key, with cached `Price` objects. .. py:class:: ExtendedCustomJsonEncoder Bases: :py:obj:`viur.core.render.json.default.CustomJsonEncoder` .. py:method:: default(o) .. py:class:: JsonResponse(json_data, *, status_code = 200, content_type = 'application/json', json_sort = True, json_indent = 2) Bases: :py:obj:`Generic`\ [\ :py:obj:`T`\ ] .. py:attribute:: json_data .. py:attribute:: status_code :value: 200 .. py:attribute:: content_type :value: 'application/json' .. py:attribute:: json_sort :value: True .. py:attribute:: json_indent :value: 2 .. py:method:: __str__() .. py:class:: OrderViewResult Bases: :py:obj:`TypedDict` Result structure returned when viewing an order, including the skeleton and validation states. Contains the order data as well as flags indicating whether checkout or ordering is currently allowed. Initialize self. See help(type(self)) for accurate signature. .. py:attribute:: skel :type: viur.shop.SkeletonInstance_T[viur.shop.OrderSkel] .. py:attribute:: can_checkout :type: StatusError .. py:attribute:: can_order :type: StatusError .. py:class:: PaymentProviderResult Bases: :py:obj:`TypedDict` Metadata and availability status for a payment provider. Includes translated title/description, an optional image path, and a flag for availability. Initialize self. See help(type(self)) for accurate signature. .. py:attribute:: title :type: viur.core.translate .. py:attribute:: descr :type: viur.core.translate .. py:attribute:: image_path :type: str | None .. py:attribute:: is_available :type: bool .. py:class:: StatusError Bases: :py:obj:`TypedDict` Represents the result of a validation check, including a success flag and a list of errors. Used to indicate whether a certain operation (e.g. checkout or order) is allowed. Initialize self. See help(type(self)) for accurate signature. .. py:attribute:: status :type: bool .. py:attribute:: errors :type: list[shop.types.data.ClientError] .. py:class:: PaymentTransaction Bases: :py:obj:`PaymentTransactionSpecific` dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2) Initialize self. See help(type(self)) for accurate signature. .. py:attribute:: payment_provider :type: str .. py:attribute:: creationdate :type: str .. py:attribute:: uuid :type: str .. py:attribute:: client_ip :type: str .. py:attribute:: user_agent :type: str .. py:class:: PaymentTransactionSpecific Bases: :py:obj:`TypedDict` dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2) Initialize self. See help(type(self)) for accurate signature. .. py:attribute:: payment_id :type: str