Beispiel #1
0
 def setUp(self):
     vendor_code = self.intervention.agreement.partner.vendor_number
     self.fr_1 = FundsReservationHeaderFactory(intervention=None,
                                               currency="USD",
                                               vendor_code=vendor_code)
     self.fr_2 = FundsReservationHeaderFactory(intervention=None,
                                               currency="USD",
                                               vendor_code=vendor_code)
     self.fr_3 = FundsReservationHeaderFactory(intervention=None,
                                               currency="RON")
Beispiel #2
0
    def test_notify_of_ended_interventions_with_some_interventions(
            self,
            mock_notification_objects,
            mock_db_connection,
            mock_logger):
        '''Exercise _notify_of_ended_interventions_with_mismatched_frs() when it has some interventions to work on'''
        # Create some interventions to work with. Interventions sort by oldest last, so I make sure my list here is
        # ordered in the same way as they'll be pulled out of the database.
        interventions = [InterventionFactory(status=Intervention.ENDED, created=_make_past_datetime(i))
                         for i in range(3)]

        # Add mismatched funds values to each intervention.
        for intervention in interventions:
            for i in range(3):
                FundsReservationHeaderFactory(intervention=intervention,
                                              actual_amt_local=_make_decimal(i + 1),
                                              total_amt_local=_make_decimal(i))

        # Create a few items that should be ignored. If they're not ignored, this test will fail.
        # Should be ignored because of status even though FRS values are mismatched
        intervention = InterventionFactory(status=Intervention.DRAFT)
        for i in range(3):
            FundsReservationHeaderFactory(intervention=intervention, actual_amt_local=_make_decimal(i + 1),
                                          total_amt_local=_make_decimal(i))

        # Should be ignored because FRS values are not mismatched
        intervention = InterventionFactory(status=Intervention.ENDED)
        for i in range(3):
            FundsReservationHeaderFactory(intervention=intervention, actual_amt_local=_make_decimal(i),
                                          total_amt_local=_make_decimal(i))

        # Mock Notifications.objects.create() to return a Mock. In order to *truly* mimic create(), my
        # mock_notification_objects.create() should return a new (mock) object every time, but the lazy way or
        # returning the same object is good enough and still allows me to count calls to .send_notification().
        mock_notification = mock.Mock(spec=['send_notification'])
        mock_notification_objects.create = mock.Mock(return_value=mock_notification)

        # I'm done mocking, it's time to call the function.
        partners.tasks._notify_of_ended_interventions_with_mismatched_frs(self.country_name)

        # Verify that Notification.objects.create() was called as expected.
        expected_call_args = [((), {'sender': intervention_,
                                    'recipients': [],
                                    'template_name': 'partners/partnership/ended/frs/outstanding',
                                    'template_data': partners.tasks.get_intervention_context(intervention_)
                                    })
                              for intervention_ in interventions]
        self._assertCalls(mock_notification_objects.create, expected_call_args)

        # Verify that each created notification object had send_notification() called.
        expected_call_args = [((), {})] * len(interventions)
        self._assertCalls(mock_notification.send_notification, expected_call_args)
Beispiel #3
0
 def test_attachment(self):
     """If Total actual amount > 100,000 need attachment with
     type Final Partnership Review
     """
     file_type = self.file_parnership_file_type
     InterventionAttachmentFactory(
         intervention=self.intervention,
         type=file_type
     )
     frs = FundsReservationHeaderFactory(
         intervention=self.intervention,
         total_amt=0.00,
         total_amt_local=120000.00,
         actual_amt_local=120000.00,
         actual_amt=0,
         outstanding_amt_local=0.00,
         outstanding_amt=0.00,
         intervention_amt=0.00,
     )
     self.assertTrue(transition_to_closed(self.intervention))
     self.expected["total_actual_amt"] = 120000.00
     self.expected["total_frs_amt"] = 120000.00
     self.expected["earliest_start_date"] = frs.start_date
     self.expected["latest_end_date"] = frs.end_date
     self.assertFundamentals(self.intervention.total_frs)
Beispiel #4
0
    def test_attachment_invalid(self):
        """If Total actual amount > 100,000 need attachment with
        type Final Partnership Review
        """
        frs = FundsReservationHeaderFactory(
            intervention=self.intervention,
            total_amt=0.00,
            total_amt_local=120000.00,
            actual_amt_local=120000.00,
            actual_amt=120000.00,
            outstanding_amt_local=0.00,
            outstanding_amt=0.00,
            intervention_amt=0.00,
        )

        with self.assertRaisesRegexp(
                TransitionError,
                'Total amount transferred greater than 100,000 and no '
                'Final Partnership Review was attached'
        ):
            transition_to_closed(self.intervention)
        self.expected["total_actual_amt"] = 120000.00
        self.expected["total_actual_amt_usd"] = 120000.00
        self.expected["total_frs_amt"] = 120000.00
        self.expected["earliest_start_date"] = frs.start_date
        self.expected["latest_end_date"] = frs.end_date
        self.assertFundamentals(self.intervention.total_frs)
