예제 #1
0
    def test_init(self):
        """
        Test the Billgroup constructor.
        """
        g = BillGroup()

        self.assertTrue(
            len(g.getPayors()) == 0, 'No payors should be added yet.')
        self.assertTrue(g.getContributionTotal() == 0,
                        'No contributions should have been made yet.')
예제 #2
0
    def test_getPayors(self):
        """
        Payors added to a bill are returned by getPayors.
        """
        g = BillGroup()
        self.z.root.g = g

        self.assertTrue(
            len(g.getPayors()) == 0,
            'No payors should be on a new bill group.')

        g.addOrUpdatePayor(1, 1)
        g.addOrUpdatePayor(1, 1)
        g.addOrUpdatePayor(2, 1)
        g.addOrUpdatePayor(3, 1)

        self.assertTrue(
            len(g.getPayors()) == 3,
            'Payors were not added to the bill group.')
        self.assertTrue(
            set([1, 2, 3]) == set(g.getPayors()), 'Payors were not the same.')

        self.cycleDb()

        self.assertTrue(
            len(self.z.root.g.getPayors()) == 3, 'Payors did not persist.')
        self.assertTrue(
            set([1, 2, 3]) == set(self.z.root.g.getPayors()),
            'Payors did not persist.')
예제 #3
0
    def test_setName(self):
        """
        Test setting the name of a bill.
        """
        g = BillGroup()

        self.z.root.g = g
        self.assertTrue(g.name == None,
                        'A bill group should start with no name.')

        g.name = 'A bill group through the desert'

        self.assertTrue(g.name == 'A bill group through the desert',
                        'Name set did not work.')
        self.cycleDb()
        self.assertTrue(
            self.z.root.g.name == 'A bill group through the desert',
            'Name did not persist.')
예제 #4
0
    def test_endCycle(self):
        """
        Test ending the current billing cycle. Deactivating bills has consequences in most of the calculations for a
        bill group, so test all of them.
        """
        g = BillGroup()
        self.z.root.g = g

        g.addOrUpdatePayor(1, 25)
        g.addOrUpdatePayor(2, 500)
        g.addOrUpdatePayor(3, 10)

        b1 = Bill()
        b1.charge = 20
        g.addBill(b1, 1)

        b2 = Bill()
        b2.charge = 5
        b2.addAdjustment(20, 'High')
        b2.addAdjustment(-10, 'Low')
        g.addBill(b2, 2)

        b3 = Bill()
        b3.charge = 10
        g.addBill(b3, 3)

        self.assertTrue(g.getContributionTotal() == 45,
                        'Total contribution is wrong.')
        g.endCycle()

        self.assertTrue(g.getContributionTotal() == 0,
                        'Total contribution is wrong after ending cycle.')
        self.assertTrue(
            g.getContributionFor(1) == 0,
            'Contribution is wrong after ending cycle.')
        self.assertTrue(
            g.getContributionFor(2) == 0,
            'Contribution is wrong after ending cycle.')
        self.assertTrue(
            g.getContributionFor(3) == 0,
            'Contribution is wrong after ending cycle.')
        self.assertTrue(
            g.calculateLiabilityFor(1) == 0,
            'Liability is wrong after ending cycle.')
        self.assertTrue(
            g.calculateLiabilityFor(2) == 0,
            'Liability is wrong after ending cycle.')
        self.assertTrue(
            g.calculateLiabilityFor(3) == 0,
            'Liability is wrong after ending cycle.')

        g.addOrUpdatePayor(2, 35)
        g.addOrUpdatePayor(4, 30)

        b4 = Bill()
        b4.charge = 20
        b4.addAdjustment(200, 'Adj')
        g.addBill(b4, 2)

        b5 = Bill()
        b5.charge = 90
        b5.addAdjustment(-10, 'Adj')
        g.addBill(b5, 4)

        # Liability percentages: 25, 35, 10, 30

        self.assertTrue(g.getContributionTotal() == 300,
                        'Total contribution is wrong after new cycle.')
        self.assertTrue(
            g.getContributionFor(1) == 0,
            'Contribution is wrong after new cycle.')
        self.assertTrue(
            g.getContributionFor(2) == 220,
            'Contribution is wrong after new cycle.')
        self.assertTrue(
            g.getContributionFor(3) == 0,
            'Contribution is wrong after new cycle.')
        self.assertTrue(
            g.getContributionFor(4) == 80,
            'Contribution is wrong after new cycle.')
        self.assertTrue(
            g.calculateLiabilityFor(1) == 75,
            'Liability is wrong after new cycle.')
        self.assertTrue(
            g.calculateLiabilityFor(2) == -115,
            'Liability is wrong after new cycle.')
        self.assertTrue(
            g.calculateLiabilityFor(3) == 30,
            'Liability is wrong after new cycle.')
        self.assertTrue(
            g.calculateLiabilityFor(4) == 10,
            'Liability is wrong after new cycle.')

        self.cycleDb()

        self.assertTrue(self.z.root.g.getContributionTotal() == 300,
                        'Total contribution did not persist after new cycle.')
        self.assertTrue(
            self.z.root.g.getContributionFor(1) == 0,
            'Contribution did not persist after new cycle.')
        self.assertTrue(
            self.z.root.g.getContributionFor(2) == 220,
            'Contribution did not persist after new cycle.')
        self.assertTrue(
            self.z.root.g.getContributionFor(3) == 0,
            'Contribution did not persist after new cycle.')
        self.assertTrue(
            self.z.root.g.getContributionFor(4) == 80,
            'Contribution did not persist after new cycle.')
        self.assertTrue(
            self.z.root.g.calculateLiabilityFor(1) == 75,
            'Liability did not persist after new cycle.')
        self.assertTrue(
            self.z.root.g.calculateLiabilityFor(2) == -115,
            'Liability did not persist after new cycle.')
        self.assertTrue(
            self.z.root.g.calculateLiabilityFor(3) == 30,
            'Liability did not persist after new cycle.')
        self.assertTrue(
            self.z.root.g.calculateLiabilityFor(4) == 10,
            'Liability did not persist after new cycle.')
