def get_form_parts(self, object): form_parts = super(ServiceEditView, self).get_form_parts(object) if not object.pk: return form_parts for form in get_provide_objects(self.form_provide_key): form_parts.append(self._get_behavior_form_part(form, object)) for form_class in get_provide_objects(self.form_part_provide_key): form_parts.append(form_class(self.request, object)) return form_parts
def _get_mass_actions(self): mass_actions = self.mass_actions[:] # copy # add mass actions from the view mass action provider if getattr(self, "mass_actions_provider_key", None): for mass_action_provider in get_provide_objects(self.mass_actions_provider_key): mass_actions.extend(list(mass_action_provider.get_mass_actions_for_view(self))) # add mass actions from the global mass action provider for mass_action_provider in get_provide_objects("admin_mass_actions_provider"): mass_actions.extend(list(mass_action_provider.get_mass_actions_for_view(self))) return mass_actions
def for_view(cls, view): toolbar = cls() # add buttons from the view toolbar button provider if getattr(view, "toolbar_buttons_provider_key", None): for toolbar_buttons_provider in get_provide_objects(view.toolbar_buttons_provider_key): toolbar.extend(list(toolbar_buttons_provider.get_buttons_for_view(view))) # add buttons from the global toolbar button provider for admin_toolbar_button_provider in get_provide_objects("admin_toolbar_button_provider"): toolbar.extend(list(admin_toolbar_button_provider.get_buttons_for_view(view))) return toolbar
def get_form_parts(self, object): form_parts = super(CampaignEditView, self).get_form_parts(object) if not object.pk: return form_parts for form in get_provide_objects(self.condition_key): form_parts.append(self._get_rules_form_part(form, object)) for provide_key, form_part_class in self.effects: for form in get_provide_objects(provide_key): form_parts.append(self._get_effects_form_part(form, object, form_part_class)) return form_parts
def get_context_data(self, **kwargs): context = super(ThemeConfigView, self).get_context_data(**kwargs) context["theme_classes"] = sorted( [t for t in get_provide_objects("xtheme") if t.identifier], key=lambda t: (t.name or t.identifier) ) context["current_theme"] = get_current_theme() return context
def _build_provided_toolbar_buttons(self): for button in get_provide_objects("admin_order_toolbar_button"): warnings.warn( "admin_order_toolbar_button provider is deprecated, use admin_order_toolbar_action_item instead", DeprecationWarning, ) self.append(button(self.order))
def _postprocess(self, context, content): for inject_func in get_provide_objects("xtheme_resource_injection"): if callable(inject_func): inject_func(context, content) add_edit_resources(context) content = inject_resources(context, content) return content
def form_valid(self, form): product_ids_to_quantities = dict( (int(key.replace("q_", "")), value) for (key, value) in six.iteritems(form.cleaned_data) if key.startswith("q_") and value > 0 ) order = self.object product_map = Product.objects.in_bulk(set(product_ids_to_quantities.keys())) products_to_quantities = dict( (product_map[product_id], quantity) for (product_id, quantity) in six.iteritems(product_ids_to_quantities) ) unsaved_shipment = Shipment(order=order, supplier=form.cleaned_data["supplier"]) for extend_class in get_provide_objects(FORM_MODIFIER_PROVIDER_KEY): extend_class().form_valid_hook(form, unsaved_shipment) try: shipment = order.create_shipment( product_quantities=products_to_quantities, shipment=unsaved_shipment ) except NoProductsToShipException: messages.error(self.request, _("No products to ship.")) return self.form_invalid(form) else: messages.success(self.request, _("Shipment %s created.") % shipment.id) return HttpResponseRedirect(get_model_url(order))
def get_form(self, form_class=None): form_classes = list(get_provide_objects(self.form_provide_key)) form_infos = _FormInfoMap(form_classes) if self.object and self.object.pk: return self._get_concrete_form(form_infos) else: return self._get_type_choice_form(form_infos)
def _build_action_menu(self, product): # cross selling cross_sell_button = DropdownItem( text=_("Manage Cross-Selling"), icon="fa fa-random", url=reverse("shuup_admin:shop_product.edit_cross_sell", kwargs={"pk": product.pk}) ) menu_items = [menu_item for menu_item in self._get_header_items( header=_("Cross-Selling"), divider=False, identifier=ProductActionCategory.CHILD_CROSS_SELL)] menu_items.append(cross_sell_button) # packages for item in self._get_variation_and_package_menu_items(product): menu_items.append(item) provided_items = get_provide_objects("admin_product_toolbar_action_item") if provided_items: for item in self._get_header_items(header=_("Other"), identifier=ProductActionCategory.CHILD_OTHER): menu_items.append(item) for button in provided_items: if button.visible_for_object(product): menu_items.append(button(product)) # add the actual Action button self.append(DropdownActionButton( menu_items, icon="fa fa-star", text=_(u"Actions"), extra_css_class="btn-inverse btn-actions", identifier=ProductActionCategory.MAIN ))
def process_payment_return_request(self, service, order, request): if not order.is_paid(): stripe_chargers = get_provide_objects("stripe_charger") for stripe_charger in stripe_chargers: if stripe_charger.identifier == service.choice_identifier: charger = stripe_charger(order=order, secret_key=self.secret_key) charger.create_charge()
def get_menu_items(self): items = [] for cls in get_provide_objects("customer_dashboard_items"): c = cls(self.request) if c.show_on_menu(): items.append(c) return items
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 __init__(self, *args, **kwargs): self.request = kwargs.pop("request") super(SnippetForm, self).__init__(*args, **kwargs) themes_choices = [ (theme.identifier, theme.name) for theme in get_provide_objects("xtheme") if theme.identifier ] self.fields["themes"] = forms.MultipleChoiceField( choices=themes_choices, required=False, help_text=_( "Select the themes that will have this snippet injected. Leave the field blank to inject in all themes." ) ) from shuup.xtheme.resources import LOCATION_INFO location_choices = [ (location_name, location["name"]) for location_name, location in LOCATION_INFO.items() ] self.fields["location"] = forms.ChoiceField( choices=location_choices, help_text=_("Select the location of the page to inject the snippet.") )
def __init__(self, *args, **kwargs): super(EmailAuthenticationForm, self).__init__(*args, **kwargs) self.fields['username'].label = _("Username or email address") for provider_cls in get_provide_objects("front_auth_form_field_provider"): provider = provider_cls() for definition in provider.get_fields(request=self.request): self.fields[definition.name] = definition.field
def _add_provided_columns(self, columns, identifier, known_names, model): provide_object_key = "provided_columns_%s" % model.__name__ for provided_column_object in get_provide_objects(provide_object_key): obj = provided_column_object() column = obj.get_column(model, known_names, identifier) if column: columns.append(column)
def _build_existing_product(self): product = self.product # :type product: shuup.core.models.Product save_as_copy_button = JavaScriptActionButton( onclick="saveAsACopy()", text=_("Save as a copy"), icon="fa fa-clone", ) self.append(save_as_copy_button) cross_sell_button = DropdownItem( text=_("Manage Cross-Selling"), icon="fa fa-random", url=reverse("shuup_admin:shop_product.edit_cross_sell", kwargs={"pk": product.pk}), ) menu_items = [ DropdownHeader(text=_("Cross-Selling")), cross_sell_button ] for item in self._get_variation_and_package_menu_items(product): menu_items.append(item) for button in get_provide_objects("admin_product_toolbar_action_item"): if button.visible_for_object(product): menu_items.append(button(product)) if menu_items: self.append(DropdownActionButton( menu_items, icon="fa fa-star", text=_(u"Actions"), extra_css_class="btn-info", ))
def search_from_provided_contexts(self, object): provide_object_key = "provided_columns_%s" % type(object).__name__ for provided_column_object in get_provide_objects(provide_object_key): obj = provided_column_object() display_callable = maybe_callable(self.display, context=obj) if display_callable: return display_callable(object)
def get_context_data(self, **kwargs): context = super(ProductEditView, self).get_context_data(**kwargs) orderability_errors = [] if self.object.pk: for shop in Shop.objects.all(): try: shop_product = self.object.get_shop_instance(shop) 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("product") 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): context["product_sections"].append(admin_product_section) context[admin_product_section.identifier] = admin_product_section.get_context_data(self.object) return context
def get_matching_for_product(shop_product, provide_category, skippable_classes=None): """ Get matching ids for shop product based on provide category For example: matching_ids = get_matching_for_product(shop_product, "campaign_catalog_filter") :param shop_product: A Shop Product :type shop_product: shuup.core.models.ShopProduct :param provide_category: Provide category name :type provide_category: str :param skip: Classes to skip :type skip: None or list :return: list of collected item ids :rtype: list[int] """ collected = set() matcher = ProductCampaignMatcher(shop_product) for item in get_provide_objects(provide_category): if skippable_classes: objects = item._meta.model.objects.not_instance_of(*skippable_classes).all() else: objects = item._meta.model.objects.all() for obj in objects: if matcher.matches(obj): collected.add(obj.pk) return collected
def get_theme_context(): return { "theme_classes": sorted( [t for t in get_provide_objects("xtheme") if t.identifier], key=lambda t: (t.name or t.identifier) ), "current_theme": get_current_theme() }
def _get_service_provider_form_defs(self): form_defs = [] for form_def in get_provide_objects(self.form_def_provide_key): inst = form_def() if inst.visible(): form_defs.append(inst) form_defs.sort(key=lambda form_def: getattr(form_def, "priority", 0)) return form_defs
def __init__(self, *args, **kwargs): self.request = kwargs.pop("request") super(PersonRegistrationForm, self).__init__(*args, **kwargs) for provider_cls in get_provide_objects("front_registration_field_provider"): provider = provider_cls() for definition in provider.get_fields(request=self.request): self.fields[definition.name] = definition.field
def __init__(self, **kwargs): self.shop = kwargs.pop("shop") self.request = kwargs.pop("request") super(CompanyAgreementForm, self).__init__(**kwargs) for provider_cls in get_provide_objects("front_registration_field_provider"): provider = provider_cls() for definition in provider.get_fields(request=self.request): self.fields[definition.name] = definition.field
def form_valid_hook(self, form, object): has_extension_errors = False for extend_class in get_provide_objects(form.form_modifier_provide_key): try: extend_class().form_valid_hook(form, object) except Problem as problem: has_extension_errors = True messages.error(self.request, problem) return has_extension_errors
def get_context_data(cls, order, request=None): provided_information = [] for provided_info in sorted(get_provide_objects("admin_order_information"), key=lambda x: x.order): info = provided_info(order) if info.provides_info(): provided_information.append((info.title, info.information)) return { "provided_information": provided_information }
def get_form_parts(self, object): form_parts = super(CatalogCampaignEditView, self).get_form_parts(object) if not object.pk: return form_parts for form in get_provide_objects(self.filter_key): form_parts.append(self._get_filters_form_part(form, object)) return form_parts
def build_provides_buttons(self): action_menu_items = [] for button in get_provide_objects("admin_contact_toolbar_action_item"): if button.visible_for_object(self.contact): action_menu_items.append(button(object=self.contact)) if action_menu_items: self.append( DropdownActionButton( action_menu_items, icon="fa fa-star", text=_("Actions"), extra_css_class="btn-info" ) ) for button in get_provide_objects("admin_contact_toolbar_button"): warnings.warn( "admin_contact_toolbar_button provider is deprecated, use admin_contact_toolbar_action_item instead", DeprecationWarning, ) self.append(button(self.contact))
def test_provides(): IDENTIFIED_OBJECT_SPEC = "%s:IdentifiedObject" % __name__ category = str(uuid.uuid4()) with override_provides(category, [ IDENTIFIED_OBJECT_SPEC, "%s:UnidentifiedObject" % __name__, "%s:VeryUnidentifiedObject" % __name__, ]): objects = get_provide_objects(category) assert set(objects) == set((IdentifiedObject, UnidentifiedObject, VeryUnidentifiedObject)) assert get_identifier_to_object_map(category)["identifier"] == IdentifiedObject assert get_identifier_to_spec_map(category)["identifier"] == IDENTIFIED_OBJECT_SPEC assert get_provide_specs_and_objects(category)[IDENTIFIED_OBJECT_SPEC] == IdentifiedObject # Test the context manager clears things correctly assert empty_iterable(get_provide_objects(category)) assert empty_iterable(get_provide_specs_and_objects(category)) assert empty_iterable(get_identifier_to_object_map(category)) assert empty_iterable(get_identifier_to_spec_map(category))
def get_toolbar(self): toolbar = get_default_edit_toolbar( self, self.get_save_form_id(), discard_url=(get_model_url(self.object) if self.object.pk else None) ) for button in get_provide_objects("admin_contact_edit_toolbar_button"): toolbar.append(button(self.object)) return toolbar
def get_service_choices(self): stripe_chargers = get_provide_objects("stripe_charger") return [ ServiceChoice(stripe_charger.identifier, stripe_charger.name) for stripe_charger in stripe_chargers ]
def get_report_classes(): items = {} for cls in list(get_provide_objects("reports")): items[cls.get_name()] = cls return OrderedDict(sorted(items.items(), key=lambda t: t[1].title))
def get_settings(request): admin_settings = {} for admin_browser_config_provider in get_provide_objects("admin_browser_config_provider"): admin_settings.update(admin_browser_config_provider.get_gettings(request)) return admin_settings
def get_form_part_classes(self): form_part_classes = ( list(self.base_form_part_classes) + list(get_provide_objects(self.form_part_class_provide_key))) return form_part_classes
def discover(): for obj in get_provide_objects("admin_module"): register(obj)
def get_importer(identifier): for i in get_provide_objects("importers"): if i.identifier == identifier: return i return None
def extend_main_menu(menu): for menu_updater in get_provide_objects("admin_main_menu_updater"): menu = menu_updater(menu).update() return menu
def get_extra_permissions(self): return [importer.get_permission_identifier() for importer in get_provide_objects("importers")]
def get_provided_layouts(): return get_provide_objects("xtheme_layout")
def get_setting(cls, setting_key): for provider_cls in get_provide_objects("shuup_settings_provider"): provider = provider_cls() if provider.offers(setting_key): return provider.get_setting_value(setting_key) return getattr(settings, setting_key)
def clean(self): cleaned_data = super(ProductListForm, self).clean() for extend_class in get_provide_objects(FORM_MODIFIER_PROVIDER_KEY): extend_class().clean_hook(self) return cleaned_data
def _build_provided_toolbar_buttons(self): for button in get_provide_objects("admin_order_toolbar_button"): warnings.warn( "admin_order_toolbar_button provider is deprecated, use admin_order_toolbar_action_item instead", RemovedFromShuupWarning) self.append(button(self.order))
def populate(self): for func in get_provide_objects("api_populator"): func(router=self)
def get_validation_errors(self): # noqa (C901) from shuup.apps.provides import get_provide_objects for order_source_validator in get_provide_objects("order_source_validator"): for error in order_source_validator.get_validation_errors(self): yield error
def clean(self): cleaned_data = super(ModifiableFormMixin, self).clean() for extend_class in get_provide_objects( self.form_modifier_provide_key): extend_class().clean_hook(self) return cleaned_data
def add_extra_fields(self, form, object=None): for extend_class in get_provide_objects( form.form_modifier_provide_key): for field_key, field in extend_class().get_extra_fields( object) or []: form.fields[field_key] = field
def _get_service_provider_form_defs(self): form_defs = [] for form_def in get_provide_objects(self.form_def_provide_key): form_defs.append(form_def()) form_defs.sort(key=lambda form_def: getattr(form_def, "priority", 0)) return form_defs
def _get_order_form(request, context, product, language): for obj in get_provide_objects("front_product_order_form"): product_order_form = obj(request, context, product, language) if product_order_form.is_compatible(): return mark_safe(product_order_form.render()) return None
def get_toolbar(self): order = self.object toolbar = Toolbar() action_menu_items = [] if not (order.is_paid() or order.is_canceled() or order.has_refunds()): action_menu_items.append( DropdownItem( url=reverse("shuup_admin:order.create-payment", kwargs={"pk": order.pk}), icon="fa fa-money", text=_("Create Payment"), ) ) if (order.get_unshipped_products() and not order.is_canceled() and not order.has_refunds()): action_menu_items.append( DropdownItem( url=reverse("shuup_admin:order.create-shipment", kwargs={"pk": order.pk}), icon="fa fa-truck", text=_("Create Shipment"), ) ) if order.can_create_refund() and order.payments.exists(): action_menu_items.append( DropdownItem( url=reverse("shuup_admin:order.create-refund", kwargs={"pk": order.pk}), icon="fa fa-dollar", text=_("Create Refund"), ) ) toolbar.append( DropdownActionButton( action_menu_items, icon="fa fa-star", text=_(u"Actions"), extra_css_class="btn-info", ) ) toolbar.append(PostActionButton( post_url=reverse("shuup_admin:order.set-status", kwargs={"pk": order.pk}), name="status", value=OrderStatus.objects.get_default_complete().pk, text=_("Set Complete"), icon="fa fa-check-circle", disable_reason=( _("This order can not be set as complete at this point") if not order.can_set_complete() else None ), extra_css_class="btn-success" )) toolbar.append(PostActionButton( post_url=reverse("shuup_admin:order.set-status", kwargs={"pk": order.pk}), name="status", value=OrderStatus.objects.get_default_canceled().pk, text=_("Cancel Order"), icon="fa fa-trash", disable_reason=( _("Paid, shipped, or canceled orders cannot be canceled") if not order.can_set_canceled() else None ), extra_css_class="btn-danger btn-inverse" )) toolbar.append(URLActionButton( text=_("Edit order"), icon="fa fa-money", disable_reason=_("This order cannot modified at this point") if not order.can_edit() else None, url=reverse("shuup_admin:order.edit", kwargs={"pk": order.pk}), extra_css_class="btn-info" )) for button in get_provide_objects("admin_order_toolbar_button"): toolbar.append(button(order)) return toolbar
def get_product_context(request, product, language=None, supplier=None): # noqa (C901) """ Get product context. Used in `shuup.front.views.product:ProductDetailView`. :return: A context dict containing everything needed to render product view. :rtype: dict """ if not language: language = get_language() shop_product = product.get_shop_instance(request.shop) context = {} context["product"] = product context["category"] = shop_product.primary_category context["orderability_errors"] = list(shop_product.get_orderability_errors( supplier=supplier, quantity=1, customer=request.customer, ignore_minimum=True)) context["variation_children"] = [] selected_variation = None variation_sku = request.GET.get("variation") if variation_sku: try: selected_variation = product.variation_children.get(sku=variation_sku) context["selected_variation"] = selected_variation except Product.DoesNotExist: raise Http404 if product.mode == ProductMode.SIMPLE_VARIATION_PARENT: context["variation_children"] = cache_product_things( request, sorted( product.variation_children.language(language).visible( shop=request.shop, customer=request.customer ), key=lambda p: get_string_sort_order(p.variation_name or p.name) ) ) context["orderable_variation_children"] = [] for p in context["variation_children"]: try: if p.get_shop_instance(request.shop).is_orderable( supplier=supplier, customer=request.customer, quantity=1): context["orderable_variation_children"].append(p) except ShopProduct.DoesNotExist: pass elif product.mode == ProductMode.VARIABLE_VARIATION_PARENT: variation_variables = product.variation_variables.all().prefetch_related("values") orderable_children, is_orderable = get_orderable_variation_children( product, request, variation_variables, supplier ) context["orderable_variation_children"] = orderable_children context["variation_orderable"] = is_orderable context["variation_variables"] = variation_variables if selected_variation: for combination in product.get_all_available_combinations(): if combination['result_product_pk'] == selected_variation.pk: values = [v.pk for v in combination['variable_to_value'].values()] context['selected_variation_values'] = values break elif product.is_container(): children = product.get_all_package_children().translated().order_by("translations__name") context["package_children"] = cache_product_things(request, children) context["shop_product"] = shop_product context["attributes"] = product.attributes.filter( attribute__visibility_mode=AttributeVisibility.SHOW_ON_PRODUCT_PAGE) context["primary_image"] = shop_product.public_primary_image context["images"] = shop_product.public_images context["supplier"] = supplier context["order_form"] = _get_order_form(request, context, product, language) for provide_object in get_provide_objects("product_context_extra"): provider = provide_object(request, product, language) if provider.provides_extra_context(): context.update(provider.extra_context) return context
def populate(self): """ Iterate over all report_writer_populator provides to fill/update the report writer map """ for report_writer_populator_func in get_provide_objects("report_writer_populator"): report_writer_populator_func(self)
def get_name_map(category_key): return sorted( [(force_text(obj.identifier), force_text(obj.name)) for obj in get_provide_objects(category_key) if obj.identifier], key=lambda t: t[1].lower(), )
def __init__(self, *args, **kwargs): super(ConfigurationForm, self).__init__(*args, **kwargs) for extend_class in get_provide_objects(FORM_MODIFIER_PROVIDER_KEY) or []: for field_key, field in extend_class().get_admin_fields() or []: self.fields[field_key] = field
def get_importer_choices(): return [(i.identifier, i.name) for i in get_provide_objects("importers")]
def get_report_classes(request=None, provides_key="reports"): items = {} for cls in list(get_provide_objects(provides_key)): if not (request and not cls.is_available(request)): items[cls.get_name()] = cls return OrderedDict(sorted(items.items(), key=lambda t: t[1].title))
def get_themes(self, value): return ", ".join([ force_text(theme.name) for theme in get_provide_objects("xtheme") if theme.identifier in value.themes ])
def _get_extension_urlpatterns(provide_category): return chain(*get_provide_objects(provide_category))
def ensure_all_supplier_modules(cls): from shuup.apps.provides import get_provide_objects for module in get_provide_objects(Supplier.module_provides_key): cls.objects.update_or_create(module_identifier=module.identifier, defaults={"name": module.name})