Beispiel #5
0
 def test_dates(self):
     """Ensure earliest and latest dates set correctly"""
     FundsReservationHeaderFactory(
         intervention=self.intervention,
         fr_number=1,
         total_amt=0.00,
         total_amt_local=100.00,
         start_date=datetime.date(2001, 1, 1),
         end_date=datetime.date(2001, 2, 1),
         actual_amt=0.00,
         actual_amt_local=100.00,
         intervention_amt=0.00,
         outstanding_amt_local=0.00,
         outstanding_amt=0.00,
     )
     FundsReservationHeaderFactory(
         intervention=self.intervention,
         fr_number=2,
         total_amt=0.00,
         total_amt_local=100.00,
         start_date=datetime.date(2000, 1, 1),
         end_date=datetime.date(2000, 2, 1),
         actual_amt=0.00,
         actual_amt_local=100.00,
         intervention_amt=0.00,
         outstanding_amt_local=0.00,
         outstanding_amt=0.00,
     )
     FundsReservationHeaderFactory(
         intervention=self.intervention,
         fr_number=3,
         total_amt=0.00,
         total_amt_local=100.00,
         start_date=datetime.date(2002, 1, 1),
         end_date=datetime.date(2002, 2, 1),
         actual_amt_local=100.00,
         actual_amt=0.00,
         intervention_amt=0.00,
         outstanding_amt_local=0.00,
         outstanding_amt=0.00,
     )
     self.assertTrue(transition_to_closed(self.intervention))
     self.expected["earliest_start_date"] = datetime.date(2000, 1, 1)
     self.expected["latest_end_date"] = datetime.date(2002, 2, 1)
     self.expected["total_actual_amt"] = 300.00
     self.expected["total_frs_amt"] = 300.00
     self.assertFundamentals(self.intervention.total_frs)
Beispiel #6
0
 def test_update(self):
     user = UserFactory()
     intervention = InterventionFactory()
     obj_dict = utils.create_dict_with_relations(intervention)
     fr = FundsReservationHeaderFactory(intervention=intervention)
     activity = utils.create_snapshot(intervention, obj_dict, user)
     self.assertEqual(activity.target, intervention)
     self.assertEqual(activity.action, activity.UPDATE)
     self.assertEqual(activity.by_user, user)
     self.assertEqual(activity.data["title"], intervention.title)
     self.assertEqual(activity.change,
                      {"frs": {
                          "before": [],
                          "after": [fr.pk]
                      }})
Beispiel #7
0
 def test_total_frs_amount(self):
     """Ensure total_frs_amt set correctly"""
     frs = FundsReservationHeaderFactory(
         intervention=self.intervention,
         total_amt=0.00,
         total_amt_local=100.00,
         actual_amt=0.00,
         actual_amt_local=100.00,
         intervention_amt=0.00,
         outstanding_amt=0.00,
         outstanding_amt_local=0.00,
     )
     self.assertTrue(transition_to_closed(self.intervention))
     self.expected["total_frs_amt"] = 100.00
     self.expected["total_actual_amt"] = 100.00
     self.expected["earliest_start_date"] = frs.start_date
     self.expected["latest_end_date"] = frs.end_date
     self.assertFundamentals(self.intervention.total_frs)
Beispiel #8
0
 def test_total_amounts_valid(self):
     """Total amounts must equal and total outstanding must be zero"""
     frs = FundsReservationHeaderFactory(
         intervention=self.intervention,
         total_amt=0.00,
         total_amt_local=10.00,
         intervention_amt=0.00,
         actual_amt=0.00,
         actual_amt_local=10.00,
         outstanding_amt=0.00,
         outstanding_amt_local=0.00
     )
     self.assertTrue(transition_to_closed(self.intervention))
     self.expected["total_frs_amt"] = 10.00
     self.expected["total_actual_amt"] = 10.00
     self.expected["earliest_start_date"] = frs.start_date
     self.expected["latest_end_date"] = frs.end_date
     self.assertFundamentals(self.intervention.total_frs)
Beispiel #9
0
 def test_total_amounts_not_equal(self):
     """Total amounts must equal and total outstanding must be zero"""
     frs = FundsReservationHeaderFactory(
         intervention=self.intervention,
         total_amt=0.00,
         total_amt_local=0.00,
         intervention_amt=10.00,
         actual_amt_local=20.00,
         actual_amt=0.00,
         outstanding_amt_local=0.00,
         outstanding_amt=0.00
     )
     with self.assertRaisesRegexp(
             TransitionError,
             'Total FR amount needs to equal total actual amount, and '
             'Total Outstanding DCTs need to equal to 0'
     ):
         transition_to_closed(self.intervention)
     self.expected["total_intervention_amt"] = 10.00
     self.expected["total_actual_amt"] = 20.00
     self.expected["earliest_start_date"] = frs.start_date
     self.expected["latest_end_date"] = frs.end_date
     self.assertFundamentals(self.intervention.total_frs)
