Beispiel #1
0
    def __init__(self, *args, **kwargs):
        from shuup.admin.modules.settings import consts
        from shuup.admin.modules.settings.enums import OrderReferenceNumberMethod
        shop = kwargs.pop("shop")
        kwargs["initial"] = {
            consts.ORDER_REFERENCE_NUMBER_LENGTH_FIELD: configuration.get(
                shop, consts.ORDER_REFERENCE_NUMBER_LENGTH_FIELD, settings.SHUUP_REFERENCE_NUMBER_LENGTH),
            consts.ORDER_REFERENCE_NUMBER_PREFIX_FIELD: configuration.get(
                shop, consts.ORDER_REFERENCE_NUMBER_PREFIX_FIELD, settings.SHUUP_REFERENCE_NUMBER_PREFIX),
        }
        super(ShopOrderConfigurationForm, self).__init__(*args, **kwargs)

        reference_method = configuration.get(
            shop, consts.ORDER_REFERENCE_NUMBER_METHOD_FIELD, settings.SHUUP_REFERENCE_NUMBER_METHOD)

        self.prefix_disabled = (reference_method in
                                [OrderReferenceNumberMethod.UNIQUE.value,
                                 OrderReferenceNumberMethod.SHOP_RUNNING.value])

        self.fields[consts.ORDER_REFERENCE_NUMBER_PREFIX_FIELD].disabled = self.prefix_disabled

        decimal_places = 2  # default
        if shop.currency in babel.core.get_global('currency_fractions'):
            decimal_places = babel.core.get_global('currency_fractions')[shop.currency][0]

        self.fields[ORDER_MIN_TOTAL_CONFIG_KEY] = FormattedDecimalFormField(
            label=_("Order minimum total"),
            decimal_places=decimal_places,
            max_digits=FORMATTED_DECIMAL_FIELD_MAX_DIGITS,
            min_value=0,
            required=False,
            initial=configuration.get(shop, ORDER_MIN_TOTAL_CONFIG_KEY, Decimal(0)),
            help_text=_("The minimum sum that an order needs to reach to be created.")
        )
Beispiel #2
0
def test_simple_set_and_get_without_shop():
    configuration.set(None, "answer", 42)
    assert configuration.get(None, "answer") == 42

    assert configuration.get(None, "non-existing") is None
    configuration.set(None, "non-existing", "hello")
    assert configuration.get(None, "non-existing") == "hello"
Beispiel #3
0
def assert_config_value(rf, admin_user, form_id, key, value, expected_value, shop=None):
    if not shop:
        shop = get_default_shop()

    request = apply_request_middleware(rf.get("/"), user=admin_user)
    view_func = SystemSettingsView.as_view()
    response = view_func(request)
    assert response.status_code == 200

    form_field = "%s-%s" % (form_id, key)
    data = {form_field: value}
    request = apply_request_middleware(rf.post("/", data=data), user=admin_user)
    response = view_func(request)
    assert response.status_code == 302
    if expected_value == "unset":
        expected_value = value
    assert configuration.get(None, key) == expected_value

    assert len(messages.get_messages(request)) == 1

    # Double save the form and the configuration should still be unchanged
    response = view_func(request)
    assert response.status_code == 302
    assert configuration.get(None, key) == expected_value

    assert len(messages.get_messages(request)) == 2

    return shop
Beispiel #4
0
def test_view_default_columns(rf, admin_user):
    shop = get_default_shop()

    view = ProductListView.as_view()

    request = apply_request_middleware(rf.get("/", {
        "jq": json.dumps({"perPage": 100, "page": 1})
    }), user=admin_user)
    response = view(request)
    assert 200 <= response.status_code < 300

    listview = ProductListView()
    assert listview.settings.default_columns == listview.default_columns

    column_names = [c.id for c in sorted(listview.columns, key=lambda x: x.id)]
    default_column_names = [c.id for c in sorted(listview.default_columns, key=lambda x: x.id)]
    assert column_names == default_column_names
    assert configuration.get(None, "view_configuration_shopproduct_name")  # name is configured
    assert listview.settings.view_configured()
    assert listview.settings.get_settings_key("name") == "view_configuration_shopproduct_name"  # we are attached to product view

    settings_view = ListSettingsView.as_view()
    view_data = {"model": "ShopProduct", "module": "shuup.core.models", "return_url": "shop_product"}
    request = rf.get("/", view_data)
    response = settings_view(request)
    assert 200 <= response.status_code < 300

    # Change configuration by posting form
    request = rf.post("/?" + urlencode(view_data), {"view_configuration_shopproduct_name": False})
    response = settings_view(request)
    assert response.status_code == 302

    assert listview.settings.get_config("name") == configuration.get(None, "view_configuration_shopproduct_name")
    assert not configuration.get(None, "view_configuration_shopproduct_name").get("active")
Beispiel #5
0
def test_global_configurations():
    with override_settings(CACHES={
        'default': {
            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
            'LOCATION': 'test_global_configurations',
        }
    }):
        cache.init_cache()
        shop = get_default_shop()
        configuration.set(None, "key1", {"data": "test1"})
        configuration.set(shop, "key2", {"data": "test2"})

        # key1 from shop should come from global configuration
        assert configuration.get(shop, "key1").get("data") == "test1"
        # key2 shouldn't be in global configurations
        assert configuration.get(None, "key2") is None

        # Update global configuration
        configuration.set(None, "key1", {"data": "test_bump"})
        assert configuration.get(shop, "key1").get("data") == "test_bump"

        # Override shop data for global key1
        configuration.set(shop, "key1", "test_data")
        assert configuration.get(shop, "key1") == "test_data"

        # Update shop configuration for global key1
        configuration.set(shop, "key1", "test_data1")
        assert configuration.get(shop, "key1") == "test_data1"
