merged upstream changes

pull/1/head
Ed Summers 2011-10-10 13:09:00 -04:00
commit c0f4ad11c3
6 changed files with 356 additions and 8 deletions

View File

@ -10,7 +10,7 @@ from regluit.core import bookloader, models
class ApiTests(TestCase): class ApiTests(TestCase):
def setUp(self): def setUp(self):
edition = bookloader.add_book(isbn='0441012035') edition = bookloader.add_by_isbn(isbn='0441012035')
campaign = models.Campaign.objects.create( campaign = models.Campaign.objects.create(
name=edition.work.title, name=edition.work.title,
work=edition.work, work=edition.work,

View File

@ -0,0 +1,155 @@
# encoding: 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 field 'Campaign.activated'
db.add_column('core_campaign', 'activated', self.gf('django.db.models.fields.DateTimeField')(null=True), keep_default=False)
# Adding field 'Campaign.suspended'
db.add_column('core_campaign', 'suspended', self.gf('django.db.models.fields.DateTimeField')(null=True), keep_default=False)
# Adding field 'Campaign.withdrawn'
db.add_column('core_campaign', 'withdrawn', self.gf('django.db.models.fields.DateTimeField')(null=True), keep_default=False)
# Adding field 'Campaign.supended_reason'
db.add_column('core_campaign', 'supended_reason', self.gf('django.db.models.fields.CharField')(max_length=10000, null=True), keep_default=False)
# Adding field 'Campaign.withdrawn_reason'
db.add_column('core_campaign', 'withdrawn_reason', self.gf('django.db.models.fields.CharField')(max_length=10000, null=True), keep_default=False)
def backwards(self, orm):
# Deleting field 'Campaign.activated'
db.delete_column('core_campaign', 'activated')
# Deleting field 'Campaign.suspended'
db.delete_column('core_campaign', 'suspended')
# Deleting field 'Campaign.withdrawn'
db.delete_column('core_campaign', 'withdrawn')
# Deleting field 'Campaign.supended_reason'
db.delete_column('core_campaign', 'supended_reason')
# Deleting field 'Campaign.withdrawn_reason'
db.delete_column('core_campaign', 'withdrawn_reason')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'core.author': {
'Meta': {'object_name': 'Author'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
'openlibrary_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'works': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'authors'", 'symmetrical': 'False', 'to': "orm['core.Work']"})
},
'core.campaign': {
'Meta': {'object_name': 'Campaign'},
'activated': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'amazon_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'deadline': ('django.db.models.fields.DateTimeField', [], {}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '10000'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
'paypal_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}),
'supended_reason': ('django.db.models.fields.CharField', [], {'max_length': '10000', 'null': 'True'}),
'suspended': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'target': ('django.db.models.fields.DecimalField', [], {'max_digits': '14', 'decimal_places': '2'}),
'withdrawn': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'withdrawn_reason': ('django.db.models.fields.CharField', [], {'max_length': '10000', 'null': 'True'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'to': "orm['core.Work']"})
},
'core.edition': {
'Meta': {'object_name': 'Edition'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'isbn_10': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}),
'isbn_13': ('django.db.models.fields.CharField', [], {'max_length': '13', 'null': 'True'}),
'openlibrary_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'publication_date': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'publisher': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'editions'", 'null': 'True', 'to': "orm['core.Work']"})
},
'core.editioncover': {
'Meta': {'object_name': 'EditionCover'},
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'covers'", 'to': "orm['core.Edition']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'openlibrary_id': ('django.db.models.fields.IntegerField', [], {})
},
'core.subject': {
'Meta': {'object_name': 'Subject'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
'works': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subjects'", 'symmetrical': 'False', 'to': "orm['core.Work']"})
},
'core.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'tagline': ('django.db.models.fields.CharField', [], {'max_length': '140', 'blank': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'})
},
'core.wishlist': {
'Meta': {'object_name': 'Wishlist'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'wishlist'", 'unique': 'True', 'to': "orm['auth.User']"}),
'works': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'wishlists'", 'symmetrical': 'False', 'to': "orm['core.Work']"})
},
'core.work': {
'Meta': {'object_name': 'Work'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'openlibrary_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
}
}
complete_apps = ['core']

View File

@ -1,10 +1,13 @@
import random import random
import datetime
from decimal import Decimal from decimal import Decimal
from django.db import models from django.db import models
from django.db.models import Q from django.db.models import Q
from django.contrib.auth.models import User from django.contrib.auth.models import User
class UnglueitError(RuntimeError):
pass
class Campaign(models.Model): class Campaign(models.Model):
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
@ -12,12 +15,78 @@ class Campaign(models.Model):
description = models.CharField(max_length=10000, null=False) description = models.CharField(max_length=10000, null=False)
target = models.DecimalField(max_digits=14, decimal_places=2) target = models.DecimalField(max_digits=14, decimal_places=2)
deadline = models.DateTimeField(null=False) deadline = models.DateTimeField(null=False)
activated = models.DateTimeField(null=True)
suspended = models.DateTimeField(null=True)
withdrawn = models.DateTimeField(null=True)
supended_reason = models.CharField(max_length=10000, null=True)
withdrawn_reason = models.CharField(max_length=10000, null=True)
paypal_receiver = models.CharField(max_length=100, null=True) paypal_receiver = models.CharField(max_length=100, null=True)
amazon_receiver = models.CharField(max_length=100, null=True) amazon_receiver = models.CharField(max_length=100, null=True)
work = models.ForeignKey("Work", related_name="campaigns") work = models.ForeignKey("Work", related_name="campaigns", null=False)
def __unicode__(self): def __unicode__(self):
try:
return u"Campaign for %s" % self.work.title return u"Campaign for %s" % self.work.title
except:
return u"Campaign %s (no associated work)" % self.name
def status(self):
"""Returns the status of the campaign
"""
now = datetime.datetime.utcnow()
if self.activated is None:
return 'INITIALIZED'
elif self.suspended is not None:
return 'SUSPENDED'
elif self.withdrawn is not None:
return 'WITHDRAWN'
elif self.deadline < now:
# calculate the total amount of money pledged/authorized
p = PaymentManager()
current_total = p.query_campaign(campaign=self,summary=True)
if current_total >= self.target:
return 'SUCCESSFUL'
else:
return 'UNSUCCESSFUL'
else:
return 'ACTIVE'
def activate(self):
status = self.status()
if status != 'INITIALIZED':
raise UnglueitError('Campaign needs to be initialized in order to be activated')
self.activated = datetime.datetime.utcnow()
self.save()
return self
def suspend(self, reason):
status = self.status()
if status != 'ACTIVE':
raise UnglueitError('Campaign needs to be active in order to be suspended')
self.suspended = datetime.datetime.utcnow()
self.supended_reason = reason
self.save()
return self
def withdraw(self, reason):
status = self.status()
if status != 'ACTIVE':
raise UnglueitError('Campaign needs to be active in order to be withdrawn')
self.withdrawn = datetime.datetime.utcnow()
self.withdrawn_reason = reason
self.save()
return self
def resume(self):
"""Change campaign status from SUSPENDED to ACTIVE. We may want to track reason for resuming and track history"""
status = self.status()
if status != 'SUSPENDED':
raise UnglueitError('Campaign needs to be suspended in order to be resumed')
self.suspended = None
self.suspended_reason = None
self.save()
return self
class Work(models.Model): class Work(models.Model):
@ -88,3 +157,4 @@ class UserProfile(models.Model):
tagline = models.CharField(max_length=140, blank=True) tagline = models.CharField(max_length=140, blank=True)
from regluit.core import signals from regluit.core import signals
from regluit.payment.manager import PaymentManager

View File

@ -1,6 +1,14 @@
from django.test import TestCase from decimal import Decimal as D
from datetime import datetime, timedelta
from django.test import TestCase
from django.utils import unittest
from django.db import IntegrityError
from regluit.payment.models import Transaction
from regluit.core.models import Campaign, Work, UnglueitError
from regluit.core import bookloader, models, search from regluit.core import bookloader, models, search
from regluit.payment.parameters import PAYMENT_TYPE_AUTHORIZATION
class TestBooks(TestCase): class TestBooks(TestCase):
@ -53,3 +61,82 @@ class SearchTests(TestCase):
def test_googlebooks_search(self): def test_googlebooks_search(self):
response = search.googlebooks_search('melville') response = search.googlebooks_search('melville')
self.assertEqual(len(response['items']), 10) self.assertEqual(len(response['items']), 10)
class CampaignTests(TestCase):
def test_required_fields(self):
# a campaign must have a target, deadline and a work
c = Campaign()
self.assertRaises(IntegrityError, c.save)
c = Campaign(target=D('1000.00'))
self.assertRaises(IntegrityError, c.save)
c = Campaign(target=D('1000.00'), deadline=datetime(2012, 1, 1))
self.assertRaises(IntegrityError, c.save)
w = Work()
w.save()
c = Campaign(target=D('1000.00'), deadline=datetime(2012, 1, 1), work=w)
c.save()
def test_campaign_status(self):
w = Work()
w.save()
# INITIALIZED
c1 = Campaign(target=D('1000.00'),deadline=datetime(2012,1,1),work=w)
c1.save()
self.assertEqual(c1.status(), 'INITIALIZED')
# ACTIVATED
c2 = Campaign(target=D('1000.00'),deadline=datetime(2012,1,1),work=w)
c2.save()
self.assertEqual(c2.status(), 'INITIALIZED')
c2.activate()
self.assertEqual(c2.status(), 'ACTIVE')
# SUSPENDED
c2.suspend(reason="for testing")
self.assertEqual(c2.status(), 'SUSPENDED')
# RESUMING
c2.resume()
self.assertEqual(c2.suspended, None)
self.assertEqual(c2.status(),'ACTIVE')
# should not let me suspend a campaign that hasn't been initialized
self.assertRaises(UnglueitError, c1.suspend, "for testing")
# UNSUCCESSFUL
c3 = Campaign(target=D('1000.00'),deadline=datetime.utcnow() - timedelta(days=1),work=w)
c3.save()
c3.activate()
self.assertEqual(c3.status(), 'UNSUCCESSFUL')
# SUCCESSFUL
c4 = Campaign(target=D('1000.00'),deadline=datetime.utcnow() - timedelta(days=1),work=w)
c4.save()
c4.activate()
t = Transaction()
t.amount = D('1234.00')
t.type = PAYMENT_TYPE_AUTHORIZATION
t.status = 'ACTIVE'
t.campaign = c4
t.save()
self.assertEqual(c4.status(), 'SUCCESSFUL')
# ACTIVE
c4.deadline = datetime.utcnow() + timedelta(days=1)
c4.save()
self.assertEqual(c4.status(), 'ACTIVE')
# WITHDRAWN
c5 = Campaign(target=D('1000.00'),deadline=datetime(2012,1,1),work=w)
c5.save()
c5.activate().withdraw('testing')
self.assertEqual(c5.status(), 'WITHDRAWN')
def suite():
testcases = [TestBooks, SearchTests, CampaignTests]
suites = unittest.TestSuite([unittest.TestLoader().loadTestsFromTestCase(testcase) for testcase in testcases])
return suites

View File

@ -108,8 +108,8 @@ class PaymentManager( object ):
authorized_list = [] authorized_list = []
if summary: if summary:
pledged_amount = 0.0 pledged_amount = D('0.00')
authorized_amount = 0.0 authorized_amount = D('0.00')
for t in pledged_list: for t in pledged_list:
for r in t.receiver_set.all(): for r in t.receiver_set.all():

View File

@ -6,11 +6,12 @@ Replace this with more appropriate tests for your application.
""" """
from django.test import TestCase from django.test import TestCase
from django.utils import unittest
from regluit.payment.manager import PaymentManager from regluit.payment.manager import PaymentManager
from regluit.payment.paypal import IPN, IPN_PAY_STATUS_ACTIVE, IPN_PAY_STATUS_COMPLETED, IPN_TXN_STATUS_COMPLETED from regluit.payment.paypal import IPN, IPN_PAY_STATUS_ACTIVE, IPN_PAY_STATUS_COMPLETED, IPN_TXN_STATUS_COMPLETED
from noseselenium.cases import SeleniumTestCaseMixin from noseselenium.cases import SeleniumTestCaseMixin
from regluit.payment.models import Transaction from regluit.payment.models import Transaction
from regluit.core.models import Campaign, Wishlist from regluit.core.models import Campaign, Wishlist, Work
from django.contrib.auth.models import User from django.contrib.auth.models import User
from regluit.payment.parameters import * from regluit.payment.parameters import *
import traceback import traceback
@ -19,7 +20,8 @@ from django.core.exceptions import ValidationError
import time import time
from selenium import selenium, webdriver from selenium import selenium, webdriver
from decimal import Decimal as D
import datetime
def loginSandbox(test, selenium): def loginSandbox(test, selenium):
@ -214,5 +216,39 @@ class AuthorizeTest(TestCase):
self.assertEqual(t.status, IPN_PAY_STATUS_ACTIVE) self.assertEqual(t.status, IPN_PAY_STATUS_ACTIVE)
class TransactionTest(TestCase):
def setUp(self):
"""
"""
pass
def testSimple(self):
"""
create a single transaction with PAYMENT_TYPE_INSTANT / COMPLETED with a $12.34 pledge and see whether the payment
manager can query and get the right amount.
"""
w = Work()
w.save()
c = Campaign(target=D('1000.00'),deadline=datetime.datetime(2012,1,1),work=w)
c.save()
t = Transaction()
t.amount = D('12.34')
t.type = PAYMENT_TYPE_AUTHORIZATION
t.status = 'ACTIVE'
t.campaign = c
t.save()
p = PaymentManager()
results = p.query_campaign(campaign=c)
self.assertEqual(results[0].amount, D('12.34'))
def suite():
#testcases = [PledgeTest, AuthorizeTest]
testcases = [TransactionTest]
suites = unittest.TestSuite([unittest.TestLoader().loadTestsFromTestCase(testcase) for testcase in testcases])
return suites