Example #1
0
    def setUp(self):
        self.gl_structure = GeneralLedgerStructure("NameA",
                                                   description="DescriptionA")
        self.sales_acc = self.gl_structure._acci_sales_.create_account(
            "sales_default", "0000")
        self.cos_acc = self.gl_structure._acci_cos_.create_account(
            "cos_default", "0000")
        self.reva_acc = self.gl_structure["Other Income"].create_account(
            "RevA", number="011")
        self.expa_acc = self.gl_structure["Expense"].create_account(
            "ExpenseA", number="011")

        self.object = Entity("EntityA",
                             gl_structure=self.gl_structure,
                             description="DescriptionA")
        # Set up the needed objects
        self.comp1 = self.object.create_component("ComponentA1",
                                                  description="ca1")
        basic_activity = BasicActivity("BasicActivityA",
                                       description="DescriptionA",
                                       dt_account="Bank",
                                       cr_account="Sales",
                                       amount=5000,
                                       start=datetime(2016, 2, 1),
                                       end=datetime(2017, 2, 1),
                                       interval=1)
        self.comp1.add_activity(basic_activity)

        self.clock = Clock("NameA", start_datetime=datetime(2016, 1, 1))
Example #2
0
 def __init__(self,
              name,
              description=None,
              start_datetime=datetime.now(),
              period_duration=TimePeriod.year,
              period_count=1):
     self.clock = Clock(
         "Clock",
         start_datetime=get_date(start_datetime),
         timestep_period_duration=period_duration)
     self.period_count = period_count
     self.entities = []
     super(TimeBasedModel, self).__init__(name, description=description)
Example #3
0
    def test_run(self):
        """
        Test that the activity run method creates a transaction with an amount
        of 5000.
        """

        structure = GeneralLedgerStructure("NameA", description="DescriptionA")
        gl = GeneralLedger("NameA", structure, description="DescriptionA")
        clock = Clock("NameA", start_datetime=datetime(2016, 1, 1))
        clock.tick()
        clock.tick()
        self.object.prepare_to_run(clock, 20)
        self.object.run(clock, gl)
        self.assertEqual(len(gl.transactions), 1)
        self.assertEqual(gl.transactions[0].amount, 5000)
Example #4
0
    def test_run(self):
        """
        Test that the activity run method creates a transaction with an amount
        of 5000.
        """

        structure = GeneralLedgerStructure("NameA", description="DescriptionA")
        gl = GeneralLedger("NameA", structure, description="DescriptionA")
        clock = Clock("NameA", start_datetime=datetime(2016, 1, 1))
        clock.tick()
        clock.tick()
        self.object.prepare_to_run(clock, 20)
        self.object.run(clock, gl)
        self.assertEqual(len(gl.transactions), 1)
        self.assertEqual(gl.transactions[0].amount, 5000)
Example #5
0
    def setUp(self):
        self.gl_structure = GeneralLedgerStructure(
            "GL Structure",
            description="General Ledger Structure")
        self.gl_structure["Account Payable"].create_account(
            "Capital Loan",
            "0000")
        self.gl_structure["Expense"].create_account(
            "Interest Expense",
            "0000")

        self.gl = GeneralLedger(
            "GL",
            self.gl_structure,
            description="General Ledger")

        self.clock = Clock("NameA", start_datetime=datetime(2016, 2, 1))

        self.object = BasicLoanActivity(
            "Capital Loan",
            bank_account="Bank/Default",
            loan_account="Account Payable/Capital Loan",
            interest_account="Expense/Interest Expense",
            amount=180000,
            interest_rate=0.15,
            start=datetime(2016, 2, 1),
            duration=36,
            interval=1,
            description="Loan for Capital")
Example #6
0
    def setUp(self):
        self.gl_structure = GeneralLedgerStructure(
            "NameA",
            description="DescriptionA")
        self.sales_acc = self.gl_structure._acci_sales_.create_account(
            "sales_default",
            "0000")
        self.cos_acc = self.gl_structure._acci_cos_.create_account(
            "cos_default",
            "0000")
        self.reva_acc = self.gl_structure["Other Income"].create_account(
            "RevA",
            number="011")
        self.expa_acc = self.gl_structure["Expense"].create_account(
            "ExpenseA",
            number="011")

        self.object = Entity("EntityA",
                             gl_structure=self.gl_structure,
                             description="DescriptionA")
        # Set up the needed objects
        self.comp1 = self.object.create_component("ComponentA1",
                                                  description="ca1")
        basic_activity = BasicActivity("BasicActivityA",
                                       description="DescriptionA",
                                       dt_account="Bank",
                                       cr_account="Sales",
                                       amount=5000,
                                       start=datetime(2016, 2, 1),
                                       end=datetime(2017, 2, 1),
                                       interval=1)
        self.comp1.add_activity(basic_activity)

        self.clock = Clock("NameA", start_datetime=datetime(2016, 1, 1))
Example #7
0
 def test_run(self):
     """
     Test that the component runs its activities.
     """
     # Set up the general ledger so that an activity can create a
     # transaction.
     structure = GeneralLedgerStructure("NameA", description="DescriptionA")
     gl = GeneralLedger("NameA", structure, description="DescriptionA")
     # Prepare the component for a run. Tick the clock to the correct place
     # for the activity to create a transaction.
     clock = Clock("NameA", start_datetime=datetime(2016, 1, 1))
     clock.tick()
     clock.tick()
     self.object.prepare_to_run(clock, 20)
     self.object.run(clock, gl)
     # If the activity has been run, then a transaction should have
     # been generated.
     self.assertEqual(len(gl.transactions), 1)
Example #8
0
 def test_run(self):
     """
     Test that the component runs its activities.
     """
     # Set up the general ledger so that an activity can create a
     # transaction.
     structure = GeneralLedgerStructure("NameA", description="DescriptionA")
     gl = GeneralLedger("NameA", structure, description="DescriptionA")
     # Prepare the component for a run. Tick the clock to the correct place
     # for the activity to create a transaction.
     clock = Clock("NameA", start_datetime=datetime(2016, 1, 1))
     clock.tick()
     clock.tick()
     self.object.prepare_to_run(clock, 20)
     self.object.run(clock, gl)
     # If the activity has been run, then a transaction should have
     # been generated.
     self.assertEqual(len(gl.transactions), 1)
Example #9
0
 def test_prepare_to_run(self):
     """
     Test that the component run's its activities' prepare_to_run methods.
     """
     clock = Clock("NameA", start_datetime=datetime(2016, 1, 1))
     self.object.prepare_to_run(clock, 18)
     # The activity's start and end period indexes should be changed.
     self.assertEqual(
         self.object.components[0].activities[0].start_period_ix, 2)
     self.assertEqual(self.object.components[0].activities[0].end_period_ix,
                      14)
Example #10
0
    def test__meet_execution_criteria(self):
        """
        Test that the activity only meets the execution criteria when
        it's amount is greater than 0.
        """

        clock = Clock("NameA", start_datetime=datetime(2016, 1, 1))
        self.object.prepare_to_run(clock, 13)
        self.assertEqual(self.object._meet_execution_criteria(5), True)
        self.object.amount = 0
        self.assertEqual(self.object._meet_execution_criteria(5), False)
Example #11
0
 def __init__(self,
              name,
              description=None,
              start_datetime=datetime.now(),
              period_duration=TimePeriod.year,
              period_count=1):
     self.clock = Clock(
         "Clock",
         start_datetime=get_date(start_datetime),
         timestep_period_duration=period_duration)
     self.period_count = period_count
     self.entities = []
     super(TimeBasedModel, self).__init__(name, description=description)
Example #12
0
    def setUp(self):
        self.gl_structure = GeneralLedgerStructure(
            "GL Structure", description="General Ledger Structure")
        self.gl_structure["Account Payable"].create_account(
            "Capital Loan", "0000")
        self.gl_structure["Expense"].create_account("Interest Expense", "0000")

        self.gl = GeneralLedger("GL",
                                self.gl_structure,
                                description="General Ledger")

        self.clock = Clock("NameA", start_datetime=datetime(2016, 2, 1))

        self.object = BasicLoanActivity(
            "Capital Loan",
            bank_account="Bank/Default",
            loan_account="Account Payable/Capital Loan",
            interest_account="Expense/Interest Expense",
            amount=180000,
            interest_rate=0.15,
            start=datetime(2016, 2, 1),
            duration=36,
            interval=1,
            description="Loan for Capital")
