Revision c4028837

b/snf-astakos-app/astakos/im/forms.py
906 906

  
907 907
    def save(self, commit=True):
908 908
        data = dict(self.cleaned_data)
909
        data['precursor_id'] = self.instance.id
910 909
        is_new = self.instance.id is None
910
        data['project_id'] = self.instance.chain.id if not is_new else None
911 911
        data['owner'] = self.user if is_new else self.instance.owner
912 912
        data['resource_policies'] = self.cleaned_resource_policies()
913 913
        data['request_user'] = self.user
b/snf-astakos-app/astakos/im/functions.py
573 573

  
574 574
def submit_application(owner=None,
575 575
                       name=None,
576
                       precursor_id=None,
576
                       project_id=None,
577 577
                       homepage=None,
578 578
                       description=None,
579 579
                       start_date=None,
......
585 585
                       resource_policies=None,
586 586
                       request_user=None):
587 587

  
588
    precursor = None
589
    if precursor_id is not None:
590
        get_chain_of_application_for_update(precursor_id)
591
        precursor = ProjectApplication.objects.get(id=precursor_id)
588
    project = None
589
    if project_id is not None:
590
        get_chain_for_update(project_id)
591
        project = Project.objects.get(id=project_id)
592 592

  
593 593
        if (request_user and
594
            (not precursor.owner == request_user and
594
            (not project.application.owner == request_user and
595 595
             not request_user.is_superuser
596 596
             and not request_user.is_project_admin())):
597 597
            m = _(astakos_messages.NOT_ALLOWED)
598 598
            raise PermissionDenied(m)
599 599

  
600 600
    force = request_user.is_project_admin()
601
    ok, limit = qh_add_pending_app(owner, precursor, force)
601
    ok, limit = qh_add_pending_app(owner, project, force)
602 602
    if not ok:
603 603
        m = _(astakos_messages.REACHED_PENDING_APPLICATION_LIMIT) % limit
604 604
        raise PermissionDenied(m)
......
607 607
        applicant=request_user,
608 608
        owner=owner,
609 609
        name=name,
610
        precursor_application_id=precursor_id,
611 610
        homepage=homepage,
612 611
        description=description,
613 612
        start_date=start_date,
......
617 616
        limit_on_members_number=limit_on_members_number,
618 617
        comments=comments)
619 618

  
620
    if precursor is None:
619
    if project is None:
621 620
        chain = new_chain()
622 621
        application.chain_id = chain.chain
623 622
        application.save()
624 623
        Project.objects.create(id=chain.chain, application=application)
625 624
    else:
626
        chain = precursor.chain
627
        application.chain = chain
625
        application.chain = project
628 626
        application.save()
629
        if chain.application.state != ProjectApplication.APPROVED:
630
            chain.application = application
631
            chain.save()
627
        if project.application.state != ProjectApplication.APPROVED:
628
            project.application = application
629
            project.save()
632 630

  
633 631
        pending = ProjectApplication.objects.filter(
634
            chain=chain,
632
            chain=project,
635 633
            state=ProjectApplication.PENDING).exclude(id=application.id)
636 634
        for app in pending:
637 635
            app.state = ProjectApplication.REPLACED
......
816 814
    return usage
817 815

  
818 816

  
819
def get_pending_app_diff(user, precursor):
820
    if precursor is None:
817
def get_pending_app_diff(user, project):
818
    if project is None:
821 819
        diff = 1
822 820
    else:
823
        chain = precursor.chain
824 821
        objs = ProjectApplication.objects
825
        q = objs.filter(chain=chain, state=ProjectApplication.PENDING)
822
        q = objs.filter(chain=project, state=ProjectApplication.PENDING)
826 823
        count = q.count()
827 824
        diff = 1 - count
828 825
    return diff
829 826

  
830 827

  
831
def qh_add_pending_app(user, precursor=None, force=False):
828
def qh_add_pending_app(user, project=None, force=False):
832 829
    user = AstakosUser.forupdate.get_for_update(id=user.id)
833
    diff = get_pending_app_diff(user, precursor)
830
    diff = get_pending_app_diff(user, project)
834 831
    return register_pending_apps(user, diff, force)
835 832

  
836 833

  
837
def check_pending_app_quota(user, precursor=None):
838
    diff = get_pending_app_diff(user, precursor)
834
def check_pending_app_quota(user, project=None):
835
    diff = get_pending_app_diff(user, project)
839 836
    quota = get_pending_app_quota(user)
840 837
    limit = quota['limit']
841 838
    usage = quota['usage']
