diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 814b64b8e2..9466dfae8f 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -5,6 +5,143 @@ We provide Akvo RSR as a service on your own URL and with your own branding, as Check out [Introducing Akvo Really Simple Reporting](http://akvo.org/products/rsr/). Read more about [Akvo Products](http://akvo.org/products/). +Akvo RSR ver 2.3.6 Voavanga +--- + +Wednesday 14th May 2014, adriancollier + +New Features +--- + +### Add Update button change + +If a user was attempting to add an update to a project that they didn't have the permission for, then they were being served a 403 error page. We have now changed this activity to grey out the Add Update button for users that do not have permission to add updates on individual projects. + +Github issue [#150](https://github.com/akvo/akvo-rsr/issues/150) + +### Character validation in admin + +Now that we are working with XML more deeply with the API and IATI information, we have added validation to the RSR admin to check for any characters that have been included within the added fields that are not valid within XML. A warning is now displayed in the event that any of these characters are present. + +Github issue [#242](https://github.com/akvo/akvo-rsr/issues/242) + +### Back button on Akvo Pages + +We have added a custom option to Akvo Pages to allow the back button to have a different text added. So now our partners can allow this button to say something more appropriate to the location that the user will be taken to upon pressing. + +Github issue [#258](https://github.com/akvo/akvo-rsr/issues/258) + +### Sign in target location + +We have tidied up the signing in process to direct users to the main page after completing the sign in process. + +Github issue [#301](https://github.com/akvo/akvo-rsr/issues/301) + +### Organisation filter on Akvo Pages + +We had previously removed the project filter on Akvo Pages that allows any project to be viewed within a Pages instance. This has now been extended to organisations so that organisations can be visualised within an instance without the need for that organisation to be present within projects. + +Github issue [#433](https://github.com/akvo/akvo-rsr/issues/433) + +### Facebook meta information + +We have tidied up the meta information when sharing projects via Facebook to provide the information of the organisation that owns the Akvo Pages instance in place of Akvo. + +Github issue [#442](https://github.com/akvo/akvo-rsr/issues/442) + +### RSR favicon + +We have replaced the favicon being used within RSR to use the more updated icon as is present within the Akvo.org website. + +Github issue [#443](https://github.com/akvo/akvo-rsr/issues/443) + +### Donation redirect page for Akvo Pages + +We have added a new timed redirection page that users will see when completing a donation from an Akvo Pages instance. This provides information to the user to inform them that they will be leaving the previous domain and be directed to the Akvo.org donation process. + +Github issue [#480](https://github.com/akvo/akvo-rsr/issues/480) + +### Translation management process + +We have documented our process for managing the content translations with a team of external language translators. This is just a documentation update. + +Github issue [#494](https://github.com/akvo/akvo-rsr/issues/494) + +### Documentation Update + +We have performed a merging process to pull some recent documentation efforts into the main code repository to ensure that the right information is always available for users to see. + +Github issue [#512](https://github.com/akvo/akvo-rsr/issues/512) + +### Project summary pop-up Akvo Pages map widget + +We have added a project summary pop-up to the Akvo Pages map widget that displays basic information about a project to the user when they click on the pin for a specific project. + +Github issue [#505](https://github.com/akvo/akvo-rsr/issues/505) + +### Project and organisation management flags + +Following on from recent work on management flags, we have extended this functionality to projects. Now it is possible to set a flag on both projects and organisations that will prevent unwanted changes being made. + +Organisations can have an owner flag set so that any changes made by other organisations inform the user that these changes could be overwritten by the managing organisation. + +Partners can also set a flag on their organisation record to prevent their projects being modified by other organisations. Only Admins from the support partner organisation will be able to make changes to the project content for these projects. + +Github issue [#233](https://github.com/akvo/akvo-rsr/issues/233) + + +Bug Fixes +--- + +### Blank location error + +We were experiencing a problem where if new locations were added to a project but no information was completed, the admin form would not save. This has been corrected to now ignore any added but incomplete locations. + +Github issue [#312](https://github.com/akvo/akvo-rsr/issues/312) + +### Budget totals + +We previously had 2 different budget items within the dataset that referred to total budgets. This has now been consolidated so that we only have a single entry and all information will be merged to this single entry. + +Github issue [#471](https://github.com/akvo/akvo-rsr/issues/471) + +### Akvo Pages widgets layout error + +We have tidied up some layout issues with the widgets being provided for Akvo Pages. + +Github issue [#498](https://github.com/akvo/akvo-rsr/issues/498) + +### Wrapped links on project pages + +We have fixed an issue that long links provided on projects were extending beyond the box provided in the visual layout. These links will now wrap to the next line if they are too long to fit within the available space. + +Github issue [#506](https://github.com/akvo/akvo-rsr/issues/506) + +### Global maps in Internet Explorer 8 + +We have resolved some visualisation issues when viewing the global maps in IE8. Now the maps are correctly displaying the points. + +Github issue [#507](https://github.com/akvo/akvo-rsr/issues/507) + +### IATI export missing data + +We were missing some date information within the budget item export when creating IATI files. This prevented the files from validating as a correct IATI XML file. This has now been included. + +Github issue [#533](https://github.com/akvo/akvo-rsr/issues/533) + +### Live server logging + +We have made a small change to the underlying code that will provide better logging information for our system to help discover and troubleshoot any issues that occur. + +Github issue [#432](https://github.com/akvo/akvo-rsr/issues/432) + +### Using Sentry within RSR + +We have added Sentry as a tool to assist us with monitoring and logging with RSR as part of our efforts to ensure we have a great performing system and access to all the right information to investigate when things don't go entirely to plan. You can read more about Sentry [here](http://sentry.readthedocs.org/en/latest/). + +Github issue [#541](https://github.com/akvo/akvo-rsr/issues/541) + + Akvo RSR ver 2.3.5 Uglyfruit --- diff --git a/akvo/mediaroot/akvo/img/base/favicon.ico b/akvo/mediaroot/akvo/img/base/favicon.ico index 0d8fab86d4..73211b7c53 100644 Binary files a/akvo/mediaroot/akvo/img/base/favicon.ico and b/akvo/mediaroot/akvo/img/base/favicon.ico differ diff --git a/akvo/mediaroot/akvo/img/favicon.ico b/akvo/mediaroot/akvo/img/favicon.ico index 0d8fab86d4..73211b7c53 100644 Binary files a/akvo/mediaroot/akvo/img/favicon.ico and b/akvo/mediaroot/akvo/img/favicon.ico differ diff --git a/akvo/mediaroot/ps_widgets/projectList.css b/akvo/mediaroot/ps_widgets/projectList.css index df98747b0d..d9fc67464f 100644 --- a/akvo/mediaroot/ps_widgets/projectList.css +++ b/akvo/mediaroot/ps_widgets/projectList.css @@ -59,12 +59,17 @@ td.projectDescrTd { width: 35%; } td.projectLocTd { width: 15%; } td.projectStatusTd { width: 15%; } td.projectPartnerTd { width: 15%; } -td.projectFundingTd { margin-top:-45px; display:inline-block !important;} +td.projectFundingTd { + margin-top:-45px; + display:inline-block !important; + width:90%; + height:220px; +} .projectListWidget .projectBudget { position: relative; overflow: auto; float: none; - width: 95%; + width: 100%; margin: 0; } .projectStatusTd span { display: block; } @@ -87,6 +92,7 @@ td.projectFundingTd { margin-top:-45px; display:inline-block !important;} white-space: normal; text-overflow: ellipsis; overflow: hidden; + line-height: 1.5; } .rsrWidget { font-size:0.8em; diff --git a/akvo/mediaroot/ps_widgets/rsrWidgets.css b/akvo/mediaroot/ps_widgets/rsrWidgets.css index 17e4094615..e90cb493e2 100644 --- a/akvo/mediaroot/ps_widgets/rsrWidgets.css +++ b/akvo/mediaroot/ps_widgets/rsrWidgets.css @@ -267,7 +267,6 @@ ul.basicInfo li .projectLocation { background: url(pinLocation.png) left center no-repeat; margin: 0 0 0 5px; text-overflow: ellipsis; - overflow: hidden; line-height: 1; } #container.lightBG ul.basicInfo li .projectLocation { @@ -428,11 +427,10 @@ li.neededBudget { .html5-progress-bar progress { background-color: #f3f3f3; border: 0; - width: 90%; - height: 2px; - border-radius: 9px; + border-radius: 15px; margin: 0 auto; border: 3px solid rgb(52,52,52); + width: 95%; } .html5-progress-bar progress::-webkit-progress-bar { background-color: rgb(225,225,225); diff --git a/akvo/mediaroot/ps_widgets/w170px.css b/akvo/mediaroot/ps_widgets/w170px.css index 01efda74b7..ee7a30ddb6 100644 --- a/akvo/mediaroot/ps_widgets/w170px.css +++ b/akvo/mediaroot/ps_widgets/w170px.css @@ -36,7 +36,7 @@ display: inline-block; position: relative; float: none; - width: 148px; + width: 95%; margin: 10px 5px 0 0; max-height: none; padding: 15px 4px; diff --git a/akvo/rsr/admin.py b/akvo/rsr/admin.py index ca539747d2..e4c2977c6d 100644 --- a/akvo/rsr/admin.py +++ b/akvo/rsr/admin.py @@ -85,11 +85,14 @@ def clean(self): for form in self.forms: if form.is_valid() and not form.cleaned_data.get('DELETE', False): form_count += 1 - primary_count += 1 if form.cleaned_data['primary'] else 0 + try: + primary_count += 1 if form.cleaned_data['primary'] else 0 + except: + pass # if we have any forms left there must be exactly 1 primary location if form_count > 0 and not primary_count == 1: self._non_form_errors = ErrorList([ - _(u'The project must have exactly one primary location if any locations at all are to be included') + _(u'The project must have exactly one filled in primary location if any locations at all are to be included') ]) @@ -120,7 +123,7 @@ class OrganisationAdmin(TimestampsAdminDisplayMixin, admin.ModelAdmin): fieldsets = ( (_(u'General information'), {'fields': ('name', 'long_name', 'partner_types', 'organisation_type', 'new_organisation_type', 'logo', 'url', 'iati_org_id', 'language', - 'content_owner',)}), + 'allow_edit',)}), (_(u'Contact information'), {'fields': ('phone', 'mobile', 'fax', 'contact_person', 'contact_email', ), }), (_(u'About the organisation'), {'fields': ('description', 'notes',)}), ) @@ -354,9 +357,28 @@ class BudgetItemLabelAdmin(admin.ModelAdmin): admin.site.register(get_model('rsr', 'budgetitemlabel'), BudgetItemLabelAdmin) +class BudgetItemAdminInLineFormSet(forms.models.BaseInlineFormSet): + def clean(self): + super(BudgetItemAdminInLineFormSet, self).clean() + + budget_item_count = 0 + including_total = False + for form in self.forms: + if not form.is_valid(): + return + if form.cleaned_data and not form.cleaned_data.get('DELETE'): + budget_item_count += 1 + if form.cleaned_data.get('label').label == 'total': + including_total = True + + if budget_item_count > 1 and including_total: + raise forms.ValidationError(_("The 'total' budget item cannot be used in combination with other budget items.")) + + class BudgetItemAdminInLine(admin.TabularInline): model = get_model('rsr', 'budgetitem') extra = 1 + formset = BudgetItemAdminInLineFormSet class Media: css = {'all': (os.path.join(settings.MEDIA_URL, 'akvo/css/src/rsr_admin.css').replace('\\', '/'),)} @@ -674,12 +696,14 @@ def queryset(self, request): """ qs = super(ProjectAdmin, self).queryset(request) opts = self.opts + user_profile = request.user.get_profile() if request.user.has_perm(opts.app_label + '.' + opts.get_change_permission()): return qs elif request.user.has_perm(opts.app_label + '.' + get_rsr_limited_change_permission(opts)): - projects = request.user.get_profile().organisation.all_projects() - #projects = get_model('rsr', 'organisation').projects.filter(pk__in=[request.user.get_profile().organisation.pk]) - return qs.filter(pk__in=projects) + projects = user_profile.organisation.all_projects() + # Access to Partner users may be limited by Support partner "ownership" + allowed_projects = [project.pk for project in projects if user_profile.allow_edit(project)] + return qs.filter(pk__in=allowed_projects) else: raise PermissionDenied @@ -695,17 +719,23 @@ def has_change_permission(self, request, obj=None): "own" projects, organisation and user profiles """ opts = self.opts - if request.user.has_perm(opts.app_label + '.' + opts.get_change_permission()): + user = request.user + user_profile = user.get_profile() + + # RSR editors/managers + if user.has_perm(opts.app_label + '.' + opts.get_change_permission()): return True - if request.user.has_perm(opts.app_label + '.' + get_rsr_limited_change_permission(opts)): - projects = request.user.get_profile().organisation.all_projects() - #projects = get_model('rsr', 'organisation').projects.filter(pk__in=[request.user.get_profile().organisation.pk]) + + # RSR Partner admins/editors + if user.has_perm(opts.app_label + '.' + get_rsr_limited_change_permission(opts)): + # On the Project form if obj: - return obj in projects - else: - return True + return user_profile.allow_edit(obj) + return True + return False + @csrf_protect_m @transaction.commit_on_success def add_view(self, request, form_url='', extra_context=None): @@ -1100,7 +1130,7 @@ class ProjectUpdateAdmin(TimestampsAdminDisplayMixin, admin.ModelAdmin): 'fields': ('title','text','language', ), }), (_(u'Image and video'), { - 'fields': ('photo', 'photo_location', 'photo_caption', 'photo_credit', 'video', 'video_caption', 'video_credit',), + 'fields': ('photo', 'photo_caption', 'photo_credit', 'video', 'video_caption', 'video_credit',), }), ) #Methods overridden from ModelAdmin (django/contrib/admin/options.py) @@ -1179,7 +1209,7 @@ class PartnerSiteAdmin(TimestampsAdminDisplayMixin, admin.ModelAdmin): fieldsets = ( # the 'notes' field is added in get_fieldsets() for eligible users (u'General', dict(fields=('organisation', 'enabled',))), - (u'HTTP', dict(fields=('hostname', 'cname', 'custom_return_url',))), + (u'HTTP', dict(fields=('hostname', 'cname', 'custom_return_url', 'custom_return_url_text'))), (u'Style and content', dict(fields=('about_box', 'about_image', 'custom_css', 'custom_logo', 'custom_favicon',))), (u'Languages and translation', dict(fields=('default_language', 'ui_translation', 'google_translation',))), diff --git a/akvo/rsr/fields.py b/akvo/rsr/fields.py index cd3659fd01..244efe6b24 100644 --- a/akvo/rsr/fields.py +++ b/akvo/rsr/fields.py @@ -12,6 +12,8 @@ from south.modelsinspector import add_introspection_rules +from akvo.rsr.validators import string_validator + class NullCharField(models.CharField): @@ -48,7 +50,25 @@ def __init__(self, *args, **kwargs): self.validators = [MinValueValidator(-180), MaxValueValidator(180)] -class LimitedTextField(models.TextField): +class ValidXMLCharField(models.CharField): + + description = "A CharField containing only valid XML characters" + + def __init__(self, *args, **kwargs): + super(ValidXMLCharField, self).__init__(*args, **kwargs) + self.validators += [string_validator] + + +class ValidXMLTextField(models.TextField): + + description = "A TextField containing only valid XML characters" + + def __init__(self, *args, **kwargs): + super(ValidXMLTextField, self).__init__(*args, **kwargs) + self.validators += [string_validator] + + +class LimitedTextField(ValidXMLTextField): description = "A TextField that honors the max_length param" @@ -78,5 +98,7 @@ def clean(self, value, model_instance): add_introspection_rules([], ["^akvo\.rsr\.fields\.NullCharField"]) add_introspection_rules([], ["^akvo\.rsr\.fields\.LatitudeField"]) add_introspection_rules([], ["^akvo\.rsr\.fields\.LongitudeField"]) +add_introspection_rules([], ["^akvo\.rsr\.fields\.ValidXMLCharField"]) +add_introspection_rules([], ["^akvo\.rsr\.fields\.ValidXMLTextField"]) add_introspection_rules([], ["^akvo\.rsr\.fields\.LimitedTextField"]) add_introspection_rules([], ["^akvo\.rsr\.fields\.ProjectLimitedTextField"]) diff --git a/akvo/rsr/filters.py b/akvo/rsr/filters.py index 46c9474c8e..e87485eb78 100644 --- a/akvo/rsr/filters.py +++ b/akvo/rsr/filters.py @@ -14,9 +14,7 @@ from akvo.rsr.iso3166 import CONTINENTS -from akvo.rsr.models import ( - Organisation, Project, STATUSES, CURRENCY_CHOICES -) +from akvo.rsr.models import Organisation, Project, STATUSES, CURRENCY_CHOICES class CheckboxMultipleChoiceField(MultipleChoiceField): widget = widgets.CheckboxSelectMultiple diff --git a/akvo/rsr/forms.py b/akvo/rsr/forms.py index e826a5e4ed..6a1c46833b 100644 --- a/akvo/rsr/forms.py +++ b/akvo/rsr/forms.py @@ -327,10 +327,6 @@ def get_form(self, request, obj=None, **kwargs): class ProjectUpdateForm(forms.ModelForm): """Form representing a ProjectUpdate.""" - MEDIA_LOCATIONS = ( - ('B', _('At the beginning of the update.')), - ('E', _('At the end of the update.')) - ) title = forms.CharField(widget=forms.TextInput(attrs={ 'class': 'input', 'size': '42', @@ -347,8 +343,6 @@ class ProjectUpdateForm(forms.ModelForm): 'size': '15', 'style': 'height: 2em', })) - photo_location = forms.CharField(required=False, widget=forms.RadioSelect( - choices=ProjectUpdate.PHOTO_LOCATIONS, attrs={'class': 'radio'})) photo_caption = forms.CharField(required=False, widget=forms.TextInput(attrs={ 'class': 'input', 'size': '25', diff --git a/akvo/rsr/iati_file_generator.py b/akvo/rsr/iati_file_generator.py index dfb8e8e94c..cbc897d552 100644 --- a/akvo/rsr/iati_file_generator.py +++ b/akvo/rsr/iati_file_generator.py @@ -189,7 +189,7 @@ def organisation_role(role): return activity -def iati_budget(activity, budgets): +def iati_budget(activity, budgets, project): """Collects budget of the RSR project and adds it to the activity.""" # Ignore total budgets -- label 13 or 14 -- if not all budgets are a total budget @@ -203,6 +203,10 @@ def iati_budget(activity, budgets): if check_value(budget.amount): budget_value = schema.textType(valueOf_=budget.amount) + + if check_value(project.date_request_posted): + budget_value.set_anyAttributes_({"value-date": project.date_request_posted}) + budget_node.add_value(budget_value) if check_value(budget_label): @@ -523,7 +527,7 @@ def process_project(xml, project, org_id): activity = iati_goals(activity, goals) activity = iati_photo(activity, project) activity = iati_location(activity, location, country) - activity = iati_budget(activity, budgets) + activity = iati_budget(activity, budgets, project) activity = iati_participating_org(activity, project, participating_orgs) activity = iati_links(activity, links) activity = iati_outcome(activity, benchmarks, benchmark_names, categories) diff --git a/akvo/rsr/middleware.py b/akvo/rsr/middleware.py index 7c9326ea18..fda78ee97f 100644 --- a/akvo/rsr/middleware.py +++ b/akvo/rsr/middleware.py @@ -19,6 +19,8 @@ from django.utils.cache import patch_vary_headers from akvo.rsr.models import PartnerSite + +import logging import re @@ -217,3 +219,11 @@ def is_language_prefix_patterns_used(self, request): if isinstance(url_pattern, LocaleRegexURLResolver): return True return False + + +class ExceptionLoggingMiddleware(object): + """ Used to log exceptions on production systems + """ + def process_exception(self, request, exception): + + logging.exception('Exception handling request for ' + request.path) diff --git a/akvo/rsr/migrations/0050_auto__add_field_partnersite_custom_return_url_text.py b/akvo/rsr/migrations/0050_auto__add_field_partnersite_custom_return_url_text.py new file mode 100644 index 0000000000..b880d10e1a --- /dev/null +++ b/akvo/rsr/migrations/0050_auto__add_field_partnersite_custom_return_url_text.py @@ -0,0 +1,391 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'PartnerSite.custom_return_url_text' + db.add_column('rsr_partnersite', 'custom_return_url_text', + self.gf('django.db.models.fields.CharField')(default='', max_length=50), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'PartnerSite.custom_return_url_text' + db.delete_column('rsr_partnersite', 'custom_return_url_text') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'gateway.gateway': { + 'Meta': {'object_name': 'Gateway'}, + 'host_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'msg_id': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'name': ('django.db.models.fields.SlugField', [], {'max_length': '30'}), + 'receiver': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'send_path': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'sender': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'timestamp': ('django.db.models.fields.CharField', [], {'max_length': '30'}) + }, + 'gateway.gatewaynumber': { + 'Meta': {'object_name': 'GatewayNumber'}, + 'gateway': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gateway.Gateway']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'number': ('django.db.models.fields.CharField', [], {'max_length': '30'}) + }, + 'rsr.benchmark': { + 'Meta': {'ordering': "('category__name', 'name__order')", 'object_name': 'Benchmark'}, + 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Category']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Benchmarkname']"}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'benchmarks'", 'to': "orm['rsr.Project']"}), + 'value': ('django.db.models.fields.IntegerField', [], {}) + }, + 'rsr.benchmarkname': { + 'Meta': {'ordering': "['order', 'name']", 'object_name': 'Benchmarkname'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'rsr.budgetitem': { + 'Meta': {'ordering': "('label',)", 'unique_together': "(('project', 'label'),)", 'object_name': 'BudgetItem'}, + 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '2'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.BudgetItemLabel']"}), + 'other_extra': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'budget_items'", 'to': "orm['rsr.Project']"}) + }, + 'rsr.budgetitemlabel': { + 'Meta': {'ordering': "('label',)", 'object_name': 'BudgetItemLabel'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20', 'db_index': 'True'}) + }, + 'rsr.category': { + 'Meta': {'ordering': "['name']", 'object_name': 'Category'}, + 'benchmarknames': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['rsr.Benchmarkname']", 'symmetrical': 'False', 'blank': 'True'}), + 'focus_area': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'categories'", 'symmetrical': 'False', 'to': "orm['rsr.FocusArea']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}) + }, + 'rsr.country': { + 'Meta': {'ordering': "['name']", 'object_name': 'Country'}, + 'continent': ('django.db.models.fields.CharField', [], {'max_length': '20', 'db_index': 'True'}), + 'continent_code': ('django.db.models.fields.CharField', [], {'max_length': '2', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'iso_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2', 'db_index': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}) + }, + 'rsr.focusarea': { + 'Meta': {'ordering': "['name']", 'object_name': 'FocusArea'}, + 'description': ('django.db.models.fields.TextField', [], {'max_length': '500'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), + 'link_to': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}) + }, + 'rsr.goal': { + 'Meta': {'object_name': 'Goal'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'goals'", 'to': "orm['rsr.Project']"}), + 'text': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}) + }, + 'rsr.internalorganisationid': { + 'Meta': {'unique_together': "(('recording_org', 'referenced_org'),)", 'object_name': 'InternalOrganisationID'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'identifier': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'recording_org': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'internal_ids'", 'to': "orm['rsr.Organisation']"}), + 'referenced_org': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reference_ids'", 'to': "orm['rsr.Organisation']"}) + }, + 'rsr.invoice': { + 'Meta': {'ordering': "['-id']", 'object_name': 'Invoice'}, + 'amount': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'amount_received': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '10', 'decimal_places': '2', 'blank': 'True'}), + 'bank': ('django.db.models.fields.CharField', [], {'max_length': '4', 'blank': 'True'}), + 'campaign_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'engine': ('django.db.models.fields.CharField', [], {'default': "'paypal'", 'max_length': '10'}), + 'http_referer': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ipn': ('django.db.models.fields.CharField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'notes': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'invoices'", 'to': "orm['rsr.Project']"}), + 'status': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '1'}), + 'test': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'transaction_id': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}) + }, + 'rsr.link': { + 'Meta': {'object_name': 'Link'}, + 'caption': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'kind': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'links'", 'to': "orm['rsr.Project']"}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'rsr.minicms': { + 'Meta': {'ordering': "['-active', '-id']", 'object_name': 'MiniCMS'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'feature_box': ('django.db.models.fields.TextField', [], {'max_length': '350'}), + 'feature_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'lower_height': ('django.db.models.fields.IntegerField', [], {'default': '500'}), + 'top_right_box': ('django.db.models.fields.TextField', [], {'max_length': '350'}) + }, + 'rsr.molliegateway': { + 'Meta': {'object_name': 'MollieGateway'}, + 'currency': ('django.db.models.fields.CharField', [], {'default': "'EUR'", 'max_length': '3'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'notification_email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'partner_id': ('django.db.models.fields.CharField', [], {'max_length': '10'}) + }, + 'rsr.organisation': { + 'Meta': {'ordering': "['name']", 'object_name': 'Organisation'}, + 'contact_email': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'contact_person': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'content_owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Organisation']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'fax': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), + 'iati_org_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '75', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'internal_org_ids': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'recording_organisation'", 'symmetrical': 'False', 'through': "orm['rsr.InternalOrganisationID']", 'to': "orm['rsr.Organisation']"}), + 'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}), + 'last_modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'logo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'long_name': ('django.db.models.fields.CharField', [], {'max_length': '75', 'blank': 'True'}), + 'mobile': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_index': 'True'}), + 'new_organisation_type': ('django.db.models.fields.IntegerField', [], {'default': '22', 'db_index': 'True'}), + 'notes': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'organisation_type': ('django.db.models.fields.CharField', [], {'max_length': '1', 'db_index': 'True'}), + 'partner_types': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['rsr.PartnerType']", 'symmetrical': 'False'}), + 'phone': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), + 'primary_location': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.OrganisationLocation']", 'null': 'True', 'on_delete': 'models.SET_NULL'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'rsr.organisationaccount': { + 'Meta': {'object_name': 'OrganisationAccount'}, + 'account_level': ('django.db.models.fields.CharField', [], {'default': "'free'", 'max_length': '12'}), + 'organisation': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['rsr.Organisation']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'rsr.organisationlocation': { + 'Meta': {'ordering': "['-primary']", 'object_name': 'OrganisationLocation'}, + 'address_1': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'address_2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Country']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latitude': ('akvo.rsr.fields.LatitudeField', [], {'default': '0', 'db_index': 'True'}), + 'location_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'locations'", 'null': 'True', 'to': "orm['rsr.Organisation']"}), + 'longitude': ('akvo.rsr.fields.LongitudeField', [], {'default': '0', 'db_index': 'True'}), + 'postcode': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}), + 'primary': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) + }, + 'rsr.partnership': { + 'Meta': {'ordering': "['partner_type']", 'object_name': 'Partnership'}, + 'funding_amount': ('django.db.models.fields.DecimalField', [], {'db_index': 'True', 'null': 'True', 'max_digits': '10', 'decimal_places': '2', 'blank': 'True'}), + 'iati_activity_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'iati_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'internal_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'organisation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'partnerships'", 'to': "orm['rsr.Organisation']"}), + 'partner_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'db_index': 'True'}), + 'partner_type_extra': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'partnerships'", 'to': "orm['rsr.Project']"}) + }, + 'rsr.partnersite': { + 'Meta': {'ordering': "('organisation__name',)", 'object_name': 'PartnerSite'}, + 'about_box': ('django.db.models.fields.TextField', [], {'max_length': '500', 'blank': 'True'}), + 'about_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'cname': ('akvo.rsr.fields.NullCharField', [], {'max_length': '100', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'custom_css': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'custom_favicon': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'custom_logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'custom_return_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'custom_return_url_text': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}), + 'default_language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '5'}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'facebook_app_id': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'facebook_button': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'google_translation': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'notes': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'organisation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Organisation']"}), + 'twitter_button': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'ui_translation': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'rsr.partnertype': { + 'Meta': {'ordering': "('label',)", 'object_name': 'PartnerType'}, + 'id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '8', 'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'rsr.paymentgatewayselector': { + 'Meta': {'object_name': 'PaymentGatewaySelector'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mollie_gateway': ('django.db.models.fields.related.ForeignKey', [], {'default': '1', 'to': "orm['rsr.MollieGateway']"}), + 'paypal_gateway': ('django.db.models.fields.related.ForeignKey', [], {'default': '1', 'to': "orm['rsr.PayPalGateway']"}), + 'project': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['rsr.Project']", 'unique': 'True'}) + }, + 'rsr.paypalgateway': { + 'Meta': {'object_name': 'PayPalGateway'}, + 'account_email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'currency': ('django.db.models.fields.CharField', [], {'default': "'EUR'", 'max_length': '3'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'locale': ('django.db.models.fields.CharField', [], {'default': "'US'", 'max_length': '2'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'notification_email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}) + }, + 'rsr.project': { + 'Meta': {'ordering': "['-id']", 'object_name': 'Project'}, + 'background': ('akvo.rsr.fields.ProjectLimitedTextField', [], {'blank': 'True'}), + 'budget': ('django.db.models.fields.DecimalField', [], {'decimal_places': '2', 'default': '0', 'max_digits': '10', 'blank': 'True', 'null': 'True', 'db_index': 'True'}), + 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'projects'", 'symmetrical': 'False', 'to': "orm['rsr.Category']"}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'currency': ('django.db.models.fields.CharField', [], {'default': "'EUR'", 'max_length': '3'}), + 'current_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'current_image_caption': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'current_image_credit': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'current_status': ('akvo.rsr.fields.ProjectLimitedTextField', [], {'blank': 'True'}), + 'date_complete': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'date_request_posted': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today'}), + 'donate_button': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'funds': ('django.db.models.fields.DecimalField', [], {'decimal_places': '2', 'default': '0', 'max_digits': '10', 'blank': 'True', 'null': 'True', 'db_index': 'True'}), + 'funds_needed': ('django.db.models.fields.DecimalField', [], {'decimal_places': '2', 'default': '0', 'max_digits': '10', 'blank': 'True', 'null': 'True', 'db_index': 'True'}), + 'goals_overview': ('akvo.rsr.fields.ProjectLimitedTextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}), + 'last_modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'notes': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'partners': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'projects'", 'symmetrical': 'False', 'through': "orm['rsr.Partnership']", 'to': "orm['rsr.Organisation']"}), + 'primary_location': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.ProjectLocation']", 'null': 'True', 'on_delete': 'models.SET_NULL'}), + 'project_plan': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'project_plan_summary': ('akvo.rsr.fields.ProjectLimitedTextField', [], {}), + 'project_rating': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'N'", 'max_length': '1', 'db_index': 'True'}), + 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '75'}), + 'sustainability': ('django.db.models.fields.TextField', [], {}), + 'target_group': ('akvo.rsr.fields.ProjectLimitedTextField', [], {'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '45', 'db_index': 'True'}) + }, + 'rsr.projectcomment': { + 'Meta': {'ordering': "('-id',)", 'object_name': 'ProjectComment'}, + 'comment': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['rsr.Project']"}), + 'time': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'rsr.projectlocation': { + 'Meta': {'ordering': "['-primary']", 'object_name': 'ProjectLocation'}, + 'address_1': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'address_2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Country']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latitude': ('akvo.rsr.fields.LatitudeField', [], {'default': '0', 'db_index': 'True'}), + 'location_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'locations'", 'null': 'True', 'to': "orm['rsr.Project']"}), + 'longitude': ('akvo.rsr.fields.LongitudeField', [], {'default': '0', 'db_index': 'True'}), + 'postcode': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}), + 'primary': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) + }, + 'rsr.projectupdate': { + 'Meta': {'ordering': "['-id']", 'object_name': 'ProjectUpdate'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}), + 'last_modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'notes': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'photo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'photo_caption': ('django.db.models.fields.CharField', [], {'max_length': '75', 'blank': 'True'}), + 'photo_credit': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}), + 'photo_location': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'project_updates'", 'to': "orm['rsr.Project']"}), + 'text': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}), + 'update_method': ('django.db.models.fields.CharField', [], {'default': "'W'", 'max_length': '1', 'db_index': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'user_agent': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '200', 'blank': 'True'}), + 'uuid': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'db_index': 'True', 'blank': 'True'}), + 'video': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'video_caption': ('django.db.models.fields.CharField', [], {'max_length': '75', 'blank': 'True'}), + 'video_credit': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}) + }, + 'rsr.publishingstatus': { + 'Meta': {'ordering': "('-status', 'project')", 'object_name': 'PublishingStatus'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'project': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['rsr.Project']", 'unique': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'unpublished'", 'max_length': '30'}) + }, + 'rsr.smsreporter': { + 'Meta': {'unique_together': "(('userprofile', 'gw_number', 'project'),)", 'object_name': 'SmsReporter'}, + 'gw_number': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gateway.GatewayNumber']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Project']", 'null': 'True', 'blank': 'True'}), + 'userprofile': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reporters'", 'to': "orm['rsr.UserProfile']"}) + }, + 'rsr.userprofile': { + 'Meta': {'ordering': "['user__username']", 'object_name': 'UserProfile'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notes': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'organisation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Organisation']"}), + 'phone_number': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), + 'validation': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}) + } + } + + complete_apps = ['rsr'] \ No newline at end of file diff --git a/akvo/rsr/migrations/0051_projects_add_sync_owner.py b/akvo/rsr/migrations/0051_projects_add_sync_owner.py new file mode 100644 index 0000000000..3138a9f41b --- /dev/null +++ b/akvo/rsr/migrations/0051_projects_add_sync_owner.py @@ -0,0 +1,401 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'Project.sync_owner' + db.add_column('rsr_project', 'sync_owner', + self.gf('django.db.models.fields.related.ForeignKey')(to=orm['rsr.Organisation'], null=True, on_delete=models.SET_NULL, blank=True), + keep_default=False) + + # Adding field 'Organisation.allow_edit' + db.add_column('rsr_organisation', 'allow_edit', + self.gf('django.db.models.fields.BooleanField')(default=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Project.sync_owner' + db.delete_column('rsr_project', 'sync_owner') + + # Deleting field 'Organisation.allow_edit' + db.delete_column('rsr_organisation', 'allow_edit') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'gateway.gateway': { + 'Meta': {'object_name': 'Gateway'}, + 'host_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'msg_id': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'name': ('django.db.models.fields.SlugField', [], {'max_length': '30'}), + 'receiver': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'send_path': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'sender': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'timestamp': ('django.db.models.fields.CharField', [], {'max_length': '30'}) + }, + 'gateway.gatewaynumber': { + 'Meta': {'object_name': 'GatewayNumber'}, + 'gateway': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gateway.Gateway']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'number': ('django.db.models.fields.CharField', [], {'max_length': '30'}) + }, + 'rsr.benchmark': { + 'Meta': {'ordering': "('category__name', 'name__order')", 'object_name': 'Benchmark'}, + 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Category']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Benchmarkname']"}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'benchmarks'", 'to': "orm['rsr.Project']"}), + 'value': ('django.db.models.fields.IntegerField', [], {}) + }, + 'rsr.benchmarkname': { + 'Meta': {'ordering': "['order', 'name']", 'object_name': 'Benchmarkname'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'rsr.budgetitem': { + 'Meta': {'ordering': "('label',)", 'unique_together': "(('project', 'label'),)", 'object_name': 'BudgetItem'}, + 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '2'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.BudgetItemLabel']"}), + 'other_extra': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'budget_items'", 'to': "orm['rsr.Project']"}) + }, + 'rsr.budgetitemlabel': { + 'Meta': {'ordering': "('label',)", 'object_name': 'BudgetItemLabel'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20', 'db_index': 'True'}) + }, + 'rsr.category': { + 'Meta': {'ordering': "['name']", 'object_name': 'Category'}, + 'benchmarknames': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['rsr.Benchmarkname']", 'symmetrical': 'False', 'blank': 'True'}), + 'focus_area': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'categories'", 'symmetrical': 'False', 'to': "orm['rsr.FocusArea']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}) + }, + 'rsr.country': { + 'Meta': {'ordering': "['name']", 'object_name': 'Country'}, + 'continent': ('django.db.models.fields.CharField', [], {'max_length': '20', 'db_index': 'True'}), + 'continent_code': ('django.db.models.fields.CharField', [], {'max_length': '2', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'iso_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2', 'db_index': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}) + }, + 'rsr.focusarea': { + 'Meta': {'ordering': "['name']", 'object_name': 'FocusArea'}, + 'description': ('django.db.models.fields.TextField', [], {'max_length': '500'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), + 'link_to': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}) + }, + 'rsr.goal': { + 'Meta': {'object_name': 'Goal'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'goals'", 'to': "orm['rsr.Project']"}), + 'text': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}) + }, + 'rsr.internalorganisationid': { + 'Meta': {'unique_together': "(('recording_org', 'referenced_org'),)", 'object_name': 'InternalOrganisationID'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'identifier': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'recording_org': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'internal_ids'", 'to': "orm['rsr.Organisation']"}), + 'referenced_org': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reference_ids'", 'to': "orm['rsr.Organisation']"}) + }, + 'rsr.invoice': { + 'Meta': {'ordering': "['-id']", 'object_name': 'Invoice'}, + 'amount': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'amount_received': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '10', 'decimal_places': '2', 'blank': 'True'}), + 'bank': ('django.db.models.fields.CharField', [], {'max_length': '4', 'blank': 'True'}), + 'campaign_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'engine': ('django.db.models.fields.CharField', [], {'default': "'paypal'", 'max_length': '10'}), + 'http_referer': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ipn': ('django.db.models.fields.CharField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'notes': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'invoices'", 'to': "orm['rsr.Project']"}), + 'status': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '1'}), + 'test': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'transaction_id': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}) + }, + 'rsr.link': { + 'Meta': {'object_name': 'Link'}, + 'caption': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'kind': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'links'", 'to': "orm['rsr.Project']"}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'rsr.minicms': { + 'Meta': {'ordering': "['-active', '-id']", 'object_name': 'MiniCMS'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'feature_box': ('django.db.models.fields.TextField', [], {'max_length': '350'}), + 'feature_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'lower_height': ('django.db.models.fields.IntegerField', [], {'default': '500'}), + 'top_right_box': ('django.db.models.fields.TextField', [], {'max_length': '350'}) + }, + 'rsr.molliegateway': { + 'Meta': {'object_name': 'MollieGateway'}, + 'currency': ('django.db.models.fields.CharField', [], {'default': "'EUR'", 'max_length': '3'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'notification_email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'partner_id': ('django.db.models.fields.CharField', [], {'max_length': '10'}) + }, + 'rsr.organisation': { + 'Meta': {'ordering': "['name']", 'object_name': 'Organisation'}, + 'allow_edit': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'contact_email': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'contact_person': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'content_owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Organisation']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'fax': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), + 'iati_org_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '75', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'internal_org_ids': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'recording_organisation'", 'symmetrical': 'False', 'through': "orm['rsr.InternalOrganisationID']", 'to': "orm['rsr.Organisation']"}), + 'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}), + 'last_modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'logo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'long_name': ('django.db.models.fields.CharField', [], {'max_length': '75', 'blank': 'True'}), + 'mobile': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '25', 'db_index': 'True'}), + 'new_organisation_type': ('django.db.models.fields.IntegerField', [], {'default': '22', 'db_index': 'True'}), + 'notes': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'organisation_type': ('django.db.models.fields.CharField', [], {'max_length': '1', 'db_index': 'True'}), + 'partner_types': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['rsr.PartnerType']", 'symmetrical': 'False'}), + 'phone': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), + 'primary_location': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.OrganisationLocation']", 'null': 'True', 'on_delete': 'models.SET_NULL'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'rsr.organisationaccount': { + 'Meta': {'object_name': 'OrganisationAccount'}, + 'account_level': ('django.db.models.fields.CharField', [], {'default': "'free'", 'max_length': '12'}), + 'organisation': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['rsr.Organisation']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'rsr.organisationlocation': { + 'Meta': {'ordering': "['-primary']", 'object_name': 'OrganisationLocation'}, + 'address_1': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'address_2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Country']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latitude': ('akvo.rsr.fields.LatitudeField', [], {'default': '0', 'db_index': 'True'}), + 'location_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'locations'", 'null': 'True', 'to': "orm['rsr.Organisation']"}), + 'longitude': ('akvo.rsr.fields.LongitudeField', [], {'default': '0', 'db_index': 'True'}), + 'postcode': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}), + 'primary': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) + }, + 'rsr.partnership': { + 'Meta': {'ordering': "['partner_type']", 'object_name': 'Partnership'}, + 'funding_amount': ('django.db.models.fields.DecimalField', [], {'db_index': 'True', 'null': 'True', 'max_digits': '10', 'decimal_places': '2', 'blank': 'True'}), + 'iati_activity_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'iati_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'internal_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'organisation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'partnerships'", 'to': "orm['rsr.Organisation']"}), + 'partner_type': ('django.db.models.fields.CharField', [], {'max_length': '8', 'db_index': 'True'}), + 'partner_type_extra': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'partnerships'", 'to': "orm['rsr.Project']"}) + }, + 'rsr.partnersite': { + 'Meta': {'ordering': "('organisation__name',)", 'object_name': 'PartnerSite'}, + 'about_box': ('django.db.models.fields.TextField', [], {'max_length': '500', 'blank': 'True'}), + 'about_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'cname': ('akvo.rsr.fields.NullCharField', [], {'max_length': '100', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'custom_css': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'custom_favicon': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'custom_logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'custom_return_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'custom_return_url_text': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}), + 'default_language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '5'}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'facebook_app_id': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'facebook_button': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'google_translation': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'notes': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'organisation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Organisation']"}), + 'twitter_button': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'ui_translation': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'rsr.partnertype': { + 'Meta': {'ordering': "('label',)", 'object_name': 'PartnerType'}, + 'id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '8', 'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'rsr.paymentgatewayselector': { + 'Meta': {'object_name': 'PaymentGatewaySelector'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mollie_gateway': ('django.db.models.fields.related.ForeignKey', [], {'default': '1', 'to': "orm['rsr.MollieGateway']"}), + 'paypal_gateway': ('django.db.models.fields.related.ForeignKey', [], {'default': '1', 'to': "orm['rsr.PayPalGateway']"}), + 'project': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['rsr.Project']", 'unique': 'True'}) + }, + 'rsr.paypalgateway': { + 'Meta': {'object_name': 'PayPalGateway'}, + 'account_email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'currency': ('django.db.models.fields.CharField', [], {'default': "'EUR'", 'max_length': '3'}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'locale': ('django.db.models.fields.CharField', [], {'default': "'US'", 'max_length': '2'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'notification_email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}) + }, + 'rsr.project': { + 'Meta': {'ordering': "['-id']", 'object_name': 'Project'}, + 'background': ('akvo.rsr.fields.ProjectLimitedTextField', [], {'blank': 'True'}), + 'budget': ('django.db.models.fields.DecimalField', [], {'decimal_places': '2', 'default': '0', 'max_digits': '10', 'blank': 'True', 'null': 'True', 'db_index': 'True'}), + 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'projects'", 'symmetrical': 'False', 'to': "orm['rsr.Category']"}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'currency': ('django.db.models.fields.CharField', [], {'default': "'EUR'", 'max_length': '3'}), + 'current_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'current_image_caption': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'current_image_credit': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'current_status': ('akvo.rsr.fields.ProjectLimitedTextField', [], {'blank': 'True'}), + 'date_complete': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'date_request_posted': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today'}), + 'donate_button': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'funds': ('django.db.models.fields.DecimalField', [], {'decimal_places': '2', 'default': '0', 'max_digits': '10', 'blank': 'True', 'null': 'True', 'db_index': 'True'}), + 'funds_needed': ('django.db.models.fields.DecimalField', [], {'decimal_places': '2', 'default': '0', 'max_digits': '10', 'blank': 'True', 'null': 'True', 'db_index': 'True'}), + 'goals_overview': ('akvo.rsr.fields.ProjectLimitedTextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}), + 'last_modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'notes': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'partners': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'projects'", 'symmetrical': 'False', 'through': "orm['rsr.Partnership']", 'to': "orm['rsr.Organisation']"}), + 'primary_location': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.ProjectLocation']", 'null': 'True', 'on_delete': 'models.SET_NULL'}), + 'project_plan': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'project_plan_summary': ('akvo.rsr.fields.ProjectLimitedTextField', [], {}), + 'project_rating': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'N'", 'max_length': '1', 'db_index': 'True'}), + 'subtitle': ('django.db.models.fields.CharField', [], {'max_length': '75'}), + 'sustainability': ('django.db.models.fields.TextField', [], {}), + 'sync_owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Organisation']", 'null': 'True', 'on_delete': 'models.SET_NULL'}), + 'target_group': ('akvo.rsr.fields.ProjectLimitedTextField', [], {'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '45', 'db_index': 'True'}) + }, + 'rsr.projectcomment': { + 'Meta': {'ordering': "('-id',)", 'object_name': 'ProjectComment'}, + 'comment': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['rsr.Project']"}), + 'time': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'rsr.projectlocation': { + 'Meta': {'ordering': "['-primary']", 'object_name': 'ProjectLocation'}, + 'address_1': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'address_2': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Country']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latitude': ('akvo.rsr.fields.LatitudeField', [], {'default': '0', 'db_index': 'True'}), + 'location_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'locations'", 'null': 'True', 'to': "orm['rsr.Project']"}), + 'longitude': ('akvo.rsr.fields.LongitudeField', [], {'default': '0', 'db_index': 'True'}), + 'postcode': ('django.db.models.fields.CharField', [], {'max_length': '10', 'blank': 'True'}), + 'primary': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}) + }, + 'rsr.projectupdate': { + 'Meta': {'ordering': "['-id']", 'object_name': 'ProjectUpdate'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}), + 'last_modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'notes': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'photo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'photo_caption': ('django.db.models.fields.CharField', [], {'max_length': '75', 'blank': 'True'}), + 'photo_credit': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}), + 'photo_location': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'project_updates'", 'to': "orm['rsr.Project']"}), + 'text': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}), + 'update_method': ('django.db.models.fields.CharField', [], {'default': "'W'", 'max_length': '1', 'db_index': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'user_agent': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '200', 'blank': 'True'}), + 'uuid': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'db_index': 'True', 'blank': 'True'}), + 'video': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'video_caption': ('django.db.models.fields.CharField', [], {'max_length': '75', 'blank': 'True'}), + 'video_credit': ('django.db.models.fields.CharField', [], {'max_length': '25', 'blank': 'True'}) + }, + 'rsr.publishingstatus': { + 'Meta': {'ordering': "('-status', 'project')", 'object_name': 'PublishingStatus'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'project': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['rsr.Project']", 'unique': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'unpublished'", 'max_length': '30'}) + }, + 'rsr.smsreporter': { + 'Meta': {'unique_together': "(('userprofile', 'gw_number', 'project'),)", 'object_name': 'SmsReporter'}, + 'gw_number': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gateway.GatewayNumber']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Project']", 'null': 'True', 'blank': 'True'}), + 'userprofile': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reporters'", 'to': "orm['rsr.UserProfile']"}) + }, + 'rsr.userprofile': { + 'Meta': {'ordering': "['user__username']", 'object_name': 'UserProfile'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notes': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'organisation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Organisation']"}), + 'phone_number': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), + 'validation': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}) + } + } + + complete_apps = ['rsr'] \ No newline at end of file diff --git a/akvo/rsr/migrations/0052_auto__chg_field_internalorganisationid_identifier__chg_field_organisat.py b/akvo/rsr/migrations/0052_auto__chg_field_internalorganisationid_identifier__chg_field_organisat.py new file mode 100644 index 0000000000..2a980efda0 --- /dev/null +++ b/akvo/rsr/migrations/0052_auto__chg_field_internalorganisationid_identifier__chg_field_organisat.py @@ -0,0 +1,956 @@ +# -*- coding: 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): + + # Changing field 'InternalOrganisationID.identifier' + db.alter_column('rsr_internalorganisationid', 'identifier', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=200)) + + # Changing field 'Organisation.fax' + db.alter_column('rsr_organisation', 'fax', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=20)) + + # Changing field 'Organisation.organisation_type' + db.alter_column('rsr_organisation', 'organisation_type', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=1)) + + # Changing field 'Organisation.name' + db.alter_column('rsr_organisation', 'name', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=25)) + + # Changing field 'Organisation.language' + db.alter_column('rsr_organisation', 'language', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=2)) + + # Changing field 'Organisation.long_name' + db.alter_column('rsr_organisation', 'long_name', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=75)) + + # Changing field 'Organisation.iati_org_id' + db.alter_column('rsr_organisation', 'iati_org_id', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=75, unique=True, null=True)) + + # Changing field 'Organisation.phone' + db.alter_column('rsr_organisation', 'phone', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=20)) + + # Changing field 'Organisation.contact_email' + db.alter_column('rsr_organisation', 'contact_email', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=50)) + + # Changing field 'Organisation.mobile' + db.alter_column('rsr_organisation', 'mobile', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=20)) + + # Changing field 'Organisation.contact_person' + db.alter_column('rsr_organisation', 'contact_person', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=30)) + + # Changing field 'Organisation.notes' + db.alter_column('rsr_organisation', 'notes', self.gf('akvo.rsr.fields.ValidXMLTextField')()) + + # Changing field 'Organisation.description' + db.alter_column('rsr_organisation', 'description', self.gf('akvo.rsr.fields.ValidXMLTextField')()) + + # Changing field 'MollieGateway.description' + db.alter_column('rsr_molliegateway', 'description', self.gf('akvo.rsr.fields.ValidXMLTextField')()) + + # Changing field 'MollieGateway.currency' + db.alter_column('rsr_molliegateway', 'currency', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=3)) + + # Changing field 'MollieGateway.partner_id' + db.alter_column('rsr_molliegateway', 'partner_id', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=10)) + + # Changing field 'MollieGateway.name' + db.alter_column('rsr_molliegateway', 'name', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=255)) + + # Changing field 'OrganisationAccount.account_level' + db.alter_column('rsr_organisationaccount', 'account_level', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=12)) + + # Changing field 'UserProfile.phone_number' + db.alter_column('rsr_userprofile', 'phone_number', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=50)) + + # Changing field 'UserProfile.validation' + db.alter_column('rsr_userprofile', 'validation', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=20)) + + # Changing field 'UserProfile.notes' + db.alter_column('rsr_userprofile', 'notes', self.gf('akvo.rsr.fields.ValidXMLTextField')()) + + # Changing field 'Category.name' + db.alter_column('rsr_category', 'name', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=50)) + + # Changing field 'Benchmarkname.name' + db.alter_column('rsr_benchmarkname', 'name', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=80)) + + # Changing field 'PublishingStatus.status' + db.alter_column('rsr_publishingstatus', 'status', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=30)) + + # Changing field 'Link.caption' + db.alter_column('rsr_link', 'caption', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=50)) + + # Changing field 'Link.kind' + db.alter_column('rsr_link', 'kind', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=1)) + + # Changing field 'Project.subtitle' + db.alter_column('rsr_project', 'subtitle', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=75)) + + # Changing field 'Project.current_image_caption' + db.alter_column('rsr_project', 'current_image_caption', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=50)) + + # Changing field 'Project.currency' + db.alter_column('rsr_project', 'currency', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=3)) + + # Changing field 'Project.title' + db.alter_column('rsr_project', 'title', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=45)) + + # Changing field 'Project.status' + db.alter_column('rsr_project', 'status', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=1)) + + # Changing field 'Project.sustainability' + db.alter_column('rsr_project', 'sustainability', self.gf('akvo.rsr.fields.ValidXMLTextField')()) + + # Changing field 'Project.language' + db.alter_column('rsr_project', 'language', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=2)) + + # Changing field 'Project.notes' + db.alter_column('rsr_project', 'notes', self.gf('akvo.rsr.fields.ValidXMLTextField')()) + + # Changing field 'Project.project_plan' + db.alter_column('rsr_project', 'project_plan', self.gf('akvo.rsr.fields.ValidXMLTextField')()) + + # Changing field 'Project.current_image_credit' + db.alter_column('rsr_project', 'current_image_credit', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=50)) + + # Changing field 'Partnership.iati_activity_id' + db.alter_column('rsr_partnership', 'iati_activity_id', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=75, null=True)) + + # Changing field 'Partnership.internal_id' + db.alter_column('rsr_partnership', 'internal_id', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=75, null=True)) + + # Changing field 'Partnership.partner_type' + db.alter_column('rsr_partnership', 'partner_type', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=8)) + + # Changing field 'Partnership.partner_type_extra' + db.alter_column('rsr_partnership', 'partner_type_extra', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=30, null=True)) + + # Changing field 'BudgetItem.other_extra' + db.alter_column('rsr_budgetitem', 'other_extra', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=20, null=True)) + + # Changing field 'BudgetItemLabel.label' + db.alter_column('rsr_budgetitemlabel', 'label', self.gf('akvo.rsr.fields.ValidXMLCharField')(unique=True, max_length=20)) + + # Changing field 'PayPalGateway.description' + db.alter_column('rsr_paypalgateway', 'description', self.gf('akvo.rsr.fields.ValidXMLTextField')()) + + # Changing field 'PayPalGateway.locale' + db.alter_column('rsr_paypalgateway', 'locale', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=2)) + + # Changing field 'PayPalGateway.currency' + db.alter_column('rsr_paypalgateway', 'currency', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=3)) + + # Changing field 'PayPalGateway.name' + db.alter_column('rsr_paypalgateway', 'name', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=255)) + + # Changing field 'MiniCMS.top_right_box' + db.alter_column('rsr_minicms', 'top_right_box', self.gf('akvo.rsr.fields.ValidXMLTextField')(max_length=350)) + + # Changing field 'MiniCMS.label' + db.alter_column('rsr_minicms', 'label', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=50)) + + # Changing field 'MiniCMS.feature_box' + db.alter_column('rsr_minicms', 'feature_box', self.gf('akvo.rsr.fields.ValidXMLTextField')(max_length=350)) + + # Changing field 'ProjectLocation.city' + db.alter_column('rsr_projectlocation', 'city', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=255)) + + # Changing field 'ProjectLocation.state' + db.alter_column('rsr_projectlocation', 'state', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=255)) + + # Changing field 'ProjectLocation.address_1' + db.alter_column('rsr_projectlocation', 'address_1', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=255)) + + # Changing field 'ProjectLocation.address_2' + db.alter_column('rsr_projectlocation', 'address_2', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=255)) + + # Changing field 'ProjectLocation.postcode' + db.alter_column('rsr_projectlocation', 'postcode', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=10)) + + # Changing field 'Country.iso_code' + db.alter_column('rsr_country', 'iso_code', self.gf('akvo.rsr.fields.ValidXMLCharField')(unique=True, max_length=2)) + + # Changing field 'Country.name' + db.alter_column('rsr_country', 'name', self.gf('akvo.rsr.fields.ValidXMLCharField')(unique=True, max_length=50)) + + # Changing field 'Country.continent' + db.alter_column('rsr_country', 'continent', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=20)) + + # Changing field 'Country.continent_code' + db.alter_column('rsr_country', 'continent_code', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=2)) + + # Changing field 'Invoice.engine' + db.alter_column('rsr_invoice', 'engine', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=10)) + + # Changing field 'Invoice.http_referer' + db.alter_column('rsr_invoice', 'http_referer', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=255)) + + # Changing field 'Invoice.notes' + db.alter_column('rsr_invoice', 'notes', self.gf('akvo.rsr.fields.ValidXMLTextField')()) + + # Changing field 'Invoice.ipn' + db.alter_column('rsr_invoice', 'ipn', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=75, null=True)) + + # Changing field 'Invoice.campaign_code' + db.alter_column('rsr_invoice', 'campaign_code', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=15)) + + # Changing field 'Invoice.bank' + db.alter_column('rsr_invoice', 'bank', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=4)) + + # Changing field 'Invoice.transaction_id' + db.alter_column('rsr_invoice', 'transaction_id', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=100)) + + # Changing field 'Invoice.name' + db.alter_column('rsr_invoice', 'name', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=75, null=True)) + + # Changing field 'PartnerType.id' + db.alter_column('rsr_partnertype', 'id', self.gf('akvo.rsr.fields.ValidXMLCharField')(unique=True, max_length=8, primary_key=True)) + + # Changing field 'PartnerType.label' + db.alter_column('rsr_partnertype', 'label', self.gf('akvo.rsr.fields.ValidXMLCharField')(unique=True, max_length=30)) + + # Changing field 'Goal.text' + db.alter_column('rsr_goal', 'text', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=100)) + + # Changing field 'OrganisationLocation.city' + db.alter_column('rsr_organisationlocation', 'city', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=255)) + + # Changing field 'OrganisationLocation.state' + db.alter_column('rsr_organisationlocation', 'state', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=255)) + + # Changing field 'OrganisationLocation.address_1' + db.alter_column('rsr_organisationlocation', 'address_1', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=255)) + + # Changing field 'OrganisationLocation.address_2' + db.alter_column('rsr_organisationlocation', 'address_2', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=255)) + + # Changing field 'OrganisationLocation.postcode' + db.alter_column('rsr_organisationlocation', 'postcode', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=10)) + # Deleting field 'ProjectUpdate.photo_location' + db.delete_column('rsr_projectupdate', 'photo_location') + + + # Changing field 'ProjectUpdate.user_agent' + db.alter_column('rsr_projectupdate', 'user_agent', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=200)) + + # Changing field 'ProjectUpdate.photo_credit' + db.alter_column('rsr_projectupdate', 'photo_credit', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=25)) + + # Changing field 'ProjectUpdate.photo_caption' + db.alter_column('rsr_projectupdate', 'photo_caption', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=75)) + + # Changing field 'ProjectUpdate.language' + db.alter_column('rsr_projectupdate', 'language', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=2)) + + # Changing field 'ProjectUpdate.title' + db.alter_column('rsr_projectupdate', 'title', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=50)) + + # Changing field 'ProjectUpdate.text' + db.alter_column('rsr_projectupdate', 'text', self.gf('akvo.rsr.fields.ValidXMLTextField')()) + + # Changing field 'ProjectUpdate.notes' + db.alter_column('rsr_projectupdate', 'notes', self.gf('akvo.rsr.fields.ValidXMLTextField')()) + + # Changing field 'ProjectUpdate.video_credit' + db.alter_column('rsr_projectupdate', 'video_credit', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=25)) + + # Changing field 'ProjectUpdate.video_caption' + db.alter_column('rsr_projectupdate', 'video_caption', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=75)) + + # Changing field 'ProjectUpdate.update_method' + db.alter_column('rsr_projectupdate', 'update_method', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=1)) + + # Changing field 'ProjectUpdate.uuid' + db.alter_column('rsr_projectupdate', 'uuid', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=40)) + + # Changing field 'PartnerSite.about_box' + db.alter_column('rsr_partnersite', 'about_box', self.gf('akvo.rsr.fields.ValidXMLTextField')(max_length=500)) + + # Changing field 'PartnerSite.custom_return_url_text' + db.alter_column('rsr_partnersite', 'custom_return_url_text', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=50)) + + # Changing field 'PartnerSite.hostname' + db.alter_column('rsr_partnersite', 'hostname', self.gf('akvo.rsr.fields.ValidXMLCharField')(unique=True, max_length=50)) + + # Changing field 'PartnerSite.default_language' + db.alter_column('rsr_partnersite', 'default_language', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=5)) + + # Changing field 'PartnerSite.notes' + db.alter_column('rsr_partnersite', 'notes', self.gf('akvo.rsr.fields.ValidXMLTextField')()) + + # Changing field 'PartnerSite.facebook_app_id' + db.alter_column('rsr_partnersite', 'facebook_app_id', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=40, null=True)) + + # Changing field 'FocusArea.name' + db.alter_column('rsr_focusarea', 'name', self.gf('akvo.rsr.fields.ValidXMLCharField')(max_length=50)) + + # Changing field 'FocusArea.description' + db.alter_column('rsr_focusarea', 'description', self.gf('akvo.rsr.fields.ValidXMLTextField')(max_length=500)) + + # Changing field 'ProjectComment.comment' + db.alter_column('rsr_projectcomment', 'comment', self.gf('akvo.rsr.fields.ValidXMLTextField')()) + + def backwards(self, orm): + + # Changing field 'InternalOrganisationID.identifier' + db.alter_column('rsr_internalorganisationid', 'identifier', self.gf('django.db.models.fields.CharField')(max_length=200)) + + # Changing field 'Organisation.fax' + db.alter_column('rsr_organisation', 'fax', self.gf('django.db.models.fields.CharField')(max_length=20)) + + # Changing field 'Organisation.organisation_type' + db.alter_column('rsr_organisation', 'organisation_type', self.gf('django.db.models.fields.CharField')(max_length=1)) + + # Changing field 'Organisation.name' + db.alter_column('rsr_organisation', 'name', self.gf('django.db.models.fields.CharField')(max_length=25)) + + # Changing field 'Organisation.language' + db.alter_column('rsr_organisation', 'language', self.gf('django.db.models.fields.CharField')(max_length=2)) + + # Changing field 'Organisation.long_name' + db.alter_column('rsr_organisation', 'long_name', self.gf('django.db.models.fields.CharField')(max_length=75)) + + # Changing field 'Organisation.iati_org_id' + db.alter_column('rsr_organisation', 'iati_org_id', self.gf('django.db.models.fields.CharField')(unique=True, max_length=75, null=True)) + + # Changing field 'Organisation.phone' + db.alter_column('rsr_organisation', 'phone', self.gf('django.db.models.fields.CharField')(max_length=20)) + + # Changing field 'Organisation.contact_email' + db.alter_column('rsr_organisation', 'contact_email', self.gf('django.db.models.fields.CharField')(max_length=50)) + + # Changing field 'Organisation.mobile' + db.alter_column('rsr_organisation', 'mobile', self.gf('django.db.models.fields.CharField')(max_length=20)) + + # Changing field 'Organisation.contact_person' + db.alter_column('rsr_organisation', 'contact_person', self.gf('django.db.models.fields.CharField')(max_length=30)) + + # Changing field 'Organisation.notes' + db.alter_column('rsr_organisation', 'notes', self.gf('django.db.models.fields.TextField')()) + + # Changing field 'Organisation.description' + db.alter_column('rsr_organisation', 'description', self.gf('django.db.models.fields.TextField')()) + + # Changing field 'MollieGateway.description' + db.alter_column('rsr_molliegateway', 'description', self.gf('django.db.models.fields.TextField')()) + + # Changing field 'MollieGateway.currency' + db.alter_column('rsr_molliegateway', 'currency', self.gf('django.db.models.fields.CharField')(max_length=3)) + + # Changing field 'MollieGateway.partner_id' + db.alter_column('rsr_molliegateway', 'partner_id', self.gf('django.db.models.fields.CharField')(max_length=10)) + + # Changing field 'MollieGateway.name' + db.alter_column('rsr_molliegateway', 'name', self.gf('django.db.models.fields.CharField')(max_length=255)) + + # Changing field 'OrganisationAccount.account_level' + db.alter_column('rsr_organisationaccount', 'account_level', self.gf('django.db.models.fields.CharField')(max_length=12)) + + # Changing field 'UserProfile.phone_number' + db.alter_column('rsr_userprofile', 'phone_number', self.gf('django.db.models.fields.CharField')(max_length=50)) + + # Changing field 'UserProfile.validation' + db.alter_column('rsr_userprofile', 'validation', self.gf('django.db.models.fields.CharField')(max_length=20)) + + # Changing field 'UserProfile.notes' + db.alter_column('rsr_userprofile', 'notes', self.gf('django.db.models.fields.TextField')()) + + # Changing field 'Category.name' + db.alter_column('rsr_category', 'name', self.gf('django.db.models.fields.CharField')(max_length=50)) + + # Changing field 'Benchmarkname.name' + db.alter_column('rsr_benchmarkname', 'name', self.gf('django.db.models.fields.CharField')(max_length=80)) + + # Changing field 'PublishingStatus.status' + db.alter_column('rsr_publishingstatus', 'status', self.gf('django.db.models.fields.CharField')(max_length=30)) + + # Changing field 'Link.caption' + db.alter_column('rsr_link', 'caption', self.gf('django.db.models.fields.CharField')(max_length=50)) + + # Changing field 'Link.kind' + db.alter_column('rsr_link', 'kind', self.gf('django.db.models.fields.CharField')(max_length=1)) + + # Changing field 'Project.subtitle' + db.alter_column('rsr_project', 'subtitle', self.gf('django.db.models.fields.CharField')(max_length=75)) + + # Changing field 'Project.current_image_caption' + db.alter_column('rsr_project', 'current_image_caption', self.gf('django.db.models.fields.CharField')(max_length=50)) + + # Changing field 'Project.currency' + db.alter_column('rsr_project', 'currency', self.gf('django.db.models.fields.CharField')(max_length=3)) + + # Changing field 'Project.title' + db.alter_column('rsr_project', 'title', self.gf('django.db.models.fields.CharField')(max_length=45)) + + # Changing field 'Project.status' + db.alter_column('rsr_project', 'status', self.gf('django.db.models.fields.CharField')(max_length=1)) + + # Changing field 'Project.sustainability' + db.alter_column('rsr_project', 'sustainability', self.gf('django.db.models.fields.TextField')()) + + # Changing field 'Project.language' + db.alter_column('rsr_project', 'language', self.gf('django.db.models.fields.CharField')(max_length=2)) + + # Changing field 'Project.notes' + db.alter_column('rsr_project', 'notes', self.gf('django.db.models.fields.TextField')()) + + # Changing field 'Project.project_plan' + db.alter_column('rsr_project', 'project_plan', self.gf('django.db.models.fields.TextField')()) + + # Changing field 'Project.current_image_credit' + db.alter_column('rsr_project', 'current_image_credit', self.gf('django.db.models.fields.CharField')(max_length=50)) + + # Changing field 'Partnership.iati_activity_id' + db.alter_column('rsr_partnership', 'iati_activity_id', self.gf('django.db.models.fields.CharField')(max_length=75, null=True)) + + # Changing field 'Partnership.internal_id' + db.alter_column('rsr_partnership', 'internal_id', self.gf('django.db.models.fields.CharField')(max_length=75, null=True)) + + # Changing field 'Partnership.partner_type' + db.alter_column('rsr_partnership', 'partner_type', self.gf('django.db.models.fields.CharField')(max_length=8)) + + # Changing field 'Partnership.partner_type_extra' + db.alter_column('rsr_partnership', 'partner_type_extra', self.gf('django.db.models.fields.CharField')(max_length=30, null=True)) + + # Changing field 'BudgetItem.other_extra' + db.alter_column('rsr_budgetitem', 'other_extra', self.gf('django.db.models.fields.CharField')(max_length=20, null=True)) + + # Changing field 'BudgetItemLabel.label' + db.alter_column('rsr_budgetitemlabel', 'label', self.gf('django.db.models.fields.CharField')(max_length=20, unique=True)) + + # Changing field 'PayPalGateway.description' + db.alter_column('rsr_paypalgateway', 'description', self.gf('django.db.models.fields.TextField')()) + + # Changing field 'PayPalGateway.locale' + db.alter_column('rsr_paypalgateway', 'locale', self.gf('django.db.models.fields.CharField')(max_length=2)) + + # Changing field 'PayPalGateway.currency' + db.alter_column('rsr_paypalgateway', 'currency', self.gf('django.db.models.fields.CharField')(max_length=3)) + + # Changing field 'PayPalGateway.name' + db.alter_column('rsr_paypalgateway', 'name', self.gf('django.db.models.fields.CharField')(max_length=255)) + + # Changing field 'MiniCMS.top_right_box' + db.alter_column('rsr_minicms', 'top_right_box', self.gf('django.db.models.fields.TextField')(max_length=350)) + + # Changing field 'MiniCMS.label' + db.alter_column('rsr_minicms', 'label', self.gf('django.db.models.fields.CharField')(max_length=50)) + + # Changing field 'MiniCMS.feature_box' + db.alter_column('rsr_minicms', 'feature_box', self.gf('django.db.models.fields.TextField')(max_length=350)) + + # Changing field 'ProjectLocation.city' + db.alter_column('rsr_projectlocation', 'city', self.gf('django.db.models.fields.CharField')(max_length=255)) + + # Changing field 'ProjectLocation.state' + db.alter_column('rsr_projectlocation', 'state', self.gf('django.db.models.fields.CharField')(max_length=255)) + + # Changing field 'ProjectLocation.address_1' + db.alter_column('rsr_projectlocation', 'address_1', self.gf('django.db.models.fields.CharField')(max_length=255)) + + # Changing field 'ProjectLocation.address_2' + db.alter_column('rsr_projectlocation', 'address_2', self.gf('django.db.models.fields.CharField')(max_length=255)) + + # Changing field 'ProjectLocation.postcode' + db.alter_column('rsr_projectlocation', 'postcode', self.gf('django.db.models.fields.CharField')(max_length=10)) + + # Changing field 'Country.iso_code' + db.alter_column('rsr_country', 'iso_code', self.gf('django.db.models.fields.CharField')(max_length=2, unique=True)) + + # Changing field 'Country.name' + db.alter_column('rsr_country', 'name', self.gf('django.db.models.fields.CharField')(max_length=50, unique=True)) + + # Changing field 'Country.continent' + db.alter_column('rsr_country', 'continent', self.gf('django.db.models.fields.CharField')(max_length=20)) + + # Changing field 'Country.continent_code' + db.alter_column('rsr_country', 'continent_code', self.gf('django.db.models.fields.CharField')(max_length=2)) + + # Changing field 'Invoice.engine' + db.alter_column('rsr_invoice', 'engine', self.gf('django.db.models.fields.CharField')(max_length=10)) + + # Changing field 'Invoice.http_referer' + db.alter_column('rsr_invoice', 'http_referer', self.gf('django.db.models.fields.CharField')(max_length=255)) + + # Changing field 'Invoice.notes' + db.alter_column('rsr_invoice', 'notes', self.gf('django.db.models.fields.TextField')()) + + # Changing field 'Invoice.ipn' + db.alter_column('rsr_invoice', 'ipn', self.gf('django.db.models.fields.CharField')(max_length=75, null=True)) + + # Changing field 'Invoice.campaign_code' + db.alter_column('rsr_invoice', 'campaign_code', self.gf('django.db.models.fields.CharField')(max_length=15)) + + # Changing field 'Invoice.bank' + db.alter_column('rsr_invoice', 'bank', self.gf('django.db.models.fields.CharField')(max_length=4)) + + # Changing field 'Invoice.transaction_id' + db.alter_column('rsr_invoice', 'transaction_id', self.gf('django.db.models.fields.CharField')(max_length=100)) + + # Changing field 'Invoice.name' + db.alter_column('rsr_invoice', 'name', self.gf('django.db.models.fields.CharField')(max_length=75, null=True)) + + # Changing field 'PartnerType.id' + db.alter_column('rsr_partnertype', 'id', self.gf('django.db.models.fields.CharField')(max_length=8, unique=True, primary_key=True)) + + # Changing field 'PartnerType.label' + db.alter_column('rsr_partnertype', 'label', self.gf('django.db.models.fields.CharField')(max_length=30, unique=True)) + + # Changing field 'Goal.text' + db.alter_column('rsr_goal', 'text', self.gf('django.db.models.fields.CharField')(max_length=100)) + + # Changing field 'OrganisationLocation.city' + db.alter_column('rsr_organisationlocation', 'city', self.gf('django.db.models.fields.CharField')(max_length=255)) + + # Changing field 'OrganisationLocation.state' + db.alter_column('rsr_organisationlocation', 'state', self.gf('django.db.models.fields.CharField')(max_length=255)) + + # Changing field 'OrganisationLocation.address_1' + db.alter_column('rsr_organisationlocation', 'address_1', self.gf('django.db.models.fields.CharField')(max_length=255)) + + # Changing field 'OrganisationLocation.address_2' + db.alter_column('rsr_organisationlocation', 'address_2', self.gf('django.db.models.fields.CharField')(max_length=255)) + + # Changing field 'OrganisationLocation.postcode' + db.alter_column('rsr_organisationlocation', 'postcode', self.gf('django.db.models.fields.CharField')(max_length=10)) + # Adding field 'ProjectUpdate.photo_location' + db.add_column('rsr_projectupdate', 'photo_location', + self.gf('django.db.models.fields.CharField')(default='B', max_length=1), + keep_default=False) + + + # Changing field 'ProjectUpdate.user_agent' + db.alter_column('rsr_projectupdate', 'user_agent', self.gf('django.db.models.fields.CharField')(max_length=200)) + + # Changing field 'ProjectUpdate.photo_credit' + db.alter_column('rsr_projectupdate', 'photo_credit', self.gf('django.db.models.fields.CharField')(max_length=25)) + + # Changing field 'ProjectUpdate.photo_caption' + db.alter_column('rsr_projectupdate', 'photo_caption', self.gf('django.db.models.fields.CharField')(max_length=75)) + + # Changing field 'ProjectUpdate.language' + db.alter_column('rsr_projectupdate', 'language', self.gf('django.db.models.fields.CharField')(max_length=2)) + + # Changing field 'ProjectUpdate.title' + db.alter_column('rsr_projectupdate', 'title', self.gf('django.db.models.fields.CharField')(max_length=50)) + + # Changing field 'ProjectUpdate.text' + db.alter_column('rsr_projectupdate', 'text', self.gf('django.db.models.fields.TextField')()) + + # Changing field 'ProjectUpdate.notes' + db.alter_column('rsr_projectupdate', 'notes', self.gf('django.db.models.fields.TextField')()) + + # Changing field 'ProjectUpdate.video_credit' + db.alter_column('rsr_projectupdate', 'video_credit', self.gf('django.db.models.fields.CharField')(max_length=25)) + + # Changing field 'ProjectUpdate.video_caption' + db.alter_column('rsr_projectupdate', 'video_caption', self.gf('django.db.models.fields.CharField')(max_length=75)) + + # Changing field 'ProjectUpdate.update_method' + db.alter_column('rsr_projectupdate', 'update_method', self.gf('django.db.models.fields.CharField')(max_length=1)) + + # Changing field 'ProjectUpdate.uuid' + db.alter_column('rsr_projectupdate', 'uuid', self.gf('django.db.models.fields.CharField')(max_length=40)) + + # Changing field 'PartnerSite.about_box' + db.alter_column('rsr_partnersite', 'about_box', self.gf('django.db.models.fields.TextField')(max_length=500)) + + # Changing field 'PartnerSite.custom_return_url_text' + db.alter_column('rsr_partnersite', 'custom_return_url_text', self.gf('django.db.models.fields.CharField')(max_length=50)) + + # Changing field 'PartnerSite.hostname' + db.alter_column('rsr_partnersite', 'hostname', self.gf('django.db.models.fields.CharField')(max_length=50, unique=True)) + + # Changing field 'PartnerSite.default_language' + db.alter_column('rsr_partnersite', 'default_language', self.gf('django.db.models.fields.CharField')(max_length=5)) + + # Changing field 'PartnerSite.notes' + db.alter_column('rsr_partnersite', 'notes', self.gf('django.db.models.fields.TextField')()) + + # Changing field 'PartnerSite.facebook_app_id' + db.alter_column('rsr_partnersite', 'facebook_app_id', self.gf('django.db.models.fields.CharField')(max_length=40, null=True)) + + # Changing field 'FocusArea.name' + db.alter_column('rsr_focusarea', 'name', self.gf('django.db.models.fields.CharField')(max_length=50)) + + # Changing field 'FocusArea.description' + db.alter_column('rsr_focusarea', 'description', self.gf('django.db.models.fields.TextField')(max_length=500)) + + # Changing field 'ProjectComment.comment' + db.alter_column('rsr_projectcomment', 'comment', self.gf('django.db.models.fields.TextField')()) + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'gateway.gateway': { + 'Meta': {'object_name': 'Gateway'}, + 'host_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'msg_id': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'name': ('django.db.models.fields.SlugField', [], {'max_length': '30'}), + 'receiver': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'send_path': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'sender': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'timestamp': ('django.db.models.fields.CharField', [], {'max_length': '30'}) + }, + 'gateway.gatewaynumber': { + 'Meta': {'object_name': 'GatewayNumber'}, + 'gateway': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gateway.Gateway']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'number': ('django.db.models.fields.CharField', [], {'max_length': '30'}) + }, + 'rsr.benchmark': { + 'Meta': {'ordering': "('category__name', 'name__order')", 'object_name': 'Benchmark'}, + 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Category']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Benchmarkname']"}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'benchmarks'", 'to': "orm['rsr.Project']"}), + 'value': ('django.db.models.fields.IntegerField', [], {}) + }, + 'rsr.benchmarkname': { + 'Meta': {'ordering': "['order', 'name']", 'object_name': 'Benchmarkname'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '80'}), + 'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'rsr.budgetitem': { + 'Meta': {'ordering': "('label',)", 'unique_together': "(('project', 'label'),)", 'object_name': 'BudgetItem'}, + 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '2'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.BudgetItemLabel']"}), + 'other_extra': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'budget_items'", 'to': "orm['rsr.Project']"}) + }, + 'rsr.budgetitemlabel': { + 'Meta': {'ordering': "('label',)", 'object_name': 'BudgetItemLabel'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('akvo.rsr.fields.ValidXMLCharField', [], {'unique': 'True', 'max_length': '20', 'db_index': 'True'}) + }, + 'rsr.category': { + 'Meta': {'ordering': "['name']", 'object_name': 'Category'}, + 'benchmarknames': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['rsr.Benchmarkname']", 'symmetrical': 'False', 'blank': 'True'}), + 'focus_area': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'categories'", 'symmetrical': 'False', 'to': "orm['rsr.FocusArea']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '50', 'db_index': 'True'}) + }, + 'rsr.country': { + 'Meta': {'ordering': "['name']", 'object_name': 'Country'}, + 'continent': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '20', 'db_index': 'True'}), + 'continent_code': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '2', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'iso_code': ('akvo.rsr.fields.ValidXMLCharField', [], {'unique': 'True', 'max_length': '2', 'db_index': 'True'}), + 'name': ('akvo.rsr.fields.ValidXMLCharField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}) + }, + 'rsr.focusarea': { + 'Meta': {'ordering': "['name']", 'object_name': 'FocusArea'}, + 'description': ('akvo.rsr.fields.ValidXMLTextField', [], {'max_length': '500'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), + 'link_to': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'name': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '50'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}) + }, + 'rsr.goal': { + 'Meta': {'object_name': 'Goal'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'goals'", 'to': "orm['rsr.Project']"}), + 'text': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '100', 'blank': 'True'}) + }, + 'rsr.internalorganisationid': { + 'Meta': {'unique_together': "(('recording_org', 'referenced_org'),)", 'object_name': 'InternalOrganisationID'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'identifier': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '200'}), + 'recording_org': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'internal_ids'", 'to': "orm['rsr.Organisation']"}), + 'referenced_org': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reference_ids'", 'to': "orm['rsr.Organisation']"}) + }, + 'rsr.invoice': { + 'Meta': {'ordering': "['-id']", 'object_name': 'Invoice'}, + 'amount': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'amount_received': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '10', 'decimal_places': '2', 'blank': 'True'}), + 'bank': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '4', 'blank': 'True'}), + 'campaign_code': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '15', 'blank': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'engine': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "'paypal'", 'max_length': '10'}), + 'http_referer': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '255', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ipn': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'name': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'notes': ('akvo.rsr.fields.ValidXMLTextField', [], {'default': "''", 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'invoices'", 'to': "orm['rsr.Project']"}), + 'status': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '1'}), + 'test': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'transaction_id': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '100', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}) + }, + 'rsr.link': { + 'Meta': {'object_name': 'Link'}, + 'caption': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '50'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'kind': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '1'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'links'", 'to': "orm['rsr.Project']"}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'rsr.minicms': { + 'Meta': {'ordering': "['-active', '-id']", 'object_name': 'MiniCMS'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'feature_box': ('akvo.rsr.fields.ValidXMLTextField', [], {'max_length': '350'}), + 'feature_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '50'}), + 'lower_height': ('django.db.models.fields.IntegerField', [], {'default': '500'}), + 'top_right_box': ('akvo.rsr.fields.ValidXMLTextField', [], {'max_length': '350'}) + }, + 'rsr.molliegateway': { + 'Meta': {'object_name': 'MollieGateway'}, + 'currency': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "'EUR'", 'max_length': '3'}), + 'description': ('akvo.rsr.fields.ValidXMLTextField', [], {'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '255'}), + 'notification_email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'partner_id': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '10'}) + }, + 'rsr.organisation': { + 'Meta': {'ordering': "['name']", 'object_name': 'Organisation'}, + 'allow_edit': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'contact_email': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '50', 'blank': 'True'}), + 'contact_person': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '30', 'blank': 'True'}), + 'content_owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Organisation']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'description': ('akvo.rsr.fields.ValidXMLTextField', [], {'blank': 'True'}), + 'fax': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '20', 'blank': 'True'}), + 'iati_org_id': ('akvo.rsr.fields.ValidXMLCharField', [], {'db_index': 'True', 'max_length': '75', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'internal_org_ids': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'recording_organisation'", 'symmetrical': 'False', 'through': "orm['rsr.InternalOrganisationID']", 'to': "orm['rsr.Organisation']"}), + 'language': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "'en'", 'max_length': '2'}), + 'last_modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'logo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'long_name': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '75', 'blank': 'True'}), + 'mobile': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '20', 'blank': 'True'}), + 'name': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '25', 'db_index': 'True'}), + 'new_organisation_type': ('django.db.models.fields.IntegerField', [], {'default': '22', 'db_index': 'True'}), + 'notes': ('akvo.rsr.fields.ValidXMLTextField', [], {'default': "''", 'blank': 'True'}), + 'organisation_type': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '1', 'db_index': 'True'}), + 'partner_types': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['rsr.PartnerType']", 'symmetrical': 'False'}), + 'phone': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '20', 'blank': 'True'}), + 'primary_location': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.OrganisationLocation']", 'null': 'True', 'on_delete': 'models.SET_NULL'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'rsr.organisationaccount': { + 'Meta': {'object_name': 'OrganisationAccount'}, + 'account_level': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "'free'", 'max_length': '12'}), + 'organisation': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['rsr.Organisation']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'rsr.organisationlocation': { + 'Meta': {'ordering': "['-primary']", 'object_name': 'OrganisationLocation'}, + 'address_1': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '255', 'blank': 'True'}), + 'address_2': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '255', 'blank': 'True'}), + 'city': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '255', 'blank': 'True'}), + 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Country']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latitude': ('akvo.rsr.fields.LatitudeField', [], {'default': '0', 'db_index': 'True'}), + 'location_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'locations'", 'null': 'True', 'to': "orm['rsr.Organisation']"}), + 'longitude': ('akvo.rsr.fields.LongitudeField', [], {'default': '0', 'db_index': 'True'}), + 'postcode': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '10', 'blank': 'True'}), + 'primary': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'state': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '255', 'blank': 'True'}) + }, + 'rsr.partnership': { + 'Meta': {'ordering': "['partner_type']", 'object_name': 'Partnership'}, + 'funding_amount': ('django.db.models.fields.DecimalField', [], {'db_index': 'True', 'null': 'True', 'max_digits': '10', 'decimal_places': '2', 'blank': 'True'}), + 'iati_activity_id': ('akvo.rsr.fields.ValidXMLCharField', [], {'db_index': 'True', 'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'iati_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'internal_id': ('akvo.rsr.fields.ValidXMLCharField', [], {'db_index': 'True', 'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'organisation': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'partnerships'", 'to': "orm['rsr.Organisation']"}), + 'partner_type': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '8', 'db_index': 'True'}), + 'partner_type_extra': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '30', 'null': 'True', 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'partnerships'", 'to': "orm['rsr.Project']"}) + }, + 'rsr.partnersite': { + 'Meta': {'ordering': "('organisation__name',)", 'object_name': 'PartnerSite'}, + 'about_box': ('akvo.rsr.fields.ValidXMLTextField', [], {'max_length': '500', 'blank': 'True'}), + 'about_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'cname': ('akvo.rsr.fields.NullCharField', [], {'max_length': '100', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'custom_css': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'custom_favicon': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'custom_logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'custom_return_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'custom_return_url_text': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "''", 'max_length': '50', 'blank': 'True'}), + 'default_language': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "'en'", 'max_length': '5'}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'facebook_app_id': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}), + 'facebook_button': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'google_translation': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'hostname': ('akvo.rsr.fields.ValidXMLCharField', [], {'unique': 'True', 'max_length': '50'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'notes': ('akvo.rsr.fields.ValidXMLTextField', [], {'default': "''", 'blank': 'True'}), + 'organisation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Organisation']"}), + 'twitter_button': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'ui_translation': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'rsr.partnertype': { + 'Meta': {'ordering': "('label',)", 'object_name': 'PartnerType'}, + 'id': ('akvo.rsr.fields.ValidXMLCharField', [], {'unique': 'True', 'max_length': '8', 'primary_key': 'True'}), + 'label': ('akvo.rsr.fields.ValidXMLCharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'rsr.paymentgatewayselector': { + 'Meta': {'object_name': 'PaymentGatewaySelector'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mollie_gateway': ('django.db.models.fields.related.ForeignKey', [], {'default': '1', 'to': "orm['rsr.MollieGateway']"}), + 'paypal_gateway': ('django.db.models.fields.related.ForeignKey', [], {'default': '1', 'to': "orm['rsr.PayPalGateway']"}), + 'project': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['rsr.Project']", 'unique': 'True'}) + }, + 'rsr.paypalgateway': { + 'Meta': {'object_name': 'PayPalGateway'}, + 'account_email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), + 'currency': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "'EUR'", 'max_length': '3'}), + 'description': ('akvo.rsr.fields.ValidXMLTextField', [], {'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'locale': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "'US'", 'max_length': '2'}), + 'name': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '255'}), + 'notification_email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}) + }, + 'rsr.project': { + 'Meta': {'ordering': "['-id']", 'object_name': 'Project'}, + 'background': ('akvo.rsr.fields.ProjectLimitedTextField', [], {'blank': 'True'}), + 'budget': ('django.db.models.fields.DecimalField', [], {'decimal_places': '2', 'default': '0', 'max_digits': '10', 'blank': 'True', 'null': 'True', 'db_index': 'True'}), + 'categories': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'projects'", 'symmetrical': 'False', 'to': "orm['rsr.Category']"}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'currency': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "'EUR'", 'max_length': '3'}), + 'current_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'current_image_caption': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '50', 'blank': 'True'}), + 'current_image_credit': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '50', 'blank': 'True'}), + 'current_status': ('akvo.rsr.fields.ProjectLimitedTextField', [], {'blank': 'True'}), + 'date_complete': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'date_request_posted': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today'}), + 'donate_button': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'funds': ('django.db.models.fields.DecimalField', [], {'decimal_places': '2', 'default': '0', 'max_digits': '10', 'blank': 'True', 'null': 'True', 'db_index': 'True'}), + 'funds_needed': ('django.db.models.fields.DecimalField', [], {'decimal_places': '2', 'default': '0', 'max_digits': '10', 'blank': 'True', 'null': 'True', 'db_index': 'True'}), + 'goals_overview': ('akvo.rsr.fields.ProjectLimitedTextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'language': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "'en'", 'max_length': '2'}), + 'last_modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'notes': ('akvo.rsr.fields.ValidXMLTextField', [], {'default': "''", 'blank': 'True'}), + 'partners': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'projects'", 'symmetrical': 'False', 'through': "orm['rsr.Partnership']", 'to': "orm['rsr.Organisation']"}), + 'primary_location': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.ProjectLocation']", 'null': 'True', 'on_delete': 'models.SET_NULL'}), + 'project_plan': ('akvo.rsr.fields.ValidXMLTextField', [], {'blank': 'True'}), + 'project_plan_summary': ('akvo.rsr.fields.ProjectLimitedTextField', [], {}), + 'project_rating': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'status': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "'N'", 'max_length': '1', 'db_index': 'True'}), + 'subtitle': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '75'}), + 'sustainability': ('akvo.rsr.fields.ValidXMLTextField', [], {}), + 'sync_owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Organisation']", 'null': 'True', 'on_delete': 'models.SET_NULL'}), + 'target_group': ('akvo.rsr.fields.ProjectLimitedTextField', [], {'blank': 'True'}), + 'title': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '45', 'db_index': 'True'}) + }, + 'rsr.projectcomment': { + 'Meta': {'ordering': "('-id',)", 'object_name': 'ProjectComment'}, + 'comment': ('akvo.rsr.fields.ValidXMLTextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['rsr.Project']"}), + 'time': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'rsr.projectlocation': { + 'Meta': {'ordering': "['-primary']", 'object_name': 'ProjectLocation'}, + 'address_1': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '255', 'blank': 'True'}), + 'address_2': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '255', 'blank': 'True'}), + 'city': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '255', 'blank': 'True'}), + 'country': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Country']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'latitude': ('akvo.rsr.fields.LatitudeField', [], {'default': '0', 'db_index': 'True'}), + 'location_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'locations'", 'null': 'True', 'to': "orm['rsr.Project']"}), + 'longitude': ('akvo.rsr.fields.LongitudeField', [], {'default': '0', 'db_index': 'True'}), + 'postcode': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '10', 'blank': 'True'}), + 'primary': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'state': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '255', 'blank': 'True'}) + }, + 'rsr.projectupdate': { + 'Meta': {'ordering': "['-id']", 'object_name': 'ProjectUpdate'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'language': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "'en'", 'max_length': '2'}), + 'last_modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}), + 'notes': ('akvo.rsr.fields.ValidXMLTextField', [], {'default': "''", 'blank': 'True'}), + 'photo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'photo_caption': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '75', 'blank': 'True'}), + 'photo_credit': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '25', 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'project_updates'", 'to': "orm['rsr.Project']"}), + 'text': ('akvo.rsr.fields.ValidXMLTextField', [], {'blank': 'True'}), + 'title': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '50', 'db_index': 'True'}), + 'update_method': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "'W'", 'max_length': '1', 'db_index': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'user_agent': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "''", 'max_length': '200', 'blank': 'True'}), + 'uuid': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "''", 'max_length': '40', 'db_index': 'True', 'blank': 'True'}), + 'video': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), + 'video_caption': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '75', 'blank': 'True'}), + 'video_credit': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '25', 'blank': 'True'}) + }, + 'rsr.publishingstatus': { + 'Meta': {'ordering': "('-status', 'project')", 'object_name': 'PublishingStatus'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'project': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['rsr.Project']", 'unique': 'True'}), + 'status': ('akvo.rsr.fields.ValidXMLCharField', [], {'default': "'unpublished'", 'max_length': '30'}) + }, + 'rsr.smsreporter': { + 'Meta': {'unique_together': "(('userprofile', 'gw_number', 'project'),)", 'object_name': 'SmsReporter'}, + 'gw_number': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gateway.GatewayNumber']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Project']", 'null': 'True', 'blank': 'True'}), + 'userprofile': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reporters'", 'to': "orm['rsr.UserProfile']"}) + }, + 'rsr.userprofile': { + 'Meta': {'ordering': "['user__username']", 'object_name': 'UserProfile'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notes': ('akvo.rsr.fields.ValidXMLTextField', [], {'default': "''", 'blank': 'True'}), + 'organisation': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['rsr.Organisation']"}), + 'phone_number': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '50', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), + 'validation': ('akvo.rsr.fields.ValidXMLCharField', [], {'max_length': '20', 'blank': 'True'}) + } + } + + complete_apps = ['rsr'] \ No newline at end of file diff --git a/akvo/rsr/models.py b/akvo/rsr/models.py index e42e819b09..786174a7ec 100644 --- a/akvo/rsr/models.py +++ b/akvo/rsr/models.py @@ -46,7 +46,9 @@ from akvo.api.models import create_api_key from akvo.gateway.models import GatewayNumber, Gateway -from akvo.rsr.fields import LatitudeField, LongitudeField, NullCharField, ProjectLimitedTextField +from akvo.rsr.validators import string_validator +from akvo.rsr.fields import LatitudeField, LongitudeField, NullCharField, ValidXMLCharField, ValidXMLTextField +from akvo.rsr.fields import ProjectLimitedTextField from akvo.rsr.iati_code_lists import IATI_LIST_ORGANISATION_TYPE from akvo.rsr.mixins import TimestampsMixin from akvo.utils import ( @@ -99,15 +101,15 @@ def __getattr__(self, attr, *args): class Country(models.Model): - name = models.CharField(_(u'country name'), max_length=50, unique=True, db_index=True,) - iso_code = models.CharField(_(u'ISO 3166 code'), max_length=2, unique=True, db_index=True, choices=ISO_3166_COUNTRIES,) - continent = models.CharField(_(u'continent name'), max_length=20, db_index=True,) - continent_code = models.CharField(_(u'continent code'), max_length=2, db_index=True, choices=CONTINENTS) + name = ValidXMLCharField(_(u'country name'), max_length=50, unique=True, db_index=True,) + iso_code = ValidXMLCharField(_(u'ISO 3166 code'), max_length=2, unique=True, db_index=True, choices=ISO_3166_COUNTRIES,) + continent = ValidXMLCharField(_(u'continent name'), max_length=20, db_index=True,) + continent_code = ValidXMLCharField(_(u'continent code'), max_length=2, db_index=True, choices=CONTINENTS) -# name = models.CharField(_(u'country name'), max_length=50,) -# iso_code = models.CharField(_(u'ISO 3166 code'), max_length=2, choices=ISO_3166_COUNTRIES, null=True, blank=True,) -# continent = models.CharField(_(u'continent name'), max_length=20, choices=OLD_CONTINENTS, null=True, blank=True) -# continent_code = models.CharField(_(u'continent code'), max_length=2, choices=CONTINENTS, null=True, blank=True) +# name = ValidXMLCharField(_(u'country name'), max_length=50,) +# iso_code = ValidXMLCharField(_(u'ISO 3166 code'), max_length=2, choices=ISO_3166_COUNTRIES, null=True, blank=True,) +# continent = ValidXMLCharField(_(u'continent name'), max_length=20, choices=OLD_CONTINENTS, null=True, blank=True) +# continent_code = ValidXMLCharField(_(u'continent code'), max_length=2, choices=CONTINENTS, null=True, blank=True) def __unicode__(self): return self.name @@ -132,12 +134,12 @@ class Meta: # u'to get the decimal coordinates of your project.') # latitude = LatitudeField(_(u'latitude'), default=0, help_text=_help_text) # longitude = LongitudeField(_(u'longitude'), default=0, help_text=_help_text) -# city = models.CharField(_(u'city'), blank=True, max_length=255, help_text=_('(255 characters).')) -# state = models.CharField(_(u'state'), blank=True, max_length=255, help_text=_('(255 characters).')) +# city = ValidXMLCharField(_(u'city'), blank=True, max_length=255, help_text=_('(255 characters).')) +# state = ValidXMLCharField(_(u'state'), blank=True, max_length=255, help_text=_('(255 characters).')) # country = models.ForeignKey(Country, verbose_name=_(u'country')) -# address_1 = models.CharField(_(u'address 1'), max_length=255, blank=True, help_text=_('(255 characters).')) -# address_2 = models.CharField(_(u'address 2'), max_length=255, blank=True, help_text=_('(255 characters).')) -# postcode = models.CharField(_(u'postcode'), max_length=10, blank=True, help_text=_('(10 characters).')) +# address_1 = ValidXMLCharField(_(u'address 1'), max_length=255, blank=True, help_text=_('(255 characters).')) +# address_2 = ValidXMLCharField(_(u'address 2'), max_length=255, blank=True, help_text=_('(255 characters).')) +# postcode = ValidXMLCharField(_(u'postcode'), max_length=10, blank=True, help_text=_('(10 characters).')) # content_type = models.ForeignKey(ContentType) # object_id = models.PositiveIntegerField() # content_object = generic.GenericForeignKey('content_type', 'object_id') @@ -165,12 +167,12 @@ class BaseLocation(models.Model): u'to get the decimal coordinates of your project.') latitude = LatitudeField(_(u'latitude'), db_index=True, default=0, help_text=_help_text) longitude = LongitudeField(_(u'longitude'), db_index=True, default=0, help_text=_help_text) - city = models.CharField(_(u'city'), blank=True, max_length=255, help_text=_('(255 characters).')) - state = models.CharField(_(u'state'), blank=True, max_length=255, help_text=_('(255 characters).')) + city = ValidXMLCharField(_(u'city'), blank=True, max_length=255, help_text=_('(255 characters).')) + state = ValidXMLCharField(_(u'state'), blank=True, max_length=255, help_text=_('(255 characters).')) country = models.ForeignKey(Country, verbose_name=_(u'country')) - address_1 = models.CharField(_(u'address 1'), max_length=255, blank=True, help_text=_('(255 characters).')) - address_2 = models.CharField(_(u'address 2'), max_length=255, blank=True, help_text=_('(255 characters).')) - postcode = models.CharField(_(u'postcode'), max_length=10, blank=True, help_text=_('(10 characters).')) + address_1 = ValidXMLCharField(_(u'address 1'), max_length=255, blank=True, help_text=_('(255 characters).')) + address_2 = ValidXMLCharField(_(u'address 2'), max_length=255, blank=True, help_text=_('(255 characters).')) + postcode = ValidXMLCharField(_(u'postcode'), max_length=10, blank=True, help_text=_('(10 characters).')) primary = models.BooleanField(_(u'primary location'), db_index=True, default=True) # def __unicode__(self): @@ -202,8 +204,8 @@ class ProjectLocation(BaseLocation): class PartnerType(models.Model): - id = models.CharField(max_length=8, primary_key=True, unique=True) - label = models.CharField(max_length=30, unique=True) + id = ValidXMLCharField(max_length=8, primary_key=True, unique=True) + label = ValidXMLCharField(max_length=30, unique=True) def __unicode__(self): return self.label @@ -231,17 +233,17 @@ class Partnership(models.Model): organisation = models.ForeignKey('Organisation', verbose_name=_(u'organisation'), related_name='partnerships') project = models.ForeignKey('Project', verbose_name=_(u'project'), related_name='partnerships') - partner_type = models.CharField(_(u'partner type'), max_length=8, db_index=True, choices=PARTNER_TYPES,) + partner_type = ValidXMLCharField(_(u'partner type'), max_length=8, db_index=True, choices=PARTNER_TYPES,) funding_amount = models.DecimalField( _(u'funding amount'), max_digits=10, decimal_places=2, blank=True, null=True, db_index=True ) - partner_type_extra = models.CharField( + partner_type_extra = ValidXMLCharField( _(u'partner type extra'), max_length=30, blank=True, null=True, choices=PARTNER_TYPE_EXTRAS, ) - iati_activity_id = models.CharField(_(u'IATI activity ID'), max_length=75, blank=True, null=True, db_index=True,) - internal_id = models.CharField( + iati_activity_id = ValidXMLCharField(_(u'IATI activity ID'), max_length=75, blank=True, null=True, db_index=True,) + internal_id = ValidXMLCharField( _(u'Internal ID'), max_length=75, blank=True, null=True, db_index=True, help_text=_(u"The organisation's internal ID for the project"), ) @@ -291,25 +293,25 @@ def org_type_from_iati_type(cls, iati_type): def image_path(instance, file_name): return rsr_image_path(instance, file_name, 'db/org/%(instance_pk)s/%(file_name)s') - name = models.CharField( + name = ValidXMLCharField( _(u'name'), max_length=25, db_index=True, help_text=_(u'Short name which will appear in organisation and partner listings (25 characters).'), ) - long_name = models.CharField( + long_name = ValidXMLCharField( _(u'long name'), blank=True, max_length=75, help_text=_(u'Full name of organisation (75 characters).'), ) - language = models.CharField( + language = ValidXMLCharField( max_length=2, choices=settings.LANGUAGES, default='en', help_text=u'The main language of the organisation', ) partner_types = models.ManyToManyField(PartnerType) - organisation_type = models.CharField(_(u'organisation type'), max_length=1, db_index=True, choices=ORG_TYPES) + organisation_type = ValidXMLCharField(_(u'organisation type'), max_length=1, db_index=True, choices=ORG_TYPES) new_organisation_type = models.IntegerField( _(u'IATI organisation type'), db_index=True, choices=IATI_LIST_ORGANISATION_TYPE, default=22, help_text=u'Check that this field is set to an organisation type that matches your organisation.', ) - iati_org_id = models.CharField(_(u'IATI organisation ID'), max_length=75, blank=True, null=True, db_index=True, unique=True) + iati_org_id = ValidXMLCharField(_(u'IATI organisation ID'), max_length=75, blank=True, null=True, db_index=True, unique=True) internal_org_ids = models.ManyToManyField( 'self', through='InternalOrganisationID', symmetrical=False, related_name='recording_organisation' ) @@ -327,20 +329,20 @@ def image_path(instance, file_name): help_text=_(u'Enter the full address of your web site, beginning with http://.'), ) - phone = models.CharField(_(u'phone'), blank=True, max_length=20, help_text=_(u'(20 characters).')) - mobile = models.CharField(_(u'mobile'), blank=True, max_length=20, help_text=_(u'(20 characters).')) - fax = models.CharField(_(u'fax'), blank=True, max_length=20, help_text=_(u'(20 characters).')) - contact_person = models.CharField( + phone = ValidXMLCharField(_(u'phone'), blank=True, max_length=20, help_text=_(u'(20 characters).')) + mobile = ValidXMLCharField(_(u'mobile'), blank=True, max_length=20, help_text=_(u'(20 characters).')) + fax = ValidXMLCharField(_(u'fax'), blank=True, max_length=20, help_text=_(u'(20 characters).')) + contact_person = ValidXMLCharField( _(u'contact person'), blank=True, max_length=30, help_text=_(u'Name of external contact person for your organisation (30 characters).'), ) - contact_email = models.CharField( + contact_email = ValidXMLCharField( _(u'contact email'), blank=True, max_length=50, help_text=_(u'Email to which inquiries about your organisation should be sent (50 characters).'), ) - description = models.TextField(_(u'description'), blank=True, help_text=_(u'Describe your organisation.'),) + description = ValidXMLTextField(_(u'description'), blank=True, help_text=_(u'Describe your organisation.')) - notes = models.TextField(verbose_name=_("Notes and comments"), blank=True, default='') + notes = ValidXMLTextField(verbose_name=_("Notes and comments"), blank=True, default='') # old_locations = generic.GenericRelation(Location) primary_location = models.ForeignKey('OrganisationLocation', null=True, on_delete=models.SET_NULL) @@ -348,6 +350,15 @@ def image_path(instance, file_name): content_owner = models.ForeignKey('self', null=True, blank=True, on_delete=models.SET_NULL, help_text=_(u'Organisation that maintains content for this organisation through the API.'), ) + + # Allowed to manually edit information on projects of this organisation + allow_edit = models.BooleanField( + _(u'Partner editors of this organisation are allowed to manually edit projects where this organisation is ' + u'support partner'), + help_text=_(u'When manual edits are disallowed, partner admins and editors of other organisations are also not ' + u'allowed to edit these projects.'), + default=True + ) # Managers, one default, one custom @@ -427,6 +438,10 @@ def is_support_partner(self): "returns True if the organisation is a support partner to at least one project" return self.is_partner_type(Partnership.SUPPORT_PARTNER) + def partnersites(self): + "returns the partnersites belonging to the organisation in a PartnerSite queryset" + return PartnerSite.objects.filter(organisation=self) + def website(self): return '%s' % (self.url, self.url,) website.allow_tags = True @@ -510,7 +525,7 @@ class InternalOrganisationID(models.Model): referenced_org = models.ForeignKey(Organisation, verbose_name=u'referenced organisation', related_name='reference_ids',) #TODO: add index - identifier = models.CharField(max_length=200, verbose_name=u'internal ID of referenced organisation',) + identifier = ValidXMLCharField(max_length=200, verbose_name=u'internal ID of referenced organisation',) def __unicode__(self): return u"{rec_org_name}'s internal ID for {ref_org_name}: {identifier}".format( @@ -535,7 +550,7 @@ class OrganisationAccount(models.Model): ('premium', u'Premium'), ) organisation = models.OneToOneField(Organisation, verbose_name=u'organisation', primary_key=True) - account_level = models.CharField(u'account level', max_length=12, choices=ACCOUNT_LEVEL, default='free') + account_level = ValidXMLCharField(u'account level', max_length=12, choices=ACCOUNT_LEVEL, default='free') class Meta: verbose_name = u'organisation account' @@ -545,9 +560,9 @@ class Meta: class FocusArea(models.Model): def image_path(instance, file_name): return rsr_image_path(instance, file_name, 'db/focus_area/%(file_name)s') - name = models.CharField(u'focus area name', max_length=50, help_text=_(u'The name of the focus area. This will show as the title of the focus area project listing page. (30 characters).')) + name = ValidXMLCharField(u'focus area name', max_length=50, help_text=_(u'The name of the focus area. This will show as the title of the focus area project listing page. (30 characters).')) slug = models.SlugField(u'slug', max_length=50, db_index=True, help_text=_(u'Enter the "slug" i.e. a short word or hyphenated-words. This will be used in the URL of the focus area project listing page. (20 characters, only lower case letters, numbers, hyphen and underscore allowed.).')) - description = models.TextField(u'description', max_length=500, help_text=_(u'Enter the text that will appear on the focus area project listing page. (500 characters).')) + description = ValidXMLTextField(u'description', max_length=500, help_text=_(u'Enter the text that will appear on the focus area project listing page. (500 characters).')) image = ImageWithThumbnailsField( _(u'focus area image'), upload_to=image_path, @@ -574,7 +589,7 @@ class Meta: class Benchmarkname(models.Model): - name = models.CharField(_(u'benchmark name'), max_length=80, help_text=_(u'Enter a name for the benchmark. (80 characters).')) + name = ValidXMLCharField(_(u'benchmark name'), max_length=80, help_text=_(u'Enter a name for the benchmark. (80 characters).')) order = models.IntegerField(_(u'order'), default=0, help_text=_(u'Used to order the benchmarks when displayed. Larger numbers sink to the bottom of the list.')) def __unicode__(self): @@ -590,7 +605,7 @@ class Category(models.Model): #def image_path(instance, file_name): # return rsr_image_path(instance, file_name, 'db/category/%(file_name)s') - name = models.CharField( + name = ValidXMLCharField( _(u'category name'), max_length=50, db_index=True, help_text=_(u'Enter a name for the category. (50 characters).') ) @@ -647,8 +662,8 @@ class MiniCMS(models.Model): def image_path(instance, file_name): return rsr_image_path(instance, file_name, 'db/home_page/%(file_name)s') - label = models.CharField(u'label', max_length=50, help_text=u'The label is used for identification only', ) - feature_box = models.TextField( + label = ValidXMLCharField(u'label', max_length=50, help_text=u'The label is used for identification only', ) + feature_box = ValidXMLTextField( u'feature box text', max_length=350, help_text=_(dedent(u'''Enter the text that will appear in the feature box of the home page. (350 characters)

Text should be wrapped in two <div> tags, one outer specifying position and width and an inner for text formatting.

@@ -672,7 +687,7 @@ def image_path(instance, file_name): u'feature image', blank=True, upload_to=image_path, help_text=u'Ideally the image should be 645x363 pixels in size.' ) - top_right_box = models.TextField( + top_right_box = ValidXMLTextField( u'top right box text', max_length=350, help_text=u'Enter the text that will appear in the top right box of the home page. (350 characters)' ) @@ -697,9 +712,9 @@ class Project(TimestampsMixin, models.Model): def image_path(instance, file_name): return rsr_image_path(instance, file_name, 'db/project/%(instance_pk)s/%(file_name)s') - title = models.CharField(_(u'title'), max_length=45, db_index=True, help_text=_(u'A short descriptive title for your project (45 characters).')) - subtitle = models.CharField(_(u'subtitle'), max_length=75, help_text=_(u'A subtitle with more information on the project (75 characters).')) - status = models.CharField(_(u'status'), max_length=1, choices=STATUSES, db_index=True, default='N', help_text=_(u'Current project state.')) + title = ValidXMLCharField(_(u'title'), max_length=45, db_index=True, help_text=_(u'A short descriptive title for your project (45 characters).')) + subtitle = ValidXMLCharField(_(u'subtitle'), max_length=75, help_text=_(u'A subtitle with more information on the project (75 characters).')) + status = ValidXMLCharField(_(u'status'), max_length=1, choices=STATUSES, db_index=True, default='N', help_text=_(u'Current project state.')) categories = models.ManyToManyField(Category, verbose_name=_(u'categories'), related_name='projects',) partners = models.ManyToManyField(Organisation, verbose_name=_(u'partners'), through=Partnership, related_name='projects',) project_plan_summary = ProjectLimitedTextField(_(u'summary of project plan'), max_length=400, help_text=_(u'Briefly summarize the project (400 characters).')) @@ -714,29 +729,29 @@ def image_path(instance, file_name): }, help_text=_(u'The project image looks best in landscape format (4:3 width:height ratio), and should be less than 3.5 mb in size.'), ) - current_image_caption = models.CharField(_(u'photo caption'), blank=True, max_length=50, help_text=_(u'Enter a caption for your project picture (50 characters).')) - current_image_credit = models.CharField(_(u'photo credit'), blank=True, max_length=50, help_text=_(u'Enter a credit for your project picture (50 characters).')) + current_image_caption = ValidXMLCharField(_(u'photo caption'), blank=True, max_length=50, help_text=_(u'Enter a caption for your project picture (50 characters).')) + current_image_credit = ValidXMLCharField(_(u'photo credit'), blank=True, max_length=50, help_text=_(u'Enter a credit for your project picture (50 characters).')) goals_overview = ProjectLimitedTextField(_(u'overview of goals'), max_length=600, help_text=_(u'Describe what the project hopes to accomplish (600 characters).')) - # goal_1 = models.CharField(_('goal 1'), blank=True, max_length=60, help_text=_('(60 characters)')) - # goal_2 = models.CharField(_('goal 2'), blank=True, max_length=60) - # goal_3 = models.CharField(_('goal 3'), blank=True, max_length=60) - # goal_4 = models.CharField(_('goal 4'), blank=True, max_length=60) - # goal_5 = models.CharField(_('goal 5'), blank=True, max_length=60) + # goal_1 = ValidXMLCharField(_('goal 1'), blank=True, max_length=60, help_text=_('(60 characters)')) + # goal_2 = ValidXMLCharField(_('goal 2'), blank=True, max_length=60) + # goal_3 = ValidXMLCharField(_('goal 3'), blank=True, max_length=60) + # goal_4 = ValidXMLCharField(_('goal 4'), blank=True, max_length=60) + # goal_5 = ValidXMLCharField(_('goal 5'), blank=True, max_length=60) current_status = ProjectLimitedTextField(_(u'current status'), blank=True, max_length=600, help_text=_(u'Description of current phase of project. (600 characters).')) - project_plan = models.TextField(_(u'project plan'), blank=True, help_text=_(u'Detailed information about the project and plans for implementing: the what, how, who and when. (unlimited).')) - sustainability = models.TextField(_(u'sustainability'), help_text=_(u'Describe plans for sustaining/maintaining results after implementation is complete (unlimited).')) + project_plan = ValidXMLTextField(_(u'project plan'), blank=True, help_text=_(u'Detailed information about the project and plans for implementing: the what, how, who and when. (unlimited).')) + sustainability = ValidXMLTextField(_(u'sustainability'), help_text=_(u'Describe plans for sustaining/maintaining results after implementation is complete (unlimited).')) background = ProjectLimitedTextField(_(u'background'), blank=True, max_length=1000, help_text=_(u'Relevant background information, including geographic, political, environmental, social and/or cultural issues (1000 characters).')) target_group = ProjectLimitedTextField(_(u'target group'), blank=True, max_length=600, help_text=_(u'Information about the people, organisations or resources that are being impacted by this project (600 characters).')) # project meta info - language = models.CharField(max_length=2, choices=settings.LANGUAGES, default='en', help_text=u'The main language of the project') + language = ValidXMLCharField(max_length=2, choices=settings.LANGUAGES, default='en', help_text=u'The main language of the project') project_rating = models.IntegerField(_(u'project rating'), default=0) - notes = models.TextField(_(u'notes'), blank=True, default='', help_text=_(u'(Unlimited number of characters).')) + notes = ValidXMLTextField(_(u'notes'), blank=True, default='', help_text=_(u'(Unlimited number of characters).')) # budget - currency = models.CharField(_(u'currency'), choices=CURRENCY_CHOICES, max_length=3, default='EUR') + currency = ValidXMLCharField(_(u'currency'), choices=CURRENCY_CHOICES, max_length=3, default='EUR') date_request_posted = models.DateField(_(u'start date'), default=date.today) date_complete = models.DateField(_(u'date complete'), null=True, blank=True) @@ -746,6 +761,9 @@ def image_path(instance, file_name): # donate button donate_button = models.BooleanField(_(u'donate button'), default=True, help_text=(u'Show donate button for this project.')) + # synced projects + sync_owner = models.ForeignKey(Organisation, null=True, on_delete=models.SET_NULL) + # denormalized data # ================= budget = models.DecimalField(_('project budget'), max_digits=10, decimal_places=2, blank=True, null=True, db_index=True, default=0) @@ -795,7 +813,10 @@ def anonymous_donations_amount_received(self): # New API, de-normalized fields support def get_budget(self): - return BudgetItem.objects.filter(project__exact=self).aggregate(Sum('amount'))['amount__sum'] or 0 + if 'total' in BudgetItemLabel.objects.filter(budgetitem__project__exact=self): + return BudgetItem.objects.filter(project__exact=self).filter(label__label='total')[0].amount + else: + return BudgetItem.objects.filter(project__exact=self).aggregate(Sum('amount'))['amount__sum'] or 0 def update_budget(self): "Update de-normalized field" @@ -1172,7 +1193,7 @@ class Meta: class Goal(models.Model): project = models.ForeignKey(Project, verbose_name=u'project', related_name='goals') - text = models.CharField(_(u'goal'), blank=True, max_length=100, help_text=_(u'(100 characters)')) + text = ValidXMLCharField(_(u'goal'), blank=True, max_length=100, help_text=_(u'(100 characters)')) class Benchmark(models.Model): @@ -1197,7 +1218,7 @@ class Meta: class BudgetItemLabel(models.Model): - label = models.CharField(_(u'label'), max_length=20, unique=True, db_index=True) + label = ValidXMLCharField(_(u'label'), max_length=20, unique=True, db_index=True) def __unicode__(self): return self.label @@ -1214,7 +1235,7 @@ class BudgetItem(models.Model): project = models.ForeignKey(Project, verbose_name=_(u'project'), related_name='budget_items') label = models.ForeignKey(BudgetItemLabel, verbose_name=_(u'label'),) - other_extra = models.CharField( + other_extra = ValidXMLCharField( max_length=20, null=True, blank=True, verbose_name=_(u'"Other" labels extra info'), help_text=_(u'Extra information about the exact nature of an "other" budget item.'), ) @@ -1254,7 +1275,7 @@ class PublishingStatus(models.Model): #TODO: change to a generic relation if we want to have publishing stats on #other objects than projects project = models.OneToOneField(Project,) - status = models.CharField(max_length=30, choices=PUBLISHING_STATUS, default='unpublished') + status = ValidXMLCharField(max_length=30, choices=PUBLISHING_STATUS, default='unpublished') class Meta: verbose_name = _(u'publishing status') @@ -1270,9 +1291,9 @@ class Link(models.Model): ('A', _(u'Akvopedia entry')), ('E', _(u'External link')), ) - kind = models.CharField(_(u'kind'), max_length=1, choices=LINK_KINDS) + kind = ValidXMLCharField(_(u'kind'), max_length=1, choices=LINK_KINDS) url = models.URLField(_(u'URL')) - caption = models.CharField(_(u'caption'), max_length=50) + caption = ValidXMLCharField(_(u'caption'), max_length=50) project = models.ForeignKey(Project, verbose_name=u'project', related_name='links') def __unicode__(self): @@ -1322,10 +1343,10 @@ class UserProfile(models.Model, PermissionBase, WorkflowBase): ''' user = models.OneToOneField(User) organisation = models.ForeignKey(Organisation) - phone_number = models.CharField(max_length=50, blank=True) # TODO: check uniqueness if non-empty - validation = models.CharField(_('validation code'), max_length=20, blank=True) + phone_number = ValidXMLCharField(max_length=50, blank=True) # TODO: check uniqueness if non-empty + validation = ValidXMLCharField(_('validation code'), max_length=20, blank=True) - notes = models.TextField(verbose_name=_("Notes and comments"), blank=True, default='') + notes = ValidXMLTextField(verbose_name=_("Notes and comments"), blank=True, default='') objects = UserProfileManager() @@ -1435,6 +1456,27 @@ def _remove_user_from_group(self, group_name): def my_projects(self): return self.organisation.all_projects() + def allow_edit(self, project): + """ Support partner organisations may "take ownership" of projects, meaning that editing of them is restricted + This method is used "on top" of normal checking for user access to projects since it is only relevant for + Partner users + """ + allow_edit = True + partner_admins_allowed = [] + # compile list of support orgs that limit editing + for partner in project.support_partners(): + if not partner.allow_edit: + allow_edit = False + partner_admins_allowed.append(partner) + # no-one limits editing, all systems go + if allow_edit: + return True + # Only Partner admins on the list of "limiters" list may edit + else: + if self.get_is_org_admin() and self.organisation in partner_admins_allowed: + return True + return False + def my_unreported_projects(self): """ Projects I may do SMS updates for that aren't linked through an SmsReporter yet, filtering out reporters that have no project set @@ -1807,10 +1849,7 @@ class ProjectUpdate(TimestampsMixin, models.Model): ('S', _(u'SMS')), ('M', _(u'mobile')), ) - PHOTO_LOCATIONS = ( - ('B', _(u'At the beginning of the update')), - ('E', _(u'At the end of the update')), - ) + def image_path(instance, file_name): "Create a path like 'db/project//update//image_name.ext'" @@ -1819,10 +1858,10 @@ def image_path(instance, file_name): project = models.ForeignKey(Project, related_name='project_updates', verbose_name=_(u'project')) user = models.ForeignKey(User, verbose_name=_(u'user')) - title = models.CharField(_(u'title'), max_length=50, db_index=True, help_text=_(u'50 characters')) - text = models.TextField(_(u'text'), blank=True) - language = models.CharField(max_length=2, choices=settings.LANGUAGES, default='en', help_text=u'The language of the update') - #status = models.CharField(max_length=1, choices=STATUSES, default='N') + title = ValidXMLCharField(_(u'title'), max_length=50, db_index=True, help_text=_(u'50 characters')) + text = ValidXMLTextField(_(u'text'), blank=True) + language = ValidXMLCharField(max_length=2, choices=settings.LANGUAGES, default='en', help_text=u'The language of the update') + #status = ValidXMLCharField(max_length=1, choices=STATUSES, default='N') photo = ImageWithThumbnailsField( _(u'photo'), blank=True, @@ -1830,20 +1869,19 @@ def image_path(instance, file_name): thumbnail={'size': (300, 225), 'options': ('autocrop', 'sharpen', )}, help_text=_(u'The image should have 4:3 height:width ratio for best displaying result'), ) - photo_location = models.CharField(_(u'photo location'), max_length=1, choices=PHOTO_LOCATIONS) - photo_caption = models.CharField(_(u'photo caption'), blank=True, max_length=75, help_text=_(u'75 characters')) - photo_credit = models.CharField(_(u'photo credit'), blank=True, max_length=25, help_text=_(u'25 characters')) + photo_caption = ValidXMLCharField(_(u'photo caption'), blank=True, max_length=75, help_text=_(u'75 characters')) + photo_credit = ValidXMLCharField(_(u'photo credit'), blank=True, max_length=25, help_text=_(u'25 characters')) video = models.URLField(_(u'video URL'), blank=True, help_text=_(u'Supported providers: Blip, Vimeo, YouTube'), verify_exists=False) - video_caption = models.CharField(_(u'video caption'), blank=True, max_length=75, help_text=_(u'75 characters')) - video_credit = models.CharField(_(u'video credit'), blank=True, max_length=25, help_text=_(u'25 characters')) - update_method = models.CharField(_(u'update method'), blank=True, max_length=1, choices=UPDATE_METHODS, db_index=True, default='W') + video_caption = ValidXMLCharField(_(u'video caption'), blank=True, max_length=75, help_text=_(u'75 characters')) + video_credit = ValidXMLCharField(_(u'video credit'), blank=True, max_length=25, help_text=_(u'25 characters')) + update_method = ValidXMLCharField(_(u'update method'), blank=True, max_length=1, choices=UPDATE_METHODS, db_index=True, default='W') # time = models.DateTimeField(_(u'time'), db_index=True, auto_now_add=True) # time_last_updated = models.DateTimeField(_(u'time last updated'), db_index=True, auto_now=True) - user_agent = models.CharField(_(u'user agent'), blank=True, max_length=200, default='') - uuid = models.CharField(_(u'uuid'), blank=True, max_length=40, default='', db_index=True, + user_agent = ValidXMLCharField(_(u'user agent'), blank=True, max_length=200, default='') + uuid = ValidXMLCharField(_(u'uuid'), blank=True, max_length=40, default='', db_index=True, help_text=_(u'Universally unique ID set by creating user agent')) - notes = models.TextField(verbose_name=_("Notes and comments"), blank=True, default='') + notes = ValidXMLTextField(verbose_name=_("Notes and comments"), blank=True, default='') class Meta: get_latest_by = "created_at" @@ -1880,6 +1918,9 @@ def get_video_oembed(self, html=''): try: data = oembed.site.embed(self.video).get_data() html = data.get('html', '') + # Add 'rel=0' to the video link for not showing related Youtube videos + if "youtube" in html: + html = html.replace("feature=oembed", "feature=oembed&rel=0") except: pass return mark_safe(html) @@ -1917,16 +1958,6 @@ def view_count(self): counter = ViewCounter.objects.get_for_object(self) return counter.count or 0 - @property - def media_location(self): - return self.photo_location - - @property - def text_location(self, location='B'): - if self.media_location == 'B': - location = 'E' - return location - @models.permalink def get_absolute_url(self): return ('update_main', (), {'project_id': self.project.pk, 'update_id': self.pk}) @@ -1938,7 +1969,7 @@ def __unicode__(self): class ProjectComment(models.Model): project = models.ForeignKey(Project, verbose_name=_(u'project'), related_name='comments') user = models.ForeignKey(User, verbose_name=_(u'user')) - comment = models.TextField(_(u'comment')) + comment = ValidXMLTextField(_(u'comment')) time = models.DateTimeField(_(u'time'), db_index=True) class Meta: @@ -1949,9 +1980,9 @@ class Meta: # Payment engines class PaymentGateway(models.Model): - name = models.CharField(max_length=255, help_text=u'Use a short, descriptive name.') - description = models.TextField(blank=True) - currency = models.CharField(max_length=3, choices=CURRENCY_CHOICES, default='EUR') + name = ValidXMLCharField(max_length=255, help_text=u'Use a short, descriptive name.') + description = ValidXMLTextField(blank=True) + currency = ValidXMLCharField(max_length=3, choices=CURRENCY_CHOICES, default='EUR') notification_email = models.EmailField(u'notification email', help_text=u'When a donation is completed successfully, notification emails will be sent to the donor and to this address.') @@ -1967,14 +1998,14 @@ class PayPalGateway(PaymentGateway): ('US', u'US English'), ) account_email = models.EmailField() - locale = models.CharField(max_length=2, choices=PAYPAL_LOCALE_CHOICES, default='US') + locale = ValidXMLCharField(max_length=2, choices=PAYPAL_LOCALE_CHOICES, default='US') class Meta: verbose_name = u'PayPal gateway' class MollieGateway(PaymentGateway): - partner_id = models.CharField(max_length=10) + partner_id = ValidXMLCharField(max_length=10) class Meta: verbose_name = u'Mollie/iDEAL gateway' @@ -2031,7 +2062,7 @@ class Invoice(models.Model): ) # Setup test = models.BooleanField(u'test donation', help_text=u'This flag is set if the donation was made in test mode.') - engine = models.CharField(u'payment engine', choices=PAYMENT_ENGINES, max_length=10, default='paypal') + engine = ValidXMLCharField(u'payment engine', choices=PAYMENT_ENGINES, max_length=10, default='paypal') user = models.ForeignKey(User, blank=True, null=True) project = models.ForeignKey(Project, related_name='invoices') # Common @@ -2041,19 +2072,19 @@ class Invoice(models.Model): help_text=u'Amount actually received after charges have been applied.' ) time = models.DateTimeField(auto_now_add=True) - name = models.CharField(max_length=75, blank=True, null=True) + name = ValidXMLCharField(max_length=75, blank=True, null=True) email = models.EmailField(blank=True, null=True) status = models.PositiveSmallIntegerField('status', choices=STATUS_CHOICES, default=1) - http_referer = models.CharField(u'HTTP referer', max_length=255, blank=True) - campaign_code = models.CharField(u'Campaign code', blank=True, max_length=15) + http_referer = ValidXMLCharField(u'HTTP referer', max_length=255, blank=True) + campaign_code = ValidXMLCharField(u'Campaign code', blank=True, max_length=15) is_anonymous = models.BooleanField(u'anonymous donation') # PayPal - ipn = models.CharField(u'PayPal IPN', blank=True, null=True, max_length=75) + ipn = ValidXMLCharField(u'PayPal IPN', blank=True, null=True, max_length=75) # Mollie - bank = models.CharField(u'mollie.nl bank ID', max_length=4, choices=get_mollie_banklist(), blank=True) - transaction_id = models.CharField(u'mollie.nl transaction ID', max_length=100, blank=True) + bank = ValidXMLCharField(u'mollie.nl bank ID', max_length=4, choices=get_mollie_banklist(), blank=True) + transaction_id = ValidXMLCharField(u'mollie.nl transaction ID', max_length=100, blank=True) - notes = models.TextField(verbose_name=_("Notes and comments"), blank=True, default='') + notes = ValidXMLTextField(verbose_name=_("Notes and comments"), blank=True, default='') admin_objects = models.Manager() objects = InvoiceManager() @@ -2144,8 +2175,8 @@ def custom_logo_path(instance, filename): organisation = models.ForeignKey(Organisation, verbose_name=_(u'organisation'), help_text=_('Select your organisation from the drop-down list.') ) - notes = models.TextField(verbose_name=u'Akvo partner site notes', blank=True, default='') - hostname = models.CharField(_(u'hostname'), max_length=50, unique=True, + notes = ValidXMLTextField(verbose_name=u'Akvo partner site notes', blank=True, default='') + hostname = ValidXMLCharField(_(u'hostname'), max_length=50, unique=True, help_text=_( u'