Example #13
0
class ClockUnitTester(unittest.TestCase):
    """
    Tester for the auxi.core.time.Clock class.
    """

    def setUp(self):
        self.object = Clock("NameA",
                            description="DescriptionA",
                            start_datetime=datetime(2016, 2, 1),
                            timestep_period_duration=TimePeriod.year,
                            timestep_period_count=3)

    def test_constructor(self):
        self.assertEqual(self.object.name, "NameA")
        self.assertEqual(self.object.description, "DescriptionA")
        self.assertEqual(self.object.start_datetime, datetime(2016, 2, 1))
        self.assertEqual(self.object.timestep_period_duration, TimePeriod.year)
        self.assertEqual(self.object.timestep_period_count, 3)

    def test_tick(self):
        self.assertEqual(self.object.timestep_ix, 0)
        self.object.tick()
        self.assertEqual(self.object.timestep_ix, 1)

    def test_reset(self):
        self.object.tick()
        self.object.reset()
        self.assertEqual(self.object.timestep_ix, 0)

    def test_get_datetime_at_period_ix(self):
        self.assertEqual(self.object.get_datetime_at_period_ix(3),
                         datetime(2019, 2, 1))

    def test_get_datetime(self):
        self.object.tick()
        self.assertEqual(self.object.get_datetime(), datetime(2017, 2, 1))
Example #14
0
class ClockUnitTester(unittest.TestCase):
    """
    Tester for the auxi.core.time.Clock class.
    """

    def setUp(self):
        self.object = Clock("NameA",
                            description="DescriptionA",
                            start_datetime=datetime(2016, 2, 1),
                            timestep_period_duration=TimePeriod.year,
                            timestep_period_count=3)

    def test_constructor(self):
        self.assertEqual(self.object.name, "NameA")
        self.assertEqual(self.object.description, "DescriptionA")
        self.assertEqual(self.object.start_datetime, datetime(2016, 2, 1))
        self.assertEqual(self.object.timestep_period_duration, TimePeriod.year)
        self.assertEqual(self.object.timestep_period_count, 3)

    def test_tick(self):
        self.assertEqual(self.object.timestep_ix, 0)
        self.object.tick()
        self.assertEqual(self.object.timestep_ix, 1)

    def test_reset(self):
        self.object.tick()
        self.object.reset()
        self.assertEqual(self.object.timestep_ix, 0)

    def test_get_datetime_at_period_ix(self):
        self.assertEqual(self.object.get_datetime_at_period_ix(3),
                         datetime(2019, 2, 1))

    def test_get_datetime(self):
        self.object.tick()
        self.assertEqual(self.object.get_datetime(), datetime(2017, 2, 1))
