From 575e58df64c98b53edca9fb6a29b284dbc375609 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 26 Mar 2013 17:10:46 +0100 Subject: [PATCH] Added: Fundusz, dummy payments. --- .gitignore | 1 + apps/funding/admin.py | 3 +- apps/funding/forms.py | 30 +++++ ...ld_offer_book_url__add_field_offer_book.py | 108 ++++++++++++++++++ apps/funding/models.py | 12 +- .../funding.scssc | Bin 2446 -> 0 bytes apps/funding/static/funding/funding.css | 28 +++-- apps/funding/static/funding/funding.scss | 36 ++++-- .../templates/funding/offer_detail.html | 14 ++- .../funding/templates/funding/offer_list.html | 3 +- apps/funding/templates/funding/thanks.html | 17 +++ apps/funding/templates/funding/wlfund.html | 37 ++++-- apps/funding/urls.py | 9 +- apps/funding/views.py | 63 ++++++++-- 14 files changed, 315 insertions(+), 46 deletions(-) create mode 100755 apps/funding/forms.py create mode 100644 apps/funding/migrations/0002_auto__add_spent__del_field_offer_book_url__add_field_offer_book.py delete mode 100644 apps/funding/static/funding/.sass-cache/9a22640771b7b9d791c15ce50176b00a63a474df/funding.scssc create mode 100755 apps/funding/templates/funding/thanks.html diff --git a/.gitignore b/.gitignore index c3e3e48b6..6714e2301 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ dev.sqlite *~ *.orig *.log +.sass-cache # Compress output /static diff --git a/apps/funding/admin.py b/apps/funding/admin.py index 132c86304..7fbb4c488 100755 --- a/apps/funding/admin.py +++ b/apps/funding/admin.py @@ -1,6 +1,7 @@ from django.contrib import admin -from .models import Offer, Perk, Funding +from .models import Offer, Perk, Funding, Spent +admin.site.register(Spent) admin.site.register(Offer) admin.site.register(Perk) admin.site.register(Funding) diff --git a/apps/funding/forms.py b/apps/funding/forms.py new file mode 100755 index 000000000..eb75fb6f1 --- /dev/null +++ b/apps/funding/forms.py @@ -0,0 +1,30 @@ +from django import forms +from .models import Offer + + +class DummyForm(forms.Form): + amount = forms.DecimalField() + name = forms.CharField() + email = forms.EmailField() + + def __init__(self, offer, *args, **kwargs): + self.offer = offer + super(DummyForm, self).__init__(*args, **kwargs) + + def clean_amount(self): + if self.cleaned_data['amount'] <= 0: + raise forms.ValidationError("A!") + return self.cleaned_data['amount'] + + def clean(self): + if self.offer != Offer.current(): + raise forms.ValidationError("B!") + return self.cleaned_data + + def save(self): + print self.cleaned_data + return self.offer.fund( + name=self.cleaned_data['name'], + email=self.cleaned_data['email'], + amount=self.cleaned_data['amount']) + diff --git a/apps/funding/migrations/0002_auto__add_spent__del_field_offer_book_url__add_field_offer_book.py b/apps/funding/migrations/0002_auto__add_spent__del_field_offer_book_url__add_field_offer_book.py new file mode 100644 index 000000000..1c03bdbf3 --- /dev/null +++ b/apps/funding/migrations/0002_auto__add_spent__del_field_offer_book_url__add_field_offer_book.py @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'Spent' + db.create_table('funding_spent', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('amount', self.gf('django.db.models.fields.DecimalField')(max_digits=10, decimal_places=2)), + ('timestamp', self.gf('django.db.models.fields.DateField')()), + ('book', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['catalogue.Book'])), + )) + db.send_create_signal('funding', ['Spent']) + + # Deleting field 'Offer.book_url' + db.delete_column('funding_offer', 'book_url') + + # Adding field 'Offer.book' + db.add_column('funding_offer', 'book', + self.gf('django.db.models.fields.related.ForeignKey')(to=orm['catalogue.Book'], null=True, blank=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting model 'Spent' + db.delete_table('funding_spent') + + # Adding field 'Offer.book_url' + db.add_column('funding_offer', 'book_url', + self.gf('django.db.models.fields.URLField')(default='', max_length=200, blank=True), + keep_default=False) + + # Deleting field 'Offer.book' + db.delete_column('funding_offer', 'book_id') + + + models = { + 'catalogue.book': { + 'Meta': {'ordering': "('sort_key',)", 'object_name': 'Book'}, + '_related_info': ('jsonfield.fields.JSONField', [], {'null': 'True', 'blank': 'True'}), + 'changed_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), + 'common_slug': ('django.db.models.fields.SlugField', [], {'max_length': '120'}), + 'cover': ('catalogue.fields.EbookField', [], {'max_length': '100', 'null': 'True', 'format_name': "'cover'", 'blank': 'True'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'epub_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'epub'", 'blank': 'True'}), + 'extra_info': ('jsonfield.fields.JSONField', [], {'default': "'{}'"}), + 'fb2_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'fb2'", 'blank': 'True'}), + 'gazeta_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'}), + 'html_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'html'", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'default': "'pol'", 'max_length': '3', 'db_index': 'True'}), + 'mobi_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'mobi'", 'blank': 'True'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['catalogue.Book']"}), + 'parent_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'pdf_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'pdf'", 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '120'}), + 'sort_key': ('django.db.models.fields.CharField', [], {'max_length': '120', 'db_index': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '120'}), + 'txt_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'txt'", 'blank': 'True'}), + 'wiki_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'}), + 'xml_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'xml'", 'blank': 'True'}) + }, + 'funding.funding': { + 'Meta': {'ordering': "['-payed_at']", 'object_name': 'Funding'}, + 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '2'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '127'}), + 'offer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['funding.Offer']"}), + 'payed_at': ('django.db.models.fields.DateTimeField', [], {}), + 'perks': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['funding.Perk']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'funding.offer': { + 'Meta': {'ordering': "['-end']", 'object_name': 'Offer'}, + 'author': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['catalogue.Book']", 'null': 'True', 'blank': 'True'}), + 'end': ('django.db.models.fields.DateField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'redakcja_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'start': ('django.db.models.fields.DateField', [], {}), + 'target': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '2'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'funding.perk': { + 'Meta': {'ordering': "['-price']", 'object_name': 'Perk'}, + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'offer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['funding.Offer']", 'null': 'True', 'blank': 'True'}), + 'price': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '2'}) + }, + 'funding.spent': { + 'Meta': {'object_name': 'Spent'}, + 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '2'}), + 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['catalogue.Book']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'timestamp': ('django.db.models.fields.DateField', [], {}) + } + } + + complete_apps = ['funding'] \ No newline at end of file diff --git a/apps/funding/models.py b/apps/funding/models.py index a088a07b7..8c1ee9a72 100644 --- a/apps/funding/models.py +++ b/apps/funding/models.py @@ -6,13 +6,14 @@ from django.core.urlresolvers import reverse from django.db import models from django.utils.translation import ugettext_lazy as _, ugettext as __ from datetime import date, datetime +from catalogue.models import Book class Offer(models.Model): author = models.CharField(_('author'), max_length=255) title = models.CharField(_('title'), max_length=255) slug = models.SlugField(_('slug')) - book_url = models.URLField(_('book URL'), blank=True) + book = models.ForeignKey(Book, null=True, blank=True) redakcja_url = models.URLField(_('redakcja URL'), blank=True) target = models.DecimalField(_('target'), decimal_places=2, max_digits=10) start = models.DateField(_('start')) @@ -100,3 +101,12 @@ class Funding(models.Model): def __unicode__(self): return "%s payed %s for %s" % (self.name, self.amount, self.offer) + + +class Spent(models.Model): + amount = models.DecimalField(_('amount'), decimal_places=2, max_digits=10) + timestamp = models.DateField(_('when')) + book = models.ForeignKey(Book) + + def __unicode__(self): + return u"Spent: %s" % unicode(self.book) diff --git a/apps/funding/static/funding/.sass-cache/9a22640771b7b9d791c15ce50176b00a63a474df/funding.scssc b/apps/funding/static/funding/.sass-cache/9a22640771b7b9d791c15ce50176b00a63a474df/funding.scssc deleted file mode 100644 index eea6a038fddebd0647a32a2ef54043c2341ffcf0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2446 zcmb7F-*4MC5RQjJu@yU>mF7p24%3`0=QiOivJblM~YNAcYyJ3MZ zXf&#<8f5{MMpa}w0^Uc)Wpl5Sq$Ki5z$4loXOYjMiGhssA=sqEP1qW;oS2A&`q$DY z;i#z(zM=v3QZ5iW<6%gy==2v|g!0l17=K&AO*bIrh&3v4k1Z#i4Dry=uMLiN4i zu>uS?BvuJVYDLA0)`=%;CxtEKU)+N(CTT#@m<8r@i>rPI$n4+YN~KLHPly z)0m<<^J$c_F{1+T;&IA&l-#Xh6Yy?0F`RpyOrw%hX|CgE&b~|+D7hiY zbwTt{?sL3e#budhtyAy_iOPt0gX5}35^rkUaXnvuUDmZ#7kw;d;;lJMuy9&%u6`OL z2=}zA-8RQOO4|whlgjGwHpe@vcC*(xrJ>r}#d|7mnaDmq$ZOfqITvxNG4WOFEk!Z9 zk3^_`NrakA!|pwrN^LpNwhLTM1czB@vye>Yl~p9GFESCdj-lI9<{h(eay)?njM_1~ zr9mf-CP$F+1(royZ1aJ_)!rPyorTi`jVVc&fvoAx_Vf`X>bih}e}gF7$B9SJS4ZkR zpds{RMH8!opt>5cBqkp1LP3qiwt$5*)SK{>(=%%e)8heGgR;;PvmsFE$W~r%2}_|R z4|%RS8bX`->%6(GqPg2~kR@MGC@wm@k$3pq(PBG`^}xcpfkX9ksh;|rrJNpANK!uc z7g^+yATV(Q25?M#+UA*}5)_DtNitgJXfKC6cR7<7K~Hr-Oh}rF#+Ol>+`|s&vs{Uv;;w0^~qzdFj+G{{ object }}
-{% funding object add_class="standalone-funding" %} +{% funding object %} {% if object.state == 'running' %}

