Merge pull request #1 from FlowingCloudRTL/rui-dev

bill attribute added
This commit is contained in:
MelodyZhangYiqun 2022-12-11 21:58:19 -05:00 committed by GitHub
commit 7584360363
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 186 additions and 24 deletions

View file

@ -9,7 +9,8 @@ ACTIVATE_DEMO_PROJECT = True
ADMIN_PASSWORD = ""
ALLOW_PUBLIC_PROJECT_CREATION = True
ACTIVATE_ADMIN_DASHBOARD = False
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = False
TEMPLATES_AUTO_RELOAD = True
SUPPORTED_LANGUAGES = [
"de",
"el",

View file

@ -77,6 +77,7 @@ def get_billform_for(project, set_default=True, **kwargs):
active_members = [(m.id, m.name) for m in project.active_members]
form.bill_type.choices = project.bill_types
form.payed_for.choices = form.payer.choices = active_members
form.payed_for.default = [m.id for m in project.active_members]
@ -336,8 +337,9 @@ class BillForm(FlaskForm):
description=_("A link to an external document, related to this bill"),
)
payed_for = SelectMultipleField(
_("For whom?"), validators=[DataRequired()], coerce=int
_("For Who?"), validators=[DataRequired()], coerce=int
)
bill_type = SelectField(_("Bill Type"), validators=[DataRequired()], coerce=str)
submit = SubmitField(_("Submit"))
submit2 = SubmitField(_("Submit and add a new one"))
@ -351,12 +353,14 @@ class BillForm(FlaskForm):
payer_id=self.payer.data,
project_default_currency=project.default_currency,
what=self.what.data,
bill_type=self.bill_type.data,
)
def save(self, bill, project):
bill.payer_id = self.payer.data
bill.amount = self.amount.data
bill.what = self.what.data
bill.bill_type = self.bill_type.data
bill.external_link = self.external_link.data
bill.date = self.date.data
bill.owers = Person.query.get_by_ids(self.payed_for.data, project)
@ -370,6 +374,7 @@ class BillForm(FlaskForm):
self.payer.data = bill.payer_id
self.amount.data = bill.amount
self.what.data = bill.what
self.bill_type.data = bill.bill_type
self.external_link.data = bill.external_link
self.original_currency.data = bill.original_currency
self.date.data = bill.date
@ -393,6 +398,10 @@ class BillForm(FlaskForm):
# See https://github.com/python-babel/babel/issues/821
raise ValidationError(f"Result is too high: {field.data}")
def validate_bill_type(self, field):
if (field.data, field.data) not in Project.bill_types:
raise ValidationError(_("Invalid Bill Type"))
class MemberForm(FlaskForm):
name = StringField(_("Name"), validators=[DataRequired()], filters=[strip_filter])

View file

@ -0,0 +1,23 @@
"""new bill type attribute added
Revision ID: 7a9b38559992
Revises: 927ed575acbd
Create Date: 2022-12-10 17:25:38.387643
"""
# revision identifiers, used by Alembic.
revision = "7a9b38559992"
down_revision = "927ed575acbd"
from alembic import op
import sqlalchemy as sa
def upgrade():
op.add_column("bill", sa.Column("bill_type", sa.UnicodeText()))
op.add_column("bill_version", sa.Column("bill_type", sa.UnicodeText()))
def downgrade():
pass

View file

