Beispiel #1
0
    def test_bulk_update_invalid_csv(self, client, django_user_model):
        url = reverse("debt:creditline-bulk-update")
        login(client, django_user_model)
        model = apps.get_model("debt.CreditLine")
        assert model.objects.count() == 0

        # Create the CSV
        df = pd.DataFrame(
            {
                k: [v]
                for k, v in dict(
                    bad_column_name="CreditCard",
                    holder="Scooby Doo",
                    statement_date=9,
                    date_opened="2018-11-10",
                    annual_fee=100,
                    interest_rate=22,
                    credit_line=10000,
                    min_pay_pct=3,
                    min_pay_dlr=30,
                    priority=0,
                ).items()
            }
        )
        temp_path = os.path.join(settings.MEDIA_ROOT, "temp.csv")
        df.to_csv(temp_path)

        try:
            with open(temp_path, "rb") as f:
                r = client.post(url, {"csv": f})
            assert r.status_code == 200
            assert model.objects.count() == 0
            assert "columns expected but not found" in hr(r)
        finally:
            os.remove(temp_path)
Beispiel #2
0
    def test_bulk_download_empty(self, client, django_user_model):
        url = reverse("debt:statement-download")
        login(client, django_user_model)

        pattern = "Account,Date,Balance\r?\r?\n"
        r = client.get(url)
        text = "".join(line.decode("UTF-8") for line in r.streaming_content)
        assert re.match(pattern, text)
Beispiel #3
0
    def test_statement_bulk_delete_confirm_view(self, client, django_user_model):
        url = reverse("debt:statement-bulk-delete-confirm")
        template = "debt/statement-bulk-delete.html"
        login(client, django_user_model)

        # Check the page
        response = client.get(url)
        tp_names = [t.name for t in response.templates]
        assert response.status_code == 200 and template in tp_names
Beispiel #4
0
    def test_debt_summary(self, client, django_user_model):
        url = "debt:debt-summary"
        template = "debt/debt_summary.html"

        login(client, django_user_model)

        # Check the page
        response = client.get(reverse(url))
        tp_names = [t.name for t in response.templates]
        assert response.status_code == 200 and template in tp_names
Beispiel #5
0
    def test_bulk_update_unknown_account(self, client, django_user_model):
        url = reverse("debt:statement-bulk-update")
        user = login(client, django_user_model)
        acc = mommy.make(
            "debt.CreditLine", user=user, name="Checking"
        )  # type: CreditLine
        assert acc.statement_set.count() == 0

        # Create the CSV
        df = pd.DataFrame(
            dict(
                Account=["Checking", "Unknown Account"],
                Date=["11/1/18", "12/1/18"],
                Balance=[2000.00, 3000.00],
            )
        )
        temp_path = os.path.join(settings.MEDIA_ROOT, "temp.csv")
        df.to_csv(temp_path)

        try:
            with open(temp_path, "rb") as f:
                r = client.post(url, {"csv": f})
            msgs = r.cookies["messages"].value
            assert "Unknown Accounts: 1" in msgs
            assert r.status_code == 302
            assert acc.balance == 2000
            assert acc.statement_set.count() == 1
            assert acc.latest_statement_date == datetime.date(2018, 11, 1)

        finally:
            os.remove(temp_path)
Beispiel #6
0
    def test_account_update_view(self, client, django_user_model):
        url = "debt:account-update"
        model = "debt.CreditLine"
        template = "debt/account-update.html"
        user = login(client, django_user_model)

        obj_params = dict(
            name="TestObj",
            holder=TEST_NAME,
            statement_date=1,
            date_opened=today_str(),
            annual_fee=0,
            interest_rate=0,
            credit_line=0,
            min_pay_pct=0,
            min_pay_dlr=0,
            priority=0,
        )

        self.update_view_test(
            client,
            model,
            url,
            template,
            user,
            user_required=True,
            obj_params=obj_params,
        )