예제 #5
0
    def test_getContributionTotal(self):
        """
        Calculates the total amount of the bills in this bill group.
        """
        g = BillGroup()
        self.z.root.g = g

        self.assertTrue(g.getContributionTotal() == 0,
                        'Total contribution is wrong.')

        g.addOrUpdatePayor(1, 25)
        g.addOrUpdatePayor(2, 500)
        g.addOrUpdatePayor(3, 10)

        b1 = Bill()
        b1.charge = 20
        g.addBill(b1, 1)

        b2 = Bill()
        b2.charge = 5
        b2.addAdjustment(20, 'High')
        b2.addAdjustment(-10, 'Low')
        g.addBill(b2, 2)

        b3 = Bill()
        b3.charge = 10
        g.addBill(b3, 3)

        with self.assertRaises(ValueError):
            g.addBill(b1, 1)
        with self.assertRaises(ValueError):
            g.addBill(b2, 1)
        with self.assertRaises(ValueError):
            g.addBill(b3, 2)

        self.assertTrue(g.getContributionTotal() == 45,
                        'Total contribution is wrong.')

        self.cycleDb()

        self.assertTrue(self.z.root.g.getContributionTotal() == 45,
                        'Total contribution did not persist.')
예제 #6
0
    def test_getContributionFor(self):
        """
        Contributions for everyone should add up to the total contribution.
        :return:
        """
        g = BillGroup()
        self.z.root.g = g

        with self.assertRaises(TypeError):
            g.getContributionFor(None)

        g.addOrUpdatePayor(1, 1)
        g.addOrUpdatePayor(2, 2)
        g.addOrUpdatePayor(3, 3)

        with self.assertRaises(ValueError):
            g.getContributionFor(4)

        self.assertTrue(g.getContributionFor(1) == 0, 'Contribution is wrong.')
        self.assertTrue(g.getContributionFor(2) == 0, 'Contribution is wrong.')
        self.assertTrue(g.getContributionFor(3) == 0, 'Contribution is wrong.')

        b1 = Bill()
        b1.charge = 20
        b1.addAdjustment(10, '')
        g.addBill(b1, 1)

        b2 = Bill()
        b2.charge = 15
        b2.addAdjustment(-5, '')
        b2.addAdjustment(-8, '')
        g.addBill(b2, 2)

        b3 = Bill()
        b3.charge = 10
        g.addBill(b3, 3)

        self.assertTrue(
            g.getContributionFor(1) == 30,
            'Contribution is wrong (' + str(g.getContributionFor(1)) + ').')
        self.assertTrue(g.getContributionFor(2) == 2, 'Contribution is wrong.')
        self.assertTrue(
            g.getContributionFor(3) == 10, 'Contribution is wrong.')

        self.assertTrue(g.getContributionTotal() == 42,
                        'Total contribution is wrong.')

        self.cycleDb()

        self.assertTrue(
            self.z.root.g.getContributionFor(1) == 30,
            'Contribution did not persist (' +
            str(self.z.root.g.getContributionFor(1)) + ').')
        self.assertTrue(
            self.z.root.g.getContributionFor(2) == 2,
            'Contribution did not persist.')
        self.assertTrue(
            self.z.root.g.getContributionFor(3) == 10,
            'Contribution did not persist.')
        self.assertTrue(self.z.root.g.getContributionTotal() == 42,
                        'Total contribution did not persist.')
