Skip to content

Commit

Permalink
Merge pull request #1865 from akvo/#1826_reporting_org
Browse files Browse the repository at this point in the history
[#1826] Reporting organisation and keywords
  • Loading branch information
KasperBrandt committed Oct 25, 2015
2 parents d9b0704 + 3ddb58a commit 48ce7d4
Show file tree
Hide file tree
Showing 51 changed files with 650 additions and 365 deletions.
5 changes: 4 additions & 1 deletion akvo/api/resources/partnership.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,12 @@ def hydrate(self, bundle):
organisation = get_organisation(bundle)
if organisation:
bundle.data[FIELD_ORGANISATION] = organisation
# note that checking against the Partnership.IATI_ACCOUNTABLE_PARTNER only sorta right,
# it should be the reporting org, but since we know there's only one accountable,
# Cordaid, it's OK
if (
organisation.iati_org_id != bundle.data[FIELD_REPORTING_ORG] or
bundle.data[FIELD_PARTNER_TYPE] != Partnership.IATI_ACCOUNTABLE_PARTNER
bundle.data[FIELD_PARTNER_TYPE] != str(Partnership.IATI_ACCOUNTABLE_PARTNER)
):
bundle.data[FIELD_IATI_ACTIVITY_ID] = None
bundle.data[FIELD_INTERNAL_ID] = None
Expand Down
8 changes: 0 additions & 8 deletions akvo/api/resources/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,6 @@ class IATIProjectResource(ModelResource):
'recipient_regions', full=True, related_name='project'
)

# This field makes the Cordaid import dismally slow, and isn't used for anything else,
# so rather than trying to fix it by re-writing the OrganisationResource, we set the sync_owner
# to Cordaid in the post_import.py script
# This commented code remains as a reminder NOT to add the field as currently defined ;-)
# sync_owner = fields.ToOneField(
# 'akvo.api.resources.OrganisationResource',
# 'sync_owner', full=True, related_name='project'
# )

class Meta:
max_limit = 10
Expand Down
4 changes: 2 additions & 2 deletions akvo/iati/checks/versions/v201.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ def reporting_org(self):
"""
checks = []

if self.project.sync_owner:
if self.project.reporting_org:
checks.append((u'success', u'has reporting organisation'))
if self.project.sync_owner.iati_org_id:
if self.project.reporting_org.iati_org_id:
checks.append((u'success', u'reporting organisation has IATI identifier'))
else:
self.all_checks_passed = False
Expand Down
2 changes: 1 addition & 1 deletion akvo/iati/exports/elements/other_identifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def other_identifier(project):
if partnership.internal_id:
element = etree.Element("other-identifier")
element.attrib['ref'] = str(partnership.internal_id)
element.attrib['type'] = 'A1' if org == project.sync_owner else 'B9'
element.attrib['type'] = 'A1' if org == project.reporting_organisation else 'B9'

owner_org_element = etree.SubElement(element, "owner-org")

Expand Down
8 changes: 5 additions & 3 deletions akvo/iati/exports/elements/reporting_org.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ def reporting_org(project):
:param project: Project object
:return: A list of Etree elements
"""
org = project.sync_owner
org = project.reporting_org
if org:
element = etree.Element("reporting-org")

if org.iati_org_id:
element.attrib['ref'] = org.iati_org_id

if project.sync_owner_secondary_reporter is not None:
element.attrib['secondary-reporter'] = '1' if project.sync_owner_secondary_reporter else '0'
if project.reporting_partner.is_secondary_reporter:
element.attrib['secondary-reporter'] = '1'
else:
element.attrib['secondary-reporter'] = '0'

if org.new_organisation_type:
element.attrib['type'] = str(org.new_organisation_type)
Expand Down
6 changes: 3 additions & 3 deletions akvo/iati/imports/fields/dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def actual_start_date(iati_import, activity, project, activities_globals):
try:
asd_date = datetime.strptime(asd_date_text, '%Y-%m-%d').date()
except ValueError as e:
add_log(iati_import, 'planned_start_date', str(e), project)
add_log(iati_import, 'actual_start_date', str(e), project)

if project.date_start_actual != asd_date:
project.date_start_actual = asd_date
Expand Down Expand Up @@ -113,7 +113,7 @@ def planned_end_date(iati_import, activity, project, activities_globals):
try:
ped_date = datetime.strptime(ped_date_text, '%Y-%m-%d').date()
except ValueError as e:
add_log(iati_import, 'planned_start_date', str(e), project)
add_log(iati_import, 'planned_end_date', str(e), project)