@ -74,6 +74,13 @@ class Project(db.Model):
query_class = ProjectQuery
default_currency = db.Column(db.String(3))
bill_types = [
("Expense", "Expense"),
("Reimbursment", "Reimbursment"),
("Refund", "Refund"),
("Transfer", "Transfer"),
("Payment", "Payment"),
]
@property
def _to_serialize(self):
@ -334,6 +341,7 @@ class Project(db.Model):
pretty_bills.append(
{
"what": bill.what,
"bill_type": bill.bill_type,
"amount": round(bill.amount, 2),
"currency": bill.original_currency,
"date": str(bill.date),
@ -405,6 +413,7 @@ class Project(db.Model):
new_bill = Bill(
amount=b["amount"],
date=parse(b["date"]),
bill_type=b["bill_type"],
external_link="",
original_currency=b["currency"],
owers=Person.query.get_by_names(b["owers"], self),
@ -533,14 +542,15 @@ class Project(db.Model):
db.session.commit()
operations = (
("Georg", 200, ("Amina", "Georg", "Alice"), "Food shopping"),
("Alice", 20, ("Amina", "Alice"), "Beer !"),
("Amina", 50, ("Amina", "Alice", "Georg"), "AMAP"),
("Georg", 200, ("Amina", "Georg", "Alice"), "Food shopping", "Expense"),
("Alice", 20, ("Amina", "Alice"), "Beer !", "Expense"),
("Amina", 50, ("Amina", "Alice", "Georg"), "AMAP", "Expense"),
)
for (payer, amount, owers, what) in operations:
for (payer, amount, owers, what, bill_type) in operations:
db.session.add(
Bill(
amount=amount,
bill_type=bill_type,
original_currency=project.default_currency,
owers=[members[name] for name in owers],
payer_id=members[payer].id,
@ -673,6 +683,7 @@ class Bill(db.Model):
date = db.Column(db.Date, default=datetime.datetime.now)
creation_date = db.Column(db.Date, default=datetime.datetime.now)
what = db.Column(db.UnicodeText)
bill_type = db.Column(db.UnicodeText)
external_link = db.Column(db.UnicodeText)
original_currency = db.Column(db.String(3))
@ -692,6 +703,7 @@ class Bill(db.Model):
payer_id: int = None,
project_default_currency: str = "",
what: str = "",
bill_type: str = "",
):
super().__init__()
self.amount = amount
@ -701,6 +713,7 @@ class Bill(db.Model):
self.owers = owers
self.payer_id = payer_id
self.what = what
self.bill_type = bill_type
self.converted_amount = self.currency_helper.exchange_currency(
self.amount, self.original_currency, project_default_currency
)
@ -715,6 +728,7 @@ class Bill(db.Model):
"date": self.date,
"creation_date": self.creation_date,
"what": self.what,
"bill_type": self.bill_type,
"external_link": self.external_link,
"original_currency": self.original_currency,
"converted_amount": self.converted_amount,

View file

@ -164,6 +164,7 @@
{% include "display_errors.html" %}
{{ form.hidden_tag() }}
{{ input(form.date, inline=True) }}
{{ input(form.bill_type, inline=True) }}
{{ input(form.what, inline=True) }}
{{ input(form.payer, inline=True, class="form-control custom-select") }}
<div data-toggle="tooltip" data-placement="top" title='{{ _("Simple operations are allowed, e.g. (18+36.2)/3") }}'>

View file

@ -126,6 +126,7 @@
<table id="bill_table" class="col table table-striped table-hover table-responsive-sm">
<thead>
<tr><th>{{ _("When?") }}
</th><th>{{ _("Bill Type") }}
</th><th>{{ _("Who paid?") }}
</th><th>{{ _("For what?") }}
</th><th>{{ _("For whom?") }}
@ -141,6 +142,7 @@
{{ bill.date }}
</span>
</td>
<td>{{ bill.bill_type }}</td>
<td>{{ bill.payer }}</td>
<td>{{ bill.what }}</td>
<td>{% if bill.owers|length == g.project.members|length -%}

View file

@ -96,7 +96,8 @@ class APITestCase(IhatemoneyTestCase):
self.assertTrue(400, resp.status_code)
self.assertEqual(
'{"contact_email": ["Invalid email address."]}\n', resp.data.decode("utf-8")
"".join('{"contact_email": ["Invalid email address."]}\n'.split()),
"".join(resp.data.decode("utf-8").split()),
)
# create it
@ -363,6 +364,7 @@ class APITestCase(IhatemoneyTestCase):
"what": "fromage",
"payer": "1",
"payed_for": ["1", "2"],
"bill_type": "Expense",
"amount": "25",
"external_link": "https://raclette.fr",
},
@ -387,6 +389,7 @@ class APITestCase(IhatemoneyTestCase):
{"activated": True, "id": 1, "name": "zorglub", "weight": 1},
{"activated": True, "id": 2, "name": "fred", "weight": 1},
],
"bill_type": "Expense",
"amount": 25.0,
"date": "2011-08-10",
"id": 1,
@ -418,6 +421,7 @@ class APITestCase(IhatemoneyTestCase):
"what": "fromage",
"payer": "1",
"payed_for": ["1", "2"],
"bill_type": "Expense",
"amount": "25",
"external_link": "https://raclette.fr",
},
@ -426,7 +430,8 @@ class APITestCase(IhatemoneyTestCase):
self.assertStatus(400, req)
self.assertEqual(
'{"date": ["This field is required."]}\n', req.data.decode("utf-8")
"".join('{"date": ["This field is required."]}'.split()),
"".join(req.data.decode("utf-8").split()),
)
# edit a bill
@ -437,6 +442,7 @@ class APITestCase(IhatemoneyTestCase):
"what": "beer",
"payer": "2",
"payed_for": ["1", "2"],
"bill_type": "Expense",
"amount": "25",
"external_link": "https://raclette.fr",
},
@ -458,6 +464,7 @@ class APITestCase(IhatemoneyTestCase):
{"activated": True, "id": 1, "name": "zorglub", "weight": 1},
{"activated": True, "id": 2, "name": "fred", "weight": 1},
],
"bill_type": "Expense",
"amount": 25.0,
"date": "2011-09-10",
"external_link": "https://raclette.fr",
@ -512,6 +519,7 @@ class APITestCase(IhatemoneyTestCase):
"what": "fromage",
"payer": "1",
"payed_for": ["1", "2"],
"bill_type": "Expense",
"amount": input_amount,
},
headers=self.get_auth("raclette"),
@ -536,6 +544,7 @@ class APITestCase(IhatemoneyTestCase):
{"activated": True, "id": 1, "name": "zorglub", "weight": 1},
{"activated": True, "id": 2, "name": "fred", "weight": 1},
],
"bill_type": "Expense",
"amount": expected_amount,
"date": "2011-08-10",
"id": id,
@ -569,6 +578,7 @@ class APITestCase(IhatemoneyTestCase):
"what": "fromage",
"payer": "1",
"payed_for": ["1", "2"],
"bill_type": "Expense",
"amount": amount,
},
headers=self.get_auth("raclette"),
@ -615,6 +625,7 @@ class APITestCase(IhatemoneyTestCase):
"what": "fromage",
"payer": "1",
"payed_for": ["1", "2"],
"bill_type": "Expense",
"amount": "25",
"external_link": "https://raclette.fr",
},
@ -639,6 +650,7 @@ class APITestCase(IhatemoneyTestCase):
{"activated": True, "id": 1, "name": "zorglub", "weight": 1},
{"activated": True, "id": 2, "name": "fred", "weight": 1},
],
"bill_type": "Expense",
"amount": 25.0,
"date": "2011-08-10",
"id": 1,
@ -663,6 +675,7 @@ class APITestCase(IhatemoneyTestCase):
"what": "fromage",
"payer": "1",
"payed_for": ["1", "2"],
"bill_type": "Expense",
"amount": "30",
"external_link": "https://raclette.fr",
"original_currency": "CAD",
@ -684,6 +697,7 @@ class APITestCase(IhatemoneyTestCase):
{"activated": True, "id": 1, "name": "zorglub", "weight": 1.0},
{"activated": True, "id": 2, "name": "fred", "weight": 1.0},
],
"bill_type": "Expense",
"amount": 30.0,
"date": "2011-08-10",
"id": 1,
@ -704,6 +718,7 @@ class APITestCase(IhatemoneyTestCase):
"what": "Pierogi",
"payer": "1",
"payed_for": ["2", "3"],
"bill_type": "Expense",
"amount": "80",
"original_currency": "PLN",
},
@ -747,6 +762,7 @@ class APITestCase(IhatemoneyTestCase):
"what": "fromage",
"payer": "1",
"payed_for": ["1", "2"],
"bill_type": "Expense",
"amount": "25",
},
headers=self.get_auth("raclette"),
@ -814,6 +830,7 @@ class APITestCase(IhatemoneyTestCase):
"what": "fromage",
"payer": "1",
"payed_for": ["1", "2"],
"bill_type": "Expense",
"amount": "25",
},
headers=self.get_auth("raclette"),
@ -836,6 +853,7 @@ class APITestCase(IhatemoneyTestCase):
{"activated": True, "id": 1, "name": "zorglub", "weight": 1},
{"activated": True, "id": 2, "name": "freddy familly", "weight": 4},
],
"bill_type": "Expense",
"amount": 25.0,
"date": "2011-08-10",
"id": 1,
@ -923,6 +941,7 @@ class APITestCase(IhatemoneyTestCase):
"what": "fromage",
"payer": "1",
"payed_for": ["1"],
"bill_type": "Expense",
"amount": "0",
},
headers=self.get_auth("raclette"),
@ -951,6 +970,7 @@ class APITestCase(IhatemoneyTestCase):
"what": "fromage",
"payer": "1",
"payed_for": ["1"],
"bill_type": "Expense",
"amount": "9347242149381274732472348728748723473278472843.12",
},
headers=self.get_auth("raclette"),

