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", "ACTUAL_CASH_TRANSFER_DC": "13.00", "OUTSTANDING_DCT_DC": "14.00", "MULTI_CURR_FLAG": "N" } 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", "intervention_amt": "17.00", "actual_amt": "18.00", "actual_amt_local": "13.00", "outstanding_amt": "19.00", "outstanding_amt_local": "14.00", "multi_curr_flag": False } self.expected_line_item = { "line_item": "987", "fr_number": "123", "donor": None, "donor_code": None, "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 = synchronizers.FundReservationsSynchronizer(self.country) def test_init(self): a = synchronizers.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({"ROWSET": {"ROW": [self.data]}})), [self.data] ) def test_update_fr_totals_no_fr_items__overall_amount_dc(self): # Test for https://app.clubhouse.io/unicefetools/story/4978/fr-handler-none-values-failing-on-frs # We were throwing an exception because we expected Sum() to always # return a value, but if there's nothing to sum, it returns None. self.adapter.update_fr_totals() 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 = [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([self.data]) self.assertEqual(response, 2)
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", "ACTUAL_CASH_TRANSFER_DC": "13.00", "OUTSTANDING_DCT_DC": "14.00", "MULTI_CURR_FLAG": "N" } 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", "intervention_amt": "17.00", "actual_amt": "18.00", "actual_amt_local": "13.00", "outstanding_amt": "19.00", "outstanding_amt_local": "14.00", "multi_curr_flag": False } self.expected_line_item = { "line_item": "987", "fr_number": "123", "donor": None, "donor_code": None, "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({"ROWSET": { "ROW": [self.data] }})), [self.data]) def test_update_fr_totals_no_fr_items__overall_amount_dc(self): # Test for https://app.clubhouse.io/unicefetools/story/4978/fr-handler-none-values-failing-on-frs # We were throwing an exception because we expected Sum() to always # return a value, but if there's nothing to sum, it returns None. self.adapter.update_fr_totals() 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 = [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([self.data]) self.assertEqual(response, 2)
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'], 'The FR another bad value, im a bad value could not be found on eTools') def test_get_fail_with_intervention_id(self): other_intervention = InterventionFactory() fth_value = 'im a bad value' FundsReservationHeaderFactory(fr_number=fth_value, intervention=other_intervention, currency="USD") data = {'values': ','.join([fth_value, self.fr_1.fr_number]), 'intervention': self.intervention.pk} status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(result['error'], 'FR #{} is already being used by PD/SSFA ref [{}]'.format(fth_value, other_intervention)) 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_grants_filter(self): """Check that filtering on grant returns expected result""" grant_number = "G123" grant = GrantFactory(name=grant_number) FundsReservationItemFactory( fund_reservation=self.fr_1, grant_number=grant_number ) data = { "values": self.fr_1.fr_number, "grants": grant.pk, } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_200_OK) self.assertEqual(len(result['frs']), 1) def test_grants_many_filter(self): """Check that filtering on multiple grants returns expected result""" grant_number_1 = "G123" grant_number_2 = "G124" grant_1 = GrantFactory(name=grant_number_1) grant_2 = GrantFactory(name=grant_number_2) FundsReservationItemFactory( fund_reservation=self.fr_1, grant_number=grant_number_1 ) FundsReservationItemFactory( fund_reservation=self.fr_2, grant_number=grant_number_2 ) FundsReservationHeaderFactory() data = { "values": ",".join([self.fr_1.fr_number, self.fr_2.fr_number]), "grants": ",".join([str(grant_1.pk), str(grant_2.pk)]), } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_200_OK) self.assertEqual(len(result['frs']), 2) def test_grants_filter_invalid(self): """Check that filtering on invalid grant returns 400""" grant_number = "G123" GrantFactory(name=grant_number) FundsReservationItemFactory( fund_reservation=self.fr_1, grant_number=grant_number ) data = { "values": self.fr_1.fr_number, "grants": "404", } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_400_BAD_REQUEST) self.assertIn( 'please make sure to select FRs that relate to the PD/SSFA Partner', result['error'] ) def test_donors_filter(self): """Check that filtering on donor returns expected result""" donor = DonorFactory() grant_number = "G123" GrantFactory( donor=donor, name=grant_number, ) FundsReservationItemFactory( fund_reservation=self.fr_1, grant_number=grant_number ) data = { "values": self.fr_1.fr_number, "donors": donor.pk, } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_200_OK) self.assertEqual(len(result['frs']), 1) def test_donors_many_filter(self): """Check that filtering on multiple donors returns expected result""" donor_1 = DonorFactory() donor_2 = DonorFactory() grant_number_1 = "G123" grant_number_2 = "G124" GrantFactory( donor=donor_1, name=grant_number_1, ) GrantFactory( donor=donor_2, name=grant_number_2, ) FundsReservationItemFactory( fund_reservation=self.fr_1, grant_number=grant_number_1 ) FundsReservationItemFactory( fund_reservation=self.fr_2, grant_number=grant_number_2 ) FundsReservationHeaderFactory() data = { "values": ",".join([self.fr_1.fr_number, self.fr_2.fr_number]), "donors": ",".join([str(donor_1.pk), str(donor_2.pk)]), } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_200_OK) self.assertEqual(len(result['frs']), 2) def test_donors_filter_invalid(self): """Check that filtering on invalid donors returns 400""" donor = DonorFactory() grant_number = "G123" GrantFactory( donor=donor, name=grant_number, ) FundsReservationItemFactory( fund_reservation=self.fr_1, grant_number=grant_number ) data = { "values": self.fr_1.fr_number, "donors": "404", } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_400_BAD_REQUEST) self.assertIn( 'please make sure to select FRs that relate to the PD/SSFA Partner', result['error'] ) def test_grant_donors_mismatch(self): """Check that filtering on donors and grant not related to donor, returns 400 """ donor = DonorFactory() GrantFactory( donor=donor, ) grant_number = "G123" grant = GrantFactory( name=grant_number, ) FundsReservationItemFactory( fund_reservation=self.fr_1, grant_number=grant_number ) data = { "values": self.fr_1.fr_number, "grants": grant.pk, "donors": donor.pk, } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_400_BAD_REQUEST) self.assertIn( 'please make sure to select FRs that relate to the PD/SSFA Partner', result['error'] ) 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)
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'], 'The FR another bad value, im a bad value could not be found on eTools' ) def test_get_fail_with_intervention_id(self): other_intervention = InterventionFactory() fth_value = 'im a bad value' FundsReservationHeaderFactory(fr_number=fth_value, intervention=other_intervention, currency="USD") data = { 'values': ','.join([fth_value, self.fr_1.fr_number]), 'intervention': self.intervention.pk } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual( result['error'], 'FR #{} is already being used by PD/SSFA ref [{}]'.format( fth_value, other_intervention)) 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_grants_filter(self): """Check that filtering on grant returns expected result""" grant_number = "G123" grant = GrantFactory(name=grant_number) FundsReservationItemFactory(fund_reservation=self.fr_1, grant_number=grant_number) data = { "values": self.fr_1.fr_number, "grants": grant.pk, } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_200_OK) self.assertEqual(len(result['frs']), 1) def test_grants_many_filter(self): """Check that filtering on multiple grants returns expected result""" grant_number_1 = "G123" grant_number_2 = "G124" grant_1 = GrantFactory(name=grant_number_1) grant_2 = GrantFactory(name=grant_number_2) FundsReservationItemFactory(fund_reservation=self.fr_1, grant_number=grant_number_1) FundsReservationItemFactory(fund_reservation=self.fr_2, grant_number=grant_number_2) FundsReservationHeaderFactory() data = { "values": ",".join([self.fr_1.fr_number, self.fr_2.fr_number]), "grants": ",".join([str(grant_1.pk), str(grant_2.pk)]), } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_200_OK) self.assertEqual(len(result['frs']), 2) def test_grants_filter_invalid(self): """Check that filtering on invalid grant returns 400""" grant_number = "G123" GrantFactory(name=grant_number) FundsReservationItemFactory(fund_reservation=self.fr_1, grant_number=grant_number) data = { "values": self.fr_1.fr_number, "grants": "404", } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_400_BAD_REQUEST) self.assertIn( 'please make sure to select FRs that relate to the PD/SSFA Partner', result['error']) def test_donors_filter(self): """Check that filtering on donor returns expected result""" donor = DonorFactory() grant_number = "G123" GrantFactory( donor=donor, name=grant_number, ) FundsReservationItemFactory(fund_reservation=self.fr_1, grant_number=grant_number) data = { "values": self.fr_1.fr_number, "donors": donor.pk, } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_200_OK) self.assertEqual(len(result['frs']), 1) def test_donors_many_filter(self): """Check that filtering on multiple donors returns expected result""" donor_1 = DonorFactory() donor_2 = DonorFactory() grant_number_1 = "G123" grant_number_2 = "G124" GrantFactory( donor=donor_1, name=grant_number_1, ) GrantFactory( donor=donor_2, name=grant_number_2, ) FundsReservationItemFactory(fund_reservation=self.fr_1, grant_number=grant_number_1) FundsReservationItemFactory(fund_reservation=self.fr_2, grant_number=grant_number_2) FundsReservationHeaderFactory() data = { "values": ",".join([self.fr_1.fr_number, self.fr_2.fr_number]), "donors": ",".join([str(donor_1.pk), str(donor_2.pk)]), } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_200_OK) self.assertEqual(len(result['frs']), 2) def test_donors_filter_invalid(self): """Check that filtering on invalid donors returns 400""" donor = DonorFactory() grant_number = "G123" GrantFactory( donor=donor, name=grant_number, ) FundsReservationItemFactory(fund_reservation=self.fr_1, grant_number=grant_number) data = { "values": self.fr_1.fr_number, "donors": "404", } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_400_BAD_REQUEST) self.assertIn( 'please make sure to select FRs that relate to the PD/SSFA Partner', result['error']) def test_grant_donors_mismatch(self): """Check that filtering on donors and grant not related to donor, returns 400 """ donor = DonorFactory() GrantFactory(donor=donor, ) grant_number = "G123" grant = GrantFactory(name=grant_number, ) FundsReservationItemFactory(fund_reservation=self.fr_1, grant_number=grant_number) data = { "values": self.fr_1.fr_number, "grants": grant.pk, "donors": donor.pk, } status_code, result = self.run_request(data) self.assertEqual(status_code, status.HTTP_400_BAD_REQUEST) self.assertIn( 'please make sure to select FRs that relate to the PD/SSFA Partner', result['error']) 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)