Beispiel #6
0
def test_simple_set_and_get_cascading():
    with override_settings(CACHES={
        'default': {
            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
            'LOCATION': 'test_simple_set_and_get_cascading',
        }
    }):
        cache.init_cache()
        shop = get_default_shop()
        configuration.set(None, "answer", 42)
        assert configuration.get(None, "answer") == 42
        assert configuration.get(shop, "answer", 42)

        assert configuration.get(None, "non-existing") is None
        assert configuration.get(shop, "non-existing") is None
        configuration.set(shop, "non-existing", "hello")
        assert configuration.get(None, "non-existing") is None
        assert configuration.get(shop, "non-existing") == "hello"

        assert configuration.get(None, "foo") is None
        assert configuration.get(shop, "foo") is None
        configuration.set(None, "foo", "bar")
        configuration.set(shop, "foo", "baz")
        assert configuration.get(None, "foo") == "bar"
        assert configuration.get(shop, "foo") == "baz"
Beispiel #7
0
def test_simple_set_and_get_with_shop():
    shop = get_default_shop()
    configuration.set(shop, "answer", 42)
    assert configuration.get(shop, "answer") == 42

    assert configuration.get(shop, "non-existing") is None
    configuration.set(shop, "non-existing", "hello")
    assert configuration.get(shop, "non-existing") == "hello"
Beispiel #8
0
def test_configuration_gets_saved():
    configuration.set(None, "x", 1)
    assert configuration.get(None, "x") == 1
    configuration.set(None, "x", 2)
    assert configuration.get(None, "x") == 2
    configuration.set(None, "x", 3)
    assert configuration.get(None, "x") == 3
    conf_item = ConfigurationItem.objects.get(shop=None, key="x")
    assert conf_item.value == 3
Beispiel #9
0
    def is_valid(self):
        shipping_required = configuration.get(self.request.shop, SHIPPING_METHOD_REQUIRED_CONFIG_KEY, True)
        payment_required = configuration.get(self.request.shop, PAYMENT_METHOD_REQUIRED_CONFIG_KEY, True)

        if shipping_required and not self.storage.get("shipping_method_id"):
            return False
        if payment_required and not self.storage.get("payment_method_id"):
            return False

        return True
Beispiel #10
0
def get_configuration(shop=None, category=None, force_category_override=False):
    default_configuration = configuration.get(
        shop, FACETED_DEFAULT_CONF_KEY, settings.SHUUP_FRONT_DEFAULT_SORT_CONFIGURATION)

    category_config = configuration.get(None, _get_category_configuration_key(category))
    # when override_default_configuration is True, we override the default configuration
    if category_config and (category_config.get("override_default_configuration") or force_category_override):
        return category_config

    return default_configuration
Beispiel #11
0
def test_configuration_cache():
    cache.clear()
    shop = get_default_shop()
    configuration.set(None, "key1", "test1")
    configuration.set(shop, "key2", "test2")

    # Shop configurations cache should be bumped
    assert cache.get(configuration._get_cache_key(shop)) is None
    configuration.get(shop, "key1")
    # Now shop configurations and key2 should found from cache
    assert cache.get(configuration._get_cache_key(shop)).get("key2") == "test2"
Beispiel #12
0
def test_configuration_update():
    cache.clear()
    shop = get_default_shop()
    configuration.set(shop, "key1", {"data": "test1"})
    configuration.set(shop, "key2", {"data": "test2"})
    configuration.set(shop, "key3", {"data": "test3"})
    assert configuration.get(shop, "key1").get("data") == "test1"
    assert configuration.get(shop, "key3").get("data") == "test3"

    # Update configuration
    configuration.set(shop, "key3", {"data": "test_bump"})
    assert configuration.get(shop, "key3").get("data") == "test_bump"
Beispiel #13
0
def get_running_reference_number(order):
    from shuup import configuration
    from shuup.admin.modules.settings.consts import (ORDER_REFERENCE_NUMBER_PREFIX_FIELD,
                                                     ORDER_REFERENCE_NUMBER_LENGTH_FIELD)
    value = Counter.get_and_increment(CounterType.ORDER_REFERENCE)
    prefix = "%s" % configuration.get(
        order.shop, ORDER_REFERENCE_NUMBER_PREFIX_FIELD, settings.SHUUP_REFERENCE_NUMBER_PREFIX)
    ref_length = configuration.get(
        order.shop, ORDER_REFERENCE_NUMBER_LENGTH_FIELD, settings.SHUUP_REFERENCE_NUMBER_LENGTH)

    padded_value = force_text(value).rjust(ref_length - len(prefix), "0")
    reference_no = "%s%s" % (prefix, padded_value)
    return reference_no + calc_reference_number_checksum(reference_no)
Beispiel #14
0
 def get_form_defs(self):
     if not self.object.pk:
         return
     initial = {
         "shipping_method_required": configuration.get(self.object, SHIPPING_METHOD_REQUIRED_CONFIG_KEY, True),
         "payment_method_required": configuration.get(self.object, PAYMENT_METHOD_REQUIRED_CONFIG_KEY, True)
     }
     yield TemplatedFormDef(
         name=self.name,
         form_class=self.form,
         template_name="shuup/front/admin/checkout.jinja",
         required=True,
         kwargs={"initial": initial}
     )
