mirror of
https://github.com/spiral-project/ihatemoney.git
synced 2025-04-28 17:32:38 +02:00
Add a cli to count the number of active projects
Some checks are pending
CI / test (postgresql, normal, 3.11) (push) Blocked by required conditions
CI / test (postgresql, normal, 3.9) (push) Blocked by required conditions
CI / test (sqlite, minimal, 3.10) (push) Blocked by required conditions
CI / lint (push) Waiting to run
CI / test (mariadb, minimal, 3.11) (push) Blocked by required conditions
CI / test (mariadb, normal, 3.11) (push) Blocked by required conditions
CI / test (mariadb, normal, 3.9) (push) Blocked by required conditions
CI / test (postgresql, minimal, 3.11) (push) Blocked by required conditions
CI / test (sqlite, minimal, 3.11) (push) Blocked by required conditions
CI / test (sqlite, minimal, 3.12) (push) Blocked by required conditions
CI / test (sqlite, minimal, 3.9) (push) Blocked by required conditions
CI / test (sqlite, normal, 3.10) (push) Blocked by required conditions
CI / test (sqlite, normal, 3.11) (push) Blocked by required conditions
CI / test (sqlite, normal, 3.12) (push) Blocked by required conditions
CI / test (sqlite, normal, 3.8) (push) Blocked by required conditions
CI / test (sqlite, normal, 3.9) (push) Blocked by required conditions
CI / docs (push) Waiting to run
Docker build / test (push) Waiting to run
Docker build / build_upload (push) Blocked by required conditions
Some checks are pending
CI / test (postgresql, normal, 3.11) (push) Blocked by required conditions
CI / test (postgresql, normal, 3.9) (push) Blocked by required conditions
CI / test (sqlite, minimal, 3.10) (push) Blocked by required conditions
CI / lint (push) Waiting to run
CI / test (mariadb, minimal, 3.11) (push) Blocked by required conditions
CI / test (mariadb, normal, 3.11) (push) Blocked by required conditions
CI / test (mariadb, normal, 3.9) (push) Blocked by required conditions
CI / test (postgresql, minimal, 3.11) (push) Blocked by required conditions
CI / test (sqlite, minimal, 3.11) (push) Blocked by required conditions
CI / test (sqlite, minimal, 3.12) (push) Blocked by required conditions
CI / test (sqlite, minimal, 3.9) (push) Blocked by required conditions
CI / test (sqlite, normal, 3.10) (push) Blocked by required conditions
CI / test (sqlite, normal, 3.11) (push) Blocked by required conditions
CI / test (sqlite, normal, 3.12) (push) Blocked by required conditions
CI / test (sqlite, normal, 3.8) (push) Blocked by required conditions
CI / test (sqlite, normal, 3.9) (push) Blocked by required conditions
CI / docs (push) Waiting to run
Docker build / test (push) Waiting to run
Docker build / build_upload (push) Blocked by required conditions
This commit is contained in:
parent
ce20f9adea
commit
83a60b1289
2 changed files with 93 additions and 5 deletions
|
@ -4,6 +4,7 @@ import getpass
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import sys
|
import sys
|
||||||
|
import datetime
|
||||||
|
|
||||||
import click
|
import click
|
||||||
from flask.cli import FlaskGroup
|
from flask.cli import FlaskGroup
|
||||||
|
@ -93,5 +94,31 @@ def delete_project(project_name):
|
||||||
db.session.commit()
|
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__":
|
if __name__ == "__main__":
|
||||||
cli()
|
cli()
|
||||||
|
|
|
@ -3,13 +3,17 @@ import smtplib
|
||||||
import socket
|
import socket
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
import pytest
|
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
from werkzeug.security import check_password_hash
|
from werkzeug.security import check_password_hash
|
||||||
|
|
||||||
from ihatemoney import models
|
from ihatemoney import models
|
||||||
from ihatemoney.currency_convertor import CurrencyConverter
|
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.run import load_configuration
|
||||||
from ihatemoney.tests.common.ihatemoney_testcase import BaseTestCase, IhatemoneyTestCase
|
from ihatemoney.tests.common.ihatemoney_testcase import BaseTestCase, IhatemoneyTestCase
|
||||||
|
|
||||||
|
@ -229,6 +233,65 @@ class TestModels(IhatemoneyTestCase):
|
||||||
pay_each_expected = 10 / 3
|
pay_each_expected = 10 / 3
|
||||||
assert bill.pay_each() == pay_each_expected
|
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):
|
class TestEmailFailure(IhatemoneyTestCase):
|
||||||
def test_creation_email_failure_smtp(self):
|
def test_creation_email_failure_smtp(self):
|
||||||
|
@ -401,9 +464,7 @@ class TestCurrencyConverter:
|
||||||
|
|
||||||
def test_failing_remote(self):
|
def test_failing_remote(self):
|
||||||
rates = {}
|
rates = {}
|
||||||
with patch("requests.Response.json", new=lambda _: {}), pytest.warns(
|
with patch("requests.Response.json", new=lambda _: {}):
|
||||||
UserWarning
|
|
||||||
):
|
|
||||||
# we need a non-patched converter, but it seems that MagickMock
|
# we need a non-patched converter, but it seems that MagickMock
|
||||||
# is mocking EVERY instance of the class method. Too bad.
|
# is mocking EVERY instance of the class method. Too bad.
|
||||||
rates = CurrencyConverter.get_rates(self.converter)
|
rates = CurrencyConverter.get_rates(self.converter)
|
||||||
|
|
Loading…
Reference in a new issue