Wpłać:

-
+ + {% csrf_token %} + {{ form|as_uni_form }} +
{% endif %} + +

Zobacz wszystkie zbiórki.

diff --git a/apps/funding/templates/funding/offer_list.html b/apps/funding/templates/funding/offer_list.html index 926d1d3e2..6114e377c 100755 --- a/apps/funding/templates/funding/offer_list.html +++ b/apps/funding/templates/funding/offer_list.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load url from future %} {% load funding_tags %} {% block titleextra %}Funding{% endblock %} @@ -19,7 +20,7 @@ {% endif %} {% elif funding.state == "lose" %}

Cel finansowania nie został osiągnięty. Zgromadzone środki - zostały przekazane na Fundusz Wolnych Lektur.

+ zostały przekazane na Fundusz Wolnych Lektur.

{% endif %} {% endfor %} diff --git a/apps/funding/templates/funding/thanks.html b/apps/funding/templates/funding/thanks.html new file mode 100755 index 000000000..baf227558 --- /dev/null +++ b/apps/funding/templates/funding/thanks.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} +{% load funding_tags %} + +{% block titleextra %}Dziękujemy!{% endblock %} + +{% block body %} + +

Dziękujemy!

+
+ +Dziękujemy za wsparcie! + +

Wróć do strony aktualnej zbiórki.