b/snf-astakos-app/astakos/im/migrations/0045_auto__del_field_projectapplication_precursor_application.py
1
# encoding: utf-8
2
import datetime
3
from south.db import db
4
from south.v2 import SchemaMigration
5
from django.db import models
6

  
7
class Migration(SchemaMigration):
8
    
9
    def forwards(self, orm):
10
        
11
        # Deleting field 'ProjectApplication.precursor_application'
12
        db.delete_column('im_projectapplication', 'precursor_application_id')
13
    
14
    
15
    def backwards(self, orm):
16
        
17
        # Adding field 'ProjectApplication.precursor_application'
18
        db.add_column('im_projectapplication', 'precursor_application', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['im.ProjectApplication'], null=True, blank=True), keep_default=False)
19
    
20
    
21
    models = {
22
        'auth.group': {
23
            'Meta': {'object_name': 'Group'},
24
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
25
            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
26
            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
27
        },
28
        'auth.permission': {
29
            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
30
            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
31
            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
32
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
33
            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
34
        },
35
        'auth.user': {
36
            'Meta': {'object_name': 'User'},
37
            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
38
            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
39
            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
40
            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
41
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
42
            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
43
            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
44
            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
45
            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
46
            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
47
            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
48
            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
49
            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
50
        },
51
        'contenttypes.contenttype': {
52
            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
53
            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
54
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
55
            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
56
            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
57
        },
58
        'im.additionalmail': {
59
            'Meta': {'object_name': 'AdditionalMail'},
60
            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
61
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
62
            'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.AstakosUser']"})
63
        },
64
        'im.approvalterms': {
65
            'Meta': {'object_name': 'ApprovalTerms'},
66
            'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
67
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
68
            'location': ('django.db.models.fields.CharField', [], {'max_length': '255'})
69
        },