Beispiel #7
0
    def test_bulk_update_valid(self, client, django_user_model):
        url = reverse("debt:statement-bulk-update")
        user = login(client, django_user_model)
        acc = mommy.make(
            "debt.CreditLine", user=user, name="Checking"
        )  # type: CreditLine
        assert acc.statement_set.count() == 0

        # Create the CSV
        df = pd.DataFrame(
            dict(
                Account=["Checking", "Checking"],
                Date=["11/1/18", "12/1/18"],
                Balance=[2000.00, 3000.00],
            )
        )
        temp_path = os.path.join(settings.MEDIA_ROOT, "temp.csv")
        df.to_csv(temp_path)

        try:
            with open(temp_path, "rb") as f:
                r = client.post(url, {"csv": f})
            assert r.status_code == 302
            assert acc.balance == 3000
            assert acc.statement_set.count() == 2
            assert (
                acc.statement_set.aggregate(models.Sum("balance"))["balance__sum"]
                == 5000
            )
            assert acc.latest_statement_date == datetime.date(2018, 12, 1)

        finally:
            os.remove(temp_path)
Beispiel #8
0
    def test_account_earliest_statement_date(
        self, client: "Client", django_user_model: "User"
    ):
        # The date of the earliest statement.

        # Setup
        user = login(client, django_user_model)
        CreditLine = apps.get_model("debt.CreditLine")
        Statement = apps.get_model("debt.Statement")
        assert CreditLine.objects.count() == 0
        assert Statement.objects.count() == 0

        # Create the objects
        year = 2018
        month = 11
        later_month = 12
        day = 10
        obj = mommy.make(CreditLine, user=user, statement_date=day)
        __ = mommy.make(Statement, account=obj, year=year, month=month)

        # Make a later statement to make sure we correctly identify the
        # earliest one
        __ = mommy.make(Statement, account=obj, year=year, month=later_month)

        assert obj.earliest_statement_date == date(year, month, day)
Beispiel #9
0
    def test_bulk_update_invalid_csv(self, client, django_user_model):
        url = reverse("debt:statement-bulk-update")
        user = login(client, django_user_model)
        acc = mommy.make(
            "debt.CreditLine", user=user, name="Checking"
        )  # type: CreditLine
        assert acc.statement_set.count() == 0

        # Create the CSV
        df = pd.DataFrame(
            dict(
                Account=["Checking", "Checking"],
                Date=["11/1/18", "12/1/18"],
                BadColumnName=[2000.00, 3000.00],
            )
        )
        temp_path = os.path.join(settings.MEDIA_ROOT, "temp.csv")
        df.to_csv(temp_path)

        try:
            with open(temp_path, "rb") as f:
                r = client.post(url, {"csv": f})
            assert r.status_code == 200
            assert acc.statement_set.count() == 0
            assert "columns expected but not found" in hr(r)

        finally:
            os.remove(temp_path)
Beispiel #10
0
 def test_calc_balance_forecast(self, client: "Client", django_user_model: "User"):
     user = login(client, django_user_model)
     acc = mommy.make("debt.CreditLine", user=user, min_pay_dlr=30, interest_rate=12)
     mommy.make(
         "debt.Statement", user=user, account=acc, month=11, year=2018, balance=400
     )
     expected = 374  # ($400 + 1% monthly interest) - $30
     assert acc.calc_balance(12, 2018, 400) == (expected, 30)
Beispiel #11
0
 def test_calc_balance_later_stmnts(
     self, client: "Client", django_user_model: "User"
 ):
     user = login(client, django_user_model)
     acc = mommy.make("debt.CreditLine", user=user)
     mommy.make(
         "debt.Statement", user=user, account=acc, month=11, year=2018, balance=400
     )
     assert acc.calc_balance(10, 2018, 400) == (400, None)
Beispiel #12
0
    def test_statement_bulk_delete_view(self, client, django_user_model):
        url = reverse("debt:statement-bulk-delete")
        user = login(client, django_user_model)
        acc = mommy.make("debt.CreditLine", user=user)  # type: CreditLine
        for i in range(4):
            mommy.make("debt.Statement", user=user, account=acc, month=i)
        assert acc.statement_set.count() == 4

        # Check the page
        response = client.post(url)
        assert response.status_code == 302
        assert acc.statement_set.count() == 0
Beispiel #13
0
    def test_debt_summary_with_data(self, client: "Client", django_user_model: "User"):
        url = "debt:debt-summary"
        template = "debt/debt_summary.html"

        user = login(client, django_user_model)
        acc1 = mommy.make("debt.CreditLine", user=user)
        acc2 = mommy.make("debt.CreditLine", user=user)
        mommy.make("debt.Statement", account=acc1, user=user)
        mommy.make("debt.Statement", account=acc2, user=user)

        # Check the page
        response = client.get(reverse(url))
        tp_names = [t.name for t in response.templates]
        assert response.status_code == 200 and template in tp_names
