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)
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)
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
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
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)
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, )
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)
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)
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)
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)
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)
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
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
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)
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
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)
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)
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)
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
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
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
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
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)
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)
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