Skip to content

Commit

Permalink
Merge pull request #1775 from akvo/develop
Browse files Browse the repository at this point in the history
Merge develop into RC
  • Loading branch information
KasperBrandt committed Aug 26, 2015
2 parents de55d79 + ca02838 commit 671800c
Show file tree
Hide file tree
Showing 64 changed files with 1,392 additions and 736 deletions.
96 changes: 96 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,102 @@ Check out [Introducing Akvo Really Simple Reporting](http://akvo.org/products/rs
Read more about [Akvo Products](http://akvo.org/products/).

________
Akvo RSR version 3.6 Jakarta
---

Wednesday 26th of August 2015, kasperbrandt

New & Noteworthy
--
### Introducing the project editor
From the My Projects section in MyRSR, it is now possible to edit your projects in a completely new editor!

Github issues: [#1525](https://github.com/akvo/akvo-rsr/issues/1525), [#1744](https://github.com/akvo/akvo-rsr/issues/1744), [#1750](https://github.com/akvo/akvo-rsr/issues/1750), [#1759](https://github.com/akvo/akvo-rsr/issues/1759) and [#1762](https://github.com/akvo/akvo-rsr/issues/1762).

### Custom fields
It is now possible to add custom text fields or checkboxes in the project editor. These can be set in the 'old' organisation admin. When an organisation admin of that organisation then creates a project, these custom fields will be automatically added to the new project.

Github issue: [#1738](https://github.com/akvo/akvo-rsr/issues/1738).

### IATI organisation roles
We have switched from the RSR specific parter types to the IATI organisation roles. This means that the following switch has been made:

- Support partner: renamed to Accountable partner
- Field partner: renamed to Implementing partner
- Funding partner: remains Funding partner
- Extending partner: added
- Sponsor partner: removed

For current Sponsor partners, we have made sure no information is lost. Every Sponsor partner now has its own keyword, which is linked to the projects the partner used to be linked to. So it is possible to create Akvo Pages based on the keyword of a former Sponsor partner.

In addition, the RSR specific partner types are still available in the API through a backwards compatible mapping.

Github issue: [#1633](https://github.com/akvo/akvo-rsr/issues/1633).

### Updated calculation of total budget
In the calculation of the total budget, we now take into account the original and revised budgets.

Github issues: [#1505](https://github.com/akvo/akvo-rsr/issues/1505) and [#1733](https://github.com/akvo/akvo-rsr/issues/1733).

### IATI funding streams
In RSR v2, we showed the IATI activity IDs of the funding partners. This information has now been re-added on the project finance page.

Github issue: [#1659](https://github.com/akvo/akvo-rsr/issues/1659).

### Organisation page layout
The layout of the organisation page has been slightly updated. It now displays the long name as well as the short name of an organisation. In addition, the logo of the organisation is centralised and a default 'Partner logo is missing'-logo is added when no organisation logo is present.

Github issue: [#1509](https://github.com/akvo/akvo-rsr/issues/1509).

### Project dates on the project page
The (planned) start and end dates of a project have now been added to the right panel on the project main page.

Github issue: [#1514](https://github.com/akvo/akvo-rsr/issues/1514).

### Sorting of indicators
In the results section on the project main page, the indicators are now sorted by their starting date.

Github issue: [#1532](https://github.com/akvo/akvo-rsr/issues/1532).

### Filter on organisation in project_update API
It is now possible to filter on organisations in the project_update resource of the /rest/v1/ API. This can either be done by looking for all updates of an organisation's projects (project\_\_partners) or all updates of an organisation's users (user\_\_organisations).

Github issue: [#1758](https://github.com/akvo/akvo-rsr/issues/1758).

Bug fixes
--
### Search for users on the User Management page
When searching for users in the User Management page, the search would be lost when switching pages. This has now been resolved.

Github issue: [#1560](https://github.com/akvo/akvo-rsr/issues/1560).

### Disabled 'Update' button in My Project
For non-published projects, we have disabled the 'update' button. Users were getting a 'Forbidden' error before when trying to place an update to a non-published project.

Github issue: [#1571](https://github.com/akvo/akvo-rsr/issues/1571).

### IATI checks for planned disbursements
We have fixed a bug in the IATI checks for planned disbursements, which made the IATI checks crash whenever a project had a planned disbursement indicated.

Github issue: [#1749](https://github.com/akvo/akvo-rsr/issues/1749).

### Filters in API declared twice
For some resources, the filters in the API were declared twice, causing random behaviour in the output of the API. In the RSR Up app, this caused a bug where not all updates were retrieved. This has now been resolved.

Github issue: [#1766](https://github.com/akvo/akvo-rsr/issues/1766).

Under the hood
--
### Added correct meta descriptions
We have added meta descriptions for every page, so that RSR pages will have a correct description when showing up in Google search results.

Github issue: [#1713](https://github.com/akvo/akvo-rsr/issues/1713).

### Monitoring of published projects
We have seen some projects that get published, even though this is not logged. In order to keep track of the projects that get published better, we will be informed when this happens.

Github issue: [#1740](https://github.com/akvo/akvo-rsr/issues/1740).

Akvo RSR version 3.5.1 Islamabad (Minor release)
---

Expand Down
52 changes: 43 additions & 9 deletions akvo/api/resources/partnership.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
FIELD_NAME = 'name'
FIELD_LONG_NAME = 'long_name'
FIELD_NEW_ORGANISATION_TYPE = 'new_organisation_type'
FIELD_PARTNER_TYPE = 'partner_type'
FIELD_PARTNER_TYPE = 'iati_organisation_role'
ORG_FIELDS = [FIELD_IATI_ORG_ID, FIELD_NAME, FIELD_LONG_NAME, FIELD_NEW_ORGANISATION_TYPE]
# InternalOrganisationID
FIELD_INTERNAL_ORG_ID = 'internal_org_id'
Expand Down Expand Up @@ -173,7 +173,7 @@ def hydrate(self, bundle):
bundle.data[FIELD_ORGANISATION] = organisation
if (
organisation.iati_org_id != bundle.data[FIELD_REPORTING_ORG] or
bundle.data[FIELD_PARTNER_TYPE] != Partnership.SUPPORT_PARTNER
bundle.data[FIELD_PARTNER_TYPE] != Partnership.IATI_ACCOUNTABLE_PARTNER
):
bundle.data[FIELD_IATI_ACTIVITY_ID] = None
bundle.data[FIELD_INTERNAL_ID] = None
Expand All @@ -197,15 +197,48 @@ def hydrate_organisation(self, bundle):
class PartnershipResource(ConditionalFullResource):
organisation = ConditionalFullToOneField('akvo.api.resources.OrganisationResource', 'organisation')
project = ConditionalFullToOneField('akvo.api.resources.ProjectResource', 'project')
partner_type = fields.CharField(attribute='iati_role_to_partner_type')

def __init__(self, api_name=None):
""" override to be able to create custom help_text on the partner_type field
"""
super(PartnershipResource, self).__init__(api_name=None)
self.fields['partner_type'].help_text = "Uses the following key-value pair list: {%s}" % ', '.join(
['"%s": "%s"' % (k, v) for k, v in Partnership.PARTNER_TYPES]
self.fields[
'iati_organisation_role'].help_text = "Uses the following key-value pair list: {%s}" % ', '.join(
['"%s": "%s"' % (k, v) for k, v in Partnership.IATI_ROLES]
)

def apply_filters(self, request, applicable_filters):
""" Custom filtering for the "fake" field partner_type allowing the filtering of the
resource using the deprecated Akvo partner type values
Uses Partnership.PARTNER_TYPES_TO_ROLES_MAP map the filter to the
Partnership.iati_organisation_role field
"""

partner_type_filter = {}
if 'iati_role_to_partner_type' in [k.split('__')[0] for k in applicable_filters.keys()]:
for k in applicable_filters.keys():
if k.startswith('iati_role_to_partner_type'):
operator = k.split('__')[1]
if operator == 'in':
values = [
Partnership.PARTNER_TYPES_TO_ROLES_MAP[v] for v in applicable_filters[k]
]
partner_type_filter['iati_organisation_role__in'] = values
else:
partner_type_filter[
"iati_organisation_role__{}".format(operator)
] = Partnership.PARTNER_TYPES_TO_ROLES_MAP[applicable_filters[k]]
applicable_filters.pop(k)

default_filtering = super(PartnershipResource, self).apply_filters(request, applicable_filters)

if partner_type_filter:
return default_filtering.filter(**partner_type_filter)
else:
return default_filtering

class Meta:
max_limit = 10
allowed_methods = ['get']
Expand All @@ -214,10 +247,11 @@ class Meta:
filtering = dict(organisation=ALL_WITH_RELATIONS)
filtering = dict(
# other fields
iati_activity_id = ALL,
internal_id = ALL,
partner_type = ALL,
iati_activity_id = ALL,
internal_id = ALL,
partner_type = ALL,
iati_organisation_role = ALL,
# foreign keys
organisation = ALL_WITH_RELATIONS,
project = ALL_WITH_RELATIONS,
organisation = ALL_WITH_RELATIONS,
project = ALL_WITH_RELATIONS,
)
2 changes: 1 addition & 1 deletion akvo/api/resources/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ def alter_deserialized_detail_data(self, request, data):
reporting_org=temp_org['reporting_org'],
name='Incorrect business unit', #this should never be used, if it is the lookup of existing BUs is borked
long_name='Incorrect business unit',
partner_type='sponsor',
iati_organisation_role=100, # old partner type sponsor partner
new_organisation_type='21',
organisation=None,
)]
Expand Down
8 changes: 4 additions & 4 deletions akvo/api/xml/iati-xslt.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -524,16 +524,16 @@
</xsl:otherwise>
</xsl:choose>
<xsl:if test="@role='Accountable'">
<partner_type>support</partner_type>
<iati_organisation_role>2</iati_organisation_role>
</xsl:if>
<xsl:if test="@role='Extending'">
<partner_type>support</partner_type>
<iati_organisation_role>3</iati_organisation_role>
</xsl:if>
<xsl:if test="@role='Funding'">
<partner_type>funding</partner_type>
<iati_organisation_role>1</iati_organisation_role>
</xsl:if>
<xsl:if test="@role='Implementing'">
<partner_type>field</partner_type>
<iati_organisation_role>4</iati_organisation_role>
</xsl:if>
</object>
</xsl:template>
Expand Down
4 changes: 1 addition & 3 deletions akvo/cordaid_org_importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from django.core.files.temp import NamedTemporaryFile

from akvo.codelists.store.codelists_v201 import ORGANISATION_TYPE as IATI_LIST_ORGANISATION_TYPE
from akvo.rsr.models import InternalOrganisationID, Organisation, PartnerType
from akvo.rsr.models import InternalOrganisationID, Organisation
from akvo.utils import model_and_instance_based_filename


Expand Down Expand Up @@ -95,8 +95,6 @@ def import_orgs(xml_file):
identifier=identifier
)
internal_org_id.save()
for partner_type in PartnerType.objects.all():
referenced_org.partner_types.add(partner_type)
except Exception, e:
action = "failed"
internal_org_id.delete()
Expand Down
11 changes: 6 additions & 5 deletions akvo/iati/checks/v201.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,16 @@ def partners(self):
if partnership.organisation:
org = partnership.organisation
org_name = org.long_name or org.name
if partnership.partner_type and (org.iati_org_id or org_name):
if (partnership.iati_organisation_role and
partnership.iati_organisation_role < 100 and (org.iati_org_id or org_name)):
valid_partner = True
if not partnership.partner_type:
if not partnership.iati_organisation_role:
checks.append((u'error', u'missing role for partner %s' % org_name))
if not org.iati_org_id:
checks.append((u'warning', u'partner %s has no IATI identifier' % org_name))
if not org_name:
checks.append((u'warning', u'%s partner has no organisation '
u'name' % partnership.partner_type))
checks.append((u'warning', u'%s has no organisation '
u'name' % partnership.iati_organisation_role))
else:
checks.append((u'error', u'partnership has no organisation'))

Expand Down Expand Up @@ -434,7 +435,7 @@ def planned_disbursements(self):
checks = []

for pd in self.project.planned_disbursements.all():
if not pd.amount:
if not pd.value:
checks.append((u'error', u'planned disbursement (id: %s) has '
u'no amount' % str(pd.pk)))
if not pd.period_start:
Expand Down
8 changes: 5 additions & 3 deletions akvo/iati/elements/participating_org.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ def participating_org(project):
"""
partnership_elements = []

from akvo.rsr.models import Partnership

for partnership in project.partnerships.all():
org = partnership.organisation
element = etree.Element("participating-org")
Expand All @@ -32,9 +34,9 @@ def participating_org(project):

if org.new_organisation_type:
element.attrib['type'] = str(org.new_organisation_type)

if partnership.partner_type in TYPE_TO_CODE.keys():
element.attrib['role'] = TYPE_TO_CODE[partnership.partner_type]
# don't include old akvo sponsor partner value when checking
if partnership.iati_organisation_role in Partnership.IATI_ROLE_LIST[:-1]:
element.attrib['role'] = str(partnership.iati_organisation_role)

narrative_element = etree.SubElement(element, "narrative")

Expand Down
5 changes: 0 additions & 5 deletions akvo/rest/rsr_api_upload/json/organisation_1.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@
"content_owner": null,
"allow_edit": true,
"primary_location": null,
"partner_types": [
"field",
"funding",
"sponsor"
],
"internal_org_ids": []
},
"organisation_location": {
Expand Down
4 changes: 2 additions & 2 deletions akvo/rest/rsr_api_upload/json/project_1.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
},
"partnership": {
"organisation": "Akvo",
"partner_type": "field",
"iati_organisation_role": "4",
"funding_amount": null,
"partner_type_extra": null,
"iati_activity_id": null,
Expand All @@ -107,7 +107,7 @@
},
"partnership": {
"organisation": "Akvo",
"partner_type": "funding",
"iati_organisation_role": "1",
"funding_amount": 4711,
"partner_type_extra": null,
"iati_activity_id": null,
Expand Down
2 changes: 0 additions & 2 deletions akvo/rest/serializers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
from .organisation_location import (OrganisationLocationSerializer,
MapOrganisationLocationSerializer)
from .partner_site import PartnerSiteSerializer
from .partner_type import PartnerTypeSerializer
from .partnership import PartnershipSerializer
from .planned_disbursement import PlannedDisbursementSerializer
from .policy_marker import PolicyMarkerSerializer
Expand Down Expand Up @@ -82,7 +81,6 @@
'OrganisationLocationSerializer',
'PartnershipSerializer',
'PartnerSiteSerializer',
'PartnerTypeSerializer',
'PlannedDisbursementSerializer',
'PolicyMarkerSerializer',
'ProjectCommentSerializer',
Expand Down
16 changes: 0 additions & 16 deletions akvo/rest/serializers/partner_type.py

This file was deleted.

3 changes: 3 additions & 0 deletions akvo/rest/serializers/partnership.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# 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 rest_framework import serializers

from akvo.rsr.models import Partnership

Expand All @@ -12,5 +13,7 @@

class PartnershipSerializer(BaseRSRSerializer):

partner_type = serializers.Field(source='iati_role_to_partner_type')

class Meta:
model = Partnership
3 changes: 3 additions & 0 deletions akvo/rest/serializers/project_update_location.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class Meta:

class ProjectUpdateLocationExtraSerializer(ProjectUpdateLocationSerializer):

# Limit update data to its PK, this is needed because of Meta.depth = 2
location_target = serializers.Field(source='location_target.pk')

class Meta(ProjectUpdateLocationSerializer.Meta):
depth = 2

Expand Down
1 change: 0 additions & 1 deletion akvo/rest/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
router.register(r'organisation_location', views.OrganisationLocationViewSet)
router.register(r'organisation_map_location', views.MapOrganisationLocationViewSet)
router.register(r'partner_site', views.PartnerSiteViewSet)
router.register(r'partner_type', views.PartnerTypeViewSet)
router.register(r'partnership', views.PartnershipViewSet)
router.register(r'planned_disbursement', views.PlannedDisbursementViewSet)
router.register(r'policy_marker', views.PolicyMarkerViewSet)
Expand Down
Loading

0 comments on commit 671800c

Please sign in to comment.