예제 #7
0
    def test_calculateLiabilityFor(self):
        """
        Liability for everyone should zero out. Liability should not calculate for non-existant payors.
        """
        g = BillGroup()
        self.z.root.g = g

        with self.assertRaises(TypeError):
            g.calculateLiabilityFor(None)

        g.addOrUpdatePayor(1, 50)
        g.addOrUpdatePayor(2, 150)

        with self.assertRaises(ValueError):
            g.calculateLiabilityFor(4)

        b1 = Bill()
        b1.charge = 500
        g.addBill(b1, 1)

        b2 = Bill()
        b2.charge = 0
        b2.addAdjustment(750, 'Adjustment')
        g.addBill(b2, 2)

        self.assertTrue(
            g.calculateLiabilityFor(1) == -187.5, 'Payor liability incorrect.')
        self.assertTrue(
            g.calculateLiabilityFor(1) + g.calculateLiabilityFor(2) == 0,
            'Liability sum did not zero out.')

        self.cycleDb()

        self.assertTrue(
            self.z.root.g.calculateLiabilityFor(1) == -187.5,
            'Payor liability did not persist.')
        self.assertTrue(
            self.z.root.g.calculateLiabilityFor(1) +
            self.z.root.g.calculateLiabilityFor(2) == 0,
            'Liability sum did not persist.')
예제 #8
0
    def test_addBill(self):
        """
        Adding a bill should adjust the liability of the payors. Should not be able to add a bill to a bill group that
        doesn't have the specified payor associated with the bill group already. Make sure we don't add the same bill
        twice.
        """
        g = BillGroup()
        self.z.root.g = g

        b0 = Bill()
        b0.charge = 999

        with self.assertRaises(TypeError):
            g.addBill(b0, None)
        with self.assertRaises(ValueError):
            g.addBill(b0, 1)  # Can't add a bill to a non-existant payor.

        g.addOrUpdatePayor(1, 10)
        g.addOrUpdatePayor(2, 25)
        g.addOrUpdatePayor(3, 65)

        with self.assertRaises(TypeError):
            g.addBill(None, 1)
        with self.assertRaises(TypeError):
            g.addBill(400, 1)
        with self.assertRaises(TypeError):
            g.addBill('400', 1)

        self.assertTrue(
            g.calculateLiabilityFor(1) == 0, 'Payor liability incorrect.')
        self.assertTrue(
            g.calculateLiabilityFor(2) == 0, 'Payor liability incorrect.')
        self.assertTrue(
            g.calculateLiabilityFor(3) == 0, 'Payor liability incorrect.')

        b1 = Bill()
        b1.charge = 400
        g.addBill(b1, 1)
        b2 = Bill()
        b2.charge = 250
        g.addBill(b2, 2)

        with self.assertRaises(ValueError):
            g.addBill(b1, '')

        # Total charge is 650.
        self.assertTrue(
            g.calculateLiabilityFor(1) == -335, 'Payor liability incorrect (' +
            str(g.calculateLiabilityFor(1)) + ').')
        self.assertTrue(
            g.calculateLiabilityFor(2) == -87.5, 'Payor liability incorrect.')
        self.assertTrue(
            g.calculateLiabilityFor(3) == 422.5, 'Payor liability incorrect.')

        self.cycleDb()

        self.assertTrue(
            self.z.root.g.calculateLiabilityFor(1) == -335,
            'Payor liability did not persist.')
        self.assertTrue(
            self.z.root.g.calculateLiabilityFor(2) == -87.5,
            'Payor liability did not persist.')
        self.assertTrue(
            self.z.root.g.calculateLiabilityFor(3) == 422.5,
            'Payor liability did not persist.')