Beispiel #10
0
class TestFRHeaderView(BaseTenantTestCase):
    @classmethod
    def setUpTestData(cls):
        cls.unicef_staff = UserFactory(is_staff=True)
        partner = PartnerFactory(vendor_number="PVN")
        agreement = AgreementFactory(partner=partner)
        cls.intervention = InterventionFactory(agreement=agreement)

    def setUp(self):
        vendor_code = self.intervention.agreement.partner.vendor_number
        self.fr_1 = FundsReservationHeaderFactory(intervention=None,
                                                  currency="USD",
                                                  vendor_code=vendor_code)
        self.fr_2 = FundsReservationHeaderFactory(intervention=None,
                                                  currency="USD",
                                                  vendor_code=vendor_code)
        self.fr_3 = FundsReservationHeaderFactory(intervention=None,
                                                  currency="RON")

    def run_request(self, data):
        response = self.forced_auth_req('get',
                                        reverse('funds:frs'),
                                        user=self.unicef_staff,
                                        data=data)
        return response.status_code, json.loads(response.rendered_content)

    def test_get_one_fr(self):

        data = {'values': self.fr_1.fr_number}

        status_code, result = self.run_request(data)

        self.assertEqual(status_code, status.HTTP_200_OK)
        self.assertEqual(len(result['frs']), 1)
        self.assertEqual(result['total_actual_amt'],
                         float(self.fr_1.actual_amt_local))
        self.assertEqual(result['total_outstanding_amt'],
                         float(self.fr_1.outstanding_amt_local))
        self.assertEqual(result['total_frs_amt'],
                         float(self.fr_1.total_amt_local))
        self.assertEqual(result['total_intervention_amt'],
                         float(self.fr_1.intervention_amt))

    def test_get_two_frs(self):

        data = {'values': ','.join([self.fr_1.fr_number, self.fr_2.fr_number])}

        status_code, result = self.run_request(data)

        self.assertEqual(status_code, status.HTTP_200_OK)
        self.assertEqual(len(result['frs']), 2)

        # Make sure result numbers match up
        # float the Decimal sum
        self.assertEqual(
            result['total_actual_amt'],
            float(sum([self.fr_1.actual_amt_local,
                       self.fr_2.actual_amt_local])))
        self.assertEqual(
            result['total_outstanding_amt'],
            float(
                sum([
                    self.fr_1.outstanding_amt_local,
                    self.fr_2.outstanding_amt_local
                ])))
        self.assertEqual(
            result['total_frs_amt'],
            float(sum([self.fr_1.total_amt_local, self.fr_2.total_amt_local])))
        self.assertEqual(
            result['total_intervention_amt'],
            float(sum([self.fr_1.intervention_amt,
                       self.fr_2.intervention_amt])))

    def test_get_earliest_start_date_from_two_frs(self):

        data = {'values': ','.join([self.fr_1.fr_number, self.fr_2.fr_number])}

        status_code, result = self.run_request(data)

        self.assertEqual(status_code, status.HTTP_200_OK)
        self.assertEqual(len(result['frs']), 2)

        self.assertEqual(
            datetime.strptime(result['earliest_start_date'],
                              '%Y-%m-%d').date(),
            min([self.fr_1.start_date, self.fr_2.start_date]))
        self.assertEqual(
            datetime.strptime(result['latest_end_date'], '%Y-%m-%d').date(),
            max([self.fr_1.end_date, self.fr_2.end_date]))

    def test_get_earliest_start_date_from_one_fr(self):

        data = {'values': ','.join([self.fr_1.fr_number])}

        status_code, result = self.run_request(data)

        self.assertEqual(status_code, status.HTTP_200_OK)
        self.assertEqual(len(result['frs']), 1)

        self.assertEqual(
            datetime.strptime(result['earliest_start_date'],
                              '%Y-%m-%d').date(), self.fr_1.start_date)
        self.assertEqual(
            datetime.strptime(result['latest_end_date'], '%Y-%m-%d').date(),
            self.fr_1.end_date)

    def test_get_fail_with_no_values(self):
        data = {}
        status_code, result = self.run_request(data)
        self.assertEqual(status_code, status.HTTP_400_BAD_REQUEST)
        self.assertEqual(result['error'], 'Values are required')

    def test_get_fail_with_nonexistant_values(self):
        data = {'values': ','.join(['im a bad value', 'another bad value'])}
        status_code, result = self.run_request(data)
        self.assertEqual(status_code, status.HTTP_400_BAD_REQUEST)
        self.assertEqual(
            result['error'],
            'One or more of the FRs are used by another PD/SSFA '
            'or could not be found in eTools.')

    def test_get_fail_with_one_bad_value(self):
        data = {'values': ','.join(['im a bad value', self.fr_1.fr_number])}
        status_code, result = self.run_request(data)
        self.assertEqual(status_code, status.HTTP_400_BAD_REQUEST)
        self.assertEqual(
            result['error'],
            'One or more of the FRs are used by another PD/SSFA '
            'or could not be found in eTools.')

    def test_get_success_with_expired_fr(self):
        self.fr_1.end_date = timezone.now().date() - timedelta(days=1)
        self.fr_1.save()
        data = {'values': ','.join([self.fr_2.fr_number, self.fr_1.fr_number])}
        status_code, result = self.run_request(data)
        self.assertEqual(status_code, status.HTTP_200_OK)

    def test_get_fail_with_intervention_fr(self):
        self.fr_1.intervention = self.intervention
        self.fr_1.save()
        data = {'values': ','.join([self.fr_2.fr_number, self.fr_1.fr_number])}
        status_code, result = self.run_request(data)
        self.assertEqual(status_code, status.HTTP_400_BAD_REQUEST)
        self.assertEqual(
            result['error'],
            'One or more of the FRs are used by another PD/SSFA '
            'or could not be found in eTools.')

    def test_get_with_intervention_fr(self):
        self.fr_1.intervention = self.intervention
        self.fr_1.save()
        data = {
            'values': ','.join([self.fr_2.fr_number, self.fr_1.fr_number]),
            'intervention': self.intervention.id
        }
        status_code, result = self.run_request(data)
        self.assertEqual(status_code, status.HTTP_200_OK)
        self.assertEqual(len(result['frs']), 2)
        self.assertEqual(
            result['total_actual_amt'],
            float(sum([self.fr_1.actual_amt_local,
                       self.fr_2.actual_amt_local])))
        self.assertEqual(
            result['total_outstanding_amt'],
            float(
                sum([
                    self.fr_1.outstanding_amt_local,
                    self.fr_2.outstanding_amt_local
                ])))
        self.assertEqual(
            result['total_frs_amt'],
            float(sum([self.fr_1.total_amt_local, self.fr_2.total_amt_local])))
        self.assertEqual(
            result['total_intervention_amt'],
            float(sum([self.fr_1.intervention_amt,
                       self.fr_2.intervention_amt])))

    def test_frs_vendor_code_mismatch(self):
        data = {'values': ','.join([self.fr_1.fr_number, self.fr_3.fr_number])}

        status_code, result = self.run_request(data)

        self.assertEqual(status_code, status.HTTP_400_BAD_REQUEST)
        self.assertIn('FRs selected relate to various partners',
                      result['error'])

    def test_frs_partner_vendor_code_mismatch(self):
        data = {
            'values': ','.join([self.fr_3.fr_number]),
            'intervention': self.intervention.pk
        }

        status_code, result = self.run_request(data)

        self.assertEqual(status_code, status.HTTP_400_BAD_REQUEST)
        self.assertIn(
            'vendor number of the selected implementing partner in eTools does not '
            'match the vendor number entered in the FR in VISION',
            result['error'])

    def test_frs_partner_vendor_code_ok(self):
        data = {
            'values': ','.join([self.fr_1.fr_number]),
            'intervention': self.intervention.pk
        }

        status_code, result = self.run_request(data)

        self.assertEqual(status_code, status.HTTP_200_OK)

    def test_frs_currencies_match_ok(self):
        data = {'values': ','.join([self.fr_1.fr_number, self.fr_2.fr_number])}

        status_code, result = self.run_request(data)

        self.assertEqual(status_code, status.HTTP_200_OK)
        self.assertEqual(result['currencies_match'], True)
        self.assertNotEqual(result['total_intervention_amt'], 0)

    def test_frs_currencies_mismatch_ok(self):
        self.fr_2.currency = 'LBP'
        self.fr_2.save()
        data = {'values': ','.join([self.fr_1.fr_number, self.fr_2.fr_number])}

        status_code, result = self.run_request(data)

        self.assertEqual(status_code, status.HTTP_200_OK)
        self.assertEqual(result['currencies_match'], False)
        self.assertEqual(result['total_intervention_amt'], 0)
