Beispiel #1
0
def handle_update(request, basket, **kwargs):
    """
    Handle updating a basket, i.e. deleting some lines or updating quantities.

    This dispatches further to whatever is declared by the `E-Commerce_BASKET_UPDATE_METHODS_SPEC`
    configuration entry.
    """
    methods = cached_load("E-Commerce_BASKET_UPDATE_METHODS_SPEC")(request=request, basket=basket)
    prefix_method_dict = methods.get_prefix_to_method_map()
    basket_changed = False
    # If any POST items match a prefix defined in prefix_method_dict, call the appropriate model method.
    for key, value in six.iteritems(kwargs):
        for prefix, method in six.iteritems(prefix_method_dict):
            if key.startswith(prefix):
                line_id = key[len(prefix):]
                line = basket.find_line_by_line_id(line_id)
                field_changed = method(
                    key=key,
                    value=value,
                    line=line
                )
                basket_changed = (basket_changed or field_changed)
                break

    if basket_changed:  # pragma: no branch
        basket.clean_empty_lines()
        basket.dirty = True
        basket.uncache()
Beispiel #2
0
    def get_object(self):
        basket_class = cached_load("E-Commerce_BASKET_CLASS_SPEC")
        shop = self.request.shop
        uuid = get_key(self.kwargs.get(self.lookup_field, ""))
        storage = get_storage()
        if not storage.basket_exists(uuid, shop):
            raise exceptions.NotFound()

        basket = basket_class(self.request._request, basket_name=uuid)
        try:
            basket._data = basket.storage.load(basket)
        except BasketCompatibilityError as error:
            raise exceptions.ValidationError(str(error))

        # ensure correct creator
        if not self.request.user.is_superuser:
            if not basket.shop == shop:
                raise exceptions.PermissionDenied("No permission")

            customer_id = (basket.customer.pk if basket.customer else None)
            controlled_contact_ids = self._get_controlled_contacts_by_user(self.request.user)
            is_staff = self.is_staff_user(shop, self.request.user)
            if customer_id and customer_id not in controlled_contact_ids and not is_staff:
                raise exceptions.PermissionDenied("No permission")

        return basket
Beispiel #3
0
    def new(self, request, *args, **kwargs):
        """
        Create a brand new basket object
        """
        serializer = NewBasketSerializer(data=request.data)
        serializer.is_valid(True)
        data = serializer.validated_data

        self.process_request(with_basket=False, shop=data.get("shop"))
        basket_class = cached_load("E-Commerce_BASKET_CLASS_SPEC")
        basket = basket_class(request._request)

        if "customer" in data:
            customer = data["customer"]
        else:
            customer = get_company_contact(request.user) or get_person_contact(request.user)

        orderer = data.get("orderer", get_person_contact(request.user))

        # set the request basket to perform the basket command
        self.request.basket = basket
        self._handle_set_customer(
            request=self.request._request,
            basket=basket,
            customer=customer,
            orderer=orderer
        )

        stored_basket = basket.save()
        response_data = {
            "uuid": "%s-%s" % (request.shop.pk, stored_basket.key)
        }
        response_data.update(self.get_serializer(basket).data)
        return Response(data=response_data, status=status.HTTP_201_CREATED)
Beispiel #4
0
def get_basket(request, basket_name="basket", basket_class=None):
    """
    Get the basket cached in the request or create and cache a new one.

    The basket_class is used when creating a new basket, i.e. when the
    request doesn't already have a basket cached with the given name.
    If no basket_class is given, will load a class using the
    `~E-Commerce.front.settings.E-Commerce_BASKET_CLASS_SPEC` setting.

    :type request: django.http.request.HttpRequest
    :type basket_name: str
    :type basket_class: type|None
    :rtype: E-Commerce.front.basket.objects.BaseBasket
    """
    basket = _get_basket_from_request(request, basket_name)
    if basket:
        return basket

    if basket_class is None:
        basket_class = cached_load("E-Commerce_BASKET_CLASS_SPEC")

    basket = basket_class(request, basket_name=basket_name)

    _save_basket_to_request(request, basket_name, basket)

    return basket
