Skip to content

Commit

Permalink
[#1770] Add partnership import, and introduce utils
Browse files Browse the repository at this point in the history
  • Loading branch information
KasperBrandt committed Sep 8, 2015
1 parent c0bc3ad commit dcbc2a1
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 64 deletions.
2 changes: 2 additions & 0 deletions akvo/iati/imports/fields/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .descriptions import (background, current_status, goals_overview, project_plan,
project_plan_summary, sustainability, target_group)
from .image import current_image
from .partnerships import partnerships
from .status import status
from .titles import title, subtitle

Expand All @@ -27,6 +28,7 @@
'goals_overview',
'hierarchy',
'language',
'partnerships',
'planned_end_date',
'planned_start_date',
'project_plan',
Expand Down
10 changes: 6 additions & 4 deletions akvo/iati/imports/fields/dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
# 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 >.

from ..utils import get_text

from datetime import datetime


Expand All @@ -27,7 +29,7 @@ def planned_start_date(activity, project, activities_globals):
if 'iso-date' in psd_element.attrib.keys():
psd_date = psd_element.attrib['iso-date']
else:
psd_date = psd_element.text
psd_date = get_text(psd_element, activities_globals['version'])

if psd_date and (not project.date_start_planned or
project.date_start_planned.isoformat() != psd_date):
Expand Down Expand Up @@ -58,7 +60,7 @@ def actual_start_date(activity, project, activities_globals):
if 'iso-date' in asd_element.attrib.keys():
asd_date = asd_element.attrib['iso-date']
else:
asd_date = asd_element.text
asd_date = get_text(asd_element, activities_globals['version'])

if asd_date and (not project.date_start_actual or
project.date_start_actual.isoformat() != asd_date):
Expand Down Expand Up @@ -89,7 +91,7 @@ def planned_end_date(activity, project, activities_globals):
if 'iso-date' in ped_element.attrib.keys():
ped_date = ped_element.attrib['iso-date']
else:
ped_date = ped_element.text
ped_date = get_text(ped_element, activities_globals['version'])

if ped_date and (not project.date_end_planned or
project.date_end_planned.isoformat() != ped_date):
Expand Down Expand Up @@ -120,7 +122,7 @@ def actual_end_date(activity, project, activities_globals):
if 'iso-date' in aed_element.attrib.keys():
aed_date = aed_element.attrib['iso-date']
else:
aed_date = aed_element.text
aed_date = get_text(aed_element, activities_globals['version'])

if aed_date and (not project.date_end_actual or
project.date_end_actual.isoformat() != aed_date):
Expand Down
51 changes: 9 additions & 42 deletions akvo/iati/imports/fields/descriptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
# 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 >.

from ..utils import get_text

from django.conf import settings


Expand All @@ -27,12 +29,7 @@ def project_plan_summary(activity, project, activities_globals):
pps_element = descriptions_type_1[1]

if not pps_element is None:
if activities_globals['version'][0] == '1':
pps_text = pps_element.text
else:
narrative_element = pps_element.find('narrative')
if narrative_element is not None:
pps_text = narrative_element.text
pps_text = get_text(pps_element, activities_globals['version'])

if pps_text is not None and project.project_plan_summary != pps_text[:400]:
project.project_plan_summary = pps_text[:400]
Expand Down Expand Up @@ -60,12 +57,7 @@ def goals_overview(activity, project, activities_globals):
go_element = activity.find("description[@type='2']")

if not go_element is None:
if activities_globals['version'][0] == '1':
go_text = go_element.text
else:
narrative_element = go_element.find('narrative')
if narrative_element is not None:
go_text = narrative_element.text
go_text = get_text(go_element, activities_globals['version'])

if go_text is not None and project.goals_overview != go_text[:600]:
project.goals_overview = go_text[:600]
Expand Down Expand Up @@ -95,12 +87,7 @@ def background(activity, project, activities_globals):
background_element = descriptions_type_1[2]

if not background_element is None:
if activities_globals['version'][0] == '1':
background_text = background_element.text
else:
narrative_element = background_element.find('narrative')
if narrative_element is not None:
background_text = narrative_element.text
background_text = get_text(background_element, activities_globals['version'])

if background_text is not None and project.background != background_text[:1000]:
project.background = background_text[:1000]
Expand Down Expand Up @@ -130,12 +117,7 @@ def current_status(activity, project, activities_globals):
current_status_element = descriptions_type_1[3]

if not current_status_element is None:
if activities_globals['version'][0] == '1':
current_status_text = current_status_element.text
else:
narrative_element = current_status_element.find('narrative')
if narrative_element is not None:
current_status_text = narrative_element.text
current_status_text = get_text(current_status_element, activities_globals['version'])

if current_status_text is not None and project.current_status != current_status_text[:600]:
project.current_status = current_status_text[:600]
Expand Down Expand Up @@ -163,12 +145,7 @@ def target_group(activity, project, activities_globals):
target_group_element = activity.find("description[@type='3']")

if not target_group_element is None:
if activities_globals['version'][0] == '1':
target_group_text = target_group_element.text
else:
narrative_element = target_group_element.find('narrative')
if narrative_element is not None:
target_group_text = narrative_element.text
target_group_text = get_text(target_group_element, activities_globals['version'])

if target_group_text is not None and project.target_group != target_group_text[:600]:
project.target_group = target_group_text[:600]
Expand Down Expand Up @@ -198,12 +175,7 @@ def project_plan(activity, project, activities_globals):
project_plan_element = descriptions_type_1[4]

if not project_plan_element is None:
if activities_globals['version'][0] == '1':
project_plan_text = project_plan_element.text
else:
narrative_element = project_plan_element.find('narrative')
if narrative_element is not None:
project_plan_text = narrative_element.text
project_plan_text = get_text(project_plan_element, activities_globals['version'])

if project_plan_text is not None and project.project_plan != project_plan_text:
project.project_plan = project_plan_text
Expand Down Expand Up @@ -233,12 +205,7 @@ def sustainability(activity, project, activities_globals):
sustainability_element = descriptions_type_1[5]

if not sustainability_element is None:
if activities_globals['version'][0] == '1':
sustainability_text = sustainability_element.text
else:
narrative_element = sustainability_element.find('narrative')
if narrative_element is not None:
sustainability_text = narrative_element.text
sustainability_text = get_text(sustainability_element, activities_globals['version'])

if sustainability_text is not None and project.sustainability != sustainability_text:
project.sustainability = sustainability_text
Expand Down
9 changes: 3 additions & 6 deletions akvo/iati/imports/fields/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
# 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 >.

from ..utils import get_text

from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.files import File
Expand Down Expand Up @@ -59,12 +61,7 @@ def current_image(activity, project, activities_globals):
image_caption = None
title_element = document_link_element.find('title')
if title_element is not None:
if activities_globals['version'][0] == '1':
image_caption = title_element.text
else:
narrative_element = title_element.find('narrative')
if narrative_element is not None:
image_caption = narrative_element.text
image_caption = get_text(title_element, activities_globals['version'])

if image_caption is not None and \
project.current_image_caption != image_caption[:50]:
Expand Down
53 changes: 53 additions & 0 deletions akvo/iati/imports/fields/partnerships.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# -*- 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 >.

from ..utils import get_or_create_organisation, get_text

from django.db.models import get_model

ROLE_TO_CODE = {
'accountable': '2',
'extending': '3',
'funding': '1',
'implementing': '4'
}


def partnerships(activity, project, activities_globals):
"""
Retrieve and store the partnerships.
The partnerships will be extracted from the 'participating-org' elements.
:param activity: ElementTree; contains all data for the activity
:param project: Project instance
:param activities_globals: Dictionary; contains all global activities information
:return: List; contains fields that have changed
"""
imported_partnerships = []
changes = []

for partnership in activity.findall('participating-org'):
org_ref = partnership.attrib['ref'] if 'ref' in partnership.attrib.keys() else ''
org_name = get_text(partnership, activities_globals['version'])
partner = get_or_create_organisation(org_ref, org_name)
partner_role = partnership.attrib['role'] if 'role' in partnership.attrib.keys() else None
if activities_globals['version'][0] == '1':
partner_role = ROLE_TO_CODE[partner_role.lower()]
ps, created = get_model('rsr', 'partnership').objects.get_or_create(
project=project,
organisation=partner,
iati_organisation_role=int(partner_role) if partner_role else None
)
imported_partnerships.append(ps)
if created:
changes.append(ps)

for partnership in project.partnerships.all():
if not partnership in imported_partnerships:
changes.append(u'deleted %s' % partnership.__unicode__())
partnership.delete()

return changes
16 changes: 4 additions & 12 deletions akvo/iati/imports/fields/titles.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
# 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 >.

from ..utils import get_text

from django.conf import settings


Expand All @@ -21,12 +23,7 @@ def title(activity, project, activities_globals):
title_element = activity.find('title')

if title_element is not None:
if activities_globals['version'][0] == '1':
title_text = title_element.text
else:
narrative_element = title_element.find('narrative')
if narrative_element is not None:
title_text = narrative_element.text
title_text = get_text(title_element, activities_globals['version'])

if title_text is not None and project.title != title_text[:45]:
project.title = title_text[:45]
Expand Down Expand Up @@ -54,12 +51,7 @@ def subtitle(activity, project, activities_globals):
subtitle_element = activity.find("description[@type='1']")

if not subtitle_element is None:
if activities_globals['version'][0] == '1':
subtitle_text = subtitle_element.text
else:
narrative_element = subtitle_element.find('narrative')
if narrative_element is not None:
subtitle_text = narrative_element.text
subtitle_text = get_text(subtitle_element, activities_globals['version'])

if subtitle_text is not None and project.subtitle != subtitle_text[:75]:
project.subtitle = subtitle_text[:75]
Expand Down
1 change: 1 addition & 0 deletions akvo/iati/imports/iati_import_activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
'default_finance_type',
'default_flow_type',
'default_tied_status',
'partnerships',
]


