Exemple #1
0
 def test_init(self):
     """
     Bill constructor.
     """
     b = Bill()
     self.assertTrue(
         len(b.getAdjustments()) == 0,
         'A new bill should not already have adjustments.')
     self.assertTrue(b.charge == 0,
                     'A new bill should not already have a charge.')
     self.assertTrue(b.getTotal() == 0,
                     'A new bill should have a total of 0.')
Exemple #2
0
    def test_setName(self):
        b = Bill()
        self.z.root.b = b

        self.assertTrue(b.name == None, 'A bill should start with no name.')

        b.name = 'A bill through the desert'

        self.assertTrue(b.name == 'A bill through the desert',
                        'Name set did not work.')
        self.cycleDb()
        self.assertTrue(self.z.root.b.name == 'A bill through the desert',
                        'Name did not persist.')
Exemple #3
0
    def test_getTotal(self):
        """
        Adjustments and charges should all affect the total.
        """
        b = Bill()
        self.z.root.b = b

        b.charge = 100
        b.addAdjustment(350, 'Adjustment of 350')
        b.addAdjustment(-50, 'Adjustment of -50')

        self.assertTrue(
            b.getTotal() == 400,
            'Adjustments and charges should be reflected by the bill total.')

        b.charge = 50

        self.assertTrue(
            b.getTotal() == 350,
            'Adjustments and charges should be reflected by the bill total.')

        self.cycleDb()
        self.assertTrue(
            len(self.z.root.b.getAdjustments()) == 2,
            'Adjustments did not persist.')
        self.assertTrue(self.z.root.b.getTotal() == 350,
                        'Adjustments and charges did not persist.')
Exemple #4
0
    def test_setOwner(self):
        b = Bill()
        self.z.root.b = b

        self.assertTrue(b.owner == None, 'A bill should start with no owner.')

        b.owner = 1
        self.assertTrue(
            b.owner == 1,
            'A bill should be able to have an integer-valued owner.')

        b.owner = '5'
        self.assertTrue(
            b.owner == '5',
            'A bill should be able to have a string-valued owner.')

        self.cycleDb()
        self.assertTrue(self.z.root.b.owner == '5', 'Owner did not persist.')
Exemple #5
0
    def test_setDate(self):
        b = Bill()
        self.z.root.b = b

        self.assertTrue(b.date == None, 'A bill should start with no date.')

        dt = datetime.datetime.now()
        b.date = dt
        self.assertTrue(b.date == dt, 'Bill did not save date.')

        with self.assertRaises(TypeError):
            b.date = 'today'
        with self.assertRaises(TypeError):
            b.date = 1234

        self.assertTrue(b.date == dt,
                        'Failed assignments should not change date.')

        self.cycleDb()

        self.assertTrue(self.z.root.b.date == dt, 'Date should persist.')
Exemple #6
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.')
Exemple #7
0
    def test_setActive(self):
        b = Bill()
        self.z.root.b = b

        self.assertTrue(b.active == True, 'A bill should start as active.')

        with self.assertRaises(TypeError):
            b.active = None
        with self.assertRaises(TypeError):
            b.active = 'True'
        with self.assertRaises(TypeError):
            b.active = 1

        self.assertTrue(b.active == True,
                        'Active status should not change from failed tests.')

        b.active = False

        self.assertTrue(b.active == False, 'Active status did not change.')

        self.cycleDb()

        self.assertTrue(self.z.root.b.active == False,
                        'Active status did not persist.')
Exemple #8
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.')
Exemple #9
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.')
Exemple #10
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.')
Exemple #11
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.')
Exemple #12
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.')
Exemple #13
0
    def test_addAdjustment(self):
        """
        Adjustments with correct parameters should be able to be added to the bill.
        """
        b = Bill()
        self.z.root.b = b

        with self.assertRaises(TypeError):
            b.addAdjustment(None, '')
        with self.assertRaises(TypeError):
            b.addAdjustment('', '')
        with self.assertRaises(TypeError):
            b.addAdjustment(123.45, '')

        self.assertTrue(
            len(b.getAdjustments()) == 0,
            'Bad adjustments should not be added to a bill.')

        b.addAdjustment(100, 'Adjustment 1')
        b.addAdjustment(200, 'Adjustment 2')
        b.addAdjustment(-50, 'Adjustment 3')
        b.addAdjustment(0, 'Adjustment 4')

        self.assertTrue(
            len(b.getAdjustments()) == 4,
            'Adjustments should be added to bill.')
        self.assertTrue(b.getAdjustments()[0][0] == 100,
                        'Adjustment amount is off.')
        self.assertTrue(b.getAdjustments()[1][0] == 200,
                        'Adjustment amount is off.')
        self.assertTrue(b.getAdjustments()[0][1] == 'Adjustment 1',
                        'Adjustment description inconsistent.')
        self.assertTrue(b.getAdjustments()[1][1] == 'Adjustment 2',
                        'Adjustment description inconsistent.')

        self.assertTrue(b.getTotal() == 250,
                        'Adjustments should affect the bill total.')

        with self.assertRaises(ValueError):
            b.addAdjustment(-300, 'Try to make the bill negative.')

        self.assertTrue(b.getTotal() == 250,
                        'Failed adjustments should not be saved.')

        self.cycleDb()
        self.assertTrue(
            len(self.z.root.b.getAdjustments()) == 4,
            'Adjustments did not persist, we have ' +
            str(len(self.z.root.b.getAdjustments())) + ' but expected 4.')
        self.assertTrue(
            self.z.root.b.getTotal() == 250,
            'Bill did not persist (total was ' +
            str(self.z.root.b.getTotal()) + ', expected 250).')
Exemple #14
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.')
Exemple #15
0
    def test_charge(self):
        """
        A bill charge must be a positive integer.
        """
        b = Bill()
        self.z.root.b = b

        b.charge = 20

        with self.assertRaises(TypeError):
            b.charge = None
        with self.assertRaises(TypeError):
            b.charge = 'abc'
        with self.assertRaises(TypeError):
            b.charge = 12.5

        with self.assertRaises(ValueError):
            b.charge = -40

        self.assertTrue(b.getTotal() == 20,
                        'Charge must not assume invalid values.')

        b.addAdjustment(-15, 'Bring bill down to 5.')
        self.assertTrue(b.getTotal() == 5, 'Negative adjustments should work.')

        with self.assertRaises(ValueError):
            b.charge = 10
        self.assertTrue(b.getTotal() == 5,
                        'Failed charge modification should not be saved.')

        self.cycleDb()
        self.assertTrue(self.z.root.b.getTotal() == 5,
                        'Charge did not persist.')

        self.z.root.b.charge = 15
        self.assertTrue(
            self.z.root.b.getTotal() == 0,
            'Bill must be allowed to be zeroed-out via charge modification.')