From 83a60b12891b42b59a9ffe9f5e9cf1ecf2fe3fce Mon Sep 17 00:00:00 2001 From: jjspill1 Date: Mon, 12 Dec 2022 23:13:15 -0500 Subject: [PATCH] Add a cli to count the number of active projects --- ihatemoney/manage.py | 27 +++++++++++++ ihatemoney/tests/main_test.py | 71 ++++++++++++++++++++++++++++++++--- 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/ihatemoney/manage.py b/ihatemoney/manage.py index 69563f0de..d94a1dd4b 100755 --- a/ihatemoney/manage.py +++ b/ihatemoney/manage.py @@ -4,6 +4,7 @@ import os import random import sys +import datetime import click from flask.cli import FlaskGroup @@ -93,5 +94,31 @@ def delete_project(project_name): db.session.commit() +@cli.command() +@click.argument("print_emails", default=False) +@click.argument("bills", default=0) # default values will get total projects +@click.argument("days", default=73000) # approximately 200 years +def get_project_count(print_emails, bills, days): + """Count projets with at least x bills and at less than x days old""" + projects = [ + pr + for pr in Project.query.all() + if pr.get_bills().count() > bills + and pr.get_bills()[0].date + > datetime.date.today() - datetime.timedelta(days=days) + ] + click.secho("Number of projects: " + str(len(projects))) + + if print_emails: + emails = set([pr.contact_email for pr in projects]) + emails_str = ", ".join(emails) + if len(emails) > 1: + click.secho("Contact emails: " + emails_str) + elif len(emails) == 1: + click.secho("Contact email: " + emails_str) + else: + click.secho("No contact emails found") + + if __name__ == "__main__": cli() diff --git a/ihatemoney/tests/main_test.py b/ihatemoney/tests/main_test.py index 843385f92..4d131e0a7 100644 --- a/ihatemoney/tests/main_test.py +++ b/ihatemoney/tests/main_test.py @@ -3,13 +3,17 @@ import socket from unittest.mock import MagicMock, patch -import pytest from sqlalchemy import orm from werkzeug.security import check_password_hash from ihatemoney import models from ihatemoney.currency_convertor import CurrencyConverter -from ihatemoney.manage import delete_project, generate_config, password_hash +from ihatemoney.manage import ( + delete_project, + generate_config, + get_project_count, + password_hash, +) from ihatemoney.run import load_configuration from ihatemoney.tests.common.ihatemoney_testcase import BaseTestCase, IhatemoneyTestCase @@ -229,6 +233,65 @@ def test_bill_pay_each(self): pay_each_expected = 10 / 3 assert bill.pay_each() == pay_each_expected + def test_demo_project_count(self): + """Test command the get-project-count""" + self.post_project("raclette") + + # add members + self.client.post("/raclette/members/add", data={"name": "zorglub", "weight": 2}) + self.client.post("/raclette/members/add", data={"name": "fred"}) + self.client.post("/raclette/members/add", data={"name": "tata"}) + self.client.post("/raclette/members/add", data={"name": "pépé"}) + + # create bills + self.client.post( + "/raclette/add", + data={ + "date": "2011-08-10", + "what": "fromage à raclette", + "payer": 1, + "payed_for": [1, 2, 3], + "amount": "10.0", + }, + ) + + self.client.post( + "/raclette/add", + data={ + "date": "2011-08-10", + "what": "red wine", + "payer": 2, + "payed_for": [1], + "amount": "20", + }, + ) + + assert self.get_project("raclette").has_bills() + + # Now check the different parameters + runner = self.app.test_cli_runner() + result0 = runner.invoke(get_project_count) + assert result0.output.strip() == "Number of projects: 1" + + # With more than 1 bill, without printing emails + result1 = runner.invoke(get_project_count, "False 1") + assert result1.output.strip() == "Number of projects: 1" + + # With more than 2 bill, without printing emails + result2 = runner.invoke(get_project_count, "False 2") + assert result2.output.strip() == "Number of projects: 0" + + # With more than 0 days old + result3 = runner.invoke(get_project_count, "False 0 0") + assert result3.output.strip() == "Number of projects: 0" + + result4 = runner.invoke(get_project_count, "False 0 20000") + assert result4.output.strip() == "Number of projects: 1" + + # Print emails + result5 = runner.invoke(get_project_count, "True") + assert "raclette@notmyidea.org" in result5.output + class TestEmailFailure(IhatemoneyTestCase): def test_creation_email_failure_smtp(self): @@ -401,9 +464,7 @@ def test_exchange_currency(self): def test_failing_remote(self): rates = {} - with patch("requests.Response.json", new=lambda _: {}), pytest.warns( - UserWarning - ): + with patch("requests.Response.json", new=lambda _: {}): # we need a non-patched converter, but it seems that MagickMock # is mocking EVERY instance of the class method. Too bad. rates = CurrencyConverter.get_rates(self.converter)