if project.date_end_planned != ped_date:
project.date_end_planned = ped_date
Expand Down Expand Up @@ -151,7 +151,7 @@ def actual_end_date(iati_import, activity, project, activities_globals):
try:
aed_date = datetime.strptime(aed_date_text, '%Y-%m-%d').date()
except ValueError as e:
add_log(iati_import, 'planned_start_date', str(e), project)
add_log(iati_import, 'actual_end_date', str(e), project)

if project.date_end_actual != aed_date:
project.date_end_actual = aed_date
Expand Down
3 changes: 2 additions & 1 deletion akvo/iati/imports/fields/partnerships.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ def partnerships(iati_import, activity, project, activities_globals):
imported_partnerships.append(ps)

for partnership in project.partnerships.all():
if not partnership in imported_partnerships:
if not partnership in imported_partnerships and \
not partnership.iati_organisation_role == partnership.IATI_REPORTING_ORGANISATION:
changes.append(u'deleted partnership (id: %s): %s' %
(str(partnership.pk),
partnership.__unicode__()))
Expand Down
42 changes: 20 additions & 22 deletions akvo/iati/imports/iati_import_activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,8 @@ def log_changes(self):
change_message=message
)

def set_sync_owner(self):
"""
Check if the project can be edited by the current reporting organisation and set
the sync_owner.
:return: Boolean; True if all checks are passed and False otherwise
"""
sync_owner = self.project.sync_owner
def set_reporting_org(self):
reporting_org = self.project.reporting_org
reporting_org_element = self.activity.find('reporting-org')

if not reporting_org_element is None and 'ref' in reporting_org_element.attrib.keys():
Expand All @@ -147,37 +141,40 @@ def set_sync_owner(self):
organisation = get_model('rsr', 'organisation').objects.get(iati_org_id=iati_org_id)
except ObjectDoesNotExist:
add_log(self.iati_import, 'reporting_org',
'Reporting organisation not present in RSR', self.project,
'Reporting organisation not present in RSR.', self.project,
IatiImportLog.CRITICAL_ERROR)
return False

if not organisation.can_become_reporting:
if not organisation.can_create_projects:
add_log(self.iati_import, 'reporting_org',
'Reporting organisation not allowed to import projects in RSR',
'Reporting organisation not allowed to import projects in RSR.',
self.project, IatiImportLog.CRITICAL_ERROR)
return False

