Skip to content

Commit

Permalink
Merge pull request #3682 from unicef/staging
Browse files Browse the repository at this point in the history
Staging
  • Loading branch information
robertavram authored Jun 20, 2024
2 parents c4fd264 + dfa1bed commit 80f5641
Show file tree
Hide file tree
Showing 47 changed files with 1,138 additions and 677 deletions.
2 changes: 1 addition & 1 deletion src/etools/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
VERSION = __version__ = '11.2.3'
VERSION = __version__ = '11.4'
NAME = 'eTools'
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ class Command(BaseCommand):
'audit.engagement.status',
'audit.engagement.status_date',

'audit.spotcheck.face_form_start_date',
'audit.spotcheck.face_form_end_date',

'purchase_order.purchaseorder.*',
'purchase_order.auditorfirm.*',
]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.2.19 on 2024-05-07 10:59

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('audit', '0030_engagement_send_back_comment'),
]

operations = [
migrations.AlterField(
model_name='engagement',
name='end_date',
field=models.DateField(blank=True, null=True, verbose_name='Start date of first reporting FACE'),
),
migrations.AlterField(
model_name='engagement',
name='start_date',
field=models.DateField(blank=True, null=True, verbose_name='End date of last reporting FACE'),
),
]
4 changes: 2 additions & 2 deletions src/etools/applications/audit/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ class Engagement(InheritedModelMixin, TimeStampedModel, models.Model):
)
partner_contacted_at = models.DateField(verbose_name=_('Date IP was contacted'), blank=True, null=True)
engagement_type = models.CharField(verbose_name=_('Engagement Type'), max_length=10, choices=TYPES)
start_date = models.DateField(verbose_name=_('Period Start Date'), blank=True, null=True)
end_date = models.DateField(verbose_name=_('Period End Date'), blank=True, null=True)
start_date = models.DateField(verbose_name=_('Start date of first reporting FACE'), blank=True, null=True)
end_date = models.DateField(verbose_name=_('End date of last reporting FACE'), blank=True, null=True)
total_value = models.DecimalField(
verbose_name=_('Total value of selected FACE form(s)'), default=0, decimal_places=2, max_digits=20
)
Expand Down
24 changes: 18 additions & 6 deletions src/etools/applications/audit/serializers/engagement.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@ class EngagementSerializer(
WritableNestedParentSerializerMixin,
EngagementListSerializer
):
face_form_start_date = serializers.DateField(label='FACE Form(s) Start Date', read_only=True, source='start_date')
face_form_end_date = serializers.DateField(label='FACE Form(s) End Date', read_only=True, source='end_date')

