From 93d128102e1330ab5a2d1795b62b67282fae2d10 Mon Sep 17 00:00:00 2001 From: eric Date: Fri, 18 Oct 2013 12:36:55 -0400 Subject: [PATCH] display of borrowability and library holdings needed another date column on acqs to manage this bookpanel getting complicated- moved some logic into tempalte tags library page now shows b2u books it owns "library" has its own view now --- ...d_acq_refreshes__add_field_acq_lib_acq.py} | 11 +- core/models.py | 51 +++++--- core/tests.py | 5 +- frontend/templates/book_panel.html | 122 ++++++++++-------- frontend/templates/libraryauth/library.html | 17 +-- frontend/templatetags/bookpanel.py | 38 ++++++ frontend/templatetags/lib_acqs.py | 16 +++ frontend/templatetags/purchased.py | 21 ++- frontend/urls.py | 2 +- frontend/views.py | 11 +- 10 files changed, 194 insertions(+), 100 deletions(-) rename core/migrations/{0055_auto__add_field_acq_lib_acq.py => 0055_auto__add_field_acq_refreshes__add_field_acq_lib_acq.py} (97%) create mode 100644 frontend/templatetags/bookpanel.py create mode 100644 frontend/templatetags/lib_acqs.py diff --git a/core/migrations/0055_auto__add_field_acq_lib_acq.py b/core/migrations/0055_auto__add_field_acq_refreshes__add_field_acq_lib_acq.py similarity index 97% rename from core/migrations/0055_auto__add_field_acq_lib_acq.py rename to core/migrations/0055_auto__add_field_acq_refreshes__add_field_acq_lib_acq.py index 0435b236..954ae40d 100644 --- a/core/migrations/0055_auto__add_field_acq_lib_acq.py +++ b/core/migrations/0055_auto__add_field_acq_refreshes__add_field_acq_lib_acq.py @@ -8,6 +8,11 @@ from django.db import models class Migration(SchemaMigration): def forwards(self, orm): + # Adding field 'Acq.refreshes' + db.add_column('core_acq', 'refreshes', + self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime(2013, 10, 17, 0, 0), auto_now_add=True, blank=True), + keep_default=False) + # Adding field 'Acq.lib_acq' db.add_column('core_acq', 'lib_acq', self.gf('django.db.models.fields.related.ForeignKey')(related_name='loans', null=True, to=orm['core.Acq']), @@ -15,6 +20,9 @@ class Migration(SchemaMigration): def backwards(self, orm): + # Deleting field 'Acq.refreshes' + db.delete_column('core_acq', 'refreshes') + # Deleting field 'Acq.lib_acq' db.delete_column('core_acq', 'lib_acq_id') @@ -74,6 +82,7 @@ class Migration(SchemaMigration): 'lib_acq': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'loans'", 'null': 'True', 'to': "orm['core.Acq']"}), 'license': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '1'}), 'nonce': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'refreshes': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 10, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'acqs'", 'to': "orm['auth.User']"}), 'watermarked': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['booxtream.Boox']", 'null': 'True'}), 'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'acqs'", 'to': "orm['core.Work']"}) @@ -126,7 +135,7 @@ class Migration(SchemaMigration): 'core.celerytask': { 'Meta': {'object_name': 'CeleryTask'}, 'active': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 10, 16, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 10, 17, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}), 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True'}), 'function_args': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), 'function_name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), diff --git a/core/models.py b/core/models.py index 7beccd02..e21878f5 100755 --- a/core/models.py +++ b/core/models.py @@ -262,6 +262,7 @@ class Acq(models.Model): CHOICES = ((INDIVIDUAL,'Individual license'),(LIBRARY,'Library License'),(BORROWED,'Borrowed from Library'), (TESTING,'Just for Testing'), (RESERVE,'On Reserve'),) created = models.DateTimeField(auto_now_add=True) expires = models.DateTimeField(null=True) + refreshes = models.DateTimeField(auto_now_add=True, default=now()) work = models.ForeignKey("Work", related_name='acqs', null=False) user = models.ForeignKey(User, related_name='acqs') license = models.PositiveSmallIntegerField(null = False, default = INDIVIDUAL, @@ -318,6 +319,9 @@ class Acq(models.Model): def expire_in(self, delta): self.expires = now()+delta self.save() + if self.lib_acq: + self.lib_acq.refreshes = now()+ (timedelta(days=14)) + self.lib_acq.save() @property def on_reserve(self): @@ -335,9 +339,10 @@ class Acq(models.Model): def borrowable(self): if self.license == RESERVE and not self.expired: return True - if self.license != LIBRARY: + if self.license == LIBRARY: + return self.refreshes < datetime.now() + else: return False - return Acq.objects.filter(lib_acq=self,expires__gt=datetime.now()).count()==0 @@ -1108,25 +1113,37 @@ class Work(models.Model): acqs=Acq.objects.none() def __init__(self,acqs): self.acqs=acqs - def is_active(self): - if self.acqs.count()==0: - return False - for acq in self.acqs: - if acq.expires is None: - return True - if acq.expires > now(): - return True - return False + @property + def is_active(self): + return self.acqs.filter(expires__isnull = True).count()>0 or self.acqs.filter(expires__gt= now()).count()>0 + + @property + def borrowed(self): + loans = self.acqs.filter(license=BORROWED,expires__gt= now()) + if loans.count()==0: + return None + else: + return loans[0] + + @property def purchased(self): - for acq in self.acqs: - if acq.license == INDIVIDUAL: - return True - return False - + purchases = self.acqs.filter(license=INDIVIDUAL) + if purchases.count()==0: + return None + else: + return purchases[0] + + @property + def lib_acqs(self): + return self.acqs.filter(license=LIBRARY) + + @property + def borrowable(self): + return self.acqs.filter(license=LIBRARY, refreshes__lt=now()).count()>0 def get_user_license(self,user): - if user==None or not user.is_authenticated(): + if user==None or user.is_anonymous(): return None return self.user_license(self.acqs.filter(user=user)) diff --git a/core/tests.py b/core/tests.py index 299bd131..c87022fd 100755 --- a/core/tests.py +++ b/core/tests.py @@ -882,8 +882,9 @@ class LibTests(TestCase): self.assertTrue(new_acq.borrowable) reserve_acq = Acq.objects.create(user=u,work=c.work,license= RESERVE, lib_acq = new_acq) self.assertTrue(reserve_acq.borrowable) - print reserve_acq.expires - self.assertTrue(reserve_acq.expires< now()+timedelta(hours=3)) self.assertFalse(new_acq.borrowable) + + self.assertTrue(reserve_acq.expires< now()+timedelta(hours=3)) + reserve_acq.borrow() self.assertTrue(reserve_acq.expires> now()+timedelta(hours=3)) diff --git a/frontend/templates/book_panel.html b/frontend/templates/book_panel.html index b0aa30dd..fbcb4b7c 100644 --- a/frontend/templates/book_panel.html +++ b/frontend/templates/book_panel.html @@ -1,5 +1,6 @@ {% load humanize %} {% load purchased %} +{% load lib_acqs %} {% with work.first_ebook as first_ebook %} {% with work.last_campaign.supporters as supporters %} {% with work.cover_image_thumbnail as thumbnail %} @@ -10,7 +11,7 @@ {% with work.last_campaign.deadline as deadline %} {% with work.id as workid %} {% with request.user.wishlist.works.all as wishlist %} -{% purchased %} +{% purchased %}{% lib_acqs %}
@@ -18,7 +19,7 @@
{% if last_campaign %} {% comment %}top section: campaign info + optional action button. Varies by campaign status.{% endcomment %} - {% if status == 'SUCCESSFUL' %} + {% if status == 'SUCCESSFUL' or license_is_active or borrowable %}
{% comment %}bibliographic data{% endcomment %}
@@ -29,21 +30,41 @@ + {% if purchased %} +
+ Purchased! +
+ {% else %}{% if borrowed %} + Borrowed! +