View file

@ -411,6 +411,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": fred_id,
"payed_for": [fred_id],
"bill_type": "Expense",
"amount": "25",
},
)
@ -462,6 +463,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": zorglub.id,
"payed_for": [zorglub.id],
"bill_type": "Expense",
"amount": "25",
},
)
@ -635,6 +637,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": members_ids[0],
"payed_for": members_ids,
"bill_type": "Expense",
"amount": "25",
},
)
@ -650,6 +653,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": members_ids[0],
"payed_for": members_ids,
"bill_type": "Expense",
"amount": "10",
},
)
@ -673,6 +677,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": members_ids[0],
"payed_for": members_ids,
"bill_type": "Expense",
"amount": "19",
},
)
@ -684,6 +689,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": members_ids[1],
"payed_for": members_ids[0],
"bill_type": "Expense",
"amount": "20",
},
)
@ -695,6 +701,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": members_ids[1],
"payed_for": members_ids,
"bill_type": "Expense",
"amount": "17",
},
)
@ -710,6 +717,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": members_ids[0],
"payed_for": members_ids,
"bill_type": "Expense",
"amount": "-25",
},
)
@ -724,6 +732,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": members_ids[0],
"payed_for": members_ids,
"bill_type": "Expense",
"amount": "25,02",
},
)
@ -738,6 +747,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": members_ids[0],
"payed_for": members_ids,
"bill_type": "Expense",
"amount": "42",
"external_link": "https://example.com/fromage",
},
@ -753,6 +763,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "mauvais fromage à raclette",
"payer": members_ids[0],
"payed_for": members_ids,
"bill_type": "Expense",
"amount": "42000",
"external_link": "javascript:alert('Tu bluffes, Martoni.')",
},
@ -778,6 +789,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": members_ids[0],
"payed_for": members_ids,
"bill_type": "Expense",
"amount": "10",
},
)
@ -789,6 +801,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "pommes de terre",
"payer": members_ids[1],
"payed_for": members_ids,
"bill_type": "Expense",
"amount": "10",
},
)
@ -853,6 +866,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 1,
"payed_for": [1, 2, 3],
"bill_type": "Expense",
"amount": "24.36",
},
)
@ -864,6 +878,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "red wine",
"payer": 2,
"payed_for": [1],
"bill_type": "Expense",
"amount": "19.12",
},
)
@ -875,6 +890,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "delicatessen",
"payer": 1,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "22",
},
)
@ -977,6 +993,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 1,
"payed_for": [1, 2, 3],
"bill_type": "Expense",
"amount": "10.0",
},
)
@ -988,6 +1005,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "red wine",
"payer": 2,
"payed_for": [1],
"bill_type": "Expense",
"amount": "20",
},
)
@ -999,6 +1017,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "delicatessen",
"payer": 1,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "10",
},
)
@ -1047,6 +1066,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 2,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "30",
},
)
@ -1072,6 +1092,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "ice cream",
"payer": 2,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "10",
},
)
@ -1087,6 +1108,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "champomy",
"payer": 1,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "10",
},
)
@ -1102,6 +1124,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "smoothie",
"payer": 1,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "20",
},
)
@ -1118,6 +1141,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "more champomy",
"payer": 2,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "30",
},
)
@ -1150,6 +1174,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 1,
"payed_for": [1, 2, 3],
"bill_type": "Expense",
"amount": "10.0",
},
)
@ -1161,6 +1186,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "red wine",
"payer": 2,
"payed_for": [1],
"bill_type": "Expense",
"amount": "20",
},
)
@ -1172,6 +1198,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "delicatessen",
"payer": 1,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "10",
},
)
@ -1203,6 +1230,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 1,
"payed_for": [1, 2, 3],
"bill_type": "Expense",
"amount": "10.0",
},
)
@ -1214,6 +1242,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "red wine",
"payer": 2,
"payed_for": [1, 3],
"bill_type": "Expense",
"amount": "20",
},
)
@ -1225,6 +1254,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "refund",
"payer": 3,
"payed_for": [2],
"bill_type": "Expense",
"amount": "13.33",
},
)
@ -1259,6 +1289,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 1,
"payed_for": [1, 2, 3, 4],
"bill_type": "Expense",
"amount": "10.0",
},
)
@ -1277,6 +1308,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "roblochon",
"payer": 2,
"payed_for": [1, 3, 4],
"bill_type": "Expense",
"amount": "100.0",
}
# Try to access bill of another project
@ -1382,6 +1414,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 1,
"payed_for": [1, 2, 3],
"bill_type": "Expense",
"amount": "10.0",
},
)
@ -1393,6 +1426,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "red wine",
"payer": 2,
"payed_for": [1, 3],
"bill_type": "Expense",
"amount": "20",
},
)
@ -1404,6 +1438,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "refund",
"payer": 3,
"payed_for": [2],
"bill_type": "Expense",
"amount": "13.33",
},
)
@ -1429,6 +1464,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "refund from EUR",
"payer": 3,
"payed_for": [2],
"bill_type": "Expense",
"amount": "20",
"original_currency": "EUR",
},
@ -1452,6 +1488,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "Poutine",
"payer": 3,
"payed_for": [2],
"bill_type": "Expense",
"amount": "18",
"original_currency": "CAD",
},
@ -1508,6 +1545,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 1,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "10.0",
"original_currency": "EUR",
},
@ -1542,6 +1580,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 1,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "10.0",
"original_currency": "EUR",
},
@ -1554,6 +1593,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "aspirine",
"payer": 2,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "5.0",
"original_currency": "EUR",
},
@ -1587,6 +1627,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 1,
"payed_for": [1],
"bill_type": "Expense",
"amount": "0",
"original_currency": "EUR",
},
@ -1635,6 +1676,7 @@ class BudgetTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 1,
"payed_for": [1],
"bill_type": "Expense",
"amount": "9347242149381274732472348728748723473278472843.12",
"original_currency": "EUR",
},