Beispiel #5
0
    def get_price_info(self, context, product, quantity=1):
        product_id = (product if isinstance(product, six.integer_types) else product.pk)
        shop = context.shop

        # By default let's use supplier passed to context.
        supplier = context.supplier
        if not supplier:
            # Since supplier is optional I am pretty sure
            # there is cases that supplier is not passed to
            # pricing context. This is not a problem. The
            # pricing module which decides to use supplier
            # for product prices mjust need to have some sane
            # fallback.
            supplier_strategy = cached_load("E-Commerce_SHOP_PRODUCT_SUPPLIERS_STRATEGY")
            kwargs = {
                "product_id": product_id,
                "shop": context.shop,
                "customer": context.customer,
                "quantity": quantity,
                "basket": context.basket
            }

            # Since this is custom pricing module it
            # requires also custom supplier strategy.
            # Some example is provided in
            # `E-Commerce.testing.supplier_pricing.supplier_strategy:CheapestSupplierPriceSupplierStrategy`
            supplier = supplier_strategy().get_supplier(**kwargs)

        # Like now in customer group pricing let's take default price from shop product
        default_price_values = list(ShopProduct.objects.filter(
            product_id=product_id, shop=shop).values_list("default_price_value", flat=True))
        if len(default_price_values) == 0:  # No shop product
            return PriceInfo(price=shop.create_price(0), base_price=shop.create_price(0), quantity=quantity)
        else:
            default_price = default_price_values[0] or 0

        # Then the actual supplier price in case we have
        # been able to figure out some supplier. I guess
        # it is problem for supplier strategy if it allows
        # supplier to be None in some weird scenarios.
        # Not sure though what would happen in shop product
        # orderability checks and so on.
        price = None
        if supplier:
            result = SupplierPrice.objects.filter(
                shop=shop, product_id=product_id, supplier=supplier
            ).order_by("amount_value")[:1].values_list("amount_value", flat=True)
            if result:
                price = result[0]

            if not price:
                price = default_price

        return PriceInfo(
            price=shop.create_price(price * quantity),
            base_price=shop.create_price(price * quantity),
            quantity=quantity,
        )
Beispiel #6
0
 def get_supplier(self, customer=None, quantity=None, shipping_address=None):
     supplier_strategy = cached_load("E-Commerce_SHOP_PRODUCT_SUPPLIERS_STRATEGY")
     kwargs = {
         "shop_product": self,
         "customer": customer,
         "quantity": quantity,
         "shipping_address": shipping_address
     }
     return supplier_strategy().get_supplier(**kwargs)
Beispiel #7
0
def get_storage():
    """
    Retrieve a basket storage object.

    :return: A basket storage object
    :rtype: BasketStorage
    """
    storage_class = cached_load("E-Commerce_BASKET_STORAGE_CLASS_SPEC")
    return storage_class()
Beispiel #8
0
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request")
        super(CustomerInformationFormGroup, self).__init__(*args, **kwargs)
        contact = get_person_contact(self.request.user)
        address_form_class = cached_load("E-Commerce_ADDRESS_MODEL_FORM")

        for form_name in self.address_forms:
            self.add_form_def(form_name, address_form_class, kwargs={
                "instance": getattr(contact, "default_%s_address" % form_name)
            })

        self.add_form_def("contact", PersonContactForm, kwargs={"instance": contact})
Beispiel #9
0
 def __init__(self, *args, **kwargs):
     self.request = kwargs.pop("request")
     super(CompanyForm, self).__init__(*args, **kwargs)
     self.fields['name'].required = True
     self.fields['tax_number'].required = True
     address_form = cached_load('E-Commerce_ADDRESS_MODEL_FORM')()
     for field in self.fields:
         if field not in ('name', 'tax_number', 'www'):
             address_formfield = address_form.fields.get(field)
             if address_formfield:
                 self.fields[field].required = address_formfield.required
             else:
                 del self.fields[field]
