Ejemplo n.º 1
0
class OrderModule(AdminModule):
    name = _("Orders")
    breadcrumbs_menu_entry = MenuEntry(name, url="shuup_admin:order.list")

    def get_urls(self):
        return [
            admin_url(
                r"^orders/(?P<pk>\d+)/create-shipment/(?P<supplier_pk>\d+)/$",
                "shuup.admin.modules.orders.views.OrderCreateShipmentView",
                name="order.create-shipment",
            ),
            admin_url(
                r"^shipments/(?P<pk>\d+)/delete/$",
                "shuup.admin.modules.orders.views.ShipmentDeleteView",
                name="order.delete-shipment",
            ),
            admin_url(
                r"^shipments/(?P<pk>\d+)/set-sent/$",
                "shuup.admin.modules.orders.views.ShipmentSetSentView",
                name="order.set-shipment-sent",
            ),
            admin_url(r"^shipments/$",
                      "shuup.admin.modules.orders.views.ShipmentListView",
                      name="order.shipments.list"),
            admin_url(
                r"^orders/(?P<pk>\d+)/create-payment/$",
                "shuup.admin.modules.orders.views.OrderCreatePaymentView",
                name="order.create-payment",
            ),
            admin_url(
                r"^orders/(?P<pk>\d+)/delete-payment/$",
                "shuup.admin.modules.orders.views.OrderDeletePaymentView",
                name="order.delete-payment",
            ),
            admin_url(
                r"^orders/(?P<pk>\d+)/set-paid/$",
                "shuup.admin.modules.orders.views.OrderSetPaidView",
                name="order.set-paid",
            ),
            admin_url(
                r"^orders/(?P<pk>\d+)/set-status/$",
                "shuup.admin.modules.orders.views.OrderSetStatusView",
                name="order.set-status",
            ),
            admin_url(
                r"^orders/(?P<pk>\d+)/new-log-entry/$",
                "shuup.admin.modules.orders.views.NewLogEntryView",
                name="order.new-log-entry",
            ),
            admin_url(
                r"^orders/(?P<pk>\d+)/update-admin-comment/$",
                "shuup.admin.modules.orders.views.UpdateAdminCommentView",
                name="order.update-admin-comment",
            ),
            admin_url(
                r"^orders/(?P<pk>\d+)/create-refund/$",
                "shuup.admin.modules.orders.views.OrderCreateRefundView",
                name="order.create-refund",
            ),
            admin_url(
                r"^orders/(?P<pk>\d+)/create-refund/full-refund$",
                "shuup.admin.modules.orders.views.OrderCreateFullRefundView",
                name="order.create-full-refund",
            ),
            admin_url(r"^orders/(?P<pk>\d+)/$",
                      "shuup.admin.modules.orders.views.OrderDetailView",
                      name="order.detail"),
            admin_url(r"^orders/new/$",
                      "shuup.admin.modules.orders.views.OrderEditView",
                      name="order.new"),
            admin_url(r"^orders/(?P<pk>\d+)/edit/$",
                      "shuup.admin.modules.orders.views.OrderEditView",
                      name="order.edit"),
            admin_url(r"^orders/$",
                      "shuup.admin.modules.orders.views.OrderListView",
                      name="order.list"),
            admin_url(
                r"^orders/list-settings/",
                "shuup.admin.modules.settings.views.ListSettingsView",
                name="order.list_settings",
            ),
            admin_url(
                r"^orders/(?P<pk>\d+)/edit-addresses/$",
                "shuup.admin.modules.orders.views.OrderAddressEditView",
                name="order.edit-addresses",
            ),
        ]

    def get_menu_entries(self, request):
        return [
            MenuEntry(
                text=_("Orders"),
                icon="fa fa-inbox",
                url="shuup_admin:order.list",
                category=ORDERS_MENU_CATEGORY,
                ordering=1,
                aliases=[_("Show orders")],
            ),
            MenuEntry(
                text=_("Shipments"),
                icon="fa fa-truck",
                url="shuup_admin:order.shipments.list",
                category=ORDERS_MENU_CATEGORY,
                ordering=2,
                aliases=[_("Show shipments")],
            ),
        ]

    def get_search_results(self, request, query):
        minimum_query_length = 3
        if len(query) >= minimum_query_length:
            orders = Order.objects.filter(
                Q(identifier__istartswith=query)
                | Q(reference_number__istartswith=query)
                | Q(email__icontains=query)
                | Q(phone__icontains=query)).order_by("-id")[:15]

            for i, order in enumerate(orders):
                relevance = 100 - i
                yield SearchResult(text=six.text_type(order),
                                   url=get_model_url(order),
                                   category=_("Orders"),
                                   relevance=relevance)

    def get_notifications(self, request):
        shop = request.shop
        old_open_orders = Order.objects.filter(
            shop=shop,
            status__role=OrderStatusRole.INITIAL,
            order_date__lt=now() - timedelta(days=4)).count()

        if old_open_orders:
            yield Notification(title=_("Outstanding Orders"),
                               text=_("%d outstanding orders") %
                               old_open_orders,
                               kind="danger")

    def get_model_url(self, object, kind, shop=None):
        return derive_model_url(Order, "shuup_admin:order", object, kind)

    def get_help_blocks(self, request, kind):
        from shuup.admin.utils.permissions import has_permission

        if kind == "quicklink" and has_permission(request.user, "order.new"):
            actions = [{
                "text": _("New order"),
                "url": self.get_model_url(Order, "new")
            }]

            yield SimpleHelpBlock(
                text=_("New order"),
                actions=actions,
                icon_url="shuup_admin/img/product.png",
                priority=0,
                category=HelpBlockCategory.ORDERS,
                done=Order.objects.filter(
                    shop=request.shop).exists() if kind == "setup" else False,
            )
Ejemplo n.º 2
0
class ProductModule(AdminModule):
    name = _("Products")
    breadcrumbs_menu_entry = MenuEntry(name, url="shuup_admin:product.list")

    def get_urls(self):
        return [
            admin_url(
                "^products/(?P<pk>\d+)/delete/$", "shuup.admin.modules.products.views.ProductDeleteView",
                name="product.delete",
                permissions=["shuup.delete_product"]
            ),
            admin_url(
                "^products/(?P<pk>\d+)/media/$", "shuup.admin.modules.products.views.ProductMediaEditView",
                name="product.edit_media",
                permissions=get_default_model_permissions(Product),
            ),
            admin_url(
                "^products/(?P<pk>\d+)/crosssell/$", "shuup.admin.modules.products.views.ProductCrossSellEditView",
                name="product.edit_cross_sell",
                permissions=get_default_model_permissions(ProductCrossSell),
            ),
            admin_url(
                "^products/(?P<pk>\d+)/variation/$", "shuup.admin.modules.products.views.ProductVariationView",
                name="product.edit_variation",
                permissions=get_default_model_permissions(ProductVariationResult),
            ),
            admin_url(
                "^products/(?P<pk>\d+)/package/$", "shuup.admin.modules.products.views.ProductPackageView",
                name="product.edit_package",
                permissions=get_default_model_permissions(ProductPackageLink),
            ),
        ] + get_edit_and_list_urls(
            url_prefix="^products",
            view_template="shuup.admin.modules.products.views.Product%sView",
            name_template="product.%s",
            permissions=get_default_model_permissions(Product),
        )

    def get_menu_category_icons(self):
        return {self.name: "fa fa-cube"}

    def get_menu_entries(self, request):
        category = _("Products")
        return [
            MenuEntry(
                text=_("Products"),
                icon="fa fa-cube",
                url="shuup_admin:product.list",
                category=category
            )
        ]

    def get_search_results(self, request, query):
        minimum_query_length = 3
        skus_seen = set()
        if len(query) >= minimum_query_length:
            pk_counter = Counter()
            pk_counter.update(Product.objects.filter(sku__startswith=query).values_list("pk", flat=True))
            name_q = Q()
            for part in split_query(query, minimum_query_length):
                name_q &= Q(name__icontains=part)
            pk_counter.update(
                Product._parler_meta.root_model.objects.filter(name_q).values_list("master_id", flat=True)
            )
            pks = [pk for (pk, count) in pk_counter.most_common(10)]
            for product in Product.objects.filter(pk__in=pks):
                relevance = 100 - pk_counter.get(product.pk, 0)
                skus_seen.add(product.sku.lower())
                yield SearchResult(
                    text=force_text(product),
                    url=get_model_url(product),
                    category=_("Products"),
                    relevance=relevance
                )

        if len(query) >= minimum_query_length:
            url = reverse("shuup_admin:product.new")
            if " " in query:
                yield SearchResult(
                    text=_("Create Product Called \"%s\"") % query,
                    url=manipulate_query_string(url, name=query),
                    is_action=True
                )
            else:
                if query.lower() not in skus_seen:
                    yield SearchResult(
                        text=_("Create Product with SKU \"%s\"") % query,
                        url=manipulate_query_string(url, sku=query),
                        is_action=True
                    )

    def get_required_permissions(self):
        return get_permissions_from_urls(self.get_urls()) | get_default_model_permissions(Product)

    def get_model_url(self, object, kind):
        return derive_model_url(Product, "shuup_admin:product", object, kind)