Example #15
0
class EntityUnitTester(unittest.TestCase):
    """
    Tester for the auxi.modelling.entity.component class.
    """

    def setUp(self):
        self.gl_structure = GeneralLedgerStructure(
            "NameA",
            description="DescriptionA")
        self.sales_acc = self.gl_structure._acci_sales_.create_account(
            "sales_default",
            "0000")
        self.cos_acc = self.gl_structure._acci_cos_.create_account(
            "cos_default",
            "0000")
        self.reva_acc = self.gl_structure["Other Income"].create_account(
            "RevA",
            number="011")
        self.expa_acc = self.gl_structure["Expense"].create_account(
            "ExpenseA",
            number="011")

        self.object = Entity("EntityA",
                             gl_structure=self.gl_structure,
                             description="DescriptionA")
        # Set up the needed objects
        self.comp1 = self.object.create_component("ComponentA1",
                                                  description="ca1")
        basic_activity = BasicActivity("BasicActivityA",
                                       description="DescriptionA",
                                       dt_account="Bank",
                                       cr_account="Sales",
                                       amount=5000,
                                       start=datetime(2016, 2, 1),
                                       end=datetime(2017, 2, 1),
                                       interval=1)
        self.comp1.add_activity(basic_activity)

        self.clock = Clock("NameA", start_datetime=datetime(2016, 1, 1))

    def test_constructor(self):
        self.assertEqual(self.object.name, "EntityA")
        self.assertEqual(self.object.description, "DescriptionA")
        self.assertEqual(self.object.gl.structure.name, self.gl_structure.name)
        self.assertEqual(self.object.period_count, -1)

    def test_set_parent_path(self):
        self.object.set_parent_path("/modelA")
        self.assertEqual(self.object.path, "/modelA/EntityA")

    def test_set_name(self):
        """
        Test wether the name changes when it is set, that the entity's
        name changes and that the component's children's paths are updated
        correctly.
        """

        self.object.set_parent_path("modelA")
        self.object.name = "NameAt"
        self.assertEqual(self.object.name, "NameAt")
        self.assertEqual(self.object.components[0].path,
                         "modelA/NameAt/ComponentA1")
        self.assertEqual(self.object.components[0].activities[0].path,
                         "modelA/NameAt/ComponentA1/BasicActivityA")

    def test_getitem_exists(self):
        self.assertEqual(
            self.comp1,
            self.object["ComponentA1"])

    def test_getitem_not_exists(self):
        self.assertRaises(IndexError, self.object.__getitem__, "ComponentA3")

    def test_create_component(self):
        new_comp = self.object.create_component("ComponentA2",
                                                description="ca2")
        self.assertEqual(new_comp.name, "ComponentA2")
        self.assertEqual(new_comp.description, "ca2")

        self.assertEqual(new_comp, self.object.components[1])

    def test_remove_component(self):
        self.object.create_component("ComponentA2",
                                     description="ca2")
        self.object.remove_component("ComponentA2")
        self.assertEqual(len(self.object.components), 1)

    def test_prepare_to_run(self):
        """
        Test that the entity run's its component' prepare_to_run methods.
        """

        # Test the prepare to run method before any run has been performed
        self.object.gl.create_transaction(
            "TestA",
            description="TestA_Desc",
            tx_date=datetime(2016, 2, 1).date(),
            dt_account="Bank",
            cr_account="Sales",
            source="Peanut Sales",
            amount=20.00)
        self.object.negative_income_tax_total = 99

        self.object.prepare_to_run(self.clock, 18)

        # Was the component's prepare to run executed?
        self.assertEqual(
            self.object.components[0].activities[0].start_period_ix, 2)
        self.assertEqual(
            self.object.components[0].activities[0].end_period_ix, 14)
        # Was the datetime's set correctly?
        self.assertEqual(
            self.object._exec_year_end_datetime,
            self.clock.get_datetime_at_period_ix(18))
        self.assertEqual(
            self.object._prev_year_end_datetime,
            self.clock.start_datetime)
        self.assertEqual(
            self.object._curr_year_end_datetime,
            self.clock.start_datetime + relativedelta(years=1))
        # Was the transactions cleared?
        self.assertEqual(len(self.object.gl.transactions), 0)
        # Was the negative tax income reset to 0?
        self.assertEqual(self.object.negative_income_tax_total, 0)

    def test_run(self):
        """
        Test that the entity runs its components.
        """

        self.object.prepare_to_run(self.clock, 20)
        self.clock.tick()
        self.clock.tick()
        self.object.run(self.clock)
        self.assertEqual(len(self.object.gl.transactions), 1)
        self.assertEqual(self.object.gl.transactions[0].amount, 5000)

    def test__perform_year_end_gross_profit_and_income_summary(self):
        """
        Test that the year end gross profit and income summary accounts
        are summed up correctly.
        """

        gls = self.object.gl.structure
        year_end_datetime = datetime(2017, 2, 1)
        # Create the accounts to write of dict
        income_summary_write_off_accounts = collections.OrderedDict([
            (self.cos_acc, 700),
            (gls._acci_inc_tax_exp_acc_, -300),
            (self.sales_acc, 70),
            (gls._accb_bank_["Default"], -30)])
        gross_profit_write_off_accounts = collections.OrderedDict([
            (self.sales_acc, 70),
            (gls._accb_bank_["Default"], -30)])
        # Test when there the gross profit is 0.
        # The gross profit account should not be settled:
        inc = self.object._perform_year_end_gross_profit_and_income_summary(
            year_end_datetime,
            {},
            income_summary_write_off_accounts)
        # The gross profit account should not be settled.
        # Only the 4 transactions from the income summary year end calcs
        # should be there
        self.assertEqual(len(self.object.gl.transactions), 4)
        # The income summary should be that of the income summary year end calc
        # method: -360 (See the income summary year end calc, in this case,
        # gross profit starts at 0 instead of 5000, thus -360 instead of 4640)
        self.assertEqual(inc, -360)

        # Test when there is gross profit.
        # The gross profit account should not be settled:
        del self.object.gl.transactions[:]  # Clear the tx list
        self.object._perform_year_end_gross_profit_and_income_summary(
            year_end_datetime,
            gross_profit_write_off_accounts, {})
        # The gross profit account should be settled.
        # Only the 2 transactions from the income summary year end calcs
        # should be there as well as the gross profit settle transaction
        self.assertEqual(len(self.object.gl.transactions), 3)
        # Make sure the gross profit settle transaction appears correct
        # When gross profit is positive:
        self.assertEqual(self.object.gl.transactions[2].dt_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[2].cr_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[2].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[2].amount, 40)
        self.assertEqual(self.object.gl.transactions[2].is_closing_cr_account,
                         True)
        # When gross profit is negative:
        gross_profit_write_off_accounts = collections.OrderedDict([
            (self.sales_acc, -70),
            (gls._accb_bank_["Default"], 30)])
        del self.object.gl.transactions[:]  # Clear the tx list
        self.object._perform_year_end_gross_profit_and_income_summary(
            year_end_datetime,
            gross_profit_write_off_accounts, {})
        self.assertEqual(self.object.gl.transactions[2].dt_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[2].cr_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[2].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[2].amount, 40)
        self.assertEqual(self.object.gl.transactions[2].is_closing_cr_account,
                         True)

    def test__perform_year_end_gross_profit(self):
        """
        Test that the year end gross profit account is closed correctly.
        """

        gls = self.object.gl.structure
        year_end_datetime = datetime(2017, 2, 1)

        # Create the accounts to write of dict
        gross_profit_write_off_accounts = collections.OrderedDict([
            (self.sales_acc, 70),
            (gls._accb_bank_["Default"], -30)])
        gross_profit = self.object._perform_year_end_gross_profit(
            year_end_datetime, gross_profit_write_off_accounts)
        self.assertEqual(len(self.object.gl.transactions), 2)
        # Expenses: 700-300 = 400
        # Other: 70-30 = 40
        # Total: gross_profit + Other - expenses: 5000 + 40 - 400 = 4640
        self.assertEqual(gross_profit, 40)

        # Test the "self.sales_acc: 70" transaction
        self.assertEqual(self.object.gl.transactions[0].dt_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[0].cr_account,
                         self.sales_acc.path)
        self.assertEqual(self.object.gl.transactions[0].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[0].amount, 70)
        self.assertEqual(self.object.gl.transactions[0].is_closing_cr_account,
                         True)

        # Test the "gls._accb_bank_["Default"]: -30" transaction
        self.assertEqual(self.object.gl.transactions[1].dt_account,
                         gls._accb_bank_["Default"].path)
        self.assertEqual(self.object.gl.transactions[1].cr_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[1].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[1].amount, 30)
        self.assertEqual(self.object.gl.transactions[1].is_closing_cr_account,
                         True)

    def test__perform_year_end_income_summary(self):
        """
        Test that the year end income summary account is closed correctly.
        """

        gls = self.object.gl.structure
        year_end_datetime = datetime(2017, 2, 1)
        gross_profit = 5000

        # Create the accounts to write of dict
        income_summary_write_off_accounts = collections.OrderedDict([
            (self.cos_acc, 700),
            (gls._acci_inc_tax_exp_acc_, -300),
            (self.sales_acc, 70),
            (gls._accb_bank_["Default"], -30)])
        income_summary_amount = self.object._perform_year_end_income_summary(
            year_end_datetime, gross_profit, income_summary_write_off_accounts)
        self.assertEqual(len(self.object.gl.transactions), 4)
        # Expenses: 700-300 = 400
        # Other: 70-30 = 40
        # Total: gross_profit + Other - expenses: 5000 + 40 - 400 = 4640
        self.assertEqual(income_summary_amount, 4640)

        # Test the "self.cos_acc: 700" transaction
        self.assertEqual(self.object.gl.transactions[0].dt_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[0].cr_account,
                         self.cos_acc.path)
        self.assertEqual(self.object.gl.transactions[0].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[0].amount, 700)
        self.assertEqual(self.object.gl.transactions[0].is_closing_cr_account,
                         True)

        # Test the "gls._acci_inc_tax_exp_acc_: -300" transaction
        self.assertEqual(self.object.gl.transactions[1].dt_account,
                         gls._acci_inc_tax_exp_acc_.path)
        self.assertEqual(self.object.gl.transactions[1].cr_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[1].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[1].amount, 300)
        self.assertEqual(self.object.gl.transactions[1].is_closing_cr_account,
                         True)

        # Test the "self.sales_acc: 70" transaction
        self.assertEqual(self.object.gl.transactions[2].dt_account,
                         self.sales_acc.path)
        self.assertEqual(self.object.gl.transactions[2].cr_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[2].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[2].amount, 70)
        self.assertEqual(self.object.gl.transactions[2].is_closing_cr_account,
                         True)

        # Test the "gls._accb_bank_["Default"]: -30" transaction
        self.assertEqual(self.object.gl.transactions[3].dt_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[3].cr_account,
                         gls._accb_bank_["Default"].path)
        self.assertEqual(self.object.gl.transactions[3].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[3].amount, 30)
        self.assertEqual(self.object.gl.transactions[3].is_closing_cr_account,
                         True)

    def test__perform_year_end_income_tax(self):
        # TODO
        pass

    def test__perform_year_end_retained_earnings(self):
        """
        Test that the year end retained earnings account is closed correctly.
        """

        gls = self.object.gl.structure
        year_end_datetime = datetime(2017, 2, 1)
        # Test for == 0 case
        income_summary = 0
        self.object._perform_year_end_retained_earnings(
            year_end_datetime, income_summary)
        self.assertEqual(len(self.object.gl.transactions), 0)

        # Test for > 0 case
        income_summary = 1000
        self.object._perform_year_end_retained_earnings(
            year_end_datetime, income_summary)
        self.assertEqual(len(self.object.gl.transactions), 1)
        self.assertEqual(self.object.gl.transactions[0].dt_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[0].cr_account,
                         gls._accb_ret_earnings_acc_.path)
        self.assertEqual(self.object.gl.transactions[0].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[0].amount,
                         income_summary)
        self.assertEqual(self.object.gl.transactions[0].is_closing_cr_account,
                         True)

        # Test for < 0 case
        income_summary = -300
        self.object._perform_year_end_retained_earnings(
            year_end_datetime, income_summary)
        self.assertEqual(len(self.object.gl.transactions), 2)
        self.assertEqual(self.object.gl.transactions[1].dt_account,
                         gls._accb_ret_earnings_acc_.path)
        self.assertEqual(self.object.gl.transactions[1].cr_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[1].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[1].amount,
                         income_summary)
        self.assertEqual(self.object.gl.transactions[1].is_closing_cr_account,
                         True)

    def test__perform_year_end_procedure(self):
        """
        Test that all the year end accounts has been closed of correctly.
        """

        gls = self.object.gl.structure
        # Test when that no year end transactions are created in the
        # middle of a year
        self.object.prepare_to_run(self.clock, 28)
        self.clock.timestep_ix = 6
        # create the transactions
        self.object.gl.create_transaction(
            "Sales_tx",
            description="Sales tx",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=gls._accb_bank_["Default"].path,  # Bank account
            cr_account=self.sales_acc.path,
            source=self.object.path,
            amount=70)
        # create the transactions
        self.object.gl.create_transaction(
            "Cost_of_Sales_tx",
            description="Cost of Sales tx",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=self.cos_acc.path,
            cr_account=gls._accb_bank_["Default"].path,  # Bank account
            source=self.object.path,
            amount=30)
        self.object._perform_year_end_procedure(self.clock)
        # Only one transaction should have been created and no
        # year end transactions.
        self.assertEqual(len(self.object.gl.transactions), 2)

        # Test that the year end procedure, at the year end, creates
        #   - two gross profit transactions with values of 70 and 40
        #   - one gross profit and income summary settle transaction
        #      with a value of 70 - 30
        #   - one retained earnings transaction with a value of 70 - 30
        # Only the 2 transaction (sales tx, and cost of sales tx) and the
        # 4 'year end' transactions should have been created.)
        self.clock.timestep_ix = 12
        self.object._perform_year_end_procedure(self.clock)

        self.assertEqual(len(self.object.gl.transactions), 6)
        self.assertEqual(self.object.gl.transactions[2].amount, 70)
        self.assertEqual(self.object.gl.transactions[2].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[2].dt_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[2].cr_account,
                         self.sales_acc.path)

        self.assertEqual(self.object.gl.transactions[3].amount, 30)
        self.assertEqual(self.object.gl.transactions[3].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[3].dt_account,
                         self.cos_acc.path)
        self.assertEqual(self.object.gl.transactions[3].cr_account,
                         gls._acci_gross_prof_.path)

        self.assertEqual(self.object.gl.transactions[4].amount, 40)
        self.assertEqual(self.object.gl.transactions[4].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[4].dt_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[4].cr_account,
                         gls._acci_inc_sum_.path)

        self.assertEqual(self.object.gl.transactions[5].amount, 40)
        self.assertEqual(self.object.gl.transactions[5].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[5].dt_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[5].cr_account,
                         gls._accb_ret_earnings_acc_.path)

        # Test for a new year
        self.clock.timestep_ix = 18
        # Test for when other revenue and expense accounts transactions
        # exists as well.

        # create a sales transactions
        self.object.gl.create_transaction(
            "SalesTx2",
            description="Sales tx2",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=gls._accb_bank_["Default"].path,  # Bank account
            cr_account=self.sales_acc.path,
            source=self.object.path,
            amount=45)
        self.object.gl.create_transaction(
            "SalesTx3",
            description="Sales tx3",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=gls._accb_bank_["Default"].path,  # Bank account
            cr_account=self.sales_acc.path,
            source=self.object.path,
            amount=35)
        self.object.gl.create_transaction(
            "Cost_of_Sales_tx2",
            description="Cost of Sales tx 2",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=self.cos_acc.path,
            cr_account=gls._accb_bank_["Default"].path,  # Bank account
            source=self.object.path,
            amount=15)
        self.object.gl.create_transaction(
            "Cost_of_Sales_tx3",
            description="Cost of Sales tx 3",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=self.cos_acc.path,
            cr_account=gls._accb_bank_["Default"].path,  # Bank account
            source=self.object.path,
            amount=5)
        # create the transactions
        self.object.gl.create_transaction(
            "revenueATx",
            description="revenue a tx",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=gls._accb_bank_["Default"].path,  # Bank account
            cr_account=self.reva_acc.path,
            source=self.object.path,
            amount=450)
        self.object.gl.create_transaction(
            "revenueATx2",
            description="revenue a tx2",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=gls._accb_bank_["Default"].path,  # Bank account
            cr_account=self.reva_acc.path,
            source=self.object.path,
            amount=350)
        # create the transactions
        self.object.gl.create_transaction(
            "expenseAtx",
            description="expense a tx",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=self.expa_acc.path,
            cr_account=gls._accb_bank_["Default"].path,  # Bank account
            source=self.object.path,
            amount=320)
        self.object.gl.create_transaction(
            "expenseAtx2",
            description="expense a tx2",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=self.expa_acc.path,
            cr_account=gls._accb_bank_["Default"].path,  # Bank account
            source=self.object.path,
            amount=180)

        # Test that the year end procedure, at the year end, creates
        #   - two gross profit transactions with values of 80 and 20
        #   - two income summary transactions with values of 800 and 500
        #   - one gross profit and income summary settle transaction
        #      with a value of 80 - 20
        #   - one retained earnings transaction with a value of
        #      800 - 500 + 80 - 20
        # Only the 6 transactions (2 sales tx, 2 cost of sales,
        # 2 revenue a and 2 expense a) and the 5 'year end' transactions
        # should have been created.)
        self.clock.timestep_ix = 24
        self.object._perform_year_end_procedure(self.clock)

        self.assertEqual(len(self.object.gl.transactions), 20)
        self.assertEqual(self.object.gl.transactions[14].amount, 80)
        self.assertEqual(self.object.gl.transactions[14].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[14].dt_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[14].cr_account,
                         self.sales_acc.path)

        self.assertEqual(self.object.gl.transactions[15].amount, 20)
        self.assertEqual(self.object.gl.transactions[15].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[15].dt_account,
                         self.cos_acc.path)
        self.assertEqual(self.object.gl.transactions[15].cr_account,
                         gls._acci_gross_prof_.path)

        self.assertEqual(self.object.gl.transactions[16].amount, 800)
        self.assertEqual(self.object.gl.transactions[16].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[16].dt_account,
                         self.reva_acc.path)
        self.assertEqual(self.object.gl.transactions[16].cr_account,
                         gls._acci_inc_sum_.path)

        self.assertEqual(self.object.gl.transactions[17].amount, 500)
        self.assertEqual(self.object.gl.transactions[17].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[17].dt_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[17].cr_account,
                         self.expa_acc.path)

        self.assertEqual(self.object.gl.transactions[18].amount, 60)
        self.assertEqual(self.object.gl.transactions[18].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[18].dt_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[18].cr_account,
                         gls._acci_inc_sum_.path)

        self.assertEqual(self.object.gl.transactions[19].amount, 360)
        self.assertEqual(self.object.gl.transactions[19].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[19].dt_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[19].cr_account,
                         gls._accb_ret_earnings_acc_.path)
