add in credi processing; overhaul the PledgeView forms and partition authorize fn in Manager
also removed unused target, lists, ack-link,pull/1/head
parent
f299d9ecf7
commit
94270f33c6
|
@ -0,0 +1,250 @@
|
||||||
|
# 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 model 'Badge'
|
||||||
|
# first drop tables created by syncdb
|
||||||
|
db.create_table('core_badge', (
|
||||||
|
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||||
|
('name', self.gf('django.db.models.fields.CharField')(max_length=72, blank=True)),
|
||||||
|
('description', self.gf('django.db.models.fields.TextField')(default='', null=True)),
|
||||||
|
))
|
||||||
|
db.send_create_signal('core', ['Badge'])
|
||||||
|
|
||||||
|
# Adding M2M table for field badges on 'UserProfile'
|
||||||
|
db.create_table('core_userprofile_badges', (
|
||||||
|
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||||
|
('userprofile', models.ForeignKey(orm['core.userprofile'], null=False)),
|
||||||
|
('badge', models.ForeignKey(orm['core.badge'], null=False))
|
||||||
|
))
|
||||||
|
db.create_unique('core_userprofile_badges', ['userprofile_id', 'badge_id'])
|
||||||
|
|
||||||
|
|
||||||
|
def backwards(self, orm):
|
||||||
|
|
||||||
|
# Deleting model 'Badge'
|
||||||
|
db.delete_table('core_badge')
|
||||||
|
|
||||||
|
# Removing M2M table for field badges on 'UserProfile'
|
||||||
|
db.delete_table('core_userprofile_badges')
|
||||||
|
|
||||||
|
|
||||||
|
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(2012, 8, 31, 2, 9, 51, 31703)'}),
|
||||||
|
'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(2012, 8, 31, 2, 9, 51, 31561)'}),
|
||||||
|
'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'}),
|
||||||
|
'editions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'authors'", 'symmetrical': 'False', 'to': "orm['core.Edition']"}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '500'})
|
||||||
|
},
|
||||||
|
'core.badge': {
|
||||||
|
'Meta': {'object_name': 'Badge'},
|
||||||
|
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '72', 'blank': 'True'})
|
||||||
|
},
|
||||||
|
'core.campaign': {
|
||||||
|
'Meta': {'object_name': 'Campaign'},
|
||||||
|
'activated': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||||
|
'amazon_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'deadline': ('django.db.models.fields.DateTimeField', [], {}),
|
||||||
|
'description': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
|
||||||
|
'details': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'null': 'True', 'to': "orm['core.Edition']"}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'left': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}),
|
||||||
|
'license': ('django.db.models.fields.CharField', [], {'default': "'CC BY-NC-ND'", 'max_length': '255'}),
|
||||||
|
'managers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'campaigns'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
|
||||||
|
'paypal_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||||
|
'status': ('django.db.models.fields.CharField', [], {'default': "'INITIALIZED'", 'max_length': '15', 'null': 'True'}),
|
||||||
|
'target': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}),
|
||||||
|
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.campaignaction': {
|
||||||
|
'Meta': {'object_name': 'CampaignAction'},
|
||||||
|
'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['core.Campaign']"}),
|
||||||
|
'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'type': ('django.db.models.fields.CharField', [], {'max_length': '15'})
|
||||||
|
},
|
||||||
|
'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(2012, 8, 31, 2, 9, 50, 804173)', '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'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'task_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'null': 'True', 'to': "orm['auth.User']"})
|
||||||
|
},
|
||||||
|
'core.claim': {
|
||||||
|
'Meta': {'object_name': 'Claim'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'rights_holder': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.RightsHolder']"}),
|
||||||
|
'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '7'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['auth.User']"}),
|
||||||
|
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.ebook': {
|
||||||
|
'Meta': {'object_name': 'Ebook'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ebooks'", 'to': "orm['core.Edition']"}),
|
||||||
|
'format': ('django.db.models.fields.CharField', [], {'max_length': '25'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||||
|
'rights': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||||
|
'unglued': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'url': ('django.db.models.fields.URLField', [], {'max_length': '1024'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'})
|
||||||
|
},
|
||||||
|
'core.edition': {
|
||||||
|
'Meta': {'object_name': 'Edition'},
|
||||||
|
'cover_image': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'public_domain': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'publication_date': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'publisher': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'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.identifier': {
|
||||||
|
'Meta': {'unique_together': "(('type', 'value'),)", 'object_name': 'Identifier'},
|
||||||
|
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'identifiers'", 'null': 'True', 'to': "orm['core.Edition']"}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'type': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
|
||||||
|
'value': ('django.db.models.fields.CharField', [], {'max_length': '31'}),
|
||||||
|
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'identifiers'", 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.key': {
|
||||||
|
'Meta': {'object_name': 'Key'},
|
||||||
|
'encrypted_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
|
||||||
|
},
|
||||||
|
'core.premium': {
|
||||||
|
'Meta': {'object_name': 'Premium'},
|
||||||
|
'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '0'}),
|
||||||
|
'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'premiums'", 'null': 'True', 'to': "orm['core.Campaign']"}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'description': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'limit': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'type': ('django.db.models.fields.CharField', [], {'max_length': '2'})
|
||||||
|
},
|
||||||
|
'core.rightsholder': {
|
||||||
|
'Meta': {'object_name': 'RightsHolder'},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'email': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rights_holder'", 'to': "orm['auth.User']"}),
|
||||||
|
'rights_holder_name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||||
|
},
|
||||||
|
'core.subject': {
|
||||||
|
'Meta': {'ordering': "['name']", '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', [], {'unique': 'True', 'max_length': '200'}),
|
||||||
|
'works': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subjects'", 'symmetrical': 'False', 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.userprofile': {
|
||||||
|
'Meta': {'object_name': 'UserProfile'},
|
||||||
|
'badges': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'holders'", 'symmetrical': 'False', 'to': "orm['core.Badge']"}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'facebook_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
|
||||||
|
'goodreads_auth_secret': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'goodreads_auth_token': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'goodreads_user_id': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'goodreads_user_link': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'goodreads_user_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'home_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '31', 'blank': 'True'}),
|
||||||
|
'pic_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||||
|
'tagline': ('django.db.models.fields.CharField', [], {'max_length': '140', 'blank': 'True'}),
|
||||||
|
'twitter_id': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}),
|
||||||
|
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"})
|
||||||
|
},
|
||||||
|
'core.waswork': {
|
||||||
|
'Meta': {'object_name': 'WasWork'},
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'moved': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}),
|
||||||
|
'was': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}),
|
||||||
|
'work': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.wishes': {
|
||||||
|
'Meta': {'object_name': 'Wishes', 'db_table': "'core_wishlist_works'"},
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'source': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}),
|
||||||
|
'wishlist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Wishlist']"}),
|
||||||
|
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'wishes'", 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'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', 'through': "orm['core.Wishes']", 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.work': {
|
||||||
|
'Meta': {'ordering': "['title']", 'object_name': 'Work'},
|
||||||
|
'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'}),
|
||||||
|
'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}),
|
||||||
|
'num_wishes': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'openlibrary_lookup': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||||
|
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
complete_apps = ['core']
|
|
@ -296,16 +296,15 @@ class CampaignPledgeForm(forms.Form):
|
||||||
)
|
)
|
||||||
anonymous = forms.BooleanField(required=False, label=_("Don't display my name in the acknowledgements"))
|
anonymous = forms.BooleanField(required=False, label=_("Don't display my name in the acknowledgements"))
|
||||||
ack_name = forms.CharField(required=False, max_length=64, label=_("What name should we display?"))
|
ack_name = forms.CharField(required=False, max_length=64, label=_("What name should we display?"))
|
||||||
ack_link = forms.URLField(required=False, label=_("Your web site:"))
|
|
||||||
ack_dedication = forms.CharField(required=False, max_length=140, label=_("Your dedication:"))
|
ack_dedication = forms.CharField(required=False, max_length=140, label=_("Your dedication:"))
|
||||||
|
|
||||||
premium_id = forms.IntegerField(required=False)
|
premium_id = forms.IntegerField(required=False)
|
||||||
|
|
||||||
def clean_preapproval_amount(self):
|
def clean_preapproval_amount(self):
|
||||||
data = self.cleaned_data['preapproval_amount']
|
preapproval_amount = self.cleaned_data['preapproval_amount']
|
||||||
if data is None:
|
if preapproval_amount is None:
|
||||||
raise forms.ValidationError(_("Please enter a pledge amount."))
|
raise forms.ValidationError(_("Please enter a pledge amount."))
|
||||||
return data
|
return preapproval_amount
|
||||||
|
|
||||||
# should we do validation on the premium_id here?
|
# should we do validation on the premium_id here?
|
||||||
# can see whether it corresponds to a real premium -- do that here?
|
# can see whether it corresponds to a real premium -- do that here?
|
||||||
|
@ -317,11 +316,6 @@ class CampaignPledgeForm(forms.Form):
|
||||||
try:
|
try:
|
||||||
preapproval_amount = cleaned_data.get("preapproval_amount")
|
preapproval_amount = cleaned_data.get("preapproval_amount")
|
||||||
premium_id = int(cleaned_data.get("premium_id"))
|
premium_id = int(cleaned_data.get("premium_id"))
|
||||||
premium_amount = Premium.objects.get(id=premium_id).amount
|
|
||||||
logger.info("preapproval_amount: {0}, premium_id: {1}, premium_amount:{2}".format(preapproval_amount, premium_id, premium_amount))
|
|
||||||
if preapproval_amount < premium_amount:
|
|
||||||
logger.info("raising form validating error")
|
|
||||||
raise forms.ValidationError(_("Sorry, you must pledge at least $%s to select that premium." % (premium_amount)))
|
|
||||||
try:
|
try:
|
||||||
premium= Premium.objects.get(id=premium_id)
|
premium= Premium.objects.get(id=premium_id)
|
||||||
if premium.limit>0:
|
if premium.limit>0:
|
||||||
|
@ -329,6 +323,11 @@ class CampaignPledgeForm(forms.Form):
|
||||||
raise forms.ValidationError(_("Sorry, that premium is fully subscribed."))
|
raise forms.ValidationError(_("Sorry, that premium is fully subscribed."))
|
||||||
except Premium.DoesNotExist:
|
except Premium.DoesNotExist:
|
||||||
raise forms.ValidationError(_("Sorry, that premium is not valid."))
|
raise forms.ValidationError(_("Sorry, that premium is not valid."))
|
||||||
|
premium_amount = premium.amount
|
||||||
|
logger.info("preapproval_amount: {0}, premium_id: {1}, premium_amount:{2}".format(preapproval_amount, premium_id, premium_amount))
|
||||||
|
if preapproval_amount < premium_amount:
|
||||||
|
logger.info("raising form validating error")
|
||||||
|
raise forms.ValidationError(_("Sorry, you must pledge at least $%s to select that premium." % (premium_amount)))
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
if isinstance(e, forms.ValidationError):
|
if isinstance(e, forms.ValidationError):
|
||||||
|
|
|
@ -108,6 +108,8 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="cancel_notice">
|
||||||
|
{% if faqmenu == 'modify' %}We hope you won't, but of course you're also free to <a href="{% url pledge_cancel campaign_id=work.last_campaign.id %}">cancel your pledge</a>.{% endif %}</div>
|
||||||
<div id="pass_supporter_name" style="display: none;">{{ request.user.username }}</div>
|
<div id="pass_supporter_name" style="display: none;">{{ request.user.username }}</div>
|
||||||
{% if transaction.ack_name %}
|
{% if transaction.ack_name %}
|
||||||
<div id="pass_ack_name" style="display: none;">{{ transaction.ack_name }}</div>
|
<div id="pass_ack_name" style="display: none;">{{ transaction.ack_name }}</div>
|
||||||
|
|
|
@ -7,7 +7,7 @@ from django.conf import settings
|
||||||
|
|
||||||
from regluit.core.feeds import SupporterWishlistFeed
|
from regluit.core.feeds import SupporterWishlistFeed
|
||||||
from regluit.core.models import Campaign
|
from regluit.core.models import Campaign
|
||||||
from regluit.frontend.views import GoodreadsDisplayView, LibraryThingView, PledgeView, PledgeCompleteView, PledgeModifyView, PledgeCancelView, PledgeNeverMindView, PledgeRechargeView, FAQView
|
from regluit.frontend.views import GoodreadsDisplayView, LibraryThingView, PledgeView, PledgeCompleteView, PledgeCancelView, PledgeRechargeView, FAQView
|
||||||
from regluit.frontend.views import CampaignListView, DonateView, WorkListView, UngluedListView, InfoPageView, InfoLangView, DonationView
|
from regluit.frontend.views import CampaignListView, DonateView, WorkListView, UngluedListView, InfoPageView, InfoLangView, DonationView
|
||||||
|
|
||||||
urlpatterns = patterns(
|
urlpatterns = patterns(
|
||||||
|
@ -55,8 +55,7 @@ urlpatterns = patterns(
|
||||||
url(r"^pledge/(?P<work_id>\d+)/$", login_required(PledgeView.as_view()), name="pledge"),
|
url(r"^pledge/(?P<work_id>\d+)/$", login_required(PledgeView.as_view()), name="pledge"),
|
||||||
url(r"^pledge/cancel/(?P<campaign_id>\d+)$", login_required(PledgeCancelView.as_view()), name="pledge_cancel"),
|
url(r"^pledge/cancel/(?P<campaign_id>\d+)$", login_required(PledgeCancelView.as_view()), name="pledge_cancel"),
|
||||||
url(r"^pledge/complete/$", login_required(PledgeCompleteView.as_view()), name="pledge_complete"),
|
url(r"^pledge/complete/$", login_required(PledgeCompleteView.as_view()), name="pledge_complete"),
|
||||||
url(r"^pledge/nevermind/$", login_required(PledgeNeverMindView.as_view()), name="pledge_nevermind"),
|
url(r"^pledge/modify/(?P<work_id>\d+)$", login_required(PledgeView.as_view()), name="pledge_modify"),
|
||||||
url(r"^pledge/modify/(?P<work_id>\d+)$", login_required(PledgeModifyView.as_view()), name="pledge_modify"),
|
|
||||||
url(r"^pledge/recharge/(?P<work_id>\d+)$", login_required(PledgeRechargeView.as_view()), name="pledge_recharge"),
|
url(r"^pledge/recharge/(?P<work_id>\d+)$", login_required(PledgeRechargeView.as_view()), name="pledge_recharge"),
|
||||||
url(r"^subjects/$", "subjects", name="subjects"),
|
url(r"^subjects/$", "subjects", name="subjects"),
|
||||||
url(r"^librarything/$", LibraryThingView.as_view(), name="librarything"),
|
url(r"^librarything/$", LibraryThingView.as_view(), name="librarything"),
|
||||||
|
|
|
@ -50,8 +50,8 @@ from regluit.frontend.forms import EbookForm, CustomPremiumForm, EditManagersFor
|
||||||
from regluit.frontend.forms import getTransferCreditForm
|
from regluit.frontend.forms import getTransferCreditForm
|
||||||
from regluit.payment.manager import PaymentManager
|
from regluit.payment.manager import PaymentManager
|
||||||
from regluit.payment.models import Transaction
|
from regluit.payment.models import Transaction
|
||||||
from regluit.payment.parameters import TARGET_TYPE_CAMPAIGN, TARGET_TYPE_DONATION, PAYMENT_TYPE_AUTHORIZATION
|
|
||||||
from regluit.payment.parameters import TRANSACTION_STATUS_ACTIVE, TRANSACTION_STATUS_COMPLETE, TRANSACTION_STATUS_CANCELED, TRANSACTION_STATUS_ERROR, TRANSACTION_STATUS_FAILED, TRANSACTION_STATUS_INCOMPLETE
|
from regluit.payment.parameters import TRANSACTION_STATUS_ACTIVE, TRANSACTION_STATUS_COMPLETE, TRANSACTION_STATUS_CANCELED, TRANSACTION_STATUS_ERROR, TRANSACTION_STATUS_FAILED, TRANSACTION_STATUS_INCOMPLETE
|
||||||
|
from regluit.payment.parameters import PAYMENT_TYPE_AUTHORIZATION
|
||||||
from regluit.core import goodreads
|
from regluit.core import goodreads
|
||||||
from tastypie.models import ApiKey
|
from tastypie.models import ApiKey
|
||||||
from regluit.payment.models import Transaction
|
from regluit.payment.models import Transaction
|
||||||
|
@ -583,280 +583,142 @@ class DonationView(TemplateView):
|
||||||
class PledgeView(FormView):
|
class PledgeView(FormView):
|
||||||
template_name="pledge.html"
|
template_name="pledge.html"
|
||||||
form_class = CampaignPledgeForm
|
form_class = CampaignPledgeForm
|
||||||
|
transaction = None
|
||||||
|
campaign = None
|
||||||
|
work = None
|
||||||
|
premiums = None
|
||||||
|
data = None
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get_form_kwargs(self):
|
||||||
# change the default behavior from https://code.djangoproject.com/browser/django/tags/releases/1.3.1/django/views/generic/edit.py#L129
|
|
||||||
# don't automatically bind the data to the form on GET, only on POST
|
|
||||||
# compare with https://code.djangoproject.com/browser/django/tags/releases/1.3.1/django/views/generic/edit.py#L34
|
|
||||||
form_class = self.get_form_class()
|
|
||||||
form = form_class()
|
|
||||||
|
|
||||||
context_data = self.get_context_data(form=form)
|
|
||||||
# if there is already an active campaign pledge for user, redirect to the pledge modify page
|
|
||||||
if context_data.get('redirect_to_modify_pledge'):
|
|
||||||
work = context_data['work']
|
|
||||||
return HttpResponseRedirect(reverse('pledge_modify', args=[work.id]))
|
|
||||||
else:
|
|
||||||
return self.render_to_response(context_data)
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
"""set up the pledge page"""
|
|
||||||
|
|
||||||
# the following should be true since PledgeModifyView.as_view is wrapped in login_required
|
|
||||||
assert self.request.user.is_authenticated()
|
assert self.request.user.is_authenticated()
|
||||||
user = self.request.user
|
self.work = get_object_or_404(models.Work, id=self.kwargs["work_id"])
|
||||||
|
|
||||||
context = super(PledgeView, self).get_context_data(**kwargs)
|
|
||||||
|
|
||||||
work = get_object_or_404(models.Work, id=self.kwargs["work_id"])
|
|
||||||
campaign = work.last_campaign()
|
|
||||||
|
|
||||||
# if there is no campaign or if campaign is not active, we should raise an error
|
# if there is no campaign or if campaign is not active, we should raise an error
|
||||||
|
try:
|
||||||
if campaign is None or campaign.status != 'ACTIVE':
|
self.campaign = self.work.last_campaign()
|
||||||
raise Http404
|
# TODO need to sort the premiums
|
||||||
|
self.premiums = self.campaign.custom_premiums() | models.Premium.objects.filter(id=150)
|
||||||
custom_premiums = campaign.custom_premiums()
|
# Campaign must be ACTIVE
|
||||||
# need to also include the no-premiums default in the queryset we send the page
|
assert self.campaign.status == 'ACTIVE'
|
||||||
premiums = custom_premiums | models.Premium.objects.filter(id=150)
|
except Exception, e:
|
||||||
premium_id = self.request.REQUEST.get('premium_id', None)
|
raise e
|
||||||
preapproval_amount = self.request.REQUEST.get('preapproval_amount', None)
|
|
||||||
|
transactions = self.campaign.transactions().filter(user=self.request.user, status=TRANSACTION_STATUS_ACTIVE, type=PAYMENT_TYPE_AUTHORIZATION)
|
||||||
|
if transactions.count() == 0:
|
||||||
|
premium_id = self.request.REQUEST.get('premium_id', None)
|
||||||
|
preapproval_amount = self.request.REQUEST.get('preapproval_amount', None)
|
||||||
|
premium_description = None
|
||||||
|
ack_name=''
|
||||||
|
ack_dedication=''
|
||||||
|
anonymous=''
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.transaction = transactions[0]
|
||||||
|
# what stuff do we need to pull out to populate form?
|
||||||
|
# preapproval_amount, premium_id (which we don't have stored yet)
|
||||||
|
if self.transaction.premium is not None:
|
||||||
|
premium_id = self.transaction.premium.id
|
||||||
|
premium_description = self.transaction.premium.description
|
||||||
|
else:
|
||||||
|
premium_id = None
|
||||||
|
premium_description = None
|
||||||
|
preapproval_amount = self.transaction.amount
|
||||||
|
ack_name=self.transaction.ack_name
|
||||||
|
ack_dedication=self.transaction.ack_dedication
|
||||||
|
anonymous=self.transaction.anonymous
|
||||||
|
|
||||||
if premium_id is not None and preapproval_amount is None:
|
if premium_id is not None and preapproval_amount is None:
|
||||||
try:
|
try:
|
||||||
preapproval_amount = D(models.Premium.objects.get(id=premium_id).amount)
|
preapproval_amount = D(models.Premium.objects.get(id=premium_id).amount)
|
||||||
except:
|
except:
|
||||||
preapproval_amount = None
|
preapproval_amount = None
|
||||||
|
self.data = {'preapproval_amount':preapproval_amount,
|
||||||
data = {'preapproval_amount':preapproval_amount, 'premium_id':premium_id}
|
'premium_id':premium_id, 'premium_description':premium_description,
|
||||||
|
'ack_name':ack_name, 'ack_dedication':ack_dedication, 'anonymous':anonymous}
|
||||||
form_class = self.get_form_class()
|
if self.request.method == 'POST':
|
||||||
|
self.data.update(self.request.POST.dict())
|
||||||
# no validation errors, please, when we're only doing a GET
|
if self.request.method == 'POST' or premium_id:
|
||||||
# to avoid validation errors, don't bind the form
|
return {'data':self.data}
|
||||||
|
|
||||||
if preapproval_amount is not None:
|
|
||||||
form = form_class(data)
|
|
||||||
else:
|
else:
|
||||||
form = form_class()
|
return {}
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
"""set up the pledge page"""
|
||||||
|
|
||||||
|
context = super(PledgeView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pubdate = work.publication_date[:4]
|
pubdate = self.work.publication_date[:4]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pubdate = 'unknown'
|
pubdate = 'unknown'
|
||||||
|
|
||||||
context.update({
|
context.update({
|
||||||
'redirect_to_modify_pledge':False,
|
'work':self.work,
|
||||||
'work':work,'campaign':campaign,
|
'campaign':self.campaign,
|
||||||
'premiums':premiums, 'form':form,
|
'premiums':self.premiums,
|
||||||
'premium_id':premium_id,
|
'premium_id':self.data['premium_id'],
|
||||||
'faqmenu': 'pledge',
|
'faqmenu': 'modify' if self.transaction else 'pledge',
|
||||||
'pubdate':pubdate,
|
'pubdate':pubdate,
|
||||||
'payment_processor':settings.PAYMENT_PROCESSOR,
|
'transaction': self.transaction,
|
||||||
})
|
'tid': self.transaction.id if self.transaction else None,
|
||||||
|
'premium_description': self.data['premium_description'],
|
||||||
|
'preapproval_amount':self.data['preapproval_amount'],
|
||||||
|
'payment_processor':self.transaction.host if self.transaction else None,
|
||||||
|
})
|
||||||
|
|
||||||
# check whether the user already has an ACTIVE transaction for the given campaign.
|
|
||||||
# if so, we should redirect the user to modify pledge page
|
|
||||||
# BUGBUG: but what about Completed Transactions?
|
|
||||||
transactions = campaign.transactions().filter(user=user, status=TRANSACTION_STATUS_ACTIVE)
|
|
||||||
if transactions.count() > 0:
|
|
||||||
context.update({'redirect_to_modify_pledge':True})
|
|
||||||
else:
|
|
||||||
context.update({'redirect_to_modify_pledge':False})
|
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def form_valid(self, form):
|
def get_premium(self,form):
|
||||||
work_id = self.kwargs["work_id"]
|
premium_id = form.cleaned_data["premium_id"]
|
||||||
preapproval_amount = form.cleaned_data["preapproval_amount"]
|
# confirm that the premium_id is a valid one for the campaign in question
|
||||||
anonymous = form.cleaned_data["anonymous"]
|
try:
|
||||||
ack_name = form.cleaned_data["ack_name"]
|
premium = models.Premium.objects.get(id=premium_id)
|
||||||
ack_link = form.cleaned_data["ack_link"]
|
if not (premium.campaign is None or premium.campaign == self.campaign):
|
||||||
ack_dedication = form.cleaned_data["ack_dedication"]
|
premium = None
|
||||||
|
except models.Premium.DoesNotExist, e:
|
||||||
|
premium = None
|
||||||
|
return premium
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
# right now, if there is a non-zero pledge amount, go with that. otherwise, do the pre_approval
|
# right now, if there is a non-zero pledge amount, go with that. otherwise, do the pre_approval
|
||||||
campaign = models.Work.objects.get(id=int(work_id)).last_campaign()
|
|
||||||
|
|
||||||
premium_id = form.cleaned_data["premium_id"]
|
p = PaymentManager()
|
||||||
# confirm that the premium_id is a valid one for the campaign in question
|
if self.transaction:
|
||||||
try:
|
# modifying the transaction...
|
||||||
premium = models.Premium.objects.get(id=premium_id)
|
assert self.transaction.type == PAYMENT_TYPE_AUTHORIZATION and self.transaction.status == TRANSACTION_STATUS_ACTIVE
|
||||||
if not (premium.campaign is None or premium.campaign == campaign):
|
status, url = p.modify_transaction(self.transaction, form.cleaned_data["preapproval_amount"],
|
||||||
premium = None
|
premium=self.get_premium(form),
|
||||||
except models.Premium.DoesNotExist, e:
|
paymentReason="Unglue.it Pledge for {0}".format(self.campaign.name),
|
||||||
premium = None
|
ack_name=form.cleaned_data["ack_name"],
|
||||||
|
ack_dedication=form.cleaned_data["ack_dedication"],
|
||||||
p = PaymentManager(embedded=self.embedded)
|
anonymous=form.cleaned_data["anonymous"],
|
||||||
|
)
|
||||||
# PledgeView is wrapped in login_required -- so in theory, user should never be None -- but I'll keep this logic here for now.
|
logger.info("status: {0}, url:{1}".format(status, url))
|
||||||
if self.request.user.is_authenticated():
|
|
||||||
user = self.request.user
|
if status and url is not None:
|
||||||
|
logger.info("PledgeView (Modify): " + url)
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
elif status and url is None:
|
||||||
|
return HttpResponseRedirect("{0}?tid={1}".format(reverse('pledge_complete'), self.transaction.id))
|
||||||
|
else:
|
||||||
|
return HttpResponse("No modification made")
|
||||||
else:
|
else:
|
||||||
user = None
|
t, url = p.process_transaction('USD', form.cleaned_data["preapproval_amount"],
|
||||||
|
host = None,
|
||||||
if not self.embedded:
|
campaign=self.campaign,
|
||||||
|
user=self.request.user,
|
||||||
return_url = None
|
premium=premium,
|
||||||
nevermind_url = None
|
paymentReason="Unglue.it Pledge for {0}".format(self.campaign.name),
|
||||||
|
ack_name=form.cleaned_data["ack_name"],
|
||||||
# the recipients of this authorization is not specified here but rather by the PaymentManager.
|
ack_dedication=form.cleaned_data["ack_dedication"],
|
||||||
# set the expiry date based on the campaign deadline
|
anonymous=form.cleaned_data["anonymous"],
|
||||||
expiry = campaign.deadline + timedelta( days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN )
|
)
|
||||||
|
if url:
|
||||||
paymentReason = "Unglue.it Pledge for {0}".format(campaign.name)
|
logger.info("PledgeView url: " + url)
|
||||||
t, url = p.authorize('USD', TARGET_TYPE_CAMPAIGN, preapproval_amount, expiry=expiry, campaign=campaign, list=None, user=user,
|
return HttpResponseRedirect(url)
|
||||||
return_url=return_url, nevermind_url=nevermind_url, anonymous=anonymous, premium=premium,
|
else:
|
||||||
paymentReason=paymentReason, ack_name=ack_name, ack_link=ack_link, ack_dedication=ack_dedication)
|
logger.error("Attempt to produce transaction id {0} failed".format(t.id))
|
||||||
else: # embedded view -- which we're not actively using right now.
|
return HttpResponse("Our attempt to enable your transaction failed. We have logged this error.")
|
||||||
# embedded view triggerws instant payment: send to the partnering RH
|
|
||||||
receiver_list = [{'email':settings.PAYPAL_NONPROFIT_PARTNER_EMAIL, 'amount':preapproval_amount}]
|
|
||||||
|
|
||||||
return_url = None
|
|
||||||
nevermind_url = None
|
|
||||||
|
|
||||||
t, url = p.pledge('USD', TARGET_TYPE_CAMPAIGN, receiver_list, campaign=campaign, list=None, user=user,
|
|
||||||
return_url=return_url, nevermind_url=nevermind_url, anonymous=anonymous, premium=premium,
|
|
||||||
ack_name=ack_name, ack_link=ack_link, ack_dedication=ack_dedication)
|
|
||||||
|
|
||||||
if url:
|
|
||||||
logger.info("PledgeView url: " + url)
|
|
||||||
return HttpResponseRedirect(url)
|
|
||||||
else:
|
|
||||||
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 PledgeModifyView(FormView):
|
|
||||||
"""
|
|
||||||
A view to handle request to change an existing pledge
|
|
||||||
"""
|
|
||||||
|
|
||||||
template_name="pledge.html"
|
|
||||||
form_class = CampaignPledgeForm
|
|
||||||
embedded = False
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
|
|
||||||
context = super(PledgeModifyView, self).get_context_data(**kwargs)
|
|
||||||
|
|
||||||
# the following should be true since PledgeModifyView.as_view is wrapped in login_required
|
|
||||||
assert self.request.user.is_authenticated()
|
|
||||||
user = self.request.user
|
|
||||||
|
|
||||||
work = get_object_or_404(models.Work, id=self.kwargs["work_id"])
|
|
||||||
|
|
||||||
try:
|
|
||||||
campaign = work.last_campaign()
|
|
||||||
premiums = campaign.custom_premiums() | models.Premium.objects.filter(id=150)
|
|
||||||
|
|
||||||
# which combination of campaign and transaction status required?
|
|
||||||
# Campaign must be ACTIVE
|
|
||||||
assert campaign.status == 'ACTIVE'
|
|
||||||
|
|
||||||
transactions = campaign.transactions().filter(user=user, status=TRANSACTION_STATUS_ACTIVE)
|
|
||||||
assert transactions.count() == 1
|
|
||||||
transaction = transactions[0]
|
|
||||||
assert transaction.type == PAYMENT_TYPE_AUTHORIZATION and transaction.status == TRANSACTION_STATUS_ACTIVE
|
|
||||||
|
|
||||||
except Exception, e:
|
|
||||||
raise e
|
|
||||||
|
|
||||||
# what stuff do we need to pull out to populate form?
|
|
||||||
# preapproval_amount, premium_id (which we don't have stored yet)
|
|
||||||
if transaction.premium is not None:
|
|
||||||
premium_id = transaction.premium.id
|
|
||||||
premium_description = transaction.premium.description
|
|
||||||
else:
|
|
||||||
premium_id = None
|
|
||||||
premium_description = None
|
|
||||||
|
|
||||||
# is there a Transaction for an ACTIVE campaign for this
|
|
||||||
# should make sure Transaction is modifiable.
|
|
||||||
|
|
||||||
preapproval_amount = transaction.amount
|
|
||||||
data = {'preapproval_amount':preapproval_amount, 'premium_id':premium_id}
|
|
||||||
|
|
||||||
# initialize form with the current state of the transaction if the current values empty
|
|
||||||
form = kwargs['form']
|
|
||||||
|
|
||||||
if not(form.is_bound):
|
|
||||||
form_class = self.get_form_class()
|
|
||||||
form = form_class(initial=data)
|
|
||||||
|
|
||||||
context.update({
|
|
||||||
'work':work,
|
|
||||||
'campaign':campaign,
|
|
||||||
'premiums':premiums,
|
|
||||||
'form':form,
|
|
||||||
'preapproval_amount':preapproval_amount,
|
|
||||||
'premium_id':premium_id,
|
|
||||||
'premium_description': premium_description,
|
|
||||||
'faqmenu': 'modify',
|
|
||||||
'tid': transaction.id,
|
|
||||||
'payment_processor':settings.PAYMENT_PROCESSOR,
|
|
||||||
'transaction': transaction,
|
|
||||||
})
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
def form_invalid(self, form):
|
|
||||||
logger.info("form.non_field_errors: {0}".format(form.non_field_errors()))
|
|
||||||
response = self.render_to_response(self.get_context_data(form=form))
|
|
||||||
return response
|
|
||||||
|
|
||||||
def form_valid(self, form):
|
|
||||||
|
|
||||||
# What are the situations we need to deal with?
|
|
||||||
# 2 main situations: if the new amount is less than max_amount, no need to go out to PayPal again
|
|
||||||
# if new amount is greater than max_amount...need to go out and get new approval.
|
|
||||||
# to start with, we can use the standard pledge_complete, pledge_cancel machinery
|
|
||||||
# might have to modify the pledge_complete, pledge_cancel because the messages are going to be
|
|
||||||
# different because we're modifying a pledge rather than a new one.
|
|
||||||
|
|
||||||
work_id = self.kwargs["work_id"]
|
|
||||||
preapproval_amount = form.cleaned_data["preapproval_amount"]
|
|
||||||
ack_name = form.cleaned_data["ack_name"]
|
|
||||||
ack_link = form.cleaned_data["ack_link"]
|
|
||||||
ack_dedication = form.cleaned_data["ack_dedication"]
|
|
||||||
anonymous = form.cleaned_data["anonymous"]
|
|
||||||
|
|
||||||
assert self.request.user.is_authenticated()
|
|
||||||
user = self.request.user
|
|
||||||
|
|
||||||
# right now, if there is a non-zero pledge amount, go with that. otherwise, do the pre_approval
|
|
||||||
campaign = models.Work.objects.get(id=int(work_id)).last_campaign()
|
|
||||||
assert campaign.status == 'ACTIVE'
|
|
||||||
|
|
||||||
premium_id = form.cleaned_data["premium_id"]
|
|
||||||
# confirm that the premium_id is a valid one for the campaign in question
|
|
||||||
try:
|
|
||||||
premium = models.Premium.objects.get(id=premium_id)
|
|
||||||
if not (premium.campaign is None or premium.campaign == campaign):
|
|
||||||
premium = None
|
|
||||||
except models.Premium.DoesNotExist, e:
|
|
||||||
premium = None
|
|
||||||
|
|
||||||
transactions = campaign.transactions().filter(user=user, status=TRANSACTION_STATUS_ACTIVE)
|
|
||||||
assert transactions.count() == 1
|
|
||||||
transaction = transactions[0]
|
|
||||||
assert transaction.type == PAYMENT_TYPE_AUTHORIZATION and transaction.status == TRANSACTION_STATUS_ACTIVE
|
|
||||||
|
|
||||||
p = PaymentManager(embedded=self.embedded)
|
|
||||||
paymentReason = "Unglue.it Pledge for {0}".format(campaign.name)
|
|
||||||
status, url = p.modify_transaction(transaction=transaction, amount=preapproval_amount, premium=premium,
|
|
||||||
paymentReason=paymentReason, ack_name=ack_name, ack_link=ack_link,
|
|
||||||
ack_dedication=ack_dedication, anonymous=anonymous)
|
|
||||||
|
|
||||||
logger.info("status: {0}, url:{1}".format(status, url))
|
|
||||||
|
|
||||||
if status and url is not None:
|
|
||||||
logger.info("PledgeModifyView paypal: " + url)
|
|
||||||
return HttpResponseRedirect(url)
|
|
||||||
elif status and url is None:
|
|
||||||
# let's use the pledge_complete template for now and maybe look into customizing it.
|
|
||||||
return HttpResponseRedirect("{0}?tid={1}".format(reverse('pledge_complete'), transaction.id))
|
|
||||||
else:
|
|
||||||
return HttpResponse("No modification made")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PledgeRechargeView(TemplateView):
|
class PledgeRechargeView(TemplateView):
|
||||||
|
@ -869,7 +731,7 @@ class PledgeRechargeView(TemplateView):
|
||||||
|
|
||||||
context = super(PledgeRechargeView, self).get_context_data(**kwargs)
|
context = super(PledgeRechargeView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
# the following should be true since PledgeModifyView.as_view is wrapped in login_required
|
# the following should be true since PledgeView.as_view is wrapped in login_required
|
||||||
assert self.request.user.is_authenticated()
|
assert self.request.user.is_authenticated()
|
||||||
user = self.request.user
|
user = self.request.user
|
||||||
|
|
||||||
|
@ -888,18 +750,15 @@ class PledgeRechargeView(TemplateView):
|
||||||
|
|
||||||
if transaction is not None:
|
if transaction is not None:
|
||||||
# the recipients of this authorization is not specified here but rather by the PaymentManager.
|
# the recipients of this authorization is not specified here but rather by the PaymentManager.
|
||||||
# set the expiry date based on the campaign deadline
|
|
||||||
expiry = campaign.deadline + timedelta( days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN )
|
|
||||||
ack_name = transaction.ack_name
|
ack_name = transaction.ack_name
|
||||||
ack_link = transaction.ack_link
|
|
||||||
ack_dedication = transaction.ack_dedication
|
ack_dedication = transaction.ack_dedication
|
||||||
|
|
||||||
paymentReason = "Unglue.it Recharge for {0}".format(campaign.name)
|
paymentReason = "Unglue.it Recharge for {0}".format(campaign.name)
|
||||||
|
|
||||||
p = PaymentManager(embedded=False)
|
p = PaymentManager()
|
||||||
t, url = p.authorize('USD', TARGET_TYPE_CAMPAIGN, transaction.amount, expiry=expiry, campaign=campaign, list=None, user=user,
|
t, url = p.authorize('USD', transaction.amount, campaign=campaign, list=None, user=user,
|
||||||
return_url=return_url, nevermind_url=nevermind_url, anonymous=transaction.anonymous, premium=transaction.premium,
|
return_url=return_url, anonymous=transaction.anonymous, premium=transaction.premium,
|
||||||
paymentReason=paymentReason, ack_name=ack_name, ack_link=ack_link, ack_dedication=ack_dedication)
|
paymentReason=paymentReason, ack_name=ack_name, ack_dedication=ack_dedication)
|
||||||
logger.info("Recharge url: {0}".format(url))
|
logger.info("Recharge url: {0}".format(url))
|
||||||
else:
|
else:
|
||||||
url = None
|
url = None
|
||||||
|
@ -1090,73 +949,11 @@ class PledgeCancelView(FormView):
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logger.error("Exception from attempt to cancel pledge for campaign id {0} for username {1}: {2}".format(campaign_id, user.username, e))
|
logger.error("Exception from attempt to cancel pledge for campaign id {0} for username {1}: {2}".format(campaign_id, user.username, e))
|
||||||
return HttpResponse("Sorry, something went wrong in canceling your campaign pledge. We have logged this error.")
|
return HttpResponse("Sorry, something went wrong in canceling your campaign pledge. We have logged this error.")
|
||||||
|
|
||||||
|
|
||||||
class PledgeNeverMindView(TemplateView):
|
|
||||||
"""A callback for PayPal to tell unglue.it that a payment transaction has been canceled by the user"""
|
|
||||||
template_name="pledge_nevermind.html"
|
|
||||||
|
|
||||||
def get_context_data(self):
|
|
||||||
context = super(PledgeNeverMindView, self).get_context_data()
|
|
||||||
|
|
||||||
if self.request.user.is_authenticated():
|
|
||||||
user = self.request.user
|
|
||||||
else:
|
|
||||||
user = None
|
|
||||||
|
|
||||||
# pull out the transaction id and try to get the corresponding Transaction
|
|
||||||
transaction_id = self.request.REQUEST.get("tid")
|
|
||||||
transaction = Transaction.objects.get(id=transaction_id)
|
|
||||||
|
|
||||||
# work and campaign in question
|
|
||||||
try:
|
|
||||||
campaign = transaction.campaign
|
|
||||||
work = campaign.work
|
|
||||||
except Exception, e:
|
|
||||||
campaign = None
|
|
||||||
work = None
|
|
||||||
|
|
||||||
# we need to check whether the user tied to the transaction is indeed the authenticated user.
|
|
||||||
|
|
||||||
correct_user = False
|
|
||||||
try:
|
|
||||||
if user.id == transaction.user.id:
|
|
||||||
correct_user = True
|
|
||||||
except Exception, e:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# check that the user had not already approved the transaction
|
|
||||||
# do we need to first run PreapprovalDetails to check on the status
|
|
||||||
|
|
||||||
# is it of type=PAYMENT_TYPE_AUTHORIZATION and status is NONE or ACTIVE (but approved is false)
|
|
||||||
|
|
||||||
if transaction.type == PAYMENT_TYPE_AUTHORIZATION:
|
|
||||||
correct_transaction_type = True
|
|
||||||
else:
|
|
||||||
correct_transaction_type = False
|
|
||||||
|
|
||||||
# status?
|
|
||||||
|
|
||||||
# give the user an opportunity to approved the transaction again
|
|
||||||
# provide a URL to click on.
|
|
||||||
# https://www.sandbox.paypal.com/?cmd=_ap-preapproval&preapprovalkey=PA-6JV656290V840615H
|
|
||||||
try_again_url = '%s?cmd=_ap-preapproval&preapprovalkey=%s' % (settings.PAYPAL_PAYMENT_HOST, transaction.preapproval_key)
|
|
||||||
|
|
||||||
context["transaction"] = transaction
|
|
||||||
context["correct_user"] = correct_user
|
|
||||||
context["correct_transaction_type"] = correct_transaction_type
|
|
||||||
context["try_again_url"] = try_again_url
|
|
||||||
context["work"] = work
|
|
||||||
context["campaign"] = campaign
|
|
||||||
context["faqmenu"] = "cancel"
|
|
||||||
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
class DonateView(FormView):
|
class DonateView(FormView):
|
||||||
template_name="donate.html"
|
template_name="donate.html"
|
||||||
form_class = DonateForm
|
form_class = DonateForm
|
||||||
embedded = False
|
|
||||||
|
|
||||||
#def get_context_data(self, **kwargs):
|
#def get_context_data(self, **kwargs):
|
||||||
# context = super(DonateView, self).get_context_data(**kwargs)
|
# context = super(DonateView, self).get_context_data(**kwargs)
|
||||||
|
@ -1173,7 +970,7 @@ class DonateView(FormView):
|
||||||
# right now, if there is a non-zero pledge amount, go with that. otherwise, do the pre_approval
|
# right now, if there is a non-zero pledge amount, go with that. otherwise, do the pre_approval
|
||||||
campaign = None
|
campaign = None
|
||||||
|
|
||||||
p = PaymentManager(embedded=self.embedded)
|
p = PaymentManager()
|
||||||
|
|
||||||
# we should force login at this point -- or if no account, account creation, login, and return to this spot
|
# we should force login at this point -- or if no account, account creation, login, and return to this spot
|
||||||
if self.request.user.is_authenticated():
|
if self.request.user.is_authenticated():
|
||||||
|
@ -1187,8 +984,8 @@ class DonateView(FormView):
|
||||||
#redirect the page back to campaign page on success
|
#redirect the page back to campaign page on success
|
||||||
return_url = self.request.build_absolute_uri(reverse('donate'))
|
return_url = self.request.build_absolute_uri(reverse('donate'))
|
||||||
|
|
||||||
t, url = p.pledge('USD', TARGET_TYPE_DONATION, receiver_list, campaign=campaign, list=None, user=user,
|
t, url = p.pledge('USD', receiver_list, campaign=campaign, list=None, user=user,
|
||||||
return_url=return_url, anonymous=anonymous, ack_name=ack_name, ack_link=ack_link,
|
return_url=return_url, anonymous=anonymous, ack_name=ack_name,
|
||||||
ack_dedication=ack_dedication)
|
ack_dedication=ack_dedication)
|
||||||
|
|
||||||
if url:
|
if url:
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
from regluit.payment.parameters import *
|
||||||
|
from regluit.utils.localdatetime import now
|
||||||
|
from regluit.payment.baseprocessor import BasePaymentRequest
|
||||||
|
|
||||||
|
|
||||||
|
def pledge_transaction(t,user,amount):
|
||||||
|
"""commit <amount> from a <user>'s credit to a specified transaction <t>"""
|
||||||
|
|
||||||
|
if t.amount and t.host == PAYMENT_HOST_CREDIT:
|
||||||
|
#changing the pledge_transaction
|
||||||
|
user.credit.add_to_pledged(amount-t.amount)
|
||||||
|
else:
|
||||||
|
user.credit.add_to_pledged(amount)
|
||||||
|
t.amount=amount
|
||||||
|
t.max_amount=amount
|
||||||
|
t.host = PAYMENT_HOST_CREDIT
|
||||||
|
t.type = PAYMENT_TYPE_AUTHORIZATION
|
||||||
|
t.status=TRANSACTION_STATUS_ACTIVE
|
||||||
|
t.approved=True
|
||||||
|
now_val = now()
|
||||||
|
t.date_authorized = now_val
|
||||||
|
t.date_expired = now_val + timedelta( days=settings.PREAPPROVAL_PERIOD )
|
||||||
|
|
||||||
|
t.save()
|
||||||
|
|
||||||
|
|
||||||
|
class CancelPreapproval(BasePaymentRequest):
|
||||||
|
'''
|
||||||
|
Cancels an exisiting token.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, transaction):
|
||||||
|
self.transaction = transaction
|
||||||
|
if transaction.user.credit.add_to_pledged(-transaction.amount):
|
||||||
|
#success
|
||||||
|
transaction.status=TRANSACTION_STATUS_CANCELED
|
||||||
|
transaction.save()
|
||||||
|
else:
|
||||||
|
self.errorMessage="couldn't cancel the transaction"
|
||||||
|
self.status = 'Credit Cancel Failure'
|
||||||
|
|
||||||
|
class PreapprovalDetails(BasePaymentRequest):
|
||||||
|
status = None
|
||||||
|
approved = None
|
||||||
|
currency = None
|
||||||
|
amount = None
|
||||||
|
def __init__(self, transaction):
|
||||||
|
self.status = transaction.status
|
||||||
|
self.approved = transaction.approved
|
||||||
|
self.currency = transaction.currency
|
||||||
|
self.amount = transaction.amount
|
|
@ -5,6 +5,9 @@ from django.core.urlresolvers import reverse
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from regluit.payment.parameters import *
|
from regluit.payment.parameters import *
|
||||||
from regluit.payment.signals import transaction_charged, pledge_modified, pledge_created
|
from regluit.payment.signals import transaction_charged, pledge_modified, pledge_created
|
||||||
|
from regluit.payment import credit
|
||||||
|
|
||||||
|
from regluit.payment.baseprocessor import Pay, Finish, Preapproval, ProcessIPN, CancelPreapproval, PaymentDetails, PreapprovalDetails, RefundPayment
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
import traceback
|
import traceback
|
||||||
|
@ -14,6 +17,8 @@ import logging
|
||||||
from decimal import Decimal as D
|
from decimal import Decimal as D
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
import urllib, urlparse
|
import urllib, urlparse
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
@ -531,58 +536,28 @@ class PaymentManager( object ):
|
||||||
logger.info("Cancel Transaction " + str(transaction.id) + " Failed with error: " + p.error_string())
|
logger.info("Cancel Transaction " + str(transaction.id) + " Failed with error: " + p.error_string())
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def authorize(self, currency, target, amount, expiry=None, campaign=None, list=None, user=None,
|
def authorize(self, transaction, expiry= None, return_url=None, paymentReason="unglue.it Pledge", modification=False):
|
||||||
return_url=None, nevermind_url=None, anonymous=False, premium=None,
|
|
||||||
paymentReason="unglue.it Pledge", ack_name=None, ack_link=None, ack_dedication=None,
|
|
||||||
modification=False):
|
|
||||||
'''
|
'''
|
||||||
authorize
|
authorize
|
||||||
|
|
||||||
authorizes a set amount of money to be collected at a later date
|
authorizes a set amount of money to be collected at a later date
|
||||||
|
|
||||||
currency: a 3-letter paypal currency code, i.e. USD
|
|
||||||
target: a defined target type, i.e. TARGET_TYPE_CAMPAIGN, TARGET_TYPE_LIST, TARGET_TYPE_NONE
|
|
||||||
amount: the amount to authorize
|
|
||||||
campaign: optional campaign object(to be set with TARGET_TYPE_CAMPAIGN)
|
|
||||||
list: optional list object(to be set with TARGET_TYPE_LIST)
|
|
||||||
user: optional user object
|
|
||||||
return_url: url to redirect supporter to after a successful PayPal transaction
|
return_url: url to redirect supporter to after a successful PayPal transaction
|
||||||
nevermind_url: url to send supporter to if support hits cancel while in middle of PayPal transaction
|
|
||||||
anonymous: whether this pledge is anonymous
|
|
||||||
premium: the premium selected by the supporter for this transaction
|
|
||||||
paymentReason: a memo line that will show up in the Payer's Amazon (and Paypal?) account
|
paymentReason: a memo line that will show up in the Payer's Amazon (and Paypal?) account
|
||||||
modification: whether this authorize call is part of a modification of an existing pledge
|
modification: whether this authorize call is part of a modification of an existing pledge
|
||||||
ack_name, ack_link, ack_dedication: how the user will be credited in the unglued ebook, if applicable
|
|
||||||
|
|
||||||
return value: a tuple of the new transaction object and a re-direct url. If the process fails,
|
return value: a tuple of the new transaction object and a re-direct url. If the process fails,
|
||||||
the redirect url will be None
|
the redirect url will be None
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
t = Transaction.objects.create(amount=amount,
|
|
||||||
max_amount=amount,
|
|
||||||
type=PAYMENT_TYPE_AUTHORIZATION,
|
|
||||||
execution = EXECUTE_TYPE_CHAINED_DELAYED,
|
|
||||||
target=target,
|
|
||||||
currency=currency,
|
|
||||||
status='NONE',
|
|
||||||
campaign=campaign,
|
|
||||||
list=list,
|
|
||||||
user=user,
|
|
||||||
anonymous=anonymous,
|
|
||||||
premium=premium,
|
|
||||||
ack_name=ack_name,
|
|
||||||
ack_link=ack_link,
|
|
||||||
ack_dedication=ack_dedication
|
|
||||||
)
|
|
||||||
|
|
||||||
# we might want to not allow for a return_url or nevermind_url to be passed in but calculated
|
if host==None:
|
||||||
|
#TODO send user to select a payment processor
|
||||||
|
pass
|
||||||
|
|
||||||
|
# we might want to not allow for a return_url to be passed in but calculated
|
||||||
# here because we have immediate access to the Transaction object.
|
# here because we have immediate access to the Transaction object.
|
||||||
|
|
||||||
if nevermind_url is None:
|
|
||||||
nevermind_path = "{0}?{1}".format(reverse('pledge_nevermind'),
|
|
||||||
urllib.urlencode({'tid':t.id}))
|
|
||||||
nevermind_url = urlparse.urljoin(settings.BASE_URL, nevermind_path)
|
|
||||||
|
|
||||||
if return_url is None:
|
if return_url is None:
|
||||||
return_path = "{0}?{1}".format(reverse('pledge_complete'),
|
return_path = "{0}?{1}".format(reverse('pledge_complete'),
|
||||||
|
@ -590,7 +565,7 @@ class PaymentManager( object ):
|
||||||
return_url = urlparse.urljoin(settings.BASE_URL, return_path)
|
return_url = urlparse.urljoin(settings.BASE_URL, return_path)
|
||||||
|
|
||||||
method = getattr(t.get_payment_class(), "Preapproval")
|
method = getattr(t.get_payment_class(), "Preapproval")
|
||||||
p = method(t, amount, expiry, return_url=return_url, nevermind_url=nevermind_url, paymentReason=paymentReason)
|
p = method(transaction, transaction.max_amount, expiry, return_url=return_url, paymentReason=paymentReason)
|
||||||
|
|
||||||
# Create a response for this
|
# Create a response for this
|
||||||
envelope = p.envelope()
|
envelope = p.envelope()
|
||||||
|
@ -600,11 +575,11 @@ class PaymentManager( object ):
|
||||||
correlation_id = p.correlation_id(),
|
correlation_id = p.correlation_id(),
|
||||||
timestamp = p.timestamp(),
|
timestamp = p.timestamp(),
|
||||||
info = p.raw_response,
|
info = p.raw_response,
|
||||||
transaction=t)
|
transaction=transaction)
|
||||||
|
|
||||||
if p.success() and not p.error():
|
if p.success() and not p.error():
|
||||||
t.preapproval_key = p.key()
|
transaction.preapproval_key = p.key()
|
||||||
t.save()
|
transaction.save()
|
||||||
|
|
||||||
url = p.next_url()
|
url = p.next_url()
|
||||||
|
|
||||||
|
@ -624,16 +599,69 @@ class PaymentManager( object ):
|
||||||
# send the notice here for now
|
# send the notice here for now
|
||||||
# this is actually premature since we're only about to send the user off to the payment system to
|
# this is actually premature since we're only about to send the user off to the payment system to
|
||||||
# authorize a charge
|
# authorize a charge
|
||||||
pledge_created.send(sender=self, transaction=t)
|
pledge_created.send(sender=self, transaction=transaction)
|
||||||
|
|
||||||
return t, url
|
return transaction, url
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
t.error = p.error_string()
|
transaction.error = p.error_string()
|
||||||
t.save()
|
transaction.save()
|
||||||
logger.info("Authorize Error: " + p.error_string())
|
logger.info("Authorize Error: " + p.error_string())
|
||||||
|
return transaction, None
|
||||||
|
|
||||||
|
def process_transaction(self, currency, amount, host=None, campaign=None, user=None,
|
||||||
|
return_url=None, anonymous=False, premium=None,
|
||||||
|
paymentReason="unglue.it Pledge", ack_name=None, ack_dedication=None,
|
||||||
|
modification=False):
|
||||||
|
'''
|
||||||
|
process
|
||||||
|
|
||||||
|
saves and processes a proposed transaction; decides if the transaction should be processed immediately.
|
||||||
|
|
||||||
|
currency: a 3-letter currency code, i.e. USD
|
||||||
|
amount: the amount to authorize
|
||||||
|
host: the name of the processing module; if none, send user back to decide!
|
||||||
|
campaign: required campaign object
|
||||||
|
user: optional user object
|
||||||
|
return_url: url to redirect supporter to after a successful transaction
|
||||||
|
anonymous: whether this pledge is anonymous
|
||||||
|
premium: the premium selected by the supporter for this transaction
|
||||||
|
paymentReason: a memo line that will show up in the Payer's Amazon (and Paypal?) account
|
||||||
|
modification: whether this authorize call is part of a modification of an existing pledge
|
||||||
|
ack_name, ack_dedication: how the user will be credited in the unglued ebook, if applicable
|
||||||
|
|
||||||
|
return value: a tuple of the new transaction object and a re-direct url. If the process fails,
|
||||||
|
the redirect url will be None
|
||||||
|
'''
|
||||||
|
# set the expiry date based on the campaign deadline
|
||||||
|
expiry = campaign.deadline + timedelta( days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN )
|
||||||
|
|
||||||
|
t = Transaction.objects.create(amount=0,
|
||||||
|
max_amount=amount,
|
||||||
|
currency=currency,
|
||||||
|
status='NONE',
|
||||||
|
campaign=campaign,
|
||||||
|
user=user,
|
||||||
|
anonymous=anonymous,
|
||||||
|
premium=premium,
|
||||||
|
ack_name=ack_name,
|
||||||
|
ack_dedication=ack_dedication
|
||||||
|
)
|
||||||
|
|
||||||
|
# does user have enough credit to pledge now?
|
||||||
|
if user.credit.available >= amount :
|
||||||
|
# YES!
|
||||||
|
credit.pledge_transaction(t,user,amount)
|
||||||
|
return_path = "{0}?{1}".format(reverse('pledge_complete'),
|
||||||
|
urllib.urlencode({'tid':t.id}))
|
||||||
|
return_url = urlparse.urljoin(settings.BASE_URL, return_path)
|
||||||
|
pledge_created.send(sender=self, transaction=t)
|
||||||
|
return t, return_url
|
||||||
|
else:
|
||||||
|
#TODO send user to choose payment path
|
||||||
return t, None
|
return t, None
|
||||||
|
|
||||||
|
|
||||||
def cancel_related_transaction(self, transaction, status=TRANSACTION_STATUS_ACTIVE, campaign=None):
|
def cancel_related_transaction(self, transaction, status=TRANSACTION_STATUS_ACTIVE, campaign=None):
|
||||||
'''
|
'''
|
||||||
|
@ -677,26 +705,29 @@ class PaymentManager( object ):
|
||||||
|
|
||||||
return canceled
|
return canceled
|
||||||
|
|
||||||
def modify_transaction(self, transaction, amount, expiry=None, anonymous=None, premium=None,
|
def modify_transaction(self, transaction, amount, expiry=None, premium=None,
|
||||||
return_url=None, nevermind_url=None, paymentReason=None,
|
return_url=None, nevermind_url=None, paymentReason=None,
|
||||||
ack_name=None, ack_link=None, ack_dedication=None):
|
ack_name=None, ack_dedication=None, anonymous=None):
|
||||||
'''
|
'''
|
||||||
modify
|
modify
|
||||||
|
|
||||||
Modifies a transaction. The only type of modification allowed is to the amount and expiration date
|
Modifies a transaction.
|
||||||
|
2 main situations: if the new amount is less than max_amount, no need to go out to PayPal again
|
||||||
|
if new amount is greater than max_amount...need to go out and get new approval.
|
||||||
|
to start with, we can use the standard pledge_complete, pledge_cancel machinery
|
||||||
|
might have to modify the pledge_complete, pledge_cancel because the messages are going to be
|
||||||
|
different because we're modifying a pledge rather than a new one.
|
||||||
|
|
||||||
amount: the new amount
|
amount: the new amount
|
||||||
expiry: the new expiration date, or if none the current expiration date will be used
|
expiry: the new expiration date, or if none the current expiration date will be used
|
||||||
anonymous: new anonymous value; if None, then keep old value
|
anonymous: new anonymous value; if None, then keep old value
|
||||||
premium: new premium selected; if None, then keep old value
|
premium: new premium selected; if None, then keep old value
|
||||||
return_url: the return URL after the preapproval(if needed)
|
return_url: the return URL after the preapproval(if needed)
|
||||||
nevermind_url: the cancel url after the preapproval(if needed)
|
|
||||||
paymentReason: a memo line that will show up in the Payer's Amazon (and Paypal?) account
|
paymentReason: a memo line that will show up in the Payer's Amazon (and Paypal?) account
|
||||||
|
|
||||||
return value: True if successful, False otherwise. An optional second parameter for the forward URL if a new authorhization is needed
|
return value: True if successful, False otherwise. An optional second parameter for the forward URL if a new authorhization is needed
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# Can only modify the amount of a preapproval for now
|
|
||||||
if transaction.type != PAYMENT_TYPE_AUTHORIZATION:
|
if transaction.type != PAYMENT_TYPE_AUTHORIZATION:
|
||||||
logger.info("Error, attempt to modify an invalid transaction type")
|
logger.info("Error, attempt to modify an invalid transaction type")
|
||||||
return False, None
|
return False, None
|
||||||
|
@ -707,34 +738,50 @@ class PaymentManager( object ):
|
||||||
logger.info("Error, attempt to modify a transaction that is not active")
|
logger.info("Error, attempt to modify a transaction that is not active")
|
||||||
return False, None
|
return False, None
|
||||||
|
|
||||||
# if any of expiry, anonymous, or premium is None, use the existing value
|
if transaction.host == PAYMENT_HOST_CREDIT:
|
||||||
if expiry is None:
|
# does user have enough credit to pledge now?
|
||||||
expiry = transaction.date_expired
|
if transaction.user.credit.available >= amount-transaction.amount :
|
||||||
if anonymous is None:
|
# YES!
|
||||||
anonymous = transaction.anonymous
|
transaction.anonymous = anonymous
|
||||||
if premium is None:
|
transaction.premium = premium
|
||||||
premium = transaction.premium
|
transaction.ack_name = ack_name
|
||||||
|
transaction.ack_dedication = ack_dedication
|
||||||
if amount > transaction.max_amount or expiry != transaction.date_expired:
|
credit.pledge_transaction(transaction,transaction.user,amount)
|
||||||
|
return_path = "{0}?{1}".format(reverse('pledge_complete'),
|
||||||
|
urllib.urlencode({'tid':transaction.id}))
|
||||||
|
return_url = urlparse.urljoin(settings.BASE_URL, return_path)
|
||||||
|
|
||||||
# Start a new authorization for the new amount
|
logger.info("Updated amount of transaction to %f" % amount)
|
||||||
|
pledge_modified.send(sender=self, transaction=transaction,up_or_down="decreased" if amount-transaction.amount<0 else "increased")
|
||||||
|
return transaction, return_url
|
||||||
|
else:
|
||||||
|
#TODO send user to choose payment path
|
||||||
|
return t, None
|
||||||
|
elif amount > transaction.max_amount or expiry != transaction.date_expired:
|
||||||
|
|
||||||
|
# set the expiry date based on the campaign deadline
|
||||||
|
expiry = transaction.campaign.deadline + timedelta( days=settings.PREAPPROVAL_PERIOD_AFTER_CAMPAIGN )
|
||||||
|
|
||||||
|
# Start a new transaction for the new amount
|
||||||
|
t = Transaction.objects.create(amount=amount,
|
||||||
|
max_amount=amount,
|
||||||
|
host=transaction.host,
|
||||||
|
currency=currency,
|
||||||
|
status=TRANSACTION_STATUS_CREATED,
|
||||||
|
campaign=transaction.campaign,
|
||||||
|
user=transaction.user,
|
||||||
|
anonymous=anonymous if anonymous!=None else transaction.anonymous,
|
||||||
|
premium=premium if premium != None else transaction.premium,
|
||||||
|
ack_name=ack_name,
|
||||||
|
ack_dedication=ack_dedication
|
||||||
|
)
|
||||||
|
|
||||||
t, url = self.authorize(transaction.currency,
|
t, url = self.authorize(transaction,
|
||||||
transaction.target,
|
expiry=expiry if expiry else transaction.date_expired,
|
||||||
amount,
|
return_url=return_url,
|
||||||
expiry,
|
paymentReason=paymentReason,
|
||||||
transaction.campaign,
|
modification=True
|
||||||
transaction.list,
|
)
|
||||||
transaction.user,
|
|
||||||
return_url,
|
|
||||||
nevermind_url,
|
|
||||||
anonymous,
|
|
||||||
premium,
|
|
||||||
paymentReason,
|
|
||||||
ack_name,
|
|
||||||
ack_link,
|
|
||||||
ack_dedication,
|
|
||||||
True)
|
|
||||||
|
|
||||||
if t and url:
|
if t and url:
|
||||||
# Need to re-direct to approve the transaction
|
# Need to re-direct to approve the transaction
|
||||||
|
@ -762,7 +809,6 @@ class PaymentManager( object ):
|
||||||
transaction.anonymous = anonymous
|
transaction.anonymous = anonymous
|
||||||
transaction.premium = premium
|
transaction.premium = premium
|
||||||
transaction.ack_name = ack_name
|
transaction.ack_name = ack_name
|
||||||
transaction.ack_link = ack_link
|
|
||||||
transaction.ack_dedication = ack_dedication
|
transaction.ack_dedication = ack_dedication
|
||||||
|
|
||||||
transaction.save()
|
transaction.save()
|
||||||
|
@ -820,16 +866,15 @@ class PaymentManager( object ):
|
||||||
logger.info("Refund Transaction " + str(transaction.id) + " Failed with error: " + p.error_string())
|
logger.info("Refund Transaction " + str(transaction.id) + " Failed with error: " + p.error_string())
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def pledge(self, currency, target, receiver_list, campaign=None, list=None, user=None,
|
def pledge(self, currency, receiver_list, campaign=None, user=None,
|
||||||
return_url=None, nevermind_url=None, anonymous=False, premium=None, ack_name=None,
|
return_url=None, nevermind_url=None, anonymous=False, premium=None, ack_name=None,
|
||||||
ack_link=None, ack_dedication=None):
|
ack_dedication=None):
|
||||||
'''
|
'''
|
||||||
pledge
|
pledge
|
||||||
|
|
||||||
Performs an instant payment
|
Performs an instant payment
|
||||||
|
|
||||||
currency: a 3-letter paypal currency code, i.e. USD
|
currency: a 3-letter paypal currency code, i.e. USD
|
||||||
target: a defined target type, i.e. TARGET_TYPE_CAMPAIGN, TARGET_TYPE_LIST, TARGET_TYPE_NONE
|
|
||||||
receiver_list: a list of receivers for the transaction, in this format:
|
receiver_list: a list of receivers for the transaction, in this format:
|
||||||
|
|
||||||
[
|
[
|
||||||
|
@ -837,8 +882,7 @@ class PaymentManager( object ):
|
||||||
{'email':'email-2', 'amount':amount2}
|
{'email':'email-2', 'amount':amount2}
|
||||||
]
|
]
|
||||||
|
|
||||||
campaign: optional campaign object(to be set with TARGET_TYPE_CAMPAIGN)
|
campaign: required campaign object
|
||||||
list: optional list object(to be set with TARGET_TYPE_LIST)
|
|
||||||
user: optional user object
|
user: optional user object
|
||||||
return_url: url to redirect supporter to after a successful PayPal transaction
|
return_url: url to redirect supporter to after a successful PayPal transaction
|
||||||
nevermind_url: url to send supporter to if support hits cancel while in middle of PayPal transaction
|
nevermind_url: url to send supporter to if support hits cancel while in middle of PayPal transaction
|
||||||
|
@ -863,13 +907,11 @@ class PaymentManager( object ):
|
||||||
currency=currency,
|
currency=currency,
|
||||||
status='NONE',
|
status='NONE',
|
||||||
campaign=campaign,
|
campaign=campaign,
|
||||||
list=list,
|
|
||||||
user=user,
|
user=user,
|
||||||
date_payment=now(),
|
date_payment=now(),
|
||||||
anonymous=anonymous,
|
anonymous=anonymous,
|
||||||
premium=premium,
|
premium=premium,
|
||||||
ack_name=ack_name,
|
ack_name=ack_name,
|
||||||
ack_link=ack_link,
|
|
||||||
ack_dedication=ack_dedication
|
ack_dedication=ack_dedication
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,224 @@
|
||||||
|
# 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 model 'Credit'
|
||||||
|
db.create_table('payment_credit', (
|
||||||
|
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||||
|
('user', self.gf('django.db.models.fields.related.OneToOneField')(related_name='credit', unique=True, to=orm['auth.User'])),
|
||||||
|
('balance', self.gf('django.db.models.fields.DecimalField')(default='0.00', max_digits=14, decimal_places=2)),
|
||||||
|
('pledged', self.gf('django.db.models.fields.DecimalField')(default='0.00', max_digits=14, decimal_places=2)),
|
||||||
|
('last_activity', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
|
||||||
|
))
|
||||||
|
db.send_create_signal('payment', ['Credit'])
|
||||||
|
|
||||||
|
# Adding model 'CreditLog'
|
||||||
|
db.create_table('payment_creditlog', (
|
||||||
|
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||||
|
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True)),
|
||||||
|
('amount', self.gf('django.db.models.fields.DecimalField')(default='0.00', max_digits=14, decimal_places=2)),
|
||||||
|
('timestamp', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
|
||||||
|
('action', self.gf('django.db.models.fields.CharField')(max_length=16)),
|
||||||
|
))
|
||||||
|
db.send_create_signal('payment', ['CreditLog'])
|
||||||
|
|
||||||
|
# Deleting field 'Transaction.target'
|
||||||
|
db.delete_column('payment_transaction', 'target')
|
||||||
|
|
||||||
|
# Deleting field 'Transaction.list'
|
||||||
|
db.delete_column('payment_transaction', 'list_id')
|
||||||
|
|
||||||
|
# Adding field 'Transaction.ack_name'
|
||||||
|
db.add_column('payment_transaction', 'ack_name', self.gf('django.db.models.fields.CharField')(max_length=64, null=True), keep_default=False)
|
||||||
|
|
||||||
|
# Adding field 'Transaction.ack_dedication'
|
||||||
|
db.add_column('payment_transaction', 'ack_dedication', self.gf('django.db.models.fields.CharField')(max_length=140, null=True), keep_default=False)
|
||||||
|
|
||||||
|
|
||||||
|
def backwards(self, orm):
|
||||||
|
|
||||||
|
# Deleting model 'Credit'
|
||||||
|
db.delete_table('payment_credit')
|
||||||
|
|
||||||
|
# Deleting model 'CreditLog'
|
||||||
|
db.delete_table('payment_creditlog')
|
||||||
|
|
||||||
|
# Adding field 'Transaction.target'
|
||||||
|
db.add_column('payment_transaction', 'target', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
|
||||||
|
|
||||||
|
# Adding field 'Transaction.list'
|
||||||
|
db.add_column('payment_transaction', 'list', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['core.Wishlist'], null=True), keep_default=False)
|
||||||
|
|
||||||
|
# Deleting field 'Transaction.ack_name'
|
||||||
|
db.delete_column('payment_transaction', 'ack_name')
|
||||||
|
|
||||||
|
# Deleting field 'Transaction.ack_dedication'
|
||||||
|
db.delete_column('payment_transaction', 'ack_dedication')
|
||||||
|
|
||||||
|
|
||||||
|
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(2012, 8, 31, 2, 10, 24, 467332)'}),
|
||||||
|
'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(2012, 8, 31, 2, 10, 24, 467190)'}),
|
||||||
|
'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.campaign': {
|
||||||
|
'Meta': {'object_name': 'Campaign'},
|
||||||
|
'activated': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||||
|
'amazon_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'deadline': ('django.db.models.fields.DateTimeField', [], {}),
|
||||||
|
'description': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
|
||||||
|
'details': ('ckeditor.fields.RichTextField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'null': 'True', 'to': "orm['core.Edition']"}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'left': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}),
|
||||||
|
'license': ('django.db.models.fields.CharField', [], {'default': "'CC BY-NC-ND'", 'max_length': '255'}),
|
||||||
|
'managers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'campaigns'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
|
||||||
|
'name': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
|
||||||
|
'paypal_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||||
|
'status': ('django.db.models.fields.CharField', [], {'default': "'INITIALIZED'", 'max_length': '15', 'null': 'True'}),
|
||||||
|
'target': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}),
|
||||||
|
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'to': "orm['core.Work']"})
|
||||||
|
},
|
||||||
|
'core.edition': {
|
||||||
|
'Meta': {'object_name': 'Edition'},
|
||||||
|
'cover_image': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'public_domain': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'publication_date': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'publisher': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||||
|
'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.premium': {
|
||||||
|
'Meta': {'object_name': 'Premium'},
|
||||||
|
'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '0'}),
|
||||||
|
'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'premiums'", 'null': 'True', 'to': "orm['core.Campaign']"}),
|
||||||
|
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'description': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'limit': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'type': ('django.db.models.fields.CharField', [], {'max_length': '2'})
|
||||||
|
},
|
||||||
|
'core.work': {
|
||||||
|
'Meta': {'ordering': "['title']", 'object_name': 'Work'},
|
||||||
|
'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'}),
|
||||||
|
'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}),
|
||||||
|
'num_wishes': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'openlibrary_lookup': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||||
|
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
|
||||||
|
},
|
||||||
|
'payment.credit': {
|
||||||
|
'Meta': {'object_name': 'Credit'},
|
||||||
|
'balance': ('django.db.models.fields.DecimalField', [], {'default': "'0.00'", 'max_digits': '14', 'decimal_places': '2'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'last_activity': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||||
|
'pledged': ('django.db.models.fields.DecimalField', [], {'default': "'0.00'", 'max_digits': '14', 'decimal_places': '2'}),
|
||||||
|
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'credit'", 'unique': 'True', 'to': "orm['auth.User']"})
|
||||||
|
},
|
||||||
|
'payment.creditlog': {
|
||||||
|
'Meta': {'object_name': 'CreditLog'},
|
||||||
|
'action': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
|
||||||
|
'amount': ('django.db.models.fields.DecimalField', [], {'default': "'0.00'", 'max_digits': '14', 'decimal_places': '2'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'})
|
||||||
|
},
|
||||||
|
'payment.paymentresponse': {
|
||||||
|
'Meta': {'object_name': 'PaymentResponse'},
|
||||||
|
'api': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||||
|
'correlation_id': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'info': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'}),
|
||||||
|
'status': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),
|
||||||
|
'timestamp': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}),
|
||||||
|
'transaction': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['payment.Transaction']"})
|
||||||
|
},
|
||||||
|
'payment.receiver': {
|
||||||
|
'Meta': {'object_name': 'Receiver'},
|
||||||
|
'amount': ('django.db.models.fields.DecimalField', [], {'default': "'0.00'", 'max_digits': '14', 'decimal_places': '2'}),
|
||||||
|
'currency': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
|
||||||
|
'email': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'local_status': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
|
||||||
|
'primary': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'reason': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||||
|
'status': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
|
||||||
|
'transaction': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['payment.Transaction']"}),
|
||||||
|
'txn_id': ('django.db.models.fields.CharField', [], {'max_length': '64'})
|
||||||
|
},
|
||||||
|
'payment.transaction': {
|
||||||
|
'Meta': {'object_name': 'Transaction'},
|
||||||
|
'ack_dedication': ('django.db.models.fields.CharField', [], {'max_length': '140', 'null': 'True'}),
|
||||||
|
'ack_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
|
||||||
|
'amount': ('django.db.models.fields.DecimalField', [], {'default': "'0.00'", 'max_digits': '14', 'decimal_places': '2'}),
|
||||||
|
'anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'approved': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
|
||||||
|
'campaign': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Campaign']", 'null': 'True'}),
|
||||||
|
'currency': ('django.db.models.fields.CharField', [], {'default': "'USD'", 'max_length': '10', 'null': 'True'}),
|
||||||
|
'date_authorized': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||||
|
'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||||
|
'date_executed': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||||
|
'date_expired': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||||
|
'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||||
|
'date_payment': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||||
|
'error': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True'}),
|
||||||
|
'execution': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'host': ('django.db.models.fields.CharField', [], {'default': "'none'", 'max_length': '32'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'local_status': ('django.db.models.fields.CharField', [], {'default': "'NONE'", 'max_length': '32', 'null': 'True'}),
|
||||||
|
'max_amount': ('django.db.models.fields.DecimalField', [], {'default': "'0.00'", 'max_digits': '14', 'decimal_places': '2'}),
|
||||||
|
'pay_key': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}),
|
||||||
|
'preapproval_key': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}),
|
||||||
|
'premium': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Premium']", 'null': 'True'}),
|
||||||
|
'reason': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
|
||||||
|
'receipt': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True'}),
|
||||||
|
'secret': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
|
||||||
|
'status': ('django.db.models.fields.CharField', [], {'default': "'None'", 'max_length': '32'}),
|
||||||
|
'type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
complete_apps = ['payment']
|
|
@ -4,8 +4,11 @@ from django.conf import settings
|
||||||
from regluit.core.models import Campaign, Wishlist, Premium
|
from regluit.core.models import Campaign, Wishlist, Premium
|
||||||
from regluit.payment.parameters import *
|
from regluit.payment.parameters import *
|
||||||
from regluit.payment.signals import credit_balance_added
|
from regluit.payment.signals import credit_balance_added
|
||||||
from decimal import Decimal
|
from decimal import Decimal, NaN
|
||||||
import uuid
|
import uuid
|
||||||
|
import urllib
|
||||||
|
import logging
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Transaction(models.Model):
|
class Transaction(models.Model):
|
||||||
|
@ -14,16 +17,13 @@ class Transaction(models.Model):
|
||||||
type = models.IntegerField(default=PAYMENT_TYPE_NONE, null=False)
|
type = models.IntegerField(default=PAYMENT_TYPE_NONE, null=False)
|
||||||
|
|
||||||
# host: the payment processor. Named after the payment module that hosts the payment processing functions
|
# host: the payment processor. Named after the payment module that hosts the payment processing functions
|
||||||
host = models.CharField(default=settings.PAYMENT_PROCESSOR, max_length=32, null=False)
|
host = models.CharField(default=PAYMENT_HOST_NONE, max_length=32, null=False)
|
||||||
|
|
||||||
# target: e.g, TARGET_TYPE_CAMPAIGN, TARGET_TYPE_LIST -- defined in parameters.py
|
|
||||||
target = models.IntegerField(default=TARGET_TYPE_NONE, null=False)
|
|
||||||
|
|
||||||
#execution: e.g. EXECUTE_TYPE_CHAINED_INSTANT, EXECUTE_TYPE_CHAINED_DELAYED, EXECUTE_TYPE_PARALLEL
|
#execution: e.g. EXECUTE_TYPE_CHAINED_INSTANT, EXECUTE_TYPE_CHAINED_DELAYED, EXECUTE_TYPE_PARALLEL
|
||||||
execution = models.IntegerField(default=EXECUTE_TYPE_NONE, null=False)
|
execution = models.IntegerField(default=EXECUTE_TYPE_NONE, null=False)
|
||||||
|
|
||||||
# status: general status constants defined in parameters.py
|
# status: general status constants defined in parameters.py
|
||||||
status = models.CharField(max_length=32, default='None', null=False)
|
status = models.CharField(max_length=32, default=TRANSACTION_STATUS_NONE, null=False)
|
||||||
|
|
||||||
# local_status: status code specific to the payment processor
|
# local_status: status code specific to the payment processor
|
||||||
local_status = models.CharField(max_length=32, default='NONE', null=True)
|
local_status = models.CharField(max_length=32, default='NONE', null=True)
|
||||||
|
@ -75,14 +75,14 @@ class Transaction(models.Model):
|
||||||
|
|
||||||
# how to acknowledge the user on the supporter page of the campaign ebook
|
# how to acknowledge the user on the supporter page of the campaign ebook
|
||||||
ack_name = models.CharField(max_length=64, null=True)
|
ack_name = models.CharField(max_length=64, null=True)
|
||||||
ack_link = models.URLField(null=True)
|
|
||||||
ack_dedication = models.CharField(max_length=140, null=True)
|
ack_dedication = models.CharField(max_length=140, null=True)
|
||||||
|
|
||||||
# whether the user wants to be not listed publicly
|
# whether the user wants to be not listed publicly
|
||||||
anonymous = models.BooleanField(null=False)
|
anonymous = models.BooleanField(null=False)
|
||||||
|
|
||||||
# list: makes allowance for pledging against a Wishlist: not currently in use
|
@property
|
||||||
list = models.ForeignKey(Wishlist, null=True)
|
def ack_link(self):
|
||||||
|
return 'https://unglue.it/supporter/%s'%urllib.urlencode(self.user.username)
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if not self.secret:
|
if not self.secret:
|
||||||
|
@ -149,10 +149,17 @@ class Receiver(models.Model):
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u"Receiver -- email: {0} status: {1} transaction: {2}".format(self.email, self.status, unicode(self.transaction))
|
return u"Receiver -- email: {0} status: {1} transaction: {2}".format(self.email, self.status, unicode(self.transaction))
|
||||||
|
|
||||||
|
class CreditLog(models.Model):
|
||||||
|
# a write only record of Donation Credit Transactions
|
||||||
|
user = models.ForeignKey(User, null=True)
|
||||||
|
amount = models.DecimalField(default=Decimal('0.00'), max_digits=14, decimal_places=2) # max 999,999,999,999.99
|
||||||
|
timestamp = models.DateTimeField(auto_now=True)
|
||||||
|
action = models.CharField(max_length=16)
|
||||||
|
|
||||||
class Credit(models.Model):
|
class Credit(models.Model):
|
||||||
user = models.OneToOneField(User, related_name='credit')
|
user = models.OneToOneField(User, related_name='credit')
|
||||||
balance = models.IntegerField(default=0)
|
balance = models.DecimalField(default=Decimal('0.00'), max_digits=14, decimal_places=2) # max 999,999,999,999.99
|
||||||
pledged = models.IntegerField(default=0)
|
pledged = models.DecimalField(default=Decimal('0.00'), max_digits=14, decimal_places=2) # max 999,999,999,999.99
|
||||||
last_activity = models.DateTimeField(auto_now=True)
|
last_activity = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -165,17 +172,29 @@ class Credit(models.Model):
|
||||||
else:
|
else:
|
||||||
self.balance = self.balance + num_credits
|
self.balance = self.balance + num_credits
|
||||||
self.save()
|
self.save()
|
||||||
credit_balance_added.send(sender=self, amount=num_credits)
|
try: # bad things can happen here if you don't return True
|
||||||
|
CreditLog(user = self.user, amount = num_credits, action="add_to_balance").save()
|
||||||
|
except:
|
||||||
|
logger.exception("failed to log add_to_balance of %s", num_credits)
|
||||||
|
try:
|
||||||
|
credit_balance_added.send(sender=self, amount=num_credits)
|
||||||
|
except:
|
||||||
|
logger.exception("credit_balance_added failed of %s", num_credits)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def add_to_pledged(self, num_credits):
|
def add_to_pledged(self, num_credits):
|
||||||
if not isinstance( num_credits, int):
|
num_credits=Decimal(num_credits)
|
||||||
|
if num_credits is NaN:
|
||||||
return False
|
return False
|
||||||
if self.balance - self.pledged < num_credits :
|
if self.balance - self.pledged < num_credits :
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
self.pledged=self.pledged + num_credits
|
self.pledged=self.pledged + num_credits
|
||||||
self.save()
|
self.save()
|
||||||
|
try: # bad things can happen here if you don't return True
|
||||||
|
CreditLog(user = self.user, amount = num_credits, action="add_to_pledged").save()
|
||||||
|
except:
|
||||||
|
logger.exception("failed to log add_to_pledged of %s", num_credits)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def use_pledge(self, num_credits):
|
def use_pledge(self, num_credits):
|
||||||
|
@ -187,6 +206,10 @@ class Credit(models.Model):
|
||||||
self.pledged=self.pledged - num_credits
|
self.pledged=self.pledged - num_credits
|
||||||
self.balance = self.balance - num_credits
|
self.balance = self.balance - num_credits
|
||||||
self.save()
|
self.save()
|
||||||
|
try:
|
||||||
|
CreditLog(user = self.user, amount = - num_credits, action="use_pledge").save()
|
||||||
|
except:
|
||||||
|
logger.exception("failed to log use_pledge of %s", num_credits)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def transfer_to(self, receiver, num_credits):
|
def transfer_to(self, receiver, num_credits):
|
||||||
|
|
|
@ -5,17 +5,15 @@ PAYMENT_TYPE_AUTHORIZATION = 2
|
||||||
PAYMENT_HOST_NONE = "none"
|
PAYMENT_HOST_NONE = "none"
|
||||||
PAYMENT_HOST_PAYPAL = "paypal"
|
PAYMENT_HOST_PAYPAL = "paypal"
|
||||||
PAYMENT_HOST_AMAZON = "amazon"
|
PAYMENT_HOST_AMAZON = "amazon"
|
||||||
|
PAYMENT_HOST_TEST = "test"
|
||||||
|
PAYMENT_HOST_CREDIT = "credit"
|
||||||
|
PAYMENT_HOST_STRIPE = "stripe"
|
||||||
|
|
||||||
EXECUTE_TYPE_NONE = 0
|
EXECUTE_TYPE_NONE = 0
|
||||||
EXECUTE_TYPE_CHAINED_INSTANT = 1
|
EXECUTE_TYPE_CHAINED_INSTANT = 1
|
||||||
EXECUTE_TYPE_CHAINED_DELAYED = 2
|
EXECUTE_TYPE_CHAINED_DELAYED = 2
|
||||||
EXECUTE_TYPE_PARALLEL = 3
|
EXECUTE_TYPE_PARALLEL = 3
|
||||||
|
|
||||||
TARGET_TYPE_NONE = 0
|
|
||||||
TARGET_TYPE_CAMPAIGN = 1
|
|
||||||
TARGET_TYPE_LIST = 2
|
|
||||||
TARGET_TYPE_DONATION = 3
|
|
||||||
|
|
||||||
# The default status for a transaction that is newly created
|
# The default status for a transaction that is newly created
|
||||||
TRANSACTION_STATUS_NONE = 'None'
|
TRANSACTION_STATUS_NONE = 'None'
|
||||||
|
|
||||||
|
@ -47,6 +45,3 @@ TRANSACTION_STATUS_REFUNDED = 'Refunded'
|
||||||
# The transaction was refused/denied
|
# The transaction was refused/denied
|
||||||
TRANSACTION_STATUS_FAILED = 'Failed'
|
TRANSACTION_STATUS_FAILED = 'Failed'
|
||||||
|
|
||||||
# these two following parameters are probably extraneous since I think we will compute dynamically where to return each time.
|
|
||||||
COMPLETE_URL = '/paymentcomplete'
|
|
||||||
NEVERMIND_URL = '/paymentnevermind'
|
|
||||||
|
|
|
@ -190,7 +190,7 @@ class PledgeTest(TestCase):
|
||||||
|
|
||||||
# Note, set this to 1-5 different receivers with absolute amounts for each
|
# Note, set this to 1-5 different receivers with absolute amounts for each
|
||||||
receiver_list = [{'email':settings.PAYPAL_GLUEJAR_EMAIL, 'amount':20.00}]
|
receiver_list = [{'email':settings.PAYPAL_GLUEJAR_EMAIL, 'amount':20.00}]
|
||||||
t, url = p.pledge('USD', TARGET_TYPE_NONE, receiver_list, campaign=None, list=None, user=None)
|
t, url = p.pledge('USD', receiver_list, campaign=None, list=None, user=None)
|
||||||
|
|
||||||
self.validateRedirect(t, url, 1)
|
self.validateRedirect(t, url, 1)
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ class PledgeTest(TestCase):
|
||||||
receiver_list = [{'email':settings.PAYPAL_GLUEJAR_EMAIL, 'amount':20.00},
|
receiver_list = [{'email':settings.PAYPAL_GLUEJAR_EMAIL, 'amount':20.00},
|
||||||
{'email':settings.PAYPAL_TEST_RH_EMAIL, 'amount':10.00}]
|
{'email':settings.PAYPAL_TEST_RH_EMAIL, 'amount':10.00}]
|
||||||
|
|
||||||
t, url = p.pledge('USD', TARGET_TYPE_NONE, receiver_list, campaign=None, list=None, user=None)
|
t, url = p.pledge('USD', receiver_list, campaign=None, list=None, user=None)
|
||||||
|
|
||||||
self.validateRedirect(t, url, 2)
|
self.validateRedirect(t, url, 2)
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ class PledgeTest(TestCase):
|
||||||
|
|
||||||
# Note, set this to 1-5 different receivers with absolute amounts for each
|
# Note, set this to 1-5 different receivers with absolute amounts for each
|
||||||
receiver_list = [{'email':settings.PAYPAL_GLUEJAR_EMAIL, 'amount':50000.00}]
|
receiver_list = [{'email':settings.PAYPAL_GLUEJAR_EMAIL, 'amount':50000.00}]
|
||||||
t, url = p.pledge('USD', TARGET_TYPE_NONE, receiver_list, campaign=None, list=None, user=None)
|
t, url = p.pledge('USD', receiver_list, campaign=None, list=None, user=None)
|
||||||
|
|
||||||
self.validateRedirect(t, url, 1)
|
self.validateRedirect(t, url, 1)
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ class AuthorizeTest(TestCase):
|
||||||
|
|
||||||
# Note, set this to 1-5 different receivers with absolute amounts for each
|
# Note, set this to 1-5 different receivers with absolute amounts for each
|
||||||
|
|
||||||
t, url = p.authorize('USD', TARGET_TYPE_NONE, 100.0, campaign=None, list=None, user=None)
|
t, url = p.authorize('USD', 100.0, campaign=None, list=None, user=None)
|
||||||
|
|
||||||
self.validateRedirect(t, url)
|
self.validateRedirect(t, url)
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ class BasicGuiTest(TestCase):
|
||||||
def suite():
|
def suite():
|
||||||
|
|
||||||
#testcases = [PledgeTest, AuthorizeTest, TransactionTest]
|
#testcases = [PledgeTest, AuthorizeTest, TransactionTest]
|
||||||
testcases = [TransactionTest]
|
testcases = [TransactionTest, CreditTest]
|
||||||
suites = unittest.TestSuite([unittest.TestLoader().loadTestsFromTestCase(testcase) for testcase in testcases])
|
suites = unittest.TestSuite([unittest.TestLoader().loadTestsFromTestCase(testcase) for testcase in testcases])
|
||||||
return suites
|
return suites
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,6 @@ if settings.DEBUG:
|
||||||
url(r"^testexecute", "testExecute"),
|
url(r"^testexecute", "testExecute"),
|
||||||
url(r"^testcancel", "testCancel"),
|
url(r"^testcancel", "testCancel"),
|
||||||
url(r"^querycampaign", "queryCampaign"),
|
url(r"^querycampaign", "queryCampaign"),
|
||||||
url(r"^runtests", "runTests"),
|
|
||||||
url(r"^paymentcomplete","paymentcomplete"),
|
|
||||||
url(r"^checkstatus", "checkStatus"),
|
url(r"^checkstatus", "checkStatus"),
|
||||||
url(r"^testfinish", "testFinish"),
|
url(r"^testfinish", "testFinish"),
|
||||||
url(r"^testrefund", "testRefund"),
|
url(r"^testrefund", "testRefund"),
|
||||||
|
|
|
@ -13,7 +13,8 @@ from django.test.utils import setup_test_environment
|
||||||
from django.template import RequestContext
|
from django.template import RequestContext
|
||||||
|
|
||||||
from unittest import TestResult
|
from unittest import TestResult
|
||||||
from regluit.payment.tests import PledgeTest, AuthorizeTest
|
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
from decimal import Decimal as D
|
from decimal import Decimal as D
|
||||||
|
|
||||||
|
@ -112,12 +113,8 @@ def testAuthorize(request):
|
||||||
receiver_list = [{'email': TEST_RECEIVERS[0], 'amount':20.00},
|
receiver_list = [{'email': TEST_RECEIVERS[0], 'amount':20.00},
|
||||||
{'email': TEST_RECEIVERS[1], 'amount':10.00}]
|
{'email': TEST_RECEIVERS[1], 'amount':10.00}]
|
||||||
|
|
||||||
if campaign_id:
|
campaign = Campaign.objects.get(id=int(campaign_id))
|
||||||
campaign = Campaign.objects.get(id=int(campaign_id))
|
t, url = p.authorize('USD', amount, campaign=campaign, return_url=None, list=None, user=None)
|
||||||
t, url = p.authorize('USD', TARGET_TYPE_CAMPAIGN, amount, campaign=campaign, return_url=None, list=None, user=None)
|
|
||||||
|
|
||||||
else:
|
|
||||||
t, url = p.authorize('USD', TARGET_TYPE_NONE, amount, campaign=None, return_url=None, list=None, user=None)
|
|
||||||
|
|
||||||
if url:
|
if url:
|
||||||
logger.info("testAuthorize: " + url)
|
logger.info("testAuthorize: " + url)
|
||||||
|
@ -248,12 +245,9 @@ def testPledge(request):
|
||||||
else:
|
else:
|
||||||
receiver_list = [{'email':TEST_RECEIVERS[0], 'amount':78.90}, {'email':TEST_RECEIVERS[1], 'amount':34.56}]
|
receiver_list = [{'email':TEST_RECEIVERS[0], 'amount':78.90}, {'email':TEST_RECEIVERS[1], 'amount':34.56}]
|
||||||
|
|
||||||
if campaign_id:
|
campaign = Campaign.objects.get(id=int(campaign_id))
|
||||||
campaign = Campaign.objects.get(id=int(campaign_id))
|
t, url = p.pledge('USD', receiver_list, campaign=campaign, list=None, user=user, return_url=None)
|
||||||
t, url = p.pledge('USD', TARGET_TYPE_CAMPAIGN, receiver_list, campaign=campaign, list=None, user=user, return_url=None)
|
|
||||||
|
|
||||||
else:
|
|
||||||
t, url = p.pledge('USD', TARGET_TYPE_NONE, receiver_list, campaign=None, list=None, user=user, return_url=None)
|
|
||||||
|
|
||||||
if url:
|
if url:
|
||||||
logger.info("testPledge: " + url)
|
logger.info("testPledge: " + url)
|
||||||
|
@ -264,33 +258,6 @@ def testPledge(request):
|
||||||
logger.info("testPledge: Error " + str(t.error))
|
logger.info("testPledge: Error " + str(t.error))
|
||||||
return HttpResponse(response)
|
return HttpResponse(response)
|
||||||
|
|
||||||
def runTests(request):
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Setup the test environement. We need to run these tests on a live server
|
|
||||||
# so our code can receive IPN notifications from paypal
|
|
||||||
setup_test_environment()
|
|
||||||
result = TestResult()
|
|
||||||
|
|
||||||
# Run the authorize test
|
|
||||||
test = AuthorizeTest('test_authorize')
|
|
||||||
test.run(result)
|
|
||||||
|
|
||||||
# Run the pledge test
|
|
||||||
test = PledgeTest('test_pledge_single_receiver')
|
|
||||||
test.run(result)
|
|
||||||
|
|
||||||
# Run the pledge failure test
|
|
||||||
test = PledgeTest('test_pledge_too_much')
|
|
||||||
test.run(result)
|
|
||||||
|
|
||||||
output = "Tests Run: " + str(result.testsRun) + str(result.errors) + str(result.failures)
|
|
||||||
logger.info(output)
|
|
||||||
|
|
||||||
return HttpResponse(output)
|
|
||||||
|
|
||||||
except:
|
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def handleIPN(request, module):
|
def handleIPN(request, module):
|
||||||
|
@ -303,11 +270,6 @@ def handleIPN(request, module):
|
||||||
return HttpResponse("ipn")
|
return HttpResponse("ipn")
|
||||||
|
|
||||||
|
|
||||||
def paymentcomplete(request):
|
|
||||||
# pick up all get and post parameters and display
|
|
||||||
output = "payment complete"
|
|
||||||
output += request.method + "\n" + str(request.REQUEST.items())
|
|
||||||
return HttpResponse(output)
|
|
||||||
|
|
||||||
def checkStatus(request):
|
def checkStatus(request):
|
||||||
# Check the status of all PAY transactions and flag any errors
|
# Check the status of all PAY transactions and flag any errors
|
||||||
|
|
Loading…
Reference in New Issue