Beispiel #15
0
    def _handle_xtheme_save(self):
        svc_pk = config.get(self.shop, CONTENT_FOOTER_KEY)
        svc = SavedViewConfig.objects.filter(pk=svc_pk).first()
        theme = get_current_theme(self.shop)

        if not svc and theme:
            context = {"shop": self.shop}
            rendered_content = template_loader.render_to_string(content_data.FOOTER_TEMPLATE, context).strip()
            layout = Layout(theme, "footer-bottom")
            # adds the footer template
            layout.begin_row()
            layout.begin_column({"md": 12})
            layout.add_plugin(SnippetsPlugin.identifier, {"in_place": rendered_content})

            svc = SavedViewConfig(
                theme_identifier=theme.identifier,
                shop=self.shop,
                view_name=XTHEME_GLOBAL_VIEW_NAME,
                status=SavedViewConfigStatus.CURRENT_DRAFT
            )
            svc.set_layout_data(layout.placeholder_name, layout)
            svc.save()
            svc.publish()

            config.set(self.shop, CONTENT_FOOTER_KEY, svc.pk)
Beispiel #16
0
def toggle_all_seeing_for_user(user):
    if not getattr(user, "is_superuser", False):
        return

    all_seeing_key = ALL_SEEING_FORMAT % {"user_id": user.pk}
    is_all_seeing = configuration.get(None, all_seeing_key, False)
    configuration.set(None, all_seeing_key, not is_all_seeing)
Beispiel #17
0
def test_configuration_gets_saved():
    with override_settings(CACHES={
        'default': {
            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
            'LOCATION': 'test_configuration_gets_saved',
        }
    }):
        cache.init_cache()
        configuration.set(None, "x", 1)
        assert configuration.get(None, "x") == 1
        configuration.set(None, "x", 2)
        assert configuration.get(None, "x") == 2
        configuration.set(None, "x", 3)
        assert configuration.get(None, "x") == 3
        conf_item = ConfigurationItem.objects.get(shop=None, key="x")
        assert conf_item.value == 3
Beispiel #18
0
    def save(self, commit=True):
        company = self.forms['company'].save(commit=False)
        billing_address = self.forms['billing'].save(commit=False)
        person = self.forms['contact_person'].save(commit=False)
        user = self.forms['user_account'].save(commit=False)

        company.default_billing_address = billing_address
        company.default_shipping_address = billing_address

        for field in ['name', 'name_ext', 'email', 'phone']:
            setattr(billing_address, field, getattr(company, field))

        person.user = user

        user.first_name = person.first_name
        user.last_name = person.last_name
        user.email = person.email

        # If company registration requires approval,
        # company and person contacts will be created as inactive
        if configuration.get(None, "company_registration_requires_approval"):
            company.is_active = False
            person.is_active = False

        if commit:
            user.save()
            person.user = user
            person.save()
            billing_address.save()
            company.default_billing_address = billing_address
            company.default_shipping_address = billing_address
            company.save()
            company.members.add(person)

        return user
Beispiel #19
0
def get_language_choices(shop=None):
    """
    Returns a list of the available language choices, e.g.:
        [("en", "English", "English"])

    If shot is passed, the languages will be filtered by those
    enabled for the shop.

    :rtype iterable[(str, str, str)]
    """
    available_languages = []
    languages = []

    if shop:
        available_languages = configuration.get(shop, FRONT_AVAILABLE_LANGUAGES_CONFIG_KEY)
        if available_languages:
            available_languages = available_languages.split(",")

    for code, name in settings.LANGUAGES:
        if available_languages and code not in available_languages:
            continue

        lang_info = get_language_info(code)
        name_in_current_lang = ugettext(name)
        local_name = lang_info["name_local"]
        languages.append((code, name_in_current_lang, local_name))
    return languages
Beispiel #20
0
def get_unique_reference_number(shop, id):
    from shuup import configuration
    from shuup.admin.modules.settings.consts import ORDER_REFERENCE_NUMBER_LENGTH_FIELD
    now = datetime.datetime.now()
    ref_length = configuration.get(shop, ORDER_REFERENCE_NUMBER_LENGTH_FIELD, settings.SHUUP_REFERENCE_NUMBER_LENGTH)
    dt = ("%06s%07d%04d" % (now.strftime("%y%m%d"), now.microsecond, id % 1000)).rjust(ref_length, "0")
    return dt + calc_reference_number_checksum(dt)
Beispiel #21
0
    def get_methods_validation_errors(self):
        shipping_methods = self.get_available_shipping_methods()
        payment_methods = self.get_available_payment_methods()

        advice = _(
            "Try to remove some products from the basket "
            "and order them separately.")

        if (self.has_shippable_lines() and not shipping_methods and
                configuration.get(self.shop, SHIPPING_METHOD_REQUIRED_CONFIG_KEY, True)):
            msg = _("Products in basket cannot be shipped together. %s")
            yield ValidationError(msg % advice, code="no_common_shipping")

        if not payment_methods and configuration.get(self.shop, PAYMENT_METHOD_REQUIRED_CONFIG_KEY, True):
            msg = _("Products in basket have no common payment method. %s")
            yield ValidationError(msg % advice, code="no_common_payment")