Until {{ borrowed.expires|date:"M d, Y" }}

+ {% else %}{% if borrowable %} +
+ Library has it! +

{{ lib_acqs.count }}{% ifequal lib_acqs.count 1 %} copy{% else %} copies{% endifequal %}

+
+ {% else %}
UNGLUED!

On: {{ deadline|date:"M d, Y" }}

Raised: {{ work.last_campaign.current_total|floatformat:0|intcomma }}

-
+
+ {% endif %}{% endif %}{% endif %}
{% include "book_panel_addbutton.html" %}
- {% if first_ebook %} + {% if purchased %} + Read it Now + {% else %}{% if borrowed %} + Read it Now + {% else %}{% if borrowable %} + Borrow It + {% else %}{% if first_ebook %} Read it Now {% else %} Coming Soon - {% endif %} + {% endif %}{% endif %}{% endif %}{% endif %}
{% else %}{% if status == 'ACTIVE' %}
@@ -65,7 +86,7 @@

by {{ deadline|naturalday:"M d, Y" }}

{% else %}

${{ work.last_campaign.left|floatformat:0|intcomma }} needed

-

now ungluing on

+

will unglue on

{{ work.last_campaign.cc_date|naturalday:"M d, Y" }}

{% endifequal %}
@@ -80,13 +101,9 @@
{% ifequal work.last_campaign.type 1 %} - Pledge + Pledge {% else %} - {% if purchased %} - Download - {% else %} - Purchase - {% endif %} + Purchase {% endifequal %}
{% endif %} @@ -166,50 +183,37 @@
{% comment %}same logic as above{% endcomment %} - {% if request.user.is_anonymous %} + {% if show_pledge %} +
+ Pledge +
+ {% else %}{% if show_purchase %} +
+ Purchase +
+ {% else %}{% if request.user.is_anonymous %} - {% else %}{% if request.user.id in supporters %} -
- Pledged! -
- {% else %}{% ifequal supporter request.user %} - {% comment %} used only on your own supporter page. {% endcomment %} - {% ifequal status "ACTIVE" %} -
- {% ifequal work.last_campaign.type 1 %} - Pledge - {% else %} - {% if purchased %} - Download - {% else %} - Purchase - {% endif %} - - {% endifequal %} -
- {% else %} + {% else %}{% if work in wishlist %} + {% ifequal supporter request.user %} + {% comment %} used only on your own supporter page. {% endcomment %}
Un-list
+ {% else %} +
+ {% if purchased %} + Purchased! + {% else %}{% if borrowed %} + Borrowed! + {% else %}{% if request.user.id in supporters %} + Pledged! + {% else %} + On My List! + {% endif %}{% endif %}{% endif %} +
{% endifequal %} - {% else %}{% ifequal status "ACTIVE" %} -
- {% ifequal work.last_campaign.type 1 %} - Pledge - {% else %} - {% if purchased %} - Download - {% else %} - Purchase - {% endif %} - {% endifequal %} -
- {% else %}{% if work in wishlist %} -
- On My List! -
{% else %}
{% if on_search_page %} @@ -218,15 +222,17 @@ Add to My List {% endif %}
- {% endif %}{% endifequal %}{% endifequal %}{% endif %}{% endif %} + {% endif %}{% endif %}{% endif %}{% endif %}
{% ifequal status "ACTIVE" %} - {% ifequal work.last_campaign.type 1 %} + {% if library %} + {{ lib_acqs.count }} {% ifequal lib_acqs.count 1 %} copy{% else %} copies{% endifequal %} + {% else %}{% ifequal work.last_campaign.type 1 %} ${{ work.last_campaign.current_total|floatformat:0|intcomma }}/${{ work.last_campaign.target|floatformat:0|intcomma }} {% else %} ${{ work.last_campaign.left|floatformat:0|intcomma }} to go - {% endifequal %} + {% endifequal %}{% endif %} {% else %}{% ifequal status "INITIALIZED" %} Status: Coming soon! {% else %}{% ifequal status "SUCCESSFUL" %} @@ -245,8 +251,14 @@ If no ebook but there is an active or successful campaign: progress toward goal Otherwise: number of wishes {% endcomment %} - {% if first_ebook %} -
Read it Now
+ {% if purchased %} +
Read it Now
+ {% else %}{% if borrowed %} +
Read it Now
+ {% else %}{% if borrowable %} +
Borrow It
+ {% else %}{% if first_ebook %} +
Read it Now
{% else %}{% if status == 'ACTIVE' or status == 'SUCCESSFUL' %}
book list status @@ -258,7 +270,7 @@ {% else %} Listed by 0 {% endif %} - {% endif %}{% endif %} + {% endif %}{% endif %}{% endif %}{% endif %}{% endif %}
diff --git a/frontend/templates/libraryauth/library.html b/frontend/templates/libraryauth/library.html index 43021f28..c99e0bf6 100644 --- a/frontend/templates/libraryauth/library.html +++ b/frontend/templates/libraryauth/library.html @@ -150,8 +150,7 @@ function highlightTarget(targetdiv) {
    @@ -257,20 +256,6 @@ function highlightTarget(targetdiv) { {% endfor %}
- {% lazy_paginate 20 works_wished using "works_wished" %} - {% for work in works_wished %} -
- {% with work.googlebooks_id as googlebooks_id %} - {% include "book_panel.html" %} - {% endwith %} -
- {% endfor %} - {% endifequal %}
diff --git a/frontend/templatetags/bookpanel.py b/frontend/templatetags/bookpanel.py new file mode 100644 index 00000000..95c5e2d4 --- /dev/null +++ b/frontend/templatetags/bookpanel.py @@ -0,0 +1,38 @@ +from django import template +from regluit.utils.localdatetime import now +from regluit.parameters import * + +register = template.Library() + +@register.simple_tag(takes_context=True) +def bookpanel(context): + work = context['work'] + library = context.get('library',None) + user = context['request'].user + campaign = context.get('last_campaign', None) + + # compute a boolean that's true if bookpanel should show a "pledge" button... + # campaign is ACTIVE, type 1 - PLEDGE + # user has not pledged or user is anonymous + + show_pledge = False + if campaign and campaign.type==PLEDGE: + if user.is_anonymous() or not user.id in context.get('supporters', []): + show_pledge = True + context['show_pledge'] = show_pledge + + # compute a boolean that's true if bookpanel should show a "purchase" button... + # campaign is ACTIVE, type 2 - BUY2UNGLUE + # user has not purchased or user is anonymous + # user has not borrowed or user is anonymous + # work not available in users library + # not on the library page + + show_purchase = False + if campaign and campaign.type==BUY2UNGLUE: + if user.is_anonymous() or not context.get('license_is_active', False): + if not context.get('borrowable', False): + if not library: + show_purchase = True + context['show_purchase'] = show_purchase + return '' diff --git a/frontend/templatetags/lib_acqs.py b/frontend/templatetags/lib_acqs.py new file mode 100644 index 00000000..b4505c13 --- /dev/null +++ b/frontend/templatetags/lib_acqs.py @@ -0,0 +1,16 @@ +from regluit.utils.localdatetime import now +from django import template +register = template.Library() + +@register.simple_tag(takes_context=True) +def lib_acqs(context): + work = context['work'] + library = context.get('library',False) + if not library: + return '' + user_license = work.get_user_license(library.user) + if user_license: + context['lib_acqs'] = user_license.lib_acqs + else: + context['lib_acqs'] = None + return '' diff --git a/frontend/templatetags/purchased.py b/frontend/templatetags/purchased.py index ce214269..03276658 100644 --- a/frontend/templatetags/purchased.py +++ b/frontend/templatetags/purchased.py @@ -7,9 +7,22 @@ register = template.Library() def purchased(context): work = context['work'] user = context['request'].user - try: - user_license = work.get_user_licence(user) + if user.is_anonymous(): + return '' + user_license = work.get_user_license(user) + if user_license: context['purchased'] = user_license.purchased - except: - context['purchased'] = False + context['borrowed'] = user_license.borrowed + context['license_is_active'] = user_license.is_active + else: + context['purchased'] = None + context['borrowed'] = None + context['license_is_active'] = False + borrowable = False + for library in user.profile.libraries: + lib_license=work.get_user_license(library.user) + if lib_license and lib_license.borrowable: + borrowable = True + continue + context['borrowable'] = borrowable return '' diff --git a/frontend/urls.py b/frontend/urls.py index 45cab66d..e105efa2 100644 --- a/frontend/urls.py +++ b/frontend/urls.py @@ -48,7 +48,7 @@ urlpatterns = patterns( url(r"^next/$", "next", name="next"), url(r"^supporter/(?P[^/]+)/$", "supporter", {'template_name': 'supporter.html'}, name="supporter"), url(r"^supporter/(?P[^/]+)/marc/$", "marc", name="user_marc"), - url(r"^library/(?P[^/]+)/$", "library", name="library"), + url(r"^library/(?P[^/]+)/$", "library", name="library"), url(r"^accounts/manage/$", login_required(ManageAccount.as_view()), name="manage_account"), url(r"^search/$", "search", name="search"), url(r"^privacy/$", TemplateView.as_view(template_name="privacy.html"), diff --git a/frontend/views.py b/frontend/views.py index 30ec70e7..289aaf06 100755 --- a/frontend/views.py +++ b/frontend/views.py @@ -1858,16 +1858,19 @@ def supporter(request, supporter_username, template_name, extra_context={}): context.update(extra_context) return render(request, template_name, context) -def library(request,library): +def library(request,library_name): context={} try: # determine if the supporter is a library - authenticator = Authenticator(request,library) + authenticator = Authenticator(request,library_name) context['authenticator'] = authenticator - context['library'] = authenticator.library + context['library'] = library = authenticator.library except Library.DoesNotExist: raise Http404 - return supporter(request,library,template_name='libraryauth/library.html', extra_context=context) + context['works_active']= models.Work.objects.filter(acqs__user=library.user,acqs__license=LIBRARY).distinct() + context['activetab'] = "#2" + + return supporter(request,library_name,template_name='libraryauth/library.html', extra_context=context)