Beispiel #11
0
 def setUp(self):
     super(TestFundsReservationItemExportList, self).setUp()
     self.unicef_staff = UserFactory(is_staff=True)
     self.frs = FundsReservationHeaderFactory()
     self.item = FundsReservationItemFactory(fund_reservation=self.frs)
Beispiel #12
0
 def setUpTestData(cls):
     cls.unicef_staff = UserFactory(is_staff=True)
     cls.frs = FundsReservationHeaderFactory()
Beispiel #13
0
 def setUpTestData(cls):
     cls.fr_header = FundsReservationHeaderFactory(fr_number='23')
Beispiel #14
0
    def test_make_intervention_status_automatic_transitions_with_mixed_interventions(
            self,
            MockInterventionValid,
            mock_db_connection,
            mock_logger):
        '''Exercise _make_intervention_status_automatic_transitions() when only some interventions are valid, but
        not all of them.
        '''
        # Make some interventions that are active that ended yesterday. (The task looks for such interventions.)
        end_date = datetime.date.today() - datetime.timedelta(days=1)
        # Interventions sort by oldest last, so I make sure my list here is ordered in the same way as they'll be
        # pulled out of the database.
        interventions = [InterventionFactory(status=Intervention.ACTIVE, end=end_date, created=_make_past_datetime(i))
                         for i in range(3)]

        # Make an intervention with some associated funds reservation headers that the task should find.
        intervention = InterventionFactory(status=Intervention.ENDED)
        for i in range(3):
            FundsReservationHeaderFactory(intervention=intervention, outstanding_amt=Decimal(0.00),
                                          intervention_amt=_make_decimal(i),
                                          actual_amt=_make_decimal(i), total_amt=_make_decimal(i))
        interventions.append(intervention)

        # Create a few items that should be ignored. If they're not ignored, this test will fail.
        # Ignored because of end date
        InterventionFactory(status=Intervention.ACTIVE, end=datetime.date.today() + datetime.timedelta(days=2))
        # Ignored because of status
        InterventionFactory(status=Intervention.IMPLEMENTED, end=end_date)
        # Ignored because funds total outstanding != 0
        intervention = InterventionFactory(status=Intervention.ENDED, end=end_date)
        for i in range(3):
            FundsReservationHeaderFactory(intervention=intervention, outstanding_amt=Decimal(i),
                                          intervention_amt=_make_decimal(i),
                                          actual_amt=_make_decimal(i), total_amt=_make_decimal(i))
        # Ignored because funds totals don't match
        intervention = InterventionFactory(status=Intervention.ENDED, end=end_date)
        for i in range(3):
            FundsReservationHeaderFactory(intervention=intervention, outstanding_amt=Decimal(0.00),
                                          intervention_amt=_make_decimal(i),
                                          actual_amt=_make_decimal(i + 1), total_amt=_make_decimal(i))

        def mock_intervention_valid_class_side_effect(*args, **kwargs):
            '''Side effect for my mock InterventionValid() that gets called each time my mock InterventionValid() class
            is instantiated. It gives me the opportunity to modify one of the agreements passed.
            '''
            if args and hasattr(args[0], 'id'):
                if args[0].id == interventions[1].id:
                    # We'll pretend the second intervention made a status transition
                    args[0].status = Intervention.CLOSED
                    args[0].save()
            # else:
                # This is a test failure; we always expect (mock) InterventionValid to be called (instantiated) with
                # an agreement passed as the first arg. However the args with which InterventionValid is called are
                # explicitly checked in this test so we don't need to react here.

            return mock.DEFAULT

        # (Mock) InterventionValid() returns a (mock) validator; set up is_valid to return False for the first
        # intervention and True for the others.
        mock_validator = mock.Mock(spec=['is_valid'], name='mock_validator')
        type(mock_validator).is_valid = mock.PropertyMock(side_effect=[False, True, True, True])

        MockInterventionValid.side_effect = mock_intervention_valid_class_side_effect
        MockInterventionValid.return_value = mock_validator

        # I'm done mocking, it's time to call the function.
        partners.tasks._make_intervention_status_automatic_transitions(self.country_name)

        expected_call_args = [((intervention_, ), {'user': self.admin_user, 'disable_rigid_check': True})
                              for intervention_ in interventions]
        self._assertCalls(MockInterventionValid, expected_call_args)

        # Verify logged messages.
        expected_call_args = [
            (('Starting intervention auto status transition for country {}'.format(self.country_name), ), {}),
            (('Total interventions 4', ), {}),
            (('Transitioned interventions 1 ', ), {})]
        self._assertCalls(mock_logger.info, expected_call_args)

        expected_call_args = [
            (('Bad interventions 1', ), {}),
            (('Bad interventions ids: {}'.format(interventions[0].id), ), {}),
        ]
        self._assertCalls(mock_logger.error, expected_call_args)