Ejemplo n.º 3
0
class ShopModule(AdminModule):
    name = _("Shops")
    breadcrumbs_menu_entry = MenuEntry(name, url="shuup_admin:shop.list")

    def get_urls(self):
        return [
            admin_url("^shops/(?P<pk>\d+)/enable/$",
                      "shuup.admin.modules.shops.views.ShopEnablerView",
                      name="shop.enable"),
            admin_url("^shops/(?P<pk>\d+)/select/$",
                      "shuup.admin.modules.shops.views.ShopSelectView",
                      name="shop.select"),
        ] + get_edit_and_list_urls(
            url_prefix="^shops",
            view_template="shuup.admin.modules.shops.views.Shop%sView",
            name_template="shop.%s")

    def get_menu_entries(self, request):
        return [
            MenuEntry(text=self.name,
                      icon="fa fa-home",
                      url="shuup_admin:shop.list",
                      category=STOREFRONT_MENU_CATEGORY,
                      ordering=4),
        ]

    def get_help_blocks(self, request, kind):
        if kind == "setup":
            shop = request.shop
            yield SimpleHelpBlock(
                text=_("Add a logo to make your store stand out"),
                actions=[{
                    "text": _("Add logo"),
                    "url": self.get_model_url(shop, "edit"),
                    "hash": "#shop-images-section"
                }],
                icon_url="shuup_admin/img/logo_icon.svg",
                done=shop.logo,
                required=False)

            shop = get_shop(request)
            yield SimpleHelpBlock(
                priority=1000,
                text=_("Publish your store"),
                description=_(
                    "Let customers browse your store and make purchases"),
                css_class="green ",
                actions=[{
                    "method":
                    "POST",
                    "text":
                    _("Publish shop"),
                    "url":
                    reverse("shuup_admin:shop.enable", kwargs={"pk": shop.pk}),
                    "data": {
                        "enable": True,
                        "redirect": reverse("shuup_admin:dashboard")
                    }
                }],
                icon_url="shuup_admin/img/publish.png",
                done=(not shop.maintenance_mode),
                required=False)

    def get_model_url(self, object, kind, shop=None):
        return derive_model_url(Shop, "shuup_admin:shop", object, kind)

    def get_search_results(self, request, query):
        if not settings.SHUUP_ENABLE_MULTIPLE_SHOPS:
            return

        minimum_query_length = 3
        if len(query) >= minimum_query_length:
            shops = Shop.objects.get_for_user(request.user).filter(
                translations__name__icontains=query, status=ShopStatus.ENABLED)
            for i, shop in enumerate(shops[:10]):
                relevance = 100 - i
                yield SearchResult(
                    text=(_('Set "{}" as the active shop')).format(shop.name),
                    url=get_model_url(shop, "select"),
                    category=(
                        _("Available Shops [currently active: {}]")).format(
                            request.shop.name),
                    relevance=relevance)
Ejemplo n.º 4
0
class ContactModule(AdminModule):
    name = _("Contacts")
    breadcrumbs_menu_entry = MenuEntry(text=name, url="shuup_admin:contact.list", category=CONTACTS_MENU_CATEGORY)

    def get_urls(self):
        return [
            admin_url(
                "^contacts/new/$",
                "shuup.admin.modules.contacts.views.ContactEditView",
                kwargs={"pk": None},
                name="contact.new",
                permissions=["shuup.add_contact"],
            ),
            admin_url(
                "^contacts/(?P<pk>\d+)/edit/$",
                "shuup.admin.modules.contacts.views.ContactEditView",
                name="contact.edit",
                permissions=["shuup.change_contact"],
            ),
            admin_url(
                "^contacts/(?P<pk>\d+)/$",
                "shuup.admin.modules.contacts.views.ContactDetailView",
                name="contact.detail",
                permissions=get_default_model_permissions(Contact),
            ),
            admin_url(
                "^contacts/reset-password/(?P<pk>\d+)/$",
                "shuup.admin.modules.contacts.views.ContactResetPasswordView",
                name="contact.reset_password",
                permissions=get_default_model_permissions(Contact),
            ),
            admin_url(
                "^contacts/$",
                "shuup.admin.modules.contacts.views.ContactListView",
                name="contact.list",
                permissions=get_default_model_permissions(Contact),
            ),
            admin_url(
                "^contacts/list-settings/",
                "shuup.admin.modules.settings.views.ListSettingsView",
                name="contact.list_settings",
                permissions=get_default_model_permissions(Contact),
            )
        ]

    def get_menu_entries(self, request):
        return [
            MenuEntry(
                text=_("Contacts"), icon="fa fa-users",
                url="shuup_admin:contact.list", category=CONTACTS_MENU_CATEGORY,
                ordering=1
            )
        ]

    def get_required_permissions(self):
        return (
            get_default_model_permissions(CompanyContact) |
            get_default_model_permissions(Contact) |
            get_default_model_permissions(PersonContact)
        )

    def get_search_results(self, request, query):
        minimum_query_length = 3
        if len(query) >= minimum_query_length:
            contacts = Contact.objects.filter(
                Q(name__icontains=query) |
                Q(email=query)
            )
            for i, contact in enumerate(contacts[:10]):
                relevance = 100 - i
                yield SearchResult(
                    text=six.text_type(contact), url=get_model_url(contact),
                    category=_("Contacts"), relevance=relevance
                )

    def get_model_url(self, object, kind):
        return derive_model_url(Contact, "shuup_admin:contact", object, kind)
Ejemplo n.º 5
0
class ImportAdminModule(AdminModule):
    name = _("Data Import")
    breadcrumbs_menu_entry = MenuEntry(name, url="shuup_admin:importer.import")

    def get_extra_permissions(self):
        extra_permissions = ["importer.show-all-imports"]
        importers_permissions = [importer.get_permission_identifier() for importer in get_provide_objects("importers")]
        return extra_permissions + importers_permissions

    def get_permissions_help_texts(self):
        help_texts = {
            "importer.show-all-imports": _("Allow the user to see the imports from all shops and suppliers."),
            "importer.import_process": _("Allow the user to run importers."),
            "importer.import": _("Allow the user to list imports."),
            "importer.import.new": _("Allow the user to import a file."),
            "importer.download_example": _("Allow the user to download sample files."),
        }

        for importer in get_provide_objects("importers"):
            help_texts[importer.get_permission_identifier()] = _(
                "Allow the user to use the {importer_name} importer."
            ).format(importer_name=importer.name)

        return help_texts

    def get_urls(self):
        return [
            admin_url(
                "^importer/imports/$", "shuup.importer.admin_module.import_views.ImportListView", name="importer.import"
            ),
            admin_url(
                r"^importer/imports/(?P<pk>.+)/$",
                "shuup.importer.admin_module.import_views.ImportDetailView",
                name="importer.import.detail",
            ),
            admin_url(
                "^importer/new/$",
                "shuup.importer.admin_module.import_views.ImportView",
                name="importer.import.new",
            ),
            admin_url(
                "^importer/process$",
                "shuup.importer.admin_module.import_views.ImportProcessView",
                name="importer.import_process",
            ),
            admin_url(
                "^importer/example$",
                "shuup.importer.admin_module.import_views.ExampleFileDownloadView",
                name="importer.download_example",
            ),
        ]

    def get_menu_entries(self, request):
        return [
            MenuEntry(
                text=_("Data Import"),
                category=SETTINGS_MENU_CATEGORY,
                url="shuup_admin:importer.import",
                icon="fa fa-star",
            )
        ]