Example #16
0
class BasicLoanActivityUnitTester(unittest.TestCase):
    """
    Tester for the auxi.modelling.business.basic.BasicLoanActivity class.
    """

    def setUp(self):
        self.gl_structure = GeneralLedgerStructure(
            "GL Structure",
            description="General Ledger Structure")
        self.gl_structure["Account Payable"].create_account(
            "Capital Loan",
            "0000")
        self.gl_structure["Expense"].create_account(
            "Interest Expense",
            "0000")

        self.gl = GeneralLedger(
            "GL",
            self.gl_structure,
            description="General Ledger")

        self.clock = Clock("NameA", start_datetime=datetime(2016, 2, 1))

        self.object = BasicLoanActivity(
            "Capital Loan",
            bank_account="Bank/Default",
            loan_account="Account Payable/Capital Loan",
            interest_account="Expense/Interest Expense",
            amount=180000,
            interest_rate=0.15,
            start=datetime(2016, 2, 1),
            duration=36,
            interval=1,
            description="Loan for Capital")

    def test_constructor(self):
        self.assertEqual(self.object.name, "Capital Loan")
        self.assertEqual(self.object.bank_account, "Bank/Default")
        self.assertEqual(
            self.object.loan_account, "Account Payable/Capital Loan")
        self.assertEqual(
            self.object.interest_account, "Expense/Interest Expense")
        self.assertEqual(self.object.amount, 180000)
        self.assertEqual(self.object.interest_rate, 0.15)
        self.assertEqual(self.object.start_datetime, datetime(2016, 2, 1))
        self.assertEqual(self.object.end_datetime, datetime(2019, 3, 1))
        self.assertEqual(self.object.duration, 36)
        self.assertEqual(self.object.interval, 1)
        self.assertEqual(self.object.description, "Loan for Capital")

    def test__meet_exection_criteria(self):
        """
        Test that the activity only meets the execution criteria when
        it's amount is greater than 0 and its duration is greater than 0.
        """

        self.object.prepare_to_run(self.clock, 13)
        self.assertEqual(self.object._meet_execution_criteria(5), True)
        self.object.amount = 0
        self.assertEqual(self.object._meet_execution_criteria(5), False)
        self.object.amount = 180000
        self.object.duration = 0
        self.assertEqual(self.object._meet_execution_criteria(5), False)

    def test_run_first_month(self):
        """
        Test that the activity run method creates a transaction with an amount
        of 180000 on the first month. No other transactions
        """

        self.object.prepare_to_run(self.clock, 1)
        self.object.run(self.clock, self.gl)
        self.assertEqual(len(self.gl.transactions), 1)
        self.assertEqual(self.gl.transactions[0].amount, 180000)

    def test_run_third_month(self):
        """
        Test that the activity run method accrued the interest correctly.
        """

        self.clock.tick()
        self.object.prepare_to_run(self.clock, 61)
        self.clock.tick()
        self.object.run(self.clock, self.gl)
        self.clock.tick()
        self.object.run(self.clock, self.gl)
        self.clock.tick()
        self.object.run(self.clock, self.gl)
        self.assertEqual(len(self.gl.transactions), 5)
        # Test the intreset rate for the first month
        # loan amount = 180000
        # First month's interest should be (180000 * 0.15) / 12 = 2250
        self.assertEqual(self.gl.transactions[1].amount, 2250)
        # Principle payment is 6239.76 (see below)
        # The interest payed the previous month is 2250
        # Making the total amount payed to the loan 6239.76 - 2250 = 3,989.76
        # New amount to calculate interest from: 180000 - 3,989.76 = 176,010.24
        # 2nd month's interest should be 176,010.24 * 0.15) / 12 = 2,200.13
        self.assertEqual("%.2f" % self.gl.transactions[3].amount, "2200.13")
        # Test the monthly principle payment
        # interest rate = 0.15: per month 0.0125.
        # loan amount = 180000
        # duration of the loan = 36
        # payment = (180000*0.0125) / (1-(1/pow((1+0.0125), 36))) = 6239.76
        self.assertEqual("%.2f" % self.gl.transactions[2].amount, "6239.76")
        self.assertEqual("%.2f" % self.gl.transactions[4].amount, "6239.76")

    def test_run_last_month(self):
        """
        Test that the activity run method creates settled the loan on the
        loans' last month and that the transactions
        """

        self.clock.tick()
        self.object.prepare_to_run(self.clock, 61)
        for i in range(0, 60):
            self.object.run(self.clock, self.gl)
            self.clock.tick()
        # Test the number of transaction that was created during the
        # loan's lifetime.
        # 2 transactions per months should be created + the initial loan amount
        # transaction. 36*2 + 1 = 73
        last_tx_ix = len(self.gl.transactions)
        self.assertEqual(len(self.gl.transactions), 73)
        # The transactions should have run only run for 36 months
        # (the duration of the loan)
        r = relativedelta.relativedelta(
            self.gl.transactions[last_tx_ix-1].tx_date,
            self.gl.transactions[0].tx_date)
        self.assertEqual(r.years * 12 + r.months, 36)

    def test_get_referenced_accounts(self):
        """
        Test that the activity run method get_referenced_accounts accounts
        matches the debit and credit accounts self.object was initialised with.
        """

        result = self.object.get_referenced_accounts()
        self.assertEqual(self.object.bank_account, result[0])
        self.assertEqual(self.object.loan_account, result[1])
        self.assertEqual(self.object.interest_account, result[2])