Beispiel #14
0
    def test_statement_create_view(self, client, django_user_model):
        url = "debt:statement-add"
        model = "debt.Statement"
        template = "debt/statement-add.html"
        user = login(client, django_user_model)

        # Parents
        parent_models = ["debt.CreditLine"]
        parents = parent_obj_set(parent_models)

        obj_params = dict(
            account=parents["debt.CreditLine"].id, year=2000, month=1, balance=0
        )

        self.create_view_test(client, model, url, template, user, obj_params=obj_params)
Beispiel #15
0
    def test_statement_delete_view(self, client, django_user_model):
        model = apps.get_model("debt.Statement")
        url = "debt:statement-delete"

        user = login(client, django_user_model)
        cl = mommy.make("debt.CreditLine", user=user)
        obj = mommy.make(model, user=user, account=cl, year=2018, month=11)
        assert model.objects.count() == 1

        # Check the delete page
        response = client.get(reverse(url, kwargs={"pk": obj.pk}))
        assert response.status_code == 200 and model.objects.count() == 1

        # Delete the object and verify
        response = client.post(reverse(url, kwargs={"pk": obj.pk}))
        assert response.status_code == 302 and model.objects.count() == 0
Beispiel #16
0
    def test_bulk_download_with_data(self, client, django_user_model):
        url = reverse("debt:statement-download")
        user = login(client, django_user_model)

        # Create a statement
        cl = mommy.make(
            "debt.CreditLine", user=user, statement_date=10, name="Checking"
        )
        mommy.make(
            "debt.Statement", user=user, account=cl, year=2018, month=11, balance=20
        )

        pattern = "Account,Date,Balance\r?\r?\nChecking,2018-11-10,20.00"
        r = client.get(url)
        text = "".join(line.decode("UTF-8") for line in r.streaming_content)
        assert re.match(pattern, text)
Beispiel #17
0
    def test_bulk_update_no_overwrites(self, client, django_user_model):
        url = reverse("debt:creditline-bulk-update")
        user = login(client, django_user_model)
        model = apps.get_model("debt.CreditLine")
        assert model.objects.count() == 0

        # Create an existing account
        _ = mommy.make(model, name="CreditCard", user=user, annual_fee=200)
        assert model.objects.count() == 1

        # Create the CSV
        df = pd.DataFrame(
            {
                k: [v]
                for k, v in dict(
                    name="CreditCard",
                    holder="Scooby Doo",
                    statement_date=9,
                    date_opened="2018-11-10",
                    annual_fee=100,
                    interest_rate=22,
                    credit_line=10000,
                    min_pay_pct=3,
                    min_pay_dlr=30,
                    priority=0,
                ).items()
            }
        )
        temp_path = os.path.join(settings.MEDIA_ROOT, "temp.csv")
        df.to_csv(temp_path)

        try:
            with open(temp_path, "rb") as f:
                r = client.post(url, {"csv": f})
            msgs = r.cookies["messages"].value
            assert "Existing Accounts Not Overwritten: 1" in msgs
            assert r.status_code == 302
            assert model.objects.count() == 1

            # Spot check some fields
            cl = model.objects.first()  # type: CreditLine
            assert cl.user == user
            assert cl.annual_fee == 200
        finally:
            os.remove(temp_path)
Beispiel #18
0
    def test_statement_date(self, client: "Client", django_user_model: "User"):
        # This should use the parent credit line's day field.

        # Setup
        user = login(client, django_user_model)
        CreditLine = apps.get_model("debt.CreditLine")
        Statement = apps.get_model("debt.Statement")
        assert CreditLine.objects.count() == 0
        assert Statement.objects.count() == 0

        # Set attributes
        year = 2018
        month = 11
        day = 10
        cl = mommy.make(CreditLine, user=user, statement_date=day)
        stmnt = mommy.make(Statement, account=cl, year=year, month=month)

        assert stmnt.date == date(year, month, day)
Beispiel #19
0
    def test_account_forecast_next(self, client: "Client", django_user_model: "User"):
        # This should return the predicted next month's balance, if only
        # the minimum payment is applied.

        # Setup
        user = login(client, django_user_model)
        CreditLine = apps.get_model("debt.CreditLine")
        assert CreditLine.objects.count() == 0

        # Set attributes
        rate = 24  # 2% per month
        bal = 100
        min_pay = 30
        expected = 72  # 100 + 2% - 30
        obj = mommy.make(CreditLine, user=user, min_pay_dlr=min_pay, interest_rate=rate)

        # Calculate
        assert obj.forecast_next(bal) == expected