Beispiel #15
0
class TestFundReservationsSynchronizer(BaseTenantTestCase):
    maxDiff = None

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

    def setUp(self):
        self.data = {
            "VENDOR_CODE": "Code123",
            "FR_NUMBER": "123",
            "FR_DOC_DATE": "14-Jan-15",
            "FR_TYPE": "Type",
            "CURRENCY": "USD",
            "FR_DOCUMENT_TEXT": "Random Text",
            "FR_START_DATE": "13-Jan-15",
            "FR_END_DATE": "20-Dec-15",
            "LINE_ITEM": "987",
            "WBS_ELEMENT": "WBS",
            "GRANT_NBR": "456",
            "FUND": "Fund",
            "OVERALL_AMOUNT": "20.00",
            "OVERALL_AMOUNT_DC": "5.00",
            "FR_LINE_ITEM_TEXT": "Line item text",
            "DUE_DATE": "18-May-15",
            "FR_OVERALL_AMOUNT": "15.00",
            "CURRENT_FR_AMOUNT": "17.00",
            "ACTUAL_CASH_TRANSFER": "18.00",
            "OUTSTANDING_DCT": "19.00",
            "FR_OVERALL_AMOUNT_DC": "12.00",
            "ACTUAL_CASH_TRANSFER_DC": "13.00",
            "OUTSTANDING_DCT_DC": "14.00",
        }
        self.expected_headers = {
            "vendor_code": "Code123",
            "fr_number": "123",
            "document_date": datetime.date(2015, 1, 14),
            "fr_type": "Type",
            "currency": "USD",
            "document_text": "Random Text",
            "start_date": datetime.date(2015, 1, 13),
            "end_date": datetime.date(2015, 12, 20),
            "total_amt": "15.00",
            # "total_amt_local": "12.00",
            "intervention_amt": "17.00",
            "actual_amt": "18.00",
            # "actual_amt_local": "13.00",
            "outstanding_amt": "19.00",
            # "outstanding_amt_local": "14.00",
        }
        self.expected_line_item = {
            "line_item": "987",
            "fr_number": "123",
            "wbs": "WBS",
            "grant_number": "456",
            "fund": "Fund",
            "overall_amount": "20.00",
            "overall_amount_dc": "5.00",
            "due_date": datetime.date(2015, 5, 18),
            "line_item_text": "Line item text",
            "fr_ref_number": "123-987"
        }
        self.fund_item = FundsReservationItemFactory(
            fr_ref_number="123-987",
            line_item=self.data["LINE_ITEM"],
            wbs=self.data["WBS_ELEMENT"],
            grant_number=self.data["GRANT_NBR"],
            fund=self.data["FUND"],
            overall_amount=self.data["OVERALL_AMOUNT"],
            overall_amount_dc=self.data["OVERALL_AMOUNT_DC"],
            due_date=datetime.date(2015, 5, 18),
            line_item_text=self.data["FR_LINE_ITEM_TEXT"],
        )
        self.fund_header = FundsReservationHeaderFactory(
            vendor_code=self.data["VENDOR_CODE"],
            fr_number=self.data["FR_NUMBER"],
            document_date=datetime.date(2015, 1, 14),
            fr_type=self.data["FR_TYPE"],
            currency=self.data["CURRENCY"],
            document_text=self.data["FR_DOCUMENT_TEXT"],
            intervention_amt=self.data["CURRENT_FR_AMOUNT"],
            total_amt=self.data["FR_OVERALL_AMOUNT"],
            actual_amt=self.data["ACTUAL_CASH_TRANSFER"],
            outstanding_amt=self.data["OUTSTANDING_DCT"],
            outstanding_amt_local=self.data["OUTSTANDING_DCT_DC"],
            start_date=datetime.date(2015, 1, 13),
            end_date=datetime.date(2015, 12, 20),
        )
        self.adapter = adapter.FundReservationsSynchronizer(self.country)

    def test_init(self):
        a = adapter.FundReservationsSynchronizer(self.country)
        self.assertEqual(a.header_records, {})
        self.assertEqual(a.item_records, {})
        self.assertEqual(a.fr_headers, {})

    def test_convert_records(self):
        self.assertEqual(
            self.adapter._convert_records(json.dumps([self.data])),
            [self.data])

    def test_filter_records_no_overall_amount(self):
        """If no overall amount then ignore record"""
        self.data["OVERALL_AMOUNT"] = ""
        records = {"ROWSET": {"ROW": [self.data]}}
        response = self.adapter._filter_records(records)
        self.assertEqual(response, [])

    def test_filter_records_no_fr_number(self):
        """If no fr number then ignore record"""
        self.data["FR_NUMBER"] = ""
        records = {"ROWSET": {"ROW": [self.data]}}
        response = self.adapter._filter_records(records)
        self.assertEqual(response, [])

    def test_filter_records(self):
        """If have both overall number and fr number then keep record"""
        records = {"ROWSET": {"ROW": [self.data]}}
        response = self.adapter._filter_records(records)
        self.assertEqual(response, [self.data])

    def test_get_value_for_field_date(self):
        """If a set field (date) then convert to datetime date type"""
        fields = ["start_date", "end_date", "document_date", "due_date"]
        for field in fields:
            response = self.adapter.get_value_for_field(field, "15-Jan-14")
            self.assertEqual(response, datetime.date(2014, 1, 15))

    def test_get_value_for_field(self):
        """If NOT a set field (date) then return value"""
        response = self.adapter.get_value_for_field("random", "val")
        self.assertEqual(response, "val")

    def test_get_fr_item_number(self):
        response = self.adapter.get_fr_item_number(self.data)
        self.assertEqual(response, "123-987")

    def test_map_header_from_record(self):
        response = self.adapter.map_header_from_record(self.data)
        self.assertEqual(response, self.expected_headers)

    def test_map_line_item_record(self):
        response = self.adapter.map_line_item_record(self.data)
        self.assertEqual(response, self.expected_line_item)

    def test_set_mapping(self):
        self.assertEqual(self.adapter.header_records, {})
        self.assertEqual(self.adapter.item_records, {})
        self.adapter.set_mapping([self.data])
        self.assertEqual(self.adapter.header_records,
                         {"123": self.expected_headers})
        self.assertEqual(self.adapter.item_records,
                         {"123-987": self.expected_line_item})

    def test_equal_fields_decimal(self):
        """If field is amt field then do comp_decimal comparison"""
        self.assertTrue(
            self.adapter.equal_fields("total_amt", "20.00", "20.00"))
        self.assertFalse(
            self.adapter.equal_fields("total_amt", "20.00", "20.01"))

    def test_equal_fields_line_item(self):
        """If field is line item then convert obj field to str
        prior to comparison
        """
        self.assertTrue(self.adapter.equal_fields("line_item", 20, "20"))
        self.assertFalse(self.adapter.equal_fields("line_item", 21, "22"))

    def test_equal_fields(self):
        """If field is not special do normal comparison"""
        self.assertTrue(self.adapter.equal_fields("fr_number", "123", "123"))
        self.assertFalse(self.adapter.equal_fields("fr_number", "124", "123"))

    def test_update_object(self):
        """Check that if a value does not match object then return True"""
        self.fund_item.fr_ref_number = "321-123",
        record = self.adapter.map_line_item_record(self.data)
        del record["fr_number"]
        self.assertTrue(self.adapter.update_obj(self.fund_item, record))
        self.assertEqual(self.fund_item.fr_ref_number, "123-987")

    def test_update_object_no_change(self):
        """Check that if all values match object then return False"""
        record = self.adapter.map_line_item_record(self.data)
        del record["fr_number"]
        self.assertFalse(self.adapter.update_obj(self.fund_item, record))

    def test_header_sync_update(self):
        """Check that FundsReservationHeader record updated
        if values differ
        """
        self.fund_header.vendor_code = "Code321"
        self.fund_header.save()
        self.adapter.set_mapping([self.data])
        updated, to_create = self.adapter.header_sync()
        self.assertEqual(updated, 1)
        self.assertEqual(to_create, 0)
        fund_header_updated = FundsReservationHeader.objects.get(
            pk=self.fund_header.pk)
        self.assertEqual(fund_header_updated.vendor_code,
                         self.data["VENDOR_CODE"])

    def test_header_sync_create(self):
        """Check that FundsReservationHeader record created
        if fr_number does not exist
        """
        self.data["FR_NUMBER"] = "333"
        fund_qs = FundsReservationHeader.objects.filter(fr_number="333")
        self.assertFalse(fund_qs.exists())
        self.adapter.set_mapping([self.data])
        updated, to_create = self.adapter.header_sync()
        self.assertEqual(updated, 0)
        self.assertEqual(to_create, 1)
        self.assertTrue(fund_qs.exists())

    def test_li_sync_update(self):
        """Check that FundsReservationItem record updated
        if values differ
        """
        self.fund_item.overall_amount = "30.00"
        self.fund_item.save()
        self.adapter.set_mapping([self.data])
        updated, to_create = self.adapter.li_sync()
        self.assertEqual(updated, 1)
        self.assertEqual(to_create, 0)
        fund_item_updated = FundsReservationItem.objects.get(
            pk=self.fund_item.pk)
        self.assertEqual(fund_item_updated.overall_amount,
                         Decimal(self.data["OVERALL_AMOUNT"]))

    def test_li_sync_create(self):
        """Check that FundsReservationItem record created
        if fr_ref_number does not exist
        """
        self.data["LINE_ITEM"] = "333"
        fund_qs = FundsReservationItem.objects.filter(fr_ref_number="123-333")
        self.assertFalse(fund_qs.exists())
        self.adapter.set_mapping([self.data])
        self.adapter.map_header_objects([self.fund_header])
        updated, to_create = self.adapter.li_sync()
        self.assertEqual(updated, 0)
        self.assertEqual(to_create, 1)
        self.assertTrue(fund_qs.exists())

    def test_save_records(self):
        self.data["LINE_ITEM"] = "333"
        response = self.adapter._save_records({"ROWSET": {"ROW": [self.data]}})
        self.assertEqual(response, 1)