Example #17
0
class EntityUnitTester(unittest.TestCase):
    """
    Tester for the auxi.modelling.entity.component class.
    """
    def setUp(self):
        self.gl_structure = GeneralLedgerStructure("NameA",
                                                   description="DescriptionA")
        self.sales_acc = self.gl_structure._acci_sales_.create_account(
            "sales_default", "0000")
        self.cos_acc = self.gl_structure._acci_cos_.create_account(
            "cos_default", "0000")
        self.reva_acc = self.gl_structure["Other Income"].create_account(
            "RevA", number="011")
        self.expa_acc = self.gl_structure["Expense"].create_account(
            "ExpenseA", number="011")

        self.object = Entity("EntityA",
                             gl_structure=self.gl_structure,
                             description="DescriptionA")
        # Set up the needed objects
        self.comp1 = self.object.create_component("ComponentA1",
                                                  description="ca1")
        basic_activity = BasicActivity("BasicActivityA",
                                       description="DescriptionA",
                                       dt_account="Bank",
                                       cr_account="Sales",
                                       amount=5000,
                                       start=datetime(2016, 2, 1),
                                       end=datetime(2017, 2, 1),
                                       interval=1)
        self.comp1.add_activity(basic_activity)

        self.clock = Clock("NameA", start_datetime=datetime(2016, 1, 1))

    def test_constructor(self):
        self.assertEqual(self.object.name, "EntityA")
        self.assertEqual(self.object.description, "DescriptionA")
        self.assertEqual(self.object.gl.structure.name, self.gl_structure.name)
        self.assertEqual(self.object.period_count, -1)

    def test_set_parent_path(self):
        self.object.set_parent_path("/modelA")
        self.assertEqual(self.object.path, "/modelA/EntityA")

    def test_set_name(self):
        """
        Test whether the name changes when it is set, that the entity's
        name changes and that the component's children's paths are updated
        correctly.
        """

        self.object.set_parent_path("modelA")
        self.object.name = "NameAt"
        self.assertEqual(self.object.name, "NameAt")
        self.assertEqual(self.object.components[0].path,
                         "modelA/NameAt/ComponentA1")
        self.assertEqual(self.object.components[0].activities[0].path,
                         "modelA/NameAt/ComponentA1/BasicActivityA")

    def test_getitem_exists(self):
        self.assertEqual(self.comp1, self.object["ComponentA1"])

    def test_getitem_not_exists(self):
        self.assertRaises(IndexError, self.object.__getitem__, "ComponentA3")

    def test_create_component(self):
        new_comp = self.object.create_component("ComponentA2",
                                                description="ca2")
        self.assertEqual(new_comp.name, "ComponentA2")
        self.assertEqual(new_comp.description, "ca2")

        self.assertEqual(new_comp, self.object.components[1])

    def test_remove_component(self):
        self.object.create_component("ComponentA2", description="ca2")
        self.object.remove_component("ComponentA2")
        self.assertEqual(len(self.object.components), 1)

    def test_prepare_to_run(self):
        """
        Test that the entity run's its component' prepare_to_run methods.
        """

        # Test the prepare to run method before any run has been performed
        self.object.gl.create_transaction("TestA",
                                          description="TestA_Desc",
                                          tx_date=datetime(2016, 2, 1).date(),
                                          dt_account="Bank",
                                          cr_account="Sales",
                                          source="Peanut Sales",
                                          amount=20.00)
        self.object.negative_income_tax_total = 99

        self.object.prepare_to_run(self.clock, 18)

        # Was the component's prepare to run executed?
        self.assertEqual(
            self.object.components[0].activities[0].start_period_ix, 2)
        self.assertEqual(self.object.components[0].activities[0].end_period_ix,
                         14)
        # Was the datetime's set correctly?
        self.assertEqual(self.object._exec_year_end_datetime,
                         self.clock.get_datetime_at_period_ix(18))
        self.assertEqual(self.object._prev_year_end_datetime,
                         self.clock.start_datetime)
        self.assertEqual(self.object._curr_year_end_datetime,
                         self.clock.start_datetime + relativedelta(years=1))
        # Was the transactions cleared?
        self.assertEqual(len(self.object.gl.transactions), 0)
        # Was the negative tax income reset to 0?
        self.assertEqual(self.object.negative_income_tax_total, 0)

    def test_run(self):
        """
        Test that the entity runs its components.
        """

        self.object.prepare_to_run(self.clock, 20)
        self.clock.tick()
        self.clock.tick()
        self.object.run(self.clock)
        self.assertEqual(len(self.object.gl.transactions), 1)
        self.assertEqual(self.object.gl.transactions[0].amount, 5000)

    def test__perform_year_end_gross_profit_and_income_summary(self):
        """
        Test that the year end gross profit and income summary accounts
        are summed up correctly.
        """

        gls = self.object.gl.structure
        year_end_datetime = datetime(2017, 2, 1)
        # Create the accounts to write of dict
        income_summary_write_off_accounts = collections.OrderedDict([
            (self.cos_acc, 700), (gls._acci_inc_tax_exp_acc_, -300),
            (self.sales_acc, 70), (gls._accb_bank_["Default"], -30)
        ])
        gross_profit_write_off_accounts = collections.OrderedDict([
            (self.sales_acc, 70), (gls._accb_bank_["Default"], -30)
        ])
        # Test when there the gross profit is 0.
        # The gross profit account should not be settled:
        inc = self.object._perform_year_end_gross_profit_and_income_summary(
            year_end_datetime, {}, income_summary_write_off_accounts)
        # The gross profit account should not be settled.
        # Only the 4 transactions from the income summary year end calcs
        # should be there
        self.assertEqual(len(self.object.gl.transactions), 4)
        # The income summary should be that of the income summary year end calc
        # method: -360 (See the income summary year end calc, in this case,
        # gross profit starts at 0 instead of 5000, thus -360 instead of 4640)
        self.assertEqual(inc, -360)

        # Test when there is gross profit.
        # The gross profit account should not be settled:
        del self.object.gl.transactions[:]  # Clear the tx list
        self.object._perform_year_end_gross_profit_and_income_summary(
            year_end_datetime, gross_profit_write_off_accounts, {})
        # The gross profit account should be settled.
        # Only the 2 transactions from the income summary year end calcs
        # should be there as well as the gross profit settle transaction
        self.assertEqual(len(self.object.gl.transactions), 3)
        # Make sure the gross profit settle transaction appears correct
        # When gross profit is positive:
        self.assertEqual(self.object.gl.transactions[2].dt_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[2].cr_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[2].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[2].amount, 40)
        self.assertEqual(self.object.gl.transactions[2].is_closing_cr_account,
                         True)
        # When gross profit is negative:
        gross_profit_write_off_accounts = collections.OrderedDict([
            (self.sales_acc, -70), (gls._accb_bank_["Default"], 30)
        ])
        del self.object.gl.transactions[:]  # Clear the tx list
        self.object._perform_year_end_gross_profit_and_income_summary(
            year_end_datetime, gross_profit_write_off_accounts, {})
        self.assertEqual(self.object.gl.transactions[2].dt_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[2].cr_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[2].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[2].amount, 40)
        self.assertEqual(self.object.gl.transactions[2].is_closing_cr_account,
                         True)

    def test__perform_year_end_gross_profit(self):
        """
        Test that the year end gross profit account is closed correctly.
        """

        gls = self.object.gl.structure
        year_end_datetime = datetime(2017, 2, 1)

        # Create the accounts to write of dict
        gross_profit_write_off_accounts = collections.OrderedDict([
            (self.sales_acc, 70), (gls._accb_bank_["Default"], -30)
        ])
        gross_profit = self.object._perform_year_end_gross_profit(
            year_end_datetime, gross_profit_write_off_accounts)
        self.assertEqual(len(self.object.gl.transactions), 2)
        # Expenses: 700-300 = 400
        # Other: 70-30 = 40
        # Total: gross_profit + Other - expenses: 5000 + 40 - 400 = 4640
        self.assertEqual(gross_profit, 40)

        # Test the "self.sales_acc: 70" transaction
        self.assertEqual(self.object.gl.transactions[0].dt_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[0].cr_account,
                         self.sales_acc.path)
        self.assertEqual(self.object.gl.transactions[0].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[0].amount, 70)
        self.assertEqual(self.object.gl.transactions[0].is_closing_cr_account,
                         True)

        # Test the "gls._accb_bank_["Default"]: -30" transaction
        self.assertEqual(self.object.gl.transactions[1].dt_account,
                         gls._accb_bank_["Default"].path)
        self.assertEqual(self.object.gl.transactions[1].cr_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[1].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[1].amount, 30)
        self.assertEqual(self.object.gl.transactions[1].is_closing_cr_account,
                         True)

    def test__perform_year_end_income_summary(self):
        """
        Test that the year end income summary account is closed correctly.
        """

        gls = self.object.gl.structure
        year_end_datetime = datetime(2017, 2, 1)
        gross_profit = 5000

        # Create the accounts to write of dict
        income_summary_write_off_accounts = collections.OrderedDict([
            (self.cos_acc, 700), (gls._acci_inc_tax_exp_acc_, -300),
            (self.sales_acc, 70), (gls._accb_bank_["Default"], -30)
        ])
        income_summary_amount = self.object._perform_year_end_income_summary(
            year_end_datetime, gross_profit, income_summary_write_off_accounts)
        self.assertEqual(len(self.object.gl.transactions), 4)
        # Expenses: 700-300 = 400
        # Other: 70-30 = 40
        # Total: gross_profit + Other - expenses: 5000 + 40 - 400 = 4640
        self.assertEqual(income_summary_amount, 4640)

        # Test the "self.cos_acc: 700" transaction
        self.assertEqual(self.object.gl.transactions[0].dt_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[0].cr_account,
                         self.cos_acc.path)
        self.assertEqual(self.object.gl.transactions[0].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[0].amount, 700)
        self.assertEqual(self.object.gl.transactions[0].is_closing_cr_account,
                         True)

        # Test the "gls._acci_inc_tax_exp_acc_: -300" transaction
        self.assertEqual(self.object.gl.transactions[1].dt_account,
                         gls._acci_inc_tax_exp_acc_.path)
        self.assertEqual(self.object.gl.transactions[1].cr_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[1].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[1].amount, 300)
        self.assertEqual(self.object.gl.transactions[1].is_closing_cr_account,
                         True)

        # Test the "self.sales_acc: 70" transaction
        self.assertEqual(self.object.gl.transactions[2].dt_account,
                         self.sales_acc.path)
        self.assertEqual(self.object.gl.transactions[2].cr_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[2].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[2].amount, 70)
        self.assertEqual(self.object.gl.transactions[2].is_closing_cr_account,
                         True)

        # Test the "gls._accb_bank_["Default"]: -30" transaction
        self.assertEqual(self.object.gl.transactions[3].dt_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[3].cr_account,
                         gls._accb_bank_["Default"].path)
        self.assertEqual(self.object.gl.transactions[3].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[3].amount, 30)
        self.assertEqual(self.object.gl.transactions[3].is_closing_cr_account,
                         True)

    def test__perform_year_end_income_tax(self):
        # TODO
        pass

    def test__perform_year_end_retained_earnings(self):
        """
        Test that the year end retained earnings account is closed correctly.
        """

        gls = self.object.gl.structure
        year_end_datetime = datetime(2017, 2, 1)
        # Test for == 0 case
        income_summary = 0
        self.object._perform_year_end_retained_earnings(
            year_end_datetime, income_summary)
        self.assertEqual(len(self.object.gl.transactions), 0)

        # Test for > 0 case
        income_summary = 1000
        self.object._perform_year_end_retained_earnings(
            year_end_datetime, income_summary)
        self.assertEqual(len(self.object.gl.transactions), 1)
        self.assertEqual(self.object.gl.transactions[0].dt_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[0].cr_account,
                         gls._accb_ret_earnings_acc_.path)
        self.assertEqual(self.object.gl.transactions[0].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[0].amount, income_summary)
        self.assertEqual(self.object.gl.transactions[0].is_closing_cr_account,
                         True)

        # Test for < 0 case
        income_summary = -300
        self.object._perform_year_end_retained_earnings(
            year_end_datetime, income_summary)
        self.assertEqual(len(self.object.gl.transactions), 2)
        self.assertEqual(self.object.gl.transactions[1].dt_account,
                         gls._accb_ret_earnings_acc_.path)
        self.assertEqual(self.object.gl.transactions[1].cr_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[1].tx_date,
                         year_end_datetime)
        self.assertEqual(self.object.gl.transactions[1].amount, income_summary)
        self.assertEqual(self.object.gl.transactions[1].is_closing_cr_account,
                         True)

    def test__perform_year_end_procedure(self):
        """
        Test that all the year end accounts has been closed of correctly.
        """

        gls = self.object.gl.structure
        # Test when that no year end transactions are created in the
        # middle of a year
        self.object.prepare_to_run(self.clock, 28)
        self.clock.timestep_ix = 6
        # create the transactions
        self.object.gl.create_transaction(
            "Sales_tx",
            description="Sales tx",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=gls._accb_bank_["Default"].path,  # Bank account
            cr_account=self.sales_acc.path,
            source=self.object.path,
            amount=70)
        # create the transactions
        self.object.gl.create_transaction(
            "Cost_of_Sales_tx",
            description="Cost of Sales tx",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=self.cos_acc.path,
            cr_account=gls._accb_bank_["Default"].path,  # Bank account
            source=self.object.path,
            amount=30)
        self.object._perform_year_end_procedure(self.clock)
        # Only one transaction should have been created and no
        # year end transactions.
        self.assertEqual(len(self.object.gl.transactions), 2)

        # Test that the year end procedure, at the year end, creates
        #   - two gross profit transactions with values of 70 and 40
        #   - one gross profit and income summary settle transaction
        #      with a value of 70 - 30
        #   - one retained earnings transaction with a value of 70 - 30
        # Only the 2 transaction (sales tx, and cost of sales tx) and the
        # 4 'year end' transactions should have been created.)
        self.clock.timestep_ix = 12
        self.object._perform_year_end_procedure(self.clock)

        self.assertEqual(len(self.object.gl.transactions), 6)
        self.assertEqual(self.object.gl.transactions[2].amount, 70)
        self.assertEqual(self.object.gl.transactions[2].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[2].dt_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[2].cr_account,
                         self.sales_acc.path)

        self.assertEqual(self.object.gl.transactions[3].amount, 30)
        self.assertEqual(self.object.gl.transactions[3].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[3].dt_account,
                         self.cos_acc.path)
        self.assertEqual(self.object.gl.transactions[3].cr_account,
                         gls._acci_gross_prof_.path)

        self.assertEqual(self.object.gl.transactions[4].amount, 40)
        self.assertEqual(self.object.gl.transactions[4].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[4].dt_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[4].cr_account,
                         gls._acci_inc_sum_.path)

        self.assertEqual(self.object.gl.transactions[5].amount, 40)
        self.assertEqual(self.object.gl.transactions[5].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[5].dt_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[5].cr_account,
                         gls._accb_ret_earnings_acc_.path)

        # Test for a new year
        self.clock.timestep_ix = 18
        # Test for when other revenue and expense accounts transactions
        # exists as well.

        # create a sales transactions
        self.object.gl.create_transaction(
            "SalesTx2",
            description="Sales tx2",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=gls._accb_bank_["Default"].path,  # Bank account
            cr_account=self.sales_acc.path,
            source=self.object.path,
            amount=45)
        self.object.gl.create_transaction(
            "SalesTx3",
            description="Sales tx3",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=gls._accb_bank_["Default"].path,  # Bank account
            cr_account=self.sales_acc.path,
            source=self.object.path,
            amount=35)
        self.object.gl.create_transaction(
            "Cost_of_Sales_tx2",
            description="Cost of Sales tx 2",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=self.cos_acc.path,
            cr_account=gls._accb_bank_["Default"].path,  # Bank account
            source=self.object.path,
            amount=15)
        self.object.gl.create_transaction(
            "Cost_of_Sales_tx3",
            description="Cost of Sales tx 3",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=self.cos_acc.path,
            cr_account=gls._accb_bank_["Default"].path,  # Bank account
            source=self.object.path,
            amount=5)
        # create the transactions
        self.object.gl.create_transaction(
            "revenueATx",
            description="revenue a tx",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=gls._accb_bank_["Default"].path,  # Bank account
            cr_account=self.reva_acc.path,
            source=self.object.path,
            amount=450)
        self.object.gl.create_transaction(
            "revenueATx2",
            description="revenue a tx2",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=gls._accb_bank_["Default"].path,  # Bank account
            cr_account=self.reva_acc.path,
            source=self.object.path,
            amount=350)
        # create the transactions
        self.object.gl.create_transaction(
            "expenseAtx",
            description="expense a tx",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=self.expa_acc.path,
            cr_account=gls._accb_bank_["Default"].path,  # Bank account
            source=self.object.path,
            amount=320)
        self.object.gl.create_transaction(
            "expenseAtx2",
            description="expense a tx2",
            tx_date=self.clock.get_datetime_at_period_ix(
                self.clock.timestep_ix),
            dt_account=self.expa_acc.path,
            cr_account=gls._accb_bank_["Default"].path,  # Bank account
            source=self.object.path,
            amount=180)

        # Test that the year end procedure, at the year end, creates
        #   - two gross profit transactions with values of 80 and 20
        #   - two income summary transactions with values of 800 and 500
        #   - one gross profit and income summary settle transaction
        #      with a value of 80 - 20
        #   - one retained earnings transaction with a value of
        #      800 - 500 + 80 - 20
        # Only the 6 transactions (2 sales tx, 2 cost of sales,
        # 2 revenue a and 2 expense a) and the 5 'year end' transactions
        # should have been created.)
        self.clock.timestep_ix = 24
        self.object._perform_year_end_procedure(self.clock)

        self.assertEqual(len(self.object.gl.transactions), 20)
        self.assertEqual(self.object.gl.transactions[14].amount, 80)
        self.assertEqual(self.object.gl.transactions[14].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[14].dt_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[14].cr_account,
                         self.sales_acc.path)

        self.assertEqual(self.object.gl.transactions[15].amount, 20)
        self.assertEqual(self.object.gl.transactions[15].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[15].dt_account,
                         self.cos_acc.path)
        self.assertEqual(self.object.gl.transactions[15].cr_account,
                         gls._acci_gross_prof_.path)

        self.assertEqual(self.object.gl.transactions[16].amount, 800)
        self.assertEqual(self.object.gl.transactions[16].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[16].dt_account,
                         self.reva_acc.path)
        self.assertEqual(self.object.gl.transactions[16].cr_account,
                         gls._acci_inc_sum_.path)

        self.assertEqual(self.object.gl.transactions[17].amount, 500)
        self.assertEqual(self.object.gl.transactions[17].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[17].dt_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[17].cr_account,
                         self.expa_acc.path)

        self.assertEqual(self.object.gl.transactions[18].amount, 60)
        self.assertEqual(self.object.gl.transactions[18].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[18].dt_account,
                         gls._acci_gross_prof_.path)
        self.assertEqual(self.object.gl.transactions[18].cr_account,
                         gls._acci_inc_sum_.path)

        self.assertEqual(self.object.gl.transactions[19].amount, 360)
        self.assertEqual(self.object.gl.transactions[19].is_closing_cr_account,
                         True)
        self.assertEqual(self.object.gl.transactions[19].dt_account,
                         gls._acci_inc_sum_.path)
        self.assertEqual(self.object.gl.transactions[19].cr_account,
                         gls._accb_ret_earnings_acc_.path)
