def test_adding_donation_proportion_adds_payments_if_amount_set_first( self): self.da_repo.set_donation_amount(user=test_data.u1, amount_GBPennies=100) self.dp_repo.add_donation_proportion( DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=2)) expected = [ Payment(user=test_data.u1, charity=test_data.c1, amount_GBPennies=100) ] self.assertEquals( self.payment_repo.get_next_expected_payments(user=test_data.u1), expected) self.dp_repo.add_donation_proportion( DonationProportion.new(user=test_data.u1, charity=test_data.c2, amount=3)) expected = [ Payment(user=test_data.u1, charity=test_data.c1, amount_GBPennies=40), Payment(user=test_data.u1, charity=test_data.c2, amount_GBPennies=60), ] self.assertEquals( self.payment_repo.get_next_expected_payments(user=test_data.u1), expected)
def test_aggregates_charity_totals_across_users(self): self.setup_one_incoming_payment({test_data.u1: 250, test_data.u2: 75}) self.add_donation_proportions([ DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=100), DonationProportion.new(user=test_data.u1, charity=test_data.c2, amount=150), DonationProportion.new(user=test_data.u2, charity=test_data.c1, amount=75), ]) expected = set([ OutgoingPayment(charity=test_data.c1, amount_GBPennies=175, status=OutgoingPaymentState.DISPLAYED), OutgoingPayment(charity=test_data.c2, amount_GBPennies=150, status=OutgoingPaymentState.DISPLAYED), ]) self.assertEquals(self.payment_repo.get_pending_outgoing_payments(), expected)
def test_only_generates_outgoing_payments_if_incoming_payments_received( self): self.setup_one_incoming_payment({test_data.u1: 250}) self.setup_one_missing_payment({test_data.u2: 75}) self.add_donation_proportions([ DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=100), DonationProportion.new(user=test_data.u1, charity=test_data.c2, amount=150), DonationProportion.new(user=test_data.u2, charity=test_data.c1, amount=75), ]) expected = set([ OutgoingPayment(charity=test_data.c1, amount_GBPennies=100, status=OutgoingPaymentState.DISPLAYED), OutgoingPayment(charity=test_data.c2, amount_GBPennies=150, status=OutgoingPaymentState.DISPLAYED), ]) self.assertEquals(self.payment_repo.get_pending_outgoing_payments(), expected)
def test_donation_proportions_are_isolated_per_user(self): self.add_donation_proportions([ DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=1), DonationProportion.new(user=test_data.u1, charity=test_data.c2, amount=1), DonationProportion.new(user=test_data.u2, charity=test_data.c1, amount=1), ]) self.assertEquals(0.5, self.dp_repo.get_fraction(user=test_data.u1, charity=test_data.c1))
def test_logs_and_notifies_incoming_and_outgoing_mismatches(self): self.setup_one_mismatched_incoming_payment({ test_data.u1: (250, 249), test_data.u2: (250, 251), test_data.u4: (200, 200), test_data.u5: (75, 75), }) self.setup_one_missing_payment({test_data.u3: 10}) self.add_donation_proportions([ DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=100), DonationProportion.new(user=test_data.u1, charity=test_data.c2, amount=150), DonationProportion.new(user=test_data.u2, charity=test_data.c1, amount=250), DonationProportion.new(user=test_data.u3, charity=test_data.c1, amount=10), DonationProportion.new(user=test_data.u5, charity=test_data.c1, amount=75), ]) amount_mismatch_notifier = AccumulatingMismatchNotifier() self.payment_repo.get_pending_outgoing_payments(amount_mismatch_notifiers=[amount_mismatch_notifier]) expected = set([ AmountMismatch(user=test_data.u1, incoming_GBPennies=249, outgoing=[ OutgoingPayment(charity=test_data.c1, amount_GBPennies=100, status=OutgoingPaymentState.VALUE_MISMATCH), OutgoingPayment(charity=test_data.c2, amount_GBPennies=150, status=OutgoingPaymentState.VALUE_MISMATCH), ]), AmountMismatch(user=test_data.u2, incoming_GBPennies=251, outgoing=[OutgoingPayment(charity=test_data.c1, amount_GBPennies=250, status=OutgoingPaymentState.VALUE_MISMATCH)]), AmountMismatch(user=test_data.u3, incoming_GBPennies=0, outgoing=[OutgoingPayment(charity=test_data.c1, amount_GBPennies=10, status=OutgoingPaymentState.VALUE_MISMATCH)]), AmountMismatch(user=test_data.u4, incoming_GBPennies=200, outgoing=[]), ]) self.assertEquals(amount_mismatch_notifier.accumulated, expected)
def test_updates_multiple_donations(self): dp = DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=1) self.dp_repo.add_donation_proportion(dp) self.assertSequenceEqual(self.dp_repo.get_donation_proportions(user=test_data.u1), [dp]) dp2 = DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=2) self.dp_repo.add_donation_proportion(dp2) self.assertSequenceEqual(self.dp_repo.get_donation_proportions(user=test_data.u1), [dp2])
def test_can_add_donation_proportions(self): self.add_donation_proportions([ DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=2), DonationProportion.new(user=test_data.u1, charity=test_data.c2, amount=6), ]) self.assertEquals(0.25, self.dp_repo.get_fraction(user=test_data.u1, charity=test_data.c1)) self.assertEquals(0.75, self.dp_repo.get_fraction(user=test_data.u1, charity=test_data.c2)) self.assertEquals(0, self.dp_repo.get_fraction(user=test_data.u1, charity=test_data.c3))
def test_updates_multiple_donations(self): dp = DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=1) self.dp_repo.add_donation_proportion(dp) self.assertSequenceEqual( self.dp_repo.get_donation_proportions(user=test_data.u1), [dp]) dp2 = DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=2) self.dp_repo.add_donation_proportion(dp2) self.assertSequenceEqual( self.dp_repo.get_donation_proportions(user=test_data.u1), [dp2])
def test_adding_donation_proportion_adds_payments_if_amount_set_first(self): self.da_repo.set_donation_amount(user=test_data.u1, amount_GBPennies=100) self.dp_repo.add_donation_proportion(DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=2)) expected = [Payment(user=test_data.u1, charity=test_data.c1, amount_GBPennies=100)] self.assertEquals(self.payment_repo.get_next_expected_payments(user=test_data.u1), expected) self.dp_repo.add_donation_proportion(DonationProportion.new(user=test_data.u1, charity=test_data.c2, amount=3)) expected = [ Payment(user=test_data.u1, charity=test_data.c1, amount_GBPennies=40), Payment(user=test_data.u1, charity=test_data.c2, amount_GBPennies=60), ] self.assertEquals(self.payment_repo.get_next_expected_payments(user=test_data.u1), expected)
def test_donation_proportions_are_isolated_per_user(self): self.add_donation_proportions([ DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=1), DonationProportion.new(user=test_data.u1, charity=test_data.c2, amount=1), DonationProportion.new(user=test_data.u2, charity=test_data.c1, amount=1), ]) self.assertEquals( 0.5, self.dp_repo.get_fraction(user=test_data.u1, charity=test_data.c1))
def test_only_generates_outgoing_payments_if_incoming_payments_received(self): self.setup_one_incoming_payment({test_data.u1: 250}) self.setup_one_missing_payment({test_data.u2: 75}) self.add_donation_proportions([ DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=100), DonationProportion.new(user=test_data.u1, charity=test_data.c2, amount=150), DonationProportion.new(user=test_data.u2, charity=test_data.c1, amount=75), ]) expected = set([ OutgoingPayment(charity=test_data.c1, amount_GBPennies=100, status=OutgoingPaymentState.DISPLAYED), OutgoingPayment(charity=test_data.c2, amount_GBPennies=150, status=OutgoingPaymentState.DISPLAYED), ]) self.assertEquals(self.payment_repo.get_pending_outgoing_payments(), expected)
def test_generates_outgoing_payments_despite_mismatches(self): self.setup_one_incoming_payment({ test_data.u1: 100, test_data.u2: 75, }) self.add_donation_proportions([ DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=100), ]) expected = set([ OutgoingPayment(charity=test_data.c1, amount_GBPennies=100, status=OutgoingPaymentState.DISPLAYED), ]) expected_notifications = set([ AmountMismatch(user=test_data.u2, incoming_GBPennies=75, outgoing=[]), ]) amount_mismatch_notifier = AccumulatingMismatchNotifier() self.assertEquals( self.payment_repo.get_pending_outgoing_payments( amount_mismatch_notifiers=[amount_mismatch_notifier]), expected) self.assertEquals(amount_mismatch_notifier.accumulated, expected_notifications)
def test_aggregates_charity_totals_across_users(self): self.setup_one_incoming_payment({ test_data.u1: 250, test_data.u2: 75 }) self.add_donation_proportions([ DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=100), DonationProportion.new(user=test_data.u1, charity=test_data.c2, amount=150), DonationProportion.new(user=test_data.u2, charity=test_data.c1, amount=75), ]) expected = set([ OutgoingPayment(charity=test_data.c1, amount_GBPennies=175, status=OutgoingPaymentState.DISPLAYED), OutgoingPayment(charity=test_data.c2, amount_GBPennies=150, status=OutgoingPaymentState.DISPLAYED), ]) self.assertEquals(self.payment_repo.get_pending_outgoing_payments(), expected)
def test_can_add_donation_proportions(self): self.add_donation_proportions([ DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=2), DonationProportion.new(user=test_data.u1, charity=test_data.c2, amount=6), ]) self.assertEquals( 0.25, self.dp_repo.get_fraction(user=test_data.u1, charity=test_data.c1)) self.assertEquals( 0.75, self.dp_repo.get_fraction(user=test_data.u1, charity=test_data.c2)) self.assertEquals( 0, self.dp_repo.get_fraction(user=test_data.u1, charity=test_data.c3))
def get_donation_proportions(self, user=None, charity=None): """Gets the donation proportions filtered by user and/or charity. If user is unspecified, returns for all users. If charity is unspecified, returns for all charities. It does not make sense to specify charity without user, and the magnitude of DonationProportion.amount is relative to the user's other donations. """ query = DonationProportion.all() if user is not None: query.ancestor(user.key()) if charity is not None: query.filter('charity =', charity) return [dp for dp in query.run()]
def get_donation_proportions(self, user=None, charity=None): """Gets the donation proportions filtered by user and/or charity. If user is unspecified, returns for all users. If charity is unspecified, returns for all charities. It does not make sense to specify charity without user, and the magnitude of DonationProportion.amount is relative to the user's other donations. """ query = DonationProportion.all() if user is not None: query.ancestor(user.key()) if charity is not None: query.filter('charity =', charity) return [dp for dp in query.run()]
def test_generates_outgoing_payments_despite_mismatches(self): self.setup_one_incoming_payment({ test_data.u1: 100, test_data.u2: 75, }) self.add_donation_proportions([ DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=100), ]) expected = set([ OutgoingPayment(charity=test_data.c1, amount_GBPennies=100, status=OutgoingPaymentState.DISPLAYED), ]) expected_notifications = set([ AmountMismatch(user=test_data.u2, incoming_GBPennies=75, outgoing=[]), ]) amount_mismatch_notifier = AccumulatingMismatchNotifier() self.assertEquals(self.payment_repo.get_pending_outgoing_payments(amount_mismatch_notifiers=[amount_mismatch_notifier]), expected) self.assertEquals(amount_mismatch_notifier.accumulated, expected_notifications)
def test_logs_and_notifies_incoming_and_outgoing_mismatches(self): self.setup_one_mismatched_incoming_payment({ test_data.u1: (250, 249), test_data.u2: (250, 251), test_data.u4: (200, 200), test_data.u5: (75, 75), }) self.setup_one_missing_payment({test_data.u3: 10}) self.add_donation_proportions([ DonationProportion.new(user=test_data.u1, charity=test_data.c1, amount=100), DonationProportion.new(user=test_data.u1, charity=test_data.c2, amount=150), DonationProportion.new(user=test_data.u2, charity=test_data.c1, amount=250), DonationProportion.new(user=test_data.u3, charity=test_data.c1, amount=10), DonationProportion.new(user=test_data.u5, charity=test_data.c1, amount=75), ]) amount_mismatch_notifier = AccumulatingMismatchNotifier() self.payment_repo.get_pending_outgoing_payments( amount_mismatch_notifiers=[amount_mismatch_notifier]) expected = set([ AmountMismatch(user=test_data.u1, incoming_GBPennies=249, outgoing=[ OutgoingPayment( charity=test_data.c1, amount_GBPennies=100, status=OutgoingPaymentState.VALUE_MISMATCH), OutgoingPayment( charity=test_data.c2, amount_GBPennies=150, status=OutgoingPaymentState.VALUE_MISMATCH), ]), AmountMismatch(user=test_data.u2, incoming_GBPennies=251, outgoing=[ OutgoingPayment( charity=test_data.c1, amount_GBPennies=250, status=OutgoingPaymentState.VALUE_MISMATCH) ]), AmountMismatch(user=test_data.u3, incoming_GBPennies=0, outgoing=[ OutgoingPayment( charity=test_data.c1, amount_GBPennies=10, status=OutgoingPaymentState.VALUE_MISMATCH) ]), AmountMismatch(user=test_data.u4, incoming_GBPennies=200, outgoing=[]), ]) self.assertEquals(amount_mismatch_notifier.accumulated, expected)