Beispiel #16
0
def setup_intervention_test_data(test_case,
                                 include_results_and_indicators=False):
    today = datetime.date.today()
    test_case.unicef_staff = UserFactory(is_staff=True)
    test_case.partnership_manager_user = UserFactory(is_staff=True)
    test_case.partnership_manager_user.groups.add(GroupFactory())
    test_case.partner = PartnerFactory(name='Partner 1', vendor_number="VP1")
    test_case.partner1 = PartnerFactory(name='Partner 2')
    test_case.agreement = AgreementFactory(
        partner=test_case.partner, signed_by_unicef_date=datetime.date.today())

    test_case.active_agreement = AgreementFactory(
        partner=test_case.partner1,
        status='active',
        signed_by_unicef_date=datetime.date.today(),
        signed_by_partner_date=datetime.date.today())

    test_case.intervention = InterventionFactory(agreement=test_case.agreement,
                                                 title='Intervention 1')
    test_case.intervention_2 = InterventionFactory(
        agreement=test_case.agreement,
        title='Intervention 2',
        document_type=Intervention.PD,
    )
    test_case.active_intervention = InterventionFactory(
        agreement=test_case.active_agreement,
        title='Active Intervention',
        document_type=Intervention.PD,
        start=today - datetime.timedelta(days=1),
        end=today + datetime.timedelta(days=90),
        status='active',
        signed_by_unicef_date=today - datetime.timedelta(days=1),
        signed_by_partner_date=today - datetime.timedelta(days=1),
        unicef_signatory=test_case.unicef_staff,
        partner_authorized_officer_signatory=test_case.partner1.staff_members.
        all().first())

    test_case.result_type = ResultType.objects.get_or_create(
        name=ResultType.OUTPUT)[0]
    test_case.result = ResultFactory(result_type=test_case.result_type)

    test_case.partnership_budget = InterventionBudget.objects.create(
        intervention=test_case.intervention,
        unicef_cash=10,
        unicef_cash_local=100,
        partner_contribution=20,
        partner_contribution_local=200,
        in_kind_amount_local=10,
    )

    # set up two frs not connected to any interventions
    test_case.fr_1 = FundsReservationHeaderFactory(intervention=None,
                                                   currency='USD')
    test_case.fr_2 = FundsReservationHeaderFactory(intervention=None,
                                                   currency='USD')

    if include_results_and_indicators:
        # setup additional inicator/results
        test_case.result = ResultFactory(name='A Result')
        test_case.result_link = InterventionResultLink.objects.create(
            intervention=test_case.active_intervention,
            cp_output=test_case.result)
        test_case.lower_result = LowerResult.objects.create(
            result_link=test_case.result_link, name='Lower Result 1')
        test_case.indicator_blueprint = IndicatorBlueprint.objects.create(
            title='The Blueprint')
        test_case.applied_indicator = AppliedIndicator.objects.create(
            indicator=test_case.indicator_blueprint,
            lower_result=test_case.lower_result,
        )
        test_case.applied_indicator.locations.add(
            LocationFactory(name='A Location',
                            gateway=GatewayTypeFactory(name='A Gateway'),
                            p_code='a-p-code'))
        test_case.disaggregation = test_case.applied_indicator.disaggregation.create(
            name='A Disaggregation')