Expand Down
60 changes: 60 additions & 0 deletions akvo/iati/imports/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# -*- 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 >.

from django.core.exceptions import ObjectDoesNotExist
from django.db.models import get_model


def get_text(element, version):
"""
Returns the text of an element. Based on the IATI version, this is the direct text of the
element (v1) or the the text in the underlying 'narrative' element (v2).
:param element: ElementTree node
:param version: String; the full IATI version, e.g. '1.03' or '2.01'
:return: String; text of the element or an empty string in case there is no text
"""
if version[0] == '1':
return element.text
else:
narrative_element = element.find('narrative')
if narrative_element is not None:
return narrative_element.text
return ''


def get_or_create_organisation(ref, name):
"""
Looks for an organisation in the RSR database.
First the ref will be looked up in the Organisation.iati_org_id field. If this does not exist,
the name will be looked up in the Organisation.name and Organisation.long_name fields.
If none of these return a match, a new organisation will be created.
:param ref: String; the reference of the organisation that is specified in the IATI file.
:param name: String; the name of the organisation that is specified in the IATI file.
:return: Organisation instance
"""
if ref:
try:
return get_model('rsr', 'organisation').objects.get(iati_org_id=ref)
except ObjectDoesNotExist:
pass

if name:
try:
return get_model('rsr', 'organisation').objects.get(name=name[:25])
except ObjectDoesNotExist:
try:
return get_model('rsr', 'organisation').objects.get(long_name=name[:75])
except ObjectDoesNotExist:
pass

return get_model('rsr', 'organisation').objects.create(
name=name[:25],
long_name=name[:75],
iati_org_id=ref,
organisation_type='N'
)

0 comments on commit dcbc2a1

Please sign in to comment.