Ejemplo n.º 6
0
class OrderModule(AdminModule):
    name = _("Orders")
    breadcrumbs_menu_entry = MenuEntry(name, url="shuup_admin:order.list")

    def get_urls(self):
        return [
            admin_url(
                "^orders/(?P<pk>\d+)/create-shipment/$",
                "shuup.admin.modules.orders.views.OrderCreateShipmentView",
                name="order.create-shipment",
                permissions=["shuup.add_shipment"]),
            admin_url("^shipments/(?P<pk>\d+)/delete/$",
                      "shuup.admin.modules.orders.views.ShipmentDeleteView",
                      name="order.delete-shipment",
                      permissions=["shuup.delete_shipment"]),
            admin_url(
                "^orders/(?P<pk>\d+)/create-payment/$",
                "shuup.admin.modules.orders.views.OrderCreatePaymentView",
                name="order.create-payment",
                permissions=["shuup.add_payment"]),
            admin_url("^orders/(?P<pk>\d+)/set-paid/$",
                      "shuup.admin.modules.orders.views.OrderSetPaidView",
                      name="order.set-paid",
                      permissions=["shuup.add_payment"]),
            admin_url("^orders/(?P<pk>\d+)/set-status/$",
                      "shuup.admin.modules.orders.views.OrderSetStatusView",
                      name="order.set-status",
                      permissions=get_default_model_permissions(Order)),
            admin_url("^orders/(?P<pk>\d+)/new-log-entry/$",
                      "shuup.admin.modules.orders.views.NewLogEntryView",
                      name="order.new-log-entry",
                      permissions=get_default_model_permissions(Order)),
            admin_url(
                "^orders/(?P<pk>\d+)/update-admin-comment/$",
                "shuup.admin.modules.orders.views.UpdateAdminCommentView",
                name="order.update-admin-comment",
                permissions=get_default_model_permissions(Order)),
            admin_url("^orders/(?P<pk>\d+)/create-refund/$",
                      "shuup.admin.modules.orders.views.OrderCreateRefundView",
                      name="order.create-refund",
                      permissions=get_default_model_permissions(Order)),
            admin_url(
                "^orders/(?P<pk>\d+)/create-refund/full-refund$",
                "shuup.admin.modules.orders.views.OrderCreateFullRefundView",
                name="order.create-full-refund",
                permissions=get_default_model_permissions(Order)),
            admin_url("^orders/(?P<pk>\d+)/$",
                      "shuup.admin.modules.orders.views.OrderDetailView",
                      name="order.detail",
                      permissions=get_default_model_permissions(Order)),
            admin_url("^orders/new/$",
                      "shuup.admin.modules.orders.views.OrderEditView",
                      name="order.new",
                      permissions=["shuup.add_order"]),
            admin_url("^orders/(?P<pk>\d+)/edit/$",
                      "shuup.admin.modules.orders.views.OrderEditView",
                      name="order.edit",
                      permissions=["shuup.change_order"]),
            admin_url(
                "^orders/$",
                "shuup.admin.modules.orders.views.OrderListView",
                name="order.list",
                permissions=get_default_model_permissions(Order),
            ),
            admin_url(
                "^orders/list-settings/",
                "shuup.admin.modules.settings.views.ListSettingsView",
                name="order.list_settings",
                permissions=get_default_model_permissions(Order),
            )
        ]

    def get_menu_entries(self, request):
        return [
            MenuEntry(text=_("Orders"),
                      icon="fa fa-inbox",
                      url="shuup_admin:order.list",
                      category=ORDERS_MENU_CATEGORY,
                      ordering=1,
                      aliases=[_("Show orders")]),
        ]

    def get_required_permissions(self):
        return (get_permissions_from_urls(self.get_urls())
                | get_default_model_permissions(Contact)
                | get_default_model_permissions(Order)
                | get_default_model_permissions(Product))

    def get_search_results(self, request, query):
        minimum_query_length = 3
        if len(query) >= minimum_query_length:
            orders = Order.objects.filter(
                Q(identifier__istartswith=query)
                | Q(reference_number__istartswith=query)
                | Q(email__icontains=query)
                | Q(phone__icontains=query)).order_by("-id")[:15]

            for i, order in enumerate(orders):
                relevance = 100 - i
                yield SearchResult(text=six.text_type(order),
                                   url=get_model_url(order),
                                   category=_("Orders"),
                                   relevance=relevance)

    def get_notifications(self, request):
        old_open_orders = Order.objects.filter(
            status__role=OrderStatusRole.INITIAL,
            order_date__lt=now() - timedelta(days=4)).count()

        if old_open_orders:
            yield Notification(title=_("Outstanding Orders"),
                               text=_("%d outstanding orders") %
                               old_open_orders,
                               kind="danger")

    def get_model_url(self, object, kind):
        return derive_model_url(Order, "shuup_admin:order", object, kind)
Ejemplo n.º 7
0
 def get_menu_entries(self, request):
     return [
         MenuEntry(
             text=self.name, icon="fa fa-image", url="shuup_admin:reports.list", category=REPORTS_MENU_CATEGORY
         )
     ]
Ejemplo n.º 8
0
 def get_breadcrumb_parents(self):
     return [
         MenuEntry(text="%s" % self.object,
                   url=get_model_url(self.object, shop=self.request.shop))
     ]
Ejemplo n.º 9
0
class CategoryModule(AdminModule):
    name = _("Categories")
    category = _("Categories")
    breadcrumbs_menu_entry = MenuEntry(text=name,
                                       url="shuup_admin:category.list",
                                       category=PRODUCTS_MENU_CATEGORY)

    def get_urls(self):
        return [
            admin_url(
                r"^categories/(?P<pk>\d+)/copy-visibility/$",
                "shuup.admin.modules.categories.views.CategoryCopyVisibilityView",
                name="category.copy_visibility",
            ),
            admin_url(
                r"^categories/(?P<pk>\d+)/delete/$",
                "shuup.admin.modules.categories.views.CategoryDeleteView",
                name="category.delete",
            ),
        ] + get_edit_and_list_urls(
            url_prefix="^categories",
            view_template="shuup.admin.modules.categories.views.Category%sView",
            name_template="category.%s",
        )

    def get_menu_entries(self, request):
        return [
            MenuEntry(
                text=_("Categories"),
                icon="fa fa-sitemap",
                url="shuup_admin:category.list",
                category=PRODUCTS_MENU_CATEGORY,
                ordering=2,
            )
        ]

    def get_search_results(self, request, query):
        minimum_query_length = 3

        if len(query) >= minimum_query_length:
            shop = get_shop(request)
            categories = (Category.objects.all_except_deleted(
                shop=shop).filter(
                    Q(translations__name__icontains=query)
                    | Q(identifier__icontains=query)).distinct().order_by(
                        "tree_id", "lft"))
            for i, category in enumerate(categories[:10]):
                relevance = 100 - i
                yield SearchResult(
                    text=six.text_type(category),
                    url=get_model_url(category),
                    category=self.category,
                    relevance=relevance,
                )

    def get_help_blocks(self, request, kind):
        from shuup.admin.utils.permissions import has_permission

        if has_permission(request.user, "category.new"):
            yield SimpleHelpBlock(
                text=_("Add a product category to organize your products."),
                actions=[{
                    "text": _("New category"),
                    "url": get_model_url(Category, "new")
                }],
                icon_url="shuup_admin/img/category.png",
                category=HelpBlockCategory.PRODUCTS,
                priority=1,
                done=Category.objects.filter(
                    shops=request.shop).exists() if kind == "setup" else False,
            )

    def get_model_url(self, object, kind, shop=None):
        return derive_model_url(Category, "shuup_admin:category", object, kind)

    def get_extra_permissions(self) -> Iterable[str]:
        return [get_object_selector_permission_name(Category)]

    def get_permissions_help_texts(self) -> Iterable[str]:
        return {
            get_object_selector_permission_name(Category):
            _("Allow the user to select categories in admin.")
        }
Ejemplo n.º 10
0
class TaskAdminModule(AdminModule):
    name = _("Tasks")
    breadcrumbs_menu_entry = MenuEntry(name, "shuup_admin:task.list")

    def get_urls(self):
        return get_edit_and_list_urls(
            url_prefix="^tasks",
            view_template="shuup.tasks.admin_module.views.Task%sView",
            name_template="task.%s",
            permissions=get_default_model_permissions(Task)
        ) + [
            admin_url(
                "^tasks/(?P<pk>\d+)/delete/$",
                "shuup.tasks.admin_module.views.TaskDeleteView",
                name="task.delete",
                permissions=get_default_model_permissions(Task)
            ),
            admin_url(
                "^tasks/(?P<pk>\d+)/set_status/$",
                "shuup.tasks.admin_module.views.TaskSetStatusView",
                name="task.set_status",
                permissions=get_default_model_permissions(Task)
            ),
        ]

    def get_menu_entries(self, request):
        return [
            MenuEntry(
                text=_("Tasks"),
                icon="fa fa-file-text",
                url="shuup_admin:task.list",
                category=CONTACTS_MENU_CATEGORY,
                ordering=4,
                aliases=[_("Show Tasks")]
            )
        ]

    def get_required_permissions(self):
        return get_default_model_permissions(Task)

    def get_model_url(self, object, kind, shop=None):
        return derive_model_url(Task, "shuup_admin:task", object, kind)

    def get_dashboard_blocks(self, request):
        """ Return the latest 10 pending tasks """
        contact = get_person_contact(request.user)
        tasks = (
            Task.objects.for_shop(get_shop(request))
            .assigned_to(contact)
            .exclude(status__in=(TaskStatus.DELETED, TaskStatus.COMPLETED))
            .order_by("-priority")
        )[:10]

        if tasks.exists():
            tasks_block = DashboardContentBlock.by_rendering_template(
                "articles",
                request,
                "shuup/admin/tasks/tasks_dashboard_block.jinja",
                context=dict(tasks=tasks)
            )
            tasks_block.size = "medium"
            yield tasks_block

    def get_search_results(self, request, query):
        shop = get_shop(request)

        if len(query) >= 3:
            contact = get_person_contact(request.user)
            tasks = (
                Task.objects
                .for_shop(get_shop(request))
                .filter(name__icontains=query)
                .assigned_to(contact)
                .exclude(status__in=(TaskStatus.DELETED, TaskStatus.COMPLETED))
            )
            for task in tasks:
                yield SearchResult(
                    text=force_text("{task_name} [{task_status}]".format(**dict(
                        task_name=task.name,
                        task_status=task.status
                    ))),
                    url=get_model_url(task, shop=shop),
                    category=_("Tasks")
                )
Ejemplo n.º 11
0
    def infer(cls, context):
        """
        Infer breadcrumbs from the rendering context.

        :param context: Jinja Context
        :type context: jinja2.runtime.Context
        :return: Breadcrumbs object or None if things fail
        :rtype: Breadcrumbs|None
        """
        request = context["request"]
        if not getattr(request, "resolver_match", None):
            # If we don't have a resolver match, we can't infer anything.
            return None

        url_names = (
            request.resolver_match.url_name,
            "%s:%s" % (request.resolver_match.app_name, request.resolver_match.url_name)
        )
        url_admin_module = _get_admin_module_for_url(url_names)

        # Synthesize a menu entry for the current view.
        current_view_entry = MenuEntry(url=request.path, text="")

        if url_admin_module:
            # See if we have an idea for the title of this view from the menu entries
            for entry in url_admin_module.get_menu_entries(request):
                if entry.original_url in url_names:
                    current_view_entry.text = entry.text
                    break

        # See if we have a title for the synthesized entry in the context.
        view = context.get("view")  # This should be the CBV view object.
        title = (
            context.get("title") or
            context.get("breadcrumb_title") or
            (view and getattr(view, "title", None))
        )

        if title:
            current_view_entry.text = force_text(title)

        # Begin building the entries...

        entries = []

        # See if we have the top level menu entry ("Contacts" for example).
        if url_admin_module and url_admin_module.breadcrumbs_menu_entry:
            # (But don't duplicate steps)
            if url_admin_module.breadcrumbs_menu_entry.url != request.path or not current_view_entry.text:
                entries.append(url_admin_module.breadcrumbs_menu_entry)

        # See if the view declares parents...
        parent_getter = getattr(view, "get_breadcrumb_parents", None)
        if parent_getter:
            entries.extend(parent_getter() or ())

        # If the current entry seems valid (would be visible), then go for it!
        if current_view_entry.text:
            entries.append(current_view_entry)

        return cls(entries)
Ejemplo n.º 12
0
class ContactModule(AdminModule):
    name = _("Contacts")
    category = name
    breadcrumbs_menu_entry = MenuEntry(text=name,
                                       url="shuup_admin:contact.list")

    def get_urls(self):
        return [
            admin_url(
                "^contacts/new/$",
                "shuup.admin.modules.contacts.views.ContactEditView",
                kwargs={"pk": None},
                name="contact.new",
                permissions=["shuup.add_contact"],
            ),
            admin_url(
                "^contacts/(?P<pk>\d+)/edit/$",
                "shuup.admin.modules.contacts.views.ContactEditView",
                name="contact.edit",
                permissions=["shuup.change_contact"],
            ),
            admin_url(
                "^contacts/(?P<pk>\d+)/$",
                "shuup.admin.modules.contacts.views.ContactDetailView",
                name="contact.detail",
                permissions=get_default_model_permissions(Contact),
            ),
            admin_url(
                "^contacts/reset-password/(?P<pk>\d+)/$",
                "shuup.admin.modules.contacts.views.ContactResetPasswordView",
                name="contact.reset_password",
                permissions=get_default_model_permissions(Contact),
            ),
            admin_url(
                "^contacts/$",
                "shuup.admin.modules.contacts.views.ContactListView",
                name="contact.list",
                permissions=get_default_model_permissions(Contact),
            ),
        ]

    def get_menu_category_icons(self):
        return {self.category: "fa fa-users"}

    def get_menu_entries(self, request):
        return [
            MenuEntry(text=_("Contacts"),
                      icon="fa fa-users",
                      url="shuup_admin:contact.list",
                      category=self.category)
        ]

    def get_required_permissions(self):
        return get_permissions_from_urls(
            self.get_urls()) | get_default_model_permissions(Contact)

    def get_search_results(self, request, query):
        minimum_query_length = 3
        if len(query) >= minimum_query_length:
            contacts = Contact.objects.filter(
                Q(name__icontains=query) | Q(email=query))
            for i, contact in enumerate(contacts[:10]):
                relevance = 100 - i
                yield SearchResult(text=six.text_type(contact),
                                   url=get_model_url(contact),
                                   category=self.category,
                                   relevance=relevance)

    def get_dashboard_blocks(self, request):
        yield get_active_customers_block(request)

    def get_model_url(self, object, kind):
        return derive_model_url(Contact, "shuup_admin:contact", object, kind)
Ejemplo n.º 13
0
class OrderModule(AdminModule):
    name = _("Orders")
    breadcrumbs_menu_entry = MenuEntry(name, url="shuup_admin:order.list")

    def get_urls(self):
        return [
            admin_url(
                "^orders/(?P<pk>\d+)/create-shipment/$",
                "shuup.admin.modules.orders.views.OrderCreateShipmentView",
                name="order.create-shipment",
                permissions=["shuup.add_shipment"]),
            admin_url("^shipments/(?P<pk>\d+)/delete/$",
                      "shuup.admin.modules.orders.views.ShipmentDeleteView",
                      name="order.delete-shipment",
                      permissions=["shuup.delete_shipment"]),
            admin_url(
                "^orders/(?P<pk>\d+)/create-payment/$",
                "shuup.admin.modules.orders.views.OrderCreatePaymentView",
                name="order.create-payment",
                permissions=["shuup.add_payment"]),
            admin_url("^orders/(?P<pk>\d+)/set-paid/$",
                      "shuup.admin.modules.orders.views.OrderSetPaidView",
                      name="order.set-paid",
                      permissions=["shuup.add_payment"]),
            admin_url("^orders/(?P<pk>\d+)/set-status/$",
                      "shuup.admin.modules.orders.views.OrderSetStatusView",
                      name="order.set-status",
                      permissions=get_default_model_permissions(Order)),
            admin_url("^orders/(?P<pk>\d+)/new-log-entry/$",
                      "shuup.admin.modules.orders.views.NewLogEntryView",
                      name="order.new-log-entry",
                      permissions=get_default_model_permissions(Order)),
            admin_url(
                "^orders/(?P<pk>\d+)/update-admin-comment/$",
                "shuup.admin.modules.orders.views.UpdateAdminCommentView",
                name="order.update-admin-comment",
                permissions=get_default_model_permissions(Order)),
            admin_url("^orders/(?P<pk>\d+)/create-refund/$",
                      "shuup.admin.modules.orders.views.OrderCreateRefundView",
                      name="order.create-refund",
                      permissions=get_default_model_permissions(Order)),
            admin_url(
                "^orders/(?P<pk>\d+)/create-refund/full-refund$",
                "shuup.admin.modules.orders.views.OrderCreateFullRefundView",
                name="order.create-full-refund",
                permissions=get_default_model_permissions(Order)),
            admin_url("^orders/(?P<pk>\d+)/$",
                      "shuup.admin.modules.orders.views.OrderDetailView",
                      name="order.detail",
                      permissions=get_default_model_permissions(Order)),
            admin_url("^orders/new/$",
                      "shuup.admin.modules.orders.views.OrderEditView",
                      name="order.new",
                      permissions=["shuup.add_order"]),
            admin_url("^orders/(?P<pk>\d+)/edit/$",
                      "shuup.admin.modules.orders.views.OrderEditView",
                      name="order.edit",
                      permissions=["shuup.change_order"]),
            admin_url(
                "^orders/$",
                "shuup.admin.modules.orders.views.OrderListView",
                name="order.list",
                permissions=get_default_model_permissions(Order),
            ),
            admin_url(
                "^orders/list-settings/",
                "shuup.admin.modules.settings.views.ListSettingsView",
                name="order.list_settings",
                permissions=get_default_model_permissions(Order),
            ),
            admin_url("^orders/(?P<pk>\d+)/edit-addresses/$",
                      "shuup.admin.modules.orders.views.OrderAddressEditView",
                      name="order.edit-addresses",
                      permissions=["shuup.change_order"]),
        ] + get_edit_and_list_urls(
            url_prefix="^order-status",
            view_template="shuup.admin.modules.orders.views.OrderStatus%sView",
            name_template="order_status.%s",
            permissions=get_default_model_permissions(OrderStatus))

    def get_menu_entries(self, request):
        return [
            MenuEntry(text=_("Orders"),
                      icon="fa fa-inbox",
                      url="shuup_admin:order.list",
                      category=ORDERS_MENU_CATEGORY,
                      ordering=1,
                      aliases=[_("Show orders")]),
            # MenuEntry(
            #     text=_("Order Status"),
            #     icon="fa fa-inbox",
            #     url="shuup_admin:order_status.list",
            #     category=STOREFRONT_MENU_CATEGORY,
            #     subcategory="settings",
            #     ordering=1,
            #     aliases=[_("List Statuses")]
            # ),
        ]

    def get_required_permissions(self):
        return (get_permissions_from_urls(self.get_urls())
                | get_default_model_permissions(Contact)
                | get_default_model_permissions(Order)
                | get_default_model_permissions(Product))

    def get_search_results(self, request, query):
        minimum_query_length = 3
        if len(query) >= minimum_query_length:
            orders = Order.objects.filter(
                Q(identifier__istartswith=query)
                | Q(reference_number__istartswith=query)
                | Q(email__icontains=query)
                | Q(phone__icontains=query)).order_by("-id")[:15]

            for i, order in enumerate(orders):
                relevance = 100 - i
                yield SearchResult(text=six.text_type(order),
                                   url=get_model_url(order),
                                   category=_("Orders"),
                                   relevance=relevance)

    def get_notifications(self, request):
        old_open_orders = Order.objects.filter(
            status__role=OrderStatusRole.INITIAL,
            order_date__lt=now() - timedelta(days=4)).count()

        if old_open_orders:
            yield Notification(title=_("Outstanding Orders"),
                               text=_("%d outstanding orders") %
                               old_open_orders,
                               kind="danger")

    def get_model_url(self, object, kind):
        if hasattr(object, "role"):
            return derive_model_url(OrderStatus, "shuup_admin:order_status",
                                    object, kind)
        return derive_model_url(Order, "shuup_admin:order", object, kind)

    def get_help_blocks(self, request, kind):
        if kind == "quicklink":
            actions = [{
                "text": _("New order"),
                "url": self.get_model_url(Order, "new")
            }]

            yield SimpleHelpBlock(
                text=_("New order"),
                actions=actions,
                icon_url="shuup_admin/img/product.png",
                priority=0,
                category=HelpBlockCategory.ORDERS,
                done=Order.objects.exists() if kind == "setup" else False)
Ejemplo n.º 14
0
class XthemeAdminModule(AdminModule):
    """
    Admin module for Xtheme.

    Allows theme activation/deactivation and further configuration.
    """

    name = _("Shuup Extensible Theme Engine")
    breadcrumbs_menu_entry = MenuEntry(_("Themes"), "shuup_admin:xtheme.config", category=CONTENT_MENU_CATEGORY)

    def get_urls(self):  # doccov: ignore
        return [
            admin_url(
                r"^xtheme/guide/(?P<theme_identifier>.+?)/",
                "shuup.xtheme.admin_module.views.ThemeGuideTemplateView",
                name="xtheme.guide",
            ),
            admin_url(
                r"^xtheme/configure/(?P<theme_identifier>.+?)/",
                "shuup.xtheme.admin_module.views.ThemeConfigDetailView",
                name="xtheme.config_detail",
            ),
            admin_url(r"^xtheme/theme", "shuup.xtheme.admin_module.views.ThemeConfigView", name="xtheme.config"),
        ]

    def get_menu_entries(self, request):  # doccov: ignore
        return [
            MenuEntry(
                text=_("Themes"),
                icon="fa fa-paint-brush",
                url="shuup_admin:xtheme.config",
                category=CONTENT_MENU_CATEGORY,
                ordering=1,
            )
        ]

    def get_help_blocks(self, request, kind):
        theme = getattr(request, "theme", None) or get_current_theme(request.shop)
        if kind == "quicklink" and theme:
            yield SimpleHelpBlock(
                text=_("Customize the look and feel of your shop"),
                actions=[
                    {
                        "text": _("Customize theme"),
                        "url": reverse(
                            "shuup_admin:xtheme.config_detail", kwargs={"theme_identifier": theme.identifier}
                        ),
                    }
                ],
                priority=200,
                category=HelpBlockCategory.STOREFRONT,
                icon_url="xtheme/theme.png",
            )

    def get_notifications(self, request):
        try:
            engine = engines["jinja2"]
        except KeyError:
            engine = None

        if engine and isinstance(engine, Jinja2):  # The engine is what we expect...
            if isinstance(engine.env, XthemeEnvironment):  # ... and it's capable of loading themes...
                if not (getattr(request, "theme", None) or get_current_theme(request.shop)):
                    # ... but there's no theme active?!
                    # Panic!
                    yield Notification(
                        text=_("No theme is active. Click here to activate one."),
                        title=_("Theming"),
                        url="shuup_admin:xtheme.config",
                    )
Ejemplo n.º 15
0
class ShopModule(AdminModule):
    name = _("Shops")
    breadcrumbs_menu_entry = MenuEntry(name, url="shuup_admin:shop.list")

    def get_urls(self):
        return [
            admin_url("^shops/(?P<pk>\d+)/enable/$",
                      "shuup.admin.modules.shops.views.ShopEnablerView",
                      name="shop.enable",
                      permissions=get_default_model_permissions(Shop)),
            admin_url("^shops/(?P<pk>\d+)/select/$",
                      "shuup.admin.modules.shops.views.ShopSelectView",
                      name="shop.select",
                      permissions=get_default_model_permissions(Shop)),
        ] + get_edit_and_list_urls(
            url_prefix="^shops",
            view_template="shuup.admin.modules.shops.views.Shop%sView",
            name_template="shop.%s",
            permissions=get_default_model_permissions(Shop))

    def get_menu_entries(self, request):
        return [
            MenuEntry(text=self.name,
                      icon="fa fa-house",
                      url="shuup_admin:shop.list",
                      category=STOREFRONT_MENU_CATEGORY,
                      subcategory="settings",
                      ordering=4),
        ]

    def get_help_blocks(self, request, kind):
        if kind == "setup":
            shop = request.shop
            yield SimpleHelpBlock(
                text=_("Add a logo to make your store stand out"),
                actions=[{
                    "text": _("Add logo"),
                    "url": self.get_model_url(shop, "edit"),
                    "hash": "#shop-images-section"
                }],
                icon_url="shuup_admin/img/logo_icon.svg",
                done=shop.logo,
                required=False)

    def get_required_permissions(self):
        return get_default_model_permissions(
            Shop) | get_default_model_permissions(File)

    def get_model_url(self, object, kind, shop=None):
        return derive_model_url(Shop, "shuup_admin:shop", object, kind)

    def get_search_results(self, request, query):
        if not settings.SHUUP_ENABLE_MULTIPLE_SHOPS:
            return

        minimum_query_length = 3
        if len(query) >= minimum_query_length:
            shops = Shop.objects.get_for_user(request.user).filter(
                translations__name__icontains=query, status=ShopStatus.ENABLED)
            for i, shop in enumerate(shops[:10]):
                relevance = 100 - i
                yield SearchResult(
                    text=(_('Set "{}" as the active shop')).format(shop.name),
                    url=get_model_url(shop, "select"),
                    category=(
                        _("Available Shops [currently active: {}]")).format(
                            request.shop.name),
                    relevance=relevance)
Ejemplo n.º 16
0
class CategoryModule(AdminModule):
    name = _("Categories")
    category = _("Products")
    breadcrumbs_menu_entry = MenuEntry(text=name, url="shuup_admin:category.list", category=PRODUCTS_MENU_CATEGORY)

    def get_urls(self):
        return [
            admin_url(
                "^categories/(?P<pk>\d+)/copy-visibility/$",
                "shuup.admin.modules.categories.views.CategoryCopyVisibilityView",
                name="category.copy_visibility",
                permissions=get_default_model_permissions(Category)
            ),
            admin_url(
                "^categories/(?P<pk>\d+)/delete/$",
                "shuup.admin.modules.categories.views.CategoryDeleteView",
                name="category.delete",
                permissions=get_default_model_permissions(Category)
            ),
        ] + get_edit_and_list_urls(
            url_prefix="^categories",
            view_template="shuup.admin.modules.categories.views.Category%sView",
            name_template="category.%s",
            permissions=get_default_model_permissions(Category),
        )

    def get_menu_entries(self, request):
        return [
            MenuEntry(
                text=_("Categories"), icon="fa fa-sitemap",
                url="shuup_admin:category.list", category=PRODUCTS_MENU_CATEGORY, ordering=2
            )
        ]

    def get_search_results(self, request, query):
        minimum_query_length = 3
        if len(query) >= minimum_query_length:
            categories = Category.objects.filter(
                Q(translations__name__icontains=query) |
                Q(identifier__icontains=query)
            ).distinct().order_by("tree_id", "lft")
            for i, category in enumerate(categories[:10]):
                relevance = 100 - i
                yield SearchResult(
                    text=six.text_type(category),
                    url=get_model_url(category),
                    category=self.category,
                    relevance=relevance
                )

    def get_help_blocks(self, request, kind):
        yield SimpleHelpBlock(
            text=_("Add a product category to organize your products"),
            actions=[{
                "text": _("Add a category"),
                "url": get_model_url(Category, "new")
            }],
            icon_url="shuup_admin/img/category.png",
            priority=0,
            done=Category.objects.exists() if kind == "setup" else False
        )

    def get_required_permissions(self):
        return get_default_model_permissions(Category) | get_default_model_permissions(File)

    def get_model_url(self, object, kind):
        return derive_model_url(Category, "shuup_admin:category", object, kind)
Ejemplo n.º 17
0
 def get_breadcrumb_parents(self):
     return [MenuEntry(text=self.parent_name, url=self.parent_url)]
Ejemplo n.º 18
0
 def get_breadcrumb_parents(self):
     return [
         MenuEntry(text=force_text(
             self.model._meta.verbose_name_plural).title(),
                   url="shuup_admin:service_provider.list")
     ]
Ejemplo n.º 19
0
    def infer(cls, context):
        """
        Infer breadcrumbs from the rendering context.

        :param context: Jinja Context
        :type context: jinja2.runtime.Context
        :return: Breadcrumbs object or None if things fail
        :rtype: Breadcrumbs|None
        """
        request = context["request"]
        if not getattr(request, "resolver_match", None):
            # If we don't have a resolver match, we can't infer anything.
            return None

        url_names = (
            request.resolver_match.url_name,
            "%s:%s" % (request.resolver_match.app_name, request.resolver_match.url_name)
        )
        url_admin_module = _get_admin_module_for_url(url_names)

        # Synthesize a menu entry for the current view.
        current_view_entry = MenuEntry(url=request.path, text="")

        if url_admin_module:
            # See if we have an idea for the title of this view from the menu entries
            for entry in url_admin_module.get_menu_entries(request):
                if entry.original_url in url_names:
                    current_view_entry.text = entry.text
                    break

        # See if we have a title for the synthesized entry in the context.
        view = context.get("view")  # This should be the CBV view object.
        title = (
            context.get("title") or
            context.get("breadcrumb_title") or
            (view and getattr(view, "title", None))
        )

        if title:
            current_view_entry.text = force_text(title)

        # Begin building the entries...

        entries = []

        # See if we have the top level menu entry ("Contacts" for example).
        if url_admin_module and url_admin_module.breadcrumbs_menu_entry:
            # (But don't duplicate steps)
            if url_admin_module.breadcrumbs_menu_entry.url != request.path or not current_view_entry.text:
                entries.append(url_admin_module.breadcrumbs_menu_entry)

        # See if the view declares parents...
        parent_getter = getattr(view, "get_breadcrumb_parents", None)
        if parent_getter:
            entries.extend(parent_getter() or ())

        # If the current entry seems valid (would be visible), then go for it!
        if current_view_entry.text:
            entries.append(current_view_entry)

        return cls(entries)
Ejemplo n.º 20
0
class ProductModule(AdminModule):
    name = _("Products")
    breadcrumbs_menu_entry = MenuEntry(name,
                                       url="shuup_admin:shop_product.list")

    def get_urls(self):
        return [
            admin_url(r"^products/(?P<pk>\d+)/delete/$",
                      "shuup.admin.modules.products.views.ProductDeleteView",
                      name="shop_product.delete"),
            admin_url(
                r"^products/(?P<pk>\d+)/media/$",
                "shuup.admin.modules.products.views.ProductMediaEditView",
                name="shop_product.edit_media"),
            admin_url(
                r"^products/(?P<pk>\d+)/media/add/$",
                "shuup.admin.modules.products.views.ProductMediaBulkAdderView",
                name="shop_product.add_media"),
            admin_url(
                r"^products/(?P<pk>\d+)/crosssell/$",
                "shuup.admin.modules.products.views.ProductCrossSellEditView",
                name="shop_product.edit_cross_sell"),
            admin_url(
                r"^products/(?P<pk>\d+)/variation/$",
                "shuup.admin.modules.products.views.ProductVariationView",
                name="shop_product.edit_variation"),
            admin_url(r"^products/(?P<pk>\d+)/package/$",
                      "shuup.admin.modules.products.views.ProductPackageView",
                      name="shop_product.edit_package"),
            admin_url(r"^products/mass-edit/$",
                      "shuup.admin.modules.products.views.ProductMassEditView",
                      name="shop_product.mass_edit"),
            admin_url(
                r"^products/(?P<pk>\d+)/copy/$",
                "shuup.admin.modules.products.views.copy.ProductCopyView",
                name="shop_product.copy"),
        ] + get_edit_and_list_urls(
            url_prefix="^products",
            view_template="shuup.admin.modules.products.views.Product%sView",
            name_template="shop_product.%s")

    def get_menu_entries(self, request):
        return [
            MenuEntry(text=_("Products"),
                      icon="fa fa-cube",
                      url="shuup_admin:shop_product.list",
                      category=PRODUCTS_MENU_CATEGORY,
                      ordering=1)
        ]

    def get_search_results(self, request, query):
        shop = request.shop
        minimum_query_length = 3
        skus_seen = set()
        if len(query) >= minimum_query_length:
            pk_counter = Counter()
            pk_counter.update(
                Product.objects.filter(sku__startswith=query).values_list(
                    "pk", flat=True))
            name_q = Q()
            for part in split_query(query, minimum_query_length):
                name_q &= Q(name__icontains=part)
            pk_counter.update(
                Product._parler_meta.root_model.objects.filter(
                    name_q).values_list("master_id", flat=True))
            pks = [pk for (pk, count) in pk_counter.most_common(10)]

            for product in Product.objects.filter(
                    pk__in=pks, shop_products__shop_id=shop.id):
                relevance = 100 - pk_counter.get(product.pk, 0)
                skus_seen.add(product.sku.lower())
                yield SearchResult(text=force_text(product),
                                   url=get_model_url(product,
                                                     shop=request.shop),
                                   category=_("Products"),
                                   relevance=relevance)

        if len(query) >= minimum_query_length:
            url = reverse("shuup_admin:shop_product.new")
            if " " in query:
                yield SearchResult(
                    text=_("Create Product Called \"%s\"") % query,
                    url=manipulate_query_string(url, name=query),
                    is_action=True)
            else:
                if query.lower() not in skus_seen:
                    yield SearchResult(
                        text=_("Create Product with SKU \"%s\"") % query,
                        url=manipulate_query_string(url, sku=query),
                        is_action=True)

    def get_help_blocks(self, request, kind):
        actions = []

        from shuup.admin.utils.permissions import has_permission
        if has_permission(request.user, "shop_product.new"):
            actions.append({
                "text": _("New product"),
                "url": self.get_model_url(ShopProduct, "new")
            })
        if "shuup.importer" in settings.INSTALLED_APPS and has_permission(
                request.user, "importer.import"):
            actions.append({
                "text": _("Import"),
                "url": reverse("shuup_admin:importer.import")
            })

        if actions:
            yield SimpleHelpBlock(
                text=_("Add a product to see it in your store"),
                actions=actions,
                icon_url="shuup_admin/img/product.png",
                priority=0,
                category=HelpBlockCategory.PRODUCTS,
                done=Product.objects.filter(
                    shop_products__shop=request.shop).exists()
                if kind == "setup" else False)

    def get_model_url(self, object, kind, shop=None):
        if isinstance(object, Product):
            if not shop:
                try:
                    shop = object.shop_products.first().shop
                except ObjectDoesNotExist:
                    return None
            object = object.get_shop_instance(shop)
        return derive_model_url(ShopProduct, "shuup_admin:shop_product",
                                object, kind)
Ejemplo n.º 21
0
 def get_menu_entries(self, request):
     return [
         MenuEntry(text=self.name,
                   url=self.menu_entry_url,
                   category=self.category)
     ]
Ejemplo n.º 22
0
class ProductModule(AdminModule):
    name = _("Products")
    breadcrumbs_menu_entry = MenuEntry(name, url="shuup_admin:product.list")

    def get_urls(self):
        return [
            admin_url("^products/(?P<pk>\d+)/delete/$",
                      "shuup.admin.modules.products.views.ProductDeleteView",
                      name="product.delete",
                      permissions=["shuup.delete_product"]),
            admin_url(
                "^products/(?P<pk>\d+)/media/$",
                "shuup.admin.modules.products.views.ProductMediaEditView",
                name="product.edit_media",
                permissions=get_default_model_permissions(Product),
            ),
            admin_url(
                "^products/(?P<pk>\d+)/crosssell/$",
                "shuup.admin.modules.products.views.ProductCrossSellEditView",
                name="product.edit_cross_sell",
                permissions=get_default_model_permissions(ProductCrossSell),
            ),
            admin_url(
                "^products/(?P<pk>\d+)/variation/$",
                "shuup.admin.modules.products.views.ProductVariationView",
                name="product.edit_variation",
                permissions=get_default_model_permissions(
                    ProductVariationResult),
            ),
            admin_url(
                "^products/(?P<pk>\d+)/package/$",
                "shuup.admin.modules.products.views.ProductPackageView",
                name="product.edit_package",
                permissions=get_default_model_permissions(ProductPackageLink)),
            admin_url("^products/mass-edit/$",
                      "shuup.admin.modules.products.views.ProductMassEditView",
                      name="product.mass_edit",
                      permissions=get_default_model_permissions(Product))
        ] + get_edit_and_list_urls(
            url_prefix="^products",
            view_template="shuup.admin.modules.products.views.Product%sView",
            name_template="product.%s",
            permissions=get_default_model_permissions(Product))

    def get_menu_entries(self, request):
        return [
            MenuEntry(text=_("Products"),
                      icon="fa fa-cube",
                      url="shuup_admin:product.list",
                      category=PRODUCTS_MENU_CATEGORY,
                      ordering=1)
        ]

    def get_search_results(self, request, query):
        minimum_query_length = 3
        skus_seen = set()
        if len(query) >= minimum_query_length:
            pk_counter = Counter()
            pk_counter.update(
                Product.objects.filter(sku__startswith=query).values_list(
                    "pk", flat=True))
            name_q = Q()
            for part in split_query(query, minimum_query_length):
                name_q &= Q(name__icontains=part)
            pk_counter.update(
                Product._parler_meta.root_model.objects.filter(
                    name_q).values_list("master_id", flat=True))
            pks = [pk for (pk, count) in pk_counter.most_common(10)]
            for product in Product.objects.filter(pk__in=pks):
                relevance = 100 - pk_counter.get(product.pk, 0)
                skus_seen.add(product.sku.lower())
                yield SearchResult(text=force_text(product),
                                   url=get_model_url(product),
                                   category=_("Products"),
                                   relevance=relevance)

        if len(query) >= minimum_query_length:
            url = reverse("shuup_admin:product.new")
            if " " in query:
                yield SearchResult(
                    text=_("Create Product Called \"%s\"") % query,
                    url=manipulate_query_string(url, name=query),
                    is_action=True)
            else:
                if query.lower() not in skus_seen:
                    yield SearchResult(
                        text=_("Create Product with SKU \"%s\"") % query,
                        url=manipulate_query_string(url, sku=query),
                        is_action=True)

    def get_help_blocks(self, request, kind):
        actions = [{
            "text": _("Add a product"),
            "url": self.get_model_url(Product, "new")
        }]

        if "shuup.importer" in settings.INSTALLED_APPS:
            actions.append({
                "text": _("Import products"),
                "url": reverse("shuup_admin:importer.import")
            })

        yield SimpleHelpBlock(
            text=_("Add a product to see it in your store"),
            actions=actions,
            icon_url="shuup_admin/img/product.png",
            done=Product.objects.exists() if kind == "setup" else False)

    def get_required_permissions(self):
        return (get_permissions_from_urls(self.get_urls())
                | get_default_model_permissions(Product)
                | get_default_model_permissions(File))

    def get_model_url(self, object, kind):
        return derive_model_url(Product, "shuup_admin:product", object, kind)
Ejemplo n.º 23
0
 def get_breadcrumb_parents(self):
     return [
         MenuEntry(text="%s" % self.object, url=get_model_url(self.object))
     ]
Ejemplo n.º 24
0
class UserModule(AdminModule):
    name = _("Users")
    breadcrumbs_menu_entry = MenuEntry(name, url="shuup_admin:user.list")

    def get_urls(self):
        permissions = get_default_model_permissions(get_user_model())

        return [
            admin_url("^users/(?P<pk>\d+)/change-password/$",
                      "shuup.admin.modules.users.views.UserChangePasswordView",
                      name="user.change-password",
                      permissions=permissions),
            admin_url("^users/(?P<pk>\d+)/reset-password/$",
                      "shuup.admin.modules.users.views.UserResetPasswordView",
                      name="user.reset-password",
                      permissions=permissions),
            admin_url(
                "^users/(?P<pk>\d+)/change-permissions/$",
                "shuup.admin.modules.users.views.UserChangePermissionsView",
                name="user.change-permissions",
                permissions=["auth.change_permission"]),
            admin_url("^users/(?P<pk>\d+)/$",
                      "shuup.admin.modules.users.views.UserDetailView",
                      name="user.detail",
                      permissions=permissions),
            admin_url("^users/new/$",
                      "shuup.admin.modules.users.views.UserDetailView",
                      kwargs={"pk": None},
                      name="user.new",
                      permissions=permissions),
            admin_url("^users/$",
                      "shuup.admin.modules.users.views.UserListView",
                      name="user.list",
                      permissions=permissions),
            admin_url("^users/(?P<pk>\d+)/login/$",
                      "shuup.admin.modules.users.views.LoginAsUserView",
                      name="user.login-as",
                      permissions=permissions),
            admin_url(
                "^contacts/list-settings/",
                "shuup.admin.modules.settings.views.ListSettingsView",
                name="user.list_settings",
                permissions=permissions,
            )
        ]

    def get_menu_entries(self, request):
        return [
            MenuEntry(text=_("Users"),
                      icon="fa fa-users",
                      url="shuup_admin:user.list",
                      category=SETTINGS_MENU_CATEGORY,
                      ordering=1)
        ]

    def get_search_results(self, request, query):
        minimum_query_length = 3
        if len(query) >= minimum_query_length:
            users = get_user_model().objects.filter(
                Q(username__icontains=query) | Q(email=query))
            for i, user in enumerate(users[:10]):
                relevance = 100 - i
                yield SearchResult(text=six.text_type(user),
                                   url=get_model_url(user),
                                   category=_("Contacts"),
                                   relevance=relevance)

    def get_required_permissions(self):
        return get_default_model_permissions(get_user_model())

    def get_model_url(self, object, kind):
        return derive_model_url(get_user_model(), "shuup_admin:user", object,
                                kind)
Ejemplo n.º 25
0
class UserModule(AdminModule):
    name = _("Users")
    breadcrumbs_menu_entry = MenuEntry(name, url="shuup_admin:user.list")

    def get_urls(self):
        permissions = get_default_model_permissions(get_user_model())

        return [
            admin_url("^users/(?P<pk>\d+)/change-password/$",
                      "shuup.admin.modules.users.views.UserChangePasswordView",
                      name="user.change-password",
                      permissions=permissions),
            admin_url("^users/(?P<pk>\d+)/reset-password/$",
                      "shuup.admin.modules.users.views.UserResetPasswordView",
                      name="user.reset-password",
                      permissions=permissions),
            admin_url(
                "^users/(?P<pk>\d+)/change-permissions/$",
                "shuup.admin.modules.users.views.UserChangePermissionsView",
                name="user.change-permissions",
                permissions=["auth.change_permission"]),
            admin_url("^users/(?P<pk>\d+)/$",
                      "shuup.admin.modules.users.views.UserDetailView",
                      name="user.detail",
                      permissions=permissions),
            admin_url("^users/new/$",
                      "shuup.admin.modules.users.views.UserDetailView",
                      kwargs={"pk": None},
                      name="user.new",
                      permissions=permissions),
            admin_url("^users/$",
                      "shuup.admin.modules.users.views.UserListView",
                      name="user.list",
                      permissions=permissions),
            admin_url("^users/(?P<pk>\d+)/login/$",
                      "shuup.admin.modules.users.views.LoginAsUserView",
                      name="user.login-as",
                      permissions=permissions),
            admin_url(
                "^contacts/list-settings/",
                "shuup.admin.modules.settings.views.ListSettingsView",
                name="user.list_settings",
                permissions=permissions,
            )
        ]

    def get_menu_entries(self, request):
        return [
            MenuEntry(text=_("Users"),
                      icon="fa fa-users",
                      url="shuup_admin:user.list",
                      category=SETTINGS_MENU_CATEGORY,
                      subcategory="permissions",
                      ordering=1)
        ]

    def get_search_results(self, request, query):
        minimum_query_length = 3
        if len(query) >= minimum_query_length:
            users = get_user_model().objects.filter(
                Q(username__icontains=query) | Q(email=query))
            for i, user in enumerate(users[:10]):
                relevance = 100 - i
                yield SearchResult(text=six.text_type(user),
                                   url=get_model_url(user),
                                   category=_("Contacts"),
                                   relevance=relevance)

    def get_help_blocks(self, request, kind):
        yield SimpleHelpBlock(
            text=_("Add some users to help manage your shop"),
            actions=[{
                "text": _("New user"),
                "url": self.get_model_url(get_user_model(), "new")
            }],
            priority=3,
            category=HelpBlockCategory.CONTACTS,
            icon_url="shuup_admin/img/users.png",
            done=get_user_model().objects.exists()
            if kind == "setup" else False)

    def get_required_permissions(self):
        return get_default_model_permissions(get_user_model())

    def get_model_url(self, object, kind):
        return derive_model_url(get_user_model(), "shuup_admin:user", object,
                                kind)
