def test_contact_company_list_multishop(rf): with override_settings(E-Commerce_MANAGE_CONTACTS_PER_SHOP=True, E-Commerce_ENABLE_MULTIPLE_SHOPS=True): staff_user = create_random_user(is_staff=True) shop1 = get_shop(identifier="shop-1", enabled=True) shop2 = get_shop(identifier="shop-2", enabled=True) shop1.staff_members.add(staff_user) shop2.staff_members.add(staff_user) # only available in shop2 contact = create_random_person(locale="en_US", minimum_name_comp_len=5, shop=shop2) # only available in shop1 company = create_random_company() company.add_to_shop(shop1) view = ContactListView() request = apply_request_middleware(rf.get("/"), user=staff_user, shop=shop1) view.request = request assert company in view.get_queryset() assert contact not in view.get_queryset() request = apply_request_middleware(rf.get("/"), user=staff_user, shop=shop2) view.request = request assert contact in view.get_queryset() assert company not in view.get_queryset()
def test_contact_edit_multishop(rf): with override_settings(E-Commerce_MANAGE_CONTACTS_PER_SHOP=True, E-Commerce_ENABLE_MULTIPLE_SHOPS=True): staff_user = create_random_user(is_staff=True) shop1 = get_shop(identifier="shop-1", enabled=True) shop2 = get_shop(identifier="shop-2", enabled=True) shop1.staff_members.add(staff_user) shop2.staff_members.add(staff_user) contact = create_random_person(locale="en_US", minimum_name_comp_len=5, shop=shop2) # only available in shop2 assert contact.registered_in(shop2) assert contact.in_shop(shop2) request = apply_request_middleware(rf.get("/"), user=staff_user, shop=shop1) view = ContactDetailView.as_view() # contact not found for this shop with pytest.raises(Http404): response = view(request, pk=contact.id) request = apply_request_middleware(rf.get("/"), user=staff_user, shop=shop2) response = view(request, pk=contact.id) assert response.status_code == 200 assert contact.registered_in(shop2) assert contact.in_shop(shop2) assert not contact.registered_in(shop1) assert not contact.in_shop(shop1)
def test_get_shipments(admin_user): client = _get_client(admin_user) shop1 = get_shop(True) shop2 = get_shop(True) customer1 = create_random_person() customer2 = create_random_person() order1 = create_random_order(customer1, shop=shop1, completion_probability=1) order2 = create_random_order(customer2, shop=shop1, completion_probability=1) order3 = create_random_order(customer1, shop=shop2, completion_probability=1) order4 = create_random_order(customer2, shop=shop1, completion_probability=1) # list shipments response = client.get("/api/E-Commerce/shipment/") assert response.status_code == status.HTTP_200_OK shipment_data = json.loads(response.content.decode("utf-8")) assert len(shipment_data) == 4 assert shipment_data[0]["id"] == order1.shipments.first().pk assert shipment_data[1]["id"] == order2.shipments.first().pk assert shipment_data[2]["id"] == order3.shipments.first().pk assert shipment_data[3]["id"] == order4.shipments.first().pk # get shipment by id response = client.get("/api/E-Commerce/shipment/%s/" % order1.shipments.first().pk) assert response.status_code == status.HTTP_200_OK shipment_data = json.loads(response.content.decode("utf-8")) assert shipment_data["id"] == order1.shipments.first().pk assert shipment_data["order"] == order1.pk # get shipment by product product = order2.shipments.first().products.first() response = client.get("/api/E-Commerce/shipment/?product=%s" % product.pk) assert response.status_code == status.HTTP_200_OK shipment_data = json.loads(response.content.decode("utf-8")) for ship in shipment_data: for ship_product in shipment_data["product"]: assert ship_product["id"] == product.pk assert ship_product["order"] == order2.pk # get shipment by order response = client.get("/api/E-Commerce/shipment/?order=%s" % order3.pk) assert response.status_code == status.HTTP_200_OK shipment_data = json.loads(response.content.decode("utf-8")) for ship in shipment_data: assert ship["order"] == order3.pk # get shipment by shop response = client.get("/api/E-Commerce/shipment/?shop=%s" % shop1.pk) assert response.status_code == status.HTTP_200_OK shipment_data = json.loads(response.content.decode("utf-8")) for ship in shipment_data: assert Shipment.objects.filter(pk=ship["id"], order__shop=shop1).exists()
def get(self, request): # noqa (C901) model_name = request.GET.get("model") object_id = request.GET.get("pk", request.GET.get("id")) if not model_name or not object_id: return HttpResponseBadRequest(_("Invalid object.")) url = None try: model = apps.get_model(model_name) except LookupError: return HttpResponseBadRequest(_("Invalid model.")) instance = model.objects.filter(pk=object_id).first() if instance: try: # try edit first try: url = get_model_url( instance, kind="edit", user=request.user, shop=get_shop(request), raise_permission_denied=True ) except NoModelUrl: # try detail try: url = get_model_url( instance, kind="detail", user=request.user, shop=get_shop(request), raise_permission_denied=True ) except NoModelUrl: pass except PermissionDenied as exception: from django.utils.encoding import force_text raise Problem(force_text(exception)) if url: # forward the mode param if request.GET.get("mode"): url = "{}?mode={}".format(url, request.GET["mode"]) return HttpResponseRedirect(url) raise Http404(_("Object not found"))
def test_stacked_tax_taxful_price(): shop = get_shop(prices_include_tax=True, currency='EUR') source = OrderSource(shop) assert source.prices_include_tax source.add_line( type=OrderLineType.OTHER, quantity=1, base_unit_price=source.create_price(20) ) with override_provides("tax_module", TAX_MODULE_SPEC): with override_settings(E-Commerce_TAX_MODULE="irvine"): source.shipping_address = MutableAddress( street="16215 Alton Pkwy", postal_code="92602", ) line = source.get_final_lines(with_taxes=True)[0] assert isinstance(line, SourceLine) assert line.taxes assert line.taxful_price == TaxfulPrice(20, 'EUR') assert_almost_equal(line.taxless_price, TaxlessPrice("18.52", 'EUR')) source.uncache() # Let's move out to a taxless location. source.shipping_address.postal_code = "11111" line = source.get_final_lines(with_taxes=True)[0] assert isinstance(line, SourceLine) assert not line.taxes assert line.taxful_price == TaxfulPrice(20, source.currency) assert line.taxless_price.value == Decimal("20")
def test_editing_sales_ranges_multi_shop(rf, admin_user): default_shop = get_default_shop() another_shop = get_shop(prices_include_tax=True) another_shop.status = ShopStatus.ENABLED another_shop.save() group = get_default_customer_group() data = {} for shop in Shop.objects.all(): data.update(get_edit_view_data(shop, group, 0, 50)) assert ContactGroupSalesRange.objects.count() == 0 # To make this test work we need to mock members form_part since the extra # forms does not render correctly with patch.object(ContactGroupEditView, "base_form_part_classes", [ContactGroupBaseFormPart]): request = apply_request_middleware(rf.post("/", data=data), user=admin_user) view = ContactGroupEditView.as_view() response = view(request=request, pk=group.pk) if hasattr(response, "render"): response.render() assert response.status_code in [200, 302] # Even if the data is for both shops only the current shop takes # effect. From admin sales ranges can be only defined for the current # shop. assert ContactGroupSalesRange.objects.count() == 1 sales_range = ContactGroupSalesRange.objects.filter(group=group, shop=default_shop).first() assert sales_range.min_value == 0 assert sales_range.max_value == 50
def _get_source(user, shipping_country, billing_country): prices_include_taxes = True shop = get_shop(prices_include_taxes) payment_method = get_payment_method(shop) shipping_method = get_shipping_method(shop) source = _seed_source(shop, user, shipping_country, billing_country) source.payment_method = payment_method source.shipping_method = shipping_method assert source.payment_method_id == payment_method.id assert source.shipping_method_id == shipping_method.id supplier = get_default_supplier() product = create_product( sku="test-%s--%s" % (prices_include_taxes, 10), shop=source.shop, supplier=supplier, default_price=10 ) source.add_line( type=OrderLineType.PRODUCT, product=product, supplier=supplier, quantity=1, base_unit_price=source.create_price(10), ) assert payment_method == source.payment_method assert shipping_method == source.shipping_method return source
def save_form(self, form): self.object = form.save() contact = self._get_bind_contact() # only touch in shop staff member if the user is not a superuser if not getattr(self.object, "is_superuser", False): shop = get_shop(self.request) if getattr(self.object, "is_staff", False): shop.staff_members.add(self.object) else: shop.staff_members.remove(self.object) if contact and not contact.user: contact.user = self.object contact.save() messages.info(self.request, _(u"User bound to contact %(contact)s.") % {"contact": contact}) if getattr(self.object, "is_staff", False) and form.cleaned_data.get("send_confirmation"): shop_url = "%s://%s/" % (self.request.scheme, self.request.get_host()) admin_url = self.request.build_absolute_uri(reverse("E-Commerce_admin:login")) send_mail( subject=_("You've been added as an admin user to %s" % shop_url), message=NEW_USER_EMAIL_CONFIRMATION_TEMPLATE % { "first_name": getattr(self.object, "first_name") or getattr(self.object, "username", _("User")), "shop_url": shop_url, "admin_url": admin_url, "username": getattr(self.object, "username") or getattr(self.object.email) }, from_email=django_settings.DEFAULT_FROM_EMAIL, recipient_list=[self.object.email] )
def get_queryset(self): # get coupons for this shop or for shared shops queryset = super(CouponEditView, self).get_queryset().filter(shop=get_shop(self.request)) supplier = get_supplier(self.request) if supplier: queryset = queryset.filter(supplier=supplier) return queryset
def get_context_data(self, **kwargs): context = super(ProductEditView, self).get_context_data(**kwargs) orderability_errors = [] if self.object.pk: context["title"] = self.object.product.name shop = self.request.shop try: shop_product = self.object orderability_errors.extend( ["%s: %s" % (shop.name, msg.message) for msg in shop_product.get_orderability_errors( supplier=None, quantity=shop_product.minimum_purchase_quantity, customer=None)]) except ObjectDoesNotExist: orderability_errors.extend(["%s: %s" % (shop.name, _("Product is not available."))]) context["orderability_errors"] = orderability_errors context["product_sections"] = [] context["tour_key"] = "product" context["tour_complete"] = is_tour_complete(get_shop(self.request), "product", user=self.request.user) product_sections_provides = sorted(get_provide_objects("admin_product_section"), key=lambda x: x.order) for admin_product_section in product_sections_provides: if admin_product_section.visible_for_object(self.object.product, self.request): context["product_sections"].append(admin_product_section) context[admin_product_section.identifier] = admin_product_section.get_context_data( self.object.product, self.request ) return context
def is_url_valid(self, language_code, field_name, url): """ Ensure URL given is unique. Check through the pages translation model objects to make sure that the url given doesn't already exist. Possible failure cases: for new page: * URL already exists for existing page: * URL (other than owned by existing page) exists * URL exists in other languages of existing page """ pages_ids = Page.objects.for_shop(get_shop(self.request)).values_list("id", flat=True) qs = self._get_translation_model().objects.filter(url=url, master_id__in=pages_ids) if not self.instance.pk and qs.exists(): return False other_qs = qs.exclude(master=self.instance) if other_qs.exists(): return False own_qs = qs.filter(master=self.instance).exclude(language_code=language_code) if own_qs.exists(): return False return True
def test_module(address, expected_taxes): """ Test the DefaultTaxModule. """ # Create a product shop = get_shop(prices_include_tax=False, currency='USD') product = create_product('PROD', shop=shop, default_price=1000) price = product.get_shop_instance(shop).default_price # Put the tax rules into database for ruledef in shuffled(TAX_RULE_DEFS): rule = ruledef.get_tax_rule() rule.tax.save() rule.tax = rule.tax # refresh the id rule.save() rule.tax_classes.add(product.tax_class) assert TaxRule.objects.count() == len(TAX_RULE_DEFS) with override_settings(E-Commerce_TAX_MODULE='default_tax'): module = get_tax_module() assert isinstance(module, DefaultTaxModule) context = TaxingContext(location=address) taxed_price = module.get_taxed_price_for(context, product, price) expected_codes = set(sum([x.split() for x in expected_taxes], [])) assert set(x.tax.code for x in taxed_price.taxes) == expected_codes expected_tax = Money(TAX_AMOUNTS[expected_taxes], 'USD') assert taxed_price.taxful.amount == price.amount + expected_tax # Clean-up the rules TaxRule.objects.all().delete()
def model_url(context, model, kind="detail", default=None, **kwargs): """ Get a model URL of the given kind for a model (instance or class). :param context: Jinja rendering context :type context: jinja2.runtime.Context :param model: The model instance or class. :type model: django.db.Model :param kind: The URL kind to retrieve. See `get_model_url`. :type kind: str :param default: Default value to return if model URL retrieval fails. :type default: str :return: URL string. :rtype: str """ user = context.get("user") try: request = context.get("request") shop = get_shop(request) if request else None admin_model_url_resolvers = get_provide_objects("admin_model_url_resolver") for resolver in admin_model_url_resolvers: url = resolver(model, kind=kind, user=user, shop=shop, **kwargs) if url: return url except NoModelUrl: return default
def inject_global_snippet(context, content): if not valid_view(context): return from E-Commerce.xtheme import get_current_theme from E-Commerce.xtheme.models import Snippet, SnippetType shop = get_shop(context["request"]) cache_key = GLOBAL_SNIPPETS_CACHE_KEY.format(shop_id=shop.id) snippets = cache.get(cache_key) if snippets is None: snippets = Snippet.objects.filter(shop=shop) cache.set(cache_key, snippets) for snippet in snippets: if snippet.themes: current_theme = get_current_theme(shop) if current_theme and current_theme.identifier not in snippet.themes: continue content = snippet.snippet if snippet.snippet_type == SnippetType.InlineJS: content = InlineScriptResource(content) elif snippet.snippet_type == SnippetType.InlineCSS: content = InlineStyleResource(content) elif snippet.snippet_type == SnippetType.InlineHTMLMarkup: content = InlineMarkupResource(content) add_resource(context, snippet.location, content)
def handle_get_folder(self, data): shop = get_shop(self.request) try: folder_id = int(data.get("id", 0)) if folder_id: folder = _get_folder_query(shop).get(pk=folder_id) subfolders = folder.get_children().filter(_get_folder_query_filter(shop)) files = _get_file_query(shop, folder) else: folder = None subfolders = _get_folder_query(shop).filter(parent=None) files = _get_file_query(shop).filter(folder=None) except ObjectDoesNotExist: return JsonResponse({ "folder": None, "error": "Folder does not exist" }) if self.filter == "images": files = files.instance_of(Image) return JsonResponse({"folder": { "id": folder.id if folder else 0, "name": get_folder_name(folder), "files": [_filer_file_to_json_dict(file) for file in files if file.is_public], "folders": [ # Explicitly pass empty list of children to avoid recursion _filer_folder_to_json_dict(subfolder, children=()) for subfolder in subfolders.order_by("name") ] }})
def _get_source(user, prices_include_taxes, total_price_value): shop = get_shop(prices_include_taxes) payment_method = get_payment_method(shop) shipping_method = get_shipping_method(shop) source = _seed_source(shop, user) source.payment_method = payment_method source.shipping_method = shipping_method assert source.payment_method_id == payment_method.id assert source.shipping_method_id == shipping_method.id supplier = get_default_supplier() product = create_product( sku="test-%s--%s" % (prices_include_taxes, total_price_value), shop=source.shop, supplier=supplier, default_price=total_price_value ) source.add_line( type=OrderLineType.PRODUCT, product=product, supplier=supplier, quantity=1, base_unit_price=source.create_price(total_price_value), ) if prices_include_taxes: assert source.taxful_total_price.value == total_price_value else: assert source.taxless_total_price.value == total_price_value assert payment_method == source.payment_method assert shipping_method == source.shipping_method return source, shipping_method
def get_request_for_contact_tests(rf): activate("en") request = rf.get("/") request.shop = get_shop(prices_include_tax=True) get_payment_method(request.shop) apply_request_middleware(request) return request
def media_upload(request, *args, **kwargs): shop = get_shop(request) try: folder_id = int(request.POST.get("folder_id") or request.GET.get("folder_id") or 0) path = request.POST.get("path") or request.GET.get("path") or None if folder_id != 0: folder = _get_folder_query(shop).get(pk=folder_id) elif path: folder = get_or_create_folder(shop, path) else: folder = None # Root folder upload. How bold! except Exception as exc: return JsonResponse({"error": "Invalid folder: %s" % force_text(exc)}) try: upload_file = request.FILES["file"] if upload_file.content_type.startswith("image/"): filer_file = filer_image_from_upload(request, path=folder, upload_data=upload_file) else: filer_file = filer_file_from_upload(request, path=folder, upload_data=upload_file) _ensure_media_file(shop, filer_file) except Exception as exc: return JsonResponse({"error": force_text(exc)}) return JsonResponse({ "file": _filer_file_to_json_dict(filer_file), "message": _("%(file)s uploaded to %(folder)s") % { "file": filer_file.label, "folder": get_folder_name(folder) } })
def test_rules_with_disabled_tax(): """ Test whether rules match when tax is disabled """ tax_class = TaxClass.objects.create(name="test") # Create a product shop = get_shop(prices_include_tax=False, currency='USD') product = create_product('PROD', shop=shop, default_price=1000) product.tax_class = tax_class product.save() price = product.get_shop_instance(shop).default_price # create disabled tax tax = Tax.objects.create(code="any", rate=0.1, name="Tax for any customer", enabled=False) tax_rule = TaxRule.objects.create(tax=tax) tax_rule.tax_classes.add(tax_class) with override_settings(E-Commerce_TAX_MODULE='default_tax'): module = get_tax_module() assert isinstance(module, DefaultTaxModule) # 1) check the tax for anonymous anonymous_context = TaxingContext() taxed_price = module.get_taxed_price_for(anonymous_context, product, price) assert len(list(taxed_price.taxes)) == 0 # Clean-up the rules TaxRule.objects.all().delete()
def post(self, request): """ Create the Script from template directly if the template does not have a bound form. If the script template has a bound form, redirect to the template configuration view. If no script template is found, redirect to the script list. """ identifier = request.POST.get("id", None) script_template_class = get_identifier_to_object_map(SCRIPT_TEMPLATES_PROVIDE_CATEGORY).get(identifier) if script_template_class: script_template = script_template_class() # the template has a form for configuration.. lets redirect to the correct view if script_template.get_form(): return redirect("E-Commerce_admin:notify.script-template-config", id=identifier) else: shop = get_shop(request) script = script_template.create_script(shop) if script: script.template = identifier script.save(update_fields=["template"]) messages.success(request, _("Script created from template!")) return redirect("E-Commerce_admin:notify.script.list") else: messages.error(request, _("Template Script not found!")) return redirect("E-Commerce_admin:notify.script.list")
def save(self, commit=True): if not self.instance.pk: self.instance.is_active = True obj = super(ContactBaseFormMixin, self).save(commit) shop = get_shop(self.request) obj.groups = [obj.get_default_group()] + list(self.cleaned_data["groups"]) obj.add_to_shops(shop, list(self.cleaned_data["shops"])) return obj
def get_queryset(self, *args, **kwargs): queryset = Supplier.objects.filter(shops=get_shop(self.request)).not_deleted() supplier = get_supplier(self.request) if supplier: # If admin has supplier enabled allow only delete self # althought not good view to enable for vendor queryset = queryset.filter(id=supplier.pk) return queryset
def get_context_data(self, **kwargs): context = super(CategoryEditView, self).get_context_data(**kwargs) context["tour_key"] = "category" context["tour_complete"] = is_tour_complete(get_shop(self.request), "category", user=self.request.user) if self.object.pk: context["title"] = self.object.name return context
def test_page_different_shops(rf): shop1 = get_shop(status=ShopStatus.ENABLED, identifier="shop-1", name="Shop 1", domain="shop1") shop2 = get_shop(status=ShopStatus.ENABLED, identifier="shop-2", name="Shop 2", domain="shop2") # dreate page only for shop2 page = create_page(available_from=datetime.date(1988, 1, 1), shop=shop2) view_func = PageView.as_view() request = apply_request_middleware(rf.get("/", HTTP_HOST=shop1.domain)) with pytest.raises(Http404): response = view_func(request, url=page.url) request = apply_request_middleware(rf.get("/", HTTP_HOST=shop2.domain)) response = view_func(request, url=page.url) assert response.status_code == 200 response.render() assert "<h1>Bacon ipsum" in response.rendered_content
def __init__(self, **kwargs): self.request = kwargs.pop("request") super(GDPRSettingsForm, self).__init__(**kwargs) shop = get_shop(self.request) choices = [(p.id, p.title) for p in get_possible_consent_pages(shop)] self.fields["privacy_policy_page"].choices = choices self.fields["consent_pages"].required = False self.fields["consent_pages"].choices = choices
def get_queryset(self): """ Ignore potentially active carts, displaying only those not updated for at least 2 hours. """ shop = get_shop(self.request) cutoff = now() - datetime.timedelta(hours=get_cart_delay_hours(shop)) filters = {"updated_on__lt": cutoff, "product_count__gte": 0, "persistent": False, "shop": shop} return super(CartListView, self).get_queryset().filter(**filters)
def get_queryset(self, *args, **kwargs): queryset = super(PageDeleteView, self).get_queryset() queryset = queryset.for_shop(get_shop(self.request)).not_deleted() supplier = get_supplier(self.request) if supplier: queryset = queryset.filter(supplier=supplier) return queryset
def save(self, commit=True): instance = super(SupplierBaseForm, self).save(commit) instance.shop_products.remove( *list(instance.shop_products.exclude(shop_id__in=instance.shops.all()).values_list("pk", flat=True))) if not settings.E-Commerce_ENABLE_MULTIPLE_SUPPLIERS or "shops" not in self.fields: instance.shops.add(get_shop(self.request)) return instance
def get_queryset(self): queryset = Contact.objects.all() limited = (settings.E-Commerce_ENABLE_MULTIPLE_SHOPS and settings.E-Commerce_MANAGE_CONTACTS_PER_SHOP and not self.request.user.is_superuser) if limited: queryset = queryset.filter(shops=get_shop(self.request)) return queryset
def get_queryset(self): queryset = super(CouponListView, self).get_queryset() if not self.request.user.is_superuser: queryset = queryset.filter(shop=get_shop(self.request)) supplier = get_supplier(self.request) if supplier: queryset = queryset.filter(supplier=supplier) return queryset