Beispiel #22
0
    def get_validation_errors(self):
        # check for the minimum sum of order total
        min_total = configuration.get(self.shop, ORDER_MIN_TOTAL_CONFIG_KEY, Decimal(0))
        total = (self.taxful_total_price.value if self.shop.prices_include_tax else self.taxless_total_price.value)
        if total < min_total:
            min_total_price = format_money(self.shop.create_price(min_total))
            yield ValidationError(_("The total should be greater than {} to be ordered.").format(min_total_price),
                                  code="order_total_too_low")

        shipping_method = self.shipping_method
        payment_method = self.payment_method

        if shipping_method:
            for error in shipping_method.get_unavailability_reasons(source=self):
                yield error

        if payment_method:
            for error in payment_method.get_unavailability_reasons(source=self):
                yield error

        for supplier in self._get_suppliers():
            for product, quantity in iteritems(self._get_products_and_quantities(supplier)):
                shop_product = product.get_shop_instance(shop=self.shop)
                if not shop_product:
                    yield ValidationError(
                        _("%s not available in this shop") % product.name,
                        code="product_not_available_in_shop"
                    )
                for error in shop_product.get_orderability_errors(
                        supplier=supplier, quantity=quantity, customer=self.customer):
                    error.message = "%s: %s" % (product.name, error.message)
                    yield error
Beispiel #23
0
def test_consolidate_objects(rf):
    get_default_shop()

    # just visit to make sure GET is ok
    request = apply_request_middleware(rf.get("/"))
    response = APIPermissionView.as_view()(request)
    assert response.status_code == 200

    perm_key = make_permission_config_key(UserViewSet())
    assert configuration.get(None, perm_key) is None

    # now post the form to see what happens
    request = apply_request_middleware(rf.post("/", {perm_key: PermissionLevel.ADMIN}))
    response = APIPermissionView.as_view()(request)
    assert response.status_code == 302      # good
    assert int(configuration.get(None, perm_key)) == PermissionLevel.ADMIN
Beispiel #24
0
def toggle_all_seeing(request):
    return_url = request.META["HTTP_REFERER"]
    if not request.user.is_superuser:
        return HttpResponseRedirect(return_url)
    all_seeing_key = "is_all_seeing:%d" % request.user.pk
    is_all_seeing = not configuration.get(None, all_seeing_key, False)
    configuration.set(None, all_seeing_key, is_all_seeing)
    return HttpResponseRedirect(return_url)
Beispiel #25
0
def test_behavior_form():
    shop = get_default_shop()

    assert Script.objects.count() == 0
    assert configuration.get(shop, BEHAVIOR_ORDER_CONFIRM_KEY) is None

    form = BehaviorWizardForm(shop=shop, data={"order_confirm_notification": True})
    assert form._get_saved_script() is None
    form.save()

    # check if the form creates a order notification correctely
    script = Script.objects.first()
    assert script.pk == configuration.get(shop, BEHAVIOR_ORDER_CONFIRM_KEY)
    assert form._get_saved_script().pk == script.pk
    assert len(script.get_steps()) == 1
    step = script.get_steps()[0]
    step_data = step.serialize()
    assert step_data["next"] == StepNext.STOP.value
    action = step._actions[0]
    assert isinstance(action, SendEmail)
    action_data = action.serialize()
    assert action_data["recipient"]["variable"] == "customer_email"
    assert action_data["language"]["variable"] == "language"
    lang = translation.get_language()
    assert action_data["fallback_language"]["constant"] == lang
    assert action_data["template_data"][lang]["content_type"] == "html"
    assert action_data["template_data"][lang]["subject"] == force_text(data.ORDER_CONFIRMATION["subject"])
    context = {"shop": shop}
    content = loader.render_to_string(data.ORDER_CONFIRMATION["body_template"], context).strip()
    assert action_data["template_data"][lang]["body"] == content

    # the widget must be disabled
    form = BehaviorWizardForm(shop=shop, data={"order_confirm_notification": True})
    assert form.fields["order_confirm_notification"].widget.attrs["disabled"] is True

    # clear scripts
    Script.objects.all().delete()
    configuration.set(shop, BEHAVIOR_ORDER_CONFIRM_KEY, None)

    # save the form but do not create the order confirmation notification
    form = BehaviorWizardForm(shop=shop, data={"order_confirm_notification": False})
    form.save()

    # nothing created
    assert Script.objects.count() == 0
    assert configuration.get(shop, BEHAVIOR_ORDER_CONFIRM_KEY) is None
Beispiel #26
0
def test_configuration_update():
    with override_settings(CACHES={
        'default': {
            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
            'LOCATION': 'test_configuration_update',
        }
    }):
        cache.init_cache()
        shop = get_default_shop()
        configuration.set(shop, "key1", {"data": "test1"})
        configuration.set(shop, "key2", {"data": "test2"})
        configuration.set(shop, "key3", {"data": "test3"})
        assert configuration.get(shop, "key1").get("data") == "test1"
        assert configuration.get(shop, "key3").get("data") == "test3"

        # Update configuration
        configuration.set(shop, "key3", {"data": "test_bump"})
        assert configuration.get(shop, "key3").get("data") == "test_bump"
Beispiel #27
0
def get_global_configuration(name, default=None):
    """
    Get global configuration variable value.

    :type name: str
    :type default: Any
    """
    from shuup import configuration
    return configuration.get(None, name, default)
Beispiel #28
0
def test_configuration_cache():
    with override_settings(CACHES={
        'default': {
            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
            'LOCATION': 'test_configuration_cache',
        }
    }):
        cache.init_cache()

        shop = get_default_shop()
        configuration.set(None, "key1", "test1")
        configuration.set(shop, "key2", "test2")

        # Shop configurations cache should be bumped
        assert cache.get(configuration._get_cache_key(shop)) is None
        configuration.get(shop, "key1")
        # Now shop configurations and key2 should found from cache
        assert cache.get(configuration._get_cache_key(shop)).get("key2") == "test2"