Beispiel #10
0
 def get_form(self, form_class=None):
     order = self.get_object()
     form_group = FormGroup(**self.get_form_kwargs())
     address_form_class = cached_load("E-Commerce_ADDRESS_MODEL_FORM")
     form_group.add_form_def(
         "billing_address",
         address_form_class,
         kwargs={"initial": get_data_dict(order.billing_address) if order.billing_address else {}})
     form_group.add_form_def(
         "shipping_address",
         address_form_class,
         kwargs={"initial": get_data_dict(order.shipping_address) if order.shipping_address else {}})
     return form_group
Beispiel #11
0
    def get_form(self, form_class=None):
        fg = FormGroup(**self.get_form_kwargs())
        default_address_form_class = cached_load("E-Commerce_ADDRESS_MODEL_FORM")
        for kind in self.address_kinds:
            fg.add_form_def(kind, form_class=self.address_form_classes.get(kind, default_address_form_class))
            fg.add_form_def("saved_{}".format(kind),
                            form_class=SavedAddressForm,
                            required=False,
                            kwargs={"kind": kind, "owner": self.basket.customer})

        if self.company_form_class and allow_company_registration(self.request.shop) and not self.request.customer:
            fg.add_form_def("company", self.company_form_class, required=False, kwargs={"request": self.request})

        return fg
Beispiel #12
0
 def get_form_defs(self):
     initial = {}  # TODO: should we do this? model_to_dict(self.object, AddressForm._meta.fields)
     address_form_class = cached_load("E-Commerce_ADDRESS_MODEL_FORM")
     yield FormDef(
         name="shipping_address", form_class=address_form_class,
         required=False, kwargs={"instance": self.object.default_shipping_address, "initial": initial}
     )
     yield FormDef(
         name="billing_address", form_class=address_form_class,
         required=False, kwargs={"instance": self.object.default_billing_address, "initial": initial}
     )
     # Using a pseudo formdef to group the two actual formdefs...
     yield TemplatedFormDef(
         name="addresses", form_class=forms.Form,
         required=False, template_name="E-Commerce/admin/contacts/_edit_addresses_form.jinja"
     )
Beispiel #13
0
def test_basket_with_custom_shop(rf):
    """
    Set a different shop for basket
    """
    with override_settings(**CORE_BASKET_SETTINGS):
        shop1 = factories.get_default_shop()
        shop2 = factories.get_shop(identifier="shop2")
        user = factories.create_random_user()
        request = apply_request_middleware(rf.get("/"), user=user, shop=shop1)
        basket_class = cached_load("E-Commerce_BASKET_CLASS_SPEC")
        basket = basket_class(request, "basket", shop=shop2)
        assert basket.shop == shop2

        product_shop2 = factories.create_product("product_shop2", shop2, factories.get_default_supplier(), 10)
        line = basket.add_product(factories.get_default_supplier(), shop2, product_shop2, 1)
        assert line.shop == shop2
Beispiel #14
0
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request")
        super(CompanyRegistrationForm, self).__init__(*args, **kwargs)
        address_form_cls = cached_load('E-Commerce_ADDRESS_MODEL_FORM')
        self.add_form_def('company', CompanyForm, kwargs={"request": self.request})
        self.add_form_def('billing', address_form_cls)
        self.add_form_def('contact_person', ContactPersonForm)
        self.add_form_def('user_account', UserCreationForm)

        for provider_cls in get_provide_objects("front_company_registration_form_provider"):
            provider = provider_cls(self, self.request)
            for definition in provider.get_definitions():
                self.add_form_def(
                    name=definition.form_name,
                    form_class=definition.form_class,
                    required=definition.required,
                    kwargs=dict(shop=self.request.shop, request=self.request))
