mirror of
https://github.com/spiral-project/ihatemoney.git
synced 2025-05-06 05:01:48 +02:00
Merge pull request #8 from ndkoch/billform
Fix minor issues with BillForm task
This commit is contained in:
commit
deead1528e
6 changed files with 87 additions and 23 deletions
|
@ -24,6 +24,7 @@ import email_validator
|
||||||
from ihatemoney.models import Project, Person
|
from ihatemoney.models import Project, Person
|
||||||
from ihatemoney.utils import slugify, eval_arithmetic_expression, CurrencyConverter
|
from ihatemoney.utils import slugify, eval_arithmetic_expression, CurrencyConverter
|
||||||
|
|
||||||
|
|
||||||
def strip_filter(string):
|
def strip_filter(string):
|
||||||
try:
|
try:
|
||||||
return string.strip()
|
return string.strip()
|
||||||
|
@ -38,8 +39,10 @@ def get_billform_for(project, set_default=True, **kwargs):
|
||||||
display the default form, it will call set_default on it.
|
display the default form, it will call set_default on it.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
form = BillForm(project=project, **kwargs)
|
form = BillForm(**kwargs)
|
||||||
form.original_currency.label = Label("original_currency", "Currency (Default: %s)" % (project.default_currency))
|
form.original_currency.label = Label(
|
||||||
|
"original_currency", "Currency (Default: %s)" % (project.default_currency)
|
||||||
|
)
|
||||||
active_members = [(m.id, m.name) for m in project.active_members]
|
active_members = [(m.id, m.name) for m in project.active_members]
|
||||||
|
|
||||||
form.payed_for.choices = form.payer.choices = active_members
|
form.payed_for.choices = form.payer.choices = active_members
|
||||||
|
@ -90,7 +93,9 @@ class EditProjectForm(FlaskForm):
|
||||||
contact_email = StringField(_("Email"), validators=[DataRequired(), Email()])
|
contact_email = StringField(_("Email"), validators=[DataRequired(), Email()])
|
||||||
currency_helper = CurrencyConverter()
|
currency_helper = CurrencyConverter()
|
||||||
default_currency = SelectField(
|
default_currency = SelectField(
|
||||||
_("Default Currency"), choices=currency_helper.get_currencies(), validators=[DataRequired()]
|
_("Default Currency"),
|
||||||
|
choices=currency_helper.get_currencies(),
|
||||||
|
validators=[DataRequired()],
|
||||||
)
|
)
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
|
@ -103,7 +108,7 @@ class EditProjectForm(FlaskForm):
|
||||||
id=self.id.data,
|
id=self.id.data,
|
||||||
password=generate_password_hash(self.password.data),
|
password=generate_password_hash(self.password.data),
|
||||||
contact_email=self.contact_email.data,
|
contact_email=self.contact_email.data,
|
||||||
default_currency=self.default_currency.data
|
default_currency=self.default_currency.data,
|
||||||
)
|
)
|
||||||
return project
|
return project
|
||||||
|
|
||||||
|
@ -172,7 +177,9 @@ class BillForm(FlaskForm):
|
||||||
amount = CalculatorStringField(_("Amount paid"), validators=[DataRequired()])
|
amount = CalculatorStringField(_("Amount paid"), validators=[DataRequired()])
|
||||||
currency_helper = CurrencyConverter()
|
currency_helper = CurrencyConverter()
|
||||||
original_currency = SelectField(
|
original_currency = SelectField(
|
||||||
_("Currency"), choices=currency_helper.get_currencies(), validators=[DataRequired()]
|
_("Currency"),
|
||||||
|
choices=currency_helper.get_currencies(),
|
||||||
|
validators=[DataRequired()],
|
||||||
)
|
)
|
||||||
external_link = URLField(
|
external_link = URLField(
|
||||||
_("External link"),
|
_("External link"),
|
||||||
|
@ -193,7 +200,9 @@ class BillForm(FlaskForm):
|
||||||
bill.date = self.date.data
|
bill.date = self.date.data
|
||||||
bill.owers = [Person.query.get(ower, project) for ower in self.payed_for.data]
|
bill.owers = [Person.query.get(ower, project) for ower in self.payed_for.data]
|
||||||
bill.original_currency = self.original_currency.data
|
bill.original_currency = self.original_currency.data
|
||||||
bill.original_amount = currency_helper.exchange_currency(bill.amount, bill.original_currency, project.default_currency)
|
bill.original_amount = self.currency_helper.exchange_currency(
|
||||||
|
float(bill.amount), bill.original_currency, project.default_currency
|
||||||
|
)
|
||||||
|
|
||||||
return bill
|
return bill
|
||||||
|
|
||||||
|
|
|
@ -379,7 +379,6 @@ class Bill(db.Model):
|
||||||
"external_link": self.external_link,
|
"external_link": self.external_link,
|
||||||
"original_currency": self.original_currency,
|
"original_currency": self.original_currency,
|
||||||
"original_amount": self.original_amount,
|
"original_amount": self.original_amount,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def pay_each(self):
|
def pay_each(self):
|
||||||
|
|
|
@ -97,8 +97,8 @@
|
||||||
{{ input(form.what, inline=True) }}
|
{{ input(form.what, inline=True) }}
|
||||||
{{ input(form.payer, inline=True, class="form-control custom-select") }}
|
{{ input(form.payer, inline=True, class="form-control custom-select") }}
|
||||||
{{ input(form.amount, inline=True) }}
|
{{ input(form.amount, inline=True) }}
|
||||||
{{ input(form.external_link, inline=True) }}
|
|
||||||
{{ input(form.original_currency, inline=True) }}
|
{{ input(form.original_currency, inline=True) }}
|
||||||
|
{{ input(form.external_link, inline=True) }}
|
||||||
|
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label class="col-3" for="payed_for">{{ _("For whom?") }}</label>
|
<label class="col-3" for="payed_for">{{ _("For whom?") }}</label>
|
||||||
|
|
|
@ -414,6 +414,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": fred_id,
|
"payer": fred_id,
|
||||||
"payed_for": [fred_id],
|
"payed_for": [fred_id],
|
||||||
"amount": "25",
|
"amount": "25",
|
||||||
|
"original_amount": "25",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -465,6 +467,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": alexis.id,
|
"payer": alexis.id,
|
||||||
"payed_for": [alexis.id],
|
"payed_for": [alexis.id],
|
||||||
"amount": "25",
|
"amount": "25",
|
||||||
|
"original_amount": "25",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -619,6 +623,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": members_ids[0],
|
"payer": members_ids[0],
|
||||||
"payed_for": members_ids,
|
"payed_for": members_ids,
|
||||||
"amount": "25",
|
"amount": "25",
|
||||||
|
"original_amount": "25",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
models.Project.query.get("raclette")
|
models.Project.query.get("raclette")
|
||||||
|
@ -634,6 +640,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": members_ids[0],
|
"payer": members_ids[0],
|
||||||
"payed_for": members_ids,
|
"payed_for": members_ids,
|
||||||
"amount": "10",
|
"amount": "10",
|
||||||
|
"original_amount": "10",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -653,6 +661,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": members_ids[0],
|
"payer": members_ids[0],
|
||||||
"payed_for": members_ids,
|
"payed_for": members_ids,
|
||||||
"amount": "19",
|
"amount": "19",
|
||||||
|
"original_amount": "19",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -664,6 +674,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": members_ids[1],
|
"payer": members_ids[1],
|
||||||
"payed_for": members_ids[0],
|
"payed_for": members_ids[0],
|
||||||
"amount": "20",
|
"amount": "20",
|
||||||
|
"original_amount": "20",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -675,6 +687,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": members_ids[1],
|
"payer": members_ids[1],
|
||||||
"payed_for": members_ids,
|
"payed_for": members_ids,
|
||||||
"amount": "17",
|
"amount": "17",
|
||||||
|
"original_amount": "17",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -690,6 +704,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": members_ids[0],
|
"payer": members_ids[0],
|
||||||
"payed_for": members_ids,
|
"payed_for": members_ids,
|
||||||
"amount": "-25",
|
"amount": "-25",
|
||||||
|
"original_amount": "-25",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
bill = models.Bill.query.filter(models.Bill.date == "2011-08-12")[0]
|
bill = models.Bill.query.filter(models.Bill.date == "2011-08-12")[0]
|
||||||
|
@ -704,6 +720,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": members_ids[0],
|
"payer": members_ids[0],
|
||||||
"payed_for": members_ids,
|
"payed_for": members_ids,
|
||||||
"amount": "25,02",
|
"amount": "25,02",
|
||||||
|
"original_amount": "25,02",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
bill = models.Bill.query.filter(models.Bill.date == "2011-08-01")[0]
|
bill = models.Bill.query.filter(models.Bill.date == "2011-08-01")[0]
|
||||||
|
@ -729,6 +747,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": members_ids[0],
|
"payer": members_ids[0],
|
||||||
"payed_for": members_ids,
|
"payed_for": members_ids,
|
||||||
"amount": "10",
|
"amount": "10",
|
||||||
|
"original_amount": "10",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -740,6 +760,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": members_ids[1],
|
"payer": members_ids[1],
|
||||||
"payed_for": members_ids,
|
"payed_for": members_ids,
|
||||||
"amount": "10",
|
"amount": "10",
|
||||||
|
"original_amount": "10",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -804,6 +826,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 1,
|
"payer": 1,
|
||||||
"payed_for": [1, 2, 3],
|
"payed_for": [1, 2, 3],
|
||||||
"amount": "24.36",
|
"amount": "24.36",
|
||||||
|
"original_amount": "24.36",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -815,6 +839,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 2,
|
"payer": 2,
|
||||||
"payed_for": [1],
|
"payed_for": [1],
|
||||||
"amount": "19.12",
|
"amount": "19.12",
|
||||||
|
"original_amount": "19.12",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -826,6 +852,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 1,
|
"payer": 1,
|
||||||
"payed_for": [1, 2],
|
"payed_for": [1, 2],
|
||||||
"amount": "22",
|
"amount": "22",
|
||||||
|
"original_amount": "22",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -913,6 +941,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 1,
|
"payer": 1,
|
||||||
"payed_for": [1, 2, 3],
|
"payed_for": [1, 2, 3],
|
||||||
"amount": "10.0",
|
"amount": "10.0",
|
||||||
|
"original_amount": "10",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -924,6 +954,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 2,
|
"payer": 2,
|
||||||
"payed_for": [1],
|
"payed_for": [1],
|
||||||
"amount": "20",
|
"amount": "20",
|
||||||
|
"original_amount": "20",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -935,6 +967,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 1,
|
"payer": 1,
|
||||||
"payed_for": [1, 2],
|
"payed_for": [1, 2],
|
||||||
"amount": "10",
|
"amount": "10",
|
||||||
|
"original_amount": "10",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -992,6 +1026,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 1,
|
"payer": 1,
|
||||||
"payed_for": [1, 2, 3],
|
"payed_for": [1, 2, 3],
|
||||||
"amount": "10.0",
|
"amount": "10.0",
|
||||||
|
"original_amount": "10.0",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1003,6 +1039,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 2,
|
"payer": 2,
|
||||||
"payed_for": [1],
|
"payed_for": [1],
|
||||||
"amount": "20",
|
"amount": "20",
|
||||||
|
"original_amount": "20",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1014,6 +1052,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 1,
|
"payer": 1,
|
||||||
"payed_for": [1, 2],
|
"payed_for": [1, 2],
|
||||||
"amount": "10",
|
"amount": "10",
|
||||||
|
"original_amount": "10",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
project = models.Project.query.get("raclette")
|
project = models.Project.query.get("raclette")
|
||||||
|
@ -1045,6 +1085,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 1,
|
"payer": 1,
|
||||||
"payed_for": [1, 2, 3],
|
"payed_for": [1, 2, 3],
|
||||||
"amount": "10.0",
|
"amount": "10.0",
|
||||||
|
"original_amount": "10",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1056,6 +1098,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 2,
|
"payer": 2,
|
||||||
"payed_for": [1, 3],
|
"payed_for": [1, 3],
|
||||||
"amount": "20",
|
"amount": "20",
|
||||||
|
"original_amount": "20",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1067,6 +1111,8 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 3,
|
"payer": 3,
|
||||||
"payed_for": [2],
|
"payed_for": [2],
|
||||||
"amount": "13.33",
|
"amount": "13.33",
|
||||||
|
"original_amount": "13.33",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
project = models.Project.query.get("raclette")
|
project = models.Project.query.get("raclette")
|
||||||
|
@ -1099,6 +1145,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 1,
|
"payer": 1,
|
||||||
"payed_for": [1, 2, 3, 4],
|
"payed_for": [1, 2, 3, 4],
|
||||||
"amount": "10.0",
|
"amount": "10.0",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1110,6 +1157,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 2,
|
"payer": 2,
|
||||||
"payed_for": [1, 3],
|
"payed_for": [1, 3],
|
||||||
"amount": "200",
|
"amount": "200",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1121,6 +1169,7 @@ class BudgetTestCase(IhatemoneyTestCase):
|
||||||
"payer": 3,
|
"payer": 3,
|
||||||
"payed_for": [2],
|
"payed_for": [2],
|
||||||
"amount": "13.33",
|
"amount": "13.33",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1729,7 +1778,7 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
"id": id,
|
"id": id,
|
||||||
"external_link": "",
|
"external_link": "",
|
||||||
"original_currency": "USD",
|
"original_currency": "USD",
|
||||||
"original_amount": input_amount,
|
"original_amount": expected_amount,
|
||||||
}
|
}
|
||||||
|
|
||||||
got = json.loads(req.data.decode("utf-8"))
|
got = json.loads(req.data.decode("utf-8"))
|
||||||
|
@ -1758,6 +1807,8 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
"payer": "1",
|
"payer": "1",
|
||||||
"payed_for": ["1", "2"],
|
"payed_for": ["1", "2"],
|
||||||
"amount": amount,
|
"amount": amount,
|
||||||
|
"original_amount": amount,
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
headers=self.get_auth("raclette"),
|
headers=self.get_auth("raclette"),
|
||||||
)
|
)
|
||||||
|
@ -1780,6 +1831,8 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
"payer": "1",
|
"payer": "1",
|
||||||
"payed_for": ["1", "2"],
|
"payed_for": ["1", "2"],
|
||||||
"amount": "25",
|
"amount": "25",
|
||||||
|
"original_amount": "25",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
headers=self.get_auth("raclette"),
|
headers=self.get_auth("raclette"),
|
||||||
)
|
)
|
||||||
|
@ -1847,6 +1900,8 @@ class APITestCase(IhatemoneyTestCase):
|
||||||
"payer": "1",
|
"payer": "1",
|
||||||
"payed_for": ["1", "2"],
|
"payed_for": ["1", "2"],
|
||||||
"amount": "25",
|
"amount": "25",
|
||||||
|
"original_amount": "25",
|
||||||
|
"original_currency": "USD",
|
||||||
},
|
},
|
||||||
headers=self.get_auth("raclette"),
|
headers=self.get_auth("raclette"),
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,12 +14,13 @@ from datetime import datetime, timedelta
|
||||||
import csv
|
import csv
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
|
||||||
class CurrencyConverter(object):
|
class CurrencyConverter(object):
|
||||||
api_url = 'https://api.exchangerate-api.com/v4/latest/USD'
|
api_url = "https://api.exchangerate-api.com/v4/latest/USD"
|
||||||
response = []
|
response = []
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.response = requests.get(self.api_url).json();
|
self.response = requests.get(self.api_url).json()
|
||||||
|
|
||||||
def get_currencies(self):
|
def get_currencies(self):
|
||||||
currencies = []
|
currencies = []
|
||||||
|
@ -28,6 +29,9 @@ class CurrencyConverter(object):
|
||||||
return currencies
|
return currencies
|
||||||
|
|
||||||
def exchange_currency(self, amount, currency1, currency2):
|
def exchange_currency(self, amount, currency1, currency2):
|
||||||
|
if currency1 == currency2:
|
||||||
|
return amount
|
||||||
|
|
||||||
base = self.response["base"]
|
base = self.response["base"]
|
||||||
conversion_rate1 = self.response["rates"][currency1]
|
conversion_rate1 = self.response["rates"][currency1]
|
||||||
conversion_rate2 = self.response["rates"][currency2]
|
conversion_rate2 = self.response["rates"][currency2]
|
||||||
|
@ -35,6 +39,7 @@ class CurrencyConverter(object):
|
||||||
# round to two digits because we are dealing with money
|
# round to two digits because we are dealing with money
|
||||||
return round(new_amount, 2)
|
return round(new_amount, 2)
|
||||||
|
|
||||||
|
|
||||||
def slugify(value):
|
def slugify(value):
|
||||||
"""Normalizes string, converts to lowercase, removes non-alpha characters,
|
"""Normalizes string, converts to lowercase, removes non-alpha characters,
|
||||||
and converts spaces to hyphens.
|
and converts spaces to hyphens.
|
||||||
|
|
|
@ -317,9 +317,7 @@ def create_project():
|
||||||
)
|
)
|
||||||
return redirect(url_for(".list_bills", project_id=project.id))
|
return redirect(url_for(".list_bills", project_id=project.id))
|
||||||
|
|
||||||
return render_template(
|
return render_template("create_project.html", form=form,)
|
||||||
"create_project.html", form=form,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@main.route("/password-reminder", methods=["GET", "POST"])
|
@main.route("/password-reminder", methods=["GET", "POST"])
|
||||||
|
@ -391,9 +389,7 @@ def edit_project():
|
||||||
edit_form.contact_email.data = g.project.contact_email
|
edit_form.contact_email.data = g.project.contact_email
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"edit_project.html",
|
"edit_project.html", edit_form=edit_form, current_view="edit_project",
|
||||||
edit_form=edit_form,
|
|
||||||
current_view="edit_project",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue