diff --git a/.bumpversion.cfg b/.bumpversion.cfg index e6efb02..6e173cf 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.1.0 +current_version = 1.0.0 files = setup.py oscar_support/__init__.py docs/source/conf.py commit = True tag = True diff --git a/.travis.yml b/.travis.yml index b9b0fdc..9a488fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,8 @@ python: - "2.6" - "2.7" env: - - DJANGO_VERSION=">=1.4,<1.5" OSCAR_VERSION=">=0.6,<0.7" - - DJANGO_VERSION=">=1.5,<1.6" OSCAR_VERSION=">=0.6,<0.7" + - DJANGO_VERSION=">=1.8,<2.0" OSCAR_VERSION=">=1.3,<1.6" + - DJANGO_VERSION=">=1.8,<2.0" OSCAR_VERSION=">=1.3,<1.6" install: - pip install Django$DJANGO_VERSION django-oscar$OSCAR_VERSION - pip install . diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e69de29..53e2972 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -0,0 +1,7 @@ +__CHANGELOG:__ + +__1.0.0__ + +- Support for insert files, orders, lines and products in `dashboard` and `admin`. +- Add ticket types, ticket statuses and priorities in `dashboard`. +- Create, Edit and Delete tickets. diff --git a/README.rst b/README.rst index 67f6956..15fafac 100644 --- a/README.rst +++ b/README.rst @@ -24,11 +24,11 @@ Currently it only allow very basic functionality such as: #. Reply to a customer with a message. #. Make a note on the ticket for internal use. #. Assign tickets to a staff user. +#. Relating a ticket to products, orders or order lines(User case: only staff can do it, staff take al information from attached files (invoices for example)) +#. Allow file attachments Features currently in the making: -#. Relating a ticket to products, orders or order lines -#. Allow file attachments #. Integrate with Oscar's alert system to notify the user of new replies. #. Add templating for messages in the dashboard for quicker replies. @@ -44,6 +44,11 @@ Longer-term direction: are then prioritized or re-assigned according to actions related to these SLAs. +For to do: + +* Test and coverage for all features. +* Improve styles: print only file name instead his path. +* Not all changes in the forms have to make a new messages. Screenshots ----------- diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 0585d28..b23c6c2 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -2,12 +2,6 @@ Getting Started =============== -.. warning:: *django-oscar-support* has been tested with Oscar 0.6 ``master`` - (due to it's pre-release state) and only works with commit `4aea545de3`_ - or later. Due to major changes in the stock record architecture and the - customer account templates earlier version will not work with the - instructions below. - .. _`4aea545de3`: https://github.com/tangentlabs/django-oscar/commit/4aea545de3d79fb20af49c24984541873c6be89c Installation @@ -24,7 +18,7 @@ Start off by installing the required package either from PyPI:: or install the latest version from github using:: - pip install git+https://github.com/tangentlabs/django-oscar-support.git + pip install git+https://github.com/mykljohn/django-oscar-support.git To make your Django project aware of the new package add it to your ``INSTALLED_APPS``:: @@ -57,14 +51,18 @@ a default UI for these two entry points but they need to be hooked into your Oscar project. Let's start by adding the URL patterns to your current project by adding the following line into your ``urls.py`` file:: - import oscar_support.urls - - urlpatterns = patterns('' + from oscar_support.app import application as support + from oscar_support.api.app import application as support_api + from oscar_support.dashboard.app import application as support_dashboard + + urlpatterns = [ ... + url(r'^dashboard/support/', include(support_dashboard.urls)), url(r'^', include(shop.urls)), # Oscar's URL patterns - url(r'^', include(oscar_support.urls)), + url(r'', include(support.urls)), + url(r'^api/', include(support_api.urls)), # You can use instead Oscar api urls ... - ) + ] This will provide all the URLs required to interact with the support system. The next step is to make the dashboard UI available in the navigation using @@ -75,7 +73,7 @@ Oscar's ``OSCAR_DASHBOARD_NAVIGATION`` settings:: .... - OSCAR_DASHBOARD_NAVIGATION = OSCAR_DASHBOARD_NAVIGATION + [ + OSCAR_DASHBOARD_NAVIGATION += [ { 'label': _("Support"), 'icon': 'icon-comments', @@ -83,10 +81,6 @@ Oscar's ``OSCAR_DASHBOARD_NAVIGATION`` settings:: } ] -.. note:: Make sure that you aren't using ``OSCAR_DASHBOARD_NAVIGATION +=`` - because this will cause duplicate entries due to a bug in Django that will - only be fixed in version 1.6+ - All that is left to do now is integrating the customer-facing part of the support system. The templates that come with *django-oscar-support* extend Oscar's customer account templates and should pick up the styles that are @@ -102,11 +96,10 @@ template directory and add the following content:: {% extends "oscar/customer/baseaccountpage.html" %} {% load i18n %} - {% load url from future %} {% block standard_tabs %} {{ block.super }} -
  • + {% trans "Support" %}
  • {% endblock %} diff --git a/oscar_support/__init__.py b/oscar_support/__init__.py index b794fd4..f6c9b7b 100644 --- a/oscar_support/__init__.py +++ b/oscar_support/__init__.py @@ -1 +1,2 @@ -__version__ = '0.1.0' +__version__ = '0.2.0' +default_app_config = 'oscar_support.config.OscarSupportConfig' diff --git a/oscar_support/abstract_models.py b/oscar_support/abstract_models.py index 2384eb9..c4db174 100644 --- a/oscar_support/abstract_models.py +++ b/oscar_support/abstract_models.py @@ -1,4 +1,6 @@ from django.db import models +from django.urls import reverse +from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import ugettext_lazy as _ from shortuuidfield import ShortUUIDField @@ -17,11 +19,12 @@ class Meta: abstract = True +@python_2_unicode_compatible class AbstractTicketType(BaseSupportModel): slug = AutoSlugField(_("Slug"), populate_from='name', unique=True) name = models.CharField(_("Name"), max_length=64) - def __unicode__(self): + def __str__(self): return self.name class Meta: @@ -30,11 +33,12 @@ class Meta: verbose_name_plural = _("Ticket types") +@python_2_unicode_compatible class AbstractTicketStatus(BaseSupportModel): slug = AutoSlugField(_("Slug"), populate_from='name', unique=True) name = models.CharField(_("Name"), max_length=64) - def __unicode__(self): + def __str__(self): return self.name class Meta: @@ -43,6 +47,7 @@ class Meta: verbose_name_plural = _("Ticket statuses") +@python_2_unicode_compatible class AbstractTicket(ModificationTrackingMixin, BaseSupportModel): number = models.CharField( _("Number"), @@ -93,7 +98,9 @@ class AbstractTicket(ModificationTrackingMixin, BaseSupportModel): # main content of the (initial) ticket subject = models.CharField(_("Subject"), max_length=255) - body = models.TextField(_("Body")) + body = models.TextField(_("Body"), blank=True) + # TODO: In CreateForm in dashboard JS give us: An invalid form control with name='body' is not focusable, + # for avoid it was needed make BODY unrequired, putting "black=true" property. It doesn't happen in customer view. priority = models.ForeignKey( 'Priority', @@ -145,8 +152,15 @@ def save(self, *args, **kwargs): self.subticket_id = ticket_numbers['subticket_id'] return super(AbstractTicket, self).save(*args, **kwargs) - def __unicode__(self): - return "Ticket #{0}".format(self.printable_number) + def __str__(self): + return _("Ticket #{0}").format(self.printable_number) + + def get_absolute_url(self): + """ + Return a product's absolute url + """ + return reverse('support:customer-ticket-update', + kwargs={'pk': self.uuid}) class Meta: abstract = True @@ -158,17 +172,22 @@ class Meta: unique_together = (('number', 'subticket_id'),) +@python_2_unicode_compatible class AbstractPriority(BaseSupportModel): name = models.CharField(_("Name"), max_length=255) slug = AutoSlugField(_("Slug"), populate_from='name') comment = models.TextField(_("Comment"), blank=True) + def __str__(self): + return self.name + class Meta: abstract = True verbose_name = _("Priority") verbose_name_plural = _("Priorities") +@python_2_unicode_compatible class AbstractMessage(ModificationTrackingMixin, BaseSupportModel): PUBLIC = u'public' INTERNAL = u'internal' @@ -198,8 +217,8 @@ class AbstractMessage(ModificationTrackingMixin, BaseSupportModel): def is_internal(self): return self.type == self.INTERNAL - def __unicode__(self): - return "{0} from {1} for ticket #{2}".format( + def __str__(self): + return _("{0} from {1} for {2}").format( self.type, self.user.email, self.ticket @@ -212,6 +231,7 @@ class Meta: verbose_name_plural = _("Messages") +@python_2_unicode_compatible class AbstractRelatedItem(ModificationTrackingMixin, BaseSupportModel): ticket = models.ForeignKey( 'Ticket', @@ -224,10 +244,14 @@ class AbstractRelatedItem(ModificationTrackingMixin, BaseSupportModel): related_name="%(class)ss", ) + def __str__(self): + return _("{0} related to {1}").format(self.ticket, self.user) + class Meta: abstract = True +@python_2_unicode_compatible class AbstractRelatedOrderLine(AbstractRelatedItem): line = models.ForeignKey( "order.Line", @@ -235,8 +259,8 @@ class AbstractRelatedOrderLine(AbstractRelatedItem): related_name="ticket_related_order_lines", ) - def __unicode__(self): - return "{0} related to {1}".format(self.line, self.ticket) + def __str__(self): + return _("{0} related to {1}").format(self.line, self.ticket) class Meta: abstract = True @@ -244,6 +268,7 @@ class Meta: verbose_name_plural = _("Related order lines") +@python_2_unicode_compatible class AbstractRelatedOrder(AbstractRelatedItem): order = models.ForeignKey( "order.Order", @@ -251,8 +276,8 @@ class AbstractRelatedOrder(AbstractRelatedItem): related_name="ticket_related_orders", ) - def __unicode__(self): - return "{0} related to {1}".format(self.order, self.ticket) + def __str__(self): + return _("{0} related to {1}").format(self.order, self.ticket) class Meta: abstract = True @@ -260,6 +285,7 @@ class Meta: verbose_name_plural = _("Related orders") +@python_2_unicode_compatible class AbstractRelatedProduct(AbstractRelatedItem): product = models.ForeignKey( "catalogue.Product", @@ -267,8 +293,8 @@ class AbstractRelatedProduct(AbstractRelatedItem): related_name="ticket_related_products", ) - def __unicode__(self): - return "{0} related to {1}".format(self.product, self.ticket) + def __str__(self): + return _("{0} related to {1}").format(self.product, self.ticket) class Meta: abstract = True @@ -276,6 +302,7 @@ class Meta: verbose_name_plural = _("Related products") +@python_2_unicode_compatible class AbstractAttachment(ModificationTrackingMixin, BaseSupportModel): ticket = models.ForeignKey( 'Ticket', @@ -289,11 +316,13 @@ class AbstractAttachment(ModificationTrackingMixin, BaseSupportModel): ) file = models.FileField( upload_to="oscar_support/%Y/%m", - verbose_name=_("File") + verbose_name=_("File"), + help_text=_("Add documents that present important information to understand the problem, " + "such as: invoices, catalogs, photos, orders, etc.") ) - def __unicode__(self): - return "{0} attached to {1}".format(self.file.url, self.ticket) + def __str__(self): + return _("{0} attached to {1}").format(self.file.url, self.ticket) class Meta: abstract = True diff --git a/oscar_support/admin.py b/oscar_support/admin.py index 56a27fa..ba53e5f 100644 --- a/oscar_support/admin.py +++ b/oscar_support/admin.py @@ -1,13 +1,131 @@ from django.contrib import admin -from django.db.models import get_model - - -admin.site.register(get_model('oscar_support', 'TicketType')) -admin.site.register(get_model('oscar_support', 'TicketStatus')) -admin.site.register(get_model('oscar_support', 'Ticket')) -admin.site.register(get_model('oscar_support', 'Priority')) -admin.site.register(get_model('oscar_support', 'Message')) -admin.site.register(get_model('oscar_support', 'RelatedOrder')) -admin.site.register(get_model('oscar_support', 'RelatedOrderLine')) -admin.site.register(get_model('oscar_support', 'RelatedProduct')) -admin.site.register(get_model('oscar_support', 'Attachment')) +from oscar.core.loading import get_model + +Attachment = get_model('oscar_support', 'Attachment') +Line = get_model('order', 'Line') +Message = get_model('oscar_support', 'Message') +Priority = get_model("oscar_support", "Priority") +Product = get_model('catalogue', 'Product') +RelatedOrder = get_model("oscar_support", "RelatedOrder") +RelatedOrderLine = get_model("oscar_support", "RelatedOrderLine") +RelatedProduct = get_model("oscar_support", "RelatedProduct") +Ticket = get_model('oscar_support', 'Ticket') +TicketStatus = get_model('oscar_support', 'TicketStatus') +TicketType = get_model('oscar_support', 'TicketType') + + +class AttacmentInlineAdmin(admin.TabularInline): + model = Attachment + fields = ['user', 'file'] + + +class LinesInlineAdmin(admin.TabularInline): + model = Ticket.related_lines.through + fields = ['line'] + + +class OrderInlineAdmin(admin.TabularInline): + model = Ticket.related_orders.through + fields = ['order'] + + +class ProductInlineAdmin(admin.TabularInline): + model = Ticket.related_products.through + fields = ['product'] + + +class MessageInlineAdmin(admin.TabularInline): + model = Message + fields = ['user', 'type', 'text'] + + +class TicketTypeAdmin(admin.ModelAdmin): + list_display = ['name', 'slug'] + fields = ['name', 'slug'] + readonly_fields = ['slug'] + + +class TicketStatusAdmin(admin.ModelAdmin): + list_display = ['name', 'slug'] + fields = ['name', 'slug'] + readonly_fields = ['slug'] + + +class PriorityAdmin(admin.ModelAdmin): + list_display = ['name', 'slug', 'comment'] + fields = ['name', 'slug', 'comment'] + readonly_fields = ['slug'] + + +class TicketAdmin(admin.ModelAdmin): + date_hierarchy = 'date_updated' + inlines = [ + AttacmentInlineAdmin, + LinesInlineAdmin, + OrderInlineAdmin, + ProductInlineAdmin, + MessageInlineAdmin + ] + list_display = ['number', 'is_internal', 'requester', 'type', 'assignee', 'priority', 'status'] + list_filter = ['is_internal', 'requester', 'type', 'assignee', 'priority', 'status'] + raw_id_fields = ['related_lines', 'related_orders', 'related_products'] + readonly_fields = ['date_created', 'date_updated'] + search_fields = [ + 'is_internal', + 'requester__username', + 'type__name', + 'assignee__username', + 'priority__name', + 'status__name' + ] + + +class MessageAdmin(admin.ModelAdmin): + date_hierarchy = 'date_updated' + list_display = ['user', 'type', 'ticket', 'text'] + list_filter = ['user', 'type', 'ticket'] + readonly_fields = ['date_created', 'date_updated'] + search_fields = ['user__username', 'type', 'ticket__number'] + + +class RelatedOrderAdmin(admin.ModelAdmin): + date_hierarchy = 'date_updated' + list_display = ['user', 'ticket', 'order'] + list_filter = ['user', 'ticket', ] + readonly_fields = ['date_created', 'date_updated'] + search_fields = ['user__username', 'ticket__number', ] + + +class RelatedOrderLineAdmin(admin.ModelAdmin): + date_hierarchy = 'date_updated' + list_display = ['user', 'ticket', 'line'] + list_filter = ['user', 'ticket', ] + readonly_fields = ['date_created', 'date_updated'] + search_fields = ['user__username', 'ticket__number', ] + + +class RelatedProductAdmin(admin.ModelAdmin): + date_hierarchy = 'date_updated' + list_display = ['user', 'ticket', 'product'] + list_filter = ['user', 'ticket', ] + readonly_fields = ['date_created', 'date_updated'] + search_fields = ['user__username', 'ticket__number', ] + + +class AttachmentAdmin(admin.ModelAdmin): + date_hierarchy = 'date_updated' + list_display = ['user', 'ticket', 'file'] + list_filter = ['user', 'ticket', ] + readonly_fields = ['date_created', 'date_updated'] + search_fields = ['user__username', 'ticket__number', ] + + +admin.site.register(TicketType, TicketTypeAdmin) +admin.site.register(TicketStatus, TicketStatusAdmin) +admin.site.register(Priority, PriorityAdmin) +admin.site.register(Ticket, TicketAdmin) +admin.site.register(Message, MessageAdmin) +admin.site.register(RelatedOrder, RelatedOrderAdmin) +admin.site.register(RelatedOrderLine, RelatedOrderLineAdmin) +admin.site.register(RelatedProduct, RelatedProductAdmin) +admin.site.register(Attachment, AttachmentAdmin) diff --git a/oscar_support/api/app.py b/oscar_support/api/app.py new file mode 100644 index 0000000..b259875 --- /dev/null +++ b/oscar_support/api/app.py @@ -0,0 +1,20 @@ +from oscar.core.application import Application +from oscar.views.decorators import permissions_required + +from .urls import urlpatterns + + +class RESTApiApplication(Application): + def get_url_decorator(self, pattern): + "Fixes bug in Application.get_url_decorator which would decorate None values." + permissions = self.get_permissions(pattern.name) + if permissions is not None: + return permissions_required(permissions) + + return None + + def get_urls(self): + return self.post_process_urls(urlpatterns) + + +application = RESTApiApplication() diff --git a/oscar_support/api/serializers.py b/oscar_support/api/serializers.py deleted file mode 100644 index 160d28c..0000000 --- a/oscar_support/api/serializers.py +++ /dev/null @@ -1,19 +0,0 @@ -from rest_framework import serializers - -from oscar.core.compat import get_user_model - - -class UserSerializer(serializers.ModelSerializer): - display_text = serializers.SerializerMethodField('get_display_text') - - class Meta: - model = get_user_model() - fields = ('id', 'email', 'first_name', 'last_name', 'display_text') - - def get_display_text(self, obj): - if not obj: - return '' - full_name = obj.get_full_name() - if full_name: - return "{0} <{1}>".format(full_name, obj.email) - return obj.email diff --git a/oscar_support/api/serializers/__init__.py b/oscar_support/api/serializers/__init__.py new file mode 100644 index 0000000..4a3a5e8 --- /dev/null +++ b/oscar_support/api/serializers/__init__.py @@ -0,0 +1 @@ +from .ticket import * diff --git a/oscar_support/api/serializers/ticket.py b/oscar_support/api/serializers/ticket.py new file mode 100644 index 0000000..5121608 --- /dev/null +++ b/oscar_support/api/serializers/ticket.py @@ -0,0 +1,230 @@ +from rest_framework import serializers + +from oscar.core.compat import get_user_model +from oscar.core.loading import get_model + +from oscarapi.utils import ( + OscarModelSerializer, + overridable, + OscarHyperlinkedModelSerializer +) + +Attachment = get_model('oscar_support', 'Attachment') +Basket = get_model('basket', 'Basket') +Line = get_model('order', 'Line') +Message = get_model('oscar_support', 'Message') +Order = get_model('order', 'Order') +Product = get_model('catalogue', 'Product') +Ticket = get_model('oscar_support', 'Ticket') +TicketStatus = get_model('oscar_support', 'TicketStatus') +TicketType = get_model('oscar_support', 'TicketType') + + +class UserSerializer(serializers.ModelSerializer): + display_text = serializers.SerializerMethodField('get_display_text') + + class Meta: + model = get_user_model() + fields = ('id', 'email', 'first_name', 'last_name', 'display_text') + + def get_display_text(self, obj): + if not obj: + return '' + full_name = obj.get_full_name() + if full_name: + return "{0} <{1}>".format(full_name, obj.email) + return obj.email + + +""" +class PartnerSerializer(OscarModelSerializer): + class Meta: + model = Partner + fields = '__all__' + + +class OptionSerializer(OscarHyperlinkedModelSerializer): + class Meta: + model = Option + fields = overridable('OSCARAPI_OPTION_FIELDS', default=( + 'url', 'id', 'name', 'code', 'type' + )) +""" + + +class TicketLinkSerializer(OscarHyperlinkedModelSerializer): + priority = serializers.StringRelatedField(required=False) + + class Meta: + model = Ticket + fields = ['url', 'number', 'subject', 'priority'] + # overridable('OSCARAPI_TICKET_FIELDS', default=()) + + +""" +class ProductAttributeValueSerializer(OscarModelSerializer): + name = serializers.StringRelatedField(source="attribute") + value = serializers.StringRelatedField() + + class Meta: + model = ProductAttributeValue + fields = overridable('OSCARAPI_PRODUCT_ATTRIBUTE_VALUE_FIELDS', default=('name', 'value',)) + + +class ProductAttributeSerializer(OscarModelSerializer): + productattributevalue_set = ProductAttributeValueSerializer(many=True) + + class Meta: + model = ProductAttribute + fields = overridable('OSCARAPI_PRODUCT_ATTRIBUTE_FIELDS', default=('name', 'productattributevalue_set')) + + +class ProductImageSerializer(OscarModelSerializer): + class Meta: + model = ProductImage + fields = '__all__' + + +class AvailabilitySerializer(serializers.Serializer): + is_available_to_buy = serializers.BooleanField() + num_available = serializers.IntegerField(required=False) + message = serializers.CharField() + + +class RecommmendedProductSerializer(OscarModelSerializer): + url = serializers.HyperlinkedIdentityField(view_name='product-detail') + + class Meta: + model = Product + fields = overridable( + 'OSCARAPI_RECOMMENDED_PRODUCT_FIELDS', default=('url',)) +""" + + +class TicketRelatedLineSerializer(OscarModelSerializer): + order = serializers.StringRelatedField() + partner = serializers.StringRelatedField() + product = serializers.HyperlinkedRelatedField( + view_name='product-detail', read_only=True) + + # status = models.CharField() + + class Meta: + model = Line + fields = ['url', 'order', 'partner', 'product', 'status', ] + + +class TicketRelatedOrderSerializer(OscarModelSerializer): + basket = serializers.HyperlinkedRelatedField( + view_name='basket-detail', queryset=Basket.objects) + owner = serializers.HyperlinkedRelatedField( + view_name='user-detail', read_only=True, source='user') + + # TODO: Status doesn't show anything + # status = models.CharField() + + class Meta: + model = Order + fields = ['url', 'number', 'basket', 'owner', 'status', ] + + +class TicketRelatedProductSerializer(OscarModelSerializer): + class Meta: + model = Product + fields = ['url', 'upc', 'title', 'rating'] + + +class TicketAttachmentSerializer(OscarModelSerializer): + user = serializers.HyperlinkedRelatedField( + view_name='user-detail', read_only=True, ) + + class Meta: + model = Attachment + fields = '__all__' + + +class TicketMessageSerializer(OscarModelSerializer): + user = serializers.HyperlinkedRelatedField( + view_name='user-detail', read_only=True, ) + + class Meta: + model = Message + fields = '__all__' + + +class TicketSerializer(OscarModelSerializer): + url = serializers.HyperlinkedIdentityField(view_name='ticket-detail') + requester = serializers.StringRelatedField() # TODO: It need be hyperlinked + status = serializers.StringRelatedField() + type = serializers.StringRelatedField() + assigned_group = serializers.StringRelatedField() + assignee = serializers.StringRelatedField() + priority = serializers.StringRelatedField(required=False) + # parent = serializers.StringRelatedField() + attachments = TicketAttachmentSerializer(many=True, required=False, ) + related_lines = TicketRelatedLineSerializer(many=True, required=False, ) # TODO: Review it + related_orders = TicketRelatedOrderSerializer(many=True, required=False, ) + related_products = TicketRelatedProductSerializer(many=True, required=False, ) + messages = TicketMessageSerializer(many=True, required=False, ) + + class Meta: + model = Ticket + fields = [ + 'url', + 'is_internal', + 'type', + 'number', + 'subject', + 'requester', + 'status', + 'body', + 'subticket_id', + # 'parent', + 'assigned_group', + 'assignee', + 'priority', + 'attachments', + 'related_lines', + 'related_orders', + 'related_products', + 'messages' + ] + # overridable('OSCARAPI_PRODUCTDETAIL_FIELDS', default=()) + + +""" +class OptionValueSerializer(serializers.Serializer): + option = serializers.HyperlinkedRelatedField( + view_name='option-detail', queryset=Option.objects) + value = serializers.CharField() + + +class AddProductSerializer(serializers.Serializer): + # Serializes and validates an add to basket request. + quantity = serializers.IntegerField(required=True) + url = serializers.HyperlinkedRelatedField( + view_name='product-detail', queryset=Product.objects, required=True) + options = OptionValueSerializer(many=True, required=False) + + class Meta: + model = Product +""" + + +class AddTicketSerializer(serializers.HyperlinkedModelSerializer): + requester = serializers.StringRelatedField() # TODO: It need be hyperlinked + type = serializers.StringRelatedField() + attachments = TicketAttachmentSerializer(many=True, required=False, ) + + class Meta: + model = Ticket + fields = [ + 'type', + 'subject', + 'requester', + 'body', + 'attachments', + ] + + def create(self, validated_data): + return Ticket.objects.create(**validated_data) diff --git a/oscar_support/api/urls.py b/oscar_support/api/urls.py index 19a4975..21955d1 100644 --- a/oscar_support/api/urls.py +++ b/oscar_support/api/urls.py @@ -1,28 +1,21 @@ -from django.conf import settings -from django.conf.urls import url, patterns, include - -from rest_framework import routers +import django +from django.conf.urls import url +from rest_framework.urlpatterns import format_suffix_patterns from . import views +urlpatterns = [ + # url(r'^', include(router.urls, namespace='support-api')), + url(r'^$', views.api_root, name='support-api'), + url(r'^tickets/$', views.TicketList.as_view(), name='ticket-list'), + url(r'^tickets/(?P[a-zA-Z0-9]+)/$', views.TicketDetail.as_view(), name='ticket-detail'), + url(r'^ticket/add-ticket/$', views.AddTicketView.as_view(), name='ticket-add-ticket'), + # url(r'^ticket/update-ticket/$', views.UpdateTicketView.as_view(), name='ticket-update-ticket'), +] -router = routers.DefaultRouter() -router.register(r'customers', views.CustomerViewSet, base_name="customer") -router.register(r'agents', views.AgentViewSet, base_name="agent") -router.register(r'groups', views.GroupViewSet) - - -urlpatterns = patterns( - '', - url(r'^', include(router.urls, namespace='support-api')), -) +urlpatterns = format_suffix_patterns(urlpatterns) +if django.VERSION[:2] < (1, 8): + from django.conf.urls import patterns -if settings.DEBUG: - urlpatterns = urlpatterns + patterns( - '', - url( - r'^api-auth/', - include('rest_framework.urls', namespace='rest_framework') - ), - ) + urlpatterns = patterns('', *urlpatterns) diff --git a/oscar_support/api/views.py b/oscar_support/api/views.py deleted file mode 100644 index 2d19b87..0000000 --- a/oscar_support/api/views.py +++ /dev/null @@ -1,31 +0,0 @@ -from django.db.models import get_model - -from rest_framework import viewsets - -from oscar.core.compat import get_user_model - -from . import serializers -from .mixins import UserFilterMixin - -User = get_user_model() -Group = get_model('auth', 'Group') - - -class CustomerViewSet(UserFilterMixin, viewsets.ModelViewSet): - model = User - serializer_class = serializers.UserSerializer - - def get_queryset(self): - return self.filter_queryset(self.model.objects.all()) - - -class AgentViewSet(UserFilterMixin, viewsets.ModelViewSet): - model = User - serializer_class = serializers.UserSerializer - - def get_queryset(self): - return self.filter_queryset(self.model.objects.filter(is_staff=True)) - - -class GroupViewSet(viewsets.ModelViewSet): - model = Group diff --git a/oscar_support/api/views/__init__.py b/oscar_support/api/views/__init__.py new file mode 100644 index 0000000..c873610 --- /dev/null +++ b/oscar_support/api/views/__init__.py @@ -0,0 +1,2 @@ +from .root import * +from .ticket import * diff --git a/oscar_support/api/views/root.py b/oscar_support/api/views/root.py new file mode 100644 index 0000000..2ef7f63 --- /dev/null +++ b/oscar_support/api/views/root.py @@ -0,0 +1,38 @@ +import collections + +from oscarapi.views.root import PUBLIC_APIS +from oscarapi.views.root import PROTECTED_APIS +from rest_framework.decorators import api_view +from rest_framework.response import Response +from rest_framework.reverse import reverse + +__all__ = ('api_root',) + + +def PUBLIC_SUPPORT_APIS(r, f): + return [ + ('tickets', reverse('ticket-list', request=r, format=f)), + ('add-ticket', reverse('ticket-add-ticket', request=r, format=f)), + # ('update-ticket', reverse('ticket-update-ticket', request=r, format=f)), + ] + + +def PROTECTED_SUPPORT_APIS(r, f): + return [] + + +@api_view(('GET',)) +def api_root(request, format=None): + """ + GET: + Display all available urls. + Since some urls have specific permissions, you might not be able to access + them all. + """ + apis = PUBLIC_APIS(request, format) + apis += PUBLIC_SUPPORT_APIS(request, format) + if request.user.is_staff: + apis += PROTECTED_APIS(request, format) + apis += PROTECTED_SUPPORT_APIS(request, format) + + return Response(collections.OrderedDict(apis)) diff --git a/oscar_support/api/views/ticket.py b/oscar_support/api/views/ticket.py new file mode 100644 index 0000000..54ac2a6 --- /dev/null +++ b/oscar_support/api/views/ticket.py @@ -0,0 +1,59 @@ +from rest_framework import generics + +from oscar.core.loading import get_model +from oscar_support.api import serializers # permissions + +__all__ = ( + 'TicketList', + 'TicketDetail', + 'AddTicketView', +) + +Ticket = get_model('oscar_support', 'Ticket') + + +class TicketList(generics.ListAPIView): + queryset = Ticket.objects.all() + serializer_class = serializers.TicketLinkSerializer + + +class TicketDetail(generics.RetrieveAPIView): + queryset = Ticket.objects.all() + serializer_class = serializers.TicketSerializer + + +class AddTicketView(generics.ListCreateAPIView): + """ + Create a new ticket. + POST(ticket, attachment, + [total, shipping_method_code, shipping_charge, billing_address]): + { + "type": "Products", + "subject": "Title for ticket", + "requester": "@username", + "body": "Text for ticket", + "attachments": [ + { + "uuid": "znup8iQM2rWmg7r8RiNCGd", + "user": "http://localhost:8000/api/users/#/", + "date_created": "2017-10-05T21:44:59.361697Z", + "date_updated": "2017-10-05T21:44:59.383862Z", + "file": "http://localhost:8000/media/oscar_support/2017/10/PSI_Docker_Certification_Exam_lX6nNfE.pdf", + "ticket": "rVszTeuXWcZ9fspMkYh7wd" + }, + { + "uuid": "Q8DNTzTXqtMXEDyfyeZFuY", + "user": "http://localhost:8000/api/users/#/", + "date_created": "2017-10-05T20:21:08.748900Z", + "date_updated": "2017-10-05T21:44:59.339411Z", + "file": "http://localhost:8000/media/oscar_support/2017/10/Invoice_Docker_Certification_lvnH4mk.pdf", + "ticket": "rVszTeuXWcZ9fspMkYh7wd" + } + ] + } + returns the order object. + """ + queryset = Ticket.objects.all() + serializer_class = serializers.AddTicketSerializer + +# class UpdateTicketView(APIView): diff --git a/oscar_support/app.py b/oscar_support/app.py index cc14d43..d0bb2f9 100644 --- a/oscar_support/app.py +++ b/oscar_support/app.py @@ -1,4 +1,4 @@ -from django.conf.urls import patterns, url +from django.conf.urls import url from django.contrib.auth.decorators import login_required from shortuuid import get_alphabet @@ -16,32 +16,26 @@ class SupportApplication(Application): ticket_update_view = views.TicketUpdateView def get_urls(self): - urlpatterns = super(SupportApplication, self).get_urls() - - urlpatterns += patterns( - '', + urls = [ url( r'accounts/support/$', - self.ticket_list_view.as_view(), + login_required(self.ticket_list_view.as_view()), name='customer-ticket-list' ), url( r'accounts/support/ticket/create/$', - self.ticket_create_view.as_view(), + login_required(self.ticket_create_view.as_view()), name='customer-ticket-create' ), url( r'accounts/support/ticket/(?P[{0}]+)/update/$'.format( get_alphabet() ), - self.ticket_update_view.as_view(), + login_required(self.ticket_update_view.as_view()), name='customer-ticket-update' ), - ) - return self.post_process_urls(urlpatterns) - - def get_url_decorator(self, url_name): - return login_required + ] + return self.post_process_urls(urls) application = SupportApplication() diff --git a/oscar_support/config.py b/oscar_support/config.py new file mode 100644 index 0000000..2041268 --- /dev/null +++ b/oscar_support/config.py @@ -0,0 +1,8 @@ +from django.apps import AppConfig +from django.utils.translation import ugettext_lazy as _ + + +class OscarSupportConfig(AppConfig): + # label = 'support' + name = 'oscar_support' + verbose_name = _('Support') diff --git a/oscar_support/dashboard/app.py b/oscar_support/dashboard/app.py index 5c72e8d..7c2dee2 100644 --- a/oscar_support/dashboard/app.py +++ b/oscar_support/dashboard/app.py @@ -1,24 +1,27 @@ -from django.conf.urls import patterns, url +from django.conf.urls import url +from django.contrib.admin.views.decorators import staff_member_required from shortuuid import get_alphabet -from oscar.core.application import Application -from oscar.views.decorators import staff_member_required +from oscar.core.application import DashboardApplication from . import views -class SupportDashboardApplication(Application): +class SupportDashboardApplication(DashboardApplication): name = 'support-dashboard' + default_permissions = ['is_staff', ] ticket_list_view = views.TicketListView ticket_create_view = views.TicketCreateView ticket_update_view = views.TicketUpdateView + types_edit_view = views.TypesEditView + statuses_edit_view = views.StatusesEditView + priorities_edit_view = views.PrioritiesEditView def get_urls(self): - urlpatterns = patterns( - '', - url(r'^$', self.ticket_list_view.as_view(), name='ticket-list'), + urls = [ + url(r'^ticket/$', self.ticket_list_view.as_view(), name='ticket-list'), url(r'^ticket/create/$', self.ticket_create_view.as_view(), name='ticket-create'), url( @@ -26,11 +29,20 @@ def get_urls(self): self.ticket_update_view.as_view(), name='ticket-update' ), - ) - return self.post_process_urls(urlpatterns) - - def get_url_decorator(self, url_name): - return staff_member_required + url( + r'tags/types/$', self.types_edit_view.as_view(), + name='tag-type-list' + ), + url( + r'tags/statuses/$', self.statuses_edit_view.as_view(), + name='tag-status-list' + ), + url( + r'tags/priorities/$', self.priorities_edit_view.as_view(), + name='tag-priority-list' + ), + ] + return self.post_process_urls(urls) application = SupportDashboardApplication() diff --git a/oscar_support/dashboard/config.py b/oscar_support/dashboard/config.py new file mode 100644 index 0000000..981e162 --- /dev/null +++ b/oscar_support/dashboard/config.py @@ -0,0 +1,8 @@ +from django.apps import AppConfig +from django.utils.translation import ugettext_lazy as _ + + +class OscarSupportDashboardConfig(AppConfig): + # label = 'support_dashboard' + name = 'oscar_support.dashboard' + verbose_name = _('Support dashboard') diff --git a/oscar_support/dashboard/forms.py b/oscar_support/dashboard/forms.py index c4c9275..74bb7b4 100644 --- a/oscar_support/dashboard/forms.py +++ b/oscar_support/dashboard/forms.py @@ -1,35 +1,26 @@ from django import forms -from django.db.models import get_model from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ from oscar.core.compat import get_user_model +from oscar.core.loading import get_model -from ..forms.widgets import AutoCompleteWidget, CustomRadioFieldRenderer +from ..forms.widgets import AutoCompleteWidget +from ..forms.widgets import CustomRadioInput User = get_user_model() -Ticket = get_model('oscar_support', 'Ticket') -Message = get_model('oscar_support', 'Message') CommunicationEventType = get_model('customer', 'CommunicationEventType') - +Message = get_model('oscar_support', 'Message') +Priority = get_model("oscar_support", "Priority") +Ticket = get_model('oscar_support', 'Ticket') +TicketStatus = get_model("oscar_support", "TicketStatus") +TicketType = get_model("oscar_support", "TicketType") REQUESTER_FIELDS = ['requester', 'is_internal'] MESSAGE_FIELDS = ['subject', 'body'] class TicketCreateForm(forms.ModelForm): - requester = forms.IntegerField( - widget=AutoCompleteWidget( - url=reverse_lazy('support-api:customer-list') - ) - ) - assignee = forms.IntegerField( - widget=AutoCompleteWidget( - url=reverse_lazy('support-api:agent-list'), - ), - required=False, - ) - def get_message_fields(self): for field in self: if field.name in MESSAGE_FIELDS: @@ -41,25 +32,6 @@ def get_property_fields(self): if field.name not in ignore_fields: yield field - def clean_requester(self): - requester_id = self.cleaned_data.get('requester') - try: - requester = User.objects.get(id=requester_id) - except User.DoesNotExist: - raise forms.ValidationError("Invalid user specified") - return requester - - def clean_assignee(self): - assignee_id = self.cleaned_data.get('assignee') - # The assignee is not mandatory so if it is empty, we just ignore it - if not assignee_id: - return assignee_id - try: - assignee = User.objects.get(id=assignee_id, is_staff=True) - except User.DoesNotExist: - raise forms.ValidationError("Invalid user specified") - return assignee - class Meta: model = Ticket fields = REQUESTER_FIELDS + [ @@ -77,7 +49,7 @@ class Meta: class TicketUpdateForm(forms.ModelForm): message_type = forms.ChoiceField( - widget=forms.RadioSelect(renderer=CustomRadioFieldRenderer), + widget=CustomRadioInput(attrs={'class': 'radio-inline'}), choices=Message.MESSAGE_TYPES, label=_("Message type"), initial=Message.PUBLIC, @@ -100,7 +72,14 @@ def get_message_fields(self): class Meta: model = Ticket - fields = ['status', 'message_type', 'message_text'] + fields = [ + 'status', + 'priority', + 'assignee', + 'assigned_group', + 'message_type', + 'message_text' + ] widgets = { 'status': forms.HiddenInput(), } @@ -114,3 +93,21 @@ class RequesterCreateForm(forms.ModelForm): class Meta: model = User fields = ['first_name', 'last_name', 'email'] + + +class PriorityForm(forms.ModelForm): + class Meta: + model = Priority + fields = ['name', 'comment', ] + + +class TicketStatusForm(forms.ModelForm): + class Meta: + model = TicketStatus + fields = ['name', ] + + +class TicketTypeForm(forms.ModelForm): + class Meta: + model = TicketType + fields = ['name', ] diff --git a/oscar_support/dashboard/views.py b/oscar_support/dashboard/views.py index a46a60c..ee35b6d 100644 --- a/oscar_support/dashboard/views.py +++ b/oscar_support/dashboard/views.py @@ -1,15 +1,33 @@ -from django.views import generic -from django.db.models import get_model, Q -from django.http import HttpResponseRedirect +from django.contrib import messages from django.core.urlresolvers import reverse +from django.db.models import Q +from django.http import HttpResponseRedirect +from django.utils.translation import ugettext_lazy as _ +from django.views import generic + +from extra_views import ModelFormSetView + +from oscar.core.loading import get_model +from oscar_support.dashboard.forms import ( + PriorityForm, + TicketStatusForm, + TicketTypeForm +) +from oscar_support.forms.formsets import ( + AttachmentFormSet, + RelatedOrderFormSet, + RelatedOrderLineFormSet, + RelatedProductFormSet, +) from . import forms from .. import utils -Note = get_model('oscar_support', 'Note') -Ticket = get_model('oscar_support', 'Ticket') Message = get_model('oscar_support', 'Message') +Priority = get_model("oscar_support", "Priority") +Ticket = get_model('oscar_support', 'Ticket') TicketStatus = get_model('oscar_support', 'TicketStatus') +TicketType = get_model("oscar_support", "TicketType") class TicketListMixin(object): @@ -44,7 +62,6 @@ def get_queryset(self, queryset=None): class UserFormInlineMixin(object): - def get_extra_form_kwargs(self): kwargs = super(UserFormInlineMixin, self).get_extra_form_kwargs() kwargs['user'] = self.request.user @@ -73,6 +90,7 @@ def get_context_data(self, **kwargs): ctx['default_status'] = status ctx['status_list'] = TicketStatus.objects.exclude(name=status.name) ctx['requester_create_form'] = forms.RequesterCreateForm() + ctx['title'] = _('New ticket') return ctx def get_success_url(self, **kwargs): @@ -84,14 +102,65 @@ class TicketUpdateView(TicketListMixin, generic.UpdateView): default_message_model = Message context_object_name = 'selected_ticket' form_class = forms.TicketUpdateForm + attachment_formset = AttachmentFormSet + related_order_formset = RelatedOrderFormSet + related_line_formset = RelatedOrderLineFormSet + related_product_formset = RelatedProductFormSet template_name = 'oscar_support/dashboard/ticket_detail.html' + def __init__(self, *args, **kwargs): + super(TicketUpdateView, self).__init__(*args, **kwargs) + self.formsets = { + 'attachment_formset': self.attachment_formset, + 'related_order_formset': self.related_order_formset, + 'related_line_formset': self.related_line_formset, + 'related_product_formset': self.related_product_formset, + } + def get_context_data(self, **kwargs): ctx = super(TicketUpdateView, self).get_context_data(**kwargs) + ticket_name = self.object ctx['ticket_list'] = self.get_ticket_list() + ctx['title'] = _('Update {name}').format(name=ticket_name) + for ctx_name, formset_class in self.formsets.items(): + if ctx_name not in ctx: + ctx[ctx_name] = formset_class( + self.object.requester, + instance=self.object + ) return ctx - def form_valid(self, form): + def process_all_forms(self, form): + + if form.is_valid(): + self.object = form.save() + + formsets = {} + for ctx_name, formset_class in self.formsets.items(): + formsets[ctx_name] = formset_class( + self.object.requester, + self.request.POST, + self.request.FILES, + instance=self.object + ) + + is_valid = form.is_valid() and all( + [formset.is_valid() for formset in formsets.values()] + ) + + cross_form_validation_result = self.clean(form, formsets) + if is_valid and cross_form_validation_result: + return self.forms_valid(form, formsets) + else: + return self.forms_invalid(form, formsets) + + form_valid = form_invalid = process_all_forms + + def clean(self, form, formsets): + + return True + + def forms_valid(self, form, formsets): ticket = form.save() message_type = form.cleaned_data.get('message_type', Message.PUBLIC) message_text = form.cleaned_data.get('message_text') @@ -101,7 +170,111 @@ def form_valid(self, form): text=message_text, ticket=ticket ) + + # Save formsets + for formset in formsets.values(): + formset.save() + return HttpResponseRedirect(self.get_success_url()) + def forms_invalid(self, form, formsets): + + messages.error( + self.request, + _("Your submitted data was not valid - please " + "correct the errors below") + ) + ctx = self.get_context_data(form=form, **formsets) + return self.render_to_response(ctx) + def get_success_url(self): + + messages.success( + self.request, + _("Successfully updated {0}.").format(self.object), extra_tags="safe noicon" + ) return reverse("support-dashboard:ticket-list") + + +class TypesEditView(TicketListMixin, ModelFormSetView): + template_name = 'oscar_support/dashboard/tags/types.html' + page_title = _('Types') + active_tab = 'types' + model = TicketType + form_class = TicketTypeForm + extra = 5 + max_num = None + can_delete = True + + def get_context_data(self, **kwargs): + ctx = super(TypesEditView, self).get_context_data(**kwargs) + ctx.setdefault('page_title', self.page_title) + ctx.setdefault('active_tab', self.active_tab) + ctx.setdefault('url', reverse("support-dashboard:tag-type-list")) + ctx['type_count'] = self.model.objects.all().count() + return ctx + + def get_success_url(self): + messages.success( + self.request, + # TODO: Render the model updated value + # _("Successfully updated type {0}!.").format(self.get_formset), extra_tags="safe noicon" + _("Successfully updated type!."), extra_tags="safe noicon" + ) + return reverse("support-dashboard:tag-type-list") + + +class StatusesEditView(TicketListMixin, ModelFormSetView): + template_name = 'oscar_support/dashboard/tags/statuses.html' + page_title = _('Statuses') + active_tab = 'statuses' + model = TicketStatus + form_class = TicketStatusForm + extra = 5 + max_num = None + can_delete = True + + def get_context_data(self, **kwargs): + ctx = super(StatusesEditView, self).get_context_data(**kwargs) + ctx.setdefault('page_title', self.page_title) + ctx.setdefault('active_tab', self.active_tab) + ctx.setdefault('url', reverse("support-dashboard:tag-status-list")) + ctx['status_count'] = self.model.objects.all().count() + return ctx + + def get_success_url(self): + messages.success( + self.request, + # TODO: Render the model updated value + # _("Successfully updated status {0}!.").format(self.get_formset), extra_tags="safe noicon" + _("Successfully updated status!."), extra_tags="safe noicon" + ) + return reverse("support-dashboard:tag-status-list") + + +class PrioritiesEditView(TicketListMixin, ModelFormSetView): + template_name = 'oscar_support/dashboard/tags/priorities.html' + page_title = _('Priorities') + active_tab = 'priorities' + model = Priority + form_class = PriorityForm + extra = 5 + max_num = None + can_delete = True + + def get_context_data(self, **kwargs): + ctx = super(PrioritiesEditView, self).get_context_data(**kwargs) + ctx.setdefault('page_title', self.page_title) + ctx.setdefault('active_tab', self.active_tab) + ctx.setdefault('url', reverse("support-dashboard:tag-priority-list")) + ctx['priority_count'] = self.model.objects.all().count() + return ctx + + def get_success_url(self): + messages.success( + self.request, + # TODO: Render the model updated value + # _("Successfully updated priority {0}!.").format(self.get_formset), extra_tags="safe noicon" + _("Successfully updated priority!."), extra_tags="safe noicon" + ) + return reverse("support-dashboard:tag-priority-list") diff --git a/oscar_support/defaults.py b/oscar_support/defaults.py index 6f47bda..af9e4e3 100644 --- a/oscar_support/defaults.py +++ b/oscar_support/defaults.py @@ -5,19 +5,3 @@ SUPPORT_RESOLVED_STATUS = _("Resolved") SUPPORT_RESOLVED_STATUS_SLUG = "resolved" - -# Setting defaults for the REST API provided by django-rest-framework -# for security reasons we only enable session-based authentication and -# JSON formatting. This can be overwritten in you own settings file. For more -# details on the DRF settings checkout http://django-rest-framework.org -REST_FRAMEWORK = { - 'DEFAULT_PERMISSION_CLASSES': ( - 'rest_framework.permissions.IsAuthenticated', - ), - 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'rest_framework.authentication.SessionAuthentication', - ), - 'DEFAULT_RENDERER_CLASSES': ( - 'rest_framework.renderers.JSONRenderer', - ) -} diff --git a/oscar_support/fixtures/ticket_statuses.json b/oscar_support/fixtures/ticket_statuses.json deleted file mode 100644 index c1f4838..0000000 --- a/oscar_support/fixtures/ticket_statuses.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "pk": 1, - "model": "oscar_support.ticketstatus", - "fields": { - "name": "New" - } - }, - { - "pk": 3, - "model": "oscar_support.ticketstatus", - "fields": { - "name": "Open" - } - }, - { - "pk": 4, - "model": "oscar_support.ticketstatus", - "fields": { - "name": "Solved" - } - }, - { - "pk": 5, - "model": "oscar_support.ticketstatus", - "fields": { - "name": "Pending" - } - }, - { - "pk": 6, - "model": "oscar_support.ticketstatus", - "fields": { - "name": "Resolved" - } - } -] diff --git a/oscar_support/fixtures/ticket_types.json b/oscar_support/fixtures/ticket_types.json deleted file mode 100644 index 615fe12..0000000 --- a/oscar_support/fixtures/ticket_types.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "pk": 1, - "model": "oscar_support.tickettype", - "fields": { - "name": "Question about a product" - } - }, - { - "pk": 2, - "model": "oscar_support.tickettype", - "fields": { - "name": "Where is my order?" - } - } -] diff --git a/oscar_support/forms/__init__.py b/oscar_support/forms/__init__.py index 36c7acd..25e9d5f 100644 --- a/oscar_support/forms/__init__.py +++ b/oscar_support/forms/__init__.py @@ -1,37 +1,109 @@ from django import forms -from django.db.models import get_model from django.utils.translation import ugettext_lazy as _ +from oscar.core.loading import get_model + from .. import utils +Attachment = get_model('oscar_support', 'Attachment') Order = get_model('order', 'Order') RelatedOrder = get_model("oscar_support", "RelatedOrder") -TicketStatus = get_model("oscar_support", "TicketStatus") +RelatedOrderLine = get_model("oscar_support", "RelatedOrderLine") +RelatedProduct = get_model("oscar_support", "RelatedProduct") + + +class AttachmentForm(forms.ModelForm): + def __init__(self, user, *args, **kwargs): + self.user = user + super(AttachmentForm, self).__init__(*args, **kwargs) + + class Meta: + model = Attachment + fields = ['ticket', 'file', ] + + def save(self, *args, **kwargs): + kwargs['commit'] = False + obj = super(AttachmentForm, self).save(*args, **kwargs) + obj.user = self.user + obj.save() + return obj + + +class RelatedOrderForm(forms.ModelForm): + def __init__(self, user, *args, **kwargs): + self.user = user + super(RelatedOrderForm, self).__init__(*args, **kwargs) + + class Meta: + model = RelatedOrder + fields = ['order'] + + def save(self, *args, **kwargs): + kwargs['commit'] = False + obj = super(RelatedOrderForm, self).save(*args, **kwargs) + obj.user = self.user + obj.save() + return obj + + +class RelatedOrderLineForm(forms.ModelForm): + def __init__(self, user, *args, **kwargs): + self.user = user + super(RelatedOrderLineForm, self).__init__(*args, **kwargs) + + class Meta: + model = RelatedOrderLine + fields = ['line'] + + def save(self, *args, **kwargs): + kwargs['commit'] = False + obj = super(RelatedOrderLineForm, self).save(*args, **kwargs) + obj.user = self.user + obj.save() + return obj + + +class RelatedProductForm(forms.ModelForm): + def __init__(self, user, *args, **kwargs): + self.user = user + super(RelatedProductForm, self).__init__(*args, **kwargs) + + class Meta: + model = RelatedProduct + fields = ['product'] + + def save(self, *args, **kwargs): + kwargs['commit'] = False + obj = super(RelatedProductForm, self).save(*args, **kwargs) + obj.user = self.user + obj.save() + return obj class TicketUpdateForm(forms.ModelForm): message_text = forms.CharField(label=_("Message"), widget=forms.Textarea()) + def __init__(self, user, *args, **kwargs): + self.user = user + super(TicketUpdateForm, self).__init__(*args, **kwargs) + class Meta: model = get_model("oscar_support", "Ticket") fields = ['message_text'] class TicketCreateForm(forms.ModelForm): - def __init__(self, user, *args, **kwargs): self.user = user super(TicketCreateForm, self).__init__(*args, **kwargs) - def save(self, commit=True): - instance = super(TicketCreateForm, self).save(commit=False) - - instance.status = utils.TicketStatusGenerator.get_initial_status() - instance.requester = self.user - - if commit: - instance.save() - return instance + def save(self, *args, **kwargs): + kwargs['commit'] = False + obj = super(TicketCreateForm, self).save(*args, **kwargs) + obj.status = utils.TicketStatusGenerator.get_initial_status() + obj.requester = self.user + obj.save() + return obj class Meta: model = get_model("oscar_support", "Ticket") diff --git a/oscar_support/forms/formsets.py b/oscar_support/forms/formsets.py new file mode 100644 index 0000000..902fa68 --- /dev/null +++ b/oscar_support/forms/formsets.py @@ -0,0 +1,98 @@ +from django.forms import formset_factory, modelformset_factory +from django.forms import inlineformset_factory +from oscar.core.loading import get_model +from oscar_support.dashboard.forms import ( + PriorityForm, + TicketStatusForm, + TicketTypeForm +) + +from oscar_support.forms import ( + AttachmentForm, + RelatedOrderForm, + RelatedOrderLineForm, + RelatedProductForm, +) + +Attachment = get_model('oscar_support', 'Attachment') +Order = get_model('order', 'Order') +RelatedOrder = get_model("oscar_support", "RelatedOrder") +Priority = get_model("oscar_support", "Priority") +RelatedOrderLine = get_model("oscar_support", "RelatedOrderLine") +RelatedProduct = get_model("oscar_support", "RelatedProduct") +Ticket = get_model("oscar_support", "Ticket") +TicketStatus = get_model("oscar_support", "TicketStatus") +TicketType = get_model("oscar_support", "TicketType") + +BaseAttachmentFormSet = inlineformset_factory( + Ticket, Attachment, form=AttachmentForm, extra=2, + can_delete=True) + + +class AttachmentFormSet(BaseAttachmentFormSet): + def __init__(self, user, *args, **kwargs): + self.user = user + super(AttachmentFormSet, self).__init__(*args, **kwargs) + + def _construct_form(self, i, **kwargs): + kwargs['user'] = self.user + return super(AttachmentFormSet, self)._construct_form( + i, **kwargs) + + +BaseRelatedOrderFormSet = inlineformset_factory( + Ticket, RelatedOrder, form=RelatedOrderForm, extra=1, + can_delete=True) + + +class RelatedOrderFormSet(BaseRelatedOrderFormSet): + def __init__(self, user, *args, **kwargs): + self.user = user + super(RelatedOrderFormSet, self).__init__(*args, **kwargs) + + def _construct_form(self, i, **kwargs): + kwargs['user'] = self.user + return super(RelatedOrderFormSet, self)._construct_form( + i, **kwargs) + + def get_num_orders(self): + num_orders = 0 + for i in range(0, self.total_form_count()): + form = self.forms[i] + if (hasattr(form, 'cleaned_data') + and form.cleaned_data.get('order', None) + and not form.cleaned_data.get('DELETE', False)): + num_orders += 1 + return num_orders + + +BaseRelatedOrderLineFormSet = inlineformset_factory( + Ticket, RelatedOrderLine, form=RelatedOrderLineForm, extra=1, + can_delete=True) + + +class RelatedOrderLineFormSet(BaseRelatedOrderLineFormSet): + def __init__(self, user, *args, **kwargs): + self.user = user + super(RelatedOrderLineFormSet, self).__init__(*args, **kwargs) + + def _construct_form(self, i, **kwargs): + kwargs['user'] = self.user + return super(RelatedOrderLineFormSet, self)._construct_form( + i, **kwargs) + + +BaseRelatedProductFormSet = inlineformset_factory( + Ticket, RelatedProduct, form=RelatedProductForm, extra=5, + can_delete=True) + + +class RelatedProductFormSet(BaseRelatedProductFormSet): + def __init__(self, user, *args, **kwargs): + self.user = user + super(RelatedProductFormSet, self).__init__(*args, **kwargs) + + def _construct_form(self, i, **kwargs): + kwargs['user'] = self.user + return super(RelatedProductFormSet, self)._construct_form( + i, **kwargs) diff --git a/oscar_support/forms/widgets.py b/oscar_support/forms/widgets.py index 7e43701..52df383 100644 --- a/oscar_support/forms/widgets.py +++ b/oscar_support/forms/widgets.py @@ -1,9 +1,11 @@ -from django.forms.util import flatatt -from django.template import loader, Context -from django.utils.encoding import force_unicode -from django.utils.html import conditional_escape +from django.forms.widgets import Widget +from django.forms.widgets import RadioSelect from django.template.loader import render_to_string -from django.forms.widgets import Widget, RadioInput, RadioFieldRenderer + +try: + from django.utils.encoding import force_unicode as force_text +except ImportError: + from django.utils.encoding import force_text class AutoCompleteWiget(Widget): @@ -16,54 +18,17 @@ def __init__(self, url, user_field=None, *args, **kwargs): def render(self, name, value, attrs=None): if value is None: value = u'' - tmpl = loader.get_template( - 'oscar_support/widgets/autocomplete_widget.html' - ) - return tmpl.render(Context({ + ctx = { 'name': name, 'url': self.url, 'user_field': self.user_field, 'value': value, - })) + } + return render_to_string('oscar_support/widgets/autocomplete_widget.html', context=ctx) AutoCompleteWidget = AutoCompleteWiget -class CustomRadioInput(RadioInput): +class CustomRadioInput(RadioSelect): template_name = 'oscar_support/partials/custom_radio_select.html' - - def render(self, name=None, value=None, attrs=None, choices=()): - name = name or self.name - value = value or self.value - attrs = attrs or self.attrs - - if 'id' in self.attrs: - self.attrs['id'] = '%s_%s' % (self.attrs['id'], self.index) - - if 'id' in self.attrs: - label_for = ' for="%s"' % self.attrs['id'] - else: - label_for = '' - - choice_label = conditional_escape(force_unicode(self.choice_label)) - return render_to_string(self.template_name, Context({ - 'attrs': flatatt(self.attrs), - 'checked': self.is_checked(), - 'name': self.name, - 'value': self.choice_value, - 'label_for': label_for, - 'choice_label': choice_label, - })) - - -class CustomRadioFieldRenderer(RadioFieldRenderer): - - def __iter__(self): - for i, choice in enumerate(self.choices): - yield CustomRadioInput(self.name, self.value, self.attrs.copy(), - choice, i) - - def __getitem__(self, idx): - choice = self.choices[idx] # Let the IndexError propogate - return CustomRadioInput(self.name, self.value, self.attrs.copy(), - choice, idx) + option_template_name = 'oscar_support/partials/custom_radio_option.html' diff --git a/oscar_support/migrations/0001_initial.py b/oscar_support/migrations/0001_initial.py index 546a12c..8515805 100644 --- a/oscar_support/migrations/0001_initial.py +++ b/oscar_support/migrations/0001_initial.py @@ -1,499 +1,288 @@ # -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models +# Generated by Django 1.11.4 on 2017-09-02 23:12 +from __future__ import unicode_literals -from oscar.core.compat import AUTH_USER_MODEL, AUTH_USER_MODEL_NAME +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django_extensions.db.fields +import shortuuidfield.fields -class Migration(SchemaMigration): +def create_default_ticket_status(apps, schema_editor): + statuses = [ + 'Closed' + 'In progress', + 'In review', + 'New', + 'Open', + 'Pending', + 'Solved', + ] - def forwards(self, orm): - # Adding model 'TicketType' - db.create_table(u'oscar_support_tickettype', ( - ('uuid', self.gf('shortuuidfield.fields.ShortUUIDField')(max_length=22, primary_key=True)), - ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=64)), - )) - db.send_create_signal(u'oscar_support', ['TicketType']) + Status = apps.get_model('oscar_support.ticketstatus') - # Adding model 'TicketStatus' - db.create_table(u'oscar_support_ticketstatus', ( - ('uuid', self.gf('shortuuidfield.fields.ShortUUIDField')(max_length=22, primary_key=True)), - ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=64)), - )) - db.send_create_signal(u'oscar_support', ['TicketStatus']) + for status in statuses: + Status.objects.create(name=status) - # Adding model 'Ticket' - db.create_table(u'oscar_support_ticket', ( - ('date_created', self.gf('django.db.models.fields.DateTimeField')()), - ('date_updated', self.gf('django.db.models.fields.DateTimeField')()), - ('uuid', self.gf('shortuuidfield.fields.ShortUUIDField')(max_length=22, primary_key=True)), - ('number', self.gf('django.db.models.fields.CharField')(max_length=64, db_index=True)), - ('subticket_id', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), - ('parent', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='subtickets', null=True, to=orm['oscar_support.Ticket'])), - ('requester', self.gf('django.db.models.fields.related.ForeignKey')(related_name='submitted_tickets', to=orm[AUTH_USER_MODEL])), - ('status', self.gf('django.db.models.fields.related.ForeignKey')(related_name='tickets', to=orm['oscar_support.TicketStatus'])), - ('type', self.gf('django.db.models.fields.related.ForeignKey')(related_name='tickets', to=orm['oscar_support.TicketType'])), - ('assigned_group', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='tickets', null=True, to=orm['auth.Group'])), - ('assignee', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='assigned_tickets', null=True, to=orm[AUTH_USER_MODEL])), - ('subject', self.gf('django.db.models.fields.CharField')(max_length=255)), - ('body', self.gf('django.db.models.fields.TextField')()), - ('priority', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='tickets', null=True, to=orm['oscar_support.Priority'])), - ('is_internal', self.gf('django.db.models.fields.BooleanField')(default=False)), - )) - db.send_create_signal(u'oscar_support', ['Ticket']) - # Adding unique constraint on 'Ticket', fields ['number', 'subticket_id'] - db.create_unique(u'oscar_support_ticket', ['number', 'subticket_id']) +def create_default_ticket_type(apps, schema_editor): + types = [ + 'Customer', + 'Error', + 'Initiative', + 'Order', + 'Product', + 'Work' + ] - # Adding model 'Priority' - db.create_table(u'oscar_support_priority', ( - ('uuid', self.gf('shortuuidfield.fields.ShortUUIDField')(max_length=22, primary_key=True)), - ('name', self.gf('django.db.models.fields.CharField')(max_length=255)), - ('slug', self.gf('django_extensions.db.fields.AutoSlugField')(allow_duplicates=False, max_length=50, separator=u'-', blank=True, populate_from='name', overwrite=False)), - ('comment', self.gf('django.db.models.fields.TextField')(blank=True)), - )) - db.send_create_signal(u'oscar_support', ['Priority']) + Type = apps.get_model('oscar_support.tickettype') - # Adding model 'Message' - db.create_table(u'oscar_support_message', ( - ('date_created', self.gf('django.db.models.fields.DateTimeField')()), - ('date_updated', self.gf('django.db.models.fields.DateTimeField')()), - ('uuid', self.gf('shortuuidfield.fields.ShortUUIDField')(max_length=22, primary_key=True)), - ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='messages', to=orm[AUTH_USER_MODEL])), - ('type', self.gf('django.db.models.fields.CharField')(default=u'public', max_length=3)), - ('ticket', self.gf('django.db.models.fields.related.ForeignKey')(related_name='messages', to=orm['oscar_support.Ticket'])), - ('text', self.gf('django.db.models.fields.TextField')()), - )) - db.send_create_signal(u'oscar_support', ['Message']) + for type in types: + Type.objects.create(name=type) - # Adding model 'RelatedOrderLine' - db.create_table(u'oscar_support_relatedorderline', ( - ('date_created', self.gf('django.db.models.fields.DateTimeField')()), - ('date_updated', self.gf('django.db.models.fields.DateTimeField')()), - ('uuid', self.gf('shortuuidfield.fields.ShortUUIDField')(max_length=22, primary_key=True)), - ('ticket', self.gf('django.db.models.fields.related.ForeignKey')(related_name='relatedorderlines', to=orm['oscar_support.Ticket'])), - ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='relatedorderlines', to=orm[AUTH_USER_MODEL])), - ('line', self.gf('django.db.models.fields.related.ForeignKey')(related_name='ticket_related_order_lines', to=orm['order.Line'])), - )) - db.send_create_signal(u'oscar_support', ['RelatedOrderLine']) - # Adding model 'RelatedOrder' - db.create_table(u'oscar_support_relatedorder', ( - ('date_created', self.gf('django.db.models.fields.DateTimeField')()), - ('date_updated', self.gf('django.db.models.fields.DateTimeField')()), - ('uuid', self.gf('shortuuidfield.fields.ShortUUIDField')(max_length=22, primary_key=True)), - ('ticket', self.gf('django.db.models.fields.related.ForeignKey')(related_name='relatedorders', to=orm['oscar_support.Ticket'])), - ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='relatedorders', to=orm[AUTH_USER_MODEL])), - ('order', self.gf('django.db.models.fields.related.ForeignKey')(related_name='ticket_related_orders', to=orm['order.Order'])), - )) - db.send_create_signal(u'oscar_support', ['RelatedOrder']) +def create_default_priority(apps, schema_editor): + priorities = [ + 'Extremely', + 'High', + 'Infrequent', + 'Low', + 'N/A', + 'Normal', + 'Unsure', + ] + comments = [ + "Extremely disruptive, can't be working until resolved.", + 'Very high priority. Needs to be resolved in short time range.', + 'Infrequent, serious problems. Should fix in near term.', + 'A low impact, low urgency issue.', + 'This issue did not require any action, so this field does not apply.', + 'Normal, common problem.', + "Unsure when we're going to fix this.", + ] - # Adding model 'RelatedProduct' - db.create_table(u'oscar_support_relatedproduct', ( - ('date_created', self.gf('django.db.models.fields.DateTimeField')()), - ('date_updated', self.gf('django.db.models.fields.DateTimeField')()), - ('uuid', self.gf('shortuuidfield.fields.ShortUUIDField')(max_length=22, primary_key=True)), - ('ticket', self.gf('django.db.models.fields.related.ForeignKey')(related_name='relatedproducts', to=orm['oscar_support.Ticket'])), - ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='relatedproducts', to=orm[AUTH_USER_MODEL])), - ('product', self.gf('django.db.models.fields.related.ForeignKey')(related_name='ticket_related_products', to=orm['catalogue.Product'])), - )) - db.send_create_signal(u'oscar_support', ['RelatedProduct']) + Priority = apps.get_model('oscar_support.priority') - # Adding model 'Attachment' - db.create_table(u'oscar_support_attachment', ( - ('date_created', self.gf('django.db.models.fields.DateTimeField')()), - ('date_updated', self.gf('django.db.models.fields.DateTimeField')()), - ('uuid', self.gf('shortuuidfield.fields.ShortUUIDField')(max_length=22, primary_key=True)), - ('ticket', self.gf('django.db.models.fields.related.ForeignKey')(related_name='attachments', to=orm['oscar_support.Ticket'])), - ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='attachments', to=orm[AUTH_USER_MODEL])), - ('file', self.gf('django.db.models.fields.files.FileField')(max_length=100)), - )) - db.send_create_signal(u'oscar_support', ['Attachment']) + for priority, comment in zip(priorities, comments): + Priority.objects.create(name=priority, comment=comment) - def backwards(self, orm): - # Removing unique constraint on 'Ticket', fields ['number', 'subticket_id'] - db.delete_unique(u'oscar_support_ticket', ['number', 'subticket_id']) +class Migration(migrations.Migration): - # Deleting model 'TicketType' - db.delete_table(u'oscar_support_tickettype') + initial = True - # Deleting model 'TicketStatus' - db.delete_table(u'oscar_support_ticketstatus') + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('catalogue', '0012_auto_20170609_1902'), + ('order', '0005_update_email_length'), + ('auth', '0008_alter_user_username_max_length'), + ] - # Deleting model 'Ticket' - db.delete_table(u'oscar_support_ticket') - - # Deleting model 'Priority' - db.delete_table(u'oscar_support_priority') - - # Deleting model 'Message' - db.delete_table(u'oscar_support_message') - - # Deleting model 'RelatedOrderLine' - db.delete_table(u'oscar_support_relatedorderline') - - # Deleting model 'RelatedOrder' - db.delete_table(u'oscar_support_relatedorder') - - # Deleting model 'RelatedProduct' - db.delete_table(u'oscar_support_relatedproduct') - - # Deleting model 'Attachment' - db.delete_table(u'oscar_support_attachment') - - - models = { - u'address.country': { - 'Meta': {'ordering': "('-display_order', 'name')", 'object_name': 'Country'}, - 'display_order': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0', 'db_index': 'True'}), - 'is_shipping_country': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'iso_3166_1_a2': ('django.db.models.fields.CharField', [], {'max_length': '2', 'primary_key': 'True'}), - 'iso_3166_1_a3': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True', 'db_index': 'True'}), - 'iso_3166_1_numeric': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True', 'db_index': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'printable_name': ('django.db.models.fields.CharField', [], {'max_length': '128'}) - }, - u'auth.group': { - 'Meta': {'object_name': 'Group'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - u'auth.permission': { - 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - AUTH_USER_MODEL: { - 'Meta': {'object_name': AUTH_USER_MODEL_NAME}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - u'catalogue.attributeentity': { - 'Meta': {'object_name': 'AttributeEntity'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'blank': 'True'}), - 'type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'entities'", 'to': u"orm['catalogue.AttributeEntityType']"}) - }, - u'catalogue.attributeentitytype': { - 'Meta': {'object_name': 'AttributeEntityType'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'blank': 'True'}) - }, - u'catalogue.attributeoption': { - 'Meta': {'object_name': 'AttributeOption'}, - 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'options'", 'to': u"orm['catalogue.AttributeOptionGroup']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'option': ('django.db.models.fields.CharField', [], {'max_length': '255'}) - }, - u'catalogue.attributeoptiongroup': { - 'Meta': {'object_name': 'AttributeOptionGroup'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}) - }, - u'catalogue.category': { - 'Meta': {'ordering': "['full_name']", 'object_name': 'Category'}, - 'depth': ('django.db.models.fields.PositiveIntegerField', [], {}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'full_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - 'numchild': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}) - }, - u'catalogue.option': { - 'Meta': {'object_name': 'Option'}, - 'code': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'type': ('django.db.models.fields.CharField', [], {'default': "'Required'", 'max_length': '128'}) - }, - u'catalogue.product': { - 'Meta': {'ordering': "['-date_created']", 'object_name': 'Product'}, - 'attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.ProductAttribute']", 'through': u"orm['catalogue.ProductAttributeValue']", 'symmetrical': 'False'}), - 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Category']", 'through': u"orm['catalogue.ProductCategory']", 'symmetrical': 'False'}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_discountable': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'variants'", 'null': 'True', 'to': u"orm['catalogue.Product']"}), - 'product_class': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'products'", 'null': 'True', 'to': u"orm['catalogue.ProductClass']"}), - 'product_options': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Option']", 'symmetrical': 'False', 'blank': 'True'}), - 'rating': ('django.db.models.fields.FloatField', [], {'null': 'True'}), - 'recommended_products': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Product']", 'symmetrical': 'False', 'through': u"orm['catalogue.ProductRecommendation']", 'blank': 'True'}), - 'related_products': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'relations'", 'blank': 'True', 'to': u"orm['catalogue.Product']"}), - 'score': ('django.db.models.fields.FloatField', [], {'default': '0.0', 'db_index': 'True'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}), - 'status': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'upc': ('django.db.models.fields.CharField', [], {'max_length': '64', 'unique': 'True', 'null': 'True', 'blank': 'True'}) - }, - u'catalogue.productattribute': { - 'Meta': {'ordering': "['code']", 'object_name': 'ProductAttribute'}, - 'code': ('django.db.models.fields.SlugField', [], {'max_length': '128'}), - 'entity_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeEntityType']", 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'option_group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeOptionGroup']", 'null': 'True', 'blank': 'True'}), - 'product_class': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attributes'", 'null': 'True', 'to': u"orm['catalogue.ProductClass']"}), - 'required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'type': ('django.db.models.fields.CharField', [], {'default': "'text'", 'max_length': '20'}) - }, - u'catalogue.productattributevalue': { - 'Meta': {'object_name': 'ProductAttributeValue'}, - 'attribute': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.ProductAttribute']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attribute_values'", 'to': u"orm['catalogue.Product']"}), - 'value_boolean': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'value_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), - 'value_entity': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeEntity']", 'null': 'True', 'blank': 'True'}), - 'value_float': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), - 'value_integer': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'value_option': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeOption']", 'null': 'True', 'blank': 'True'}), - 'value_richtext': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'value_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}) - }, - u'catalogue.productcategory': { - 'Meta': {'ordering': "['-is_canonical']", 'object_name': 'ProductCategory'}, - 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Category']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_canonical': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']"}) - }, - u'catalogue.productclass': { - 'Meta': {'ordering': "['name']", 'object_name': 'ProductClass'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'options': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Option']", 'symmetrical': 'False', 'blank': 'True'}), - 'requires_shipping': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - 'track_stock': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) - }, - u'catalogue.productrecommendation': { - 'Meta': {'object_name': 'ProductRecommendation'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'primary': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'primary_recommendations'", 'to': u"orm['catalogue.Product']"}), - 'ranking': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}), - 'recommendation': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']"}) - }, - u'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - u'order.billingaddress': { - 'Meta': {'object_name': 'BillingAddress'}, - 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['address.Country']"}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'line1': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'line2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line3': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line4': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'postcode': ('oscar.models.fields.UppercaseCharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), - 'search_text': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), - 'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}) - }, - u'order.line': { - 'Meta': {'object_name': 'Line'}, - 'est_dispatch_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'line_price_before_discounts_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_before_discounts_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'order': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'lines'", 'to': u"orm['order.Order']"}), - 'partner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'order_lines'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['partner.Partner']"}), - 'partner_line_notes': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'partner_line_reference': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'partner_name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'partner_sku': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), - 'quantity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), - 'status': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'stockrecord': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['partner.StockRecord']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'unit_cost_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_price_excl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_price_incl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_retail_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'upc': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}) - }, - u'order.order': { - 'Meta': {'ordering': "['-date_placed']", 'object_name': 'Order'}, - 'basket_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'billing_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['order.BillingAddress']", 'null': 'True', 'blank': 'True'}), - 'currency': ('django.db.models.fields.CharField', [], {'default': "'GBP'", 'max_length': '12'}), - 'date_placed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}), - 'guest_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'number': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}), - 'shipping_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['order.ShippingAddress']", 'null': 'True', 'blank': 'True'}), - 'shipping_code': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}), - 'shipping_excl_tax': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}), - 'shipping_incl_tax': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}), - 'shipping_method': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['sites.Site']"}), - 'status': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), - 'total_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'total_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'orders'", 'null': 'True', 'to': u"orm['{}']".format(AUTH_USER_MODEL)}) - }, - u'order.shippingaddress': { - 'Meta': {'object_name': 'ShippingAddress'}, - 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['address.Country']"}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'line1': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'line2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line3': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line4': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'notes': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'phone_number': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), - 'postcode': ('oscar.models.fields.UppercaseCharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), - 'search_text': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), - 'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}) - }, - u'oscar_support.attachment': { - 'Meta': {'object_name': 'Attachment'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attachments'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attachments'", 'to': u"orm['{}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.message': { - 'Meta': {'ordering': "['-date_created']", 'object_name': 'Message'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'text': ('django.db.models.fields.TextField', [], {}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['oscar_support.Ticket']"}), - 'type': ('django.db.models.fields.CharField', [], {'default': "u'public'", 'max_length': '3'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['{}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.priority': { - 'Meta': {'object_name': 'Priority'}, - 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django_extensions.db.fields.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '50', 'separator': "u'-'", 'blank': 'True', 'populate_from': "'name'", 'overwrite': 'False'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedorder': { - 'Meta': {'object_name': 'RelatedOrder'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'order': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_orders'", 'to': u"orm['order.Order']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorders'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorders'", 'to': u"orm['{}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedorderline': { - 'Meta': {'object_name': 'RelatedOrderLine'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'line': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_order_lines'", 'to': u"orm['order.Line']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorderlines'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorderlines'", 'to': u"orm['{}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedproduct': { - 'Meta': {'object_name': 'RelatedProduct'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_products'", 'to': u"orm['catalogue.Product']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedproducts'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedproducts'", 'to': u"orm['{}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.ticket': { - 'Meta': {'ordering': "['-date_updated']", 'unique_together': "(('number', 'subticket_id'),)", 'object_name': 'Ticket'}, - 'assigned_group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tickets'", 'null': 'True', 'to': u"orm['auth.Group']"}), - 'assignee': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'assigned_tickets'", 'null': 'True', 'to': u"orm['{}']".format(AUTH_USER_MODEL)}), - 'body': ('django.db.models.fields.TextField', [], {}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'is_internal': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'number': ('django.db.models.fields.CharField', [], {'max_length': '64', 'db_index': 'True'}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'subtickets'", 'null': 'True', 'to': u"orm['oscar_support.Ticket']"}), - 'priority': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tickets'", 'null': 'True', 'to': u"orm['oscar_support.Priority']"}), - 'related_lines': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedOrderLine']", 'to': u"orm['order.Line']"}), - 'related_orders': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedOrder']", 'to': u"orm['order.Order']"}), - 'related_products': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedProduct']", 'to': u"orm['catalogue.Product']"}), - 'requester': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'submitted_tickets'", 'to': u"orm['{}']".format(AUTH_USER_MODEL)}), - 'status': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tickets'", 'to': u"orm['oscar_support.TicketStatus']"}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'subticket_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tickets'", 'to': u"orm['oscar_support.TicketType']"}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.ticketstatus': { - 'Meta': {'object_name': 'TicketStatus'}, - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.tickettype': { - 'Meta': {'object_name': 'TicketType'}, - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'partner.partner': { - 'Meta': {'object_name': 'Partner'}, - 'code': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'users': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'partners'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['{}']".format(AUTH_USER_MODEL)}) - }, - u'partner.stockrecord': { - 'Meta': {'unique_together': "(('partner', 'partner_sku'),)", 'object_name': 'StockRecord'}, - 'cost_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'low_stock_threshold': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'num_allocated': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'num_in_stock': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'partner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'stockrecords'", 'to': u"orm['partner.Partner']"}), - 'partner_sku': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'price_currency': ('django.db.models.fields.CharField', [], {'default': "'GBP'", 'max_length': '12'}), - 'price_excl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'price_retail': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'stockrecords'", 'to': u"orm['catalogue.Product']"}) - }, - u'sites.site': { - 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"}, - 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - } - } - - complete_apps = ['oscar_support'] + operations = [ + migrations.CreateModel( + name='Attachment', + fields=[ + ('date_created', models.DateTimeField(verbose_name='Created')), + ('date_updated', models.DateTimeField(verbose_name='Last modified')), + ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22, primary_key=True, serialize=False)), + ('file', models.FileField(upload_to='oscar_support/%Y/%m', verbose_name='File')), + ], + options={ + 'verbose_name': 'Attachment', + 'verbose_name_plural': 'Attachments', + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Message', + fields=[ + ('date_created', models.DateTimeField(verbose_name='Created')), + ('date_updated', models.DateTimeField(verbose_name='Last modified')), + ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22, primary_key=True, serialize=False)), + ('type', models.CharField(choices=[('public', 'Public message'), ('internal', 'Internal note')], default='public', max_length=30, verbose_name='Message type')), + ('text', models.TextField(verbose_name='Text')), + ], + options={ + 'verbose_name': 'Message', + 'verbose_name_plural': 'Messages', + 'ordering': ['-date_created'], + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Priority', + fields=[ + ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=255, verbose_name='Name')), + ('slug', django_extensions.db.fields.AutoSlugField(blank=True, editable=False, populate_from='name', verbose_name='Slug')), + ('comment', models.TextField(blank=True, verbose_name='Comment')), + ], + options={ + 'verbose_name': 'Priority', + 'verbose_name_plural': 'Priorities', + 'abstract': False, + }, + ), + migrations.CreateModel( + name='RelatedOrder', + fields=[ + ('date_created', models.DateTimeField(verbose_name='Created')), + ('date_updated', models.DateTimeField(verbose_name='Last modified')), + ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22, primary_key=True, serialize=False)), + ('order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_related_orders', to='order.Order', verbose_name='Order')), + ], + options={ + 'verbose_name': 'Related order', + 'verbose_name_plural': 'Related orders', + 'abstract': False, + }, + ), + migrations.CreateModel( + name='RelatedOrderLine', + fields=[ + ('date_created', models.DateTimeField(verbose_name='Created')), + ('date_updated', models.DateTimeField(verbose_name='Last modified')), + ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22, primary_key=True, serialize=False)), + ('line', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_related_order_lines', to='order.Line', verbose_name='Order line')), + ], + options={ + 'verbose_name': 'Related order line', + 'verbose_name_plural': 'Related order lines', + 'abstract': False, + }, + ), + migrations.CreateModel( + name='RelatedProduct', + fields=[ + ('date_created', models.DateTimeField(verbose_name='Created')), + ('date_updated', models.DateTimeField(verbose_name='Last modified')), + ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22, primary_key=True, serialize=False)), + ('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_related_products', to='catalogue.Product', verbose_name='Product')), + ], + options={ + 'verbose_name': 'Related product', + 'verbose_name_plural': 'Related products', + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Ticket', + fields=[ + ('date_created', models.DateTimeField(verbose_name='Created')), + ('date_updated', models.DateTimeField(verbose_name='Last modified')), + ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22, primary_key=True, serialize=False)), + ('number', models.CharField(db_index=True, max_length=64, verbose_name='Number')), + ('subticket_id', models.PositiveIntegerField(default=0, verbose_name='Subticket number')), + ('subject', models.CharField(max_length=255, verbose_name='Subject')), + ('body', models.TextField(verbose_name='Body')), + ('is_internal', models.BooleanField(default=False, help_text="use this ticket only internally and don't display to the customer", verbose_name='Internal ticket')), + ('assigned_group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tickets', to='auth.Group', verbose_name='Assigned group')), + ('assignee', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='assigned_tickets', to=settings.AUTH_USER_MODEL, verbose_name='Assignee')), + ('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subtickets', to='oscar_support.Ticket', verbose_name='Parent ticket')), + ('priority', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tickets', to='oscar_support.Priority', verbose_name='Priority')), + ('related_lines', models.ManyToManyField(blank=True, related_name='tickets', through='oscar_support.RelatedOrderLine', to='order.Line', verbose_name='Related order lines')), + ('related_orders', models.ManyToManyField(blank=True, related_name='tickets', through='oscar_support.RelatedOrder', to='order.Order', verbose_name='Related Orders')), + ('related_products', models.ManyToManyField(blank=True, related_name='tickets', through='oscar_support.RelatedProduct', to='catalogue.Product', verbose_name='Related products')), + ('requester', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='submitted_tickets', to=settings.AUTH_USER_MODEL, verbose_name='Requester')), + ], + options={ + 'verbose_name': 'Ticket', + 'verbose_name_plural': 'Tickets', + 'ordering': ['-date_updated'], + 'abstract': False, + }, + ), + migrations.CreateModel( + name='TicketStatus', + fields=[ + ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22, primary_key=True, serialize=False)), + ('slug', django_extensions.db.fields.AutoSlugField(blank=True, editable=False, populate_from='name', unique=True, verbose_name='Slug')), + ('name', models.CharField(max_length=64, verbose_name='Name')), + ], + options={ + 'verbose_name': 'Ticket status', + 'verbose_name_plural': 'Ticket statuses', + 'abstract': False, + }, + ), + migrations.CreateModel( + name='TicketType', + fields=[ + ('uuid', shortuuidfield.fields.ShortUUIDField(blank=True, editable=False, max_length=22, primary_key=True, serialize=False)), + ('slug', django_extensions.db.fields.AutoSlugField(blank=True, editable=False, populate_from='name', unique=True, verbose_name='Slug')), + ('name', models.CharField(max_length=64, verbose_name='Name')), + ], + options={ + 'verbose_name': 'Ticket type', + 'verbose_name_plural': 'Ticket types', + 'abstract': False, + }, + ), + migrations.AddField( + model_name='ticket', + name='status', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tickets', to='oscar_support.TicketStatus', verbose_name='Status'), + ), + migrations.AddField( + model_name='ticket', + name='type', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tickets', to='oscar_support.TicketType', verbose_name='Type'), + ), + migrations.AddField( + model_name='relatedproduct', + name='ticket', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='relatedproducts', to='oscar_support.Ticket', verbose_name='Ticket'), + ), + migrations.AddField( + model_name='relatedproduct', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='relatedproducts', to=settings.AUTH_USER_MODEL, verbose_name='Added by'), + ), + migrations.AddField( + model_name='relatedorderline', + name='ticket', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='relatedorderlines', to='oscar_support.Ticket', verbose_name='Ticket'), + ), + migrations.AddField( + model_name='relatedorderline', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='relatedorderlines', to=settings.AUTH_USER_MODEL, verbose_name='Added by'), + ), + migrations.AddField( + model_name='relatedorder', + name='ticket', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='relatedorders', to='oscar_support.Ticket', verbose_name='Ticket'), + ), + migrations.AddField( + model_name='relatedorder', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='relatedorders', to=settings.AUTH_USER_MODEL, verbose_name='Added by'), + ), + migrations.AddField( + model_name='message', + name='ticket', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='oscar_support.Ticket', verbose_name='Ticket'), + ), + migrations.AddField( + model_name='message', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to=settings.AUTH_USER_MODEL, verbose_name='Sender'), + ), + migrations.AddField( + model_name='attachment', + name='ticket', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attachments', to='oscar_support.Ticket', verbose_name='Ticket'), + ), + migrations.AddField( + model_name='attachment', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attachments', to=settings.AUTH_USER_MODEL, verbose_name='User'), + ), + migrations.AlterUniqueTogether( + name='ticket', + unique_together=set([('number', 'subticket_id')]), + ), + migrations.RunPython(create_default_ticket_status), + migrations.RunPython(create_default_ticket_type), + ] diff --git a/oscar_support/migrations/0002_auto__chg_field_message_type.py b/oscar_support/migrations/0002_auto__chg_field_message_type.py deleted file mode 100644 index ab61592..0000000 --- a/oscar_support/migrations/0002_auto__chg_field_message_type.py +++ /dev/null @@ -1,375 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -from oscar.core.compat import AUTH_USER_MODEL, AUTH_USER_MODEL_NAME - - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Changing field 'Message.type' - db.alter_column(u'oscar_support_message', 'type', self.gf('django.db.models.fields.CharField')(max_length=30)) - - def backwards(self, orm): - - # Changing field 'Message.type' - db.alter_column(u'oscar_support_message', 'type', self.gf('django.db.models.fields.CharField')(max_length=3)) - - models = { - u'address.country': { - 'Meta': {'ordering': "('-display_order', 'name')", 'object_name': 'Country'}, - 'display_order': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0', 'db_index': 'True'}), - 'is_shipping_country': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'iso_3166_1_a2': ('django.db.models.fields.CharField', [], {'max_length': '2', 'primary_key': 'True'}), - 'iso_3166_1_a3': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True', 'db_index': 'True'}), - 'iso_3166_1_numeric': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True', 'db_index': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'printable_name': ('django.db.models.fields.CharField', [], {'max_length': '128'}) - }, - u'auth.group': { - 'Meta': {'object_name': 'Group'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - u'auth.permission': { - 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - AUTH_USER_MODEL: { - 'Meta': {'object_name': AUTH_USER_MODEL_NAME}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - u'catalogue.attributeentity': { - 'Meta': {'object_name': 'AttributeEntity'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'blank': 'True'}), - 'type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'entities'", 'to': u"orm['catalogue.AttributeEntityType']"}) - }, - u'catalogue.attributeentitytype': { - 'Meta': {'object_name': 'AttributeEntityType'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'blank': 'True'}) - }, - u'catalogue.attributeoption': { - 'Meta': {'object_name': 'AttributeOption'}, - 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'options'", 'to': u"orm['catalogue.AttributeOptionGroup']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'option': ('django.db.models.fields.CharField', [], {'max_length': '255'}) - }, - u'catalogue.attributeoptiongroup': { - 'Meta': {'object_name': 'AttributeOptionGroup'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}) - }, - u'catalogue.category': { - 'Meta': {'ordering': "['full_name']", 'object_name': 'Category'}, - 'depth': ('django.db.models.fields.PositiveIntegerField', [], {}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'full_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - 'numchild': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}) - }, - u'catalogue.option': { - 'Meta': {'object_name': 'Option'}, - 'code': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'type': ('django.db.models.fields.CharField', [], {'default': "'Required'", 'max_length': '128'}) - }, - u'catalogue.product': { - 'Meta': {'ordering': "['-date_created']", 'object_name': 'Product'}, - 'attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.ProductAttribute']", 'through': u"orm['catalogue.ProductAttributeValue']", 'symmetrical': 'False'}), - 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Category']", 'through': u"orm['catalogue.ProductCategory']", 'symmetrical': 'False'}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_discountable': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'variants'", 'null': 'True', 'to': u"orm['catalogue.Product']"}), - 'product_class': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'products'", 'null': 'True', 'to': u"orm['catalogue.ProductClass']"}), - 'product_options': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Option']", 'symmetrical': 'False', 'blank': 'True'}), - 'rating': ('django.db.models.fields.FloatField', [], {'null': 'True'}), - 'recommended_products': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Product']", 'symmetrical': 'False', 'through': u"orm['catalogue.ProductRecommendation']", 'blank': 'True'}), - 'related_products': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'relations'", 'blank': 'True', 'to': u"orm['catalogue.Product']"}), - 'score': ('django.db.models.fields.FloatField', [], {'default': '0.0', 'db_index': 'True'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}), - 'status': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'upc': ('django.db.models.fields.CharField', [], {'max_length': '64', 'unique': 'True', 'null': 'True', 'blank': 'True'}) - }, - u'catalogue.productattribute': { - 'Meta': {'ordering': "['code']", 'object_name': 'ProductAttribute'}, - 'code': ('django.db.models.fields.SlugField', [], {'max_length': '128'}), - 'entity_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeEntityType']", 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'option_group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeOptionGroup']", 'null': 'True', 'blank': 'True'}), - 'product_class': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attributes'", 'null': 'True', 'to': u"orm['catalogue.ProductClass']"}), - 'required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'type': ('django.db.models.fields.CharField', [], {'default': "'text'", 'max_length': '20'}) - }, - u'catalogue.productattributevalue': { - 'Meta': {'object_name': 'ProductAttributeValue'}, - 'attribute': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.ProductAttribute']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attribute_values'", 'to': u"orm['catalogue.Product']"}), - 'value_boolean': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), - 'value_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), - 'value_entity': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeEntity']", 'null': 'True', 'blank': 'True'}), - 'value_file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'value_float': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), - 'value_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'value_integer': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'value_option': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeOption']", 'null': 'True', 'blank': 'True'}), - 'value_richtext': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'value_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}) - }, - u'catalogue.productcategory': { - 'Meta': {'ordering': "['-is_canonical']", 'object_name': 'ProductCategory'}, - 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Category']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_canonical': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']"}) - }, - u'catalogue.productclass': { - 'Meta': {'ordering': "['name']", 'object_name': 'ProductClass'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'options': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Option']", 'symmetrical': 'False', 'blank': 'True'}), - 'requires_shipping': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - 'track_stock': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) - }, - u'catalogue.productrecommendation': { - 'Meta': {'object_name': 'ProductRecommendation'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'primary': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'primary_recommendations'", 'to': u"orm['catalogue.Product']"}), - 'ranking': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}), - 'recommendation': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']"}) - }, - u'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - u'order.billingaddress': { - 'Meta': {'object_name': 'BillingAddress'}, - 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['address.Country']"}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'line1': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'line2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line3': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line4': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'postcode': ('oscar.models.fields.UppercaseCharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), - 'search_text': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), - 'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}) - }, - u'order.line': { - 'Meta': {'object_name': 'Line'}, - 'est_dispatch_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'line_price_before_discounts_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_before_discounts_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'order': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'lines'", 'to': u"orm['order.Order']"}), - 'partner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'order_lines'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['partner.Partner']"}), - 'partner_line_notes': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'partner_line_reference': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'partner_name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'partner_sku': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), - 'quantity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), - 'status': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'stockrecord': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['partner.StockRecord']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'unit_cost_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_price_excl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_price_incl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_retail_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'upc': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}) - }, - u'order.order': { - 'Meta': {'ordering': "['-date_placed']", 'object_name': 'Order'}, - 'basket_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'billing_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['order.BillingAddress']", 'null': 'True', 'blank': 'True'}), - 'currency': ('django.db.models.fields.CharField', [], {'default': "'GBP'", 'max_length': '12'}), - 'date_placed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}), - 'guest_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'number': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}), - 'shipping_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['order.ShippingAddress']", 'null': 'True', 'blank': 'True'}), - 'shipping_code': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}), - 'shipping_excl_tax': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}), - 'shipping_incl_tax': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}), - 'shipping_method': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['sites.Site']"}), - 'status': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), - 'total_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'total_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'orders'", 'null': 'True', 'to': u"orm['{}']".format(AUTH_USER_MODEL)}) - }, - u'order.shippingaddress': { - 'Meta': {'object_name': 'ShippingAddress'}, - 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['address.Country']"}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'line1': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'line2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line3': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line4': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'notes': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'phone_number': ('oscar.models.fields.PhoneNumberField', [], {'max_length': '128', 'blank': 'True'}), - 'postcode': ('oscar.models.fields.UppercaseCharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), - 'search_text': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), - 'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}) - }, - u'oscar_support.attachment': { - 'Meta': {'object_name': 'Attachment'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attachments'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attachments'", 'to': u"orm['{}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.message': { - 'Meta': {'ordering': "['-date_created']", 'object_name': 'Message'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'text': ('django.db.models.fields.TextField', [], {}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['oscar_support.Ticket']"}), - 'type': ('django.db.models.fields.CharField', [], {'default': "u'public'", 'max_length': '30'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['{}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.priority': { - 'Meta': {'object_name': 'Priority'}, - 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django_extensions.db.fields.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '50', 'separator': "u'-'", 'blank': 'True', 'populate_from': "'name'", 'overwrite': 'False'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedorder': { - 'Meta': {'object_name': 'RelatedOrder'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'order': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_orders'", 'to': u"orm['order.Order']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorders'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorders'", 'to': u"orm['{}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedorderline': { - 'Meta': {'object_name': 'RelatedOrderLine'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'line': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_order_lines'", 'to': u"orm['order.Line']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorderlines'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorderlines'", 'to': u"orm['{}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedproduct': { - 'Meta': {'object_name': 'RelatedProduct'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_products'", 'to': u"orm['catalogue.Product']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedproducts'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedproducts'", 'to': u"orm['{}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.ticket': { - 'Meta': {'ordering': "['-date_updated']", 'unique_together': "(('number', 'subticket_id'),)", 'object_name': 'Ticket'}, - 'assigned_group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tickets'", 'null': 'True', 'to': u"orm['auth.Group']"}), - 'assignee': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'assigned_tickets'", 'null': 'True', 'to': u"orm['{}']".format(AUTH_USER_MODEL)}), - 'body': ('django.db.models.fields.TextField', [], {}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'is_internal': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'number': ('django.db.models.fields.CharField', [], {'max_length': '64', 'db_index': 'True'}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'subtickets'", 'null': 'True', 'to': u"orm['oscar_support.Ticket']"}), - 'priority': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tickets'", 'null': 'True', 'to': u"orm['oscar_support.Priority']"}), - 'related_lines': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedOrderLine']", 'to': u"orm['order.Line']"}), - 'related_orders': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedOrder']", 'to': u"orm['order.Order']"}), - 'related_products': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedProduct']", 'to': u"orm['catalogue.Product']"}), - 'requester': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'submitted_tickets'", 'to': u"orm['{}']".format(AUTH_USER_MODEL)}), - 'status': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tickets'", 'to': u"orm['oscar_support.TicketStatus']"}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'subticket_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tickets'", 'to': u"orm['oscar_support.TicketType']"}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.ticketstatus': { - 'Meta': {'object_name': 'TicketStatus'}, - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.tickettype': { - 'Meta': {'object_name': 'TicketType'}, - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'partner.partner': { - 'Meta': {'object_name': 'Partner'}, - 'code': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'users': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'partners'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['{}']".format(AUTH_USER_MODEL)}) - }, - u'partner.stockrecord': { - 'Meta': {'unique_together': "(('partner', 'partner_sku'),)", 'object_name': 'StockRecord'}, - 'cost_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'low_stock_threshold': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'num_allocated': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'num_in_stock': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'partner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'stockrecords'", 'to': u"orm['partner.Partner']"}), - 'partner_sku': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'price_currency': ('django.db.models.fields.CharField', [], {'default': "'GBP'", 'max_length': '12'}), - 'price_excl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'price_retail': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'stockrecords'", 'to': u"orm['catalogue.Product']"}) - }, - u'sites.site': { - 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"}, - 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - } - } - - complete_apps = ['oscar_support'] \ No newline at end of file diff --git a/oscar_support/migrations/0003_auto__add_field_tickettype_slug__add_field_ticketstatus_slug.py b/oscar_support/migrations/0003_auto__add_field_tickettype_slug__add_field_ticketstatus_slug.py deleted file mode 100644 index 655e318..0000000 --- a/oscar_support/migrations/0003_auto__add_field_tickettype_slug__add_field_ticketstatus_slug.py +++ /dev/null @@ -1,387 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -from oscar.core.compat import AUTH_USER_MODEL, AUTH_USER_MODEL_NAME - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Adding field 'TicketType.slug' - db.add_column(u'oscar_support_tickettype', 'slug', - self.gf('django_extensions.db.fields.AutoSlugField')(allow_duplicates=False, max_length=50, separator=u'-', blank=True, default='', populate_from='name', overwrite=False), - keep_default=False) - - # Adding field 'TicketStatus.slug' - db.add_column(u'oscar_support_ticketstatus', 'slug', - self.gf('django_extensions.db.fields.AutoSlugField')(allow_duplicates=False, max_length=50, separator=u'-', blank=True, default='', populate_from='name', overwrite=False), - keep_default=False) - - - def backwards(self, orm): - # Deleting field 'TicketType.slug' - db.delete_column(u'oscar_support_tickettype', 'slug') - - # Deleting field 'TicketStatus.slug' - db.delete_column(u'oscar_support_ticketstatus', 'slug') - - - models = { - u'address.country': { - 'Meta': {'ordering': "('-display_order', 'name')", 'object_name': 'Country'}, - 'display_order': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0', 'db_index': 'True'}), - 'is_shipping_country': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'iso_3166_1_a2': ('django.db.models.fields.CharField', [], {'max_length': '2', 'primary_key': 'True'}), - 'iso_3166_1_a3': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True', 'db_index': 'True'}), - 'iso_3166_1_numeric': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True', 'db_index': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'printable_name': ('django.db.models.fields.CharField', [], {'max_length': '128'}) - }, - u'auth.group': { - 'Meta': {'object_name': 'Group'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - u'auth.permission': { - 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - AUTH_USER_MODEL: { - 'Meta': {'object_name': AUTH_USER_MODEL_NAME}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - u'catalogue.attributeentity': { - 'Meta': {'object_name': 'AttributeEntity'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'blank': 'True'}), - 'type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'entities'", 'to': u"orm['catalogue.AttributeEntityType']"}) - }, - u'catalogue.attributeentitytype': { - 'Meta': {'object_name': 'AttributeEntityType'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'blank': 'True'}) - }, - u'catalogue.attributeoption': { - 'Meta': {'object_name': 'AttributeOption'}, - 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'options'", 'to': u"orm['catalogue.AttributeOptionGroup']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'option': ('django.db.models.fields.CharField', [], {'max_length': '255'}) - }, - u'catalogue.attributeoptiongroup': { - 'Meta': {'object_name': 'AttributeOptionGroup'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}) - }, - u'catalogue.category': { - 'Meta': {'ordering': "['full_name']", 'object_name': 'Category'}, - 'depth': ('django.db.models.fields.PositiveIntegerField', [], {}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'full_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - 'numchild': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}) - }, - u'catalogue.option': { - 'Meta': {'object_name': 'Option'}, - 'code': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'type': ('django.db.models.fields.CharField', [], {'default': "'Required'", 'max_length': '128'}) - }, - u'catalogue.product': { - 'Meta': {'ordering': "['-date_created']", 'object_name': 'Product'}, - 'attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.ProductAttribute']", 'through': u"orm['catalogue.ProductAttributeValue']", 'symmetrical': 'False'}), - 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Category']", 'through': u"orm['catalogue.ProductCategory']", 'symmetrical': 'False'}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_discountable': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'variants'", 'null': 'True', 'to': u"orm['catalogue.Product']"}), - 'product_class': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'products'", 'null': 'True', 'to': u"orm['catalogue.ProductClass']"}), - 'product_options': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Option']", 'symmetrical': 'False', 'blank': 'True'}), - 'rating': ('django.db.models.fields.FloatField', [], {'null': 'True'}), - 'recommended_products': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Product']", 'symmetrical': 'False', 'through': u"orm['catalogue.ProductRecommendation']", 'blank': 'True'}), - 'related_products': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'relations'", 'blank': 'True', 'to': u"orm['catalogue.Product']"}), - 'score': ('django.db.models.fields.FloatField', [], {'default': '0.0', 'db_index': 'True'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}), - 'status': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'upc': ('django.db.models.fields.CharField', [], {'max_length': '64', 'unique': 'True', 'null': 'True', 'blank': 'True'}) - }, - u'catalogue.productattribute': { - 'Meta': {'ordering': "['code']", 'object_name': 'ProductAttribute'}, - 'code': ('django.db.models.fields.SlugField', [], {'max_length': '128'}), - 'entity_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeEntityType']", 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'option_group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeOptionGroup']", 'null': 'True', 'blank': 'True'}), - 'product_class': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attributes'", 'null': 'True', 'to': u"orm['catalogue.ProductClass']"}), - 'required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'type': ('django.db.models.fields.CharField', [], {'default': "'text'", 'max_length': '20'}) - }, - u'catalogue.productattributevalue': { - 'Meta': {'object_name': 'ProductAttributeValue'}, - 'attribute': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.ProductAttribute']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attribute_values'", 'to': u"orm['catalogue.Product']"}), - 'value_boolean': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), - 'value_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), - 'value_entity': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeEntity']", 'null': 'True', 'blank': 'True'}), - 'value_file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'value_float': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), - 'value_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'value_integer': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'value_option': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeOption']", 'null': 'True', 'blank': 'True'}), - 'value_richtext': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'value_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}) - }, - u'catalogue.productcategory': { - 'Meta': {'ordering': "['-is_canonical']", 'object_name': 'ProductCategory'}, - 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Category']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_canonical': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']"}) - }, - u'catalogue.productclass': { - 'Meta': {'ordering': "['name']", 'object_name': 'ProductClass'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'options': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Option']", 'symmetrical': 'False', 'blank': 'True'}), - 'requires_shipping': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - 'track_stock': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) - }, - u'catalogue.productrecommendation': { - 'Meta': {'object_name': 'ProductRecommendation'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'primary': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'primary_recommendations'", 'to': u"orm['catalogue.Product']"}), - 'ranking': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}), - 'recommendation': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']"}) - }, - u'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - u'order.billingaddress': { - 'Meta': {'object_name': 'BillingAddress'}, - 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['address.Country']"}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'line1': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'line2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line3': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line4': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'postcode': ('oscar.models.fields.UppercaseCharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), - 'search_text': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), - 'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}) - }, - u'order.line': { - 'Meta': {'object_name': 'Line'}, - 'est_dispatch_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'line_price_before_discounts_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_before_discounts_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'order': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'lines'", 'to': u"orm['order.Order']"}), - 'partner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'order_lines'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['partner.Partner']"}), - 'partner_line_notes': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'partner_line_reference': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'partner_name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'partner_sku': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), - 'quantity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), - 'status': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'stockrecord': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['partner.StockRecord']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'unit_cost_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_price_excl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_price_incl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_retail_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'upc': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}) - }, - u'order.order': { - 'Meta': {'ordering': "['-date_placed']", 'object_name': 'Order'}, - 'basket_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'billing_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['order.BillingAddress']", 'null': 'True', 'blank': 'True'}), - 'currency': ('django.db.models.fields.CharField', [], {'default': "'GBP'", 'max_length': '12'}), - 'date_placed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}), - 'guest_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'number': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}), - 'shipping_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['order.ShippingAddress']", 'null': 'True', 'blank': 'True'}), - 'shipping_code': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}), - 'shipping_excl_tax': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}), - 'shipping_incl_tax': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}), - 'shipping_method': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['sites.Site']"}), - 'status': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), - 'total_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'total_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'orders'", 'null': 'True', 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}) - }, - u'order.shippingaddress': { - 'Meta': {'object_name': 'ShippingAddress'}, - 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['address.Country']"}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'line1': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'line2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line3': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line4': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'notes': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'phone_number': ('oscar.models.fields.PhoneNumberField', [], {'max_length': '128', 'blank': 'True'}), - 'postcode': ('oscar.models.fields.UppercaseCharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), - 'search_text': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), - 'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}) - }, - u'oscar_support.attachment': { - 'Meta': {'object_name': 'Attachment'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attachments'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attachments'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.message': { - 'Meta': {'ordering': "['-date_created']", 'object_name': 'Message'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'text': ('django.db.models.fields.TextField', [], {}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['oscar_support.Ticket']"}), - 'type': ('django.db.models.fields.CharField', [], {'default': "u'public'", 'max_length': '30'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.priority': { - 'Meta': {'object_name': 'Priority'}, - 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django_extensions.db.fields.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '50', 'separator': "u'-'", 'blank': 'True', 'populate_from': "'name'", 'overwrite': 'False'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedorder': { - 'Meta': {'object_name': 'RelatedOrder'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'order': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_orders'", 'to': u"orm['order.Order']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorders'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorders'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedorderline': { - 'Meta': {'object_name': 'RelatedOrderLine'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'line': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_order_lines'", 'to': u"orm['order.Line']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorderlines'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorderlines'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedproduct': { - 'Meta': {'object_name': 'RelatedProduct'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_products'", 'to': u"orm['catalogue.Product']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedproducts'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedproducts'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.ticket': { - 'Meta': {'ordering': "['-date_updated']", 'unique_together': "(('number', 'subticket_id'),)", 'object_name': 'Ticket'}, - 'assigned_group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tickets'", 'null': 'True', 'to': u"orm['auth.Group']"}), - 'assignee': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'assigned_tickets'", 'null': 'True', 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'body': ('django.db.models.fields.TextField', [], {}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'is_internal': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'number': ('django.db.models.fields.CharField', [], {'max_length': '64', 'db_index': 'True'}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'subtickets'", 'null': 'True', 'to': u"orm['oscar_support.Ticket']"}), - 'priority': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tickets'", 'null': 'True', 'to': u"orm['oscar_support.Priority']"}), - 'related_lines': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedOrderLine']", 'to': u"orm['order.Line']"}), - 'related_orders': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedOrder']", 'to': u"orm['order.Order']"}), - 'related_products': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedProduct']", 'to': u"orm['catalogue.Product']"}), - 'requester': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'submitted_tickets'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'status': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tickets'", 'to': u"orm['oscar_support.TicketStatus']"}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'subticket_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tickets'", 'to': u"orm['oscar_support.TicketType']"}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.ticketstatus': { - 'Meta': {'object_name': 'TicketStatus'}, - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), - 'slug': ('django_extensions.db.fields.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '50', 'separator': "u'-'", 'blank': 'True', 'populate_from': "'name'", 'overwrite': 'False'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.tickettype': { - 'Meta': {'object_name': 'TicketType'}, - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), - 'slug': ('django_extensions.db.fields.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '50', 'separator': "u'-'", 'blank': 'True', 'populate_from': "'name'", 'overwrite': 'False'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'partner.partner': { - 'Meta': {'object_name': 'Partner'}, - 'code': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'users': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'partners'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}) - }, - u'partner.stockrecord': { - 'Meta': {'unique_together': "(('partner', 'partner_sku'),)", 'object_name': 'StockRecord'}, - 'cost_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'low_stock_threshold': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'num_allocated': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'num_in_stock': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'partner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'stockrecords'", 'to': u"orm['partner.Partner']"}), - 'partner_sku': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'price_currency': ('django.db.models.fields.CharField', [], {'default': "'GBP'", 'max_length': '12'}), - 'price_excl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'price_retail': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'stockrecords'", 'to': u"orm['catalogue.Product']"}) - }, - u'sites.site': { - 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"}, - 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - } - } - - complete_apps = ['oscar_support'] \ No newline at end of file diff --git a/oscar_support/migrations/0004_populate_slug_fields.py b/oscar_support/migrations/0004_populate_slug_fields.py deleted file mode 100644 index cd5ea4f..0000000 --- a/oscar_support/migrations/0004_populate_slug_fields.py +++ /dev/null @@ -1,382 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import DataMigration -from django.db import models - -from oscar.core.compat import AUTH_USER_MODEL, AUTH_USER_MODEL_NAME - - -class Migration(DataMigration): - - def forwards(self, orm): - "Write your forwards methods here." - for ticket_type in orm['oscar_support.TicketType'].objects.filter(slug=''): - # AutoSlugField will create a slug based on the name - ticket_type.save() - - for ticket_status in orm['oscar_support.TicketStatus'].objects.filter(slug=''): - # AutoSlugField will create a slug based on the name - ticket_status.save() - - def backwards(self, orm): - "Write your backwards methods here." - pass - - models = { - u'address.country': { - 'Meta': {'ordering': "('-display_order', 'name')", 'object_name': 'Country'}, - 'display_order': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0', 'db_index': 'True'}), - 'is_shipping_country': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'iso_3166_1_a2': ('django.db.models.fields.CharField', [], {'max_length': '2', 'primary_key': 'True'}), - 'iso_3166_1_a3': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True', 'db_index': 'True'}), - 'iso_3166_1_numeric': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True', 'db_index': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'printable_name': ('django.db.models.fields.CharField', [], {'max_length': '128'}) - }, - u'auth.group': { - 'Meta': {'object_name': 'Group'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - u'auth.permission': { - 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - AUTH_USER_MODEL: { - 'Meta': {'object_name': AUTH_USER_MODEL_NAME}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - u'catalogue.attributeentity': { - 'Meta': {'object_name': 'AttributeEntity'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'blank': 'True'}), - 'type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'entities'", 'to': u"orm['catalogue.AttributeEntityType']"}) - }, - u'catalogue.attributeentitytype': { - 'Meta': {'object_name': 'AttributeEntityType'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'blank': 'True'}) - }, - u'catalogue.attributeoption': { - 'Meta': {'object_name': 'AttributeOption'}, - 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'options'", 'to': u"orm['catalogue.AttributeOptionGroup']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'option': ('django.db.models.fields.CharField', [], {'max_length': '255'}) - }, - u'catalogue.attributeoptiongroup': { - 'Meta': {'object_name': 'AttributeOptionGroup'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}) - }, - u'catalogue.category': { - 'Meta': {'ordering': "['full_name']", 'object_name': 'Category'}, - 'depth': ('django.db.models.fields.PositiveIntegerField', [], {}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'full_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - 'numchild': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}) - }, - u'catalogue.option': { - 'Meta': {'object_name': 'Option'}, - 'code': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'type': ('django.db.models.fields.CharField', [], {'default': "'Required'", 'max_length': '128'}) - }, - u'catalogue.product': { - 'Meta': {'ordering': "['-date_created']", 'object_name': 'Product'}, - 'attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.ProductAttribute']", 'through': u"orm['catalogue.ProductAttributeValue']", 'symmetrical': 'False'}), - 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Category']", 'through': u"orm['catalogue.ProductCategory']", 'symmetrical': 'False'}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_discountable': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'variants'", 'null': 'True', 'to': u"orm['catalogue.Product']"}), - 'product_class': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'products'", 'null': 'True', 'to': u"orm['catalogue.ProductClass']"}), - 'product_options': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Option']", 'symmetrical': 'False', 'blank': 'True'}), - 'rating': ('django.db.models.fields.FloatField', [], {'null': 'True'}), - 'recommended_products': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Product']", 'symmetrical': 'False', 'through': u"orm['catalogue.ProductRecommendation']", 'blank': 'True'}), - 'related_products': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'relations'", 'blank': 'True', 'to': u"orm['catalogue.Product']"}), - 'score': ('django.db.models.fields.FloatField', [], {'default': '0.0', 'db_index': 'True'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}), - 'status': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'upc': ('django.db.models.fields.CharField', [], {'max_length': '64', 'unique': 'True', 'null': 'True', 'blank': 'True'}) - }, - u'catalogue.productattribute': { - 'Meta': {'ordering': "['code']", 'object_name': 'ProductAttribute'}, - 'code': ('django.db.models.fields.SlugField', [], {'max_length': '128'}), - 'entity_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeEntityType']", 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'option_group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeOptionGroup']", 'null': 'True', 'blank': 'True'}), - 'product_class': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attributes'", 'null': 'True', 'to': u"orm['catalogue.ProductClass']"}), - 'required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'type': ('django.db.models.fields.CharField', [], {'default': "'text'", 'max_length': '20'}) - }, - u'catalogue.productattributevalue': { - 'Meta': {'object_name': 'ProductAttributeValue'}, - 'attribute': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.ProductAttribute']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attribute_values'", 'to': u"orm['catalogue.Product']"}), - 'value_boolean': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), - 'value_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), - 'value_entity': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeEntity']", 'null': 'True', 'blank': 'True'}), - 'value_file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'value_float': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), - 'value_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'value_integer': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'value_option': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeOption']", 'null': 'True', 'blank': 'True'}), - 'value_richtext': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'value_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}) - }, - u'catalogue.productcategory': { - 'Meta': {'ordering': "['-is_canonical']", 'object_name': 'ProductCategory'}, - 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Category']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_canonical': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']"}) - }, - u'catalogue.productclass': { - 'Meta': {'ordering': "['name']", 'object_name': 'ProductClass'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'options': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Option']", 'symmetrical': 'False', 'blank': 'True'}), - 'requires_shipping': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - 'track_stock': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) - }, - u'catalogue.productrecommendation': { - 'Meta': {'object_name': 'ProductRecommendation'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'primary': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'primary_recommendations'", 'to': u"orm['catalogue.Product']"}), - 'ranking': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}), - 'recommendation': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']"}) - }, - u'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - u'order.billingaddress': { - 'Meta': {'object_name': 'BillingAddress'}, - 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['address.Country']"}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'line1': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'line2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line3': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line4': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'postcode': ('oscar.models.fields.UppercaseCharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), - 'search_text': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), - 'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}) - }, - u'order.line': { - 'Meta': {'object_name': 'Line'}, - 'est_dispatch_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'line_price_before_discounts_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_before_discounts_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'order': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'lines'", 'to': u"orm['order.Order']"}), - 'partner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'order_lines'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['partner.Partner']"}), - 'partner_line_notes': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'partner_line_reference': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'partner_name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'partner_sku': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), - 'quantity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), - 'status': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'stockrecord': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['partner.StockRecord']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'unit_cost_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_price_excl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_price_incl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_retail_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'upc': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}) - }, - u'order.order': { - 'Meta': {'ordering': "['-date_placed']", 'object_name': 'Order'}, - 'basket_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'billing_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['order.BillingAddress']", 'null': 'True', 'blank': 'True'}), - 'currency': ('django.db.models.fields.CharField', [], {'default': "'GBP'", 'max_length': '12'}), - 'date_placed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}), - 'guest_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'number': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}), - 'shipping_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['order.ShippingAddress']", 'null': 'True', 'blank': 'True'}), - 'shipping_code': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}), - 'shipping_excl_tax': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}), - 'shipping_incl_tax': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}), - 'shipping_method': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['sites.Site']"}), - 'status': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), - 'total_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'total_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'orders'", 'null': 'True', 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}) - }, - u'order.shippingaddress': { - 'Meta': {'object_name': 'ShippingAddress'}, - 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['address.Country']"}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'line1': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'line2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line3': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line4': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'notes': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'phone_number': ('oscar.models.fields.PhoneNumberField', [], {'max_length': '128', 'blank': 'True'}), - 'postcode': ('oscar.models.fields.UppercaseCharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), - 'search_text': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), - 'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}) - }, - u'oscar_support.attachment': { - 'Meta': {'object_name': 'Attachment'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attachments'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attachments'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.message': { - 'Meta': {'ordering': "['-date_created']", 'object_name': 'Message'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'text': ('django.db.models.fields.TextField', [], {}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['oscar_support.Ticket']"}), - 'type': ('django.db.models.fields.CharField', [], {'default': "u'public'", 'max_length': '30'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.priority': { - 'Meta': {'object_name': 'Priority'}, - 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django_extensions.db.fields.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '50', 'separator': "u'-'", 'blank': 'True', 'populate_from': "'name'", 'overwrite': 'False'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedorder': { - 'Meta': {'object_name': 'RelatedOrder'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'order': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_orders'", 'to': u"orm['order.Order']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorders'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorders'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedorderline': { - 'Meta': {'object_name': 'RelatedOrderLine'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'line': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_order_lines'", 'to': u"orm['order.Line']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorderlines'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorderlines'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedproduct': { - 'Meta': {'object_name': 'RelatedProduct'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_products'", 'to': u"orm['catalogue.Product']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedproducts'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedproducts'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.ticket': { - 'Meta': {'ordering': "['-date_updated']", 'unique_together': "(('number', 'subticket_id'),)", 'object_name': 'Ticket'}, - 'assigned_group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tickets'", 'null': 'True', 'to': u"orm['auth.Group']"}), - 'assignee': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'assigned_tickets'", 'null': 'True', 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'body': ('django.db.models.fields.TextField', [], {}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'is_internal': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'number': ('django.db.models.fields.CharField', [], {'max_length': '64', 'db_index': 'True'}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'subtickets'", 'null': 'True', 'to': u"orm['oscar_support.Ticket']"}), - 'priority': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tickets'", 'null': 'True', 'to': u"orm['oscar_support.Priority']"}), - 'related_lines': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedOrderLine']", 'to': u"orm['order.Line']"}), - 'related_orders': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedOrder']", 'to': u"orm['order.Order']"}), - 'related_products': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedProduct']", 'to': u"orm['catalogue.Product']"}), - 'requester': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'submitted_tickets'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'status': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tickets'", 'to': u"orm['oscar_support.TicketStatus']"}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'subticket_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tickets'", 'to': u"orm['oscar_support.TicketType']"}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.ticketstatus': { - 'Meta': {'object_name': 'TicketStatus'}, - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), - 'slug': ('django_extensions.db.fields.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '50', 'separator': "u'-'", 'blank': 'True', 'populate_from': "'name'", 'overwrite': 'False'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.tickettype': { - 'Meta': {'object_name': 'TicketType'}, - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), - 'slug': ('django_extensions.db.fields.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '50', 'separator': "u'-'", 'blank': 'True', 'populate_from': "'name'", 'overwrite': 'False'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'partner.partner': { - 'Meta': {'object_name': 'Partner'}, - 'code': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'users': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'partners'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}) - }, - u'partner.stockrecord': { - 'Meta': {'unique_together': "(('partner', 'partner_sku'),)", 'object_name': 'StockRecord'}, - 'cost_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'low_stock_threshold': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'num_allocated': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'num_in_stock': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'partner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'stockrecords'", 'to': u"orm['partner.Partner']"}), - 'partner_sku': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'price_currency': ('django.db.models.fields.CharField', [], {'default': "'GBP'", 'max_length': '12'}), - 'price_excl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'price_retail': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'stockrecords'", 'to': u"orm['catalogue.Product']"}) - }, - u'sites.site': { - 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"}, - 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - } - } - - complete_apps = ['oscar_support'] - symmetrical = True diff --git a/oscar_support/migrations/0005_auto__add_unique_tickettype_slug__del_unique_tickettype_name__add_uniq.py b/oscar_support/migrations/0005_auto__add_unique_tickettype_slug__del_unique_tickettype_name__add_uniq.py deleted file mode 100644 index bf8ae0f..0000000 --- a/oscar_support/migrations/0005_auto__add_unique_tickettype_slug__del_unique_tickettype_name__add_uniq.py +++ /dev/null @@ -1,394 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - -from oscar.core.compat import AUTH_USER_MODEL, AUTH_USER_MODEL_NAME - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Removing unique constraint on 'TicketStatus', fields ['name'] - db.delete_unique(u'oscar_support_ticketstatus', ['name']) - - # Removing unique constraint on 'TicketType', fields ['name'] - db.delete_unique(u'oscar_support_tickettype', ['name']) - - # Adding unique constraint on 'TicketType', fields ['slug'] - db.create_unique(u'oscar_support_tickettype', ['slug']) - - # Adding unique constraint on 'TicketStatus', fields ['slug'] - db.create_unique(u'oscar_support_ticketstatus', ['slug']) - - def backwards(self, orm): - # Removing unique constraint on 'TicketStatus', fields ['slug'] - db.delete_unique(u'oscar_support_ticketstatus', ['slug']) - - # Removing unique constraint on 'TicketType', fields ['slug'] - db.delete_unique(u'oscar_support_tickettype', ['slug']) - - # Adding unique constraint on 'TicketType', fields ['name'] - db.create_unique(u'oscar_support_tickettype', ['name']) - - # Adding unique constraint on 'TicketStatus', fields ['name'] - db.create_unique(u'oscar_support_ticketstatus', ['name']) - - - models = { - u'address.country': { - 'Meta': {'ordering': "('-display_order', 'name')", 'object_name': 'Country'}, - 'display_order': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0', 'db_index': 'True'}), - 'is_shipping_country': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'iso_3166_1_a2': ('django.db.models.fields.CharField', [], {'max_length': '2', 'primary_key': 'True'}), - 'iso_3166_1_a3': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True', 'db_index': 'True'}), - 'iso_3166_1_numeric': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True', 'db_index': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'printable_name': ('django.db.models.fields.CharField', [], {'max_length': '128'}) - }, - u'auth.group': { - 'Meta': {'object_name': 'Group'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - u'auth.permission': { - 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - AUTH_USER_MODEL: { - 'Meta': {'object_name': AUTH_USER_MODEL_NAME}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - u'catalogue.attributeentity': { - 'Meta': {'object_name': 'AttributeEntity'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'blank': 'True'}), - 'type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'entities'", 'to': u"orm['catalogue.AttributeEntityType']"}) - }, - u'catalogue.attributeentitytype': { - 'Meta': {'object_name': 'AttributeEntityType'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'blank': 'True'}) - }, - u'catalogue.attributeoption': { - 'Meta': {'object_name': 'AttributeOption'}, - 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'options'", 'to': u"orm['catalogue.AttributeOptionGroup']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'option': ('django.db.models.fields.CharField', [], {'max_length': '255'}) - }, - u'catalogue.attributeoptiongroup': { - 'Meta': {'object_name': 'AttributeOptionGroup'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}) - }, - u'catalogue.category': { - 'Meta': {'ordering': "['full_name']", 'object_name': 'Category'}, - 'depth': ('django.db.models.fields.PositiveIntegerField', [], {}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'full_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - 'numchild': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}) - }, - u'catalogue.option': { - 'Meta': {'object_name': 'Option'}, - 'code': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'type': ('django.db.models.fields.CharField', [], {'default': "'Required'", 'max_length': '128'}) - }, - u'catalogue.product': { - 'Meta': {'ordering': "['-date_created']", 'object_name': 'Product'}, - 'attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.ProductAttribute']", 'through': u"orm['catalogue.ProductAttributeValue']", 'symmetrical': 'False'}), - 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Category']", 'through': u"orm['catalogue.ProductCategory']", 'symmetrical': 'False'}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_discountable': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'variants'", 'null': 'True', 'to': u"orm['catalogue.Product']"}), - 'product_class': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'products'", 'null': 'True', 'to': u"orm['catalogue.ProductClass']"}), - 'product_options': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Option']", 'symmetrical': 'False', 'blank': 'True'}), - 'rating': ('django.db.models.fields.FloatField', [], {'null': 'True'}), - 'recommended_products': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Product']", 'symmetrical': 'False', 'through': u"orm['catalogue.ProductRecommendation']", 'blank': 'True'}), - 'related_products': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'relations'", 'blank': 'True', 'to': u"orm['catalogue.Product']"}), - 'score': ('django.db.models.fields.FloatField', [], {'default': '0.0', 'db_index': 'True'}), - 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}), - 'status': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'upc': ('django.db.models.fields.CharField', [], {'max_length': '64', 'unique': 'True', 'null': 'True', 'blank': 'True'}) - }, - u'catalogue.productattribute': { - 'Meta': {'ordering': "['code']", 'object_name': 'ProductAttribute'}, - 'code': ('django.db.models.fields.SlugField', [], {'max_length': '128'}), - 'entity_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeEntityType']", 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'option_group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeOptionGroup']", 'null': 'True', 'blank': 'True'}), - 'product_class': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attributes'", 'null': 'True', 'to': u"orm['catalogue.ProductClass']"}), - 'required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'type': ('django.db.models.fields.CharField', [], {'default': "'text'", 'max_length': '20'}) - }, - u'catalogue.productattributevalue': { - 'Meta': {'object_name': 'ProductAttributeValue'}, - 'attribute': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.ProductAttribute']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attribute_values'", 'to': u"orm['catalogue.Product']"}), - 'value_boolean': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), - 'value_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), - 'value_entity': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeEntity']", 'null': 'True', 'blank': 'True'}), - 'value_file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'value_float': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}), - 'value_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'value_integer': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'value_option': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeOption']", 'null': 'True', 'blank': 'True'}), - 'value_richtext': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'value_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}) - }, - u'catalogue.productcategory': { - 'Meta': {'ordering': "['-is_canonical']", 'object_name': 'ProductCategory'}, - 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Category']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_canonical': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']"}) - }, - u'catalogue.productclass': { - 'Meta': {'ordering': "['name']", 'object_name': 'ProductClass'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'options': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Option']", 'symmetrical': 'False', 'blank': 'True'}), - 'requires_shipping': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - 'track_stock': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) - }, - u'catalogue.productrecommendation': { - 'Meta': {'object_name': 'ProductRecommendation'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'primary': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'primary_recommendations'", 'to': u"orm['catalogue.Product']"}), - 'ranking': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}), - 'recommendation': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']"}) - }, - u'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - u'order.billingaddress': { - 'Meta': {'object_name': 'BillingAddress'}, - 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['address.Country']"}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'line1': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'line2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line3': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line4': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'postcode': ('oscar.models.fields.UppercaseCharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), - 'search_text': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), - 'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}) - }, - u'order.line': { - 'Meta': {'object_name': 'Line'}, - 'est_dispatch_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'line_price_before_discounts_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_before_discounts_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'line_price_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'order': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'lines'", 'to': u"orm['order.Order']"}), - 'partner': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'order_lines'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['partner.Partner']"}), - 'partner_line_notes': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'partner_line_reference': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'partner_name': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'partner_sku': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), - 'quantity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), - 'status': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'stockrecord': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['partner.StockRecord']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'unit_cost_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_price_excl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_price_incl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'unit_retail_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'upc': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}) - }, - u'order.order': { - 'Meta': {'ordering': "['-date_placed']", 'object_name': 'Order'}, - 'basket_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'billing_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['order.BillingAddress']", 'null': 'True', 'blank': 'True'}), - 'currency': ('django.db.models.fields.CharField', [], {'default': "'GBP'", 'max_length': '12'}), - 'date_placed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}), - 'guest_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'number': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}), - 'shipping_address': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['order.ShippingAddress']", 'null': 'True', 'blank': 'True'}), - 'shipping_code': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}), - 'shipping_excl_tax': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}), - 'shipping_incl_tax': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '12', 'decimal_places': '2'}), - 'shipping_method': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['sites.Site']"}), - 'status': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), - 'total_excl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'total_incl_tax': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'orders'", 'null': 'True', 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}) - }, - u'order.shippingaddress': { - 'Meta': {'object_name': 'ShippingAddress'}, - 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['address.Country']"}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'line1': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'line2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line3': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'line4': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'notes': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'phone_number': ('oscar.models.fields.PhoneNumberField', [], {'max_length': '128', 'blank': 'True'}), - 'postcode': ('oscar.models.fields.UppercaseCharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), - 'search_text': ('django.db.models.fields.CharField', [], {'max_length': '1000'}), - 'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}) - }, - u'oscar_support.attachment': { - 'Meta': {'object_name': 'Attachment'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attachments'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attachments'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.message': { - 'Meta': {'ordering': "['-date_created']", 'object_name': 'Message'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'text': ('django.db.models.fields.TextField', [], {}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['oscar_support.Ticket']"}), - 'type': ('django.db.models.fields.CharField', [], {'default': "u'public'", 'max_length': '30'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.priority': { - 'Meta': {'object_name': 'Priority'}, - 'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'slug': ('django_extensions.db.fields.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '50', 'separator': "u'-'", 'blank': 'True', 'populate_from': "'name'", 'overwrite': 'False'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedorder': { - 'Meta': {'object_name': 'RelatedOrder'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'order': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_orders'", 'to': u"orm['order.Order']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorders'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorders'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedorderline': { - 'Meta': {'object_name': 'RelatedOrderLine'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'line': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_order_lines'", 'to': u"orm['order.Line']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorderlines'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedorderlines'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.relatedproduct': { - 'Meta': {'object_name': 'RelatedProduct'}, - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ticket_related_products'", 'to': u"orm['catalogue.Product']"}), - 'ticket': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedproducts'", 'to': u"orm['oscar_support.Ticket']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'relatedproducts'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.ticket': { - 'Meta': {'ordering': "['-date_updated']", 'unique_together': "(('number', 'subticket_id'),)", 'object_name': 'Ticket'}, - 'assigned_group': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tickets'", 'null': 'True', 'to': u"orm['auth.Group']"}), - 'assignee': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'assigned_tickets'", 'null': 'True', 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'body': ('django.db.models.fields.TextField', [], {}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {}), - 'is_internal': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'number': ('django.db.models.fields.CharField', [], {'max_length': '64', 'db_index': 'True'}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'subtickets'", 'null': 'True', 'to': u"orm['oscar_support.Ticket']"}), - 'priority': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tickets'", 'null': 'True', 'to': u"orm['oscar_support.Priority']"}), - 'related_lines': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedOrderLine']", 'to': u"orm['order.Line']"}), - 'related_orders': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedOrder']", 'to': u"orm['order.Order']"}), - 'related_products': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'tickets'", 'blank': 'True', 'through': u"orm['oscar_support.RelatedProduct']", 'to': u"orm['catalogue.Product']"}), - 'requester': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'submitted_tickets'", 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}), - 'status': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tickets'", 'to': u"orm['oscar_support.TicketStatus']"}), - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'subticket_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tickets'", 'to': u"orm['oscar_support.TicketType']"}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.ticketstatus': { - 'Meta': {'object_name': 'TicketStatus'}, - 'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}), - 'slug': ('django_extensions.db.fields.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '50', 'separator': "u'-'", 'blank': 'True', 'unique': 'True', 'populate_from': "'name'", 'overwrite': 'False'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'oscar_support.tickettype': { - 'Meta': {'object_name': 'TicketType'}, - 'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}), - 'slug': ('django_extensions.db.fields.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '50', 'separator': "u'-'", 'blank': 'True', 'unique': 'True', 'populate_from': "'name'", 'overwrite': 'False'}), - 'uuid': ('shortuuidfield.fields.ShortUUIDField', [], {'max_length': '22', 'primary_key': 'True'}) - }, - u'partner.partner': { - 'Meta': {'object_name': 'Partner'}, - 'code': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), - 'users': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'partners'", 'null': 'True', 'symmetrical': 'False', 'to': u"orm['{0}']".format(AUTH_USER_MODEL)}) - }, - u'partner.stockrecord': { - 'Meta': {'unique_together': "(('partner', 'partner_sku'),)", 'object_name': 'StockRecord'}, - 'cost_price': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'low_stock_threshold': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'num_allocated': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), - 'num_in_stock': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), - 'partner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'stockrecords'", 'to': u"orm['partner.Partner']"}), - 'partner_sku': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'price_currency': ('django.db.models.fields.CharField', [], {'default': "'GBP'", 'max_length': '12'}), - 'price_excl_tax': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'price_retail': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}), - 'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'stockrecords'", 'to': u"orm['catalogue.Product']"}) - }, - u'sites.site': { - 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"}, - 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - } - } - - complete_apps = ['oscar_support'] \ No newline at end of file diff --git a/oscar_support/mixins.py b/oscar_support/mixins.py index d44e2b8..972154e 100644 --- a/oscar_support/mixins.py +++ b/oscar_support/mixins.py @@ -4,8 +4,8 @@ class ModificationTrackingMixin(models.Model): - date_created = models.DateTimeField(_("Created")) - date_updated = models.DateTimeField(_("Last modified")) + date_created = models.DateTimeField(_("Created"), blank=True) + date_updated = models.DateTimeField(_("Last modified"), blank=True) def save(self, *args, **kwargs): if not self.date_created: diff --git a/oscar_support/static/oscar_support/js/dashboard.js b/oscar_support/static/oscar_support/js/dashboard.js deleted file mode 100644 index 9110086..0000000 --- a/oscar_support/static/oscar_support/js/dashboard.js +++ /dev/null @@ -1,50 +0,0 @@ -var support = support || {}; -support.dashboard = { - init: function () {}, - initAutoComplete: function () { - $('.autocomplete-ajax-field').select2({ - minimumInputLength: 3, - query: function (options) { - var apiUrl = $(this)[0].element.data('source-url'); - var results = []; - - $.ajax({ - url: apiUrl, - dataType: 'json', - data: { - filter: options.term, - }, - success: function (data) { - $.each(data, function (key, obj) { - results.push({ - id: obj.id, - text: obj.display_text, - }); - }); - options.callback({more: false, results: results}); - } - }); - }, - /** - * Initialise the select2 element with the ID in the value. This - * requests the corresponding entity (given bey the source URL with - * the specified ID and passes the returned object to select2. - * If no value is present, the lookup is ignored. - * - */ - initSelection: function (element, callback) { - var elemValue = $(element).val(); - if (elemValue === null) { - return; - } - $.ajax({ - url: $(element).data('source-url') + elemValue + '/', - dataType: 'json', - success: function (data) { - callback({id: data.id, text: data.display_text}); - } - }); - } - }); - } -}; diff --git a/oscar_support/static/oscar_support/less/support.less b/oscar_support/static/oscar_support/less/support.less deleted file mode 100644 index df902a8..0000000 --- a/oscar_support/static/oscar_support/less/support.less +++ /dev/null @@ -1,154 +0,0 @@ -.ticket-list { - .well { - margin-bottom:0; - border-top-width:0; - border-color:#e2e2e2; - position: relative; - &:first-child { - border-top-width:1px; - } - &:nth-child(odd) { - background:#fff; - } - &:hover { - background:#f1faff; - } - } - .well.active { - background:#f1faff; - &:after { - border-bottom: 10px solid transparent; - border-left: 10px solid #f1faff; - border-top: 10px solid transparent; - content: ""; - display: inline-block; - position: absolute; - right: -10px; - top: 40px; - } - &:before { - border-bottom: 11px solid transparent; - border-left: 11px solid #bbb; - border-top: 11px solid transparent; - content: ""; - display: inline-block; - position: absolute; - right: -11px; - top: 39px; - } - } -} -.ticket-messages { - .well { - border-left-width:0; - border-right-width:0; - background-color:#fff; - border-color:#e2e2e2; - font-size: 1.2em; - - &:hover { - background-color:#fff; - } - ul, ul>li { - margin-left: 0; - } - ul>li { - list-style-type: none; - } - } - .internal-message { - background:#f1faff; - &:nth-child(odd) { - background:#f1faff; - } - } -} -.form-assigned { - .control-label { - text-align:right; - } -} -.ticket-message { - ul { - margin:0; - } - li { - display:inline-block; - } -} -:root .ticket-message { - input[type=radio] { - position: absolute; - clip: rect(0,0,0,0); - } - input[type=radio] ~ label { - font-size: 12px; - font-weight: bold; - display: inline-block; - padding: 4px 14px; - margin-bottom: 0; - line-height: 20px; - text-align: center; - vertical-align: middle; - cursor: pointer; - color: #fff; - border: 1px solid #BBB; - border-bottom-color: #A2A2A2; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - background-color: #006FB5; - background-image: -moz-linear-gradient(top, #0083C9, #005096); - background-image: -ms-linear-gradient(top, #0083C9, #005096); - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0083C9), to(#005096)); - background-image: -webkit-linear-gradient(top, #0083C9, #005096); - background-image: -o-linear-gradient(top, #0083C9, #005096); - background-image: linear-gradient(top, #0083C9, #005096); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0083c9', endColorstr='#005096', GradientType=0); - border-color: #005096 #005096 #00274A; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - filter: progid:dximagetransform.microsoft.gradient(enabled=false); - } - input[type=radio]:checked ~ label { - background-color: #005096; - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); - } - textarea { - width: 99%; - height: 150px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } -} - -.status-dropdown-button { - width: 100%; - border: none; -} - -.ticket-message-fields { - padding-right: 30px; - input { - width: 100%; - } - textarea { - width: 100%; - height: 200px; - } -} - -.ticket-property-fields { - input, select { - width: 100%; - } -} - diff --git a/oscar_support/static/oscar_support/lib/less/less-1.4.1.min.js b/oscar_support/static/oscar_support/lib/less/less-1.4.1.min.js deleted file mode 100644 index 5aaea85..0000000 --- a/oscar_support/static/oscar_support/lib/less/less-1.4.1.min.js +++ /dev/null @@ -1,11 +0,0 @@ -/* - * LESS - Leaner CSS v1.4.1 - * http://lesscss.org - * - * Copyright (c) 2009-2013, Alexis Sellier - * Licensed under the Apache 2.0 License. - * - * @licence - */(function(e,t){function n(t){return e.less[t.split("/")[1]]}function f(){r.env==="development"?(r.optimization=0,r.watchTimer=setInterval(function(){r.watchMode&&g(function(e,t,n,i,s){e?k(e,i.href):t&&S(t.toCSS(r),i,s.lastModified)})},r.poll)):r.optimization=3}function m(){var e=document.getElementsByTagName("style");for(var t=0;t0&&(s.splice(o-1,2),o-=2)}return i.hostPart=r[1],i.directories=s,i.path=r[1]+s.join("/"),i.fileUrl=i.path+(r[4]||""),i.url=i.fileUrl+(r[5]||""),i}function w(t,n,i,s){var o=b(t.href,e.location.href),u=o.url,a=l&&l.getItem(u),f=l&&l.getItem(u+":timestamp"),c={css:a,timestamp:f},h,p={relativeUrls:r.relativeUrls,currentDirectory:o.path,filename:u};t instanceof r.tree.parseEnv?(h=new r.tree.parseEnv(t),p.entryPath=h.currentFileInfo.entryPath,p.rootpath=h.currentFileInfo.rootpath,p.rootFilename=h.currentFileInfo.rootFilename):(h=new r.tree.parseEnv(r),h.mime=t.type,p.entryPath=o.path,p.rootpath=r.rootpath||o.path,p.rootFilename=u),h.relativeUrls&&(r.rootpath?p.rootpath=b(r.rootpath+y(o.path,p.entryPath)).path:p.rootpath=o.path),x(u,t.type,function(e,a){v+=e.replace(/@import .+?;/ig,"");if(!i&&c&&a&&(new Date(a)).valueOf()===(new Date(c.timestamp)).valueOf())S(c.css,t),n(null,null,e,t,{local:!0,remaining:s},u);else try{h.contents[u]=e,h.paths=[o.path],h.currentFileInfo=p,(new r.Parser(h)).parse(e,function(r,i){if(r)return n(r,null,null,t);try{n(r,i,e,t,{local:!1,lastModified:a,remaining:s},u),h.currentFileInfo.rootFilename===u&&N(document.getElementById("less-error-message:"+E(u)))}catch(r){n(r,null,null,t)}})}catch(f){n(f,null,null,t)}},function(e,r){n({type:"File",message:"'"+r+"' wasn't found ("+e+")"},null,null,t)})}function E(e){return e.replace(/^[a-z-]+:\/+?[^\/]+/,"").replace(/^\//,"").replace(/\.[a-zA-Z]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function S(e,t,n){var r=t.href||"",i="less:"+(t.title||E(r)),s=document.getElementById(i),o=!1,u=document.createElement("style");u.setAttribute("type","text/css"),t.media&&u.setAttribute("media",t.media),u.id=i;if(u.styleSheet)try{u.styleSheet.cssText=e}catch(a){throw new Error("Couldn't reassign styleSheet.cssText.")}else u.appendChild(document.createTextNode(e)),o=s!==null&&s.childNodes.length>0&&u.childNodes.length>0&&s.firstChild.nodeValue===u.firstChild.nodeValue;var f=document.getElementsByTagName("head")[0];if(s==null||o===!1){var c=t&&t.nextSibling||null;(c||document.getElementsByTagName("head")[0]).parentNode.insertBefore(u,c)}s&&o===!1&&f.removeChild(s);if(n&&l){C("saving "+r+" to cache.");try{l.setItem(r,e),l.setItem(r+":timestamp",n)}catch(a){C("failed to save")}}}function x(e,t,n,i){function a(t,n,r){t.status>=200&&t.status<300?n(t.responseText,t.getResponseHeader("Last-Modified")):typeof r=="function"&&r(t.status,e)}var s=T(),u=o?r.fileAsync:r.async;typeof s.overrideMimeType=="function"&&s.overrideMimeType("text/css"),s.open("GET",e,u),s.setRequestHeader("Accept",t||"text/x-less, text/css; q=0.9, */*; q=0.5"),s.send(null),o&&!r.fileAsync?s.status===0||s.status>=200&&s.status<300?n(s.responseText):i(s.status,e):u?s.onreadystatechange=function(){s.readyState==4&&a(s,n,i)}:a(s,n,i)}function T(){if(e.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(t){return C("browser doesn't support AJAX."),null}}function N(e){return e&&e.parentNode.removeChild(e)}function C(e){r.env=="development"&&typeof console!="undefined"&&console.log("less: "+e)}function k(e,n){var i="less-error-message:"+E(n||""),s='
  • {content}
  • ',o=document.createElement("div"),u,a,f=[],l=e.filename||n,c=l.match(/([^\/]+(\?.*)?)$/)[1];o.id=i,o.className="less-error-message",a="

    "+(e.type||"Syntax")+"Error: "+(e.message||"There is an error in your .less file")+"

    "+'

    in '+c+" ";var h=function(e,n,r){e.extract[n]!=t&&f.push(s.replace(/\{line\}/,(parseInt(e.line)||0)+(n-1)).replace(/\{class\}/,r).replace(/\{content\}/,e.extract[n]))};e.extract?(h(e,0,""),h(e,1,"line"),h(e,2,""),a+="on line "+e.line+", column "+(e.column+1)+":

    "+"
      "+f.join("")+"
    "):e.stack&&(a+="
    "+e.stack.split("\n").slice(1).join("
    ")),o.innerHTML=a,S([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),o.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),r.env=="development"&&(u=setInterval(function(){document.body&&(document.getElementById(i)?document.body.replaceChild(o,document.getElementById(i)):document.body.insertBefore(o,document.body.firstChild),clearInterval(u))},10))}var r,i,s;typeof environment=="object"&&{}.toString.call(environment)==="[object Environment]"?(typeof e=="undefined"?r={}:r=e.less={},i=r.tree={},r.mode="rhino"):typeof e=="undefined"?(r=exports,i=n("./tree"),r.mode="node"):(typeof e.less=="undefined"&&(e.less={}),r=e.less,i=e.less.tree={},r.mode="browser"),r.Parser=function(t){function m(){a=c[u],f=o,h=o}function g(){c[u]=a,o=f,h=o}function y(){o>h&&(c[u]=c[u].slice(o-h),h=o)}function b(e){var t=e.charCodeAt(0);return t===32||t===10||t===9}function w(e){var t,n,r,i,a;if(e instanceof Function)return e.call(p.parsers);if(typeof e=="string")t=s.charAt(o)===e?e:null,r=1,y();else{y();if(!(t=e.exec(c[u])))return null;r=t[0].length}if(t)return E(r),typeof t=="string"?t:t.length===1?t[0]:t}function E(e){var t=o,n=u,r=o+c[u].length,i=o+=e;while(o=0&&t.charAt(n)!=="\n";n--)r++;return{line:typeof e=="number"?(t.slice(0,e).match(/\n/g)||"").length:null,column:r}}function k(e,t,i){var s=i.currentFileInfo.filename;return r.mode!=="browser"&&r.mode!=="rhino"&&(s=n("path").resolve(s)),{lineNumber:C(e,t).line+1,fileName:s}}function L(e,t){var n=N(e,t),r=C(e.index,n),i=r.line,s=r.column,o=n.split("\n");this.type=e.type||"Syntax",this.message=e.message,this.filename=e.filename||t.currentFileInfo.filename,this.index=e.index,this.line=typeof i=="number"?i+1:null,this.callLine=e.call&&C(e.call,n).line+1,this.callExtract=o[C(e.call,n).line],this.stack=e.stack,this.column=s,this.extract=[o[i-1],o[i],o[i+1]]}var s,o,u,a,f,l,c,h,p,d=this;t instanceof i.parseEnv||(t=new i.parseEnv(t));var v=this.imports={paths:t.paths||[],queue:[],files:t.files,contents:t.contents,mime:t.mime,error:null,push:function(e,n,i){var s=this;this.queue.push(e),r.Parser.importer(e,n,function(t,n,r){s.queue.splice(s.queue.indexOf(e),1);var o=r in s.files;s.files[r]=n,t&&!s.error&&(s.error=t),i(t,n,o)},t)}};return L.prototype=new Error,L.prototype.constructor=L,this.env=t=t||{},this.optimization="optimization"in this.env?this.env.optimization:1,p={imports:v,parse:function(e,a){var f,d,v,m,g,y,b=[],E,S=null;o=u=h=l=0,s=e.replace(/\r\n/g,"\n"),s=s.replace(/^\uFEFF/,""),c=function(e){var n=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,o=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,u=0,a,f=e[0],l;for(var c=0,h,p;c0?"missing closing `}`":"missing opening `{`",filename:t.currentFileInfo.filename},t)),e.map(function(e){return e.join("")})}([[]]);if(S)return a(new L(S,t));try{f=new i.Ruleset([],w(this.parsers.primary)),f.root=!0,f.firstRoot=!0}catch(x){return a(new L(x,t))}f.toCSS=function(e){var s,o,u;return function(s,o){s=s||{};var u,a=new i.evalEnv(s);typeof o=="object"&&!Array.isArray(o)&&(o=Object.keys(o).map(function(e){var t=o[e];return t instanceof i.Value||(t instanceof i.Expression||(t=new i.Expression([t])),t=new i.Value([t])),new i.Rule("@"+e,t,!1,0)}),a.frames=[new i.Ruleset(null,o)]);try{var f=e.call(this,a);(new i.joinSelectorVisitor).run(f),(new i.processExtendsVisitor).run(f);var l=f.toCSS({compress:Boolean(s.compress),dumpLineNumbers:t.dumpLineNumbers,strictUnits:Boolean(s.strictUnits)})}catch(c){throw new L(c,t)}return s.yuicompress&&r.mode==="node"?n("ycssmin").cssmin(l,s.maxLineLen):s.compress?l.replace(/(\s)+/g,"$1"):l}}(f.eval);if(o=0&&s.charAt(T)!=="\n";T--)N++;S={type:"Parse",message:"Unrecognised input",index:o,filename:t.currentFileInfo.filename,line:g,column:N,extract:[y[g-2],y[g-1],y[g]]}}var C=function(e){e=S||e||p.imports.error,e?(e instanceof L||(e=new L(e,t)),a(e)):a(null,f)};t.processImports!==!1?(new i.importVisitor(this.imports,C)).run(f):C()},parsers:{primary:function(){var e,t=[];while((e=w(this.extendRule)||w(this.mixin.definition)||w(this.rule)||w(this.ruleset)||w(this.mixin.call)||w(this.comment)||w(this.directive))||w(/^[\s\n]+/)||w(/^;+/))e&&t.push(e);return t},comment:function(){var e;if(s.charAt(o)!=="/")return;if(s.charAt(o+1)==="/")return new i.Comment(w(/^\/\/.*/),!0);if(e=w(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){var e,n=o,r,u=o;s.charAt(n)==="~"&&(n++,r=!0);if(s.charAt(n)!=='"'&&s.charAt(n)!=="'")return;r&&w("~");if(e=w(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new i.Quoted(e[0],e[1]||e[2],r,u,t.currentFileInfo)},keyword:function(){var e;if(e=w(/^[_A-Za-z-][_A-Za-z0-9-]*/))return i.colors.hasOwnProperty(e)?new i.Color(i.colors[e].slice(1)):new i.Keyword(e)},call:function(){var e,n,r,s,a=o;if(!(e=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(c[u])))return;e=e[1],n=e.toLowerCase();if(n==="url")return null;o+=e.length;if(n==="alpha"){s=w(this.alpha);if(typeof s!="undefined")return s}w("("),r=w(this.entities.arguments);if(!w(")"))return;if(e)return new i.Call(e,r,a,t.currentFileInfo)},arguments:function(){var e=[],t;while(t=w(this.entities.assignment)||w(this.expression)){e.push(t);if(!w(","))break}return e},literal:function(){return w(this.entities.dimension)||w(this.entities.color)||w(this.entities.quoted)||w(this.entities.unicodeDescriptor)},assignment:function(){var e,t;if((e=w(/^\w+(?=\s?=)/i))&&w("=")&&(t=w(this.entity)))return new i.Assignment(e,t)},url:function(){var e;if(s.charAt(o)!=="u"||!w(/^url\(/))return;return e=w(this.entities.quoted)||w(this.entities.variable)||w(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",S(")"),new i.URL(e.value!=null||e instanceof i.Variable?e:new i.Anonymous(e),t.currentFileInfo)},variable:function(){var e,n=o;if(s.charAt(o)==="@"&&(e=w(/^@@?[\w-]+/)))return new i.Variable(e,n,t.currentFileInfo)},variableCurly:function(){var e,n,r=o;if(s.charAt(o)==="@"&&(n=w(/^@\{([\w-]+)\}/)))return new i.Variable("@"+n[1],r,t.currentFileInfo)},color:function(){var e;if(s.charAt(o)==="#"&&(e=w(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/)))return new i.Color(e[1])},dimension:function(){var e,t=s.charCodeAt(o);if(t>57||t<43||t===47||t==44)return;if(e=w(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/))return new i.Dimension(e[1],e[2])},unicodeDescriptor:function(){var e;if(e=w(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/))return new i.UnicodeDescriptor(e[0])},javascript:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=="`")return;n&&w("~");if(e=w(/^`([^`]*)`/))return new i.JavaScript(e[1],o,n)}},variable:function(){var e;if(s.charAt(o)==="@"&&(e=w(/^(@[\w-]+)\s*:/)))return e[1]},extend:function(e){var t,n,r=o,s,u=[];if(!w(e?/^&:extend\(/:/^:extend\(/))return;do{s=null,t=[];for(;;){s=w(/^(all)(?=\s*(\)|,))/);if(s)break;n=w(this.element);if(!n)break;t.push(n)}s=s&&s[1],u.push(new i.Extend(new i.Selector(t),s,r))}while(w(","));return S(/^\)/),e&&S(/^;/),u},extendRule:function(){return this.extend(!0)},mixin:{call:function(){var e=[],n,r,u,a,f,l=o,c=s.charAt(o),h=!1;if(c!=="."&&c!=="#")return;m();while(n=w(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/))e.push(new i.Element(r,n,o)),r=w(">");w("(")&&(u=this.mixin.args.call(this,!0).args,S(")")),u=u||[],w(this.important)&&(h=!0);if(e.length>0&&(w(";")||T("}")))return new i.mixin.Call(e,u,l,t.currentFileInfo,h);g()},args:function(e){var t=[],n=[],r,u=[],a,f,l,c,h,p={args:null,variadic:!1};for(;;){if(e)h=w(this.expression);else{w(this.comment);if(s.charAt(o)==="."&&w(/^\.{3}/)){p.variadic=!0,w(";")&&!r&&(r=!0),(r?n:u).push({variadic:!0});break}h=w(this.entities.variable)||w(this.entities.literal)||w(this.entities.keyword)}if(!h)break;l=null,h.throwAwayComments&&h.throwAwayComments(),c=h;var d=null;if(e){if(h.value.length==1)var d=h.value[0]}else d=h;if(d&&d instanceof i.Variable)if(w(":"))t.length>0&&(r&&x("Cannot mix ; and , as delimiter types"),a=!0),c=S(this.expression),l=f=d.name;else{if(!e&&w(/^\.{3}/)){p.variadic=!0,w(";")&&!r&&(r=!0),(r?n:u).push({name:h.name,variadic:!0});break}e||(f=l=d.name,c=null)}c&&t.push(c),u.push({name:l,value:c});if(w(","))continue;if(w(";")||r)a&&x("Cannot mix ; and , as delimiter types"),r=!0,t.length>1&&(c=new i.Value(t)),n.push({name:f,value:c}),f=null,t=[],a=!1}return p.args=r?n:u,p},definition:function(){var e,t=[],n,r,u,a,f,c=!1;if(s.charAt(o)!=="."&&s.charAt(o)!=="#"||T(/^[^{]*\}/))return;m();if(n=w(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){e=n[1];var h=this.mixin.args.call(this,!1);t=h.args,c=h.variadic,w(")")||(l=o,g()),w(this.comment),w(/^when/)&&(f=S(this.conditions,"expected condition")),r=w(this.block);if(r)return new i.mixin.Definition(e,t,r,f,c);g()}}},entity:function(){return w(this.entities.literal)||w(this.entities.variable)||w(this.entities.url)||w(this.entities.call)||w(this.entities.keyword)||w(this.entities.javascript)||w(this.comment)},end:function(){return w(";")||T("}")},alpha:function(){var e;if(!w(/^\(opacity=/i))return;if(e=w(/^\d+/)||w(this.entities.variable))return S(")"),new i.Alpha(e)},element:function(){var e,t,n,r;n=w(this.combinator),e=w(/^(?:\d+\.\d+|\d+)%/)||w(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||w("*")||w("&")||w(this.attribute)||w(/^\([^()@]+\)/)||w(/^[\.#](?=@)/)||w(this.entities.variableCurly),e||w("(")&&(r=w(this.selector))&&w(")")&&(e=new i.Paren(r));if(e)return new i.Element(n,e,o)},combinator:function(){var e=s.charAt(o);if(e===">"||e==="+"||e==="~"||e==="|"){o++;while(s.charAt(o).match(/\s/))o++;return new i.Combinator(e)}return s.charAt(o-1).match(/\s/)?new i.Combinator(" "):new i.Combinator(null)},selector:function(){var e,t,n=[],r,u,a=[];while((u=w(this.extend))||(t=w(this.element))){u?a.push.apply(a,u):(a.length&&x("Extend can only be used at the end of selector"),r=s.charAt(o),n.push(t),t=null);if(r==="{"||r==="}"||r===";"||r===","||r===")")break}if(n.length>0)return new i.Selector(n,a);a.length&&x("Extend must be used to extend a selector, it cannot be used on its own")},attribute:function(){var e="",t,n,r;if(!w("["))return;(t=w(this.entities.variableCurly))||(t=S(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/));if(r=w(/^[|~*$^]?=/))n=w(this.entities.quoted)||w(/^[\w-]+/)||w(this.entities.variableCurly);return S("]"),new i.Attribute(t,r,n)},block:function(){var e;if(w("{")&&(e=w(this.primary))&&w("}"))return e},ruleset:function(){var e=[],n,r,u;m(),t.dumpLineNumbers&&(u=k(o,s,t));while(n=w(this.selector)){e.push(n),w(this.comment);if(!w(","))break;w(this.comment)}if(e.length>0&&(r=w(this.block))){var a=new i.Ruleset(e,r,t.strictImports);return t.dumpLineNumbers&&(a.debugInfo=u),a}l=o,g()},rule:function(e){var n,r,u=s.charAt(o),a;m();if(u==="."||u==="#"||u==="&")return;if(n=w(this.variable)||w(this.property)){r=!e&&(t.compress||n.charAt(0)==="@")?w(this.value)||w(this.anonymousValue):w(this.anonymousValue)||w(this.value),a=w(this.important);if(r&&w(this.end))return new i.Rule(n,r,a,f,t.currentFileInfo);l=o,g();if(r&&!e)return this.rule(!0)}},anonymousValue:function(){var e;if(e=/^([^@+\/'"*`(;{}-]*);/.exec(c[u]))return o+=e[0].length-1,new i.Anonymous(e[1])},"import":function(){var e,n,r=o;m();var s=w(/^@import?\s+/),u=(s?w(this.importOptions):null)||{};if(s&&(e=w(this.entities.quoted)||w(this.entities.url))){n=w(this.mediaFeatures);if(w(";"))return n=n&&new i.Value(n),new i.Import(e,n,u,r,t.currentFileInfo)}g()},importOptions:function(){var e,t={},n,r;if(!w("("))return null;do if(e=w(this.importOption)){n=e,r=!0;switch(n){case"css":n="less",r=!1;break;case"once":n="multiple",r=!1}t[n]=r;if(!w(","))break}while(e);return S(")"),t},importOption:function(){var e=w(/^(less|css|multiple|once)/);if(e)return e[1]},mediaFeature:function(){var e,n,r=[];do if(e=w(this.entities.keyword))r.push(e);else if(w("(")){n=w(this.property),e=w(this.value);if(!w(")"))return null;if(n&&e)r.push(new i.Paren(new i.Rule(n,e,null,o,t.currentFileInfo,!0)));else{if(!e)return null;r.push(new i.Paren(e))}}while(e);if(r.length>0)return new i.Expression(r)},mediaFeatures:function(){var e,t=[];do if(e=w(this.mediaFeature)){t.push(e);if(!w(","))break}else if(e=w(this.entities.variable)){t.push(e);if(!w(","))break}while(e);return t.length>0?t:null},media:function(){var e,n,r,u;t.dumpLineNumbers&&(u=k(o,s,t));if(w(/^@media/)){e=w(this.mediaFeatures);if(n=w(this.block))return r=new i.Media(n,e),t.dumpLineNumbers&&(r.debugInfo=u),r}},directive:function(){var e,n,r,u,a,f,l,c,h,p;if(s.charAt(o)!=="@")return;if(n=w(this["import"])||w(this.media))return n;m(),e=w(/^@[a-z-]+/);if(!e)return;l=e,e.charAt(1)=="-"&&e.indexOf("-",2)>0&&(l="@"+e.slice(e.indexOf("-",2)+1));switch(l){case"@font-face":c=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":c=!0;break;case"@page":case"@document":case"@supports":case"@keyframes":c=!0,h=!0;break;case"@namespace":p=!0}h&&(e+=" "+(w(/^[^{]+/)||"").trim());if(c){if(r=w(this.block))return new i.Directive(e,r)}else if((n=p?w(this.expression):w(this.entity))&&w(";")){var d=new i.Directive(e,n);return t.dumpLineNumbers&&(d.debugInfo=k(o,s,t)),d}g()},value:function(){var e,t=[],n;while(e=w(this.expression)){t.push(e);if(!w(","))break}if(t.length>0)return new i.Value(t)},important:function(){if(s.charAt(o)==="!")return w(/^! *important/)},sub:function(){var e,t;if(w("("))if(e=w(this.addition))return t=new i.Expression([e]),S(")"),t.parens=!0,t},multiplication:function(){var e,t,n,r,u,a=[];if(e=w(this.operand)){u=b(s.charAt(o-1));while(!T(/^\/[*\/]/)&&(n=w("/")||w("*"))){if(!(t=w(this.operand)))break;e.parensInOp=!0,t.parensInOp=!0,r=new i.Operation(n,[r||e,t],u),u=b(s.charAt(o-1))}return r||e}},addition:function(){var e,t,n,r,u;if(e=w(this.multiplication)){u=b(s.charAt(o-1));while((n=w(/^[-+]\s+/)||!u&&(w("+")||w("-")))&&(t=w(this.multiplication)))e.parensInOp=!0,t.parensInOp=!0,r=new i.Operation(n,[r||e,t],u),u=b(s.charAt(o-1));return r||e}},conditions:function(){var e,t,n=o,r;if(e=w(this.condition)){while(w(",")&&(t=w(this.condition)))r=new i.Condition("or",r||e,t,n);return r||e}},condition:function(){var e,t,n,r,s=o,u=!1;w(/^not/)&&(u=!0),S("(");if(e=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))return(r=w(/^(?:>=|=<|[<=>])/))?(t=w(this.addition)||w(this.entities.keyword)||w(this.entities.quoted))?n=new i.Condition(r,e,t,s,u):x("expected expression"):n=new i.Condition("=",e,new i.Keyword("true"),s,u),S(")"),w(/^and/)?new i.Condition("and",n,w(this.condition)):n},operand:function(){var e,t=s.charAt(o+1);s.charAt(o)==="-"&&(t==="@"||t==="(")&&(e=w("-"));var n=w(this.sub)||w(this.entities.dimension)||w(this.entities.color)||w(this.entities.variable)||w(this.entities.call);return e&&(n.parensInOp=!0,n=new i.Negative(n)),n},expression:function(){var e,t,n=[],r;while(e=w(this.addition)||w(this.entity))n.push(e),!T(/^\/[\/*]/)&&(t=w("/"))&&n.push(new i.Anonymous(t));if(n.length>0)return new i.Expression(n)},property:function(){var e;if(e=w(/^(\*?-?[_a-z0-9-]+)\s*:/))return e[1]}}}};if(r.mode==="browser"||r.mode==="rhino")r.Parser.importer=function(e,t,n,r){!/^([a-z-]+:)?\//.test(e)&&t.currentDirectory&&(e=t.currentDirectory+e);var i=r.toSheet(e);i.processImports=!1,i.currentFileInfo=t,w(i,function(e,t,r,i,s,o){n.call(null,e,t,o)},!0)};(function(r){function u(e){return r.functions.hsla(e.h,e.s,e.l,e.a)}function a(e,t){return e instanceof r.Dimension&&e.unit.is("%")?parseFloat(e.value*t/100):f(e)}function f(e){if(e instanceof r.Dimension)return parseFloat(e.unit.is("%")?e.value/100:e.value);if(typeof e=="number")return e;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function l(e){return Math.min(1,Math.max(0,e))}r.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(e,t,n,i){var s=[e,t,n].map(function(e){return a(e,256)});return i=f(i),new r.Color(s,i)},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,n,r){function o(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?s+(i-s)*e*6:e*2<1?i:e*3<2?s+(i-s)*(2/3-e)*6:s}e=f(e)%360/360,t=l(f(t)),n=l(f(n)),r=l(f(r));var i=n<=.5?n*(t+1):n+t-n*t,s=n*2-i;return this.rgba(o(e+1/3)*255,o(e)*255,o(e-1/3)*255,r)},hsv:function(e,t,n){return this.hsva(e,t,n,1)},hsva:function(e,t,n,r){e=f(e)%360/360*360,t=f(t),n=f(n),r=f(r);var i,s;i=Math.floor(e/60%6),s=e/60-i;var o=[n,n*(1-t),n*(1-s*t),n*(1-(1-s)*t)],u=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return this.rgba(o[u[i][0]]*255,o[u[i][1]]*255,o[u[i][2]]*255,r)},hue:function(e){return new r.Dimension(Math.round(e.toHSL().h))},saturation:function(e){return new r.Dimension(Math.round(e.toHSL().s*100),"%")},lightness:function(e){return new r.Dimension(Math.round(e.toHSL().l*100),"%")},hsvhue:function(e){return new r.Dimension(Math.round(e.toHSV().h))},hsvsaturation:function(e){return new r.Dimension(Math.round(e.toHSV().s*100),"%")},hsvvalue:function(e){return new r.Dimension(Math.round(e.toHSV().v*100),"%")},red:function(e){return new r.Dimension(e.rgb[0])},green:function(e){return new r.Dimension(e.rgb[1])},blue:function(e){return new r.Dimension(e.rgb[2])},alpha:function(e){return new r.Dimension(e.toHSL().a)},luma:function(e){return new r.Dimension(Math.round(e.luma()*e.alpha*100),"%")},saturate:function(e,t){var n=e.toHSL();return n.s+=t.value/100,n.s=l(n.s),u(n)},desaturate:function(e,t){var n=e.toHSL();return n.s-=t.value/100,n.s=l(n.s),u(n)},lighten:function(e,t){var n=e.toHSL();return n.l+=t.value/100,n.l=l(n.l),u(n)},darken:function(e,t){var n=e.toHSL();return n.l-=t.value/100,n.l=l(n.l),u(n)},fadein:function(e,t){var n=e.toHSL();return n.a+=t.value/100,n.a=l(n.a),u(n)},fadeout:function(e,t){var n=e.toHSL();return n.a-=t.value/100,n.a=l(n.a),u(n)},fade:function(e,t){var n=e.toHSL();return n.a=t.value/100,n.a=l(n.a),u(n)},spin:function(e,t){var n=e.toHSL(),r=(n.h+t.value)%360;return n.h=r<0?360+r:r,u(n)},mix:function(e,t,n){n||(n=new r.Dimension(50));var i=n.value/100,s=i*2-1,o=e.toHSL().a-t.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[e.rgb[0]*u+t.rgb[0]*a,e.rgb[1]*u+t.rgb[1]*a,e.rgb[2]*u+t.rgb[2]*a],l=e.alpha*i+t.alpha*(1-i);return new r.Color(f,l)},greyscale:function(e){return this.desaturate(e,new r.Dimension(100))},contrast:function(e,t,n,r){if(!e.rgb)return null;typeof n=="undefined"&&(n=this.rgba(255,255,255,1)),typeof t=="undefined"&&(t=this.rgba(0,0,0,1));if(t.luma()>n.luma()){var i=n;n=t,t=i}return typeof r=="undefined"?r=.43:r=f(r),e.luma()*e.alpha=d){if(this.env.ieCompat!==!1)return this.env.silent||console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!",o,v,d),(new r.URL(i||t,this.currentFileInfo)).eval(this.env);this.env.silent||console.warn("WARNING: Embedding %s (%dKB) exceeds IE8's data-uri size limit of %dKB!",o,v,d)}p=f?p.toString("base64"):encodeURIComponent(p);var m="'data:"+s+","+p+"'";return new r.URL(new r.Anonymous(m))}},r._mime={_types:{".htm":"text/html",".html":"text/html",".gif":"image/gif",".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png"},lookup:function(e){var i=n("path").extname(e),s=r._mime._types[i];if(s===t)throw new Error('Optional dependency "mime" is required for '+i);return s},charsets:{lookup:function(e){return e&&/^text\//.test(e)?"UTF-8":""}}};var i=[{name:"ceil"},{name:"floor"},{name:"sqrt"},{name:"abs"},{name:"tan",unit:""},{name:"sin",unit:""},{name:"cos",unit:""},{name:"atan",unit:"rad"},{name:"asin",unit:"rad"},{name:"acos",unit:"rad"}],s=function(e,t){return function(n){return t!=null&&(n=n.unify()),this._math(Math[e],t,n)}};for(var o=0;o255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("");return n&&(r=r.split(""),r[0]==r[1]&&r[2]==r[3]&&r[4]==r[5]?r=r[0]+r[2]+r[4]:r=r.join("")),"#"+r},operate:function(t,n,r){var i=[];r instanceof e.Color||(r=r.toColor());for(var s=0;s<3;s++)i[s]=e.operate(t,n,this.rgb[s],r.rgb[s]);return new e.Color(i,this.alpha+r.alpha)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t,n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},compare:function(e){return e.rgb?e.rgb[0]===this.rgb[0]&&e.rgb[1]===this.rgb[1]&&e.rgb[2]===this.rgb[2]&&e.alpha===this.alpha?0:-1:-1}}}(n("../tree")),function(e){e.Comment=function(e,t){this.value=e,this.silent=!!t},e.Comment.prototype={type:"Comment",toCSS:function(e){return e.compress?"":this.value},eval:function(){return this}}}(n("../tree")),function(e){e.Condition=function(e,t,n,r,i){this.op=e.trim(),this.lvalue=t,this.rvalue=n,this.index=r,this.negate=i},e.Condition.prototype={type:"Condition",accept:function(e){this.lvalue=e.visit(this.lvalue),this.rvalue=e.visit(this.rvalue)},eval:function(e){var t=this.lvalue.eval(e),n=this.rvalue.eval(e),r=this.index,i,i=function(e){switch(e){case"and":return t&&n;case"or":return t||n;default:if(t.compare)i=t.compare(n);else{if(!n.compare)throw{type:"Type",message:"Unable to perform comparison",index:r};i=n.compare(t)}switch(i){case-1:return e==="<"||e==="=<";case 0:return e==="="||e===">="||e==="=<";case 1:return e===">"||e===">="}}}(this.op);return this.negate?!i:i}}}(n("../tree")),function(e){e.Dimension=function(n,r){this.value=parseFloat(n),this.unit=r&&r instanceof e.Unit?r:new e.Unit(r?[r]:t)},e.Dimension.prototype={type:"Dimension",accept:function(e){this.unit=e.visit(this.unit)},eval:function(e){return this},toColor:function(){return new e.Color([this.value,this.value,this.value])},toCSS:function(e){if(e&&e.strictUnits&&!this.unit.isSingular())throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());var t=this.value,n=String(t);t!==0&&t<1e-6&&t>-0.000001&&(n=t.toFixed(20).replace(/0+$/,""));if(e&&e.compress){if(t===0&&!this.unit.isAngle())return n;t>0&&t<1&&(n=n.substr(1))}return n+this.unit.toCSS(e)},operate:function(t,n,r){var i=e.operate(t,n,this.value,r.value),s=this.unit.clone();if(n==="+"||n==="-"){if(s.numerator.length===0&&s.denominator.length===0)s.numerator=r.unit.numerator.slice(0),s.denominator=r.unit.denominator.slice(0);else if(r.unit.numerator.length!=0||s.denominator.length!=0){r=r.convertTo(this.unit.usedUnits());if(t.strictUnits&&r.unit.toString()!==s.toString())throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '"+s.toString()+"' and '"+r.unit.toString()+"'.");i=e.operate(t,n,this.value,r.value)}}else n==="*"?(s.numerator=s.numerator.concat(r.unit.numerator).sort(),s.denominator=s.denominator.concat(r.unit.denominator).sort(),s.cancel()):n==="/"&&(s.numerator=s.numerator.concat(r.unit.denominator).sort(),s.denominator=s.denominator.concat(r.unit.numerator).sort(),s.cancel());return new e.Dimension(i,s)},compare:function(t){if(t instanceof e.Dimension){var n=this.unify(),r=t.unify(),i=n.value,s=r.value;return s>i?-1:s=1?this.numerator[0]:this.denominator.length>=1?this.denominator[0]:(!e||!e.strictUnits)&&this.backupUnit?this.backupUnit:""},toString:function(){var e,t=this.numerator.join("*");for(e=0;e0)for(n=0;n":e.compress?">":" > ","|":e.compress?"|":" | "}[this.value]}}}(n("../tree")),function(e){e.Expression=function(e){this.value=e},e.Expression.prototype={type:"Expression",accept:function(e){this.value=e.visit(this.value)},eval:function(t){var n,r=this.parens&&!this.parensInOp,i=!1;return r&&t.inParenthesis(),this.value.length>1?n=new e.Expression(this.value.map(function(e){return e.eval(t)})):this.value.length===1?(this.value[0].parens&&!this.value[0].parensInOp&&(i=!0),n=this.value[0].eval(t)):n=this,r&&t.outOfParenthesis(),this.parens&&this.parensInOp&&!t.isMathOn()&&!i&&(n=new e.Paren(n)),n},toCSS:function(e){return this.value.map(function(t){return t.toCSS?t.toCSS(e):""}).join(" ")},throwAwayComments:function(){this.value=this.value.filter(function(t){return!(t instanceof e.Comment)})}}}(n("../tree")),function(e){e.Extend=function(t,n,r){this.selector=t,this.option=n,this.index=r;switch(n){case"all":this.allowBefore=!0,this.allowAfter=!0;break;default:this.allowBefore=!1,this.allowAfter=!1}},e.Extend.prototype={type:"Extend",accept:function(e){this.selector=e.visit(this.selector)},eval:function(t){return new e.Extend(this.selector.eval(t),this.option,this.index)},clone:function(t){return new e.Extend(this.selector,this.option,this.index)},findSelfSelectors:function(e){var t=[],n;for(n=0;n1){var r=this.emptySelectors();n=new e.Ruleset(r,t.mediaBlocks),n.multiMedia=!0}return delete t.mediaBlocks,delete t.mediaPath,n},evalNested:function(t){var n,r,i=t.mediaPath.concat([this]);for(n=0;n0;n--)t.splice(n,0,new e.Anonymous("and"));return new e.Expression(t)})),new e.Ruleset([],[])},permute:function(e){if(e.length===0)return[];if(e.length===1)return e[0];var t=[],n=this.permute(e.slice(1));for(var r=0;r0){c=!0;for(a=0;athis.params.length)return!1;if(this.required>0&&n>this.params.length)return!1}r=Math.min(n,this.arity);for(var s=0;si.selectors[o].elements.length?Array.prototype.push.apply(r,i.find(new e.Selector(t.elements.slice(1)),n)):r.push(i);break}}),this._lookups[o]=r)},toCSS:function(t){var n=[],r=[],i=[],s=[],o,u,a;for(var f=0;f0){u=e.debugInfo(t,this),o=this.paths.map(function(e){return e.map(function(e){return e.toCSS(t)}).join("").trim()}).join(t.compress?",":",\n");for(var f=r.length-1;f>=0;f--)(r[f].slice(0,2)==="/*"||i.indexOf(r[f])===-1)&&i.unshift(r[f]);r=i,n.push(u+o+(t.compress?"{":" {\n ")+r.join(t.compress?"":"\n ")+(t.compress?"}":"\n}\n"))}return n.push(s),n.join("")+(t.compress?"\n":"")},joinSelectors:function(e,t,n){for(var r=0;r0)for(i=0;i0&&this.mergeElementsOnToSelectors(g,a);for(s=0;s0&&(l[0].elements=l[0].elements.slice(0),l[0].elements.push(new e.Element(f.combinator,"",0))),y.push(l);else for(o=0;o0?(h=l.slice(0),m=h.pop(),d=new e.Selector(m.elements.slice(0),r.extendList),v=!1):d=new e.Selector([],r.extendList),c.length>1&&(p=p.concat(c.slice(1))),c.length>0&&(v=!1,d.elements.push(new e.Element(f.combinator,c[0].elements[0].value,0)),d.elements=d.elements.concat(c[0].elements.slice(1))),v||h.push(d),h=h.concat(p),y.push(h)}a=y,g=[]}}g.length>0&&this.mergeElementsOnToSelectors(g,a);for(i=0;i0&&t.push(a[i])},mergeElementsOnToSelectors:function(t,n){var r,i,s;if(n.length==0){n.push([new e.Selector(t)]);return}for(r=0;r0?i[i.length-1]=new e.Selector(i[i.length-1].elements.concat(t),i[i.length-1].extendList):i.push(new e.Selector(t))}}}(n("../tree")),function(e){e.Selector=function(e,t){this.elements=e,this.extendList=t||[]},e.Selector.prototype={type:"Selector",accept:function(e){this.elements=e.visit(this.elements),this.extendList=e.visit(this.extendList)},match:function(e){var t=this.elements,n=t.length,r,i,s,o;r=e.elements.slice(e.elements.length&&e.elements[0].value==="&"?1:0),i=r.length,s=Math.min(n,i);if(i===0||n1?"["+e.value.map(function(e){return e.toCSS(!1)}).join(", ")+"]":e.toCSS(!1)}}(n("./tree")),function(e){var t=["paths","optimization","files","contents","relativeUrls","strictImports","dumpLineNumbers","compress","processImports","syncImport","mime","currentFileInfo"];e.parseEnv=function(e){r(e,this,t),this.contents||(this.contents={}),this.files||(this.files={});if(!this.currentFileInfo){var n=e&&e.filename||"input",i=n.replace(/[^\/\\]*$/,"");e&&(e.filename=null),this.currentFileInfo={filename:n,relativeUrls:this.relativeUrls,rootpath:e&&e.rootpath||"",currentDirectory:i,entryPath:i,rootFilename:n}}},e.parseEnv.prototype.toSheet=function(t){var n=new e.parseEnv(this);return n.href=t,n.type=this.mime,n};var n=["silent","verbose","compress","yuicompress","ieCompat","strictMath","strictUnits"];e.evalEnv=function(e,t){r(e,this,n),this.frames=t||[]},e.evalEnv.prototype.inParenthesis=function(){this.parensStack||(this.parensStack=[]),this.parensStack.push(!0)},e.evalEnv.prototype.outOfParenthesis=function(){this.parensStack.pop()},e.evalEnv.prototype.isMathOn=function(){return this.strictMath?this.parensStack&&this.parensStack.length:!0},e.evalEnv.prototype.isPathRelative=function(e){return!/^(?:[a-z-]+:|\/)/.test(e)};var r=function(e,t,n){if(!e)return;for(var r=0;r100){var d="{unable to calculate}",v="{unable to calculate}";try{d=u[0].selfSelectors[0].toCSS(),v=u[0].selector.toCSS()}catch(m){}throw{message:"extend circular reference detected. One of the circular extends is currently:"+d+":extend("+v+")"}}return u.concat(f.doExtendChaining(u,n,r+1))}return u},inInheritanceChain:function(e,t){if(e===t)return!0;if(t.parents){if(this.inInheritanceChain(e,t.parents[0]))return!0;if(this.inInheritanceChain(e,t.parents[1]))return!0}return!1},visitRule:function(e,t){t.visitDeeper=!1},visitMixinDefinition:function(e,t){t.visitDeeper=!1},visitSelector:function(e,t){t.visitDeeper=!1},visitRuleset:function(e,t){if(e.root)return;var n,r,i,s=this.allExtendsStack[this.allExtendsStack.length-1],o=[],u=this,a;for(i=0;i0&&f[c.matched].combinator.value!==o?c=null:c.matched++,c&&(c.finished=c.matched===f.length,c.finished&&!e.allowAfter&&(i+1i&&s>0&&(o[o.length-1].elements=o[o.length-1].elements.concat(n[i].elements.slice(s)),s=0,i++),o=o.concat(n.slice(i,l.pathIndex)),o.push(new e.Selector(a.elements.slice(s,l.index).concat([f]).concat(r.elements.slice(1)))),i=l.endPathIndex,s=l.endPathElementIndex,s>=a.elements.length&&(s=0,i++);return i0&&(o[o.length-1].elements=o[o.length-1].elements.concat(n[i].elements.slice(s)),s=0,i++),o=o.concat(n.slice(i,n.length)),o},visitRulesetOut:function(e){},visitMedia:function(e,t){var n=e.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);n=n.concat(this.doExtendChaining(n,e.allExtends)),this.allExtendsStack.push(n)},visitMediaOut:function(e){this.allExtendsStack.length=this.allExtendsStack.length-1},visitDirective:function(e,t){var n=e.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);n=n.concat(this.doExtendChaining(n,e.allExtends)),this.allExtendsStack.push(n)},visitDirectiveOut:function(e){this.allExtendsStack.length=this.allExtendsStack.length-1}}}(n("./tree"));var o=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);r.env=r.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||o?"development":"production"),r.async=r.async||!1,r.fileAsync=r.fileAsync||!1,r.poll=r.poll||(o?1e3:1500);if(r.functions)for(var u in r.functions)r.tree.functions[u]=r.functions[u];var a=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);a&&(r.dumpLineNumbers=a[1]),r.watch=function(){return r.watchMode||(r.env="development",f()),this.watchMode=!0},r.unwatch=function(){return clearInterval(r.watchTimer),this.watchMode=!1},/!watch/.test(location.hash)&&r.watch();var l=null;if(r.env!="development")try{l=typeof e.localStorage=="undefined"?null:e.localStorage}catch(c){}var h=document.getElementsByTagName("link"),p=/^text\/(x-)?less$/;r.sheets=[];for(var d=0;d .select2-chosen { - margin-right: 26px; - display: block; - overflow: hidden; - - white-space: nowrap; - - text-overflow: ellipsis; -} - -.select2-container .select2-choice abbr { - display: none; - width: 12px; - height: 12px; - position: absolute; - right: 24px; - top: 8px; - - font-size: 1px; - text-decoration: none; - - border: 0; - background: url('select2.png') right top no-repeat; - cursor: pointer; - outline: 0; -} - -.select2-container.select2-allowclear .select2-choice abbr { - display: inline-block; -} - -.select2-container .select2-choice abbr:hover { - background-position: right -11px; - cursor: pointer; -} - -.select2-drop-mask { - border: 0; - margin: 0; - padding: 0; - position: fixed; - left: 0; - top: 0; - min-height: 100%; - min-width: 100%; - height: auto; - width: auto; - opacity: 0; - z-index: 9998; - /* styles required for IE to work */ - background-color: #fff; - filter: alpha(opacity=0); -} - -.select2-drop { - width: 100%; - margin-top: -1px; - position: absolute; - z-index: 9999; - top: 100%; - - background: #fff; - color: #000; - border: 1px solid #aaa; - border-top: 0; - - border-radius: 0 0 4px 4px; - - -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15); - box-shadow: 0 4px 5px rgba(0, 0, 0, .15); -} - -.select2-drop-auto-width { - border-top: 1px solid #aaa; - width: auto; -} - -.select2-drop-auto-width .select2-search { - padding-top: 4px; -} - -.select2-drop.select2-drop-above { - margin-top: 1px; - border-top: 1px solid #aaa; - border-bottom: 0; - - border-radius: 4px 4px 0 0; - - -webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15); - box-shadow: 0 -4px 5px rgba(0, 0, 0, .15); -} - -.select2-drop-active { - border: 1px solid #5897fb; - border-top: none; -} - -.select2-drop.select2-drop-above.select2-drop-active { - border-top: 1px solid #5897fb; -} - -.select2-container .select2-choice .select2-arrow { - display: inline-block; - width: 18px; - height: 100%; - position: absolute; - right: 0; - top: 0; - - border-left: 1px solid #aaa; - border-radius: 0 4px 4px 0; - - background-clip: padding-box; - - background: #ccc; - background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee)); - background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%); - background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#cccccc', GradientType = 0); - background-image: linear-gradient(top, #ccc 0%, #eee 60%); -} - -.select2-container .select2-choice .select2-arrow b { - display: block; - width: 100%; - height: 100%; - background: url('select2.png') no-repeat 0 1px; -} - -.select2-search { - display: inline-block; - width: 100%; - min-height: 26px; - margin: 0; - padding-left: 4px; - padding-right: 4px; - - position: relative; - z-index: 10000; - - white-space: nowrap; -} - -.select2-search input { - width: 100%; - height: auto !important; - min-height: 26px; - padding: 4px 20px 4px 5px; - margin: 0; - - outline: 0; - font-family: sans-serif; - font-size: 1em; - - border: 1px solid #aaa; - border-radius: 0; - - -webkit-box-shadow: none; - box-shadow: none; - - background: #fff url('select2.png') no-repeat 100% -22px; - background: url('select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee)); - background: url('select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%); - background: url('select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%); - background: url('select2.png') no-repeat 100% -22px, linear-gradient(top, #fff 85%, #eee 99%); -} - -.select2-drop.select2-drop-above .select2-search input { - margin-top: 4px; -} - -.select2-search input.select2-active { - background: #fff url('select2-spinner.gif') no-repeat 100%; - background: url('select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee)); - background: url('select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%); - background: url('select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%); - background: url('select2-spinner.gif') no-repeat 100%, linear-gradient(top, #fff 85%, #eee 99%); -} - -.select2-container-active .select2-choice, -.select2-container-active .select2-choices { - border: 1px solid #5897fb; - outline: none; - - -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3); - box-shadow: 0 0 5px rgba(0, 0, 0, .3); -} - -.select2-dropdown-open .select2-choice { - border-bottom-color: transparent; - -webkit-box-shadow: 0 1px 0 #fff inset; - box-shadow: 0 1px 0 #fff inset; - - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - - background-color: #eee; - background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #fff), color-stop(0.5, #eee)); - background-image: -webkit-linear-gradient(center bottom, #fff 0%, #eee 50%); - background-image: -moz-linear-gradient(center bottom, #fff 0%, #eee 50%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0); - background-image: linear-gradient(top, #fff 0%, #eee 50%); -} - -.select2-dropdown-open.select2-drop-above .select2-choice, -.select2-dropdown-open.select2-drop-above .select2-choices { - border: 1px solid #5897fb; - border-top-color: transparent; - - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(0.5, #eee)); - background-image: -webkit-linear-gradient(center top, #fff 0%, #eee 50%); - background-image: -moz-linear-gradient(center top, #fff 0%, #eee 50%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0); - background-image: linear-gradient(bottom, #fff 0%, #eee 50%); -} - -.select2-dropdown-open .select2-choice .select2-arrow { - background: transparent; - border-left: none; - filter: none; -} -.select2-dropdown-open .select2-choice .select2-arrow b { - background-position: -18px 1px; -} - -/* results */ -.select2-results { - max-height: 200px; - padding: 0 0 0 4px; - margin: 4px 4px 4px 0; - position: relative; - overflow-x: hidden; - overflow-y: auto; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} - -.select2-results ul.select2-result-sub { - margin: 0; - padding-left: 0; -} - -.select2-results ul.select2-result-sub > li .select2-result-label { padding-left: 20px } -.select2-results ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 40px } -.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 60px } -.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 80px } -.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 100px } -.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 110px } -.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 120px } - -.select2-results li { - list-style: none; - display: list-item; - background-image: none; -} - -.select2-results li.select2-result-with-children > .select2-result-label { - font-weight: bold; -} - -.select2-results .select2-result-label { - padding: 3px 7px 4px; - margin: 0; - cursor: pointer; - - min-height: 1em; - - -webkit-touch-callout: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.select2-results .select2-highlighted { - background: #3875d7; - color: #fff; -} - -.select2-results li em { - background: #feffde; - font-style: normal; -} - -.select2-results .select2-highlighted em { - background: transparent; -} - -.select2-results .select2-highlighted ul { - background: #fff; - color: #000; -} - - -.select2-results .select2-no-results, -.select2-results .select2-searching, -.select2-results .select2-selection-limit { - background: #f4f4f4; - display: list-item; -} - -/* -disabled look for disabled choices in the results dropdown -*/ -.select2-results .select2-disabled.select2-highlighted { - color: #666; - background: #f4f4f4; - display: list-item; - cursor: default; -} -.select2-results .select2-disabled { - background: #f4f4f4; - display: list-item; - cursor: default; -} - -.select2-results .select2-selected { - display: none; -} - -.select2-more-results.select2-active { - background: #f4f4f4 url('select2-spinner.gif') no-repeat 100%; -} - -.select2-more-results { - background: #f4f4f4; - display: list-item; -} - -/* disabled styles */ - -.select2-container.select2-container-disabled .select2-choice { - background-color: #f4f4f4; - background-image: none; - border: 1px solid #ddd; - cursor: default; -} - -.select2-container.select2-container-disabled .select2-choice .select2-arrow { - background-color: #f4f4f4; - background-image: none; - border-left: 0; -} - -.select2-container.select2-container-disabled .select2-choice abbr { - display: none; -} - - -/* multiselect */ - -.select2-container-multi .select2-choices { - height: auto !important; - height: 1%; - margin: 0; - padding: 0; - position: relative; - - border: 1px solid #aaa; - cursor: text; - overflow: hidden; - - background-color: #fff; - background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eee), color-stop(15%, #fff)); - background-image: -webkit-linear-gradient(top, #eee 1%, #fff 15%); - background-image: -moz-linear-gradient(top, #eee 1%, #fff 15%); - background-image: linear-gradient(top, #eee 1%, #fff 15%); -} - -.select2-locked { - padding: 3px 5px 3px 5px !important; -} - -.select2-container-multi .select2-choices { - min-height: 26px; -} - -.select2-container-multi.select2-container-active .select2-choices { - border: 1px solid #5897fb; - outline: none; - - -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3); - box-shadow: 0 0 5px rgba(0, 0, 0, .3); -} -.select2-container-multi .select2-choices li { - float: left; - list-style: none; -} -.select2-container-multi .select2-choices .select2-search-field { - margin: 0; - padding: 0; - white-space: nowrap; -} - -.select2-container-multi .select2-choices .select2-search-field input { - padding: 5px; - margin: 1px 0; - - font-family: sans-serif; - font-size: 100%; - color: #666; - outline: 0; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - background: transparent !important; -} - -.select2-container-multi .select2-choices .select2-search-field input.select2-active { - background: #fff url('select2-spinner.gif') no-repeat 100% !important; -} - -.select2-default { - color: #999 !important; -} - -.select2-container-multi .select2-choices .select2-search-choice { - padding: 3px 5px 3px 18px; - margin: 3px 0 3px 5px; - position: relative; - - line-height: 13px; - color: #333; - cursor: default; - border: 1px solid #aaaaaa; - - border-radius: 3px; - - -webkit-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05); - box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05); - - background-clip: padding-box; - - -webkit-touch-callout: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - - background-color: #e4e4e4; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#f4f4f4', GradientType=0); - background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eee)); - background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); - background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); - background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); -} -.select2-container-multi .select2-choices .select2-search-choice .select2-chosen { - cursor: default; -} -.select2-container-multi .select2-choices .select2-search-choice-focus { - background: #d4d4d4; -} - -.select2-search-choice-close { - display: block; - width: 12px; - height: 13px; - position: absolute; - right: 3px; - top: 4px; - - font-size: 1px; - outline: none; - background: url('select2.png') right top no-repeat; -} - -.select2-container-multi .select2-search-choice-close { - left: 3px; -} - -.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover { - background-position: right -11px; -} -.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close { - background-position: right -11px; -} - -/* disabled styles */ -.select2-container-multi.select2-container-disabled .select2-choices { - background-color: #f4f4f4; - background-image: none; - border: 1px solid #ddd; - cursor: default; -} - -.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice { - padding: 3px 5px 3px 5px; - border: 1px solid #ddd; - background-image: none; - background-color: #f4f4f4; -} - -.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close { display: none; - background: none; -} -/* end multiselect */ - - -.select2-result-selectable .select2-match, -.select2-result-unselectable .select2-match { - text-decoration: underline; -} - -.select2-offscreen, .select2-offscreen:focus { - clip: rect(0 0 0 0) !important; - width: 1px !important; - height: 1px !important; - border: 0 !important; - margin: 0 !important; - padding: 0 !important; - overflow: hidden !important; - position: absolute !important; - outline: 0 !important; - left: 0px !important; - top: 0px !important; -} - -.select2-display-none { - display: none; -} - -.select2-measure-scrollbar { - position: absolute; - top: -10000px; - left: -10000px; - width: 100px; - height: 100px; - overflow: scroll; -} -/* Retina-ize icons */ - -@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi) { - .select2-search input, .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice .select2-arrow b { - background-image: url('select2x2.png') !important; - background-repeat: no-repeat !important; - background-size: 60px 40px !important; - } - .select2-search input { - background-position: 100% -21px !important; - } -} diff --git a/oscar_support/static/oscar_support/lib/select2/select2.min.js b/oscar_support/static/oscar_support/lib/select2/select2.min.js deleted file mode 100644 index 0910fdf..0000000 --- a/oscar_support/static/oscar_support/lib/select2/select2.min.js +++ /dev/null @@ -1,22 +0,0 @@ -/* -Copyright 2012 Igor Vaynberg - -Version: 3.4.3 Timestamp: Tue Sep 17 06:47:14 PDT 2013 - -This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU -General Public License version 2 (the "GPL License"). You may choose either license to govern your -use of this software only upon the condition that you accept all of the terms of either the Apache -License or the GPL License. - -You may obtain a copy of the Apache License and the GPL License at: - -http://www.apache.org/licenses/LICENSE-2.0 -http://www.gnu.org/licenses/gpl-2.0.html - -Unless required by applicable law or agreed to in writing, software distributed under the Apache License -or the GPL Licesnse is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, -either express or implied. See the Apache License and the GPL License for the specific language governing -permissions and limitations under the Apache License and the GPL License. -*/ -!function(a){"undefined"==typeof a.fn.each2&&a.extend(a.fn,{each2:function(b){for(var c=a([0]),d=-1,e=this.length;++dc;c++)e=a.charAt(c),b+=m[e]||e;return b}function o(a,b){for(var c=0,d=b.length;d>c;c+=1)if(q(a,b[c]))return c;return-1}function p(){var b=a(l);b.appendTo("body");var c={width:b.width()-b[0].clientWidth,height:b.height()-b[0].clientHeight};return b.remove(),c}function q(a,c){return a===c?!0:a===b||c===b?!1:null===a||null===c?!1:a.constructor===String?a+""==c+"":c.constructor===String?c+""==a+"":!1}function r(b,c){var d,e,f;if(null===b||b.length<1)return[];for(d=b.split(c),e=0,f=d.length;f>e;e+=1)d[e]=a.trim(d[e]);return d}function s(a){return a.outerWidth(!1)-a.width()}function t(c){var d="keyup-change-value";c.on("keydown",function(){a.data(c,d)===b&&a.data(c,d,c.val())}),c.on("keyup",function(){var e=a.data(c,d);e!==b&&c.val()!==e&&(a.removeData(c,d),c.trigger("keyup-change"))})}function u(c){c.on("mousemove",function(c){var d=i;(d===b||d.x!==c.pageX||d.y!==c.pageY)&&a(c.target).trigger("mousemove-filtered",c)})}function v(a,c,d){d=d||b;var e;return function(){var b=arguments;window.clearTimeout(e),e=window.setTimeout(function(){c.apply(d,b)},a)}}function w(a){var c,b=!1;return function(){return b===!1&&(c=a(),b=!0),c}}function x(a,b){var c=v(a,function(a){b.trigger("scroll-debounced",a)});b.on("scroll",function(a){o(a.target,b.get())>=0&&c(a)})}function y(a){a[0]!==document.activeElement&&window.setTimeout(function(){var d,b=a[0],c=a.val().length;a.focus(),a.is(":visible")&&b===document.activeElement&&(b.setSelectionRange?b.setSelectionRange(c,c):b.createTextRange&&(d=b.createTextRange(),d.collapse(!1),d.select()))},0)}function z(b){b=a(b)[0];var c=0,d=0;if("selectionStart"in b)c=b.selectionStart,d=b.selectionEnd-c;else if("selection"in document){b.focus();var e=document.selection.createRange();d=document.selection.createRange().text.length,e.moveStart("character",-b.value.length),c=e.text.length-d}return{offset:c,length:d}}function A(a){a.preventDefault(),a.stopPropagation()}function B(a){a.preventDefault(),a.stopImmediatePropagation()}function C(b){if(!h){var c=b[0].currentStyle||window.getComputedStyle(b[0],null);h=a(document.createElement("div")).css({position:"absolute",left:"-10000px",top:"-10000px",display:"none",fontSize:c.fontSize,fontFamily:c.fontFamily,fontStyle:c.fontStyle,fontWeight:c.fontWeight,letterSpacing:c.letterSpacing,textTransform:c.textTransform,whiteSpace:"nowrap"}),h.attr("class","select2-sizer"),a("body").append(h)}return h.text(b.val()),h.width()}function D(b,c,d){var e,g,f=[];e=b.attr("class"),e&&(e=""+e,a(e.split(" ")).each2(function(){0===this.indexOf("select2-")&&f.push(this)})),e=c.attr("class"),e&&(e=""+e,a(e.split(" ")).each2(function(){0!==this.indexOf("select2-")&&(g=d(this),g&&f.push(this))})),b.attr("class",f.join(" "))}function E(a,b,c,d){var e=n(a.toUpperCase()).indexOf(n(b.toUpperCase())),f=b.length;return 0>e?(c.push(d(a)),void 0):(c.push(d(a.substring(0,e))),c.push(""),c.push(d(a.substring(e,e+f))),c.push(""),c.push(d(a.substring(e+f,a.length))),void 0)}function F(a){var b={"\\":"\","&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};return String(a).replace(/[&<>"'\/\\]/g,function(a){return b[a]})}function G(c){var d,e=null,f=c.quietMillis||100,g=c.url,h=this;return function(i){window.clearTimeout(d),d=window.setTimeout(function(){var d=c.data,f=g,j=c.transport||a.fn.select2.ajaxDefaults.transport,k={type:c.type||"GET",cache:c.cache||!1,jsonpCallback:c.jsonpCallback||b,dataType:c.dataType||"json"},l=a.extend({},a.fn.select2.ajaxDefaults.params,k);d=d?d.call(h,i.term,i.page,i.context):null,f="function"==typeof f?f.call(h,i.term,i.page,i.context):f,e&&e.abort(),c.params&&(a.isFunction(c.params)?a.extend(l,c.params.call(h)):a.extend(l,c.params)),a.extend(l,{url:f,dataType:c.dataType,data:d,success:function(a){var b=c.results(a,i.page);i.callback(b)}}),e=j.call(h,l)},f)}}function H(b){var d,e,c=b,f=function(a){return""+a.text};a.isArray(c)&&(e=c,c={results:e}),a.isFunction(c)===!1&&(e=c,c=function(){return e});var g=c();return g.text&&(f=g.text,a.isFunction(f)||(d=g.text,f=function(a){return a[d]})),function(b){var g,d=b.term,e={results:[]};return""===d?(b.callback(c()),void 0):(g=function(c,e){var h,i;if(c=c[0],c.children){h={};for(i in c)c.hasOwnProperty(i)&&(h[i]=c[i]);h.children=[],a(c.children).each2(function(a,b){g(b,h.children)}),(h.children.length||b.matcher(d,f(h),c))&&e.push(h)}else b.matcher(d,f(c),c)&&e.push(c)},a(c().results).each2(function(a,b){g(b,e.results)}),b.callback(e),void 0)}}function I(c){var d=a.isFunction(c);return function(e){var f=e.term,g={results:[]};a(d?c():c).each(function(){var a=this.text!==b,c=a?this.text:this;(""===f||e.matcher(f,c))&&g.results.push(a?this:{id:this,text:this})}),e.callback(g)}}function J(b,c){if(a.isFunction(b))return!0;if(!b)return!1;throw new Error(c+" must be a function or a falsy value")}function K(b){return a.isFunction(b)?b():b}function L(b){var c=0;return a.each(b,function(a,b){b.children?c+=L(b.children):c++}),c}function M(a,c,d,e){var h,i,j,k,l,f=a,g=!1;if(!e.createSearchChoice||!e.tokenSeparators||e.tokenSeparators.length<1)return b;for(;;){for(i=-1,j=0,k=e.tokenSeparators.length;k>j&&(l=e.tokenSeparators[j],i=a.indexOf(l),!(i>=0));j++);if(0>i)break;if(h=a.substring(0,i),a=a.substring(i+l.length),h.length>0&&(h=e.createSearchChoice.call(this,h,c),h!==b&&null!==h&&e.id(h)!==b&&null!==e.id(h))){for(g=!1,j=0,k=c.length;k>j;j++)if(q(e.id(h),e.id(c[j]))){g=!0;break}g||d(h)}}return f!==a?a:void 0}function N(b,c){var d=function(){};return d.prototype=new b,d.prototype.constructor=d,d.prototype.parent=b.prototype,d.prototype=a.extend(d.prototype,c),d}if(window.Select2===b){var c,d,e,f,g,h,j,k,i={x:0,y:0},c={TAB:9,ENTER:13,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,SHIFT:16,CTRL:17,ALT:18,PAGE_UP:33,PAGE_DOWN:34,HOME:36,END:35,BACKSPACE:8,DELETE:46,isArrow:function(a){switch(a=a.which?a.which:a){case c.LEFT:case c.RIGHT:case c.UP:case c.DOWN:return!0}return!1},isControl:function(a){var b=a.which;switch(b){case c.SHIFT:case c.CTRL:case c.ALT:return!0}return a.metaKey?!0:!1},isFunctionKey:function(a){return a=a.which?a.which:a,a>=112&&123>=a}},l="
    ",m={"\u24b6":"A","\uff21":"A","\xc0":"A","\xc1":"A","\xc2":"A","\u1ea6":"A","\u1ea4":"A","\u1eaa":"A","\u1ea8":"A","\xc3":"A","\u0100":"A","\u0102":"A","\u1eb0":"A","\u1eae":"A","\u1eb4":"A","\u1eb2":"A","\u0226":"A","\u01e0":"A","\xc4":"A","\u01de":"A","\u1ea2":"A","\xc5":"A","\u01fa":"A","\u01cd":"A","\u0200":"A","\u0202":"A","\u1ea0":"A","\u1eac":"A","\u1eb6":"A","\u1e00":"A","\u0104":"A","\u023a":"A","\u2c6f":"A","\ua732":"AA","\xc6":"AE","\u01fc":"AE","\u01e2":"AE","\ua734":"AO","\ua736":"AU","\ua738":"AV","\ua73a":"AV","\ua73c":"AY","\u24b7":"B","\uff22":"B","\u1e02":"B","\u1e04":"B","\u1e06":"B","\u0243":"B","\u0182":"B","\u0181":"B","\u24b8":"C","\uff23":"C","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\xc7":"C","\u1e08":"C","\u0187":"C","\u023b":"C","\ua73e":"C","\u24b9":"D","\uff24":"D","\u1e0a":"D","\u010e":"D","\u1e0c":"D","\u1e10":"D","\u1e12":"D","\u1e0e":"D","\u0110":"D","\u018b":"D","\u018a":"D","\u0189":"D","\ua779":"D","\u01f1":"DZ","\u01c4":"DZ","\u01f2":"Dz","\u01c5":"Dz","\u24ba":"E","\uff25":"E","\xc8":"E","\xc9":"E","\xca":"E","\u1ec0":"E","\u1ebe":"E","\u1ec4":"E","\u1ec2":"E","\u1ebc":"E","\u0112":"E","\u1e14":"E","\u1e16":"E","\u0114":"E","\u0116":"E","\xcb":"E","\u1eba":"E","\u011a":"E","\u0204":"E","\u0206":"E","\u1eb8":"E","\u1ec6":"E","\u0228":"E","\u1e1c":"E","\u0118":"E","\u1e18":"E","\u1e1a":"E","\u0190":"E","\u018e":"E","\u24bb":"F","\uff26":"F","\u1e1e":"F","\u0191":"F","\ua77b":"F","\u24bc":"G","\uff27":"G","\u01f4":"G","\u011c":"G","\u1e20":"G","\u011e":"G","\u0120":"G","\u01e6":"G","\u0122":"G","\u01e4":"G","\u0193":"G","\ua7a0":"G","\ua77d":"G","\ua77e":"G","\u24bd":"H","\uff28":"H","\u0124":"H","\u1e22":"H","\u1e26":"H","\u021e":"H","\u1e24":"H","\u1e28":"H","\u1e2a":"H","\u0126":"H","\u2c67":"H","\u2c75":"H","\ua78d":"H","\u24be":"I","\uff29":"I","\xcc":"I","\xcd":"I","\xce":"I","\u0128":"I","\u012a":"I","\u012c":"I","\u0130":"I","\xcf":"I","\u1e2e":"I","\u1ec8":"I","\u01cf":"I","\u0208":"I","\u020a":"I","\u1eca":"I","\u012e":"I","\u1e2c":"I","\u0197":"I","\u24bf":"J","\uff2a":"J","\u0134":"J","\u0248":"J","\u24c0":"K","\uff2b":"K","\u1e30":"K","\u01e8":"K","\u1e32":"K","\u0136":"K","\u1e34":"K","\u0198":"K","\u2c69":"K","\ua740":"K","\ua742":"K","\ua744":"K","\ua7a2":"K","\u24c1":"L","\uff2c":"L","\u013f":"L","\u0139":"L","\u013d":"L","\u1e36":"L","\u1e38":"L","\u013b":"L","\u1e3c":"L","\u1e3a":"L","\u0141":"L","\u023d":"L","\u2c62":"L","\u2c60":"L","\ua748":"L","\ua746":"L","\ua780":"L","\u01c7":"LJ","\u01c8":"Lj","\u24c2":"M","\uff2d":"M","\u1e3e":"M","\u1e40":"M","\u1e42":"M","\u2c6e":"M","\u019c":"M","\u24c3":"N","\uff2e":"N","\u01f8":"N","\u0143":"N","\xd1":"N","\u1e44":"N","\u0147":"N","\u1e46":"N","\u0145":"N","\u1e4a":"N","\u1e48":"N","\u0220":"N","\u019d":"N","\ua790":"N","\ua7a4":"N","\u01ca":"NJ","\u01cb":"Nj","\u24c4":"O","\uff2f":"O","\xd2":"O","\xd3":"O","\xd4":"O","\u1ed2":"O","\u1ed0":"O","\u1ed6":"O","\u1ed4":"O","\xd5":"O","\u1e4c":"O","\u022c":"O","\u1e4e":"O","\u014c":"O","\u1e50":"O","\u1e52":"O","\u014e":"O","\u022e":"O","\u0230":"O","\xd6":"O","\u022a":"O","\u1ece":"O","\u0150":"O","\u01d1":"O","\u020c":"O","\u020e":"O","\u01a0":"O","\u1edc":"O","\u1eda":"O","\u1ee0":"O","\u1ede":"O","\u1ee2":"O","\u1ecc":"O","\u1ed8":"O","\u01ea":"O","\u01ec":"O","\xd8":"O","\u01fe":"O","\u0186":"O","\u019f":"O","\ua74a":"O","\ua74c":"O","\u01a2":"OI","\ua74e":"OO","\u0222":"OU","\u24c5":"P","\uff30":"P","\u1e54":"P","\u1e56":"P","\u01a4":"P","\u2c63":"P","\ua750":"P","\ua752":"P","\ua754":"P","\u24c6":"Q","\uff31":"Q","\ua756":"Q","\ua758":"Q","\u024a":"Q","\u24c7":"R","\uff32":"R","\u0154":"R","\u1e58":"R","\u0158":"R","\u0210":"R","\u0212":"R","\u1e5a":"R","\u1e5c":"R","\u0156":"R","\u1e5e":"R","\u024c":"R","\u2c64":"R","\ua75a":"R","\ua7a6":"R","\ua782":"R","\u24c8":"S","\uff33":"S","\u1e9e":"S","\u015a":"S","\u1e64":"S","\u015c":"S","\u1e60":"S","\u0160":"S","\u1e66":"S","\u1e62":"S","\u1e68":"S","\u0218":"S","\u015e":"S","\u2c7e":"S","\ua7a8":"S","\ua784":"S","\u24c9":"T","\uff34":"T","\u1e6a":"T","\u0164":"T","\u1e6c":"T","\u021a":"T","\u0162":"T","\u1e70":"T","\u1e6e":"T","\u0166":"T","\u01ac":"T","\u01ae":"T","\u023e":"T","\ua786":"T","\ua728":"TZ","\u24ca":"U","\uff35":"U","\xd9":"U","\xda":"U","\xdb":"U","\u0168":"U","\u1e78":"U","\u016a":"U","\u1e7a":"U","\u016c":"U","\xdc":"U","\u01db":"U","\u01d7":"U","\u01d5":"U","\u01d9":"U","\u1ee6":"U","\u016e":"U","\u0170":"U","\u01d3":"U","\u0214":"U","\u0216":"U","\u01af":"U","\u1eea":"U","\u1ee8":"U","\u1eee":"U","\u1eec":"U","\u1ef0":"U","\u1ee4":"U","\u1e72":"U","\u0172":"U","\u1e76":"U","\u1e74":"U","\u0244":"U","\u24cb":"V","\uff36":"V","\u1e7c":"V","\u1e7e":"V","\u01b2":"V","\ua75e":"V","\u0245":"V","\ua760":"VY","\u24cc":"W","\uff37":"W","\u1e80":"W","\u1e82":"W","\u0174":"W","\u1e86":"W","\u1e84":"W","\u1e88":"W","\u2c72":"W","\u24cd":"X","\uff38":"X","\u1e8a":"X","\u1e8c":"X","\u24ce":"Y","\uff39":"Y","\u1ef2":"Y","\xdd":"Y","\u0176":"Y","\u1ef8":"Y","\u0232":"Y","\u1e8e":"Y","\u0178":"Y","\u1ef6":"Y","\u1ef4":"Y","\u01b3":"Y","\u024e":"Y","\u1efe":"Y","\u24cf":"Z","\uff3a":"Z","\u0179":"Z","\u1e90":"Z","\u017b":"Z","\u017d":"Z","\u1e92":"Z","\u1e94":"Z","\u01b5":"Z","\u0224":"Z","\u2c7f":"Z","\u2c6b":"Z","\ua762":"Z","\u24d0":"a","\uff41":"a","\u1e9a":"a","\xe0":"a","\xe1":"a","\xe2":"a","\u1ea7":"a","\u1ea5":"a","\u1eab":"a","\u1ea9":"a","\xe3":"a","\u0101":"a","\u0103":"a","\u1eb1":"a","\u1eaf":"a","\u1eb5":"a","\u1eb3":"a","\u0227":"a","\u01e1":"a","\xe4":"a","\u01df":"a","\u1ea3":"a","\xe5":"a","\u01fb":"a","\u01ce":"a","\u0201":"a","\u0203":"a","\u1ea1":"a","\u1ead":"a","\u1eb7":"a","\u1e01":"a","\u0105":"a","\u2c65":"a","\u0250":"a","\ua733":"aa","\xe6":"ae","\u01fd":"ae","\u01e3":"ae","\ua735":"ao","\ua737":"au","\ua739":"av","\ua73b":"av","\ua73d":"ay","\u24d1":"b","\uff42":"b","\u1e03":"b","\u1e05":"b","\u1e07":"b","\u0180":"b","\u0183":"b","\u0253":"b","\u24d2":"c","\uff43":"c","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\xe7":"c","\u1e09":"c","\u0188":"c","\u023c":"c","\ua73f":"c","\u2184":"c","\u24d3":"d","\uff44":"d","\u1e0b":"d","\u010f":"d","\u1e0d":"d","\u1e11":"d","\u1e13":"d","\u1e0f":"d","\u0111":"d","\u018c":"d","\u0256":"d","\u0257":"d","\ua77a":"d","\u01f3":"dz","\u01c6":"dz","\u24d4":"e","\uff45":"e","\xe8":"e","\xe9":"e","\xea":"e","\u1ec1":"e","\u1ebf":"e","\u1ec5":"e","\u1ec3":"e","\u1ebd":"e","\u0113":"e","\u1e15":"e","\u1e17":"e","\u0115":"e","\u0117":"e","\xeb":"e","\u1ebb":"e","\u011b":"e","\u0205":"e","\u0207":"e","\u1eb9":"e","\u1ec7":"e","\u0229":"e","\u1e1d":"e","\u0119":"e","\u1e19":"e","\u1e1b":"e","\u0247":"e","\u025b":"e","\u01dd":"e","\u24d5":"f","\uff46":"f","\u1e1f":"f","\u0192":"f","\ua77c":"f","\u24d6":"g","\uff47":"g","\u01f5":"g","\u011d":"g","\u1e21":"g","\u011f":"g","\u0121":"g","\u01e7":"g","\u0123":"g","\u01e5":"g","\u0260":"g","\ua7a1":"g","\u1d79":"g","\ua77f":"g","\u24d7":"h","\uff48":"h","\u0125":"h","\u1e23":"h","\u1e27":"h","\u021f":"h","\u1e25":"h","\u1e29":"h","\u1e2b":"h","\u1e96":"h","\u0127":"h","\u2c68":"h","\u2c76":"h","\u0265":"h","\u0195":"hv","\u24d8":"i","\uff49":"i","\xec":"i","\xed":"i","\xee":"i","\u0129":"i","\u012b":"i","\u012d":"i","\xef":"i","\u1e2f":"i","\u1ec9":"i","\u01d0":"i","\u0209":"i","\u020b":"i","\u1ecb":"i","\u012f":"i","\u1e2d":"i","\u0268":"i","\u0131":"i","\u24d9":"j","\uff4a":"j","\u0135":"j","\u01f0":"j","\u0249":"j","\u24da":"k","\uff4b":"k","\u1e31":"k","\u01e9":"k","\u1e33":"k","\u0137":"k","\u1e35":"k","\u0199":"k","\u2c6a":"k","\ua741":"k","\ua743":"k","\ua745":"k","\ua7a3":"k","\u24db":"l","\uff4c":"l","\u0140":"l","\u013a":"l","\u013e":"l","\u1e37":"l","\u1e39":"l","\u013c":"l","\u1e3d":"l","\u1e3b":"l","\u017f":"l","\u0142":"l","\u019a":"l","\u026b":"l","\u2c61":"l","\ua749":"l","\ua781":"l","\ua747":"l","\u01c9":"lj","\u24dc":"m","\uff4d":"m","\u1e3f":"m","\u1e41":"m","\u1e43":"m","\u0271":"m","\u026f":"m","\u24dd":"n","\uff4e":"n","\u01f9":"n","\u0144":"n","\xf1":"n","\u1e45":"n","\u0148":"n","\u1e47":"n","\u0146":"n","\u1e4b":"n","\u1e49":"n","\u019e":"n","\u0272":"n","\u0149":"n","\ua791":"n","\ua7a5":"n","\u01cc":"nj","\u24de":"o","\uff4f":"o","\xf2":"o","\xf3":"o","\xf4":"o","\u1ed3":"o","\u1ed1":"o","\u1ed7":"o","\u1ed5":"o","\xf5":"o","\u1e4d":"o","\u022d":"o","\u1e4f":"o","\u014d":"o","\u1e51":"o","\u1e53":"o","\u014f":"o","\u022f":"o","\u0231":"o","\xf6":"o","\u022b":"o","\u1ecf":"o","\u0151":"o","\u01d2":"o","\u020d":"o","\u020f":"o","\u01a1":"o","\u1edd":"o","\u1edb":"o","\u1ee1":"o","\u1edf":"o","\u1ee3":"o","\u1ecd":"o","\u1ed9":"o","\u01eb":"o","\u01ed":"o","\xf8":"o","\u01ff":"o","\u0254":"o","\ua74b":"o","\ua74d":"o","\u0275":"o","\u01a3":"oi","\u0223":"ou","\ua74f":"oo","\u24df":"p","\uff50":"p","\u1e55":"p","\u1e57":"p","\u01a5":"p","\u1d7d":"p","\ua751":"p","\ua753":"p","\ua755":"p","\u24e0":"q","\uff51":"q","\u024b":"q","\ua757":"q","\ua759":"q","\u24e1":"r","\uff52":"r","\u0155":"r","\u1e59":"r","\u0159":"r","\u0211":"r","\u0213":"r","\u1e5b":"r","\u1e5d":"r","\u0157":"r","\u1e5f":"r","\u024d":"r","\u027d":"r","\ua75b":"r","\ua7a7":"r","\ua783":"r","\u24e2":"s","\uff53":"s","\xdf":"s","\u015b":"s","\u1e65":"s","\u015d":"s","\u1e61":"s","\u0161":"s","\u1e67":"s","\u1e63":"s","\u1e69":"s","\u0219":"s","\u015f":"s","\u023f":"s","\ua7a9":"s","\ua785":"s","\u1e9b":"s","\u24e3":"t","\uff54":"t","\u1e6b":"t","\u1e97":"t","\u0165":"t","\u1e6d":"t","\u021b":"t","\u0163":"t","\u1e71":"t","\u1e6f":"t","\u0167":"t","\u01ad":"t","\u0288":"t","\u2c66":"t","\ua787":"t","\ua729":"tz","\u24e4":"u","\uff55":"u","\xf9":"u","\xfa":"u","\xfb":"u","\u0169":"u","\u1e79":"u","\u016b":"u","\u1e7b":"u","\u016d":"u","\xfc":"u","\u01dc":"u","\u01d8":"u","\u01d6":"u","\u01da":"u","\u1ee7":"u","\u016f":"u","\u0171":"u","\u01d4":"u","\u0215":"u","\u0217":"u","\u01b0":"u","\u1eeb":"u","\u1ee9":"u","\u1eef":"u","\u1eed":"u","\u1ef1":"u","\u1ee5":"u","\u1e73":"u","\u0173":"u","\u1e77":"u","\u1e75":"u","\u0289":"u","\u24e5":"v","\uff56":"v","\u1e7d":"v","\u1e7f":"v","\u028b":"v","\ua75f":"v","\u028c":"v","\ua761":"vy","\u24e6":"w","\uff57":"w","\u1e81":"w","\u1e83":"w","\u0175":"w","\u1e87":"w","\u1e85":"w","\u1e98":"w","\u1e89":"w","\u2c73":"w","\u24e7":"x","\uff58":"x","\u1e8b":"x","\u1e8d":"x","\u24e8":"y","\uff59":"y","\u1ef3":"y","\xfd":"y","\u0177":"y","\u1ef9":"y","\u0233":"y","\u1e8f":"y","\xff":"y","\u1ef7":"y","\u1e99":"y","\u1ef5":"y","\u01b4":"y","\u024f":"y","\u1eff":"y","\u24e9":"z","\uff5a":"z","\u017a":"z","\u1e91":"z","\u017c":"z","\u017e":"z","\u1e93":"z","\u1e95":"z","\u01b6":"z","\u0225":"z","\u0240":"z","\u2c6c":"z","\ua763":"z"};j=a(document),g=function(){var a=1;return function(){return a++}}(),j.on("mousemove",function(a){i.x=a.pageX,i.y=a.pageY}),d=N(Object,{bind:function(a){var b=this;return function(){a.apply(b,arguments)}},init:function(c){var d,e,h,i,f=".select2-results";this.opts=c=this.prepareOpts(c),this.id=c.id,c.element.data("select2")!==b&&null!==c.element.data("select2")&&c.element.data("select2").destroy(),this.container=this.createContainer(),this.containerId="s2id_"+(c.element.attr("id")||"autogen"+g()),this.containerSelector="#"+this.containerId.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g,"\\$1"),this.container.attr("id",this.containerId),this.body=w(function(){return c.element.closest("body")}),D(this.container,this.opts.element,this.opts.adaptContainerCssClass),this.container.attr("style",c.element.attr("style")),this.container.css(K(c.containerCss)),this.container.addClass(K(c.containerCssClass)),this.elementTabIndex=this.opts.element.attr("tabindex"),this.opts.element.data("select2",this).attr("tabindex","-1").before(this.container).on("click.select2",A),this.container.data("select2",this),this.dropdown=this.container.find(".select2-drop"),D(this.dropdown,this.opts.element,this.opts.adaptDropdownCssClass),this.dropdown.addClass(K(c.dropdownCssClass)),this.dropdown.data("select2",this),this.dropdown.on("click",A),this.results=d=this.container.find(f),this.search=e=this.container.find("input.select2-input"),this.queryCount=0,this.resultsPage=0,this.context=null,this.initContainer(),this.container.on("click",A),u(this.results),this.dropdown.on("mousemove-filtered touchstart touchmove touchend",f,this.bind(this.highlightUnderEvent)),x(80,this.results),this.dropdown.on("scroll-debounced",f,this.bind(this.loadMoreIfNeeded)),a(this.container).on("change",".select2-input",function(a){a.stopPropagation()}),a(this.dropdown).on("change",".select2-input",function(a){a.stopPropagation()}),a.fn.mousewheel&&d.mousewheel(function(a,b,c,e){var f=d.scrollTop();e>0&&0>=f-e?(d.scrollTop(0),A(a)):0>e&&d.get(0).scrollHeight-d.scrollTop()+e<=d.height()&&(d.scrollTop(d.get(0).scrollHeight-d.height()),A(a))}),t(e),e.on("keyup-change input paste",this.bind(this.updateResults)),e.on("focus",function(){e.addClass("select2-focused")}),e.on("blur",function(){e.removeClass("select2-focused")}),this.dropdown.on("mouseup",f,this.bind(function(b){a(b.target).closest(".select2-result-selectable").length>0&&(this.highlightUnderEvent(b),this.selectHighlighted(b))})),this.dropdown.on("click mouseup mousedown",function(a){a.stopPropagation()}),a.isFunction(this.opts.initSelection)&&(this.initSelection(),this.monitorSource()),null!==c.maximumInputLength&&this.search.attr("maxlength",c.maximumInputLength);var h=c.element.prop("disabled");h===b&&(h=!1),this.enable(!h);var i=c.element.prop("readonly");i===b&&(i=!1),this.readonly(i),k=k||p(),this.autofocus=c.element.prop("autofocus"),c.element.prop("autofocus",!1),this.autofocus&&this.focus(),this.nextSearchTerm=b},destroy:function(){var a=this.opts.element,c=a.data("select2");this.close(),this.propertyObserver&&(delete this.propertyObserver,this.propertyObserver=null),c!==b&&(c.container.remove(),c.dropdown.remove(),a.removeClass("select2-offscreen").removeData("select2").off(".select2").prop("autofocus",this.autofocus||!1),this.elementTabIndex?a.attr({tabindex:this.elementTabIndex}):a.removeAttr("tabindex"),a.show())},optionToData:function(a){return a.is("option")?{id:a.prop("value"),text:a.text(),element:a.get(),css:a.attr("class"),disabled:a.prop("disabled"),locked:q(a.attr("locked"),"locked")||q(a.data("locked"),!0)}:a.is("optgroup")?{text:a.attr("label"),children:[],element:a.get(),css:a.attr("class")}:void 0},prepareOpts:function(c){var d,e,f,g,h=this;if(d=c.element,"select"===d.get(0).tagName.toLowerCase()&&(this.select=e=c.element),e&&a.each(["id","multiple","ajax","query","createSearchChoice","initSelection","data","tags"],function(){if(this in c)throw new Error("Option '"+this+"' is not allowed for Select2 when attached to a ","
    "," ","
      ","
    ","
    "].join(""));return b},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.focusser.prop("disabled",!this.isInterfaceEnabled())},opening:function(){var c,d,e;this.opts.minimumResultsForSearch>=0&&this.showSearch(!0),this.parent.opening.apply(this,arguments),this.showSearchInput!==!1&&this.search.val(this.focusser.val()),this.search.focus(),c=this.search.get(0),c.createTextRange?(d=c.createTextRange(),d.collapse(!1),d.select()):c.setSelectionRange&&(e=this.search.val().length,c.setSelectionRange(e,e)),""===this.search.val()&&this.nextSearchTerm!=b&&(this.search.val(this.nextSearchTerm),this.search.select()),this.focusser.prop("disabled",!0).val(""),this.updateResults(!0),this.opts.element.trigger(a.Event("select2-open"))},close:function(a){this.opened()&&(this.parent.close.apply(this,arguments),a=a||{focus:!0},this.focusser.removeAttr("disabled"),a.focus&&this.focusser.focus())},focus:function(){this.opened()?this.close():(this.focusser.removeAttr("disabled"),this.focusser.focus())},isFocused:function(){return this.container.hasClass("select2-container-active")},cancel:function(){this.parent.cancel.apply(this,arguments),this.focusser.removeAttr("disabled"),this.focusser.focus()},destroy:function(){a("label[for='"+this.focusser.attr("id")+"']").attr("for",this.opts.element.attr("id")),this.parent.destroy.apply(this,arguments)},initContainer:function(){var b,d=this.container,e=this.dropdown;this.opts.minimumResultsForSearch<0?this.showSearch(!1):this.showSearch(!0),this.selection=b=d.find(".select2-choice"),this.focusser=d.find(".select2-focusser"),this.focusser.attr("id","s2id_autogen"+g()),a("label[for='"+this.opts.element.attr("id")+"']").attr("for",this.focusser.attr("id")),this.focusser.attr("tabindex",this.elementTabIndex),this.search.on("keydown",this.bind(function(a){if(this.isInterfaceEnabled()){if(a.which===c.PAGE_UP||a.which===c.PAGE_DOWN)return A(a),void 0;switch(a.which){case c.UP:case c.DOWN:return this.moveHighlight(a.which===c.UP?-1:1),A(a),void 0;case c.ENTER:return this.selectHighlighted(),A(a),void 0;case c.TAB:return this.selectHighlighted({noFocus:!0}),void 0;case c.ESC:return this.cancel(a),A(a),void 0}}})),this.search.on("blur",this.bind(function(){document.activeElement===this.body().get(0)&&window.setTimeout(this.bind(function(){this.search.focus()}),0)})),this.focusser.on("keydown",this.bind(function(a){if(this.isInterfaceEnabled()&&a.which!==c.TAB&&!c.isControl(a)&&!c.isFunctionKey(a)&&a.which!==c.ESC){if(this.opts.openOnEnter===!1&&a.which===c.ENTER)return A(a),void 0;if(a.which==c.DOWN||a.which==c.UP||a.which==c.ENTER&&this.opts.openOnEnter){if(a.altKey||a.ctrlKey||a.shiftKey||a.metaKey)return;return this.open(),A(a),void 0}return a.which==c.DELETE||a.which==c.BACKSPACE?(this.opts.allowClear&&this.clear(),A(a),void 0):void 0}})),t(this.focusser),this.focusser.on("keyup-change input",this.bind(function(a){if(this.opts.minimumResultsForSearch>=0){if(a.stopPropagation(),this.opened())return;this.open()}})),b.on("mousedown","abbr",this.bind(function(a){this.isInterfaceEnabled()&&(this.clear(),B(a),this.close(),this.selection.focus())})),b.on("mousedown",this.bind(function(b){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.opened()?this.close():this.isInterfaceEnabled()&&this.open(),A(b)})),e.on("mousedown",this.bind(function(){this.search.focus()})),b.on("focus",this.bind(function(a){A(a)})),this.focusser.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active")})).on("blur",this.bind(function(){this.opened()||(this.container.removeClass("select2-container-active"),this.opts.element.trigger(a.Event("select2-blur")))})),this.search.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active")})),this.initContainerWidth(),this.opts.element.addClass("select2-offscreen"),this.setPlaceholder()},clear:function(b){var c=this.selection.data("select2-data");if(c){var d=a.Event("select2-clearing");if(this.opts.element.trigger(d),d.isDefaultPrevented())return;var e=this.getPlaceholderOption();this.opts.element.val(e?e.val():""),this.selection.find(".select2-chosen").empty(),this.selection.removeData("select2-data"),this.setPlaceholder(),b!==!1&&(this.opts.element.trigger({type:"select2-removed",val:this.id(c),choice:c}),this.triggerChange({removed:c}))}},initSelection:function(){if(this.isPlaceholderOptionSelected())this.updateSelection(null),this.close(),this.setPlaceholder();else{var c=this;this.opts.initSelection.call(null,this.opts.element,function(a){a!==b&&null!==a&&(c.updateSelection(a),c.close(),c.setPlaceholder())})}},isPlaceholderOptionSelected:function(){var a;return this.getPlaceholder()?(a=this.getPlaceholderOption())!==b&&a.is(":selected")||""===this.opts.element.val()||this.opts.element.val()===b||null===this.opts.element.val():!1},prepareOpts:function(){var b=this.parent.prepareOpts.apply(this,arguments),c=this;return"select"===b.element.get(0).tagName.toLowerCase()?b.initSelection=function(a,b){var d=a.find(":selected");b(c.optionToData(d))}:"data"in b&&(b.initSelection=b.initSelection||function(c,d){var e=c.val(),f=null;b.query({matcher:function(a,c,d){var g=q(e,b.id(d));return g&&(f=d),g},callback:a.isFunction(d)?function(){d(f)}:a.noop})}),b},getPlaceholder:function(){return this.select&&this.getPlaceholderOption()===b?b:this.parent.getPlaceholder.apply(this,arguments)},setPlaceholder:function(){var a=this.getPlaceholder();if(this.isPlaceholderOptionSelected()&&a!==b){if(this.select&&this.getPlaceholderOption()===b)return;this.selection.find(".select2-chosen").html(this.opts.escapeMarkup(a)),this.selection.addClass("select2-default"),this.container.removeClass("select2-allowclear")}},postprocessResults:function(a,b,c){var d=0,e=this;if(this.findHighlightableChoices().each2(function(a,b){return q(e.id(b.data("select2-data")),e.opts.element.val())?(d=a,!1):void 0}),c!==!1&&(b===!0&&d>=0?this.highlight(d):this.highlight(0)),b===!0){var g=this.opts.minimumResultsForSearch;g>=0&&this.showSearch(L(a.results)>=g)}},showSearch:function(b){this.showSearchInput!==b&&(this.showSearchInput=b,this.dropdown.find(".select2-search").toggleClass("select2-search-hidden",!b),this.dropdown.find(".select2-search").toggleClass("select2-offscreen",!b),a(this.dropdown,this.container).toggleClass("select2-with-searchbox",b))},onSelect:function(a,b){if(this.triggerSelect(a)){var c=this.opts.element.val(),d=this.data();this.opts.element.val(this.id(a)),this.updateSelection(a),this.opts.element.trigger({type:"select2-selected",val:this.id(a),choice:a}),this.nextSearchTerm=this.opts.nextSearchTerm(a,this.search.val()),this.close(),b&&b.noFocus||this.focusser.focus(),q(c,this.id(a))||this.triggerChange({added:a,removed:d})}},updateSelection:function(a){var d,e,c=this.selection.find(".select2-chosen");this.selection.data("select2-data",a),c.empty(),null!==a&&(d=this.opts.formatSelection(a,c,this.opts.escapeMarkup)),d!==b&&c.append(d),e=this.opts.formatSelectionCssClass(a,c),e!==b&&c.addClass(e),this.selection.removeClass("select2-default"),this.opts.allowClear&&this.getPlaceholder()!==b&&this.container.addClass("select2-allowclear")},val:function(){var a,c=!1,d=null,e=this,f=this.data();if(0===arguments.length)return this.opts.element.val();if(a=arguments[0],arguments.length>1&&(c=arguments[1]),this.select)this.select.val(a).find(":selected").each2(function(a,b){return d=e.optionToData(b),!1}),this.updateSelection(d),this.setPlaceholder(),c&&this.triggerChange({added:d,removed:f});else{if(!a&&0!==a)return this.clear(c),void 0;if(this.opts.initSelection===b)throw new Error("cannot call val() if initSelection() is not defined");this.opts.element.val(a),this.opts.initSelection(this.opts.element,function(a){e.opts.element.val(a?e.id(a):""),e.updateSelection(a),e.setPlaceholder(),c&&e.triggerChange({added:a,removed:f})})}},clearSearch:function(){this.search.val(""),this.focusser.val("")},data:function(a){var c,d=!1;return 0===arguments.length?(c=this.selection.data("select2-data"),c==b&&(c=null),c):(arguments.length>1&&(d=arguments[1]),a?(c=this.data(),this.opts.element.val(a?this.id(a):""),this.updateSelection(a),d&&this.triggerChange({added:a,removed:c})):this.clear(d),void 0)}}),f=N(d,{createContainer:function(){var b=a(document.createElement("div")).attr({"class":"select2-container select2-container-multi"}).html(["
      ","
    • "," ","
    • ","
    ","
    ","
      ","
    ","
    "].join(""));return b},prepareOpts:function(){var b=this.parent.prepareOpts.apply(this,arguments),c=this;return"select"===b.element.get(0).tagName.toLowerCase()?b.initSelection=function(a,b){var d=[];a.find(":selected").each2(function(a,b){d.push(c.optionToData(b))}),b(d)}:"data"in b&&(b.initSelection=b.initSelection||function(c,d){var e=r(c.val(),b.separator),f=[];b.query({matcher:function(c,d,g){var h=a.grep(e,function(a){return q(a,b.id(g))}).length;return h&&f.push(g),h},callback:a.isFunction(d)?function(){for(var a=[],c=0;c0||(this.selectChoice(null),this.clearPlaceholder(),this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.open(),this.focusSearch(),b.preventDefault()))})),this.container.on("focus",b,this.bind(function(){this.isInterfaceEnabled()&&(this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"),this.clearPlaceholder())})),this.initContainerWidth(),this.opts.element.addClass("select2-offscreen"),this.clearSearch()},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.search.prop("disabled",!this.isInterfaceEnabled())},initSelection:function(){if(""===this.opts.element.val()&&""===this.opts.element.text()&&(this.updateSelection([]),this.close(),this.clearSearch()),this.select||""!==this.opts.element.val()){var c=this;this.opts.initSelection.call(null,this.opts.element,function(a){a!==b&&null!==a&&(c.updateSelection(a),c.close(),c.clearSearch())})}},clearSearch:function(){var a=this.getPlaceholder(),c=this.getMaxSearchWidth();a!==b&&0===this.getVal().length&&this.search.hasClass("select2-focused")===!1?(this.search.val(a).addClass("select2-default"),this.search.width(c>0?c:this.container.css("width"))):this.search.val("").width(10)},clearPlaceholder:function(){this.search.hasClass("select2-default")&&this.search.val("").removeClass("select2-default")},opening:function(){this.clearPlaceholder(),this.resizeSearch(),this.parent.opening.apply(this,arguments),this.focusSearch(),this.updateResults(!0),this.search.focus(),this.opts.element.trigger(a.Event("select2-open"))},close:function(){this.opened()&&this.parent.close.apply(this,arguments)},focus:function(){this.close(),this.search.focus()},isFocused:function(){return this.search.hasClass("select2-focused")},updateSelection:function(b){var c=[],d=[],e=this;a(b).each(function(){o(e.id(this),c)<0&&(c.push(e.id(this)),d.push(this))}),b=d,this.selection.find(".select2-search-choice").remove(),a(b).each(function(){e.addSelectedChoice(this)}),e.postprocessResults()},tokenize:function(){var a=this.search.val();a=this.opts.tokenizer.call(this,a,this.data(),this.bind(this.onSelect),this.opts),null!=a&&a!=b&&(this.search.val(a),a.length>0&&this.open())},onSelect:function(a,b){this.triggerSelect(a)&&(this.addSelectedChoice(a),this.opts.element.trigger({type:"selected",val:this.id(a),choice:a}),(this.select||!this.opts.closeOnSelect)&&this.postprocessResults(a,!1,this.opts.closeOnSelect===!0),this.opts.closeOnSelect?(this.close(),this.search.width(10)):this.countSelectableResults()>0?(this.search.width(10),this.resizeSearch(),this.getMaximumSelectionSize()>0&&this.val().length>=this.getMaximumSelectionSize()&&this.updateResults(!0),this.positionDropdown()):(this.close(),this.search.width(10)),this.triggerChange({added:a}),b&&b.noFocus||this.focusSearch())},cancel:function(){this.close(),this.focusSearch()},addSelectedChoice:function(c){var j,k,d=!c.locked,e=a("
  • "),f=a("
  • "),g=d?e:f,h=this.id(c),i=this.getVal();j=this.opts.formatSelection(c,g.find("div"),this.opts.escapeMarkup),j!=b&&g.find("div").replaceWith("
    "+j+"
    "),k=this.opts.formatSelectionCssClass(c,g.find("div")),k!=b&&g.addClass(k),d&&g.find(".select2-search-choice-close").on("mousedown",A).on("click dblclick",this.bind(function(b){this.isInterfaceEnabled()&&(a(b.target).closest(".select2-search-choice").fadeOut("fast",this.bind(function(){this.unselect(a(b.target)),this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"),this.close(),this.focusSearch()})).dequeue(),A(b))})).on("focus",this.bind(function(){this.isInterfaceEnabled()&&(this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"))})),g.data("select2-data",c),g.insertBefore(this.searchContainer),i.push(h),this.setVal(i)},unselect:function(a){var c,d,b=this.getVal();if(a=a.closest(".select2-search-choice"),0===a.length)throw"Invalid argument: "+a+". Must be .select2-search-choice";if(c=a.data("select2-data")){for(;(d=o(this.id(c),b))>=0;)b.splice(d,1),this.setVal(b),this.select&&this.postprocessResults();a.remove(),this.opts.element.trigger({type:"removed",val:this.id(c),choice:c}),this.triggerChange({removed:c})}},postprocessResults:function(a,b,c){var d=this.getVal(),e=this.results.find(".select2-result"),f=this.results.find(".select2-result-with-children"),g=this;e.each2(function(a,b){var c=g.id(b.data("select2-data"));o(c,d)>=0&&(b.addClass("select2-selected"),b.find(".select2-result-selectable").addClass("select2-selected"))}),f.each2(function(a,b){b.is(".select2-result-selectable")||0!==b.find(".select2-result-selectable:not(.select2-selected)").length||b.addClass("select2-selected")}),-1==this.highlight()&&c!==!1&&g.highlight(0),!this.opts.createSearchChoice&&!e.filter(".select2-result:not(.select2-selected)").length>0&&(!a||a&&!a.more&&0===this.results.find(".select2-no-results").length)&&J(g.opts.formatNoMatches,"formatNoMatches")&&this.results.append("
  • "+g.opts.formatNoMatches(g.search.val())+"
  • ")},getMaxSearchWidth:function(){return this.selection.width()-s(this.search)},resizeSearch:function(){var a,b,c,d,e,f=s(this.search);a=C(this.search)+10,b=this.search.offset().left,c=this.selection.width(),d=this.selection.offset().left,e=c-(b-d)-f,a>e&&(e=c-f),40>e&&(e=c-f),0>=e&&(e=a),this.search.width(Math.floor(e))},getVal:function(){var a;return this.select?(a=this.select.val(),null===a?[]:a):(a=this.opts.element.val(),r(a,this.opts.separator))},setVal:function(b){var c;this.select?this.select.val(b):(c=[],a(b).each(function(){o(this,c)<0&&c.push(this)}),this.opts.element.val(0===c.length?"":c.join(this.opts.separator)))},buildChangeDetails:function(a,b){for(var b=b.slice(0),a=a.slice(0),c=0;c. Attach to instead.");this.search.width(0),this.searchContainer.hide()},onSortEnd:function(){var b=[],c=this;this.searchContainer.show(),this.searchContainer.appendTo(this.searchContainer.parent()),this.resizeSearch(),this.selection.find(".select2-search-choice").each(function(){b.push(c.opts.id(a(this).data("select2-data")))}),this.setVal(b),this.triggerChange()},data:function(b,c){var e,f,d=this;return 0===arguments.length?this.selection.find(".select2-search-choice").map(function(){return a(this).data("select2-data")}).get():(f=this.data(),b||(b=[]),e=a.map(b,function(a){return d.opts.id(a)}),this.setVal(e),this.updateSelection(b),this.clearSearch(),c&&this.triggerChange(this.buildChangeDetails(f,this.data())),void 0)}}),a.fn.select2=function(){var d,g,h,i,j,c=Array.prototype.slice.call(arguments,0),k=["val","destroy","opened","open","close","focus","isFocused","container","dropdown","onSortStart","onSortEnd","enable","disable","readonly","positionDropdown","data","search"],l=["opened","isFocused","container","dropdown"],m=["val","data"],n={search:"externalSearch"};return this.each(function(){if(0===c.length||"object"==typeof c[0])d=0===c.length?{}:a.extend({},c[0]),d.element=a(this),"select"===d.element.get(0).tagName.toLowerCase()?j=d.element.prop("multiple"):(j=d.multiple||!1,"tags"in d&&(d.multiple=j=!0)),g=j?new f:new e,g.init(d);else{if("string"!=typeof c[0])throw"Invalid arguments to select2 plugin: "+c;if(o(c[0],k)<0)throw"Unknown method: "+c[0];if(i=b,g=a(this).data("select2"),g===b)return;if(h=c[0],"container"===h?i=g.container:"dropdown"===h?i=g.dropdown:(n[h]&&(h=n[h]),i=g[h].apply(g,c.slice(1))),o(c[0],l)>=0||o(c[0],m)&&1==c.length)return!1}}),i===b?this:i},a.fn.select2.defaults={width:"copy",loadMorePadding:0,closeOnSelect:!0,openOnEnter:!0,containerCss:{},dropdownCss:{},containerCssClass:"",dropdownCssClass:"",formatResult:function(a,b,c,d){var e=[];return E(a.text,c.term,e,d),e.join("")},formatSelection:function(a,c,d){return a?d(a.text):b},sortResults:function(a){return a},formatResultCssClass:function(){return b},formatSelectionCssClass:function(){return b},formatNoMatches:function(){return"No matches found"},formatInputTooShort:function(a,b){var c=b-a.length;return"Please enter "+c+" more character"+(1==c?"":"s")},formatInputTooLong:function(a,b){var c=a.length-b;return"Please delete "+c+" character"+(1==c?"":"s")},formatSelectionTooBig:function(a){return"You can only select "+a+" item"+(1==a?"":"s")},formatLoadMore:function(){return"Loading more results..."},formatSearching:function(){return"Searching..."},minimumResultsForSearch:0,minimumInputLength:0,maximumInputLength:null,maximumSelectionSize:0,id:function(a){return a.id},matcher:function(a,b){return n(""+b).toUpperCase().indexOf(n(""+a).toUpperCase())>=0},separator:",",tokenSeparators:[],tokenizer:M,escapeMarkup:F,blurOnChange:!1,selectOnBlur:!1,adaptContainerCssClass:function(a){return a},adaptDropdownCssClass:function(){return null},nextSearchTerm:function(){return b}},a.fn.select2.ajaxDefaults={transport:a.ajax,params:{type:"GET",cache:!1,dataType:"json"}},window.Select2={query:{ajax:G,local:H,tags:I},util:{debounce:v,markMatch:E,escapeMarkup:F,stripDiacritics:n},"class":{"abstract":d,single:e,multi:f}}}}(jQuery); \ No newline at end of file diff --git a/oscar_support/static/oscar_support/lib/select2/select2.png b/oscar_support/static/oscar_support/lib/select2/select2.png deleted file mode 100644 index 1d804ff..0000000 Binary files a/oscar_support/static/oscar_support/lib/select2/select2.png and /dev/null differ diff --git a/oscar_support/static/oscar_support/lib/select2/select2x2.png b/oscar_support/static/oscar_support/lib/select2/select2x2.png deleted file mode 100644 index 4bdd5c9..0000000 Binary files a/oscar_support/static/oscar_support/lib/select2/select2x2.png and /dev/null differ diff --git a/oscar_support/templates/oscar_support/customer/partials/ticket_table.html b/oscar_support/templates/oscar_support/customer/partials/ticket_table.html index cb8a204..f10bd15 100644 --- a/oscar_support/templates/oscar_support/customer/partials/ticket_table.html +++ b/oscar_support/templates/oscar_support/customer/partials/ticket_table.html @@ -1,5 +1,4 @@ {% load i18n %} -{% load url from future %} {% if ticket_list|length %} @@ -19,7 +18,7 @@ {% endfor %} diff --git a/oscar_support/templates/oscar_support/customer/ticket_create.html b/oscar_support/templates/oscar_support/customer/ticket_create.html index c63548b..c0706bb 100644 --- a/oscar_support/templates/oscar_support/customer/ticket_create.html +++ b/oscar_support/templates/oscar_support/customer/ticket_create.html @@ -1,46 +1,40 @@ -{% extends "oscar/customer/profile/profile.html" %} - +{% extends "customer/baseaccountpage.html" %} {% load i18n %} -{% load url from future %} - -{% block title %} -{% trans 'Create new ticket' %} | {{ block.super }} -{% endblock %} -{% block body_class %}account-pages{% endblock %} - -{% block breadcrumbs %} - {% endblock %} -{% block headertext %}{% trans 'Create new ticket' %}{% endblock headertext %} - -{% block content %} - - {% csrf_token %} - - {% include "partials/form_fields.html" %} - -
    - - {% trans "or" %} - {% trans "cancel" %} -
    - -{% endblock content %} +{% block tabcontent %} + + {% csrf_token %} + + {% include "partials/form_fields.html" %} + + {% block ticket_attachment %} +
    + {% block ticket_attachment_content %} +
    {{ ticket.date_updated|date:"jS M Y H:i" }} {{ ticket.assignee.get_full_name|default:"-" }} - {% trans "Update" %} + {% trans "Update" %}
    + {{ attachment_formset.management_form }} + {{ attachment_formset.non_form_errors }} + {% for attachment_form in attachment_formset %} + + + + {% endfor %} +
    + {% include "dashboard/partials/form_fields_inline.html" with form=attachment_form %} +
    + {% endblock ticket_attachment_content %} + + {% endblock ticket_attachment %} + +
    + + {% trans "or" %} + {% trans "cancel" %} +
    + +{% endblock tabcontent %} diff --git a/oscar_support/templates/oscar_support/customer/ticket_list.html b/oscar_support/templates/oscar_support/customer/ticket_list.html index 658ec81..b280a38 100644 --- a/oscar_support/templates/oscar_support/customer/ticket_list.html +++ b/oscar_support/templates/oscar_support/customer/ticket_list.html @@ -1,61 +1,34 @@ -{% extends "oscar/customer/profile/profile.html" %} +{% extends "customer/baseaccountpage.html" %} {% load i18n %} -{% load url from future %} -{% block title %} -{% trans 'Your tickets' %} | {{ block.super }} -{% endblock %} - -{% block body_class %}account-pages{% endblock %} - -{% block breadcrumbs %} - -{% endblock %} - -{% block headertext %}{% trans 'Your tickets' %}{% endblock headertext %} - -{% block content %} - - -
    - -{% endblock %} - -{% block onbodyload %} - {{ block.super }} - support.dashboard.initAutoComplete(); +
    {% endblock %} diff --git a/oscar_support/templates/oscar_support/dashboard/ticket_detail.html b/oscar_support/templates/oscar_support/dashboard/ticket_detail.html index 1550832..fc5a676 100644 --- a/oscar_support/templates/oscar_support/dashboard/ticket_detail.html +++ b/oscar_support/templates/oscar_support/dashboard/ticket_detail.html @@ -1,38 +1,55 @@ -{% extends 'oscar_support/dashboard/layout.html' %} +{% extends "dashboard/layout.html" %} {% load currency_filters %} {% load ticket_tags %} {% load i18n %} -{% load url from future %} -{% block body_class %}support home{% endblock %} +{% block body_class %}{{ block.super }} support home{% endblock %} + +{% block title %} +{% trans "Support tickets" %} | {{ block.super }} +{% endblock %} + +{% block headertext %} +{% trans "Support tickets" %} +{% endblock %} + +{% block extrastyles %} +{{ block.super }} + +{% endblock %} {% block breadcrumbs %} {% endblock %} -{% block header %} - -{% endblock %} - {% block dashboard_content %} -
    + {% csrf_token %} -
    -