Example #18
0
 def setUp(self):
     self.object = Clock("NameA",
                         description="DescriptionA",
                         start_datetime=datetime(2016, 2, 1),
                         timestep_period_duration=TimePeriod.year,
                         timestep_period_count=3)
Example #19
0
class TimeBasedModel(NamedObject):
    """
    Represents an time based model class. An instance of this class is by
    default configured to run only once, thus functioning as a steady state
    model. The instance's time based parameters must be configured for it to
    function as a time based model.

    :param name: The name.
    :param description: The description.
    :param start_datetime: The start datetime of the model.
    :param period_duration: The duration of the model's time period.
      e.g. month, day etc.
    :param period_count: The number of periods to execute the model for.
    """

    def __init__(self,
                 name,
                 description=None,
                 start_datetime=datetime.now(),
                 period_duration=TimePeriod.year,
                 period_count=1):
        self.clock = Clock(
            "Clock",
            start_datetime=get_date(start_datetime),
            timestep_period_duration=period_duration)
        self.period_count = period_count
        self.entities = []
        super(TimeBasedModel, self).__init__(name, description=description)

    def _update_childrens_parent_path(self):
        for e in self.entities:
            e.set_parent_path(self.name)

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value
        self._update_childrens_parent_path()

    def create_entity(self, name, gl_structure, description=None):
        """
        Create an entity and add it to the model.

        :param name: The entity name.
        :param gl_structure: The entity's general ledger structure.
        :param description: The entity description.

        :returns: The created entity.
        """

        new_entity = Entity(name, gl_structure, description=description)
        self.entities.append(new_entity)
        return new_entity

    def remove_entity(self, name):
        """
        Remove an entity from the model.

        :param name: The name of the entity to remove.
        """

        entity_to_remove = None
        for e in self.entities:
            if e.name == name:
                entity_to_remove = e
        if entity_to_remove is not None:
            self.entities.remove(entity_to_remove)

    def prepare_to_run(self):
        """
        Prepare the model for execution.
        """

        self.clock.reset()
        for e in self.entities:
            e.prepare_to_run(self.clock, self.period_count)

    def run(self):
        """
        Execute the model.
        """

        self.prepare_to_run()
        for i in range(0, self.period_count):
            for e in self.entities:
                e.run(self.clock)
            self.clock.tick()

    def __getitem__(self, key):
        return [e for e in self.entities if e.name == key][0]