70
        'im.astakosuser': {
71
            'Meta': {'object_name': 'AstakosUser', '_ormbases': ['auth.User']},
72
            'accepted_email': ('django.db.models.fields.EmailField', [], {'default': 'None', 'max_length': '75', 'null': 'True', 'blank': 'True'}),
73
            'accepted_policy': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
74
            'activation_sent': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
75
            'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
76
            'auth_token': ('django.db.models.fields.CharField', [], {'max_length': '64', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
77
            'auth_token_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
78
            'auth_token_expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
79
            'date_signed_terms': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
80
            'deactivated_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
81
            'deactivated_reason': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
82
            'disturbed_quota': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True', 'blank': 'True'}),
83
            'email_verified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
84
            'has_credits': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
85
            'has_signed_terms': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
86
            'invitations': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
87
            'is_rejected': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
88
            'is_verified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
89
            'level': ('django.db.models.fields.IntegerField', [], {'default': '4'}),
90
            'moderated': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
91
            'moderated_at': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
92
            'moderated_data': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
93
            'policy': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['im.Resource']", 'null': 'True', 'through': "orm['im.AstakosUserQuota']", 'symmetrical': 'False'}),
94
            'rejected_reason': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
95
            'updated': ('django.db.models.fields.DateTimeField', [], {}),
96
            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),
97
            'uuid': ('django.db.models.fields.CharField', [], {'max_length': '255', 'unique': 'True', 'null': 'True'}),
98
            'verification_code': ('django.db.models.fields.CharField', [], {'max_length': '255', 'unique': 'True', 'null': 'True'}),
99
            'verified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
100
        },
101
        'im.astakosuserauthprovider': {
102
            'Meta': {'unique_together': "(('identifier', 'module', 'user'),)", 'object_name': 'AstakosUserAuthProvider'},
103
            'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
104
            'affiliation': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
105
            'auth_backend': ('django.db.models.fields.CharField', [], {'default': "'astakos'", 'max_length': '255'}),
106
            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
107
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
108
            'identifier': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
109
            'info_data': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True', 'blank': 'True'}),
110
            'module': ('django.db.models.fields.CharField', [], {'default': "'local'", 'max_length': '255'}),
111
            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_providers'", 'to': "orm['im.AstakosUser']"})
112
        },
113
        'im.astakosuserquota': {
114
            'Meta': {'unique_together': "(('resource', 'user'),)", 'object_name': 'AstakosUserQuota'},
115
            'capacity': ('snf_django.lib.db.fields.IntDecimalField', [], {'max_digits': '38', 'decimal_places': '0'}),
116
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
117
            'resource': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.Resource']"}),
118
            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.AstakosUser']"})
119
        },
120
        'im.authproviderpolicyprofile': {
121
            'Meta': {'object_name': 'AuthProviderPolicyProfile'},
122
            'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
123
            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'authpolicy_profiles'", 'symmetrical': 'False', 'to': "orm['auth.Group']"}),
124
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
125
            'is_exclusive': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
126
            'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
127
            'policy_add': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
128
            'policy_automoderate': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
129
            'policy_create': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
130
            'policy_limit': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
131
            'policy_login': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
132
            'policy_remove': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
133
            'policy_required': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
134
            'policy_switch': ('django.db.models.fields.NullBooleanField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
135
            'priority': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
136
            'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
137
            'users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'authpolicy_profiles'", 'symmetrical': 'False', 'to': "orm['im.AstakosUser']"})
138
        },
139
        'im.chain': {
140
            'Meta': {'object_name': 'Chain'},
141
            'chain': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
142
        },
143
        'im.component': {
144
            'Meta': {'object_name': 'Component'},
145
            'auth_token': ('django.db.models.fields.CharField', [], {'max_length': '64', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
146
            'auth_token_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
147
            'auth_token_expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
148
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
149
            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'}),
150
            'url': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True'})
151
        },
152
        'im.emailchange': {
153
            'Meta': {'object_name': 'EmailChange'},
154
            'activation_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
155
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
156
            'new_email_address': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
157
            'requested_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
158
            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emailchanges'", 'unique': 'True', 'to': "orm['im.AstakosUser']"})
159
        },
160
        'im.endpoint': {
161
            'Meta': {'object_name': 'Endpoint'},
162
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
163
            'service': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'endpoints'", 'to': "orm['im.Service']"})
164
        },
165
        'im.endpointdata': {
166
            'Meta': {'unique_together': "(('endpoint', 'key'),)", 'object_name': 'EndpointData'},
167
            'endpoint': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'data'", 'to': "orm['im.Endpoint']"}),
168
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
169
            'key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
170
            'value': ('django.db.models.fields.CharField', [], {'max_length': '1024'})
171
        },
172
        'im.invitation': {
173
            'Meta': {'object_name': 'Invitation'},
174
            'code': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True'}),
175
            'consumed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
176
            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
177
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
178
            'inviter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'invitations_sent'", 'null': 'True', 'to': "orm['im.AstakosUser']"}),
179
            'is_consumed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
180
            'realname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
181
            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
182
        },
183
        'im.pendingthirdpartyuser': {
184
            'Meta': {'unique_together': "(('provider', 'third_party_identifier'),)", 'object_name': 'PendingThirdPartyUser'},
185
            'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
186
            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
187
            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
188
            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
189
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
190
            'info': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True', 'blank': 'True'}),
191
            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}),
192
            'provider': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
193
            'third_party_identifier': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
194
            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
195
            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
196
        },
197
        'im.project': {
198
            'Meta': {'object_name': 'Project'},
199
            'application': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'project'", 'unique': 'True', 'to': "orm['im.ProjectApplication']"}),
200
            'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
201
            'deactivation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
202
            'deactivation_reason': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
203
            'id': ('django.db.models.fields.BigIntegerField', [], {'primary_key': 'True', 'db_column': "'id'"}),
204
            'last_approval_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
205
            'members': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['im.AstakosUser']", 'through': "orm['im.ProjectMembership']", 'symmetrical': 'False'}),
206
            'name': ('django.db.models.fields.CharField', [], {'max_length': '80', 'unique': 'True', 'null': 'True', 'db_index': 'True'}),
207
            'state': ('django.db.models.fields.IntegerField', [], {'default': '1', 'db_index': 'True'})
208
        },
209
        'im.projectapplication': {
210
            'Meta': {'unique_together': "(('chain', 'id'),)", 'object_name': 'ProjectApplication'},
211
            'applicant': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projects_applied'", 'to': "orm['im.AstakosUser']"}),
212
            'chain': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'chained_apps'", 'db_column': "'chain'", 'to': "orm['im.Project']"}),
213
            'comments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
214
            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
215
            'end_date': ('django.db.models.fields.DateTimeField', [], {}),
216
            'homepage': ('django.db.models.fields.URLField', [], {'max_length': '255', 'null': 'True'}),
217
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
218
            'issue_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
219
            'limit_on_members_number': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
220
            'member_join_policy': ('django.db.models.fields.IntegerField', [], {}),
221
            'member_leave_policy': ('django.db.models.fields.IntegerField', [], {}),
222
            'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
223
            'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projects_owned'", 'to': "orm['im.AstakosUser']"}),
224
            'resource_grants': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['im.Resource']", 'null': 'True', 'through': "orm['im.ProjectResourceGrant']", 'blank': 'True'}),
225
            'response': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
226
            'response_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
227
            'start_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
228
            'state': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True'})
229
        },
230
        'im.projectmembership': {
231
            'Meta': {'unique_together': "(('person', 'project'),)", 'object_name': 'ProjectMembership'},
232
            'acceptance_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
233
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
234
            'leave_request_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
235
            'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.AstakosUser']"}),
236
            'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.Project']"}),
237
            'request_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
238
            'state': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True'})
239
        },