Beispiel #29
0
def test_simple_set_and_get_cascading():
    shop = get_default_shop()
    configuration.set(None, "answer", 42)
    assert configuration.get(None, "answer") == 42
    assert configuration.get(shop, "answer", 42)

    assert configuration.get(None, "non-existing") is None
    assert configuration.get(shop, "non-existing") is None
    configuration.set(shop, "non-existing", "hello")
    assert configuration.get(None, "non-existing") is None
    assert configuration.get(shop, "non-existing") == "hello"

    assert configuration.get(None, "foo") is None
    assert configuration.get(shop, "foo") is None
    configuration.set(None, "foo", "bar")
    configuration.set(shop, "foo", "baz")
    assert configuration.get(None, "foo") == "bar"
    assert configuration.get(shop, "foo") == "baz"
Beispiel #30
0
def get_shop_language_choices(context):
    request = context["request"]
    languages = []
    for code, name in configuration.get(request.shop, "languages", settings.LANGUAGES):
        lang_info = get_language_info(code)
        name_in_current_lang = ugettext(name)
        local_name = lang_info["name_local"]
        languages.append((code, name_in_current_lang, local_name))
    return languages
Beispiel #31
0
def setup_wizard_complete(request):
    """
    Check if shop wizard should be run.

    :return: whether setup wizard needs to be run
    :rtype: boolean
    """
    if getattr(settings, "SHUUP_ENABLE_MULTIPLE_SHOPS", False):
        # setup wizard is only applicable in single shop mode
        return True
    shop = request.shop
    complete = configuration.get(shop, "setup_wizard_complete")
    if complete is None:
        return not setup_wizard_visible_panes(shop)
    return complete
Beispiel #32
0
 def __init__(self, name, form_class, template_name, request, extra_js=""):
     shop = request.shop
     form_def_kwargs = {
         "name": name,
         "kwargs": {
             "instance": form_class._meta.model.objects.first(),
             "languages": configuration.get(shop, "languages", settings.LANGUAGES)
         }
     }
     super(ServiceWizardFormDef, self).__init__(
         form_class=form_class,
         template_name=template_name,
         extra_js=extra_js,
         **form_def_kwargs
     )
Beispiel #33
0
def set_reference_method(rf, admin_user, reference_method, shop=None):
    if not shop:
        shop = get_default_shop()
    request = apply_request_middleware(rf.get("/"), user=admin_user)
    view_func = SystemSettingsView.as_view()
    response = view_func(request)
    assert response.status_code == 200

    data = {
        "order_settings-order_reference_number_method": reference_method.value
    }
    request = apply_request_middleware(rf.post("/", data=data), user=admin_user)
    view_func(request)
    assert configuration.get(None, consts.ORDER_REFERENCE_NUMBER_METHOD_FIELD) == reference_method.value
    return shop
Beispiel #34
0
def test_view_default_columns(rf, admin_user):
    shop = get_default_shop()

    view = ProductListView.as_view()

    request = apply_request_middleware(rf.get("/", {"jq": json.dumps({"perPage": 100, "page": 1})}), user=admin_user)
    response = view(request)
    assert 200 <= response.status_code < 300

    listview = ProductListView()
    assert listview.settings.default_columns == listview.default_columns

    column_names = [c.id for c in sorted(listview.columns, key=lambda x: x.id)]
    default_column_names = [c.id for c in sorted(listview.default_columns, key=lambda x: x.id)]
    assert column_names == default_column_names
    assert configuration.get(None, "view_configuration_shopproduct_product_name")  # name is configured
    assert listview.settings.view_configured()
    assert (
        listview.settings.get_settings_key("product_name") == "view_configuration_shopproduct_product_name"
    )  # we are attached to product view

    settings_view = ListSettingsView.as_view()
    view_data = {"model": "ShopProduct", "module": "shuup.core.models", "return_url": "shop_product"}
    request = rf.get("/", view_data)
    response = settings_view(request)
    assert 200 <= response.status_code < 300

    # Change configuration by posting form
    request = rf.post("/?" + urlencode(view_data), {"view_configuration_shopproduct_product_name": False})
    response = settings_view(request)
    assert response.status_code == 302

    assert listview.settings.get_config("product_name") == configuration.get(
        None, "view_configuration_shopproduct_product_name"
    )
    assert not configuration.get(None, "view_configuration_shopproduct_product_name").get("active")
def test_configuration_set_and_get():
    with override_settings(CACHES={
        'default': {
            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
            'LOCATION': 'test_configuration_set_and_get',
        }
    }):
        cache.init_cache()
        shop = get_default_shop()
        test_conf_data = {"data": "test"}
        configuration.set(shop, "key", test_conf_data)

        # Get the configuration via configuration API
        assert configuration.get(shop, "key") == test_conf_data
        # Check that configuration is saved to database
        assert ConfigurationItem.objects.get(shop=shop, key="key").value == test_conf_data
Beispiel #36
0
    def get_validation_errors(cls, order_source):
        # check for the minimum sum of order total
        min_total = configuration.get(order_source.shop,
                                      ORDER_MIN_TOTAL_CONFIG_KEY, Decimal(0))

        if order_source.shop.prices_include_tax:
            total = order_source.taxful_total_price.value
        else:
            total = order_source.taxless_total_price.value

        if total < min_total:
            min_total_price = format_money(
                order_source.shop.create_price(min_total))
            msg = _("The total price should be greater than {} to be ordered."
                    ).format(min_total_price)
            yield ValidationError(msg, code="order_total_too_low")