View file

@ -200,6 +200,7 @@ class HistoryTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": user_id,
"payed_for": [user_id],
"bill_type": "Expense",
"amount": "25",
},
follow_redirects=True,
@ -216,6 +217,7 @@ class HistoryTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": user_id,
"payed_for": [user_id],
"bill_type": "Expense",
"amount": "10",
},
follow_redirects=True,
@ -367,6 +369,7 @@ class HistoryTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 1,
"payed_for": [1],
"bill_type": "Expense",
"amount": "25",
},
follow_redirects=True,
@ -388,6 +391,7 @@ class HistoryTestCase(IhatemoneyTestCase):
"what": "new thing",
"payer": 1,
"payed_for": [1],
"bill_type": "Expense",
"amount": "10",
},
follow_redirects=True,
@ -486,6 +490,7 @@ class HistoryTestCase(IhatemoneyTestCase):
"what": "Bill 1",
"payer": 1,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "25",
},
)
@ -496,6 +501,7 @@ class HistoryTestCase(IhatemoneyTestCase):
"what": "Bill 2",
"payer": 1,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "20",
},
)
@ -514,6 +520,7 @@ class HistoryTestCase(IhatemoneyTestCase):
"what": "Bill 1",
"payer": 1,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "88",
},
)
@ -555,6 +562,7 @@ class HistoryTestCase(IhatemoneyTestCase):
"what": "Bill 1",
"payer": 1,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "25",
},
)
@ -579,6 +587,7 @@ class HistoryTestCase(IhatemoneyTestCase):
"what": "Bill 2",
"payer": 1,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "20",
},
)
@ -641,6 +650,7 @@ class HistoryTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 1,
"payed_for": [1],
"bill_type": "Expense",
"amount": "10",
"original_currency": "EUR",
},