staff_members = SeparatedReadWriteField(
read_field=serializers.SerializerMethodField(),
label=_('Audit Staff Team Members')
Expand Down Expand Up @@ -287,6 +290,7 @@ class EngagementSerializer(

class Meta(EngagementListSerializer.Meta):
fields = EngagementListSerializer.Meta.fields + [
'face_form_start_date', 'face_form_end_date',
'total_value', 'staff_members', 'active_pd', 'authorized_officers', 'users_notified',
'joint_audit', 'year_of_audit', 'shared_ip_with', 'exchange_rate', 'currency_of_report',
'start_date', 'end_date', 'partner_contacted_at', 'date_of_field_visit', 'date_of_draft_report_to_ip',
Expand Down Expand Up @@ -399,16 +403,13 @@ class Meta(WritableNestedSerializerMixin.Meta):
class SpotCheckSerializer(ActivePDValidationMixin, EngagementSerializer):
findings = FindingSerializer(many=True, required=False)

face_form_start_date = serializers.DateField(label='FACE Form(s) Start Date', read_only=True, source='start_date')
face_form_end_date = serializers.DateField(label='FACE Form(s) End Date', read_only=True, source='end_date')

pending_unsupported_amount = serializers.DecimalField(20, 2, label=_('Pending Unsupported Amount'), read_only=True)

class Meta(EngagementSerializer.Meta):
model = SpotCheck
fields = EngagementSerializer.Meta.fields + [
'total_amount_tested', 'total_amount_of_ineligible_expenditure',
'internal_controls', 'findings', 'face_form_start_date', 'face_form_end_date',
'internal_controls', 'findings',
'amount_refunded', 'additional_supporting_documentation_provided',
'justification_provided_and_accepted', 'write_off_required', 'pending_unsupported_amount',
'explanation_for_additional_information'
Expand Down Expand Up @@ -561,18 +562,29 @@ def get_number_of_financial_findings(self, obj):
def _validate_financial_findings(self, validated_data):
financial_findings = validated_data.get('financial_findings')
audited_expenditure = validated_data.get('audited_expenditure')
if not (financial_findings or audited_expenditure):
financial_findings_local = validated_data.get('financial_findings_local')
audited_expenditure_local = validated_data.get('audited_expenditure_local')
if not (financial_findings or audited_expenditure) and not (financial_findings_local or audited_expenditure_local):
return

if not financial_findings:
financial_findings = self.instance.financial_findings if self.instance else None
if not audited_expenditure:
audited_expenditure = self.instance.audited_expenditure if self.instance else None

if audited_expenditure and financial_findings and financial_findings > audited_expenditure:
if audited_expenditure and financial_findings and financial_findings >= audited_expenditure:
raise serializers.ValidationError({'financial_findings': _('Cannot exceed Audited Expenditure')})

if not financial_findings_local:
financial_findings_local = self.instance.financial_findings_local if self.instance else None
if not audited_expenditure_local:
audited_expenditure_local = self.instance.audited_expenditure_local if self.instance else None

if audited_expenditure_local and financial_findings_local and financial_findings_local >= audited_expenditure_local:
raise serializers.ValidationError({'financial_findings_local': _('Cannot exceed Audited Expenditure Local')})

def validate(self, validated_data):
validated_data = super().validate(validated_data)
self._validate_financial_findings(validated_data)
return validated_data

Expand Down
27 changes: 27 additions & 0 deletions src/etools/applications/audit/serializers/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,33 @@ def _validate_dates(self, validated_data):
if value and key in date_fields and timezone.now().date() < value:
errors[key] = _('Date should be in past.')

start_date = validated_data.get('start_date', self.instance.start_date if self.instance else None)
end_date = validated_data.get('end_date', self.instance.end_date if self.instance else None)
partner_contacted_at = validated_data.get('partner_contacted_at', self.instance.partner_contacted_at if self.instance else None)
date_of_field_visit = validated_data.get('date_of_field_visit', self.instance.date_of_field_visit if self.instance else None)
date_of_draft_report_to_ip = validated_data.get('date_of_draft_report_to_ip', self.instance.date_of_draft_report_to_ip if self.instance else None)
date_of_comments_by_ip = validated_data.get('date_of_comments_by_ip', self.instance.date_of_comments_by_ip if self.instance else None)
date_of_draft_report_to_unicef = validated_data.get('date_of_draft_report_to_unicef', self.instance.date_of_draft_report_to_unicef if self.instance else None)
date_of_comments_by_unicef = validated_data.get('date_of_comments_by_unicef', self.instance.date_of_comments_by_unicef if self.instance else None)

if start_date and end_date and end_date < start_date:
errors['end_date'] = _('This date should be after Period Start Date.')
if end_date and partner_contacted_at and partner_contacted_at < end_date:
errors['partner_contacted_at'] = _('This date should be after Period End Date.')

if partner_contacted_at and date_of_field_visit and date_of_field_visit < partner_contacted_at:
errors['date_of_field_visit'] = _('This date should be after Date IP was contacted.')

if date_of_field_visit and date_of_draft_report_to_ip and date_of_draft_report_to_ip < date_of_field_visit:
# date of field visit is editable even if date of draft report is readonly, map error to field visit date
errors['date_of_field_visit'] = _('This date should be before Date Draft Report Issued to IP.')
if date_of_draft_report_to_ip and date_of_comments_by_ip and date_of_comments_by_ip < date_of_draft_report_to_ip:
errors['date_of_comments_by_ip'] = _('This date should be after Date Draft Report Issued to UNICEF.')
if date_of_comments_by_ip and date_of_draft_report_to_unicef and date_of_draft_report_to_unicef < date_of_comments_by_ip:
errors['date_of_draft_report_to_unicef'] = _('This date should be after Date Comments Received from IP.')
if date_of_draft_report_to_unicef and date_of_comments_by_unicef and date_of_comments_by_unicef < date_of_draft_report_to_unicef:
errors['date_of_comments_by_unicef'] = _('This date should be after Date Draft Report Issued to UNICEF.')

if errors:
raise serializers.ValidationError(errors)
return validated_data
11 changes: 11 additions & 0 deletions src/etools/applications/audit/tests/factories.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import random
from datetime import timedelta

from django.db.models import signals
from django.utils import timezone

import factory
from factory import fuzzy
Expand Down Expand Up @@ -133,16 +135,25 @@ class Meta:


class AuditFactory(EngagementFactory):
start_date = timezone.now().date() - timedelta(days=30)
end_date = timezone.now().date() - timedelta(days=10)

class Meta:
model = Audit


class SpecialAuditFactory(EngagementFactory):
start_date = timezone.now().date() - timedelta(days=30)
end_date = timezone.now().date() - timedelta(days=10)

class Meta:
model = SpecialAudit


class SpotCheckFactory(EngagementFactory):
start_date = timezone.now().date() - timedelta(days=30)
end_date = timezone.now().date() - timedelta(days=10)

class Meta:
model = SpotCheck

Expand Down
Loading

0 comments on commit 80f5641

Please sign in to comment.