if not self.created and sync_owner and sync_owner != organisation:
add_log(self.iati_import, 'sync_owner',
'Project has a different sync_owner (%s)' % sync_owner.name,
if not self.created and reporting_org and reporting_org != organisation:
add_log(self.iati_import, 'reporting_org',
'Project has a different reporting-org already (%s).' % reporting_org.name,
self.project, IatiImportLog.CRITICAL_ERROR)
return False

self.project.set_reporting_org(organisation)

if 'secondary-reporter' in reporting_org_element.attrib.keys():
if reporting_org_element.attrib['secondary-reporter'] == '1':
self.project.sync_owner_secondary_reporter = True
self.project.reporting_partner.is_secondary_reporter = True
self.project.reporting_partner.save()
elif reporting_org_element.attrib['secondary-reporter'] == '0':
self.project.sync_owner_secondary_reporter = False
self.project.reporting_partner.is_secondary_reporter = False
self.project.reporting_partner.save()

self.project.sync_owner = organisation
self.project.save(update_fields=['sync_owner', 'sync_owner_secondary_reporter'])
return True

add_log(self.iati_import, 'reporting_org',
'Reporting organisation not correctly specified', self.project,
'Reporting organisation not correctly specified.', self.project,
IatiImportLog.CRITICAL_ERROR)
return False


def get_or_create_project(self):
"""
Get an existing project or create a new project if no existing project can be found
Expand Down Expand Up @@ -237,12 +234,13 @@ def __init__(self, iati_import, activity, user, activities_globals):
# Start import process
self.set_status(IatiProjectImport.IN_PROGRESS_STATUS)
self.set_start_date()
if self.set_sync_owner():
if self.set_reporting_org():
for field in FIELDS:
try:
with transaction.atomic():
changes = getattr(fields, field)(self.iati_import, self.activity,
self.project, self.globals)
changes = getattr(fields, field)(
self.iati_import, self.activity, self.project, self.globals
)
except Exception as e:
changes = []
add_log(self.iati_import, field, str(e), self.project,
Expand Down
1 change: 0 additions & 1 deletion akvo/rest/rsr_api_upload/json/project_1.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
"date_complete": "2014-06-30",
"primary_location": null,
"donate_button": true,
"sync_owner": null,
"categories": [1],
"partners": []
},
Expand Down
2 changes: 2 additions & 0 deletions akvo/rest/serializers/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class ProjectSerializer(BaseRSRSerializer):

publishing_status = serializers.Field(source='publishingstatus.status')
current_image = Base64ImageField(required=False, allow_empty_file=True)
sync_owner = serializers.Field(source='reporting_org.id')
sync_owner_secondary_reporter = serializers.Field(source='reporting_partner.is_secondary_reporter')

class Meta:
model = Project
Expand Down
3 changes: 0 additions & 3 deletions akvo/rest/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,6 @@
url(r'typeaheads/organisations$',
views.typeahead_organisation,
name='organisation_typeahead'),
url(r'typeaheads/reporting_organisations$',
views.typeahead_reporting_organisation,
name='reporting_organisation_typeahead'),
url(r'typeaheads/projects$',
views.typeahead_project,
name='project_typeahead'),
Expand Down
2 changes: 0 additions & 2 deletions akvo/rest/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
from .transaction import TransactionViewSet, TransactionSectorViewSet
from .typeahead import (typeahead_country,
typeahead_organisation,
typeahead_reporting_organisation,
typeahead_project,
typeahead_projectupdate)
from .user import (UserViewSet, change_password, update_details,
Expand Down Expand Up @@ -144,7 +143,6 @@
'TransactionSectorViewSet',
'typeahead_country',
'typeahead_organisation',
'typeahead_reporting_organisation',
'typeahead_project',
'typeahead_projectupdate',
'update_details',
Expand Down
13 changes: 12 additions & 1 deletion akvo/rest/views/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ class ProjectViewSet(BaseRSRViewSet):
'date_end_actual': ['exact', 'gt', 'gte', 'lt', 'lte', ],
'created_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],
'last_modified_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],
'sync_owner': ['exact', ],
'iati_activity_id': ['exact', 'icontains', ],
'hierarchy': ['exact', ],
'project_scope': ['exact', ],
Expand All @@ -84,6 +83,18 @@ class ProjectViewSet(BaseRSRViewSet):
'publishingstatus__status': ['exact', ],
}

def get_queryset(self):
"""
Allow custom filter for sync_owner, since this field has been replaced by the
reporting org partnership.
"""
queryset = self.queryset
sync_owner = self.request.QUERY_PARAMS.get('sync_owner', None)
if sync_owner:
queryset = queryset.filter(partnerships__iati_organisation_role=101,
partnerships__organisation__pk=sync_owner)
return queryset


class ProjectExtraViewSet(ProjectViewSet):

Expand Down
12 changes: 0 additions & 12 deletions akvo/rest/views/project_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,6 @@

## Section 3 ##

SECTION_THREE_FIELDS = (
('sync_owner', 'value-reportingOrganisation', 'related-object'),
('sync_owner_secondary_reporter', 'secondaryReporter', 'boolean'),
)

PARTNER_FIELDS = (
('organisation', 'value-partner-', 'related-object'),
('iati_organisation_role', 'partner-role-', 'integer'),
Expand Down Expand Up @@ -761,13 +756,6 @@ def project_editor_step3(request, pk=None):
changes = []
rel_objects = []

# Project fields
for field in SECTION_THREE_FIELDS:
if field[0] == 'sync_owner':
errors, changes = process_field(project, data, field, errors, changes, '', Organisation)
else:
errors, changes = process_field(project, data, field, errors, changes)

# Related objects
for key in data.keys():

Expand Down
4 changes: 0 additions & 4 deletions akvo/rest/views/project_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,8 @@ class ProjectUpdateViewSet(BaseRSRViewSet):
'user': ['exact', ],
'uuid': ['exact', 'icontains', ],
'period_update': ['exact', 'gt', 'gte', 'lt', 'lte', ],
# These filters only accept a date, not a datetime
# 'created_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],
# 'last_modified_at': ['exact', 'gt', 'gte', 'lt', 'lte', ],
}

# filter_fields = ('project', 'user', )
paginate_by_param = 'limit'
max_paginate_by = 1000

Expand Down
30 changes: 0 additions & 30 deletions akvo/rest/views/typeahead.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,6 @@ def typeahead_organisation(request):
many=True))
)

@api_view(['GET'])
def typeahead_reporting_organisation(request):
organisations = Organisation.objects.filter(can_become_reporting=True)
return Response(
rejig(organisations, TypeaheadOrganisationSerializer(organisations,
many=True))
)

@api_view(['GET'])
def typeahead_project(request):
projects = Project.objects.all().exclude(title='')
Expand All @@ -63,25 +55,3 @@ def typeahead_projectupdate(request):
return Response(
rejig(updates, TypeaheadProjectUpdateSerializer(updates, many=True))
)


# @api_view(['GET'])
# def typeahead_sector(request):
# """
# """

# sectors = Sector.objects.all()

# return Response(
# rejig(sectors, TypeaheadSectorSerializer(sectors, many=True))
# )


# @api_view(['GET'])
# def typeahead_sector(request):
# """
# """
# sectors = SectorCategory.objects.all()
# return Response(
# rejig(sectors, TypeaheadSectorSerializer(sectors, many=True))
# )
22 changes: 11 additions & 11 deletions akvo/rsr/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class OrganisationAdmin(TimestampsAdminDisplayMixin, ObjectPermissionsModelAdmin
fieldsets = (
(_(u'General information'), {'fields': (
'name', 'long_name', 'organisation_type', 'new_organisation_type',
'can_become_reporting', 'logo', 'url', 'facebook', 'twitter', 'linkedin', 'iati_org_id',
'can_create_projects', 'logo', 'url', 'facebook', 'twitter', 'linkedin', 'iati_org_id',
'public_iati_file', 'language', 'content_owner', 'allow_edit',)}),
(_(u'Contact information'),
{'fields': ('phone', 'mobile', 'fax', 'contact_person', 'contact_email', ), }),
Expand All @@ -125,7 +125,7 @@ def get_readonly_fields(self, request, obj=None):
if request.user.is_superuser:
return ['created_at', 'last_modified_at']
else:
return ['created_at', 'last_modified_at', 'can_become_reporting']
return ['created_at', 'last_modified_at', 'can_create_projects']

def get_queryset(self, request):
if request.user.is_admin or request.user.is_superuser:
Expand Down Expand Up @@ -598,15 +598,15 @@ class ProjectAdmin(TimestampsAdminDisplayMixin, ObjectPermissionsModelAdmin, Nes
),
'fields': (),
}),
(_(u'Reporting Organisation'), {
'description': u'<p style="margin-left:0; padding-left:0; margin-top:1em; width:75%%;">%s</p>' % _(
u'Indicate the reporting organisation of this project. This organisation must be existing '
u'already in Akvo RSR. If the organisation does not exist in the system, please send the details of '
u'the organisation including Name, Address, Logo, Contact Person and Website to '
u'<a href="mailto:support@akvo.org" target="_blank">support@akvo.org</a>.'
),
'fields': ('sync_owner', 'sync_owner_secondary_reporter'),
}),
# (_(u'Reporting Organisation'), {
# 'description': u'<p style="margin-left:0; padding-left:0; margin-top:1em; width:75%%;">%s</p>' % _(
# u'Indicate the reporting organisation of this project. This organisation must be existing '
# u'already in Akvo RSR. If the organisation does not exist in the system, please send the details of '
# u'the organisation including Name, Address, Logo, Contact Person and Website to '
# u'<a href="mailto:support@akvo.org" target="_blank">support@akvo.org</a>.'
# ),
# 'fields': ('sync_owner', 'sync_owner_secondary_reporter'),
# }),
(_(u'Project Partners'), {
'description': u'<p style="margin-left:0; padding-left:0; margin-top:1em; width:75%%;">%s</p>' % _(
u'Add each of the partners you are working with on your project. These organisations must be existing '
Expand Down
2 changes: 1 addition & 1 deletion akvo/rsr/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ class Meta:
def __init__(self, org=None, *args, **kwargs):
super(IatiExportForm, self).__init__(*args, **kwargs)
if org:
self.fields['projects'].queryset = org.reporting_projects.all()
self.fields['projects'].queryset = org.reporting_on_projects()

def save(self, reporting_organisation=None, user=None):
if reporting_organisation and user:
Expand Down
Loading

0 comments on commit 48ce7d4

Please sign in to comment.