add donation box to homepage

pull/43/head
eric 2017-02-13 13:33:26 -05:00
parent 0cedaa84bd
commit 417f9eac58
17 changed files with 181 additions and 40 deletions

View File

@ -932,10 +932,6 @@ class Campaign(models.Model):
return countdown
@property
def deadline_or_now(self):
return self.deadline if self.deadline else now()
@classmethod
def latest_ending(cls):
return timedelta(days=int(settings.UNGLUEIT_LONGEST_DEADLINE)) + now()

View File

@ -97,6 +97,7 @@ def create_notice_types( **kwargs):
notification.create_notice_type("purchase_got_gift", _("Your gift was received."), _("The ebook you sent as a gift has been redeemed."))
notification.create_notice_type("purchase_gift_waiting", _("Your gift is waiting."), _("Please claim your ebook."))
notification.create_notice_type("purchase_notgot_gift", _("Your gift wasn't received."), _("The ebook you sent as a gift has not yet been redeemed."))
notification.create_notice_type("donation", _("Your donation was processed."), _("Thank you, your generous donation has been processed."))
signals.post_syncdb.connect(create_notice_types, sender=notification)
@ -161,7 +162,14 @@ def handle_transaction_charged(sender,transaction=None, **kwargs):
return
transaction._current_total = None
context = {'transaction':transaction,'current_site':Site.objects.get_current()}
if transaction.campaign.type is REWARDS:
if not transaction.campaign:
if transaction.user:
notification.send([transaction.user], "donation", context, True)
elif transaction.receipt:
from regluit.core.tasks import send_mail_task
message = render_to_string("notification/donation/full.txt", context )
send_mail_task.delay('unglue.it donation confirmation', message, 'notices@gluejar.com', [transaction.receipt])
elif transaction.campaign.type is REWARDS:
notification.send([transaction.user], "pledge_charged", context, True)
elif transaction.campaign.type is BUY2UNGLUE:
# provision the book
@ -216,7 +224,7 @@ def handle_transaction_failed(sender,transaction=None, **kwargs):
return
# window for recharging
recharge_deadline = transaction.campaign.deadline_or_now + datetime.timedelta(settings.RECHARGE_WINDOW)
recharge_deadline = transaction.deadline_or_now + datetime.timedelta(settings.RECHARGE_WINDOW)
notification.send([transaction.user], "pledge_failed", {
'transaction':transaction,

View File

@ -769,6 +769,15 @@ class CampaignThanksForm(forms.Form):
def trans_extra(self):
pe = PledgeExtra( anonymous=self.cleaned_data['anonymous'] )
class DonationForm(forms.Form):
amount = forms.DecimalField(
required = True,
min_value=D('1.00'),
max_value=D('20000.00'),
decimal_places=2,
label="Donation Amount",
)
class CampaignPledgeForm(forms.Form):
preapproval_amount = forms.DecimalField(

View File

@ -193,6 +193,21 @@ function put_un_in_cookie2(){
</div>
</div>
{% endif %}
<div class="jsmodule">
<h3 class="module-title">Donate!</h3>
<div class="jsmod-content">
<div>Please help support Unglue.it by making a tax-deductible donation to the Free Ebook Foundation.</div>
<form class="askform" method="POST" action="{% url 'newdonation' %}">
<div class="donate_amount">
<label>Amount ($): </label><input id="amount" max="20000.00" min="1.00" name="amount" step="0.01" type="number" value="10.00" class="donate"></div>
<div class="button">
<input name="pledge" type="submit" value="Donate" id="donatesubmit" class="donate" />
</div>
</form>
</div>
</div>
<div class="jsmodule">
<h3 class="module-title">News</h3>
<div class="jsmod-content">

View File

@ -0,0 +1,9 @@
{% load humanize %}{% ifequal transaction.host 'credit' %}Your Unglue.it transaction has completed and ${{transaction.max_amount|default:"0"}} has been deducted from your Unglue.it credit balance. You have ${{transaction.user.credit.available|default:"0"}} of credit left. {% else %}{% if transaction.max_amount > transaction.amount %}Your transaction for ${{transaction.max_amount|default:"0"}} has completed. Your credit card has been charged ${{transaction.amount}} and the rest has been deducted from your unglue.it credit balance. You have ${{transaction.user.credit.available|default:"0"}} of credit left. {% else %}Your Unglue.it credit card transaction has completed and your credit card has been charged ${{ transaction.amount|default:"0" }}. {% endif %}{% endifequal %}
Your donation of ${{transaction.max_amount|default:"0"}} to the Free Ebook Foundation will help us make free ebooks of all types more accessible for those that need them. The Free Ebook Foundation is a US 501(c)3 non-profit organization. Our tax ID number is 61-1767266. Your gift is tax deductible to the full extent provided by the law.
For more information about the Free Ebook Foundation, visit http://ebookfoundation.org/
Thank you again for your generous support.
Eric Hellman and the Unglue.it team

View File

@ -0,0 +1,33 @@
{% extends 'notification/notice_template.html' %}
{% load humanize %}
{% block comments_book %}
{% endblock %}
{% block comments_graphical %}
{% ifequal transaction.host 'credit' %}
Your Unglue.it transaction has completed and ${{transaction.max_amount|floatformat:2|intcomma}} has been deducted from your Unglue.it credit balance.
You have ${{transaction.user.credit.available|default:"0"}} of credit left.
{% else %}
{% if transaction.max_amount > transaction.amount %}
Your transaction for ${{transaction.max_amount|floatformat:2|intcomma}} has completed.
Your credit card has been charged ${{transaction.amount}} and the
rest has been deducted from your unglue.it credit balance.
You have ${{transaction.user.credit.available|intcomma}} of credit left.
{% else %}
Your Unglue.it credit card transaction has completed and your credit card has been charged ${{ transaction.amount|floatformat:2|intcomma }}.
{% endif %}
{% endifequal %}
{% endblock %}
{% block comments_textual %}
<p>Your donation of ${{transaction.max_amount|default:"0"}} to the Free Ebook Foundation will help us make free ebooks of all types more accessible for those that need them. The Free Ebook Foundation is a US 501(c)3 non-profit organization. Our tax ID number is 61-1767266. Your gift is tax deductible to the full extent provided by the law.<p>
<p>For more information about the Free Ebook Foundation, visit <a href="http://ebookfoundation.org/ ">our website</a>.
</p>
<p>Thank you again for your support.
</p>
<p>Eric Hellman and the Unglue.it team
</p>
{% endblock %}

View File

@ -0,0 +1 @@
You have donated ${{transaction.amount}} to the Free Ebook Foundation.

View File

@ -28,6 +28,9 @@
<div class="clearfix">
<h2 class="thank-you">Thank you!</h2>
{% if not campaign %}
<p class="pledge_complete">You've just donated ${{ transaction.amount|floatformat:2|intcomma }} to the <a href="http://ebookfoundation.org">Free Ebook Foundation</a></p>
{% endif %}
{% ifequal campaign.type 1 %}
<p class="pledge_complete">You've just {% if modified %}modified your pledge for{% else %}pledged{% endif %} ${{ transaction.amount|floatformat:2|intcomma }} to <I><a href="{% url 'work' work.id %}">{{ work.title }}</a></I>. If it reaches its goal of ${{ campaign.target|intcomma }} by {{ campaign.deadline|date:"M d Y"}}, it will be unglued for all to enjoy.</p>
{% endifequal %}
@ -59,15 +62,22 @@
{% include "trans_summary.html" %}
</div>
<p class="pledge_complete">You can help even more by sharing this campaign with your friends:</p>
<p class="pledge_complete">You can help even more by sharing this with your friends:</p>
{% if campaign %}
<div id="widgetcode">Copy/paste this into your site:<br /><textarea rows="7" cols="22">&lt;iframe src="https://{{request.META.HTTP_HOST}}/api/widget/{{work.first_isbn_13}}/" width="152" height="325" frameborder="0"&gt;&lt;/iframe&gt;</textarea></div>
<ul class="social menu pledge">
<a href="https://www.facebook.com/sharer.php?u=https://{{ site.domain }}{% url 'work' work.id|urlencode:"" %}"><li class="facebook first"><span>Facebook</span></li></a>
<a href="https://twitter.com/intent/tweet?url=https://{{ site.domain }}{% url 'work' work.id|urlencode:"" %}&amp;text=I%20just%20supported%20{{ work.title|urlencode }}%20at%20%40unglueit.%20Will%20you%20join%20me%3F"><li class="twitter"><span>Twitter</span></li></a>
<a href="https://twitter.com/intent/tweet?url=https://{{ site.domain }}{% url 'work' work.id|urlencode:"" %}&amp;text=I%20just%20supported%20{{ work.title|urlencode }}%20at%20%40unglue.it.%20Will%20you%20join%20me%3F"><li class="twitter"><span>Twitter</span></li></a>
{% if request.user.is_authenticated %}<a href="{% url 'emailshare' 'pledged' %}?next={% url 'work' work.id|urlencode:"" %}"><li class="email"><span>Email</span></li></a>{% endif%}
<a href="#" id="embed"><li class="embed"><span>Embed</span></li></a>
</ul>
{% else %}
<ul class="social menu pledge">
<a href="https://www.facebook.com/sharer.php?u=http://ebookfoundation.org"><li class="facebook first"><span>Facebook</span></li></a>
<a href="https://twitter.com/intent/tweet?url=http://ebookfoundation.org&amp;text=I%20just%20supported%20The%20Free%20Ebook%20Foundation.%20Will%20you%20join%20me%3F"><li class="twitter"><span>Twitter</span></li></a>
</ul>
{% endif %}
</div>

View File

@ -23,7 +23,7 @@
{% endif %}
</ul>
{% endifequal %}
{% ifequal transaction.campaign.type 2 %}
{% if transaction.campaign.type == 2 or not transaction.campaign %}
{% ifequal transaction.host 'credit' %}
Amount: ${{transaction.max_amount|floatformat:2|intcomma}}.<br />
This amount has been deducted from your Unglue.it credit balance.<br />
@ -38,10 +38,13 @@
This amount has been charged to your credit card.<br />
{% endif %}
{% endifequal %}
{% if transaction.campaign %}
License type: {{ transaction.offer.get_license_display }}<br />
{% ifequal transaction.offer.license 2 %}
Receiving library: {{ transaction.extra.library_id|libname }}<br />
Number of copies: {{ transaction.extra.copies }}
{% endifequal %}
{% endifequal %}
{% endif %}
{% endif %}
</div>

View File

@ -101,6 +101,7 @@ urlpatterns = [
url(r"^fund/complete/$", views.FundCompleteView.as_view(), name="pledge_complete"),
url(r"^pledge/modified/$", login_required(views.PledgeModifiedView.as_view()), name="pledge_modified"),
url(r"^pledge/modify/(?P<work_id>\d+)$", login_required(views.PledgeView.as_view()), name="pledge_modify"),
url(r"^payment/donation/new$", csrf_exempt(views.NewDonationView.as_view()), name="newdonation" ),
url(r"^payment/fund/(?P<t_id>\d+)$", views.FundView.as_view(), name="fund" ),
url(r"^pledge/recharge/(?P<work_id>\d+)$", login_required(views.PledgeRechargeView.as_view()), name="pledge_recharge"),
url(r"^purchase/(?P<work_id>\d+)/$", login_required(views.PurchaseView.as_view(),login_url='/accounts/login/purchase/'), name="purchase"),

View File

@ -110,6 +110,7 @@ from regluit.frontend.forms import (
SubjectSelectForm,
MapSubjectForm,
SurveyForm,
DonationForm,
)
from regluit.payment import baseprocessor, stripelib
@ -124,7 +125,8 @@ from regluit.payment.parameters import (
TRANSACTION_STATUS_NONE,
TRANSACTION_STATUS_MODIFIED,
PAYMENT_TYPE_AUTHORIZATION,
PAYMENT_HOST_NONE
PAYMENT_HOST_NONE,
COMPANY_TITLE
)
from regluit.utils.localdatetime import now, date_today
@ -240,7 +242,7 @@ def home(request, landing=False):
'-submit_date'
)[:10]
latest_pledges = Transaction.objects.filter(
anonymous=False
anonymous=False, campaign__isnull=False
).exclude(
type=0 #incomplete
).only(
@ -1396,6 +1398,22 @@ class PurchaseView(PledgeView):
logger.error("Attempt to produce transaction id {0} failed".format(t.id))
return HttpResponse("Our attempt to enable your transaction failed. We have logged this error.")
class NewDonationView(FormView):
template_name = "fund_the_pledge.html"
form_class = DonationForm
def form_valid(self, form):
p = PaymentManager()
t, url = p.process_transaction('USD', form.cleaned_data["amount"],
user = self.request.user,
paymentReason="Donation to {}".format(COMPANY_TITLE),
)
if url:
return HttpResponseRedirect(url)
else:
logger.error("Attempt to produce transaction id {0} failed".format(t.id))
return HttpResponse("Our attempt to set up your donation failed. We have logged this problem.")
class FundView(FormView):
template_name = "fund_the_pledge.html"
transaction = None
@ -1411,30 +1429,32 @@ class FundView(FormView):
def get_form_kwargs(self):
kwargs = super(FundView, self).get_form_kwargs()
#assert self.request.user.is_authenticated()
if self.transaction is None:
self.transaction = get_object_or_404(Transaction, id=self.kwargs["t_id"])
if self.transaction.campaign.type == REWARDS:
self.action = 'pledge'
elif self.transaction.campaign.type == THANKS:
self.action = 'contribution'
else:
self.action = 'purchase'
if kwargs.has_key('data'):
data = kwargs['data'].copy()
kwargs['data'] = data
else:
data = {}
kwargs['initial'] = data
t_id=self.kwargs["t_id"]
if self.transaction is None:
self.transaction = get_object_or_404(Transaction, id=t_id)
if not self.transaction.campaign:
self.action = 'donation'
elif self.transaction.campaign.type == REWARDS:
self.action = 'pledge'
elif self.transaction.campaign.type == THANKS:
self.action = 'contribution'
else:
self.action = 'purchase'
data.update(
{'preapproval_amount':self.transaction.needed_amount,
'username':self.request.user.username if self.request.user.is_authenticated else None,
'work_id':self.transaction.campaign.work.id,
'title':self.transaction.campaign.work.title}
'username':self.request.user.username if self.request.user.is_authenticated() else None,
'work_id':self.transaction.campaign.work.id if self.transaction.campaign else None,
'title':self.transaction.campaign.work.title if self.transaction.campaign else COMPANY_TITLE}
)
return kwargs
@ -1454,7 +1474,14 @@ class FundView(FormView):
self.transaction.host = settings.PAYMENT_PROCESSOR
return_url = "%s?tid=%s" % (reverse('pledge_complete'), self.transaction.id)
if self.transaction.campaign.type == THANKS and self.transaction.user == None:
if not self.transaction.campaign:
if self.request.user.is_authenticated():
self.transaction.user = self.request.user
# if there's an email address, put it in the receipt column, so far unused.
self.transaction.receipt = form.cleaned_data.get("email", None)
t, url = p.charge(self.transaction, return_url = return_url, token=stripe_token)
elif self.transaction.campaign.type == THANKS and self.transaction.user == None:
#anonymous user, just charge the card!
if self.request.user.is_authenticated():
self.transaction.user = self.request.user
@ -1609,6 +1636,8 @@ class FundCompleteView(TemplateView):
context = self.get_context_data(**kwargs)
if self.transaction:
if not self.transaction.campaign:
return self.render_to_response(context)
if self.transaction.campaign.type == THANKS:
return DownloadView.as_view()(request, work=self.transaction.campaign.work)
@ -1626,7 +1655,7 @@ class FundCompleteView(TemplateView):
def user_is_ok(self):
if not self.transaction:
return False
if self.transaction.campaign.type == THANKS and self.transaction.user == None:
if (not self.transaction.campaign or self.transaction.campaign.type == THANKS) and self.transaction.user == None:
# to handle anonymous donors- leakage not an issue
return True
else:

View File

@ -694,7 +694,10 @@ class PaymentManager( object ):
the redirect url will be None
'''
# set the expiry date based on the campaign deadline
expiry = campaign.deadline_or_now + timedelta( days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN )
if campaign and campaign.deadline:
expiry = campaign.deadline + timedelta(days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN)
else:
expiry = now() + timedelta(days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN)
t = Transaction.create(amount=0,
host = host,
@ -841,7 +844,7 @@ class PaymentManager( object ):
else:
# cancel old transaction, send user to choose new payment path
# set the expiry date based on the campaign deadline
expiry = transaction.campaign.deadline_or_now + timedelta( days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN )
expiry = transaction.deadline_or_now + timedelta( days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN )
t = Transaction.create(amount=0,
max_amount=amount,
currency=transaction.currency,
@ -857,7 +860,7 @@ class PaymentManager( object ):
elif requires_explicit_preapprovals and (amount > transaction.max_amount or expiry != transaction.date_expired):
# set the expiry date based on the campaign deadline
expiry = transaction.campaign.deadline_or_now + timedelta( days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN )
expiry = transaction.deadline_or_now + timedelta( days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN )
# Start a new transaction for the new amount
t = Transaction.create(amount=amount,

View File

@ -121,6 +121,13 @@ class Transaction(models.Model):
else:
return 3
@property
def deadline_or_now(self):
if self.campaign and self.campaign.deadline:
return self.campaign.deadline
else:
return now()
@property
def needed_amount(self):
if self.user == None or self.user.is_anonymous():
@ -487,7 +494,7 @@ class Account(models.Model):
pm = PaymentManager()
for transaction in transactions_to_recharge:
# check whether we are still within the window to recharge
if (now() - transaction.campaign.deadline_or_now) < datetime.timedelta(settings.RECHARGE_WINDOW):
if (now() - transaction.deadline_or_now) < datetime.timedelta(settings.RECHARGE_WINDOW):
logger.info("Recharging transaction {0} w/ status {1}".format(transaction.id, transaction.status))
pm.execute_transaction(transaction, [])

View File

@ -51,3 +51,5 @@ TRANSACTION_STATUS_FAILED = 'Failed'
# Transaction written off -- unable to successfully be charged after campaign succeeded
TRANSACTION_STATUS_WRITTEN_OFF = 'Written-Off'
COMPANY_TITLE = 'Free Ebook Foundation'

View File

@ -740,7 +740,7 @@ class Processor(baseprocessor.Processor):
description=json.dumps({"t.id":transaction.id,
"email":transaction.user.email if transaction.user else transaction.receipt,
"cus.id":customer_id,
"tc.id": transaction.campaign.id,
"tc.id": transaction.campaign.id if transaction.campaign else '0',
"amount": float(transaction.amount)}))
except stripe.StripeError as e:
# what to record in terms of errors? (error log?)

File diff suppressed because one or more lines are too long

View File

@ -71,19 +71,31 @@
width:90%;
outline: none;
padding-left: 16px;
font-size: @font-size-larger;
}
input.signup {
border: medium none;
color: #FFF;
cursor: pointer;
display: inline-block;
font-size: @font-size-default;
overflow: hidden;
padding: 0 31px 0 11px;
width: 111px;
margin-bottom: 10px;
}
input.donate {
cursor: pointer;
display: inline-block;
overflow: hidden;
padding: 0 31px 0 11px;
width: 50%;
}
.donate_amount {
text-align: center;
}
div {
padding:0px;
@ -94,13 +106,16 @@
div.button {
padding-top:10px;
text-align: center;
color: #FFF;
}
#donatesubmit {
font-size: @font-size-larger;
}
label {
width:100%;
display:block;
clear:both;
padding:10px 0 5px 16px;
padding:10px 0 5px 0;
}
}