예제 #9
0
    def test_removePayor(self):
        """
        Payors should be removable from the payor list and liability for everyone else should continue to calculate
        properly. A payor may not be removed if they have contributed to any bills, as this would prevent calculate
        liability from zeroing out.
        """
        g = BillGroup()
        self.z.root.g = g

        g.addOrUpdatePayor(1, 40)
        g.addOrUpdatePayor(2, 60)

        with self.assertRaises(TypeError):
            g.removePayor(None)

        with self.assertRaises(ValueError):
            g.removePayor(400)

        self.assertTrue(
            g.calculateLiabilityFor(1) == 0, 'Payor liability incorrect.')
        self.assertTrue(
            g.calculateLiabilityFor(2) == 0, 'Payor liability incorrect.')

        b1 = Bill()
        b1.charge = 200
        g.addBill(b1, 1)

        # Total charge is 200.
        self.assertTrue(
            g.calculateLiabilityFor(1) == -120, 'Payor liability incorrect.')
        self.assertTrue(
            g.calculateLiabilityFor(2) == 120, 'Payor liability incorrect.')

        with self.assertRaises(ValueError):
            g.removePayor(1)

        self.assertTrue(
            g.calculateLiabilityFor(1) == -120, 'Payor liability incorrect.')
        self.assertTrue(
            g.calculateLiabilityFor(2) == 120, 'Payor liability incorrect.')

        g.removePayor(2)

        with self.assertRaises(ValueError):
            g.addBill(Bill(), 2)

        self.assertTrue(
            g.calculateLiabilityFor(1) == 0, 'Payor liability incorrect.')

        g.addOrUpdatePayor(2, 40)

        self.assertTrue(
            g.calculateLiabilityFor(1) == -100, 'Payor liability incorrect.')
        self.assertTrue(
            g.calculateLiabilityFor(2) == 100, 'Payor liability incorrect.')

        self.cycleDb()

        self.assertTrue(
            self.z.root.g.calculateLiabilityFor(1) == -100,
            'Payor liability did not persist.')
        self.assertTrue(
            self.z.root.g.calculateLiabilityFor(2) == 100,
            'Payor liability did not persist.')
