def create(self, request, *args, **kwargs): """ Add a new Intervention :return: JSON """ related_fields = ['planned_budget', 'planned_visits', 'result_links'] nested_related_names = ['ll_results'] serializer = self.my_create(request, related_fields, nested_related_names=nested_related_names, **kwargs) instance = serializer.instance validator = InterventionValid(instance, user=request.user) if not validator.is_valid: logging.debug(validator.errors) raise ValidationError(validator.errors) headers = self.get_success_headers(serializer.data) if getattr(instance, '_prefetched_objects_cache', None): # If 'prefetch_related' has been applied to a queryset, we need to # refresh the instance from the database. instance = self.get_object() return Response(InterventionDetailSerializer( instance, context=self.get_serializer_context()).data, status=status.HTTP_201_CREATED, headers=headers)
def test_check_rigid_fields_invalid(self): mock_check = Mock(return_value=(False, None)) validator = InterventionValid( self.intervention, user=self.unicef_staff, ) validator.permissions = validator.get_permissions(self.intervention) with patch( "etools.applications.partners.validation.interventions.check_rigid_fields", mock_check ): with self.assertRaisesRegexp( StateValidationError, "Cannot change fields while" ): validator.check_rigid_fields(self.intervention)
def run_check(self, model_instance, metadata): master_user = metadata['master_user'] validator = InterventionValid(model_instance, master_user) if not validator.is_valid: raise IssueFoundException( 'intervention {} of type {} is invalid: (Status:{}), Errors: {}'.format( model_instance.id, model_instance.document_type, model_instance.status, ', '.join(validator.errors) ) )
def remediation_intervention_migration(): from django.db import transaction from etools.applications.partners.validation.interventions import InterventionValid User = get_user_model() master_user = User.objects.get(username='******') active_interventions = Intervention.objects.filter(status='active') for intervention in active_interventions: validator = InterventionValid(intervention, user=master_user, disable_rigid_check=True) if not validator.is_valid: logger.info(u'active intervention {} of type {} is invalid'.format( intervention.id, intervention.document_type)) logger.error(validator.errors) intervention.status = Intervention.DRAFT intervention.metadata = { 'migrated': True, 'old_status': Intervention.ACTIVE, 'error_msg': validator.errors } intervention.save() # let it run through validation again, maybe it will auto-transition to signed with transaction.atomic(): new_validator = InterventionValid(intervention, master_user, disable_rigid_check=True) if new_validator.is_valid: if intervention.status == 'signed': logger.info(u'intervention moved to signed {}'.format( intervention.status)) intervention.metadata = { 'migrated': True, 'old_status': Intervention.DRAFT, } intervention.save() else: logger.debug('draft invalid') else: logger.info( u'intervention {} of type {} successfully ported as active'. format(intervention.id, intervention.document_type))
def test_no_issue(self): """Check if intervention does not fail validation, no issue is raised """ intervention = InterventionFactory() validator = InterventionValid(intervention, self.master_user) self.assertTrue(validator.is_valid) self.assertFalse(self.qs_issue.exists()) checks.bootstrap_checks(default_is_active=True) checks.run_all_checks() self.assertFalse(self.qs_issue.exists())
def setUpTestData(cls): cls.unicef_staff = UserFactory(is_staff=True) cls.intervention = InterventionFactory() cls.intervention.old_instance = cls.intervention cls.validator = InterventionValid( cls.intervention, user=cls.unicef_staff, disable_rigid_check=True, ) cls.validator.permissions = cls.validator.get_permissions( cls.intervention) cls.future_date = datetime.date.today() + datetime.timedelta(days=2)
def test_invalid_intervention(self): """Check if intervention fails validation, issue is raised""" intervention = InterventionFactory( signed_by_unicef_date=datetime.date(2001, 2, 1), signed_by_partner_date=datetime.date(2001, 3, 1), signed_pd_document="random.pdf", start=datetime.date(2001, 1, 1)) validator = InterventionValid(intervention, self.master_user) self.assertFalse(validator.is_valid) self.assertFalse(self.qs_issue.exists()) checks.bootstrap_checks(default_is_active=True) checks.run_all_checks() self.assertTrue(self.qs_issue.exists())
def _make_intervention_status_automatic_transitions(country_name): """Implementation core of intervention_status_automatic_transition() (q.v.)""" logger.info( 'Starting intervention auto status transition for country {}'.format( country_name)) admin_user = get_user_model().objects.get( username=settings.TASK_ADMIN_USER) # these are agreements that are not even valid within their own status # compiling a list of them to send to an admin or save somewhere in the future bad_interventions = [] active_ended = Intervention.objects.filter(status=Intervention.ACTIVE, end__lt=datetime.date.today()) # get all the interventions for which their status is endend and total otustanding_amt is 0 and # actual_amt is the same as the total_amt qs = Intervention.objects\ .prefetch_related('frs')\ .filter(status=Intervention.ENDED)\ .annotate(frs_total_outstanding=Sum('frs__outstanding_amt'), frs_total_actual_amt=Sum('frs__actual_amt'), frs_intervention_amt=Sum('frs__intervention_amt'))\ .filter(frs_total_outstanding=0, frs_total_actual_amt=F('frs_intervention_amt')) processed = 0 for intervention in itertools.chain(active_ended, qs): old_status = intervention.status with transaction.atomic(): # this function mutates the intervention validator = InterventionValid(intervention, user=admin_user, disable_rigid_check=True) if validator.is_valid: if intervention.status != old_status: # this one transitioned forward intervention.save() processed += 1 else: bad_interventions.append(intervention) logger.error('Bad interventions {}'.format(len(bad_interventions))) logger.error('Bad interventions ids: ' + ' '.join(str(a.id) for a in bad_interventions)) logger.info('Total interventions {}'.format(active_ended.count() + qs.count())) logger.info("Transitioned interventions {} ".format(processed))
def test_check_rigid_fields_invalid(self): mock_check = Mock(return_value=(False, None)) validator = InterventionValid( self.intervention, user=self.unicef_staff, ) validator.permissions = validator.get_permissions(self.intervention) with patch( "etools.applications.partners.validation.interventions.check_rigid_fields", mock_check): with self.assertRaisesRegexp(StateValidationError, "Cannot change fields while"): validator.check_rigid_fields(self.intervention)
def intervention_update_task(): from etools.applications.partners.validation.interventions import InterventionValid User = get_user_model() master_user = User.objects.get(username='******') all_interventions = Intervention.objects.filter( status__in=['draft', 'signed', 'active', 'ended']) for intervention in all_interventions.all(): old_status = intervention.status validator = InterventionValid(intervention, master_user) if not validator.is_valid: logger.info( u'intervention {} of type {} is invalid: (Status:{})'.format( intervention.id, intervention.document_type, intervention.status)) logger.error(validator.errors) else: if old_status != intervention.status: intervention.save() logger.info( u'intervention {} of type {} successfully updated from {} to {}' .format(intervention.id, intervention.document_type, old_status, intervention.status))
def update(self, request, *args, **kwargs): related_fields = ['planned_budget', 'attachments', 'result_links'] nested_related_names = ['ll_results'] instance, old_instance, serializer = self.my_update( request, related_fields, nested_related_names=nested_related_names, **kwargs ) validator = InterventionValid(instance, old=old_instance, user=request.user) if not validator.is_valid: logging.debug(validator.errors) raise ValidationError(validator.errors) if getattr(instance, '_prefetched_objects_cache', None): # If 'prefetch_related' has been applied to a queryset, we need to # refresh the instance from the database. instance = self.get_object() return Response(InterventionDetailSerializer(instance, context=self.get_serializer_context()).data)