Example #20
0
class TimeBasedModel(NamedObject):
    """
    Represents an time based model class. An instance of this class is by
    default configured to run only once, thus functioning as a steady state
    model. The instance's time based parameters must be configured for it to
    function as a time based model.

    :param name: The name.
    :param description: The description.
    :param start_datetime: The start datetime of the model.
    :param period_duration: The duration of the model's time period.
      e.g. month, day etc.
    :param period_count: The number of periods to execute the model for.
    """

    def __init__(self,
                 name,
                 description=None,
                 start_datetime=datetime.now(),
                 period_duration=TimePeriod.year,
                 period_count=1):
        self.clock = Clock(
            "Clock",
            start_datetime=get_date(start_datetime),
            timestep_period_duration=period_duration)
        self.period_count = period_count
        self.entities = []
        super(TimeBasedModel, self).__init__(name, description=description)

    def _update_childrens_parent_path(self):
        for e in self.entities:
            e.set_parent_path(self.name)

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value
        self._update_childrens_parent_path()

    def create_entity(self, name, gl_structure, description=None):
        """
        Create an entity and add it to the model.

        :param name: The entity name.
        :param gl_structure: The entity's general ledger structure.
        :param description: The entity description.

        :returns: The created entity.
        """

        new_entity = Entity(name, gl_structure, description=description)
        self.entities.append(new_entity)
        return new_entity

    def remove_entity(self, name):
        """
        Remove an entity from the model.

        :param name: The name of the entity to remove.
        """

        entity_to_remove = None
        for e in self.entities:
            if e.name == name:
                entity_to_remove = e
        if entity_to_remove is not None:
            self.entities.remove(entity_to_remove)

    def prepare_to_run(self):
        """
        Prepare the model for execution.
        """

        self.clock.reset()
        for e in self.entities:
            e.prepare_to_run(self.clock, self.period_count)

    def run(self):
        """
        Execute the model.
        """

        self.prepare_to_run()
        for i in range(0, self.period_count):
            for e in self.entities:
                e.run(self.clock)
            self.clock.tick()

    def __getitem__(self, key):
        return [e for e in self.entities if e.name == key][0]