Beispiel #37
0
def assert_config_value(rf, admin_user, form_id, key, value, expected_value, shop=None):
    if not shop:
        shop = get_default_shop()
    request = apply_request_middleware(rf.get("/"), user=admin_user)
    view_func = SystemSettingsView.as_view()
    response = view_func(request)
    assert response.status_code == 200

    form_field = "%s-%s" % (form_id, key)
    data = {form_field: value}
    request = apply_request_middleware(rf.post("/", data=data))
    response = view_func(request)
    assert response.status_code == 302
    if expected_value == "unset":
        expected_value = value
    assert configuration.get(None, key) == expected_value
    return shop
Beispiel #38
0
 def __init__(self,
              name,
              form_class,
              template_name,
              extra_js="",
              kwargs={}):
     kwargs.update({
         "instance":
         form_class._meta.model.objects.first(),
         "languages":
         configuration.get(Shop.objects.first(), "languages",
                           settings.LANGUAGES)
     })
     form_def_kwargs = {"name": name, "kwargs": kwargs}
     super(ServiceWizardFormDef, self).__init__(form_class=form_class,
                                                template_name=template_name,
                                                extra_js=extra_js,
                                                **form_def_kwargs)
Beispiel #39
0
 def get_form_defs(self):
     return [
         TemplatedWizardFormDef(
             name="shop",
             template_name="shuup/admin/shops/_wizard_base_shop_form.jinja",
             extra_js="shuup/admin/shops/_wizard_base_shop_script.jinja",
             form_class=ShopWizardForm,
             kwargs={
                 "instance":
                 self.object,
                 "languages":
                 configuration.get(self.object, "languages",
                                   settings.LANGUAGES)
             }),
         WizardFormDef(name="address",
                       form_class=ShopAddressWizardForm,
                       kwargs={"instance": self.object.contact_address})
     ]
Beispiel #40
0
def get_reference_number(order):
    from shuup import configuration
    from shuup.admin.modules.settings.consts import ORDER_REFERENCE_NUMBER_METHOD_FIELD

    if order.reference_number:
        raise ValueError("Error! Order passed to function `get_reference_number()` already has a reference number.")
    reference_number_method = configuration.get(
        order.shop, ORDER_REFERENCE_NUMBER_METHOD_FIELD, settings.SHUUP_REFERENCE_NUMBER_METHOD)
    if reference_number_method == "unique":
        return get_unique_reference_number_for_order(order)
    elif reference_number_method == "running":
        return get_running_reference_number(order)
    elif reference_number_method == "shop_running":
        return get_shop_running_reference_number(order)
    elif callable(reference_number_method):
        return reference_number_method(order)
    else:
        getter = load(reference_number_method, "Reference number generator")
        return getter(order)
Beispiel #41
0
    def get_validation_errors(self):  # noqa (C901)
        # check for the minimum sum of order total
        min_total = configuration.get(self.shop, ORDER_MIN_TOTAL_CONFIG_KEY,
                                      Decimal(0))
        total = (self.taxful_total_price.value if self.shop.prices_include_tax
                 else self.taxless_total_price.value)
        if total < min_total:
            min_total_price = format_money(self.shop.create_price(min_total))
            yield ValidationError(
                _("The total should be greater than {} to be ordered.").format(
                    min_total_price),
                code="order_total_too_low")

        shipping_method = self.shipping_method
        payment_method = self.payment_method

        if shipping_method:
            for error in shipping_method.get_unavailability_reasons(
                    source=self):
                yield error

        if payment_method:
            for error in payment_method.get_unavailability_reasons(
                    source=self):
                yield error

        for supplier in self._get_suppliers():
            for product, quantity in iteritems(
                    self._get_products_and_quantities(supplier)):
                try:
                    shop_product = product.get_shop_instance(shop=self.shop)
                except ShopProduct.DoesNotExist:
                    yield ValidationError(_("%s not available in this shop") %
                                          product.name,
                                          code="product_not_available_in_shop")
                    continue
                for error in shop_product.get_orderability_errors(
                        supplier=supplier,
                        quantity=quantity,
                        customer=self.customer):
                    error.message = "%s: %s" % (product.name, error.message)
                    yield error
Beispiel #42
0
    def save(self, commit=True):
        company = self.forms['company'].save(commit=False)
        billing_address = self.forms['billing'].save(commit=False)
        person = self.forms['contact_person'].save(commit=False)
        user = self.forms['user_account'].save(commit=False)

        company.default_billing_address = billing_address
        company.default_shipping_address = billing_address

        for field in ['name', 'name_ext', 'email', 'phone']:
            setattr(billing_address, field, getattr(company, field))

        person.user = user

        user.first_name = person.first_name
        user.last_name = person.last_name
        user.email = person.email

        # If company registration requires approval,
        # company and person contacts will be created as inactive
        if configuration.get(None, "company_registration_requires_approval"):
            company.is_active = False
            person.is_active = False

        if commit:
            user.save()
            person.user = user
            person.save()
            person.shops.add(self.request.shop)
            billing_address.save()
            company.default_billing_address = billing_address
            company.default_shipping_address = billing_address
            company.save()
            company.shops.add(self.request.shop)
            company.members.add(person)

        if has_installed("shuup.gdpr"):
            from shuup.gdpr.utils import create_user_consent_for_all_documents
            create_user_consent_for_all_documents(self.request.shop, user)

        return user