Beispiel #17
0
 def test_relation(self):
     intervention = InterventionFactory()
     fr = FundsReservationHeaderFactory(intervention=intervention)
     obj_dict = utils.create_dict_with_relations(intervention)
     self.assertEqual(obj_dict["frs"], [fr.pk])
Beispiel #18
0
 def test_funds_reservation_header(self):
     funds_reservation_header = FundsReservationHeaderFactory.build(fr_number=u'R\xe4dda Barnen')
     self.assertEqual(six.text_type(funds_reservation_header), u'R\xe4dda Barnen')
Beispiel #19
0
 def setUp(self):
     self.data = {
         "VENDOR_CODE": "Code123",
         "FR_NUMBER": "123",
         "FR_DOC_DATE": "14-Jan-15",
         "FR_TYPE": "Type",
         "CURRENCY": "USD",
         "FR_DOCUMENT_TEXT": "Random Text",
         "FR_START_DATE": "13-Jan-15",
         "FR_END_DATE": "20-Dec-15",
         "LINE_ITEM": "987",
         "WBS_ELEMENT": "WBS",
         "GRANT_NBR": "456",
         "FUND": "Fund",
         "OVERALL_AMOUNT": "20.00",
         "OVERALL_AMOUNT_DC": "5.00",
         "FR_LINE_ITEM_TEXT": "Line item text",
         "DUE_DATE": "18-May-15",
         "FR_OVERALL_AMOUNT": "15.00",
         "CURRENT_FR_AMOUNT": "17.00",
         "ACTUAL_CASH_TRANSFER": "18.00",
         "OUTSTANDING_DCT": "19.00",
         "FR_OVERALL_AMOUNT_DC": "12.00",
         "ACTUAL_CASH_TRANSFER_DC": "13.00",
         "OUTSTANDING_DCT_DC": "14.00",
     }
     self.expected_headers = {
         "vendor_code": "Code123",
         "fr_number": "123",
         "document_date": datetime.date(2015, 1, 14),
         "fr_type": "Type",
         "currency": "USD",
         "document_text": "Random Text",
         "start_date": datetime.date(2015, 1, 13),
         "end_date": datetime.date(2015, 12, 20),
         "total_amt": "15.00",
         # "total_amt_local": "12.00",
         "intervention_amt": "17.00",
         "actual_amt": "18.00",
         # "actual_amt_local": "13.00",
         "outstanding_amt": "19.00",
         # "outstanding_amt_local": "14.00",
     }
     self.expected_line_item = {
         "line_item": "987",
         "fr_number": "123",
         "wbs": "WBS",
         "grant_number": "456",
         "fund": "Fund",
         "overall_amount": "20.00",
         "overall_amount_dc": "5.00",
         "due_date": datetime.date(2015, 5, 18),
         "line_item_text": "Line item text",
         "fr_ref_number": "123-987"
     }
     self.fund_item = FundsReservationItemFactory(
         fr_ref_number="123-987",
         line_item=self.data["LINE_ITEM"],
         wbs=self.data["WBS_ELEMENT"],
         grant_number=self.data["GRANT_NBR"],
         fund=self.data["FUND"],
         overall_amount=self.data["OVERALL_AMOUNT"],
         overall_amount_dc=self.data["OVERALL_AMOUNT_DC"],
         due_date=datetime.date(2015, 5, 18),
         line_item_text=self.data["FR_LINE_ITEM_TEXT"],
     )
     self.fund_header = FundsReservationHeaderFactory(
         vendor_code=self.data["VENDOR_CODE"],
         fr_number=self.data["FR_NUMBER"],
         document_date=datetime.date(2015, 1, 14),
         fr_type=self.data["FR_TYPE"],
         currency=self.data["CURRENCY"],
         document_text=self.data["FR_DOCUMENT_TEXT"],
         intervention_amt=self.data["CURRENT_FR_AMOUNT"],
         total_amt=self.data["FR_OVERALL_AMOUNT"],
         actual_amt=self.data["ACTUAL_CASH_TRANSFER"],
         outstanding_amt=self.data["OUTSTANDING_DCT"],
         outstanding_amt_local=self.data["OUTSTANDING_DCT_DC"],
         start_date=datetime.date(2015, 1, 13),
         end_date=datetime.date(2015, 12, 20),
     )
     self.adapter = adapter.FundReservationsSynchronizer(self.country)