예제 #10
0
    def test_addOrUpdatePayor(self):
        """
        Payors should be added to the payor tuple array with their associated weight. A payor that already exists should
        be updated, not duplicated. When a payor is added or updated the liability for all payors should continue to
        calculate properly.
        """
        g = BillGroup()
        self.z.root.g = g

        with self.assertRaises(TypeError):
            g.addOrUpdatePayor(None, 1)

        with self.assertRaises(TypeError):
            g.addOrUpdatePayor(1, None)
        with self.assertRaises(TypeError):
            g.addOrUpdatePayor(1, '')
        with self.assertRaises(ValueError):
            g.addOrUpdatePayor(1, -1)
        with self.assertRaises(ValueError):
            g.addOrUpdatePayor(1, 0)

        self.assertTrue(
            len(g.getPayors()) == 0, 'No payors should be added yet.')

        g.addOrUpdatePayor(1, 1)
        self.assertTrue(
            len(g.getPayors()) == 1,
            'Payors should be able to be added to a shared bill.')
        self.assertTrue(
            g.calculateLiabilityFor(1) == 0,
            'Payor liability should be able to be added to a shared bill.')

        g.addOrUpdatePayor(1, 4)

        self.assertTrue(
            len(g.getPayors()) == 1, 'Duplicate payors should not be created.')
        self.assertTrue(
            g.calculateLiabilityFor(1) == 0,
            'Liability for a bill with zero contributions should be zero.')

        # With two payors, see if the liability changes correctly when we add a third.
        g.addOrUpdatePayor(2, 1)

        self.assertTrue(
            len(g.getPayors()) == 2, 'A second payor should have been added.')

        b1 = Bill()
        b1.charge = 500
        b1.addAdjustment(500, 'Adjustment')
        g.addBill(b1, 1)

        b2 = Bill()
        b2.charge = 200
        b2.addAdjustment(300, 'Adjustment')
        g.addBill(b2, 2)

        # At this point, payor 1 has paid in 1000 and payor 2 has paid in 500.
        # Payor 1 is responsible for 4/5 of the total bill, and payor 2 is responsible for 1/5.
        # Payor 1's liability should be (4/5) * 1500, less what they have already paid in.
        # So, 200.
        self.assertTrue(
            g.calculateLiabilityFor(1) == 200, 'Payor liability incorrect.')

        # Payor 2 is responsible for 300, but has paid in 500. They need to get back $200.
        self.assertTrue(
            g.calculateLiabilityFor(2) == -200, 'Payor liability incorrect.')

        # Now, a third payor joins, with no pay-in yet, and a weight of 5.
        g.addOrUpdatePayor(3, 5)

        self.assertTrue(
            g.calculateLiabilityFor(3) == 750, 'Payor liability incorrect.')
        self.assertTrue(
            g.calculateLiabilityFor(2) == -350, 'Payor liability incorrect.')
        self.assertTrue(
            g.calculateLiabilityFor(1) == -400, 'Payor liability incorrect.')

        # Now, they pay a bill, update their liability weight to 11 and a pay-in of $400.
        # Total of 1900, total liability weights of 16.

        b3 = Bill()
        b3.charge = 350
        b3.addAdjustment(25, 'Adjustment 1')
        b3.addAdjustment(15, 'Adjustment 2')
        b3.addAdjustment(45, 'Adjustment 3')
        b3.addAdjustment(-35, 'Adjustment 1')
        g.addBill(b3, 3)
        g.addOrUpdatePayor(3, 11)

        self.assertTrue(
            g.calculateLiabilityFor(1) == -525, 'Payor liability incorrect.')
        self.assertTrue(
            g.calculateLiabilityFor(2) == -381.25,
            'Payor liability incorrect.')
        self.assertTrue(
            g.calculateLiabilityFor(3) == 906.25, 'Payor liability incorrect.')

        # Payor 1 pays a new bill.

        b11 = Bill()
        b11.charge = 150
        b1.addAdjustment(-50, 'Adjustment 1')
        g.addBill(b11, 1)

        # Total is now 2000.

        self.assertTrue(
            g.calculateLiabilityFor(1) == -600, 'Payor liability incorrect.')
        self.assertTrue(
            g.calculateLiabilityFor(2) == -375, 'Payor liability incorrect.')
        self.assertTrue(
            g.calculateLiabilityFor(3) == 975, 'Payor liability incorrect.')

        self.cycleDb()

        self.assertTrue(
            self.z.root.g.calculateLiabilityFor(1) == -600,
            'Payor liability did not persist.')
        self.assertTrue(
            self.z.root.g.calculateLiabilityFor(2) == -375,
            'Payor liability did not persist.')
        self.assertTrue(
            self.z.root.g.calculateLiabilityFor(3) == 975,
            'Payor liability did not persist.')