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()
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
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)
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
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, )
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)
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()
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})
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]
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
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
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" )
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
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))
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)
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})
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 ) ]
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())
def get_form_class(self): return cached_load("E-Commerce_ADDRESS_BOOK_EDIT_FORM")
def get_shop(request, **kwargs): return cached_load("E-Commerce_REQUEST_SHOP_PROVIDER_SPEC").get_shop(request, **kwargs)
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
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
def get_basket_order_creator(request=None): return cached_load("E-Commerce_BASKET_ORDER_CREATOR_SPEC")(request=request)
def get_supplier(request, **kwargs): return cached_load("E-Commerce_ADMIN_SUPPLIER_PROVIDER_SPEC").get_supplier(request, **kwargs)
def get_form_class(self): return cached_load("E-Commerce_COMPANY_INFORMATION_EDIT_FORM")
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()
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
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)
def run(self, shop): run_event = cached_load("E-Commerce_NOTIFY_SCRIPT_RUNNER") run_event(event=self, shop=shop)
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")