Beispiel #43
0
def _send_telemetry(request, max_age_hours, force_send=False):
    if not is_telemetry_enabled():
        raise TelemetryNotSent("Error! Telemetry not enabled.", "disabled")

    if not force_send:
        if is_opt_out():
            raise TelemetryNotSent("Error! Telemetry is opted-out.", "optout")

        if is_in_grace_period():
            raise TelemetryNotSent("Error! Telemetry in grace period.",
                                   "grace")

    if max_age_hours is not None:
        last_send_time = get_last_submission_time()
        if last_send_time and (now() - last_send_time
                               ).total_seconds() <= max_age_hours * 60 * 60:
            raise TelemetryNotSent("Trying to resend too soon", "age")

    data = get_telemetry_data(request)
    try:
        resp = requests.post(url=settings.SHUUP_TELEMETRY_URL,
                             data=data,
                             timeout=5)
        if (not settings.DEBUG and resp.status_code == 200
                and resp.json().get("support_id")
                and not configuration.get(None, "shuup_support_id")):
            configuration.set(None, "shuup_support_id",
                              resp.json().get("support_id"))
    except Exception as exc:
        data = {
            "data": data,
            "error": force_text(exc),
        }
    else:
        data = {
            "data": data,
            "response": force_text(resp.content, errors="replace"),
            "status": resp.status_code,
        }
    save_telemetry_submission(data)
    return data
    def form_valid(self, form):
        company = form["contact"].save(commit=False)
        is_new = not bool(company.pk)
        company.save()
        user = self.request.user
        person = get_person_contact(user)
        company.members.add(person)
        billing_address = form["billing"].save()
        shipping_address = form["shipping"].save()
        if billing_address.pk != company.default_billing_address_id:  # Identity changed due to immutability
            company.default_billing_address = billing_address
        if shipping_address.pk != company.default_shipping_address_id:  # Identity changed due to immutability
            company.default_shipping_address = shipping_address

        user.email = company.email
        user.first_name = company.name
        user.last_name = ""
        user.save()

        message = _("Company information saved successfully.")
        # If company registration requires activation,
        # company will be created as inactive.
        if is_new and configuration.get(
                None, "company_registration_requires_approval"):
            company.is_active = False
            message = _(
                "Company information saved successfully. "
                "Please follow the instructions sent to your email address.")

        company.save()
        if is_new:
            user_registered.send(sender=self.__class__,
                                 user=self.request.user,
                                 request=self.request)
            CompanyAccountCreated(contact=company,
                                  customer_email=company.email).run()

        messages.success(self.request, message)
        return redirect("shuup:company_edit")
Beispiel #45
0
    def has_permission(self, request, view):
        try:
            permission = int(configuration.get(None, make_permission_config_key(view), DEFAULT_PERMISSION))
        except ValueError:
            permission = DEFAULT_PERMISSION

        # god mode - just works if API is not disabled
        if request.user.is_superuser:
            return (permission <= PermissionLevel.ADMIN)

        # safe requests: GET, HEAD, OPTIONS
        if request.method in permissions.SAFE_METHODS:
            # to READ, the permissions can be WRITE or READ
            return ((request.user.is_authenticated() and permission <= PermissionLevel.AUTHENTICATED_WRITE) or
                    permission <= PermissionLevel.PUBLIC_WRITE)

        # NOT safe: POST, PUT, DELETE
        else:
            # to change data, permission must be exactly WRITE
            if request.user.is_authenticated():
                return permission in (PermissionLevel.AUTHENTICATED_WRITE, PermissionLevel.PUBLIC_WRITE)
            return (permission == PermissionLevel.PUBLIC_WRITE)
Beispiel #46
0
    def __init__(self, **kwargs):
        super(APIPermissionForm, self).__init__(**kwargs)

        # create a choice field for each entry in the router
        # this way it will be easy to set permisions based on each viewset
        # but they must be beautifully configured with name and description
        # to become more presentable to the merchant
        for __, viewset, basename in api_urls.router.registry:
            viewset_instance = viewset()
            field_name = make_permission_config_key(viewset_instance)
            initial = configuration.get(None, field_name, DEFAULT_PERMISSION)

            if issubclass(viewset, PermissionHelperMixin):
                help_text = viewset.get_help_text()
            else:
                help_text = viewset_instance.get_view_description()

            self.fields[field_name] = forms.ChoiceField(
                label=(viewset_instance.get_view_name() or basename),
                help_text=help_text,
                initial=initial,
                required=False,
                choices=self.API_PERMISSION_CHOICES)
Beispiel #47
0
def test_form(rf, admin_user, default_shop):
    configuration.cache.clear()

    assert not configuration.get(default_shop, MC_API)
    assert not configuration.get(default_shop, MC_USERNAME)
    assert not configuration.get(default_shop, MC_LIST_ID)
    form = ConfigurationForm(shop=default_shop,
                             data={
                                 "api_key": MC_API_KEY,
                                 "list_id": MC_API_LIST_ID,
                                 "username": MC_API_USERNAME,
                             })
    form.full_clean()
    form.save()
    configuration.cache.clear()
    assert configuration.get(default_shop, MC_API) == MC_API_KEY
    assert configuration.get(default_shop, MC_USERNAME) == MC_API_USERNAME
    assert configuration.get(default_shop, MC_LIST_ID) == MC_API_LIST_ID
Beispiel #48
0
    def _handle_xtheme_save(self):
        svc_pk = config.get(self.shop, CONTENT_FOOTER_KEY)
        svc = SavedViewConfig.objects.filter(pk=svc_pk).first()
        theme = get_current_theme()

        if not svc and theme:
            context = {"shop": self.shop}
            rendered_content = template_loader.render_to_string(content_data.FOOTER_TEMPLATE, context).strip()
            layout = Layout(theme, "footer-bottom")
            # adds the footer template
            layout.begin_row()
            layout.begin_column({"md": 12})
            layout.add_plugin(SnippetsPlugin.identifier, {"in_place": rendered_content})

            svc = SavedViewConfig(
                theme_identifier=theme.identifier,
                view_name=XTHEME_GLOBAL_VIEW_NAME,
                status=SavedViewConfigStatus.CURRENT_DRAFT
            )
            svc.set_layout_data(layout.placeholder_name, layout)
            svc.save()
            svc.publish()

            config.set(self.shop, CONTENT_FOOTER_KEY, svc.pk)