Ejemplo n.º 26
0
class OrderModule(CurrencyBound, AdminModule):
    name = _("Orders")
    breadcrumbs_menu_entry = MenuEntry(name, url="shuup_admin:order.list")

    def get_urls(self):
        return [
            admin_url(
                "^orders/(?P<pk>\d+)/create-shipment/$",
                "shuup.admin.modules.orders.views.OrderCreateShipmentView",
                name="order.create-shipment",
                permissions=["shuup.add_shipment"]),
            admin_url(
                "^orders/(?P<pk>\d+)/create-payment/$",
                "shuup.admin.modules.orders.views.OrderCreatePaymentView",
                name="order.create-payment",
                permissions=["shuup.add_payment"]),
            admin_url("^orders/(?P<pk>\d+)/set-status/$",
                      "shuup.admin.modules.orders.views.OrderSetStatusView",
                      name="order.set-status",
                      permissions=get_default_model_permissions(Order)),
            admin_url("^orders/(?P<pk>\d+)/new-log-entry/$",
                      "shuup.admin.modules.orders.views.NewLogEntryView",
                      name="order.new-log-entry",
                      permissions=get_default_model_permissions(Order)),
            admin_url("^orders/(?P<pk>\d+)/create-refund/$",
                      "shuup.admin.modules.orders.views.OrderCreateRefundView",
                      name="order.create-refund",
                      permissions=get_default_model_permissions(Order)),
            admin_url(
                "^orders/(?P<pk>\d+)/create-refund/full-refund$",
                "shuup.admin.modules.orders.views.OrderCreateFullRefundView",
                name="order.create-full-refund",
                permissions=get_default_model_permissions(Order)),
            admin_url("^orders/(?P<pk>\d+)/$",
                      "shuup.admin.modules.orders.views.OrderDetailView",
                      name="order.detail",
                      permissions=get_default_model_permissions(Order)),
            admin_url("^orders/new/$",
                      "shuup.admin.modules.orders.views.OrderEditView",
                      name="order.new",
                      permissions=["shuup.add_order"]),
            admin_url("^orders/(?P<pk>\d+)/edit/$",
                      "shuup.admin.modules.orders.views.OrderEditView",
                      name="order.edit",
                      permissions=["shuup.change_order"]),
            admin_url(
                "^orders/$",
                "shuup.admin.modules.orders.views.OrderListView",
                name="order.list",
                permissions=get_default_model_permissions(Order),
            ),
        ]

    def get_menu_category_icons(self):
        return {self.name: "fa fa-inbox"}

    def get_menu_entries(self, request):
        category = _("Orders")
        return [
            MenuEntry(text=_("Orders"),
                      icon="fa fa-inbox",
                      url="shuup_admin:order.list",
                      category=category,
                      aliases=[_("Show orders")]),
        ]

    def get_required_permissions(self):
        return (get_permissions_from_urls(self.get_urls())
                | get_default_model_permissions(Contact)
                | get_default_model_permissions(Order)
                | get_default_model_permissions(Product))

    def get_search_results(self, request, query):
        minimum_query_length = 3
        if len(query) >= minimum_query_length:
            orders = Order.objects.filter(
                Q(identifier__istartswith=query)
                | Q(reference_number__istartswith=query)
                | Q(email__icontains=query)
                | Q(phone__icontains=query)).order_by("-id")[:15]

            for i, order in enumerate(orders):
                relevance = 100 - i
                yield SearchResult(text=six.text_type(order),
                                   url=get_model_url(order),
                                   category=_("Orders"),
                                   relevance=relevance)

    def get_dashboard_blocks(self, request):
        import shuup.admin.modules.orders.dashboard as dashboard
        currency = self.currency
        if not currency:
            return
        yield dashboard.get_sales_of_the_day_block(request, currency)
        yield dashboard.get_lifetime_sales_block(request, currency)
        yield dashboard.get_avg_purchase_size_block(request, currency)
        yield dashboard.get_open_orders_block(request, currency)
        yield dashboard.get_order_value_chart_dashboard_block(
            request, currency)

    def get_notifications(self, request):
        old_open_orders = Order.objects.filter(
            status__role=OrderStatusRole.INITIAL,
            order_date__lt=now() - timedelta(days=4)).count()

        if old_open_orders:
            yield Notification(title=_("Outstanding Orders"),
                               text=_("%d outstanding orders") %
                               old_open_orders,
                               kind="danger")

    def get_model_url(self, object, kind):
        return derive_model_url(Order, "shuup_admin:order", object, kind)
Ejemplo n.º 27
0
class ContactModule(AdminModule):
    name = _("Contacts")
    breadcrumbs_menu_entry = MenuEntry(text=name, url="shuup_admin:contact.list", category=CONTACTS_MENU_CATEGORY)

    def get_urls(self):
        return [
            admin_url(
                r"^contacts/new/$",
                "shuup.admin.modules.contacts.views.ContactEditView",
                kwargs={"pk": None},
                name="contact.new",
            ),
            admin_url(
                r"^contacts/(?P<pk>\d+)/edit/$",
                "shuup.admin.modules.contacts.views.ContactEditView",
                name="contact.edit",
            ),
            admin_url(
                r"^contacts/(?P<pk>\d+)/$",
                "shuup.admin.modules.contacts.views.ContactDetailView",
                name="contact.detail",
            ),
            admin_url(
                r"^contacts/reset-password/(?P<pk>\d+)/$",
                "shuup.admin.modules.contacts.views.ContactResetPasswordView",
                name="contact.reset_password",
            ),
            admin_url(r"^contacts/$", "shuup.admin.modules.contacts.views.ContactListView", name="contact.list"),
            admin_url(
                r"^contacts/list-settings/",
                "shuup.admin.modules.settings.views.ListSettingsView",
                name="contact.list_settings",
            ),
            admin_url(
                r"^contacts/mass-edit/$",
                "shuup.admin.modules.contacts.views.ContactMassEditView",
                name="contact.mass_edit",
            ),
            admin_url(
                r"^contacts/mass-edit-group/$",
                "shuup.admin.modules.contacts.views.ContactGroupMassEditView",
                name="contact.mass_edit_group",
            ),
        ]

    def get_menu_entries(self, request):
        return [
            MenuEntry(
                text=_("Contacts"),
                icon="fa fa-users",
                url="shuup_admin:contact.list",
                category=CONTACTS_MENU_CATEGORY,
                ordering=1,
            )
        ]

    def get_search_results(self, request, query):
        minimum_query_length = 3
        if len(query) >= minimum_query_length:
            filters = Q(Q(name__icontains=query) | Q(email=query))

            # show only contacts which the shop has access
            if settings.SHUUP_ENABLE_MULTIPLE_SHOPS and settings.SHUUP_MANAGE_CONTACTS_PER_SHOP:
                filters &= Q(shops=request.shop)

            if not request.user.is_superuser:
                filters &= ~Q(PersonContact___user__is_superuser=True)

            contacts = Contact.objects.filter(filters)
            for i, contact in enumerate(contacts[:10]):
                relevance = 100 - i
                yield SearchResult(
                    text=six.text_type(contact), url=get_model_url(contact), category=_("Contacts"), relevance=relevance
                )

    def get_model_url(self, object, kind, shop=None):
        return derive_model_url(Contact, "shuup_admin:contact", object, kind)
Ejemplo n.º 28
0
class NotifyAdminModule(AdminModule):
    name = _(u"Notifications")
    breadcrumbs_menu_entry = MenuEntry(name, "shuup_admin:notify.script.list")

    def get_urls(self):
        permissions = get_default_model_permissions(NotificationModel)
        return [
            admin_url("notify/script-item-editor/",
                      "shuup.notify.admin_module.views.script_item_editor",
                      name="notify.script-item-editor",
                      permissions=permissions),
            admin_url("notify/script/content/(?P<pk>\d+)/",
                      "shuup.notify.admin_module.views.EditScriptContentView",
                      name="notify.script.edit-content",
                      permissions=permissions),
            admin_url("notify/mark-read/(?P<pk>\d+)/$",
                      self.mark_notification_read_view,
                      name="notify.mark-read",
                      permissions=permissions),
        ] + get_edit_and_list_urls(
            url_prefix="^notify/script",
            view_template="shuup.notify.admin_module.views.Script%sView",
            name_template="notify.script.%s",
            permissions=permissions)

    def get_menu_entries(self, request):
        return [
            MenuEntry(text=_("Notifications"),
                      icon="fa fa-code",
                      url="shuup_admin:notify.script.list",
                      category=SETTINGS_MENU_CATEGORY,
                      ordering=9,
                      aliases=[_("Show notification scripts")])
        ]

    def get_required_permissions(self):
        return get_default_model_permissions(NotificationModel)

    @csrf_exempt
    def mark_notification_read_view(self, request, pk):
        if request.method == "POST":
            try:
                notif = NotificationModel.objects.for_user(
                    request.user).get(pk=pk)
            except ObjectDoesNotExist:
                return JsonResponse({"error": "no such notification"})
            notif.mark_read(request.user)
            return JsonResponse({"ok": True})
        return JsonResponse({"error": "POST only"})

    def get_notifications(self, request):
        notif_qs = NotificationModel.objects.unread_for_user(
            request.user).order_by("-id")[:15]

        for notif in notif_qs:
            if notif.priority == Priority.HIGH:
                kind = "warning"
            elif notif.priority == Priority.CRITICAL:
                kind = "danger"
            else:
                kind = "info"

            yield Notification(text=notif.message,
                               url=notif.url,
                               kind=kind,
                               dismissal_url=reverse(
                                   "shuup_admin:notify.mark-read",
                                   kwargs={"pk": notif.pk}),
                               datetime=notif.created_on)

    def get_model_url(self, object, kind):
        return derive_model_url(Script, "shuup_admin:notify.script", object,
                                kind)
Ejemplo n.º 29
0
 def get_menu_entries(self, request):
     return [
         MenuEntry(
             text=_("Addons"), icon="fa fa-puzzle-piece", url="shuup_admin:addon.list", category=ADDONS_MENU_CATEGORY
         )
     ]