View file

@ -14,6 +14,7 @@ class CommonTestCase(object):
{
"date": "2017-01-01",
"what": "refund",
"bill_type": "Expense",
"amount": 13.33,
"payer_name": "tata",
"payer_weight": 1.0,
@ -22,6 +23,7 @@ class CommonTestCase(object):
{
"date": "2016-12-31",
"what": "red wine",
"bill_type": "Expense",
"amount": 200.0,
"payer_name": "fred",
"payer_weight": 1.0,
@ -29,7 +31,8 @@ class CommonTestCase(object):
},
{
"date": "2016-12-31",
"what": "fromage a raclette",
"what": "a raclette",
"bill_type": "Expense",
"amount": 10.0,
"payer_name": "zorglub",
"payer_weight": 2.0,
@ -71,6 +74,7 @@ class CommonTestCase(object):
if b["what"] == d["what"]:
self.assertEqual(b["payer_name"], d["payer_name"])
self.assertEqual(b["amount"], d["amount"])
self.assertEqual(b["bill_type"], d["bill_type"])
self.assertEqual(b["currency"], d["currency"])
self.assertEqual(b["payer_weight"], d["payer_weight"])
self.assertEqual(b["date"], d["date"])
@ -114,6 +118,7 @@ class CommonTestCase(object):
self.assertEqual(b["amount"], d["amount"])
# Currency should have been stripped
self.assertEqual(b["currency"], "XXX")
self.assertEqual(b["bill_type"], d["bill_type"])
self.assertEqual(b["payer_weight"], d["payer_weight"])
self.assertEqual(b["date"], d["date"])
list_project = [ower for ower in b["owers"]]
@ -172,6 +177,7 @@ class CommonTestCase(object):
self.assertEqual(b["amount"], d["amount"])
# All bills are converted to default project currency
self.assertEqual(b["currency"], "EUR")
self.assertEqual(b["bill_type"], d["bill_type"])
self.assertEqual(b["payer_weight"], d["payer_weight"])
self.assertEqual(b["date"], d["date"])
list_project = [ower for ower in b["owers"]]
@ -210,6 +216,7 @@ class CommonTestCase(object):
if b["what"] == d["what"]:
self.assertEqual(b["payer_name"], d["payer_name"])
self.assertEqual(b["amount"], d["amount"])
self.assertEqual(b["bill_type"], d["bill_type"])
self.assertEqual(b["currency"], "XXX")
self.assertEqual(b["payer_weight"], d["payer_weight"])
self.assertEqual(b["date"], d["date"])
@ -237,6 +244,7 @@ class CommonTestCase(object):
data={
"date": "2016-12-31",
"what": "red wine",
"bill_type": "Expense",
"payer": 2,
"payed_for": [1, 3],
"amount": "200",
@ -266,6 +274,7 @@ class CommonTestCase(object):
if b["what"] == d["what"]:
self.assertEqual(b["payer_name"], d["payer_name"])
self.assertEqual(b["amount"], d["amount"])
self.assertEqual(b["bill_type"], d["bill_type"])
self.assertEqual(b["currency"], d["currency"])
self.assertEqual(b["payer_weight"], d["payer_weight"])
self.assertEqual(b["date"], d["date"])
@ -292,6 +301,7 @@ class CommonTestCase(object):
{
"date": "2017-01-01",
"what": "refund",
"bill_type": "Refund",
"payer_name": "tata",
"payer_weight": 1.0,
"owers": ["fred"],
@ -319,7 +329,8 @@ class ExportTestCase(IhatemoneyTestCase):
"/raclette/add",
data={
"date": "2016-12-31",
"what": "fromage à raclette",
"bill_type": "Expense",
"what": "à raclette",
"payer": 1,
"payed_for": [1, 2, 3, 4],
"amount": "10.0",
@ -330,6 +341,7 @@ class ExportTestCase(IhatemoneyTestCase):
"/raclette/add",
data={
"date": "2016-12-31",
"bill_type": "Expense",
"what": "red wine",
"payer": 2,
"payed_for": [1, 3],
@ -341,6 +353,7 @@ class ExportTestCase(IhatemoneyTestCase):
"/raclette/add",
data={
"date": "2017-01-01",
"bill_type": "Refund",
"what": "refund",
"payer": 3,
"payed_for": [2],
@ -353,6 +366,7 @@ class ExportTestCase(IhatemoneyTestCase):
expected = [
{
"date": "2017-01-01",
"bill_type": "Refund",
"what": "refund",
"amount": 13.33,
"currency": "XXX",
@ -362,6 +376,7 @@ class ExportTestCase(IhatemoneyTestCase):
},
{
"date": "2016-12-31",
"bill_type": "Expense",
"what": "red wine",
"amount": 200.0,
"currency": "XXX",
@ -371,7 +386,8 @@ class ExportTestCase(IhatemoneyTestCase):
},
{
"date": "2016-12-31",
"what": "fromage \xe0 raclette",
"bill_type": "Expense",
"what": "\xe0 raclette",
"amount": 10.0,
"currency": "XXX",
"payer_name": "zorglub",
@ -384,10 +400,10 @@ class ExportTestCase(IhatemoneyTestCase):
# generate csv export of bills
resp = self.client.get("/raclette/export/bills.csv")
expected = [
"date,what,amount,currency,payer_name,payer_weight,owers",
"2017-01-01,refund,XXX,13.33,tata,1.0,fred",
'2016-12-31,red wine,XXX,200.0,fred,1.0,"zorglub, tata"',
'2016-12-31,fromage à raclette,10.0,XXX,zorglub,2.0,"zorglub, fred, tata, pépé"',
"date,what,bill_type,amount,currency,payer_name,payer_weight,owers",
"2017-01-01,refund,Refund,XXX,13.33,tata,1.0,fred",
'2016-12-31,red wine,Expense,XXX,200.0,fred,1.0,"zorglub, tata"',
'2016-12-31,à raclette,Expense,10.0,XXX,zorglub,2.0,"zorglub, fred, tata, pépé"',
]
received_lines = resp.data.decode("utf-8").split("\n")
@ -450,7 +466,8 @@ class ExportTestCase(IhatemoneyTestCase):
"/raclette/add",
data={
"date": "2016-12-31",
"what": "fromage à raclette",
"what": "à raclette",
"bill_type": "Expense",
"payer": 1,
"payed_for": [1, 2, 3, 4],
"amount": "10.0",
@ -463,6 +480,7 @@ class ExportTestCase(IhatemoneyTestCase):
data={
"date": "2016-12-31",
"what": "poutine from Québec",
"bill_type": "Expense",
"payer": 2,
"payed_for": [1, 3],
"amount": "100",
@ -475,6 +493,7 @@ class ExportTestCase(IhatemoneyTestCase):
data={
"date": "2017-01-01",
"what": "refund",
"bill_type": "Refund",
"payer": 3,
"payed_for": [2],
"amount": "13.33",
@ -488,6 +507,7 @@ class ExportTestCase(IhatemoneyTestCase):
{
"date": "2017-01-01",
"what": "refund",
"bill_type": "Refund",
"amount": 13.33,
"currency": "EUR",
"payer_name": "tata",
@ -497,6 +517,7 @@ class ExportTestCase(IhatemoneyTestCase):
{
"date": "2016-12-31",
"what": "poutine from Qu\xe9bec",
"bill_type": "Expense",
"amount": 100.0,
"currency": "CAD",
"payer_name": "fred",
@ -505,7 +526,8 @@ class ExportTestCase(IhatemoneyTestCase):
},
{
"date": "2016-12-31",
"what": "fromage \xe0 raclette",
"what": "\xe0 raclette",
"bill_type": "Expense",
"amount": 10.0,
"currency": "EUR",
"payer_name": "zorglub",
@ -518,10 +540,10 @@ class ExportTestCase(IhatemoneyTestCase):
# generate csv export of bills
resp = self.client.get("/raclette/export/bills.csv")
expected = [
"date,what,amount,currency,payer_name,payer_weight,owers",
"2017-01-01,refund,13.33,EUR,tata,1.0,fred",
'2016-12-31,poutine from Québec,100.0,CAD,fred,1.0,"zorglub, tata"',
'2016-12-31,fromage à raclette,10.0,EUR,zorglub,2.0,"zorglub, fred, tata, pépé"',
"date,what,bill_type,amount,currency,payer_name,payer_weight,owers",
"2017-01-01,refund,Refund,13.33,EUR,tata,1.0,fred",
'2016-12-31,poutine from Québec,Expense,100.0,CAD,fred,1.0,"zorglub, tata"',
'2016-12-31,à raclette,Expense,10.0,EUR,zorglub,2.0,"zorglub, fred, tata, pépé"',
]
received_lines = resp.data.decode("utf-8").split("\n")
@ -608,6 +630,7 @@ class ExportTestCase(IhatemoneyTestCase):
data={
"date": "2016-12-31",
"what": "=COS(36)",
"bill_type": "Expense",
"payer": 1,
"payed_for": [1],
"amount": "10.0",
@ -618,8 +641,8 @@ class ExportTestCase(IhatemoneyTestCase):
# generate csv export of bills
resp = self.client.get("/raclette/export/bills.csv")
expected = [
"date,what,amount,currency,payer_name,payer_weight,owers",
"2016-12-31,'=COS(36),10.0,EUR,zorglub,1.0,zorglub",
"date,what,bill_type,amount,currency,payer_name,payer_weight,owers",
"2016-12-31,'=COS(36),Expense,10.0,EUR,zorglub,1.0,zorglub",
]
received_lines = resp.data.decode("utf-8").split("\n")

View file

@ -127,6 +127,7 @@ class ModelsTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 1,
"payed_for": [1, 2, 3],
"bill_type": "Expense",
"amount": "10.0",
},
)
@ -138,6 +139,7 @@ class ModelsTestCase(IhatemoneyTestCase):
"what": "red wine",
"payer": 2,
"payed_for": [1],
"bill_type": "Expense",
"amount": "20",
},
)
@ -149,6 +151,7 @@ class ModelsTestCase(IhatemoneyTestCase):
"what": "delicatessen",
"payer": 1,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "10",
},
)
@ -183,6 +186,7 @@ class ModelsTestCase(IhatemoneyTestCase):
"what": "fromage à raclette",
"payer": 1,
"payed_for": [1, 2, 3],
"bill_type": "Expense",
"amount": "10.0",
},
)
@ -194,6 +198,7 @@ class ModelsTestCase(IhatemoneyTestCase):
"what": "red wine",
"payer": 2,
"payed_for": [1],
"bill_type": "Expense",
"amount": "20",
},
)
@ -205,6 +210,7 @@ class ModelsTestCase(IhatemoneyTestCase):
"what": "delicatessen",
"payer": 1,
"payed_for": [1, 2],
"bill_type": "Expense",
"amount": "10",
},
)

View file

@ -216,6 +216,7 @@ def csv2list_of_dicts(csv_to_convert):
r["amount"] = float(r["amount"])
r["payer_weight"] = float(r["payer_weight"])
r["owers"] = [o.strip() for o in r["owers"].split(",")]
r["bill_type"] = str(r["bill_type"])
result.append(r)
return result
@ -299,7 +300,16 @@ def get_members(file):
def same_bill(bill1, bill2):
attr = ["what", "payer_name", "payer_weight", "amount", "currency", "date", "owers"]
attr = [
"what",
"bill_type",
"payer_name",
"payer_weight",
"amount",
"currency",
"date",
"owers",
]
for a in attr:
if bill1[a] != bill2[a]:
return False

View file

@ -456,6 +456,7 @@ def import_project():
# Check data
attr = [
"amount",
"bill_type",
"currency",
"date",
"owers",