Beispiel #20
0
    def test_make_intervention_status_automatic_transitions_with_valid_interventions(
            self,
            MockInterventionValid,
            mock_db_connection,
            mock_logger):
        '''Exercise _make_intervention_status_automatic_transitions() when all interventions are valid'''
        # Make some interventions that are active that ended yesterday. (The task looks for such interventions.)
        end_date = datetime.date.today() - datetime.timedelta(days=1)
        # Interventions sort by oldest last, so I make sure my list here is ordered in the same way as they'll be
        # pulled out of the database.
        interventions = [InterventionFactory(status=Intervention.ACTIVE, end=end_date, created=_make_past_datetime(i))
                         for i in range(3)]

        # Make an intervention with some associated funds reservation headers that the task should find.
        intervention = InterventionFactory(status=Intervention.ENDED)
        for i in range(3):
            FundsReservationHeaderFactory(intervention=intervention, outstanding_amt=Decimal(0.00),
                                          intervention_amt=_make_decimal(i),
                                          actual_amt=_make_decimal(i), total_amt=_make_decimal(i))
        interventions.append(intervention)

        # Create a few items that should be ignored. If they're not ignored, this test will fail.
        # Ignored because of end date
        InterventionFactory(status=Intervention.ACTIVE, end=datetime.date.today() + datetime.timedelta(days=2))
        # Ignored because of status
        InterventionFactory(status=Intervention.IMPLEMENTED, end=end_date)
        # Ignored because funds total outstanding != 0
        intervention = InterventionFactory(status=Intervention.ENDED, end=end_date)
        for i in range(3):
            FundsReservationHeaderFactory(intervention=intervention, outstanding_amt=Decimal(i),
                                          intervention_amt=_make_decimal(i),
                                          actual_amt=_make_decimal(i), total_amt=_make_decimal(i))

        # Ignored because funds totals don't match
        intervention = InterventionFactory(status=Intervention.ENDED, end=end_date)
        for i in range(3):
            FundsReservationHeaderFactory(intervention=intervention, outstanding_amt=Decimal(0.00),
                                          intervention_amt=_make_decimal(i),
                                          actual_amt=_make_decimal(i + 1), total_amt=_make_decimal(i))

        # Mock InterventionValid() to always return True.
        mock_validator = mock.Mock(spec=['is_valid'])
        mock_validator.is_valid = True
        MockInterventionValid.return_value = mock_validator

        # I'm done mocking, it's time to call the function.
        partners.tasks._make_intervention_status_automatic_transitions(self.country_name)

        expected_call_args = [((intervention_, ), {'user': self.admin_user, 'disable_rigid_check': True})
                              for intervention_ in interventions]
        self._assertCalls(MockInterventionValid, expected_call_args)

        # Verify logged messages.
        expected_call_args = [
            (('Starting intervention auto status transition for country {}'.format(self.country_name), ), {}),
            (('Total interventions 4', ), {}),
            (('Transitioned interventions 0 ', ), {})]
        self._assertCalls(mock_logger.info, expected_call_args)

        expected_call_args = [
            (('Bad interventions 0', ), {}),
            (('Bad interventions ids: ', ), {}),
        ]
        self._assertCalls(mock_logger.error, expected_call_args)