240
        'im.projectmembershiphistory': {
241
            'Meta': {'object_name': 'ProjectMembershipHistory'},
242
            'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
243
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
244
            'person': ('django.db.models.fields.BigIntegerField', [], {}),
245
            'project': ('django.db.models.fields.BigIntegerField', [], {}),
246
            'reason': ('django.db.models.fields.IntegerField', [], {}),
247
            'serial': ('django.db.models.fields.BigIntegerField', [], {})
248
        },
249
        'im.projectresourcegrant': {
250
            'Meta': {'unique_together': "(('resource', 'project_application'),)", 'object_name': 'ProjectResourceGrant'},
251
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
252
            'member_capacity': ('snf_django.lib.db.fields.IntDecimalField', [], {'default': '0', 'max_digits': '38', 'decimal_places': '0'}),
253
            'project_application': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.ProjectApplication']", 'null': 'True'}),
254
            'project_capacity': ('snf_django.lib.db.fields.IntDecimalField', [], {'null': 'True', 'max_digits': '38', 'decimal_places': '0'}),
255
            'resource': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.Resource']"})
256
        },
257
        'im.resource': {
258
            'Meta': {'object_name': 'Resource'},
259
            'allow_in_projects': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
260
            'desc': ('django.db.models.fields.TextField', [], {'null': 'True'}),
261
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
262
            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
263
            'service_origin': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
264
            'service_type': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
265
            'unit': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
266
            'uplimit': ('snf_django.lib.db.fields.IntDecimalField', [], {'default': '0', 'max_digits': '38', 'decimal_places': '0'})
267
        },
268
        'im.serial': {
269
            'Meta': {'object_name': 'Serial'},
270
            'serial': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
271
        },
272
        'im.service': {
273
            'Meta': {'object_name': 'Service'},
274
            'component': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.Component']"}),
275
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
276
            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
277
            'type': ('django.db.models.fields.CharField', [], {'max_length': '255'})
278
        },
279
        'im.sessioncatalog': {
280
            'Meta': {'object_name': 'SessionCatalog'},
281
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
282
            'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
283
            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sessions'", 'null': 'True', 'to': "orm['im.AstakosUser']"})
284
        },
285
        'im.usersetting': {
286
            'Meta': {'unique_together': "(('user', 'setting'),)", 'object_name': 'UserSetting'},
287
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
288
            'setting': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
289
            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.AstakosUser']"}),
290
            'value': ('django.db.models.fields.IntegerField', [], {})
291
        }
292
    }
293
    
294
    complete_apps = ['im']
b/snf-astakos-app/astakos/im/models.py
1356 1356
    chain = models.ForeignKey('Project',
1357 1357
                              related_name='chained_apps',
1358 1358
                              db_column='chain')
1359
    precursor_application = models.ForeignKey('ProjectApplication',
1360
                                              null=True,
1361
                                              blank=True)
1362 1359
    name = models.CharField(max_length=80)
1363 1360
    homepage = models.URLField(max_length=255, null=True,
1364 1361
                               verify_exists=False)
b/snf-astakos-app/astakos/im/templates/im/projects/project_creation_notification.txt
15 15
Owner:                          {{object.owner}}
16 16
Applicant:                      {{object.applicant}}
17 17
Maximum participant number:     {{object.limit_on_members_number}}
18
Precursor:                      {{object.precursor_application.id}}
19 18
Policies:
20 19
{% for rp in object.projectresourcegrant_set.all %}
21 20
    {{rp}}
b/snf-astakos-app/astakos/im/views/projects.py
205 205

  
206 206
    if not user.is_project_admin():
207 207
        owner = app.owner
208
        ok, limit = check_pending_app_quota(owner, precursor=app)
208
        ok, limit = check_pending_app_quota(owner, project=app.chain)
209 209
        if not ok:
210 210
            m = _(astakos_messages.PENDING_APPLICATION_LIMIT_MODIFY) % limit
211 211
            messages.error(request, m)

Also available in: Unified diff