Beispiel #49
0
 def set_configuration(self, request, menus):
     config_key = CUSTOM_ADMIN_MENU_USER_PREFIX.format(request.user.pk)
     configuration_object = configuration.get(None, config_key, {}) or {}
     configuration_object.update({get_language(): menus})
     configuration.set(None, config_key, configuration_object)
Beispiel #50
0
def get_configuration(shop=None, category=None):
    default_configuration = configuration.get(
        shop, FACETED_DEFAULT_CONF_KEY,
        settings.SHUUP_FRONT_DEFAULT_SORT_CONFIGURATION)
    return (configuration.get(None, _get_category_configuration_key(category))
            or default_configuration)
Beispiel #51
0
 def dispatch(self, request, *args, **kwargs):
     if not configuration.get(None, "allow_company_registration"):
         return HttpResponseNotFound()
     return super(CompanyRegistrationView, self).dispatch(request, *args, **kwargs)
Beispiel #52
0
 def language(self):
     if self._language is not None:
         return self._language
     return configuration.get(None, "default_contact_language",
                              settings.LANGUAGE_CODE)
Beispiel #53
0
def get_support_id(context):
    support_id = None
    if is_telemetry_enabled():
        support_id = configuration.get(None, "shuup_support_id")
    return support_id
Beispiel #54
0
def get_installed_carousel(shop):
    """ Returns the installed sample carousel """
    return configuration.get(shop, SAMPLE_CAROUSEL_KEY)
Beispiel #55
0
 def set_configuration(self, request, menus):
     configuration_object = configuration.get(
         None, CUSTOM_ADMIN_MENU_SUPERUSER_KEY, {}) or {}
     configuration_object.update({get_language(): menus})
     configuration.set(None, CUSTOM_ADMIN_MENU_SUPERUSER_KEY,
                       configuration_object)
Beispiel #56
0
def customize_menu(entries, user):  # noqa (C901)
    """
    Merge system menu with customized admin menu
    """
    customized_admin_menu = configuration.get(None, "admin_menu_user_{}".format(user.pk))
    if customized_admin_menu:

        def unset_mismatched(menu):
            """
            find and remove unmatched entries from customized menu tree
            it can be when menu entry was removed from system
            """
            indexes = []
            for index, entry in enumerate(menu.get('entries', [])):
                unset_mismatched(entry)
                if isinstance(entry, dict):
                    indexes.append(index)
            for index in indexes[::-1]:
                del menu['entries'][index]

        def find_entry(menu, entry):
            """
            find recursively entry in menu
            """
            if menu['id'] == entry.id:
                return menu
            for node in menu.get('entries', []):
                n = find_entry(node, entry)
                if n:
                    return n

        def assign_entry(customized_menu, entry):
            """
            Find and replace customized entry with system menu entry
            set entry name, hidden flag from customized menu entry
            """
            custom_entries = customized_menu.get('entries', [])
            for index, node in enumerate(custom_entries):
                if node['id'] == entry.id:
                    custom_entry = custom_entries[index]
                    entry.name = custom_entry['name']
                    entry.is_hidden = custom_entry['is_hidden']
                    entry.entries = custom_entry.get('entries', [])
                    entry.ordering = index
                    custom_entries[index] = entry
                    return custom_entries[index]
                else:
                    return_entry = assign_entry(custom_entries[index], entry)
                    if return_entry:
                        return return_entry

        def transform_menu(customized_menu, menu):
            """
            Recursively sort system menu entries and assign it to the customized menu
            """
            indexes = []
            for index, entry in enumerate(menu.entries):
                transform_menu(customized_menu, entry)
                custom_entry = assign_entry(customized_menu, entry)
                if not custom_entry:
                    parent_menu = find_entry(customized_menu, menu)
                    if parent_menu:
                        parent_menu.get('entries', []).append(entry)
                        indexes.append(index)
                else:
                    indexes.append(index)
            # remove assigned entries from system menu
            for index in indexes[::-1]:
                del menu.entries[index]
            return menu

        customized_menu = {
            'id': 'root',
            'name': 'root',
            'entries': customized_admin_menu,
        }
        system_menu = BaseMenuEntry()
        system_menu.identifier = 'root'
        system_menu.entries = entries
        transform_menu(customized_menu, system_menu)
        unset_mismatched(customized_menu)

        return customized_menu['entries'] + system_menu['entries']
    else:
        return entries
Beispiel #57
0
def get_permissions_from_group(group):
    group_id = (group if isinstance(group, six.integer_types) else group.pk)
    return set(
        configuration.get(None,
                          _get_permission_key_for_group(group_id),
                          default=[]))
Beispiel #58
0
def get_installed_products(shop):
    """ Returns the installed products samples list """
    return configuration.get(shop, SAMPLE_PRODUCTS_KEY) or []
Beispiel #59
0
 def visible(self):
     return not configuration.get(None, "sample_data_wizard_completed",
                                  False)
Beispiel #60
0
def get_installed_categories(shop):
    """ Returns the installed categories samples list """
    return configuration.get(shop, SAMPLE_CATEGORIES_KEY) or []