+
+ + +{% endblock %} diff --git a/apps/funding/templates/funding/wlfund.html b/apps/funding/templates/funding/wlfund.html index eb33257a5..5f3ca65b5 100755 --- a/apps/funding/templates/funding/wlfund.html +++ b/apps/funding/templates/funding/wlfund.html @@ -5,16 +5,35 @@ {% block body %}

Fundusz Wolnych Lektur

-

Suma: {{ amount }}

- -
    - {% for entry in log %} -
  • - {{ entry.end }} +{{ entry.sum }} - Częściowa zbiórka na: {{ entry }} -
  • + + + + + + + + + {% for tag, entry in log %} + {% if tag == 'spent' %} + + + + + + + {% else %} + + + + + + + {% endif %} {% endfor %} - +
    Bilans:
    {{ amount }}
     
    {{ entry.timestamp }}
    {{ entry.total }}
    -{{ entry.amount }} zł
    Książka: + {{ entry.book }}
    {{ entry.end }}
    {{ entry.total }}
    +{{ entry.sum }} zł
    Pieniądze z częściowej zbiórki: + + {{ entry }}
    {% endblock %} diff --git a/apps/funding/urls.py b/apps/funding/urls.py index c712b5e08..dc79f3130 100755 --- a/apps/funding/urls.py +++ b/apps/funding/urls.py @@ -3,14 +3,15 @@ # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # from django.conf.urls import patterns, url -from django.views.generic import DetailView, ListView, FormView +from django.views.generic import ListView, FormView, TemplateView from .models import Offer -from .views import WLFundView +from .views import WLFundView, OfferDetailView, ThanksView urlpatterns = patterns('', url(r'^$', ListView.as_view(queryset=Offer.public()), name='funding'), - url(r'lektura/^(?P[^/]+)/$', DetailView.as_view(queryset=Offer.public()), name='funding_offer'), - url(r'fundusz/$', WLFundView.as_view(), name='funding_wlfund'), + url(r'^lektura/(?P[^/]+)/$', OfferDetailView.as_view(), name='funding_offer'), + url(r'^dziekujemy/$', ThanksView.as_view(), name='funding_thanks'), + url(r'^fundusz/$', WLFundView.as_view(), name='funding_wlfund'), ) diff --git a/apps/funding/views.py b/apps/funding/views.py index dab996a75..05bf3983c 100644 --- a/apps/funding/views.py +++ b/apps/funding/views.py @@ -1,21 +1,24 @@ # Create your views here. -from django.views.generic import TemplateView -from .models import Offer +from django.core.urlresolvers import reverse +from django.shortcuts import redirect, get_object_or_404 +from django.views.generic import TemplateView, FormView, DetailView +from .forms import DummyForm +from .models import Offer, Spent def mix(*streams): substreams = [] - for stream, read_date in streams: + for stream, read_date, tag in streams: iterstream = iter(stream) try: item = next(iterstream) except StopIteration: pass else: - substreams.append([read_date(item), item, iterstream, read_date]) + substreams.append([read_date(item), item, iterstream, read_date, tag]) while substreams: i, substream = max(enumerate(substreams), key=lambda x: x[0]) - yield substream[1] + yield substream[4], substream[1] try: item = next(substream[2]) except StopIteration: @@ -28,12 +31,56 @@ class WLFundView(TemplateView): template_name = "funding/wlfund.html" def get_context_data(self): + def add_total(total, it): + for tag, e in it: + e.total = total + if tag == 'spent': + total += e.amount + else: + total -= e.sum() + yield tag, e + ctx = super(WLFundView, self).get_context_data() offers = [o for o in Offer.objects.all() if o.state() == 'lose' and o.sum()] - amount = sum(o.sum() for o in offers) + amount = sum(o.sum() for o in offers) - sum(o.amount for o in Spent.objects.all()) print offers - #offers = (o for o in Offer.objects.all() if o.state() == 'lose' and o.sum()) ctx['amount'] = amount - ctx['log'] = mix((offers, lambda x: x.end)) + ctx['log'] = add_total(amount, mix( + (offers, lambda x: x.end, 'offer'), + (Spent.objects.all(), lambda x: x.timestamp, 'spent'), + )) + return ctx + + +class OfferDetailView(FormView): + form_class = DummyForm + template_name = "funding/offer_detail.html" + + def dispatch(self, request, slug): + self.object = get_object_or_404(Offer.public(), slug=slug) + return super(OfferDetailView, self).dispatch(request, slug) + + def get_form(self, form_class): + if self.request.method == 'POST': + return form_class(self.object, self.request.POST) + else: + return form_class(self.object) + + def get_context_data(self, *args, **kwargs): + ctx = super(OfferDetailView, self).get_context_data(*args, **kwargs) + ctx['object'] = self.object + return ctx + + def form_valid(self, form): + form.save() + return redirect(reverse("funding_thanks")) + + +class ThanksView(TemplateView): + template_name = "funding/thanks.html" + + def get_context_data(self, *args, **kwargs): + ctx = super(ThanksView, self).get_context_data(*args, **kwargs) + ctx['object'] = Offer.current() return ctx -- 2.20.1