Permalink
Browse files

moving project-specific code into repository

  • Loading branch information...
1 parent 55372c9 commit c43ecdec37e54ba69fb0762258cacdfc0036387f @elbaschid elbaschid committed Aug 31, 2012
View
@@ -0,0 +1,8 @@
+The PRIMARY AUTHORS are:
+
+* Sebastian Vetter
+
+Significant contributions from:
+
+* Jonathan Price
+* Oliver Randell
View
@@ -0,0 +1,27 @@
+Copyright (c) 2011, Tangent Communications PLC and individual contributors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of Tangent Communications PLC nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
View
@@ -0,0 +1,3 @@
+include *.rst
+recursive-include stores/templates *.txt *.html
+recursive-include stores/static *
No changes.
@@ -0,0 +1,8 @@
+from django.contrib import admin
+
+from chocolatebox.stores.models import Store, StoreGroup, OpeningTime
+
+
+admin.site.register(Store)
+admin.site.register(StoreGroup)
+admin.site.register(OpeningTime)
View
@@ -0,0 +1,23 @@
+from django.conf.urls.defaults import patterns, url
+
+from oscar.core.application import Application
+
+from chocolatebox.stores import views
+
+
+class StoresApplication(Application):
+ name = 'stores'
+ list_view = views.StoreListView
+ detail_view = views.StoreDetailView
+
+ def get_urls(self):
+ urlpatterns = super(StoresApplication, self).get_urls()
+
+ urlpatterns += patterns('',
+ url(r'^$', self.list_view.as_view(), name='index'),
+ url(r'^(?P<slug>[\w-]+)/$', self.detail_view.as_view(), name='detail'),
+ )
+ return self.post_process_urls(urlpatterns)
+
+
+application = StoresApplication()
No changes.
@@ -0,0 +1,68 @@
+from django.conf.urls.defaults import patterns, url
+from django.utils.translation import ugettext_lazy as _
+
+from oscar.apps.dashboard.nav import register, Node
+from oscar.apps.dashboard.orders import app as core_order_app
+
+from chocolatebox.dashboard.stores import views
+
+
+node = Node(_('Store Manager'))
+node.add_child(Node(_('Stores'), 'dashboard:store-list'))
+node.add_child(Node(_('Store Groups'), 'dashboard:store-group-list'))
+register(node, 100)
+
+
+class OrdersDashboardApplication(core_order_app.OrdersDashboardApplication):
+ store_list_view = views.StoreListView
+ store_create_view = views.StoreCreateView
+ store_update_view = views.StoreUpdateView
+ store_delete_view = views.StoreDeleteView
+ store_group_list_view = views.StoreGroupListView
+ store_group_create_view = views.StoreGroupCreateView
+ store_group_update_view = views.StoreGroupUpdateView
+ store_group_delete_view = views.StoreGroupDeleteView
+
+ def get_urls(self):
+ urlpatterns = patterns('',
+ url(r'^$', self.store_list_view.as_view(), name='store-list'),
+ url(
+ r'^create/$',
+ self.store_create_view.as_view(),
+ name='store-create'
+ ),
+ url(
+ r'^update/(?P<pk>[\d]+)/$',
+ self.store_update_view.as_view(),
+ name='store-update'
+ ),
+ url(
+ r'^delete/(?P<pk>[\d]+)/$',
+ self.store_delete_view.as_view(),
+ name='store-delete'
+ ),
+ url(
+ r'^groups/$',
+ self.store_group_list_view.as_view(),
+ name='store-group-list'
+ ),
+ url(
+ r'^groups/create/$',
+ self.store_group_create_view.as_view(),
+ name='store-group-create'
+ ),
+ url(
+ r'^groups/update/(?P<pk>[\d]+)/$',
+ self.store_group_update_view.as_view(),
+ name='store-group-update'
+ ),
+ url(
+ r'^groups/delete/(?P<pk>[\d]+)/$',
+ self.store_group_delete_view.as_view(),
+ name='store-group-delete'
+ ),
+ )
+ return self.post_process_urls(urlpatterns)
+
+
+application = OrdersDashboardApplication()
@@ -0,0 +1,39 @@
+from django import forms
+from django.utils.translation import ugettext_lazy as _
+from django.db.models import get_model
+
+
+class StoreForm(forms.ModelForm):
+
+ class Meta:
+ model = get_model('stores', 'store')
+ exclude = ('slug', 'opening_hours')
+ widgets = {
+ 'latitude': forms.HiddenInput(),
+ 'longitude': forms.HiddenInput(),
+ 'description': forms.Textarea(attrs={'cols': 40, 'rows': 15}),
+ }
+
+class OpeningTimeForm(forms.ModelForm):
+
+ def save(self, *args, **kwargs):
+ kwargs['commit'] = False
+ obj = super(OpeningTimeForm, self).save(*args, **kwargs)
+ obj.display_order = self.get_display_order()
+ obj.save()
+ return obj
+
+ def get_display_order(self):
+ return self.prefix.split('-').pop()
+
+ class Meta:
+ model = get_model('stores', 'openingtime')
+ exclude = ('display_order',)
+ widgets = {
+ 'title': forms.TextInput(
+ attrs={'placeholder': _("e.g. Friday or Monday - Friday")}
+ ),
+ 'time': forms.TextInput(
+ attrs={'placeholder': _("e.g. 9am - 8pm")}
+ ),
+ }
@@ -0,0 +1,89 @@
+from django.views import generic
+from django.db.models import get_model
+from django.core.urlresolvers import reverse
+
+from extra_views import (CreateWithInlinesView, UpdateWithInlinesView,
+ InlineFormSet)
+
+from chocolatebox.dashboard.stores import forms
+
+Store = get_model('stores', 'store')
+StoreGroup = get_model('stores', 'storegroup')
+OpeningTime = get_model('stores', 'openingtime')
+
+
+class StoreListView(generic.ListView):
+ model = Store
+ template_name = "dashboard/stores/store_list.html"
+ context_object_name = "store_list"
+
+
+class OpeningTimeInline(InlineFormSet):
+ extra = 7
+ max_num = 7
+ model = OpeningTime
+ form_class = forms.OpeningTimeForm
+
+
+class StoreCreateView(CreateWithInlinesView):
+ model = Store
+ template_name = "dashboard/stores/store_update.html"
+ inlines = [OpeningTimeInline]
+ form_class = forms.StoreForm
+
+ def get_success_url(self):
+ return reverse('dashboard:store-list')
+
+
+class StoreUpdateView(UpdateWithInlinesView):
+ model = Store
+ template_name = "dashboard/stores/store_update.html"
+ inlines = [OpeningTimeInline]
+ form_class = forms.StoreForm
+
+ def get_success_url(self):
+ return reverse('dashboard:store-list')
+
+
+class StoreDeleteView(generic.DeleteView):
+ model = Store
+ template_name = "dashboard/stores/store_delete.html"
+
+ def delete(self, request, *args, **kwargs):
+ self.object = self.get_object()
+ for time in self.object.opening_times.all():
+ time.delete()
+ return super(StoreDeleteView, self).delete(request, *args, **kwargs)
+
+ def get_success_url(self):
+ return reverse('dashboard:store-list')
+
+
+class StoreGroupListView(generic.ListView):
+ model = StoreGroup
+ context_object_name = 'group_list'
+ template_name = "dashboard/stores/store_group_list.html"
+
+
+class StoreGroupCreateView(generic.CreateView):
+ model = StoreGroup
+ template_name = "dashboard/stores/store_group_update.html"
+
+ def get_success_url(self):
+ return reverse('dashboard:store-group-list')
+
+
+class StoreGroupUpdateView(generic.UpdateView):
+ model = StoreGroup
+ template_name = "dashboard/stores/store_group_update.html"
+
+ def get_success_url(self):
+ return reverse('dashboard:store-group-list')
+
+
+class StoreGroupDeleteView(generic.DeleteView):
+ model = StoreGroup
+ template_name = "dashboard/stores/store_group_delete.html"
+
+ def get_success_url(self):
+ return reverse('dashboard:store-group-list')
No changes.
View
@@ -0,0 +1,101 @@
+from django.db import models
+from django.utils.translation import ugettext as _
+from django.template.defaultfilters import slugify
+
+from model_utils.managers import PassThroughManager
+
+
+class StoreGroup(models.Model):
+ name = models.CharField(_('name'), max_length=100, unique=True)
+ slug = models.SlugField(_('slug'), max_length=100, unique=True, blank=True)
+
+ def save(self, *args, **kwargs):
+ if not self.slug:
+ self.slug = slugify(self.name)
+ super(StoreGroup, self).save(*args, **kwargs)
+
+ def __unicode__(self):
+ return self.name
+
+
+class StoreQuerySet(models.query.QuerySet):
+
+ def pickup_stores(self):
+ return self.filter(is_pickup_store=True, is_active=True)
+
+
+class Store(models.Model):
+ name = models.CharField(_('name'), max_length=100)
+ slug = models.SlugField(_('slug'), max_length=100, unique=True, null=True)
+
+ line1 = models.CharField(_("First line of address"), max_length=255)
+ line2 = models.CharField(
+ _("Second line of address"),
+ max_length=255,
+ blank=True,
+ null=True
+ )
+ city = models.CharField(_('City'), max_length=255)
+ postcode = models.CharField(_('Post Code'), max_length=4)
+ country = models.ForeignKey('address.Country', verbose_name=_("Country"))
+ state = models.CharField(_("State/County"), max_length=255)
+
+ phone = models.CharField(_('Phone'), max_length=20, blank=True, null=True)
+
+ latitude = models.FloatField()
+ longitude = models.FloatField()
+
+ image = models.ImageField(
+ _("Image"),
+ upload_to="images/stores",
+ blank=True, null=True
+ )
+ description = models.CharField(
+ _("Description"),
+ max_length=2000,
+ blank=True, null=True
+ )
+
+ group = models.ForeignKey(StoreGroup, related_name='stores', null=True, blank=True)
+
+ is_pickup_store = models.BooleanField(default=True)
+ is_active = models.BooleanField(default=True)
+
+ objects = PassThroughManager.for_queryset_class(StoreQuerySet)()
+
+ def get_shipping_data(self):
+ return {
+ 'line1': self.name,
+ 'line2': self.line1,
+ 'line3': self.line2,
+ 'line4': self.city,
+ 'postcode': self.postcode,
+ 'country': self.country,
+ 'state': self.state,
+ }
+
+ def save(self, *args, **kwargs):
+ if not self.slug:
+ self.slug = slugify(self.name)
+ super(Store, self).save(*args, **kwargs)
+
+ def __unicode__(self):
+ return self.name
+
+
+class OpeningTime(models.Model):
+ title = models.CharField(max_length=100, verbose_name=_("Description"))
+ time = models.CharField(max_length=100)
+
+ # Use display_order to determine the order of times
+ display_order = models.PositiveIntegerField(_("Display Order"), default=0,
+ help_text=_("""An image with a display order of
+ zero will be the primary image for a product"""))
+
+ store = models.ForeignKey('stores.Store', related_name='opening_times')
+
+ def __unicode__(self):
+ return _("%s opened %s: %s") % (self.store.name, self.title, self.time)
+
+ class Meta:
+ ordering = ["display_order"]
Oops, something went wrong.

0 comments on commit c43ecde

Please sign in to comment.