Beispiel #20
0
    def test_account_available_credit(
        self, client: "Client", django_user_model: "User"
    ):
        # Available credit should be credit line less balance.

        # Setup
        user = login(client, django_user_model)
        CreditLine = apps.get_model("debt.CreditLine")
        Statement = apps.get_model("debt.Statement")
        assert CreditLine.objects.count() == 0
        assert Statement.objects.count() == 0

        # Create the objects
        cl = 1000
        bal = 200
        obj = mommy.make(CreditLine, user=user, credit_line=cl)
        __ = mommy.make(Statement, account=obj, balance=bal)

        assert obj.available_credit == cl - bal
Beispiel #21
0
    def test_account_min_pay(self, client: "Client", django_user_model: "User"):
        # Minimum pay for a credit line is usually on a % basis, with a
        # certain floor amount (so, e.g., if you have a $10 balance,
        # usually your minimum pay will be $10 instead of some % of it,
        # since the balance is so low)

        # Setup
        user = login(client, django_user_model)
        CreditLine = apps.get_model("debt.CreditLine")
        assert CreditLine.objects.count() == 0
        obj = mommy.make(CreditLine, user=user, min_pay_dlr=30, min_pay_pct=10)

        # Scenario 1: the balance is high enough for the % to apply
        assert obj.min_pay(500) == 50

        # Scenario 2: the balance is too low for the % to apply
        assert obj.min_pay(100) == 30

        # Scenario 3: the balance is lower than the dollar floor
        assert obj.min_pay(15) == 15
Beispiel #22
0
    def test_account_balance(self, client: "Client", django_user_model: "User"):
        # Balance should be the balance of the latest statement, or the
        # credit limit if there are no statements.

        # Setup
        user = login(client, django_user_model)
        CreditLine = apps.get_model("debt.CreditLine")
        Statement = apps.get_model("debt.Statement")
        assert CreditLine.objects.count() == 0
        assert Statement.objects.count() == 0

        # Create the object and validate balance w/ no statements
        cl = 100
        obj = mommy.make(CreditLine, user=user, credit_line=cl)
        assert obj.balance == cl

        # Create a statement and validate balance again
        bal = 200
        __ = mommy.make(Statement, account=obj, balance=bal)
        assert obj.balance == bal
Beispiel #23
0
    def detail_view_test(
        client,
        django_user_model,
        model,
        viewname,
        user_required=True,
        search_str="",
        obj_params=None,
    ):
        if obj_params is None:
            obj_params = dict()
        user = login(client, django_user_model)
        if user_required:
            obj_params.update(user=user)

        obj = mommy.make(model, **obj_params)
        obj = create_recursive_dependencies(obj)

        obj.save()
        response = client.get(reverse(viewname, kwargs={"pk": obj.id}))

        assert response.status_code == 200 and search_str in hr(response)
Beispiel #24
0
    def test_bulk_update_no_overwrites(self, client, django_user_model):
        url = reverse("debt:statement-bulk-update")
        user = login(client, django_user_model)
        acc = mommy.make(
            "debt.CreditLine", user=user, name="Checking"
        )  # type: CreditLine
        mommy.make(
            "debt.Statement", user=user, account=acc, month=11, year=2018, balance=1500
        )
        assert acc.statement_set.count() == 1

        # Create the CSV
        df = pd.DataFrame(
            dict(
                Account=["Checking", "Checking"],
                Date=["11/1/18", "12/1/18"],
                Balance=[2000.00, 3000.00],
            )
        )
        temp_path = os.path.join(settings.MEDIA_ROOT, "temp.csv")
        df.to_csv(temp_path)

        try:
            with open(temp_path, "rb") as f:
                r = client.post(url, {"csv": f})
            msgs = r.cookies["messages"].value
            assert "Existing Statements Not Overwritten: 1" in msgs
            assert r.status_code == 302
            assert acc.balance == 3000
            assert acc.statement_set.count() == 2
            assert (
                acc.statement_set.aggregate(models.Sum("balance"))["balance__sum"]
                == 4500
            )
            assert acc.latest_statement_date == datetime.date(2018, 12, 1)

        finally:
            os.remove(temp_path)
Beispiel #25
0
 def list_view_test(client, django_user_model, url, template):
     login(client, django_user_model)
     response = client.get(reverse(url))
     tp_names = [t.name for t in response.templates]
     assert response.status_code == 200 and template in tp_names