Your hostname is used in the default web address of your partner site. ' u'The web address created from the hostname myorganisation would be ' @@ -2164,6 +2195,12 @@ def custom_logo_path(instance, filename): u'should be returned when leaving the partner site.

' ) ) + custom_return_url_text = ValidXMLCharField(_(u'Return URL text'), blank=True, max_length=50, default='', + help_text=_( + u'

Enter a text for the back button and return URL. ' + u'Leave empty to display "Back to myorganisation".

' + ) + ) custom_css = models.FileField(_(u'stylesheet'), blank=True, upload_to=custom_css_path) custom_logo = models.FileField(_(u'organisation banner logo'), blank=True, upload_to=custom_logo_path, help_text=_( @@ -2177,7 +2214,7 @@ def custom_logo_path(instance, filename): u'on tabs and in the bookmark menu.

' ) ) - about_box = models.TextField(_(u'about box text'), max_length=500, blank=True, + about_box = ValidXMLTextField(_(u'about box text'), max_length=500, blank=True, help_text=_(dedent(u''' Enter HTML that will make up the top left box of the home page. (500 characters)

@@ -2210,7 +2247,7 @@ def custom_logo_path(instance, filename): ) enabled = models.BooleanField(_(u'enabled'), default=True) - default_language = models.CharField(_(u'Site UI default language'), + default_language = ValidXMLCharField(_(u'Site UI default language'), max_length=5, choices=settings.LANGUAGES, default=settings.LANGUAGE_CODE) @@ -2219,7 +2256,7 @@ def custom_logo_path(instance, filename): google_translation = models.BooleanField(_(u'Google translation widget'), default=False) facebook_button = models.BooleanField(_(u'Facebook Like button'), default=False) twitter_button = models.BooleanField(_(u'Twitter button'), default=False) - facebook_app_id = models.CharField(_(u'Facebook App Id'), max_length=40, blank=True, null=True, + facebook_app_id = ValidXMLCharField(_(u'Facebook App Id'), max_length=40, blank=True, null=True, help_text=_( u'

Your FaceBook app id is used when sharing pages from your partner site. ' u'It can be obtained by creating a Facebook app, which will let you monitor when your pages are referenced. ' @@ -2227,6 +2264,7 @@ def custom_logo_path(instance, filename): ) ) + def __unicode__(self): return u'Partner site for %(organisation_name)s' % {'organisation_name': self.organisation.name} diff --git a/akvo/rsr/templatetags/google_maps.py b/akvo/rsr/templatetags/google_maps.py.old similarity index 100% rename from akvo/rsr/templatetags/google_maps.py rename to akvo/rsr/templatetags/google_maps.py.old diff --git a/akvo/rsr/templatetags/map.py b/akvo/rsr/templatetags/map.py.old similarity index 100% rename from akvo/rsr/templatetags/map.py rename to akvo/rsr/templatetags/map.py.old diff --git a/akvo/rsr/templatetags/maps.py b/akvo/rsr/templatetags/maps.py new file mode 100644 index 0000000000..f4c3d93313 --- /dev/null +++ b/akvo/rsr/templatetags/maps.py @@ -0,0 +1,264 @@ +# -*- coding: utf-8 -*- +""" + Akvo RSR is covered by the GNU Affero General Public License. + See more details in the license.txt file located at the root folder of the + Akvo RSR module. For additional details on the GNU license please + see < http://www.gnu.org/licenses/agpl.html >. +""" + +import os +from django import template +from django.conf import settings + +from akvo.rsr.models import Project, Organisation, ProjectLocation, OrganisationLocation + +register = template.Library() + +PROJECT_MARKER_ICON = getattr(settings, 'GOOGLE_MAPS_PROJECT_MARKER_ICON', '') +ORGANISATION_MARKER_ICON = getattr(settings, 'GOOGLE_MAPS_ORGANISATION_MARKER_ICON', '') +MEDIA_URL = getattr(settings, 'MEDIA_URL', '/media/') + + +# TODO: this should be fixed so partner sites use their own domain +HOST = 'http://%s' % getattr(settings, 'RSR_DOMAIN', 'akvo.org') + +@register.inclusion_tag('inclusion_tags/maps.html') +def project_map(id, width, height, dynamic='dynamic'): + """ + params: + id: integer, id of project or organisation. + width, height: the dimensions of the map. + dynamic: 'dynamic' (default) or 'static', map is scrollable and clickable if 'dynamic'. + """ + + if dynamic != 'dynamic': + dynamic = False + + map_id = 'akvo_map_%s' % os.urandom(8).encode('hex') + marker_icon = PROJECT_MARKER_ICON + + locations = [] + + for location in ProjectLocation.objects.filter(location_target=id): + locations.append([location.latitude, location.longitude]) + + template_context = { + 'map_id': map_id, + 'width': width, + 'height': height, + 'marker_icon': marker_icon, + 'locations': locations, + 'dynamic': dynamic, + 'infowindows': False, + 'partnersite_widget': False + } + + return template_context + + +@register.inclusion_tag('inclusion_tags/maps.html') +def organisation_map(id, width, height, dynamic='dynamic'): + """ + params: + id: integer, id of project or organisation. + width, height: the dimensions of the map. + dynamic: 'dynamic' (default) or 'static', map is scrollable and clickable if 'dynamic'. + """ + + if dynamic != 'dynamic': + dynamic = False + + map_id = 'akvo_map_%s' % os.urandom(8).encode('hex') + marker_icon = ORGANISATION_MARKER_ICON + + locations = [] + + for location in OrganisationLocation.objects.filter(location_target_id=id): + locations.append([location.latitude, location.longitude]) + + template_context = { + 'map_id': map_id, + 'width': width, + 'height': height, + 'marker_icon': marker_icon, + 'locations': locations, + 'dynamic': dynamic, + 'infowindows': False, + 'partnersite_widget': False + } + + return template_context + + +@register.inclusion_tag('inclusion_tags/maps.html') +def global_project_map(width, height, dynamic='dynamic'): + """ + params: + width, height: the dimensions of the map. + dynamic: 'dynamic' (default) or 'static', map is scrollable and clickable if 'dynamic'. + """ + + if dynamic != 'dynamic': + dynamic = False + + map_id = 'akvo_map_%s' % os.urandom(8).encode('hex') + marker_icon = PROJECT_MARKER_ICON + + locations = [] + + for project in Project.objects.all().active(): + try: + location = project.primary_location + thumbnail = project.current_image.extra_thumbnails['map_thumb'].absolute_url + locations.append([location.latitude, + location.longitude, + [str(project.pk),project.title.encode('utf8'), thumbnail, 'project']]) + except: + pass + + template_context = { + 'map_id': map_id, + 'width': width, + 'height': height, + 'marker_icon': marker_icon, + 'locations': locations, + 'dynamic': dynamic, + 'infowindows': True, + 'partnersite_widget': False + } + + return template_context + + +@register.inclusion_tag('inclusion_tags/maps.html') +def global_organisation_map(width, height, dynamic='dynamic'): + """ + params: + width, height: the dimensions of the map. + dynamic: 'dynamic' (default) or 'static', map is scrollable and clickable if 'dynamic'. + """ + + if dynamic != 'dynamic': + dynamic = False + + map_id = 'akvo_map_%s' % os.urandom(8).encode('hex') + marker_icon = ORGANISATION_MARKER_ICON + + locations = [] + + for organisation in Organisation.objects.all(): + try: + location = organisation.primary_location + thumbnail = organisation.logo.extra_thumbnails['map_thumb'].absolute_url + locations.append([location.latitude, + location.longitude, + [str(organisation.pk),organisation.name.encode('utf8'), thumbnail, 'organisation']]) + except: + pass + + template_context = { + 'map_id': map_id, + 'width': width, + 'height': height, + 'marker_icon': marker_icon, + 'locations': locations, + 'dynamic': dynamic, + 'infowindows': True, + 'partnersite_widget': False + } + + return template_context + + +@register.inclusion_tag('inclusion_tags/maps.html') +def organisation_projects_map(organisation_id, width, height, dynamic='dynamic'): + """ + params: + organisation_id: id of organisation. + width, height: the dimensions of the map. + dynamic: 'dynamic' (default) or 'static', map is scrollable and clickable if 'dynamic'. + """ + + if dynamic != 'dynamic': + dynamic = False + + map_id = 'akvo_map_%s' % os.urandom(8).encode('hex') + marker_icon = PROJECT_MARKER_ICON + + locations = [] + + projects = Project.objects.filter(partnerships__organisation=organisation_id).active() + + for project in projects: + proj_locations = ProjectLocation.objects.filter(location_target=project) + for location in proj_locations: + try: + thumbnail = project.current_image.extra_thumbnails['map_thumb'].absolute_url + locations.append([location.latitude, + location.longitude, + [str(project.pk),project.title.encode('utf8'), thumbnail, 'project']]) + except: + pass + + template_context = { + 'map_id': map_id, + 'width': width, + 'height': height, + 'marker_icon': marker_icon, + 'locations': locations, + 'dynamic': dynamic, + 'infowindows': True, + 'partnersite_widget': False + } + + return template_context + + +@register.inclusion_tag('inclusion_tags/maps.html') +def partnersite_widget_project_map(organisation_id, width, height, dynamic='dynamic'): + """ + params: + organisation_id: id of organisation. + width, height: the dimensions of the map. + dynamic: 'dynamic' (default) or 'static', map is scrollable and clickable if 'dynamic'. + """ + + if dynamic != 'dynamic': + dynamic = False + + map_id = 'akvo_map_%s' % os.urandom(8).encode('hex') + marker_icon = PROJECT_MARKER_ICON + + locations = [] + + projects = Project.objects.filter(partnerships__organisation=organisation_id).active() + + for project in projects: + proj_locations = ProjectLocation.objects.filter(location_target=project) + for location in proj_locations: + location_name = location.country.name + if location.state: + location_name += ", " + location.state + if location.city: + location_name += ", " + location.city + + try: + locations.append([location.latitude, + location.longitude, + [str(project.pk), project.title.encode('utf8'), 'project'], + location_name.encode('utf8')]) + except: + pass + + template_context = { + 'map_id': map_id, + 'width': width, + 'height': height, + 'marker_icon': marker_icon, + 'locations': locations, + 'dynamic': dynamic, + 'infowindows': True, + 'partnersite_widget': True + } + + return template_context \ No newline at end of file diff --git a/akvo/rsr/templatetags/project_map.py b/akvo/rsr/templatetags/project_map.py.old similarity index 100% rename from akvo/rsr/templatetags/project_map.py rename to akvo/rsr/templatetags/project_map.py.old diff --git a/akvo/rsr/validators.py b/akvo/rsr/validators.py new file mode 100644 index 0000000000..575e63d775 --- /dev/null +++ b/akvo/rsr/validators.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- + +# Akvo RSR is covered by the GNU Affero General Public License. +# See more details in the license.txt file located at the root folder of the Akvo RSR module. +# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >. + +import sys, re + +from django.core.exceptions import ValidationError + + +def string_validator(value): + # Based on http://stackoverflow.com/questions/1707890/fast-way-to-filter-illegal-xml-unicode-chars-in-python + # Example of non-allowed character: ﷐ + _illegal_unichrs = [(0x00, 0x08), (0x0B, 0x0C), (0x0E, 0x1F), (0x7F, 0x84), (0x86, 0x9F), (0xFDD0, 0xFDDF), + (0xFFFE, 0xFFFF)] + + if sys.maxunicode >= 0x10000: # not narrow build + _illegal_unichrs.extend([(0x1FFFE, 0x1FFFF), (0x2FFFE, 0x2FFFF), (0x3FFFE, 0x3FFFF), (0x4FFFE, 0x4FFFF), + (0x5FFFE, 0x5FFFF), (0x6FFFE, 0x6FFFF), (0x7FFFE, 0x7FFFF), (0x8FFFE, 0x8FFFF), + (0x9FFFE, 0x9FFFF), (0xAFFFE, 0xAFFFF), (0xBFFFE, 0xBFFFF), (0xCFFFE, 0xCFFFF), + (0xDFFFE, 0xDFFFF), (0xEFFFE, 0xEFFFF), (0xFFFFE, 0xFFFFF), (0x10FFFE, 0x10FFFF)]) + + _illegal_ranges = ["%s-%s" % (unichr(low), unichr(high)) for (low, high) in _illegal_unichrs] + + RESTRICTED_CHARACTERS = re.compile(u'[%s]' % u''.join(_illegal_ranges)) + + match = re.search(RESTRICTED_CHARACTERS, value) + if match: + raise ValidationError('%s is not an allowed character' % match.group(0)) diff --git a/akvo/rsr/views.py b/akvo/rsr/views.py index 2f2712690d..db095bfb2a 100644 --- a/akvo/rsr/views.py +++ b/akvo/rsr/views.py @@ -75,7 +75,8 @@ def forbidden(request, template_name='403.html'): t = loader.get_template(template_name) return http.HttpResponseForbidden(t.render(Context({ 'error_message': message, - 'MEDIA_URL': settings.MEDIA_URL + 'MEDIA_URL': settings.MEDIA_URL, + 'user': request.user }))) @@ -411,9 +412,16 @@ def partners_widget(request, org_type='all'): def login(request, template_name='registration/login.html', redirect_field_name=REDIRECT_FIELD_NAME): "Displays the login form and handles the login action." redirect_to = request.REQUEST.get(redirect_field_name, '') - # Check for exeptions to the return to start of sign in process - if redirect_to == "/accounts/register/complete/": - redirect_to = "/home" + + # Non logical URLs for redirection after signing in + redirect_blacklist = [reverse('signin'), + reverse('signout'), + reverse('register1'), + reverse('register2'), + reverse('registration_update_complete')] + + if redirect_to in redirect_blacklist: + redirect_to = "/" if request.method == "POST": form = AuthenticationForm(data=request.POST) @@ -670,6 +678,7 @@ def projectcomments(request, project_id): comments = Project.objects.get(id=project_id).comments.all().order_by('-time') form = CommentForm() updates = project.project_updates.all().order_by('-created_at')[:3] + can_add_update = project.connected_to_user(request.user) return { 'project': project, 'comments': comments, @@ -677,6 +686,7 @@ def projectcomments(request, project_id): 'project_section': 'comments', 'hide_comments': True, 'updates': updates, + 'can_add_update': can_add_update } @@ -919,6 +929,8 @@ def projectmain(request, project, draft=False, can_add_update=False): else: admin_change_url = None + can_add_update = project.connected_to_user(request.user) + return { 'admin_change_url': admin_change_url, 'benchmarks': benchmarks, @@ -944,6 +956,7 @@ def projectdetails(request, project_id): def projectpartners(request, project, draft=False, can_add_update=False): updates = project.project_updates.all().order_by('-created_at')[:3] comments = project.comments.all().order_by('-time')[:3] + can_add_update = project.connected_to_user(request.user) return { 'can_add_update': can_add_update, 'draft': draft, @@ -961,6 +974,7 @@ def projectfunding(request, project, draft=False, can_add_update=False): public_donations = project.public_donations() updates = project.project_updates.all().order_by('-created_at')[:3] comments = project.comments.all().order_by('-time')[:3] + can_add_update = project.connected_to_user(request.user) return { 'can_add_update': can_add_update, 'draft': draft, @@ -1145,7 +1159,7 @@ def project_map_widget(request, org_id): textcolor = request.GET.get('textcolor', 'FFFFFF') width = request.GET.get('width', '600') zoom = request.GET.get('zoom', '1') - state = request.GET.get('state', 'static') + state = request.GET.get('state', 'dynamic') if state != 'dynamic': state = 'static' diff --git a/akvo/rsr/views_partner_sites/auth.py b/akvo/rsr/views_partner_sites/auth.py index 0798476a34..55960194f0 100644 --- a/akvo/rsr/views_partner_sites/auth.py +++ b/akvo/rsr/views_partner_sites/auth.py @@ -42,7 +42,15 @@ def dispatch(self, *args, **kwargs): def form_valid(self, form): """On valid form login and redirect the user to the appropriate url""" login(self.request, form.get_user()) - return HttpResponseRedirect(self.request.POST.get('next', '/')) + + redirect_blacklist = [reverse('sign_in'), + reverse('sign_out')] + + redirect_to = self.request.POST.get('next', '/') + if redirect_to in redirect_blacklist: + redirect_to = "/" + + return HttpResponseRedirect(redirect_to) def get_context_data(self, **kwargs): context = super(SignInView, self).get_context_data(**kwargs) @@ -88,8 +96,8 @@ def _get_redirect_url(self): hostname = self.request.partner_site.hostname app_domain = getattr(settings, 'AKVOAPP_DOMAIN', 'akvoapp.org') request_path = self.request.get_full_path() - url = 'http://%s.%s%s' % (hostname, app_domain, request_path) + url = 'http://%s.%s%s' % (hostname, app_domain, request_path) if getattr(settings, 'HTTPS_SUPPORT', True): return url.replace('http://', 'https://') return url diff --git a/akvo/rsr/views_partner_sites/base.py b/akvo/rsr/views_partner_sites/base.py index 43ab954578..1291c4676b 100644 --- a/akvo/rsr/views_partner_sites/base.py +++ b/akvo/rsr/views_partner_sites/base.py @@ -52,6 +52,7 @@ def get_context_data(self, **kwargs): Organisation, pk=self.request.organisation_id ) context['return_url'] = self.request.partner_site.return_url + context['return_url_text'] = self.request.partner_site.custom_return_url_text context['stylesheet'] = self.request.partner_site.stylesheet context['akvoapp_root_url'] = self.request.akvoapp_root_url context['domain_url'] = self.request.domain_url diff --git a/akvo/rsr/views_partner_sites/partner.py b/akvo/rsr/views_partner_sites/partner.py index 330d5ddea7..de4953ffd9 100644 --- a/akvo/rsr/views_partner_sites/partner.py +++ b/akvo/rsr/views_partner_sites/partner.py @@ -44,7 +44,4 @@ def get_context_data(self, **kwargs): context['partner'] = get_object_or_404( Organisation, pk=self.kwargs['org_id'] ) - if context['partner'] != context['organisation'] and \ - context['partner'] not in context['organisation'].partners(): - raise Http404 return context diff --git a/akvo/rsr/views_partner_sites/project.py b/akvo/rsr/views_partner_sites/project.py index 262540e80d..1a24da274c 100644 --- a/akvo/rsr/views_partner_sites/project.py +++ b/akvo/rsr/views_partner_sites/project.py @@ -31,7 +31,8 @@ 'ProjectUpdateEditView', 'ProjectUpdateListView', 'ProjectUpdateView', - 'ProjectDonationThanksView' + 'ProjectDonationThanksView', + 'ProjectDonationRedirectView' ] @@ -224,3 +225,12 @@ def get_context_data(self, invoice=None, **kwargs): raise Http404 context["invoice"] = invoice return context + +class ProjectDonationRedirectView(BaseProjectView): + "Show a redirect page before redirecting to the core RSR donate page" + template_name = "partner_sites/project/donate/donate_redirect.html" + + def get_context_data(self, **kwargs): + context = super(ProjectDonationRedirectView, self).get_context_data(**kwargs) + _project = get_object_or_404(Project, id=context['project'].pk) + return context \ No newline at end of file diff --git a/akvo/scripts/budget_totals.py b/akvo/scripts/budget_totals.py new file mode 100644 index 0000000000..10d7178736 --- /dev/null +++ b/akvo/scripts/budget_totals.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +#!/usr/bin/env python + +""" +Script for setting all budgets with budget item 13 to 14 and remove budget item 13 (total) from RSR. +""" + +from django.core.management import setup_environ +from akvo import settings +setup_environ(settings) + +from akvo.rsr.models import BudgetItem, BudgetItemLabel, Project + + +def set_budget_totals(): + '''Change all budget items with id 13 to 14''' + + print "\nGetting all budget items...\n" + + budget_items = BudgetItem.objects.filter(label_id="13") + budgets_count = budget_items.count() + + for count, item in enumerate(budget_items, start=1): + item.label_id = 14 + item.save() + + print "Budget item", str(item.pk), "adjusted (" + str(count), "out of", str(budgets_count) + ")..." + + +def remove_budgetitem_label(): + '''Remove budget item label 13 (total)''' + + BudgetItemLabel.objects.filter(id="13").delete() + print "\nRemoved the total budget item, label 13..." + + +def update_budgetitem_label(): + '''Update label of budget item 14''' + + total_budget_label = BudgetItemLabel.objects.get(id="14") + total_budget_label.label = 'total' + total_budget_label.save() + + print "\nUpdated label of item 14 to 'total'...\n" + + +def update_projects(): + '''Updates all projects using the budget sum calculator''' + + print "\nGetting all projects...\n" + + projects = Project.objects.all() + projects_count = projects.count() + + for count, project in enumerate(projects): + project.update_budget() + project.update_funds_needed() + + print "Updating project:", project.id, "(" + str(count), "out of", str(projects_count) + ")..." + + +if __name__ == '__main__': + set_budget_totals() + remove_budgetitem_label() + update_budgetitem_label() + update_projects() + + print "\nDone!\n" diff --git a/akvo/settings/10-base.conf b/akvo/settings/10-base.conf index d65601f5d3..4678dce875 100644 --- a/akvo/settings/10-base.conf +++ b/akvo/settings/10-base.conf @@ -70,6 +70,7 @@ MIDDLEWARE_CLASSES = ( 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.middleware.doc.XViewMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', + 'akvo.rsr.middleware.ExceptionLoggingMiddleware', ) ROOT_URLCONF = 'akvo.urls.rsr' @@ -96,88 +97,6 @@ TEMPLATE_LOADERS = ( ) # Logging -LOGGING = { - 'version': 1, - 'disable_existing_loggers': True, - 'formatters': { - 'verbose': { - 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' - }, - 'verbose_request': { - 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s %(request)s' - }, - 'simple': { - 'format': '%(levelname)s %(message)s' - }, - }, - 'filters': { - #'special': { - # '()': 'project.logging.SpecialFilter', - # 'foo': 'bar', - #}, - }, - 'handlers': { - 'null': { - 'level':'DEBUG', - 'class':'django.utils.log.NullHandler', - }, - 'console':{ - 'level':'DEBUG', - 'class':'logging.StreamHandler', - 'formatter': 'verbose', - }, - 'file':{ - 'level':'DEBUG', - 'class':'logging.handlers.RotatingFileHandler', - 'filename': os.path.join(os.path.dirname(__file__), '../log/akvo.log').replace('\\','/'), - 'maxBytes': 1024*1024, - 'backupCount': 4, - 'formatter': 'verbose', - }, - 'request_to_console':{ - 'level':'DEBUG', - 'class':'logging.StreamHandler', - 'formatter': 'verbose_request', - }, - 'request_to_file':{ - 'level':'DEBUG', - 'class':'logging.handlers.RotatingFileHandler', - 'filename': os.path.join(os.path.dirname(__file__), '../log/akvo.log').replace('\\','/'), - 'maxBytes': 1024*1024, - 'backupCount': 4, - 'formatter': 'verbose_request', - }, - #'mail_admins': { - # 'level': 'ERROR', - # 'class': 'django.utils.log.AdminEmailHandler', - # 'filters': ['special'] - #}, - }, - 'loggers': { - 'django': { - 'handlers':['null'], - 'propagate': True, - 'level':'INFO', - }, - #'django.request': { - # 'handlers': ['mail_admins'], - # 'level': 'ERROR', - # 'propagate': False, - #}, - # 'django.request': { - # 'handlers': ['request_to_file', ], #'request_to_console',], - # 'level': 'DEBUG', - # 'propagate': False, - # }, - 'akvo.rsr': { - 'handlers': ['file', ], #'console', ], - 'level': 'DEBUG', - 'propagate': False, - }, - 'cacheback': { - 'handlers': ['file'], - 'level': 'DEBUG', - 'propagate': False, - }, - }, -} +LOG_FILE_PATH = '/var/akvo/rsr/logs/' +ACCESS_LOG_FILE_NAME = 'akvo.log' +ERROR_LOG_FILE_NAME = 'akvo.error.log' diff --git a/akvo/settings/90-finish.conf b/akvo/settings/90-finish.conf index 05546e0d27..b6f78595ca 100644 --- a/akvo/settings/90-finish.conf +++ b/akvo/settings/90-finish.conf @@ -16,6 +16,9 @@ TEMPLATE_DIRS = ( ) # Logging +ACCESS_LOG_FILE_FULL_NAME = os.path.join(LOG_FILE_PATH, ACCESS_LOG_FILE_NAME).replace('\\','/') +ERROR_LOG_FILE_FULL_NAME = os.path.join(LOG_FILE_PATH, ERROR_LOG_FILE_NAME).replace('\\','/') + LOGGING = { 'version': 1, 'disable_existing_loggers': True, @@ -29,18 +32,11 @@ LOGGING = { 'simple': { 'format': '%(levelname)s %(message)s' }, - }, - 'filters': { - #'special': { - # '()': 'project.logging.SpecialFilter', - # 'foo': 'bar', - #}, + 'production_errors': { + 'format': '%(levelname)s %(asctime)s %(message)s' + }, }, 'handlers': { - 'null': { - 'level':'DEBUG', - 'class':'django.utils.log.NullHandler', - }, 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', @@ -49,50 +45,30 @@ LOGGING = { 'file':{ 'level':'DEBUG', 'class':'logging.handlers.RotatingFileHandler', - 'filename': os.path.join(LOG_FILE_PATH, 'akvo.log').replace('\\','/'), + 'filename': ACCESS_LOG_FILE_FULL_NAME, 'maxBytes': 1024*1024, 'backupCount': 4, 'formatter': 'verbose', }, - 'request_to_console':{ - 'level':'DEBUG', - 'class':'logging.StreamHandler', - 'formatter': 'verbose_request', - }, - 'request_to_file':{ + 'production_errors':{ 'level':'DEBUG', 'class':'logging.handlers.RotatingFileHandler', - 'filename': os.path.join(LOG_FILE_PATH, 'akvo.log').replace('\\','/'), + 'filename': ERROR_LOG_FILE_FULL_NAME, 'maxBytes': 1024*1024, 'backupCount': 4, - 'formatter': 'verbose_request', + 'formatter': 'production_errors', }, - #'mail_admins': { - # 'level': 'ERROR', - # 'class': 'django.utils.log.AdminEmailHandler', - # 'filters': ['special'] - #}, }, 'loggers': { - 'django': { - 'handlers':['null'], - 'propagate': True, - 'level':'INFO', + 'django.request': { + 'handlers': ['production_errors', 'console', ], + 'level': 'ERROR', + 'propagate': False, }, - #'django.request': { - # 'handlers': ['mail_admins'], - # 'level': 'ERROR', - # 'propagate': False, - #}, - # 'django.request': { - # 'handlers': ['request_to_file', ], #'request_to_console',], - # 'level': 'DEBUG', - # 'propagate': False, - # }, 'akvo.rsr': { 'handlers': ['file', ], #'console', ], 'level': 'DEBUG', 'propagate': False, }, - }, + } } diff --git a/akvo/templates/admin/rsr/project/change_form.html b/akvo/templates/admin/rsr/project/change_form.html index b153e9f245..c7d3d156f8 100644 --- a/akvo/templates/admin/rsr/project/change_form.html +++ b/akvo/templates/admin/rsr/project/change_form.html @@ -35,6 +35,22 @@

{% trans 'Adding and Editing Projects.' %}

{% endif %} {% endif %} {% endblock object-tools %} + {% if original.sync_owner %} + + {% endif %}
{% csrf_token %} {% block form_top %}{% endblock %} diff --git a/akvo/templates/inclusion_tags/google_global_organisation_map.html b/akvo/templates/inclusion_tags/google_global_organisation_map.html deleted file mode 100644 index 776bfe16cf..0000000000 --- a/akvo/templates/inclusion_tags/google_global_organisation_map.html +++ /dev/null @@ -1,112 +0,0 @@ -{% load i18n l10n templatetag_handlebars %} - -
-
- -
-
- -{% tplhandlebars "mapInfoWindowTemplate" %} -
- {{name}} - {{#if image_url}} -
- - - -
- {{/if}} -
-{% endtplhandlebars %} - - - - - - - - diff --git a/akvo/templates/inclusion_tags/google_global_organisation_map.html.old b/akvo/templates/inclusion_tags/google_global_organisation_map.html.old index fd8a06c48d..776bfe16cf 100644 --- a/akvo/templates/inclusion_tags/google_global_organisation_map.html.old +++ b/akvo/templates/inclusion_tags/google_global_organisation_map.html.old @@ -1,103 +1,112 @@ -{% load i18n thumbnail rsr_filters l10n %} -{% load url from future %} +{% load i18n l10n templatetag_handlebars %} +
+
+ +
+
- + + - - - + - function loadGlobalMap() { - var center = new google.maps.LatLng(0,0); - {% for organisation in organisations %} - var organisation_{{ organisation.id }}_url = "{{organisation.get_absolute_url}}"; - var organisation_{{ organisation.id }}_latitude = {{ organisation.primary_location.latitude|unlocalize }}; - var organisation_{{ organisation.id }}_longitude = {{ organisation.primary_location.longitude|unlocalize }}; - var organisation_{{ organisation.id }}_coordinates = new google.maps.LatLng(organisation_{{ organisation.id }}_latitude, organisation_{{ organisation.id }}_longitude); - var zoom = {{ zoom }}; - {% endfor %} + - -{% if width == 0 and height == 0 %} -
-{% else %} -
-{% endif %} diff --git a/akvo/templates/inclusion_tags/google_global_organisation_map.html.older b/akvo/templates/inclusion_tags/google_global_organisation_map.html.older new file mode 100644 index 0000000000..fd8a06c48d --- /dev/null +++ b/akvo/templates/inclusion_tags/google_global_organisation_map.html.older @@ -0,0 +1,103 @@ +{% load i18n thumbnail rsr_filters l10n %} +{% load url from future %} + + + + + + + + +{% if width == 0 and height == 0 %} +
+{% else %} +
+{% endif %} diff --git a/akvo/templates/inclusion_tags/google_global_project_map.html b/akvo/templates/inclusion_tags/google_global_project_map.html.old similarity index 100% rename from akvo/templates/inclusion_tags/google_global_project_map.html rename to akvo/templates/inclusion_tags/google_global_project_map.html.old diff --git a/akvo/templates/inclusion_tags/google_map.html b/akvo/templates/inclusion_tags/google_map.html.old similarity index 100% rename from akvo/templates/inclusion_tags/google_map.html rename to akvo/templates/inclusion_tags/google_map.html.old diff --git a/akvo/templates/inclusion_tags/map.html b/akvo/templates/inclusion_tags/map.html.old similarity index 100% rename from akvo/templates/inclusion_tags/map.html rename to akvo/templates/inclusion_tags/map.html.old diff --git a/akvo/templates/inclusion_tags/maps.html b/akvo/templates/inclusion_tags/maps.html new file mode 100644 index 0000000000..01f9909099 --- /dev/null +++ b/akvo/templates/inclusion_tags/maps.html @@ -0,0 +1,72 @@ +
+ + \ No newline at end of file diff --git a/akvo/templates/inclusion_tags/project_map.html b/akvo/templates/inclusion_tags/project_map.html.old similarity index 100% rename from akvo/templates/inclusion_tags/project_map.html rename to akvo/templates/inclusion_tags/project_map.html.old diff --git a/akvo/templates/partner_sites/base.html b/akvo/templates/partner_sites/base.html index 1f99ec87ac..5a9fbc95ae 100644 --- a/akvo/templates/partner_sites/base.html +++ b/akvo/templates/partner_sites/base.html @@ -65,7 +65,7 @@ {% if return_url %} - ◄ {% trans "Back to" %} {{organisation}} + ◄ {% trans "Back to" %} {% if return_url_text %}{{return_url_text}}{% else %}{{organisation}}{% endif %} {% endif %} @@ -77,9 +77,9 @@ diff --git a/akvo/templates/partner_sites/home.html b/akvo/templates/partner_sites/home.html index a1a9026099..dae042d797 100644 --- a/akvo/templates/partner_sites/home.html +++ b/akvo/templates/partner_sites/home.html @@ -1,5 +1,5 @@ {% extends "partner_sites/base.html" %} -{% load i18n google_maps rsr_tags webdesign thumbnail sorting_tags pagination_tags rsr_filters humanize %} +{% load i18n maps rsr_tags webdesign thumbnail sorting_tags pagination_tags rsr_filters humanize %} {% load url from future %} @@ -33,7 +33,7 @@
- {% google_organisation_projects_map request.organisation_id 'dynamic' 470 250 1 %} + {% organisation_projects_map request.organisation_id 470 250 'dynamic' %}

{% trans "Find projects" %}

@@ -168,7 +168,7 @@

{% trans "Find projects" %}

{% if project.funds_needed|round != 0 and not project.status == 'L' and not project.status == 'R' %} {% if project.donate_button %} diff --git a/akvo/templates/partner_sites/inclusion_tags/partner_sites_funding_box.html b/akvo/templates/partner_sites/inclusion_tags/partner_sites_funding_box.html index e64901b512..644bc074ba 100644 --- a/akvo/templates/partner_sites/inclusion_tags/partner_sites_funding_box.html +++ b/akvo/templates/partner_sites/inclusion_tags/partner_sites_funding_box.html @@ -40,7 +40,7 @@ {% if project.donate_button %}
- {% trans 'Donate' %} + {% trans 'Donate' %}
{% endif %} {% endif %} diff --git a/akvo/templates/partner_sites/inclusion_tags/widgets/project_donate_button.html b/akvo/templates/partner_sites/inclusion_tags/widgets/project_donate_button.html index bb89c7ebcd..93fb61e2db 100644 --- a/akvo/templates/partner_sites/inclusion_tags/widgets/project_donate_button.html +++ b/akvo/templates/partner_sites/inclusion_tags/widgets/project_donate_button.html @@ -1,5 +1,5 @@ {% load i18n rsr_filters %} {% if project.funds_needed|round != 0 and project.status != 'L' and project.status != 'R' and project.donate_button %} - {% trans "Donate" %} + {% trans "Donate" %} {% endif %} \ No newline at end of file diff --git a/akvo/templates/partner_sites/inclusion_tags/widgets/project_location.html b/akvo/templates/partner_sites/inclusion_tags/widgets/project_location.html index 7ca8bbfeed..c715c370fa 100644 --- a/akvo/templates/partner_sites/inclusion_tags/widgets/project_location.html +++ b/akvo/templates/partner_sites/inclusion_tags/widgets/project_location.html @@ -1,6 +1,7 @@ {% if project.primary_location.city %} - {{project.primary_location.city}}, + {{project.primary_location.city}}, {% endif %} +
{{project.primary_location.country}}
\ No newline at end of file diff --git a/akvo/templates/partner_sites/inclusion_tags/widgets/project_progress_bar.html b/akvo/templates/partner_sites/inclusion_tags/widgets/project_progress_bar.html index 7e783e919a..5f8f1190c9 100644 --- a/akvo/templates/partner_sites/inclusion_tags/widgets/project_progress_bar.html +++ b/akvo/templates/partner_sites/inclusion_tags/widgets/project_progress_bar.html @@ -1,5 +1,7 @@ +{% load i18n rsr_filters humanize rsr_tags %} +
- +
\ No newline at end of file diff --git a/akvo/templates/partner_sites/partners/partner_list.html b/akvo/templates/partner_sites/partners/partner_list.html index 6286c353f2..6a262e739d 100644 --- a/akvo/templates/partner_sites/partners/partner_list.html +++ b/akvo/templates/partner_sites/partners/partner_list.html @@ -1,5 +1,5 @@ {% extends "partner_sites/base.html" %} -{% load i18n rsr_tags webdesign thumbnail rsr_filters google_maps sorting_tags pagination_tags rsr_filters %} +{% load i18n rsr_tags webdesign thumbnail rsr_filters sorting_tags pagination_tags rsr_filters %} {% load url from future %} diff --git a/akvo/templates/partner_sites/partners/partner_main.html b/akvo/templates/partner_sites/partners/partner_main.html index 4fcbfb0e18..c9ca4af0f9 100644 --- a/akvo/templates/partner_sites/partners/partner_main.html +++ b/akvo/templates/partner_sites/partners/partner_main.html @@ -1,5 +1,5 @@ {% extends "partner_sites/base.html" %} -{% load i18n rsr_tags webdesign thumbnail rsr_filters project_map humanize %} +{% load i18n rsr_tags webdesign thumbnail rsr_filters maps humanize %} {% load url from future %} {% block title %}{{partner}} - {% endblock title %} @@ -72,8 +72,8 @@

{% trans 'Location' %}

{% if partner.primary_location.country %}{{partner.primary_location.country}}{% endif %}

{% if partner.primary_location %} - {% if organisation.primary_location.latitude != 0.0 or organisation.primary_location.longitude != 0.0 %} - {% project_map 1 1 organisation.pk 195 160 %} + {% if partner.primary_location.latitude != 0.0 or partner.primary_location.longitude != 0.0 %} + {% organisation_map partner.pk 195 160 %} {% else %}

{% trans 'No map available' %}

{% endif %} diff --git a/akvo/templates/partner_sites/project/donate/donate_redirect.html b/akvo/templates/partner_sites/project/donate/donate_redirect.html new file mode 100644 index 0000000000..378cb924db --- /dev/null +++ b/akvo/templates/partner_sites/project/donate/donate_redirect.html @@ -0,0 +1,39 @@ +{% extends "partner_sites/base.html" %} +{% load i18n rsr_tags thumbnail %} +{% load url from future %} + +{% block head %} + + + + + +{% endblock head %} + +{% block content %} + +

{% trans 'Donate to' %} {{project.title}}

+ +
+

+ {% trans 'You will be redirected to the Akvo donate page' %} +

+

+ {% trans 'If you are not redirected within 10 seconds,' %} {% trans 'click here' %} +

+
+ +{% endblock content %} diff --git a/akvo/templates/partner_sites/project/project_main.html b/akvo/templates/partner_sites/project/project_main.html index b3c2a09e61..a714d6d9da 100644 --- a/akvo/templates/partner_sites/project/project_main.html +++ b/akvo/templates/partner_sites/project/project_main.html @@ -1,10 +1,10 @@ {% extends "partner_sites/project/base_project.html" %} -{% load i18n rsr_tags webdesign thumbnail counter_tags humanize project_map %} +{% load i18n rsr_tags webdesign thumbnail counter_tags humanize maps %} {% load url from future %} {% block head %} - + {% if project.current_image %} @@ -105,7 +105,7 @@

{% trans 'Location' %}

{{ project.primary_location.latitude }}, {{ project.primary_location.longitude }}

- {% project_map 1 0 project.pk 260 180 %} + {% project_map project.pk 260 180 %} {% else %}

{% trans 'No map available' %}

{% endif %} diff --git a/akvo/templates/partner_sites/project/update_form.html b/akvo/templates/partner_sites/project/update_form.html index 02cf6d443a..f3a638d9d4 100644 --- a/akvo/templates/partner_sites/project/update_form.html +++ b/akvo/templates/partner_sites/project/update_form.html @@ -176,7 +176,6 @@

{% trans "Add update to project" %}

{% endif %} - {% csrf_token %}
diff --git a/akvo/templates/partner_sites/project/update_main.html b/akvo/templates/partner_sites/project/update_main.html index bafd3a6959..b66a229a2f 100644 --- a/akvo/templates/partner_sites/project/update_main.html +++ b/akvo/templates/partner_sites/project/update_main.html @@ -6,7 +6,7 @@ {% block title %}{{update.title}} - {% endblock title %} {% block head %} - + {% if update.photo %} @@ -120,14 +120,6 @@

{{update.title}}

{% endif %} - - {% if update.text_location == 'B' %} -

- {% autoescape off %} - {{ update.text|force_escape|urlize|markdown }} - {% endautoescape %} -

- {% endif %} {% if update.video %}
@@ -151,13 +143,11 @@

{{update.title}}

{% update_thumb update 580 435 %}
{% endif %} - {% if update.text_location == 'E' %} -

- {% autoescape off %} - {{ update.text|force_escape|urlize|markdown }} - {% endautoescape %} -

- {% endif %} +

+ {% autoescape off %} + {{ update.text|force_escape|urlize|markdown }} + {% endautoescape %} +


{% trans 'Permalink' %} diff --git a/akvo/templates/partner_sites/widgets/get_widget1.html b/akvo/templates/partner_sites/widgets/get_widget1.html index 6116674c15..96a8179dee 100644 --- a/akvo/templates/partner_sites/widgets/get_widget1.html +++ b/akvo/templates/partner_sites/widgets/get_widget1.html @@ -1,5 +1,5 @@ {% extends "partner_sites/base.html" %} -{% load i18n rsr_tags webdesign thumbnail rsr_filters google_maps sorting_tags pagination_tags rsr_filters %} +{% load i18n rsr_tags webdesign thumbnail rsr_filters sorting_tags pagination_tags rsr_filters %} {% load url from future %} diff --git a/akvo/templates/partner_sites/widgets/get_widget2.html b/akvo/templates/partner_sites/widgets/get_widget2.html index 0146239a80..e937cfad53 100644 --- a/akvo/templates/partner_sites/widgets/get_widget2.html +++ b/akvo/templates/partner_sites/widgets/get_widget2.html @@ -1,5 +1,5 @@ {% extends "partner_sites/base.html" %} -{% load i18n rsr_tags webdesign thumbnail rsr_filters google_maps sorting_tags pagination_tags rsr_filters %} +{% load i18n rsr_tags webdesign thumbnail rsr_filters sorting_tags pagination_tags rsr_filters %} {% load url from future %} @@ -93,8 +93,8 @@

{% trans "Size" %}

-
- +
+
diff --git a/akvo/templates/partner_sites/widgets/projects_map.html b/akvo/templates/partner_sites/widgets/projects_map.html index 06433373ba..8f0ac9da73 100644 --- a/akvo/templates/partner_sites/widgets/projects_map.html +++ b/akvo/templates/partner_sites/widgets/projects_map.html @@ -1,4 +1,4 @@ -{% load cache google_maps humanize i18n rsr_tags %} +{% load cache maps humanize i18n rsr_tags %} {% load url from future %} @@ -31,51 +31,11 @@ -
+{% partnersite_widget_project_map organisation.id width height|add:-30 state %} - - - - - - - - - -{% comment %} -{% if map_type == 'static' %} - draggable: false, - disableDefaultUI: true, -{% endif %} -{% endcomment %} diff --git a/akvo/templates/rsr/global_map.html b/akvo/templates/rsr/global_map.html.old similarity index 100% rename from akvo/templates/rsr/global_map.html rename to akvo/templates/rsr/global_map.html.old diff --git a/akvo/templates/rsr/organisation/global_organisation_map.html b/akvo/templates/rsr/organisation/global_organisation_map.html index 8aaf46e804..bc8d87308a 100644 --- a/akvo/templates/rsr/organisation/global_organisation_map.html +++ b/akvo/templates/rsr/organisation/global_organisation_map.html @@ -1,5 +1,5 @@ {% extends 'rsr/base.html' %} -{% load i18n map %} +{% load i18n maps %} {% load url from future %} @@ -25,7 +25,7 @@

{% trans 'Map of all organisations' %}

- {% map 'organisation' 975 600 'dynamic' %} + {% global_organisation_map 975 600 %} {% endblock %} diff --git a/akvo/templates/rsr/project/project_base.html b/akvo/templates/rsr/project/project_base.html index 183457093f..b11af168a5 100644 --- a/akvo/templates/rsr/project/project_base.html +++ b/akvo/templates/rsr/project/project_base.html @@ -133,12 +133,18 @@

{% trans 'Tools for this page' %}

+ {% if can_add_update %} {% trans 'Add update' %} + {% else %} + {% trans 'Add update' %} + {% endif %}

{% if not user.username %} {% trans 'Sign in to add an update to your project.' %} + {% elif not can_add_update %} + {% trans 'You are not allowed to post updates for this project.' %} {% endif %}

diff --git a/akvo/templates/rsr/project/project_main.html b/akvo/templates/rsr/project/project_main.html index 68f94613dc..04e232ea5b 100644 --- a/akvo/templates/rsr/project/project_main.html +++ b/akvo/templates/rsr/project/project_main.html @@ -1,5 +1,5 @@ {% extends "rsr/project/project_base.html" %} -{% load webdesign addparam humanize i18n rsr_filters rsr_tags thumbnail counter_tags project_map %} +{% load webdesign addparam humanize i18n rsr_filters rsr_tags thumbnail counter_tags maps %} {% load url from future %} {% block head %} @@ -59,7 +59,7 @@

{% trans 'Location' %}

{# Google Map #} {% if p.primary_location %} - {% project_map 1 0 project.pk 260 180 %} + {% project_map project.pk 260 180 %} {% else %}

{% trans 'No map available' %}

{% endif %} diff --git a/akvo/templates/rsr/project/project_update.html b/akvo/templates/rsr/project/project_update.html index c8e6edfa53..01ce290d10 100644 --- a/akvo/templates/rsr/project/project_update.html +++ b/akvo/templates/rsr/project/project_update.html @@ -63,37 +63,29 @@

{{ update.title|capfirst }}

{% counter_badge update %}
- {% if update.text_location == 'B' %} - {% autoescape off %} - {{ update.text|force_escape|urlize|markdown }} - {% endautoescape %} - {% endif %} {% if update.video %}
- {# {{ update.video|oembed:"580x435" }} #}
{{ update.get_video_oembed }}
-{% if update.video_caption or update.video_credit %} -

- {% if update.video_caption %} + {% if update.video_caption or update.video_credit %} +

+ {% if update.video_caption %} {{ update.video_caption }} {% endif %} {% if update.video_credit %} {% trans 'Video credit' %}: {{ update.video_credit }} {% endif %}

- {% endif %} + {% endif %} {% endif %} {% if update.photo %} {% update_thumb update 580 435 %} {% endif %} - {% if update.text_location == 'E' %} - {% autoescape off %} - {{ update.text|force_escape|urlize|markdown }} - {% endautoescape %} - {% endif %} + {% autoescape off %} + {{ update.text|force_escape|urlize|markdown }} + {% endautoescape %}
{% trans 'Permalink' %} diff --git a/akvo/templates/rsr/project/update_form.html b/akvo/templates/rsr/project/update_form.html index d2bf0cb1ad..bffa924b54 100644 --- a/akvo/templates/rsr/project/update_form.html +++ b/akvo/templates/rsr/project/update_form.html @@ -186,33 +186,6 @@

{% trans 'Video credit' %} ({% trans 'optional' %})

25 {% trans 'characters' %}

-
-
-
-
-

Text placement

-

If you added a photo and/or video...

- {# form.photo_location #} -
    -
  1. - - -
  2. -
  3. - - -
  4. -
-
-



diff --git a/akvo/templates/widgets/organisation_map_long.html b/akvo/templates/widgets/organisation_map_long.html deleted file mode 100644 index 7e165c3270..0000000000 --- a/akvo/templates/widgets/organisation_map_long.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends 'widgets/base_widget.html' %} -{% load google_maps i18n %} - - -
- {{ google_organisation_project_map project.organisation 400 400 3 }} -
diff --git a/akvo/templates/widgets/project_map.html b/akvo/templates/widgets/project_map.html index 5d62d2f966..d6950ff0d6 100644 --- a/akvo/templates/widgets/project_map.html +++ b/akvo/templates/widgets/project_map.html @@ -1,4 +1,4 @@ -{% load google_maps humanize i18n rsr_tags piwik_tags %} +{% load maps humanize i18n rsr_tags piwik_tags %} @@ -27,7 +27,7 @@ -{% google_organisation_projects_map org.id state width height zoom %} +{% organisation_projects_map org.id width height state %}