Beispiel #15
0
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request")
        self.instance = kwargs.pop("instance")
        super(AddressBookFormGroup, self).__init__(*args, **kwargs)
        address_kwargs = {}
        saved_address_kwargs = {}

        if self.instance:
            address_kwargs["instance"] = self.instance.address
            saved_address_kwargs["initial"] = {
                "role": self.instance.role,
                "status": self.instance.status,
                "title": self.instance.title,
            }

        self.add_form_def("address", cached_load("E-Commerce_ADDRESS_MODEL_FORM"), kwargs=address_kwargs)
        self.add_form_def("saved_address", self.saved_address_form, kwargs=saved_address_kwargs)
Beispiel #16
0
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request")
        super(CompanyInformationFormGroup, self).__init__(*args, **kwargs)

        user = self.request.user
        company = get_company_contact(user)
        person = get_person_contact(user)
        address_form_class = cached_load("E-Commerce_ADDRESS_MODEL_FORM")

        for form_name in self.address_forms:
            self.add_form_def(
                form_name,
                address_form_class,
                kwargs={
                    "instance": _get_default_address_for_contact(company, "default_%s_address" % form_name, person)
                }
            )
        self.add_form_def("contact", CompanyContactForm, kwargs={"instance": company})
Beispiel #17
0
    def get_form_defs(self):
        shop = self.object
        context = cached_load("E-Commerce_XTHEME_ADMIN_THEME_CONTEXT")(shop)
        context.update({"shop": shop})

        current_theme_class = (context["current_theme"] or context["theme_classes"][0])
        current_theme_settings = ThemeSettings.objects.get_or_create(
            shop=shop,
            theme_identifier=current_theme_class.identifier
        )[0]
        context["active_stylesheet"] = current_theme_settings.data.get("settings", {}).get("stylesheet", None)

        return [
            TemplatedWizardFormDef(
                template_name="E-Commerce/xtheme/admin/wizard.jinja",
                name="theme",
                form_class=ActivationForm,
                context=context
            )
        ]
Beispiel #18
0
def render_in_context(context, template_text, html_intent=False):
    """
    Render the given Jinja2 template text in the script context.

    :param context: Script context.
    :type context: E-Commerce.notify.script.Context
    :param template_text: Jinja2 template text.
    :type template_text: str
    :param html_intent: Is the template text intended for HTML output?
                        This currently turns on autoescaping.
    :type html_intent: bool
    :return: Rendered template text
    :rtype: str
    :raises: Whatever Jinja2 might happen to raise
    """

    environment_provider = cached_load("E-Commerce_NOTIFY_TEMPLATE_ENVIRONMENT_PROVIDER")
    env = environment_provider(context=context, html_intent=html_intent)
    template = env.from_string(template_text)
    return template.render(context.get_variables())
Beispiel #19
0
 def get_form_class(self):
     return cached_load("E-Commerce_ADDRESS_BOOK_EDIT_FORM")
Beispiel #20
0
def get_shop(request, **kwargs):
    return cached_load("E-Commerce_REQUEST_SHOP_PROVIDER_SPEC").get_shop(request, **kwargs)
Beispiel #21
0
 def get_context_data(self, **kwargs):
     context = super(ThemeConfigView, self).get_context_data(**kwargs)
     shop = get_shop(self.request)
     context.update(cached_load("E-Commerce_XTHEME_ADMIN_THEME_CONTEXT")(shop))
     return context
Beispiel #22
0
def get_checkout_view():
    view = cached_load("E-Commerce_CHECKOUT_VIEW_SPEC")
    if hasattr(view, "as_view"):  # pragma: no branch
        view = view.as_view()
    return view
Beispiel #23
0
def get_basket_order_creator(request=None):
    return cached_load("E-Commerce_BASKET_ORDER_CREATOR_SPEC")(request=request)
