def get_pico(rf, admin_user, model=None, columns=None): shop = get_default_shop() model = model or get_user_model() columns = columns or [ Column("id", "Id", filter_config=Filter(), display=instance_id), Column("username", "Username", sortable=False, filter_config=MultiFieldTextFilter( filter_fields=("username", "email"), operator="iregex")), Column("email", "Email", sortable=False, filter_config=TextFilter()), Column("is_superuser", "Is Superuser", display="superuser_display", filter_config=ChoicesFilter(choices=false_and_true())), Column("is_active", "Is Active", filter_config=ChoicesFilter( choices=false_and_true)), # `choices` callable Column("date_joined", "Date Joined", filter_config=DateRangeFilter()) ] admin_user.is_staff = True admin_user.save() shop.staff_members.add(admin_user) request = apply_request_middleware(rf.get("/"), user=admin_user) return Picotable(request=request, columns=columns, mass_actions=[], queryset=model.objects.all(), context=PicoContext(request))
class CategoryListView(PicotableListView): model = Category columns = [ Column("name", _(u"Name"), sort_field="translations__name", display="name", linked=True, filter_config=TextFilter(filter_field="translations__name", placeholder=_("Filter by name..."))), Column("status", _(u"Status"), filter_config=ChoicesFilter(choices=CategoryStatus.choices)), Column( "visibility", _(u"Visibility"), filter_config=ChoicesFilter(choices=CategoryVisibility.choices)), Column("parent", _(u"Parent"), sortable=False, display="parent"), ] def get_queryset(self): return Category.objects.all_except_deleted() def get_object_abstract(self, instance, item): return [{ "text": "%s" % instance, "class": "header" }, { "title": _(u"Status"), "text": item["status"] }, { "title": _(u"Parent"), "text": item["parent"] } if instance.parent_id else None]
class OrderStatusListView(PicotableListView): model = OrderStatus default_columns = [ Column("identifier", _("Identifier"), linked=True, filter_config=TextFilter(operator="startswith")), Column("name", _("Name"), linked=True, filter_config=TextFilter(operator="startswith", filter_field="translations__name")), Column("public_name", _("Public Name"), linked=False, filter_config=TextFilter(operator="startswith", filter_field="translations__name")), Column("role", _("Role"), linked=False, filter_config=ChoicesFilter(choices=OrderStatusRole.choices)), Column("default", _("Default"), linked=False, filter_config=ChoicesFilter([(False, _("yes")), (True, _("no"))])), Column("is_active", _("Active"), linked=False, filter_config=ChoicesFilter([(False, _("yes")), (True, _("no"))])), ]
def get_pico(rf, model=None, columns=None): model = model or get_user_model() columns = columns or [ Column("id", "Id", filter_config=Filter(), display=instance_id), Column("username", "Username", sortable=False, filter_config=MultiFieldTextFilter( filter_fields=("username", "email"), operator="iregex")), Column("email", "Email", sortable=False, filter_config=TextFilter()), Column("is_superuser", "Is Superuser", display="superuser_display", filter_config=ChoicesFilter(choices=false_and_true())), Column("is_active", "Is Active", filter_config=ChoicesFilter( choices=false_and_true)), # `choices` callable Column("date_joined", "Date Joined", filter_config=DateRangeFilter()) ] return Picotable(request=rf.get("/"), columns=columns, queryset=model.objects.all(), context=PicoContext())
class AttributeListView(PicotableListView): model = Attribute default_columns = [ Column("identifier", _("Identifier"), filter_config=TextFilter( filter_field="identifier", placeholder=_("Filter by identifier..."))), Column("name", _("Name"), sort_field="translations__name", display="name", filter_config=TextFilter(filter_field="translations__name", placeholder=_("Filter by name..."))), Column("type", _("Type"), filter_config=ChoicesFilter(AttributeType.choices)), Column("visibility_mode", _("Visibility Mode"), filter_config=ChoicesFilter(AttributeVisibility.choices)), Column("searchable", _("Searchable")), Column("n_product_types", _("Used in # Product Types")), ] toolbar_buttons_provider_key = "attribute_list_toolbar_provider" mass_actions_provider_key = "attribute_list_mass_actions_provider" def get_queryset(self): return Attribute.objects.all().annotate( n_product_types=Count("product_types"))
class ProductListView(PicotableListView): model = Product columns = [ Column("sku", _(u"SKU"), display="sku", filter_config=TextFilter(placeholder=_("Filter by SKU..."))), Column("name", _(u"Name"), sort_field="translations__name", display="name", filter_config=TextFilter(filter_field="translations__name", placeholder=_("Filter by name..."))), Column("barcode", _(u"Barcode"), display="barcode", filter_config=TextFilter(_("Filter by barcode..."))), Column("type", _(u"Type")), Column("mode", _(u"Mode"), filter_config=ChoicesFilter(ProductMode.choices)), Column("category", _(u"Primary Category"), filter_config=ChoicesFilter(Category.objects.all(), "category")), ] def get_queryset(self): filter = self.get_filter() shop_id = filter.get("shop") qs = Product.objects.all_except_deleted() q = Q() for mode in filter.get("modes", []): q |= Q(mode=mode) manufacturer_ids = filter.get("manufacturers") if manufacturer_ids: q |= Q(manufacturer_id__in=manufacturer_ids) qs = qs.filter(q) if shop_id: qs = qs.filter(shop_products__shop_id=int(shop_id)) return qs def get_object_abstract(self, instance, item): return [{ "text": "%s" % instance, "class": "header" }, { "title": _(u"Barcode"), "text": item["barcode"] }, { "title": _(u"SKU"), "text": item["sku"] }, { "title": _(u"Type"), "text": item["type"] }, { "title": _(u"Primary Category"), "text": item["category"] }]
class CategoryListView(PicotableListView): model = Category default_columns = [ Column("image", _("Image"), sortable=False, linked=True, raw=True), Column("name", _(u"Name"), sortable=False, display="format_name", linked=True, filter_config=MPTTFilter(choices="get_name_filter_choices", filter_field="id")), Column("status", _(u"Status"), filter_config=ChoicesFilter( choices=CategoryStatus.choices, default=CategoryStatus.VISIBLE.value)), Column( "visibility", _(u"Visibility"), filter_config=ChoicesFilter(choices=CategoryVisibility.choices)), ] def get_name_filter_choices(self): choices = [] shop = self.request.shop for c in Category.objects.all_except_deleted(shop=shop): name = self.format_name(c) choices.append((c.pk, name)) return choices def get_queryset(self): return Category.objects.all_except_deleted(shop=get_shop(self.request)) def format_name(self, instance, *args, **kwargs): level = getattr(instance, instance._mptt_meta.level_attr) return ('---' * level) + ' ' + instance.name def get_object_abstract(self, instance, item): return [ { "text": "%s" % instance.name, "class": "header" }, { "title": _(u"Status"), "text": item.get("status") }, ] def get_toolbar(self): toolbar = super(CategoryListView, self).get_toolbar() toolbar.append( URLActionButton(url=reverse("shuup_admin:category.organize"), text=_("Organize"), tooltip=_("Organize categories"), icon="fa fa-sitemap", extra_css_class="btn-default")) return toolbar
class OrderStatusListView(PicotableListView): model = OrderStatus default_columns = [ Column("identifier", _("Identifier"), linked=True, filter_config=TextFilter(operator="startswith")), Column( "name", _("Name"), linked=True, filter_config=TextFilter(operator="startswith", filter_field="translations__name"), ), Column( "public_name", _("Public Name"), linked=False, filter_config=TextFilter(operator="startswith", filter_field="translations__name"), ), Column("role", _("Role"), linked=False, filter_config=ChoicesFilter(choices=OrderStatusRole.choices)), Column("default", _("Default"), linked=False, filter_config=ChoicesFilter([(False, _("yes")), (True, _("no"))])), Column( "allowed_next_statuses", _("Allowed Next Status"), linked=False, display="get_allowed_next_statuses_display", ), Column( "visible_for_customer", _("Visible For Customer"), linked=False, filter_config=ChoicesFilter([(False, _("yes")), (True, _("no"))]), ), Column("is_active", _("Active"), linked=False, filter_config=ChoicesFilter([(False, _("yes")), (True, _("no"))])), ] def get_allowed_next_statuses_display(self, instance): order_status_names = [ order_status.name for order_status in instance.allowed_next_statuses.all() ] return ", ".join(order_status_names) if order_status_names else _( "No allowed next status.")
def test_choice_filter_with_default(rf, admin_user, regular_user): columns = [ Column("id", "Id", filter_config=Filter(), display=instance_id), Column("username", "Username", sortable=False, filter_config=MultiFieldTextFilter(filter_fields=("username", "email"), operator="iregex")), Column("email", "Email", sortable=False, filter_config=TextFilter()), Column("is_superuser", "Is Superuser", display="superuser_display", filter_config=ChoicesFilter(choices=false_and_true())), Column("date_joined", "Date Joined", filter_config=DateRangeFilter()) ] is_active = [ Column("is_active", "Is Active", filter_config=ChoicesFilter(choices=false_and_true)) ] is_active_with_default = [ Column("is_active", "Is Active", filter_config=ChoicesFilter(choices=false_and_true, default=True)) ] query = {"perPage": 100, "page": 1, "sort": "+id"} pico_no_defaults = get_pico(rf, columns=(columns + is_active)) data = pico_no_defaults.get_data(query) user_data = data["items"][0] user = get_user_model().objects.get(id=user_data["id"]) assert user.is_active pico_with_defaults = get_pico(rf, columns=(columns + is_active_with_default)) data = pico_with_defaults.get_data(query) user_data = data["items"][0] user_with_defaults = get_user_model().objects.get(id=user_data["id"]) assert user_with_defaults == user user.is_active = False user.save() data = pico_no_defaults.get_data(query) user_data = data["items"][0] new_user = get_user_model().objects.get(id=user_data["id"]) assert new_user == user data = pico_with_defaults.get_data(query) user_data = data["items"][0] new_user_with_defaults = get_user_model().objects.get(id=user_data["id"]) assert new_user_with_defaults != user_with_defaults
class OrderListView(PicotableListView): model = Order columns = [ Column("identifier", _(u"Order"), linked=True, filter_config=TextFilter(operator="startswith")), Column("order_date", _(u"Order Date"), display="format_order_date", filter_config=DateRangeFilter()), Column("customer", _(u"Customer"), filter_config=MultiFieldTextFilter( filter_fields=("customer__email", "customer__name"))), Column("status", _(u"Status"), filter_config=ChoicesFilter(choices=OrderStatus.objects.all())), Column("payment_status", _(u"Payment Status"), filter_config=ChoicesFilter(choices=PaymentStatus.choices)), Column("shipping_status", _(u"Shipping Status"), filter_config=ChoicesFilter(choices=ShippingStatus.choices)), Column("taxful_total_price", _(u"Total"), sort_field="taxful_total_price_value", display="format_taxful_total_price", class_name="text-right", filter_config=RangeFilter( field_type="number", filter_field="taxful_total_price_value")), ] def get_queryset(self): return super(OrderListView, self).get_queryset().exclude(deleted=True) def format_order_date(self, instance, *args, **kwargs): return get_locally_formatted_datetime(instance.order_date) def format_taxful_total_price(self, instance, *args, **kwargs): return escape(format_money(instance.taxful_total_price)) def get_object_abstract(self, instance, item): return [{ "text": "%s" % instance, "class": "header" }, { "title": _(u"Total"), "text": item["taxful_total_price"] }, { "title": _(u"Status"), "text": item["status"] }]
class CategoryListView(PicotableListView): model = Category category_status_choices = [(status.value, status) for status in CategoryStatus if status != CategoryStatus.DELETED] default_columns = [ Column("image", _("Image"), sortable=False, linked=True, raw=True), Column("name", _(u"Name"), sort_field="translations__name", display="format_name", linked=True, allow_highlight=False, filter_config=MPTTFilter(choices="get_name_filter_choices", filter_field="id")), Column("status", _(u"Status"), filter_config=ChoicesFilter( choices=category_status_choices, default=CategoryStatus.VISIBLE.value)), Column( "visibility", _(u"Visibility"), filter_config=ChoicesFilter(choices=CategoryVisibility.choices)), ] toolbar_buttons_provider_key = "category_list_toolbar_provider" mass_actions_provider_key = "category_list_mass_actions_provider" def get_name_filter_choices(self): choices = [] shop = self.request.shop for c in Category.objects.all_except_deleted(shop=shop): name = self.format_name(c) choices.append((c.pk, name)) return choices def get_queryset(self): return Category.objects.all_except_deleted(shop=get_shop(self.request)) def format_name(self, instance, *args, **kwargs): level = getattr(instance, instance._mptt_meta.level_attr) return ('---' * level) + ' ' + instance.name def get_object_abstract(self, instance, item): return [ { "text": "%s" % instance.name, "class": "header" }, { "title": _(u"Status"), "text": item.get("status") }, ]
class ShopListView(PicotableListView): model = Shop default_columns = [ Column("logo", _(u"Logo"), display="logo", class_name="text-center", raw=True, ordering=1, sortable=False), Column("name", _(u"Name"), sort_field="translations__name", display="name", filter_config=TextFilter( filter_field="translations__name", placeholder=_("Filter by name...") )), Column("domain", _(u"Domain")), Column("identifier", _(u"Identifier")), Column("status", _(u"Status"), filter_config=ChoicesFilter(choices=ShopStatus.choices)), ] def get_queryset(self): if self.request.user.is_superuser: return super(ShopListView, self).get_queryset() else: return Shop.objects.get_for_user(self.request.user) def get_toolbar(self): if ShuupSettings.get_setting("SHUUP_ENABLE_MULTIPLE_SHOPS"): return super(ShopListView, self).get_toolbar() else: return Toolbar([])
class UserListView(PicotableListView): model = settings.AUTH_USER_MODEL default_columns = [ Column("username", _(u"Username"), filter_config=TextFilter()), Column("email", _(u"Email"), filter_config=TextFilter()), Column("first_name", _(u"First Name"), filter_config=TextFilter()), Column("last_name", _(u"Last Name"), filter_config=TextFilter()), Column( "is_active", _(u"Active"), filter_config=ChoicesFilter([(False, _("no")), (True, _("yes"))], default=True), ), Column("is_staff", _(u"Access to Admin Panel"), filter_config=true_or_false_filter), ] toolbar_buttons_provider_key = "user_list_toolbar_provider" mass_actions_provider_key = "user_list_mass_actions_provider" def get_model(self): return get_user_model() def get_queryset(self): model = self.get_model() qs = self.get_model().objects.all() if "date_joined" in [f.name for f in model._meta.get_fields()]: qs = qs.order_by("-date_joined") # non superusers can't see superusers if not self.request.user.is_superuser: qs = qs.filter(is_superuser=False) return qs def get_context_data(self, **kwargs): context = super(UserListView, self).get_context_data(**kwargs) context["title"] = force_text( self.get_model()._meta.verbose_name_plural).title() return context def get_object_abstract(self, instance, item): bits = filter(None, [ _("First Name: %s") % (getattr(instance, 'first_name', None) or "\u2014"), _("Last Name: %s") % (getattr(instance, 'last_name', None) or "\u2014"), _("Active") if instance.is_active else _(u"Inactive"), _("Email: %s") % (getattr(instance, 'email', None) or "\u2014"), _("Access to Admin Panel") if getattr(instance, 'is_staff', None) else None, _("Superuser (Full rights)") if getattr(instance, 'is_superuser', None) else None ]) return [{ "text": instance.get_username() or _("User"), "class": "header" }, { "text": ", ".join([force_text(bit) for bit in bits]) }]
def _get_column(self, model, field, known_names, identifier): if not self._valid_field(field.name): return None field_name = field.verbose_name.title() if identifier: field_name = "%s %s" % (identifier.replace( "_", " ").capitalize(), field_name) display = "%s__%s" % (identifier, field.name) if identifier else field.name column = Column( "%s_%s" % ((identifier if identifier else model.__name__.lower()), field.name), field_name, display=display) column, is_special = self.handle_special_column(field, column) if not is_special: if isinstance(field, CharField): column.filter_config = TextFilter(filter_field=field.name, placeholder=field_name) if isinstance(field, EnumIntegerField): column.filter_config = ChoicesFilter(field.choices) if isinstance(field, BooleanField): column.filter_config = true_or_false_filter return column
class TaskListView(PicotableListView): model = Task default_columns = [ Column("name", _("Name"), sort_field="name", display="name", filter_config=TextFilter(filter_field="name", placeholder=_("Filter by name..."))), Column("priority", _("Priority")), Column("creator", _("Creator"), filter_config=TextFilter( filter_field="creator__name", placeholder=_("Filter by creator..."))), Column("status", _("Status"), filter_config=ChoicesFilter(TaskStatus.choices)), Column("comments", _("Comments"), sort_field="comments", display="get_comments_count") ] def get_comments_count(self, instance, **kwargs): return instance.comments.for_contact( get_person_contact(self.request.user)).count() def get_queryset(self): return Task.objects.for_shop(get_shop(self.request))
def get_columns(self): for column in self.columns: if column.id == 'shop': shops = Shop.objects.get_for_user(self.request.user).prefetch_related('translations') column.filter_config = ChoicesFilter(choices=shops) break return self.columns
class CampaignListView(PicotableListView): default_columns = [ Column( "name", _(u"Title"), sort_field="name", display="name", linked=True, filter_config=TextFilter(operator="startswith") ), Column("start_datetime", _("Starts")), Column("end_datetime", _("Ends")), Column("active", _("Active"), filter_config=ChoicesFilter(choices=[(0, _("No")), (1, _("Yes"))])), ] def start_datetime(self, instance, *args, **kwargs): if not instance.start_datetime: return "" return self._formatted_datetime(instance.start_datetime) def end_datetime(self, instance, *args, **kwargs): if not instance.end_datetime: return "" return self._formatted_datetime(instance.end_datetime) def _formatted_datetime(self, dt): return format_datetime(localtime(dt), locale=get_current_babel_locale()) def get_object_abstract(self, instance, item): return [ {"text": "%s" % (instance or _("CatalogCampaign")), "class": "header"}, ]
class CategoryListView(PicotableListView): model = Category default_columns = [ Column("image", _("Image"), sortable=False, linked=True, raw=True), Column("name", _(u"Name"), sortable=False, display="format_name", linked=True, filter_config=MPTTFilter(choices="get_name_filter_choices", filter_field="id")), Column("status", _(u"Status"), filter_config=ChoicesFilter( choices=CategoryStatus.choices, default=CategoryStatus.VISIBLE.value)), Column( "visibility", _(u"Visibility"), filter_config=ChoicesFilter(choices=CategoryVisibility.choices)), ] def get_name_filter_choices(self): choices = [] for c in Category.objects.all_except_deleted(): name = self.format_name(c) choices.append((c.pk, name)) return choices def get_queryset(self): return Category.objects.all_except_deleted() def format_name(self, instance, *args, **kwargs): level = getattr(instance, instance._mptt_meta.level_attr) return ('---' * level) + ' ' + instance.name def get_object_abstract(self, instance, item): return [ { "text": "%s" % instance, "class": "header" }, { "title": _(u"Status"), "text": item.get("status") }, ]
class StocksListView(PicotableListView): template_name = "shuup/simple_supplier/admin/base_picotable.jinja" model = Product default_columns = [ Column( "sku", _("SKU"), sort_field="product__sku", display="product__sku", linked=True, filter_config=TextFilter(filter_field="product__sku", placeholder=_("Filter by SKU...")) ), Column( "name", _("Name"), sort_field="product__translations__name", display="product__name", linked=True, filter_config=TextFilter(filter_field="product__translations__name", placeholder=_("Filter by name...")) ), Column( "supplier", _("Supplier"), display="supplier", linked=False, filter_config=ChoicesFilter(Supplier.objects.enabled().filter(module_identifier="simple_supplier")) ), Column( "stock_information", _("Stock information"), display="get_stock_information", linked=False, sortable=False, raw=True ), Column( "adjust_stock", _("Adjust stock"), display="get_stock_adjustment_form", sortable=False, linked=False, raw=True ) ] def __init__(self): super(StocksListView, self).__init__() self.columns = self.default_columns def get_object_abstract(self, instance, item): item.update({"_linked_in_mobile": False, "_url": ""}) return [ {"text": item.get("name"), "class": "header"}, {"title": "", "text": item.get("sku")}, {"title": "", "text": " ", "raw": item.get("stock_information")}, {"title": "", "text": " ", "raw": item.get("adjust_stock")}, ] def get_queryset(self): return StockCount.objects.filter( supplier__module_identifier="simple_supplier", supplier__enabled=True, supplier__stock_managed=True, product__deleted=False ).order_by("product__id") def get_context_data(self, **kwargs): context = super(PicotableListView, self).get_context_data(**kwargs) context["toolbar"] = None context["title"] = _("Stock management") return context def get_stock_information(self, instance): return get_stock_information_html(instance.supplier, instance.product) def get_stock_adjustment_form(self, instance): return get_stock_adjustment_div(self.request, instance.supplier, instance.product)
class ContactListView(PicotableListView): model = Contact columns = [ Column("name", _(u"Name"), linked=True, filter_config=TextFilter()), Column("type", _(u"Type"), display="get_type_display", sortable=False), # TODO: Add a filter Column("email", _(u"Email"), filter_config=TextFilter()), Column("phone", _(u"Phone"), filter_config=TextFilter()), Column( "is_active", _(u"Active"), filter_config=ChoicesFilter([(False, _("no")), (True, _("yes"))], default=True) ), Column("n_orders", _(u"# Orders"), class_name="text-right", filter_config=RangeFilter(step=1)), Column("groups", _("Groups"), filter_config=ChoicesFilter(ContactGroup.objects.all(), "groups")) ] def get_queryset(self): groups = self.get_filter().get("groups") query = Q(groups__in=groups) if groups else Q() return super(ContactListView, self).get_queryset().filter(query).annotate(n_orders=Count("customer_orders")) def get_type_display(self, instance): if isinstance(instance, PersonContact): return _(u"Person") elif isinstance(instance, CompanyContact): return _(u"Company") else: return _(u"Contact") def get_object_abstract(self, instance, item): """ :type instance: shuup.core.models.Contact """ bits = filter(None, [ item["type"], _("Active") if instance.is_active else _("Inactive"), _("Email: %s") % (instance.email or "\u2014"), _("Phone: %s") % (instance.phone or "\u2014"), _("%d orders") % instance.n_orders, ]) return [ {"text": instance.name or _("Contact"), "class": "header"}, {"text": ", ".join(bits)} ]
class UserListView(PicotableListView): model = settings.AUTH_USER_MODEL default_columns = [ Column("username", _(u"Username"), filter_config=TextFilter()), Column("email", _(u"Email"), filter_config=TextFilter()), Column("first_name", _(u"First Name"), filter_config=TextFilter()), Column("last_name", _(u"Last Name"), filter_config=TextFilter()), Column("is_active", _(u"Active"), filter_config=ChoicesFilter([(False, _("no")), (True, _("yes"))], default=True)), Column("is_staff", _(u"Staff"), filter_config=true_or_false_filter), Column("is_superuser", _(u"Superuser"), filter_config=true_or_false_filter), ] def get_model(self): return get_user_model() def get_queryset(self): model = self.get_model() qs = self.get_model().objects.all() if "date_joined" in model._meta.get_all_field_names(): qs = qs.order_by("-date_joined") return qs def get_context_data(self, **kwargs): context = super(UserListView, self).get_context_data(**kwargs) context["title"] = force_text( self.get_model()._meta.verbose_name_plural).title() return context def get_object_abstract(self, instance, item): bits = filter(None, [ _("First Name: %s") % (getattr(instance, 'first_name', None) or "\u2014"), _("Last Name: %s") % (getattr(instance, 'last_name', None) or "\u2014"), _("Active") if instance.is_active else _(u"Inactive"), _("Email: %s") % (getattr(instance, 'email', None) or "\u2014"), _("Staff") if getattr(instance, 'is_staff', None) else None, _("Superuser") if getattr(instance, 'is_superuser', None) else None ]) return [{ "text": instance.get_username() or _("User"), "class": "header" }, { "text": ", ".join([force_text(bit) for bit in bits]) }]
def _get_column(self, field): field_name = field.verbose_name.title() if not self._valid_field(field.name): return None column = Column(field.name, field_name, display=field.name) column, is_special = self.handle_special_column(field, column) if not is_special: if isinstance(field, CharField): column.filter_config = TextFilter(placeholder=field_name) if isinstance(field, EnumIntegerField): column.filter_config = ChoicesFilter(field.choices) if isinstance(field, BooleanField): column.filter_config = true_or_false_filter return column
class TaskListView(PicotableListView): model = Task default_columns = [ Column( "name", _("Name"), sort_field="name", display="name", filter_config=TextFilter(filter_field="name", placeholder=_("Filter by name...")), ), Column( "creator", _("Creator"), display="get_creator_name_display", filter_config=TextFilter(filter_field="creator__name", placeholder=_("Filter by creator...")), ), Column("status", _("Status"), filter_config=ChoicesFilter(TaskStatus.choices), class_name="text-center"), Column("priority", _("Priority"), display="get_priority_display", class_name="text-center"), Column("comments", _("Comments"), sort_field="comments", display="get_comments_count", class_name="text-center"), ] toolbar_buttons_provider_key = "task_list_toolbar_provider" mass_actions_provider_key = "task_list_actions_provider" def get_comments_count(self, instance, **kwargs): return instance.comments.for_contact( get_person_contact(self.request.user)).count() def get_queryset(self): return Task.objects.for_shop(get_shop(self.request)) def get_creator_name_display(self, instance, **kwargs): if not len(instance.creator.name): return "No name set (id: %d)" % instance.creator.id return instance.creator.name def get_priority_display(self, instance, **kwargs): return "%s" % instance.priority
class ShopListView(PicotableListView): model = Shop default_columns = [ Column("name", _(u"Name"), sort_field="translations__name", display="name", filter_config=TextFilter( filter_field="translations__name", placeholder=_("Filter by name...") )), Column("domain", _(u"Domain")), Column("identifier", _(u"Identifier")), Column("status", _(u"Status"), filter_config=ChoicesFilter(choices=ShopStatus.choices)), ] def get_toolbar(self): if settings.SHUUP_ENABLE_MULTIPLE_SHOPS: return super(ShopListView, self).get_toolbar() else: return Toolbar([])
class CampaignListView(PicotableListView): columns = [ Column( "name", _(u"Title"), sort_field="name", display="name", linked=True, filter_config=TextFilter(operator="startswith") ), Column("start_datetime", _("Starts")), Column("end_datetime", _("Ends")), Column("active", _("Active"), filter_config=ChoicesFilter(choices=[(0, _("No")), (1, _("Yes"))])), ] def start_datetime(self, instance, *args, **kwargs): if not instance.start_datetime: return "" return self._formatted_datetime(instance.start_datetime) def end_datetime(self, instance, *args, **kwargs): if not instance.end_datetime: return "" return self._formatted_datetime(instance.end_datetime) def _formatted_datetime(self, dt): return format_datetime(localtime(dt), locale=get_current_babel_locale()) def add_columns(self, column_id, columns, after=True): # TODO: Make better added = False for idx, column in enumerate(self.columns): if column.id == column_id: found_idx = idx + 1 if after else idx start = self.columns[:found_idx] end = self.columns[found_idx:] self.columns = start + columns + end added = True break if not added: self.columns += columns def get_object_abstract(self, instance, item): return [ {"text": "%s" % (instance or _("CatalogCampaign")), "class": "header"}, ]
class ProductReviewListView(PicotableListView): model = ProductReview url_identifier = "product_reviews" default_columns = [ Column( "product", _("Product"), filter_config=TextFilter( filter_field="product__translations__name", placeholder=_("Filter by product...") ) ), Column( "reviewer__name", _("Reviewer"), filter_config=TextFilter(filter_field="reviewer__name") ), Column( "rating", _("Rating"), filter_config=RangeFilter(min=1, max=5, step=1, filter_field="rating") ), Column("comment", _("Comment")), Column( "status", _("Status"), filter_config=ChoicesFilter( choices=ReviewStatus.choices(), filter_field="status" ) ) ] mass_actions = [ "shuup_product_reviews.admin_module.mass_actions.ApproveProductReviewMassAction", "shuup_product_reviews.admin_module.mass_actions.RejectProductReviewMassAction" ] def get_queryset(self): return ProductReview.objects.filter(shop=get_shop(self.request))
class TableListView(PicotableListView): model = ShippingTable default_columns = [ Column("name", _("Name"), filter_config=TextFilter()), Column("identifier", _("Identifier"), filter_config=TextFilter()), Column("enabled", _("Enabled")), Column("start_date", _("Start Date"), display="format_start_date"), Column("end_date", _("End Date"), display="format_end_date"), Column( "carrier", _("Carrier"), filter_config=ChoicesFilter(choices=ShippingCarrier.objects.all())) ] def format_start_date(self, instance, *args, **kwargs): if instance.start_date: return get_locally_formatted_datetime(instance.start_date) def format_end_date(self, instance, *args, **kwargs): if instance.end_date: return get_locally_formatted_datetime(instance.end_date)
class BaseProductReviewListView(PicotableListView): model = None default_columns = [ Column("reviewer__name", _("Reviewer"), filter_config=TextFilter(filter_field="reviewer__name")), Column("rating", _("Rating"), filter_config=RangeFilter(min=1, max=5, step=1, filter_field="rating")), Column("comment", _("Comment")), Column("status", _("Status"), filter_config=ChoicesFilter(choices=ReviewStatus.choices(), filter_field="status")) ] def __init__(self): super(BaseProductReviewListView, self).__init__() self.columns = self.default_columns
class CartListView(PicotableListView): model = StoredBasket default_columns = [ Column("key", _(u"Key"), filter_config=TextFilter(filter_field="key")), Column("updated_on", _(u"Last updated on"), display="format_updated_date", filter_config=DateRangeFilter()), Column("finished", _("Completed"), display="format_finished_status", filter_config=ChoicesFilter([(True, _("yes")), (False, _("no"))], filter_field="finished", default=False)), Column("shop", _("Shop"), filter_config=TextFilter( filter_field="shop__translations__public_name")), Column("supplier", _("Supplier"), filter_config=TextFilter(filter_field="supplier__name")), Column("customer", _(u"Customer"), filter_config=MultiFieldTextFilter( filter_fields=("customer__email", "customer__name"))), Column("product_count", _("Product count"), filter_config=RangeFilter()), Column("taxful_total_price", _(u"Total"), sort_field="taxful_total_price_value", display="format_taxful_total_price", class_name="text-right", filter_config=RangeFilter( field_type="number", filter_field="taxful_total_price_value")), ] toolbar_buttons_provider_key = "cart_list_toolbar_provider" mass_actions_provider_key = "cart_list_actions_provider" def __init__(self): super(CartListView, self).__init__() self.columns = self.default_columns def get_queryset(self): """ Ignore potentially active carts, displaying only those not updated for at least 2 hours. """ shop = get_shop(self.request) filters = {"product_count__gte": 0, "persistent": False, "shop": shop} return super(CartListView, self).get_queryset().filter(**filters) def format_finished_status(self, instance, *args, **kwargs): return "yes" if instance.finished else "no" def format_updated_date(self, instance, *args, **kwargs): return get_locally_formatted_datetime(instance.updated_on) def format_taxful_total_price(self, instance, *args, **kwargs): if not instance.taxful_total_price: return "" return escape(format_money(instance.taxful_total_price)) def get_context_data(self, **kwargs): context = super(CartListView, self).get_context_data(**kwargs) context["title"] = _("Carts") return context def get_object_abstract(self, instance, item): return [ { "text": "%s" % instance, "class": "header" }, { "title": _(u"Created on"), "text": item.get("created_on") }, { "title": _(u"Last updated on"), "text": item.get("updated_on") }, { "title": _(u"Ordered"), "text": item.get("finished") }, { "title": _(u"Total"), "text": item.get("taxful_total_price") }, ]
class OrderListView(PicotableListView): model = Order default_columns = [ Column("identifier", _(u"Order"), linked=True, filter_config=TextFilter(operator="startswith")), Column("order_date", _(u"Order Date"), display="format_order_date", filter_config=DateRangeFilter()), Column("customer", _(u"Customer"), display="format_customer_name", filter_config=MultiFieldTextFilter( filter_fields=("customer__email", "customer__name", "billing_address__name", "shipping_address__name", "orderer__name"))), Column( "status", _(u"Status"), filter_config=ChoicesFilter(choices=OrderStatus.objects.all()), ), Column("payment_status", _(u"Payment Status"), filter_config=ChoicesFilter(choices=PaymentStatus.choices)), Column("shipping_status", _(u"Shipping Status"), filter_config=ChoicesFilter(choices=ShippingStatus.choices)), Column("taxful_total_price_value", _(u"Total"), sort_field="taxful_total_price_value", display="format_taxful_total_price", class_name="text-right", filter_config=RangeFilter( field_type="number", filter_field="taxful_total_price_value")), ] related_objects = [ ("shop", "shuup.core.models:Shop"), ("billing_address", "shuup.core.models:ImmutableAddress"), ("shipping_address", "shuup.core.models:ImmutableAddress"), ] mass_actions = [ "shuup.admin.modules.orders.mass_actions:CancelOrderAction", "shuup.admin.modules.orders.mass_actions:OrderConfirmationPdfAction", "shuup.admin.modules.orders.mass_actions:OrderDeliveryPdfAction", ] toolbar_buttons_provider_key = "order_list_toolbar_provider" mass_actions_provider_key = "order_list_mass_actions_provider" def get_toolbar(self): toolbar = Toolbar([ NewActionButton.for_model(Order, url=reverse("shuup_admin:order.new")), SettingsActionButton.for_model(Order, return_url="order") ], view=self) return toolbar def get_queryset(self): return super(OrderListView, self).get_queryset().exclude( deleted=True).filter(shop=get_shop(self.request)) def format_customer_name(self, instance, *args, **kwargs): return instance.get_customer_name() or "" def format_order_date(self, instance, *args, **kwargs): return get_locally_formatted_datetime(instance.order_date) def format_taxful_total_price(self, instance, *args, **kwargs): return escape(format_money(instance.taxful_total_price)) def label(self, instance, *args, **kwargs): # format label to make it human readable return instance.label.replace("_", " ").title() def get_object_abstract(self, instance, item): return [{ "text": "%s" % instance, "class": "header" }, { "title": _(u"Total"), "text": item.get("taxful_total_price_value") }, { "title": _(u"Status"), "text": item.get("status") }]