Skip to content

Commit

Permalink
Merge pull request #1864 from unicef/staging
Browse files Browse the repository at this point in the history
Staging
  • Loading branch information
domdinicola authored Sep 20, 2018
2 parents b2520fd + cd35a25 commit 4b44a3b
Show file tree
Hide file tree
Showing 83 changed files with 1,338 additions and 874 deletions.
5 changes: 5 additions & 0 deletions src/etools/applications/EquiTrack/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
import codecs
import csv
import hashlib
import json
from datetime import datetime

Expand Down Expand Up @@ -173,3 +174,7 @@ def get_quarter(retrieve_date=None):
else:
quarter = 'q4'
return quarter


def h11(w):
return hashlib.md5(w).hexdigest()[:9]
43 changes: 11 additions & 32 deletions src/etools/applications/action_points/export/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,21 @@

class ActionPointExportSerializer(serializers.Serializer):
ref = serializers.CharField(source='reference_number', read_only=True)
cp_output = serializers.SerializerMethodField()
partner = serializers.SerializerMethodField()
office = serializers.SerializerMethodField()
section = serializers.SerializerMethodField()
category = serializers.SerializerMethodField()
assigned_to = serializers.CharField(source='assigned_to.get_full_name')
cp_output = serializers.CharField(source='cp_output.__str__', allow_null=True)
partner = serializers.CharField(source='partner.name', allow_null=True)
office = serializers.CharField(source='office.name', allow_null=True)
section = serializers.CharField(source='section.name', allow_null=True)
category = serializers.CharField(source='category.description', allow_null=True)
assigned_to = serializers.CharField(source='assigned_to.get_full_name', allow_null=True)
due_date = serializers.DateField(format='%d/%m/%Y')
status = serializers.CharField(source='get_status_display')
description = serializers.CharField()
intervention = serializers.CharField(source='intervention.reference_number', read_only=True)
pd_ssfa = serializers.SerializerMethodField()
location = serializers.SerializerMethodField()
intervention = serializers.CharField(source='intervention.reference_number', read_only=True, allow_null=True)
pd_ssfa = serializers.CharField(source='intervention.title', allow_null=True)
location = serializers.CharField(source='location.__str__', allow_null=True)
related_module = serializers.CharField()
assigned_by = serializers.CharField(source='assigned_by.get_full_name')
assigned_by = serializers.CharField(source='assigned_by.get_full_name', allow_null=True)
date_of_completion = serializers.DateTimeField(format='%d/%m/%Y')
related_ref = serializers.CharField(source='related_object.reference_number', read_only=True)
related_ref = serializers.CharField(source='related_object.reference_number', read_only=True, allow_null=True)
related_object_str = serializers.CharField()
related_object_url = serializers.CharField()

def get_cp_output(self, obj):
return obj.cp_output.__str__ if obj.cp_output else ""

def get_partner(self, obj):
return obj.partner.name if obj.partner else ""

def get_office(self, obj):
return obj.office.name if obj.office else ""

def get_section(self, obj):
return obj.section.name if obj.section else ""

def get_category(self, obj):
return obj.category.description if obj.category else ""

def get_pd_ssfa(self, obj):
return obj.intervention.title if obj.intervention else ""

def get_location(self, obj):
return obj.location.__str__ if obj.location else ""
9 changes: 6 additions & 3 deletions src/etools/applications/action_points/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

from etools.applications.action_points.categories.models import Category
from etools.applications.action_points.transitions.conditions import ActionPointCompleteActionsTakenCheck
from etools.applications.EquiTrack.utils import get_environment
from etools.applications.action_points.transitions.serializers.serializers import ActionPointCompleteSerializer
from etools.applications.EquiTrack.utils import get_environment
from etools.applications.permissions2.fsm import has_action_permission
from etools.applications.utils.common.urlresolvers import build_frontend_url
from etools.applications.utils.groups.wrappers import GroupWrapper
Expand All @@ -23,9 +23,12 @@
class ActionPoint(TimeStampedModel):
MODULE_CHOICES = Category.MODULE_CHOICES