Beispiel #24
0
def get_supplier(request, **kwargs):
    return cached_load("E-Commerce_ADMIN_SUPPLIER_PROVIDER_SPEC").get_supplier(request, **kwargs)
Beispiel #25
0
 def get_form_class(self):
     return cached_load("E-Commerce_COMPANY_INFORMATION_EDIT_FORM")
Beispiel #26
0
def get_modules():
    """
    :rtype: list[E-Commerce.admin.base.AdminModule]
    """
    get_modules_spec = cached_load("E-Commerce_GET_ADMIN_MODULES_SPEC")
    return get_modules_spec()
Beispiel #27
0
def get_basket_view():
    view = cached_load("E-Commerce_BASKET_VIEW_SPEC")
    if hasattr(view, "as_view"):  # pragma: no branch
        view = view.as_view()
    return view
Beispiel #28
0
def get_basket_command_dispatcher(request):
    """
    :type request: django.http.request.HttpRequest
    :rtype: E-Commerce.front.basket.command_dispatcher.BasketCommandDispatcher
    """
    return cached_load("E-Commerce_BASKET_COMMAND_DISPATCHER_SPEC")(request=request)
Beispiel #29
0
 def run(self, shop):
     run_event = cached_load("E-Commerce_NOTIFY_SCRIPT_RUNNER")
     run_event(event=self, shop=shop)
Beispiel #30
0
def test_provider_provides_definitions(rf, admin_user):
    if "E-Commerce.front.apps.registration" not in settings.INSTALLED_APPS:
        pytest.skip("E-Commerce.front.apps.registration required in installed apps")

    shop = get_default_shop()

    with override_provides("front_company_registration_form_provider", ["E-Commerce_tests.front.utils.FormDefTestProvider"]):
        with override_provides("front_registration_field_provider", ["E-Commerce_tests.front.utils.FieldTestProvider"]):
            request = apply_request_middleware(rf.post("/"), shop=shop)
            current_username = "******"
            current_name = "123"
            payload = {
                'company-tax_number':"123",
                'company-name': current_name,
                'billing-country': "US",
                'billing-city': "city",
                'billing-street': "street",
                'contact_person-last_name': "last",
                'contact_person-first_name': "first",
                'contact_person-email': "*****@*****.**",
                'user_account-password1': "asdf123",
                'user_account-password2': "asdf123",
                'user_account-username': current_username
            }
            form_group = CompanyRegistrationForm(request=request, data=payload)

            assert FormDefTestProvider.test_name in form_group.form_defs

            # test CompanyRegistrationForm itself
            assert "company" in form_group.form_defs
            assert "billing" in form_group.form_defs
            assert "contact_person" in form_group.form_defs
            assert "user_account" in form_group.form_defs

            assert form_group.form_defs["billing"].form_class == cached_load('E-Commerce_ADDRESS_MODEL_FORM')

            assert not form_group.is_valid()
            assert FormDefTestProvider.test_name in form_group.errors
            assert FieldTestProvider.key in form_group.errors[FormDefTestProvider.test_name]
            assert len(form_group.errors) == 1  # no other errors

            key = "%s-%s" % (FormDefTestProvider.test_name, FieldTestProvider.key)
            payload.update({key: 1})

            form_group = CompanyRegistrationForm(request=request, data=payload)

            assert FormDefTestProvider.test_name in form_group.form_defs
            assert form_group.is_valid()
            assert FormDefTestProvider.test_name not in form_group.errors
            assert not len(form_group.errors)  # no errors

            # test signal fires
            company_registration_save.connect(
                change_company_signal, dispatch_uid="test_registration_change_company_signal")
            form_group.save(commit=True)
            assert not User.objects.filter(username=username).exists()
            assert not CompanyContact.objects.filter(name=current_name).exists()

            assert User.objects.filter(username="******").exists()
            assert CompanyContact.objects.filter(name="changed_name").exists()
            company_registration_save.disconnect(dispatch_uid="test_registration_change_company_signal")