Example #21
0
 def setUp(self):
     self.object = Clock("NameA",
                         description="DescriptionA",
                         start_datetime=datetime(2016, 2, 1),
                         timestep_period_duration=TimePeriod.year,
                         timestep_period_count=3)
Example #22
0
class BasicLoanActivityUnitTester(unittest.TestCase):
    """
    Tester for the auxi.modelling.business.basic.BasicLoanActivity class.
    """
    def setUp(self):
        self.gl_structure = GeneralLedgerStructure(
            "GL Structure", description="General Ledger Structure")
        self.gl_structure["Account Payable"].create_account(
            "Capital Loan", "0000")
        self.gl_structure["Expense"].create_account("Interest Expense", "0000")

        self.gl = GeneralLedger("GL",
                                self.gl_structure,
                                description="General Ledger")

        self.clock = Clock("NameA", start_datetime=datetime(2016, 2, 1))

        self.object = BasicLoanActivity(
            "Capital Loan",
            bank_account="Bank/Default",
            loan_account="Account Payable/Capital Loan",
            interest_account="Expense/Interest Expense",
            amount=180000,
            interest_rate=0.15,
            start=datetime(2016, 2, 1),
            duration=36,
            interval=1,
            description="Loan for Capital")

    def test_constructor(self):
        self.assertEqual(self.object.name, "Capital Loan")
        self.assertEqual(self.object.bank_account, "Bank/Default")
        self.assertEqual(self.object.loan_account,
                         "Account Payable/Capital Loan")
        self.assertEqual(self.object.interest_account,
                         "Expense/Interest Expense")
        self.assertEqual(self.object.amount, 180000)
        self.assertEqual(self.object.interest_rate, 0.15)
        self.assertEqual(self.object.start_datetime, datetime(2016, 2, 1))
        self.assertEqual(self.object.end_datetime, datetime(2019, 3, 1))
        self.assertEqual(self.object.duration, 36)
        self.assertEqual(self.object.interval, 1)
        self.assertEqual(self.object.description, "Loan for Capital")

    def test__meet_execution_criteria(self):
        """
        Test that the activity only meets the execution criteria when
        it's amount is greater than 0 and its duration is greater than 0.
        """

        self.object.prepare_to_run(self.clock, 13)
        self.assertEqual(self.object._meet_execution_criteria(5), True)
        self.object.amount = 0
        self.assertEqual(self.object._meet_execution_criteria(5), False)
        self.object.amount = 180000
        self.object.duration = 0
        self.assertEqual(self.object._meet_execution_criteria(5), False)

    def test_run_first_month(self):
        """
        Test that the activity run method creates a transaction with an amount
        of 180000 on the first month. No other transactions
        """

        self.object.prepare_to_run(self.clock, 1)
        self.object.run(self.clock, self.gl)
        self.assertEqual(len(self.gl.transactions), 1)
        self.assertEqual(self.gl.transactions[0].amount, 180000)

    def test_run_third_month(self):
        """
        Test that the activity run method accrued the interest correctly.
        """

        self.clock.tick()
        self.object.prepare_to_run(self.clock, 61)
        self.clock.tick()
        self.object.run(self.clock, self.gl)
        self.clock.tick()
        self.object.run(self.clock, self.gl)
        self.clock.tick()
        self.object.run(self.clock, self.gl)
        self.assertEqual(len(self.gl.transactions), 5)
        # Test the interest rate for the first month
        # loan amount = 180000
        # First month's interest should be (180000 * 0.15) / 12 = 2250
        self.assertEqual(self.gl.transactions[1].amount, 2250)
        # Principle payment is 6239.76 (see below)
        # The interest payed the previous month is 2250
        # Making the total amount payed to the loan 6239.76 - 2250 = 3,989.76
        # New amount to calculate interest from: 180000 - 3,989.76 = 176,010.24
        # 2nd month's interest should be 176,010.24 * 0.15) / 12 = 2,200.13
        self.assertEqual("%.2f" % self.gl.transactions[3].amount, "2200.13")
        # Test the monthly principle payment
        # interest rate = 0.15: per month 0.0125.
        # loan amount = 180000
        # duration of the loan = 36
        # payment = (180000*0.0125) / (1-(1/pow((1+0.0125), 36))) = 6239.76
        self.assertEqual("%.2f" % self.gl.transactions[2].amount, "6239.76")
        self.assertEqual("%.2f" % self.gl.transactions[4].amount, "6239.76")

    def test_run_last_month(self):
        """
        Test that the activity run method creates settled the loan on the
        loans' last month and that the transactions
        """

        self.clock.tick()
        self.object.prepare_to_run(self.clock, 61)
        for i in range(0, 60):
            self.object.run(self.clock, self.gl)
            self.clock.tick()
        # Test the number of transaction that was created during the
        # loan's lifetime.
        # 2 transactions per months should be created + the initial loan amount
        # transaction. 36*2 + 1 = 73
        last_tx_ix = len(self.gl.transactions)
        self.assertEqual(len(self.gl.transactions), 73)
        # The transactions should have run only run for 36 months
        # (the duration of the loan)
        r = relativedelta.relativedelta(
            self.gl.transactions[last_tx_ix - 1].tx_date,
            self.gl.transactions[0].tx_date)
        self.assertEqual(r.years * 12 + r.months, 36)

    def test_get_referenced_accounts(self):
        """
        Test that the activity run method get_referenced_accounts accounts
        matches the debit and credit accounts self.object was initialised with.
        """

        result = self.object.get_referenced_accounts()
        self.assertEqual(self.object.bank_account, result[0])
        self.assertEqual(self.object.loan_account, result[1])
        self.assertEqual(self.object.interest_account, result[2])
Example #23
0
 def test_prepare_to_run(self):
     clock = Clock("NameA", start_datetime=datetime(2016, 1, 1))
     self.object.prepare_to_run(clock, 18)
     self.assertEqual(self.object.start_period_ix, 2)
     self.assertEqual(self.object.end_period_ix, 14)
Example #24
0
 def test__meet_execution_criteria(self):
     clock = Clock("NameA", start_datetime=datetime(2016, 1, 1))
     self.object.prepare_to_run(clock, 13)
     self.assertEqual(self.object._meet_execution_criteria(3), False)
     self.assertEqual(self.object._meet_execution_criteria(5), True)
     self.assertEqual(self.object._meet_execution_criteria(40), False)