STATUS_OPEN = 'open'
STATUS_COMPLETED = 'completed'

STATUSES = Choices(
('open', _('Open')),
('completed', _('Completed')),
(STATUS_OPEN, _('Open')),
(STATUS_COMPLETED, _('Completed')),
)

STATUSES_DATES = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from etools.applications.audit.purchase_order.models import AuditorFirm, PurchaseOrder, PurchaseOrderItem
from etools.applications.funds.models import Donor, Grant
from etools.applications.vision.adapters.manual import ManualVisionSynchronizer
from etools.applications.vision.synchronizers import ManualVisionSynchronizer


class POSynchronizer(ManualVisionSynchronizer):
Expand Down
32 changes: 32 additions & 0 deletions src/etools/applications/audit/purchase_order/tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from celery.utils.log import get_task_logger

# Not scheduled by any code in this repo, but by other means, so keep it around.
# Continues on to the next country on any VisionException, so no need to have
# celery retry it in that case.
from etools.applications.audit.purchase_order.synchronizers import POSynchronizer
from etools.applications.users.models import Country
from etools.applications.vision.exceptions import VisionException
from etools.config.celery import app

logger = get_task_logger(__name__)


@app.task
def update_purchase_orders(country_name=None):
logger.info(u'Starting update values for purchase order')
countries = Country.objects.filter(vision_sync_enabled=True)
processed = []
if country_name is not None:
countries = countries.filter(name=country_name)
for country in countries:
try:
logger.info(u'Starting purchase order update for country {}'.format(
country.name
))
POSynchronizer(country).sync()
processed.append(country.name)
logger.info(u"Update finished successfully for {}".format(country.name))
except VisionException:
logger.exception(u"{} sync failed".format(POSynchronizer.__name__))
# Keep going to the next country
logger.info(u'Purchase orders synced successfully for {}.'.format(u', '.join(processed)))
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@

import json
from unittest import mock

from etools.applications.audit.purchase_order import synchronizers
from etools.applications.audit.purchase_order.models import AuditorFirm, PurchaseOrder, PurchaseOrderItem
from etools.applications.audit.purchase_order.tasks import update_purchase_orders
from etools.applications.EquiTrack.tests.cases import BaseTenantTestCase
from etools.applications.funds.models import Donor, Grant
from etools.applications.users.models import Country
from etools.applications.vision.adapters import purchase_order as adapter


class TestPSynchronizer(BaseTenantTestCase):
Expand All @@ -25,14 +27,14 @@ def setUp(self):
"GRANT_REF": "Grantor",
"PO_ITEM": "456",
}
self.adapter = adapter.POSynchronizer(self.country)
self.adapter = synchronizers.POSynchronizer(self.country)

def test_init_no_object_number(self):
a = adapter.POSynchronizer(self.country)
a = synchronizers.POSynchronizer(self.country)
self.assertEqual(a.country, self.country)

def test_init(self):
a = adapter.POSynchronizer(self.country, object_number="123")
a = synchronizers.POSynchronizer(self.country, object_number="123")
self.assertEqual(a.country, self.country)

def test_convert_records_list(self):
Expand Down Expand Up @@ -78,3 +80,23 @@ def test_save_records(self):
self.assertTrue(auditor_qs.exists())
self.assertTrue(donor_qs.exists())
self.assertTrue(grant_qs.exists())


class TestUpdatePurchaseOrders(BaseTenantTestCase):
@classmethod
def setUpTestData(cls):
cls.country = Country.objects.first()

@mock.patch("etools.applications.vision.tasks.logger.exception")
def test_update_purchase_orders_no_country(self, mock_logger_exception):
"""Ensure no exceptions if no countries"""
update_purchase_orders(country_name="Wrong")
self.assertEqual(mock_logger_exception.call_count, 0)

