Merge branch 'relaunch' of github.com:Gluejar/regluit into relaunch
commit
839a864149
|
@ -210,6 +210,47 @@ class Campaign(models.Model):
|
||||||
except:
|
except:
|
||||||
return u"Campaign %s (no associated work)" % self.name
|
return u"Campaign %s (no associated work)" % self.name
|
||||||
|
|
||||||
|
def clone(self):
|
||||||
|
"""use a previous UNSUCCESSFUL campaign's data as the basis for a new campaign"""
|
||||||
|
if self.clonable():
|
||||||
|
old_managers= self.managers.all()
|
||||||
|
|
||||||
|
# copy custom premiums
|
||||||
|
new_premiums= self.premiums.filter(type='CU')
|
||||||
|
|
||||||
|
# setting pk to None will insert new copy http://stackoverflow.com/a/4736172/7782
|
||||||
|
self.pk = None
|
||||||
|
self.status = 'INITIALIZED'
|
||||||
|
|
||||||
|
# set deadline far in future -- presumably RH will set deadline to proper value before campaign launched
|
||||||
|
self.deadline = date_today() + timedelta(days=int(settings.UNGLUEIT_LONGEST_DEADLINE))
|
||||||
|
|
||||||
|
# allow created, activated dates to be autoset by db
|
||||||
|
self.created = None
|
||||||
|
self.name = 'copy of %s' % self.name
|
||||||
|
self.activated = None
|
||||||
|
self.update_left()
|
||||||
|
self.save()
|
||||||
|
self.managers=old_managers
|
||||||
|
|
||||||
|
# clone associated premiums
|
||||||
|
for premium in new_premiums:
|
||||||
|
premium.pk=None
|
||||||
|
premium.created = None
|
||||||
|
premium.campaign = self
|
||||||
|
premium.save()
|
||||||
|
return self
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def clonable(self):
|
||||||
|
"""campaign clonable if it's UNSUCCESSFUL and is the last campaign associated with a Work"""
|
||||||
|
|
||||||
|
if self.status == 'UNSUCCESSFUL' and self.work.last_campaign().id==self.id:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def launchable(self):
|
def launchable(self):
|
||||||
may_launch=True
|
may_launch=True
|
||||||
|
@ -341,7 +382,9 @@ class Campaign(models.Model):
|
||||||
@property
|
@property
|
||||||
def supporters_count(self):
|
def supporters_count(self):
|
||||||
# avoid transmitting the whole list if you don't need to; let the db do the count.
|
# avoid transmitting the whole list if you don't need to; let the db do the count.
|
||||||
return self.transactions().filter(status=TRANSACTION_STATUS_ACTIVE).values_list('user', flat=True).distinct().count()
|
active = self.transactions().filter(status=TRANSACTION_STATUS_ACTIVE).values_list('user', flat=True).distinct().count()
|
||||||
|
complete = self.transactions().filter(status=TRANSACTION_STATUS_COMPLETE).values_list('user', flat=True).distinct().count()
|
||||||
|
return active+complete
|
||||||
|
|
||||||
def transaction_to_recharge(self, user):
|
def transaction_to_recharge(self, user):
|
||||||
"""given a user, return the transaction to be recharged if there is one -- None otherwise"""
|
"""given a user, return the transaction to be recharged if there is one -- None otherwise"""
|
||||||
|
|
|
@ -14,7 +14,7 @@ from django.contrib.sites.models import Site
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
|
|
||||||
from regluit.payment.models import Transaction
|
from regluit.payment.models import Transaction
|
||||||
from regluit.core.models import Campaign, Work, UnglueitError, Edition, RightsHolder, Claim, Key, Ebook
|
from regluit.core.models import Campaign, Work, UnglueitError, Edition, RightsHolder, Claim, Key, Ebook, Premium
|
||||||
from regluit.core import bookloader, models, search, goodreads, librarything
|
from regluit.core import bookloader, models, search, goodreads, librarything
|
||||||
from regluit.core import isbn
|
from regluit.core import isbn
|
||||||
from regluit.payment.parameters import PAYMENT_TYPE_AUTHORIZATION
|
from regluit.payment.parameters import PAYMENT_TYPE_AUTHORIZATION
|
||||||
|
@ -388,6 +388,8 @@ class CampaignTests(TestCase):
|
||||||
|
|
||||||
w = Work()
|
w = Work()
|
||||||
w.save()
|
w.save()
|
||||||
|
w2 = Work()
|
||||||
|
w2.save()
|
||||||
# INITIALIZED
|
# INITIALIZED
|
||||||
c1 = Campaign(target=D('1000.00'),deadline=datetime(2013,1,1),work=w)
|
c1 = Campaign(target=D('1000.00'),deadline=datetime(2013,1,1),work=w)
|
||||||
c1.save()
|
c1.save()
|
||||||
|
@ -402,6 +404,8 @@ class CampaignTests(TestCase):
|
||||||
rh.save()
|
rh.save()
|
||||||
cl = Claim(rights_holder = rh, work = w, user = u, status = 'active')
|
cl = Claim(rights_holder = rh, work = w, user = u, status = 'active')
|
||||||
cl.save()
|
cl.save()
|
||||||
|
cl2 = Claim(rights_holder = rh, work = w2, user = u, status = 'active')
|
||||||
|
cl2.save()
|
||||||
c2.activate()
|
c2.activate()
|
||||||
self.assertEqual(c2.status, 'ACTIVE')
|
self.assertEqual(c2.status, 'ACTIVE')
|
||||||
# SUSPENDED
|
# SUSPENDED
|
||||||
|
@ -414,7 +418,7 @@ class CampaignTests(TestCase):
|
||||||
# should not let me suspend a campaign that hasn't been initialized
|
# should not let me suspend a campaign that hasn't been initialized
|
||||||
self.assertRaises(UnglueitError, c1.suspend, "for testing")
|
self.assertRaises(UnglueitError, c1.suspend, "for testing")
|
||||||
# UNSUCCESSFUL
|
# UNSUCCESSFUL
|
||||||
c3 = Campaign(target=D('1000.00'),deadline=now() - timedelta(days=1),work=w)
|
c3 = Campaign(target=D('1000.00'),deadline=now() - timedelta(days=1),work=w2)
|
||||||
c3.save()
|
c3.save()
|
||||||
c3.activate()
|
c3.activate()
|
||||||
self.assertEqual(c3.status, 'ACTIVE')
|
self.assertEqual(c3.status, 'ACTIVE')
|
||||||
|
@ -422,6 +426,17 @@ class CampaignTests(TestCase):
|
||||||
self.assertTrue(c3.update_status())
|
self.assertTrue(c3.update_status())
|
||||||
self.assertEqual(c3.status, 'UNSUCCESSFUL')
|
self.assertEqual(c3.status, 'UNSUCCESSFUL')
|
||||||
|
|
||||||
|
# premiums
|
||||||
|
pr1= Premium(type='CU', campaign=c3, amount=10, description='botsnack', limit=1)
|
||||||
|
pr1.save()
|
||||||
|
self.assertEqual(pr1.premium_remaining,1)
|
||||||
|
|
||||||
|
#cloning (note we changed c3 to w2 to make it clonable)
|
||||||
|
c7= c3.clone()
|
||||||
|
self.assertEqual(c7.status, 'INITIALIZED')
|
||||||
|
self.assertEqual(c7.premiums.all()[0].description , 'botsnack')
|
||||||
|
|
||||||
|
|
||||||
# SUCCESSFUL
|
# SUCCESSFUL
|
||||||
c4 = Campaign(target=D('1000.00'),deadline=now() - timedelta(days=1),work=w)
|
c4 = Campaign(target=D('1000.00'),deadline=now() - timedelta(days=1),work=w)
|
||||||
c4.save()
|
c4.save()
|
||||||
|
|
|
@ -164,6 +164,9 @@ class UserData(forms.Form):
|
||||||
return username
|
return username
|
||||||
raise forms.ValidationError(_("Your username is already "+username))
|
raise forms.ValidationError(_("Your username is already "+username))
|
||||||
|
|
||||||
|
class CloneCampaignForm(forms.Form):
|
||||||
|
campaign_id = forms.IntegerField(required = True, widget = forms.HiddenInput)
|
||||||
|
|
||||||
class OpenCampaignForm(forms.ModelForm):
|
class OpenCampaignForm(forms.ModelForm):
|
||||||
managers = AutoCompleteSelectMultipleField(
|
managers = AutoCompleteSelectMultipleField(
|
||||||
OwnerLookup,
|
OwnerLookup,
|
||||||
|
|
|
@ -208,8 +208,9 @@ Please fix the following before launching your campaign:
|
||||||
{{ form.deadline.errors }}<span style="display: none">{{ form.deadline }}</span>
|
{{ form.deadline.errors }}<span style="display: none">{{ form.deadline }}</span>
|
||||||
{% endifnotequal %}
|
{% endifnotequal %}
|
||||||
|
|
||||||
<h3>Email address</h3>
|
<h3>e-mail contact address</h3>
|
||||||
<p>Enter the email address we should contact you at for issues relating to managing this campaign.</p>
|
<p>Enter the email address where notifications about this campaign should be sent. If your campaign succeeds, this email needs to work if you want to get paid!</p>
|
||||||
|
|
||||||
|
|
||||||
<p>{{ form.paypal_receiver.errors }}{{ form.paypal_receiver }}</p>
|
<p>{{ form.paypal_receiver.errors }}{{ form.paypal_receiver }}</p>
|
||||||
|
|
||||||
|
|
|
@ -20,21 +20,33 @@
|
||||||
Any questions not covered here? Please email us at <a href="mailto:rights@gluejar.com">rights@gluejar.com</a>.
|
Any questions not covered here? Please email us at <a href="mailto:rights@gluejar.com">rights@gluejar.com</a>.
|
||||||
</div></div>
|
</div></div>
|
||||||
|
|
||||||
{% if request.user.campaigns.all %}
|
{% if campaigns %}
|
||||||
<h2>Campaigns You Manage</h2>
|
<h2>Campaigns You Manage</h2>
|
||||||
<dl>
|
<dl>
|
||||||
{% for campaign in request.user.campaigns.all %}
|
{% for campaign in campaigns %}
|
||||||
<dt>Work: <a href="{% url work work_id=campaign.work.id %}">{{campaign.work.title }}</a></dt>
|
<dt>Work: <a href="{% url work work_id=campaign.work.id %}">{{campaign.work.title }}</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<div class="work_campaigns clearfix">
|
<div class="work_campaigns clearfix">
|
||||||
<div class="campaign_info">
|
<div class="campaign_info">
|
||||||
Campaign: {{ campaign.name }}<br />
|
Campaign: {{ campaign.name }}<br />
|
||||||
Campaign status: {{ campaign.status }} <br />
|
Campaign status: {{ campaign.status }} <br />
|
||||||
Created: {{ campaign.created }}
|
Created: {{ campaign.created }}<br />
|
||||||
|
${{ campaign.current_total }} pledged of ${{ campaign.target }}, {{ campaign.supporters_count }} supporters
|
||||||
</div>
|
</div>
|
||||||
|
{% if campaign.status = 'ACTIVE' or campaign.status = 'INITIALIZED' %}
|
||||||
<div>
|
<div>
|
||||||
<a href="{% url manage_campaign campaign.id %}" class="manage">Manage This Campaign</a>
|
<a href="{% url manage_campaign campaign.id %}" class="manage">Manage This Campaign</a>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if campaign.clone_form %}
|
||||||
|
<div>
|
||||||
|
<form method="POST" action="#">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ campaign.clone_form }}{{ campaign.clone_form.errors }}
|
||||||
|
<input type="submit" name="clone" value="Clone this Campaign">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</dd>
|
</dd>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -51,7 +63,7 @@ Any questions not covered here? Please email us at <a href="mailto:rights@gluej
|
||||||
<br />Date of Claim : {{ claim.created }}
|
<br />Date of Claim : {{ claim.created }}
|
||||||
<br />Status of Claim: {{ claim.get_status_display }}
|
<br />Status of Claim: {{ claim.get_status_display }}
|
||||||
{% if claim.can_open_new %}
|
{% if claim.can_open_new %}
|
||||||
<h3>Open a campaign for this work</h3>
|
<h3>Open a blank campaign for this work</h3>
|
||||||
<form method="POST" action="#">
|
<form method="POST" action="#">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<p>Name the Campaign: {{ claim.campaign_form.name }}{{ claim.campaign_form.name.errors }}</p>
|
<p>Name the Campaign: {{ claim.campaign_form.name }}{{ claim.campaign_form.name.errors }}</p>
|
||||||
|
@ -67,6 +79,7 @@ Any questions not covered here? Please email us at <a href="mailto:rights@gluej
|
||||||
<h3>Campaigns for this work</h3>
|
<h3>Campaigns for this work</h3>
|
||||||
{% for campaign in claim.campaigns %}
|
{% for campaign in claim.campaigns %}
|
||||||
<div class="work_campaigns clearfix">
|
<div class="work_campaigns clearfix">
|
||||||
|
{% if campaign.status = 'ACTIVE' or campaign.status = 'INITIALIZED' %}
|
||||||
<div class="campaign_info">
|
<div class="campaign_info">
|
||||||
Name: Your campaign, "{{ campaign.name }}", is {{ campaign.status }}<br />
|
Name: Your campaign, "{{ campaign.name }}", is {{ campaign.status }}<br />
|
||||||
Created: {{ campaign.created }}<br />
|
Created: {{ campaign.created }}<br />
|
||||||
|
@ -81,6 +94,15 @@ Any questions not covered here? Please email us at <a href="mailto:rights@gluej
|
||||||
<a href="{% url manage_campaign campaign.id %}" class="manage">Manage This Campaign</a>
|
<a href="{% url manage_campaign campaign.id %}" class="manage">Manage This Campaign</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<div class="campaign_info">
|
||||||
|
Name: Your campaign, "{{ campaign.name }}", is {{ campaign.status }}<br />
|
||||||
|
Created: {{ campaign.created }}<br />
|
||||||
|
Manager(s): {% for user in campaign.managers.all %} <a href="{% url supporter user.username %}">{{ user.username }} </a> {% endfor %}
|
||||||
|
<br />
|
||||||
|
${{ campaign.current_total }} pledged of ${{ campaign.target }}, {{ campaign.supporters_count }} supporters
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -138,20 +160,19 @@ Any questions not covered here? Please email us at <a href="mailto:rights@gluej
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<h2>Rightsholder social media tools</h2>
|
|
||||||
|
|
||||||
Needs to be written. What would you find helpful in a social media toolkit? <a href="/feedback">Send us feedback.</a>
|
|
||||||
|
|
||||||
<h2>Rewards</h2>
|
<h2>Rewards</h2>
|
||||||
|
|
||||||
<p>Campaigns have rewards as a way to thank supporters. unglue.it includes a standard set of rewards in all campaigns. You are encouraged to add additional sweeteners to motivate people to contribute.</p>
|
<p>Campaigns can have rewards as a way to motivate and thank supporters. You are strongly encouraged to add rewards - they are given special prominence on the campaign page.</p>
|
||||||
|
|
||||||
<p>Here are the standard rewards:</p>
|
<p>What should you add as rewards? Anything you think you can reasonably deliver that will get supporters excited about the book. For example: other books, whether electronic or physical; artwork or multimedia relating to the book, its author, or its themes; in-person or online chats with the author; memorabilia.</p>
|
||||||
|
|
||||||
|
<h2>Acknowledgements</h2>
|
||||||
|
<p>Here are the standard acknowledgements. These automatically combine with your rewards. For example, if you offer a $30 reward, ungluers who pledge $30 will receive the $25 acknowledgement as well.</p>
|
||||||
<ul class="terms">
|
<ul class="terms">
|
||||||
<li><em>Any level ($1 minimum)</em> — The unglued ebook delivered to your inbox</li>
|
<li><em>Any amount</em> — The unglued ebook</li>
|
||||||
<li><em>$25</em> — Your username under "supporters" in the acknowledgements section</li>
|
<li><em>$25 and above</em> — Their name in the acknowledgements section under "supporters"</li>
|
||||||
<li><em>$50</em> — Your name & profile link under "benefactors"</li>
|
<li><em>$50 and above</em> — Their name & profile link under "benefactors"</li>
|
||||||
<li><em>$100</em> — Your name, profile link, & profile tagline under "bibliophiles"</li>
|
<li><em>$100 and above</em> — Their name, profile link, & a dedication under "bibliophiles"</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2>More Questions</h2>
|
<h2>More Questions</h2>
|
||||||
|
|
|
@ -48,7 +48,7 @@ from regluit.frontend.forms import UserData, UserEmail, ProfileForm, CampaignPle
|
||||||
from regluit.frontend.forms import RightsHolderForm, UserClaimForm, LibraryThingForm, OpenCampaignForm
|
from regluit.frontend.forms import RightsHolderForm, UserClaimForm, LibraryThingForm, OpenCampaignForm
|
||||||
from regluit.frontend.forms import getManageCampaignForm, DonateForm, CampaignAdminForm, EmailShareForm, FeedbackForm
|
from regluit.frontend.forms import getManageCampaignForm, DonateForm, CampaignAdminForm, EmailShareForm, FeedbackForm
|
||||||
from regluit.frontend.forms import EbookForm, CustomPremiumForm, EditManagersForm, EditionForm, PledgeCancelForm
|
from regluit.frontend.forms import EbookForm, CustomPremiumForm, EditManagersForm, EditionForm, PledgeCancelForm
|
||||||
from regluit.frontend.forms import getTransferCreditForm, CCForm
|
from regluit.frontend.forms import getTransferCreditForm, CCForm, CloneCampaignForm
|
||||||
from regluit.payment.manager import PaymentManager
|
from regluit.payment.manager import PaymentManager
|
||||||
from regluit.payment.models import Transaction, Account
|
from regluit.payment.models import Transaction, Account
|
||||||
from regluit.payment.parameters import TRANSACTION_STATUS_ACTIVE, TRANSACTION_STATUS_COMPLETE, TRANSACTION_STATUS_CANCELED, TRANSACTION_STATUS_ERROR, TRANSACTION_STATUS_FAILED, TRANSACTION_STATUS_INCOMPLETE, TRANSACTION_STATUS_NONE, TRANSACTION_STATUS_MODIFIED
|
from regluit.payment.parameters import TRANSACTION_STATUS_ACTIVE, TRANSACTION_STATUS_COMPLETE, TRANSACTION_STATUS_CANCELED, TRANSACTION_STATUS_ERROR, TRANSACTION_STATUS_FAILED, TRANSACTION_STATUS_INCOMPLETE, TRANSACTION_STATUS_NONE, TRANSACTION_STATUS_MODIFIED
|
||||||
|
@ -1154,7 +1154,7 @@ def rh_tools(request):
|
||||||
claim.campaigns = claim.work.campaigns.all()
|
claim.campaigns = claim.work.campaigns.all()
|
||||||
else:
|
else:
|
||||||
claim.campaigns = []
|
claim.campaigns = []
|
||||||
claim.can_open_new=True
|
claim.can_open_new=False if claim.work.last_campaign_status in ['ACTIVE','INITIALIZED'] else True
|
||||||
for campaign in claim.campaigns:
|
for campaign in claim.campaigns:
|
||||||
if campaign.status in ['ACTIVE','INITIALIZED']:
|
if campaign.status in ['ACTIVE','INITIALIZED']:
|
||||||
claim.can_open_new=False
|
claim.can_open_new=False
|
||||||
|
@ -1179,7 +1179,17 @@ def rh_tools(request):
|
||||||
claim.campaign_form = OpenCampaignForm(data={'work': claim.work, 'name': claim.work.title, 'userid': request.user.id, 'managers_1': request.user.id})
|
claim.campaign_form = OpenCampaignForm(data={'work': claim.work, 'name': claim.work.title, 'userid': request.user.id, 'managers_1': request.user.id})
|
||||||
else:
|
else:
|
||||||
claim.can_open_new=False
|
claim.can_open_new=False
|
||||||
return render(request, "rh_tools.html", {'claims': claims ,})
|
campaigns = request.user.campaigns.all()
|
||||||
|
new_campaign = None
|
||||||
|
for campaign in campaigns:
|
||||||
|
if campaign.clonable():
|
||||||
|
if request.method == 'POST' and request.POST.has_key('c%s-campaign_id'% campaign.id):
|
||||||
|
clone_form= CloneCampaignForm(data=request.POST, prefix = 'c%s' % campaign.id)
|
||||||
|
if clone_form.is_valid():
|
||||||
|
campaign.clone()
|
||||||
|
else:
|
||||||
|
campaign.clone_form= CloneCampaignForm(initial={'campaign_id':campaign.id}, prefix = 'c%s' % campaign.id)
|
||||||
|
return render(request, "rh_tools.html", {'claims': claims ,'campaigns': campaigns})
|
||||||
|
|
||||||
def rh_admin(request):
|
def rh_admin(request):
|
||||||
if not request.user.is_authenticated() :
|
if not request.user.is_authenticated() :
|
||||||
|
|
Loading…
Reference in New Issue