def test_simple_collect_multiple_donations(simple_match_funds): """ test allocations status set to COLLECTED test overall status set to COLLECTED test match_fund total balance (occurs when reservations are allocated) """ fund_matcher = FundMatcher(simple_match_funds) donation_1 = Donation("donation_1", 110) donation_2 = Donation("donation_2", 50) fund_matcher.reserve_funds(donation_1) fund_matcher.reserve_funds(donation_2) fund_matcher.collect_donation(donation_1.donation_id) fund_matcher.collect_donation(donation_2.donation_id) state = fund_matcher.allocation_state allocations_1 = state[donation_1.donation_id]['allocations'] allocations_2 = state[donation_2.donation_id]['allocations'] for a in allocations_1: assert a.status == COLLECTED for a in allocations_2: assert a.status == COLLECTED assert state[donation_1.donation_id]['overall_status'] == COLLECTED assert state[donation_2.donation_id]['overall_status'] == COLLECTED match_funds = fund_matcher.get_match_funds_as_list() assert match_funds[0].total_amount == 0 assert match_funds[1].total_amount == 40
def test_reserve_funds_donation_balance_unmatched(simple_match_funds): """ test allocations are RESERVED test allocations are RESERVED if match_funds exhausted test original_donation & donation_balance_unmatched """ fund_matcher = FundMatcher(simple_match_funds) donation_1 = Donation("donation_1", 150) donation_2 = Donation("donation_2", 250) fund_matcher.reserve_funds(donation_1) fund_matcher.reserve_funds(donation_2) state = fund_matcher.allocation_state allocations_1 = state[donation_1.donation_id]['allocations'] allocations_2 = state[donation_2.donation_id]['allocations'] for a in allocations_1: assert a.status == RESERVED for a in allocations_2: assert a.status == RESERVED assert state[donation_1.donation_id]['original_donation'] == 150 assert state[donation_1.donation_id]['donation_balance_unmatched'] == 0 assert state[donation_2.donation_id]['original_donation'] == 250 assert state[donation_2.donation_id]['donation_balance_unmatched'] == 100
def test_status_on_reserved_funds(simple_match_funds): """ test allocations are RESERVED test allocations are RESERVED if match_funds exhausted """ fund_matcher = FundMatcher(simple_match_funds) donation_1 = Donation("donation_1", 110) donation_2 = Donation("donation_2", 140) donation_3 = Donation("donation_3", 180) fund_matcher.reserve_funds(donation_1) fund_matcher.reserve_funds(donation_2) fund_matcher.reserve_funds(donation_3) state = fund_matcher.allocation_state allocations_1 = state[donation_1.donation_id]['allocations'] allocations_2 = state[donation_2.donation_id]['allocations'] allocations_3 = state[donation_2.donation_id]['allocations'] for a in allocations_1: assert a.status == RESERVED for a in allocations_2: assert a.status == RESERVED for a in allocations_3: assert a.status == RESERVED
def test_reserve_full_match_multiple_donations(simple_match_funds): """ reservation test, donations allocated to 2 fund test order of match_fund allocation test first fund is exhausted test second fund remaining total_amount ratio defaults to 1:1 """ fund_matcher = FundMatcher(simple_match_funds) donation_1 = Donation("donation_1", 110) donation_2 = Donation("donation_2", 50) fund_matcher.reserve_funds(donation_1) fund_matcher.reserve_funds(donation_2) state = fund_matcher.allocation_state allocations_1 = state[donation_1.donation_id]['allocations'] allocations_2 = state[donation_2.donation_id]['allocations'] match_funds = fund_matcher.get_match_funds_as_list() assert (len(allocations_1) == 2) assert (len(allocations_2) == 1) assert (match_funds[0].total_amount == 0) assert (match_funds[1].total_amount == 40)
def test_simple_collect_donation_wrong_id(simple_match_funds): """ Tests collection donation_id is valid """ fund_matcher = FundMatcher(simple_match_funds) donation = Donation("donation_1", 50) fund_matcher.reserve_funds(donation) with pytest.raises(BadRequestException): fund_matcher.collect_donation("donation_10")
def test_expire_donation_on_invalid_status(simple_match_funds): """ test allocation state that is set to COLLECTED is not EXPIRED """ fund_matcher = FundMatcher(simple_match_funds) donation = Donation("donation_1", 50) fund_matcher.reserve_funds(donation) fund_matcher.collect_donation(donation.donation_id) with pytest.raises(BadRequestException): fund_matcher.expire_donation(donation.donation_id)
def test_donation_is_valid(): """ Test to see if donation objects are valid amount is float amount is > MIN_DONATION amount is < MAX_DONATION """ donation_id = uuid.uuid4().hex amount = 100.00 donation = Donation(donation_id, amount) assert isinstance(donation.amount, float)
def test_simple_collect_donation(simple_match_funds): """ test allocation status set to COLLECTED """ fund_matcher = FundMatcher(simple_match_funds) donation = Donation("donation_1", 50) fund_matcher.reserve_funds(donation) fund_matcher.collect_donation(donation.donation_id) state = fund_matcher.allocation_state allocations = state[donation.donation_id]['allocations'] for a in allocations: assert a.status == COLLECTED
def test_simple_reserve_full_match(match_funds_with_ratios): """ reservation test will a full match on 1 fund """ fund_matcher = FundMatcher(match_funds_with_ratios) donation = Donation("donation_1", 50) fund_matcher.reserve_funds(donation) state = fund_matcher.allocation_state allocations = state[donation.donation_id]['allocations'] assert (len(allocations) == 1) assert (allocations[0].match_fund_id == "fund_3")
def test_simple_reserve_partial_match(match_funds_with_ratios): """ reservation test, donations allocated to > than 1 fund (partial) test donation is allocated in match_fund order """ fund_matcher = FundMatcher(match_funds_with_ratios) donation = Donation("donation_1", 130) # donation = Donation("donation_1", 250) fund_matcher.reserve_funds(donation) state = fund_matcher.allocation_state allocations = state[donation.donation_id]['allocations'] assert (len(allocations) == 2) assert (allocations[0].match_fund_id == "fund_3") assert (allocations[1].match_fund_id == "fund_1")
def test_reserve_full_match_with_ratios(match_funds_with_ratios): """ reservation test, donations allocated to 1 fund test ratio of 2:1, match_fund allocation is doubled """ fund_matcher = FundMatcher([match_funds_with_ratios[1]]) donation = Donation("donation_1", 25) fund_matcher.reserve_funds(donation) state = fund_matcher.allocation_state allocations = state[donation.donation_id]['allocations'] match_funds = fund_matcher.get_match_funds_as_list() assert (len(allocations) == 1) assert (allocations[0].match_fund_id == "fund_2") assert (match_funds[0].total_amount == 50)
def test_expire_donation_check_status_and_fund_balance(simple_match_funds): """ test allocations are EXPIRED test overall status is EXPIRED test match_fund total_balance remunerated """ fund_matcher = FundMatcher(simple_match_funds) donation = Donation("donation_1", 50) fund_matcher.reserve_funds(donation) fund_matcher.expire_donation(donation.donation_id) state = fund_matcher.allocation_state allocations = state[donation.donation_id]['allocations'] for a in allocations: assert a.status == EXPIRED assert state[donation.donation_id]['overall_status'] == EXPIRED match_funds = fund_matcher.get_match_funds_as_list() assert (match_funds[0].total_amount == 100)
def test_reserve_partial_match_with_ratios(more_match_funds_with_ratios): """ reservation test, donations allocated to 2 fund test order of match_fund allocation test ratio of 2:1, match_fund allocation is doubled test first fund is exhausted test second fund remaining total_amount """ fund_matcher = FundMatcher(more_match_funds_with_ratios) donation = Donation("donation_1", 60) fund_matcher.reserve_funds(donation) state = fund_matcher.allocation_state allocations = state[donation.donation_id]['allocations'] match_funds = fund_matcher.get_match_funds_as_list() assert (len(allocations) == 2) assert (allocations[0].match_fund_id == "fund_3") assert (allocations[1].match_fund_id == "fund_1") assert (match_funds[0].total_amount == 0) assert (match_funds[1].total_amount == 80)
def test_donation_amount_max(): donation_id = uuid.uuid4().hex amount = 25001 with pytest.raises(BadRequestException): Donation(donation_id, amount)
def test_donation_has_valid_amount_other(): donation_id = uuid.uuid4().hex amount = "500g" with pytest.raises(ValueError): Donation(donation_id, amount)
def test_list_match_fund_allocations(simple_match_funds): """ Only list RESERVED or COLLECTED allocations (ignores EXPIRED) Returns a list of allocations per donation in the format: { "donation_id" : <donation_id>, "allocations" : [ { "match_fund_id": <fund_id>, "match_fund_allocation": <amount>, "status": <status>}, {..} ], "created_time": datetime when reservation was first created, "updated_time": datetime when reservation was last updated, "overall_status": one of "Reserved" or "Collected", "donation_balance_unmatched": <amount of donation unmatched>, "original_donation": <the original donation amount> } """ fund_matcher = FundMatcher(simple_match_funds) donation_1 = Donation("donation_1", 100) donation_2 = Donation("donation_2", 250) donation_3 = Donation("donation_3", 45) fund_matcher.reserve_funds(donation_1) fund_matcher.reserve_funds(donation_2) fund_matcher.reserve_funds(donation_3) fund_matcher.collect_donation(donation_2.donation_id) fund_matcher.expire_donation(donation_3.donation_id) allocations_list = fund_matcher.list_match_fund_allocations() min_expected_output = [ { "donation_id": "donation_1", "allocations": [ {"match_fund_id": "fund_3", "match_fund_allocation": 100, "status": RESERVED } ], }, { "donation_id": "donation_2", "allocations": [ {"match_fund_id": "fund_1", "match_fund_allocation": 100, "status": COLLECTED }, {"match_fund_id": "fund_2", "match_fund_allocation": 100, "status": COLLECTED } ], "original_donation": 250, "donation_balance_unmatched": 50, "overall_status": COLLECTED } ] assert len(min_expected_output) == len(allocations_list) assert allocations_list[0]['donation_id'] == min_expected_output[0]['donation_id'] assert allocations_list[0]['allocations'] == min_expected_output[0]['allocations'] assert allocations_list[1]['donation_id'] == min_expected_output[1]['donation_id'] assert allocations_list[1]['allocations'] == min_expected_output[1]['allocations']