@mock.patch("etools.applications.vision.tasks.logger.exception")
@mock.patch("etools.applications.audit.purchase_order.tasks.POSynchronizer")
def test_update_purchase_orders(self, synchronizer, mock_logger_exception):
"""Ensure no exceptions if no countries"""
update_purchase_orders()
self.assertEqual(mock_logger_exception.call_count, 0)
self.assertEqual(synchronizer.call_count, 1)
14 changes: 14 additions & 0 deletions src/etools/applications/audit/purchase_order/tests/test_tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from unittest.mock import patch

from etools.applications.EquiTrack.tests.cases import BaseTenantTestCase
from etools.applications.audit.purchase_order.tasks import update_purchase_orders


class TestUpdatePurchaseOrders(BaseTenantTestCase):

@patch("etools.applications.audit.purchase_order.synchronizers.POSynchronizer.sync")
@patch('etools.applications.audit.purchase_order.tasks.logger', spec=['info', 'error'])
def test_update_purchase_orders(self, logger, mock_send):
update_purchase_orders()
self.assertEqual(mock_send.call_count, 1)
self.assertEqual(logger.info.call_count, 4)
8 changes: 4 additions & 4 deletions src/etools/applications/audit/serializers/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,8 @@ class Meta(EngagementPDFSerializer.Meta):
class EngagementBaseDetailCSVSerializer(serializers.Serializer):
unique_id = serializers.ReadOnlyField()
link = serializers.ReadOnlyField(source='get_object_url')
auditor = serializers.ReadOnlyField(source='agreement.auditor_firm.__str__')
partner = serializers.ReadOnlyField(source='partner.__str__')
auditor = serializers.ReadOnlyField(source='agreement.auditor_firm')
partner = serializers.ReadOnlyField()
status_display = serializers.SerializerMethodField()

def get_status_display(self, obj):
Expand Down Expand Up @@ -298,7 +298,7 @@ def get_subject_area(self, obj):
weaknesses = serializer.to_representation(serializer.get_attribute(instance=obj))

return OrderedDict(
(b['id'], ', '.join([risk['value_display'] for risk in b['risks']]) or '-')
(b['id'], ', '.join([str(risk['value_display']) for risk in b['risks']]) or '-')
for b in weaknesses['blueprints']
)

Expand Down Expand Up @@ -339,7 +339,7 @@ def get_questionnaire(self, obj):
)


class SpecialAuditDetailPDFSerializer(EngagementBaseDetailCSVSerializer):
class SpecialAuditDetailCSVSerializer(EngagementBaseDetailCSVSerializer):
"""
"""
29 changes: 27 additions & 2 deletions src/etools/applications/audit/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,32 @@ def test_hact_view(self):
self.assertEqual(len(response.data), 1)
self.assertNotEqual(response.data[0], {})

def test_csv_view(self):
AuditFactory()
MicroAssessmentFactory()
SpotCheckFactory()

response = self.forced_auth_req(
'get',
'/api/audit/engagements/csv/',
user=self.unicef_user,
)

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('text/csv', response['Content-Type'])

def test_staff_spot_checks_csv_view(self):
engagement = StaffSpotCheckFactory()

response = self.forced_auth_req(
'get',
'/api/audit/staff-spot-checks/csv/'.format(engagement.id),
user=self.unicef_user,
)

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('text/csv', response['Content-Type'])


class BaseTestEngagementsCreateViewSet(EngagementTransitionsTestCaseMixin):
endpoint = 'engagements'
Expand Down Expand Up @@ -1081,9 +1107,8 @@ def setUpTestData(cls):
def test_csv_view(self):
response = self.forced_auth_req(
'get',
'/api/audit/micro-assessments/{}/'.format(self.engagement.id),
'/api/audit/micro-assessments/{}/csv/'.format(self.engagement.id),
user=self.unicef_user,
data={'format': 'csv'}
)

self.assertEqual(response.status_code, status.HTTP_200_OK)
Expand Down
Loading

0 comments on commit 4b44a3b

Please sign in to comment.