mirror of
https://github.com/spiral-project/ihatemoney.git
synced 2025-05-08 05:41:49 +02:00
feat: Optional link field in bill form.
An optional field has been added to the bill form to add a link to a real bill. A new action button allow user to see this bill. Breaking change with Bill model update for database, a migration is needed. See issue #429.
This commit is contained in:
parent
33d497aac2
commit
0d7c027617
7 changed files with 46 additions and 4 deletions
|
@ -1,8 +1,8 @@
|
||||||
from flask_wtf.form import FlaskForm
|
from flask_wtf.form import FlaskForm
|
||||||
from wtforms.fields.core import SelectField, SelectMultipleField
|
from wtforms.fields.core import SelectField, SelectMultipleField
|
||||||
from wtforms.fields.html5 import DateField, DecimalField
|
from wtforms.fields.html5 import DateField, DecimalField, URLField
|
||||||
from wtforms.fields.simple import PasswordField, SubmitField, TextAreaField, StringField
|
from wtforms.fields.simple import PasswordField, SubmitField, TextAreaField, StringField
|
||||||
from wtforms.validators import Email, DataRequired, ValidationError, EqualTo, NumberRange
|
from wtforms.validators import Email, DataRequired, ValidationError, EqualTo, NumberRange, Optional
|
||||||
from flask_babel import lazy_gettext as _
|
from flask_babel import lazy_gettext as _
|
||||||
from flask import request
|
from flask import request
|
||||||
from werkzeug.security import generate_password_hash
|
from werkzeug.security import generate_password_hash
|
||||||
|
@ -139,6 +139,7 @@ class BillForm(FlaskForm):
|
||||||
what = StringField(_("What?"), validators=[DataRequired()])
|
what = StringField(_("What?"), validators=[DataRequired()])
|
||||||
payer = SelectField(_("Payer"), validators=[DataRequired()], coerce=int)
|
payer = SelectField(_("Payer"), validators=[DataRequired()], coerce=int)
|
||||||
amount = CalculatorStringField(_("Amount paid"), validators=[DataRequired()])
|
amount = CalculatorStringField(_("Amount paid"), validators=[DataRequired()])
|
||||||
|
document = URLField(_("Document"), validators=[Optional()], description="A link to your bill.")
|
||||||
payed_for = SelectMultipleField(_("For whom?"),
|
payed_for = SelectMultipleField(_("For whom?"),
|
||||||
validators=[DataRequired()], coerce=int)
|
validators=[DataRequired()], coerce=int)
|
||||||
submit = SubmitField(_("Submit"))
|
submit = SubmitField(_("Submit"))
|
||||||
|
@ -149,6 +150,7 @@ class BillForm(FlaskForm):
|
||||||
bill.amount = self.amount.data
|
bill.amount = self.amount.data
|
||||||
bill.what = self.what.data
|
bill.what = self.what.data
|
||||||
bill.date = self.date.data
|
bill.date = self.date.data
|
||||||
|
bill.document = self.document.data
|
||||||
bill.owers = [Person.query.get(ower, project)
|
bill.owers = [Person.query.get(ower, project)
|
||||||
for ower in self.payed_for.data]
|
for ower in self.payed_for.data]
|
||||||
|
|
||||||
|
@ -159,6 +161,7 @@ class BillForm(FlaskForm):
|
||||||
self.amount.data = bill.amount
|
self.amount.data = bill.amount
|
||||||
self.what.data = bill.what
|
self.what.data = bill.what
|
||||||
self.date.data = bill.date
|
self.date.data = bill.date
|
||||||
|
self.document.data = bill.document
|
||||||
self.payed_for.data = [int(ower.id) for ower in bill.owers]
|
self.payed_for.data = [int(ower.id) for ower in bill.owers]
|
||||||
|
|
||||||
def set_default(self):
|
def set_default(self):
|
||||||
|
|
26
ihatemoney/migrations/versions/df95884d26ae_.py
Normal file
26
ihatemoney/migrations/versions/df95884d26ae_.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: df95884d26ae
|
||||||
|
Revises: a67119aa3ee5
|
||||||
|
Create Date: 2019-09-15 23:17:29.721176
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'df95884d26ae'
|
||||||
|
down_revision = 'a67119aa3ee5'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('bill', sa.Column('document', sa.UnicodeText(), nullable=True))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('bill', 'document')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -358,12 +358,13 @@ class Bill(db.Model):
|
||||||
date = db.Column(db.Date, default=datetime.now)
|
date = db.Column(db.Date, default=datetime.now)
|
||||||
creation_date = db.Column(db.Date, default=datetime.now)
|
creation_date = db.Column(db.Date, default=datetime.now)
|
||||||
what = db.Column(db.UnicodeText)
|
what = db.Column(db.UnicodeText)
|
||||||
|
document = db.Column(db.UnicodeText)
|
||||||
|
|
||||||
archive = db.Column(db.Integer, db.ForeignKey("archive.id"))
|
archive = db.Column(db.Integer, db.ForeignKey("archive.id"))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _to_serialize(self):
|
def _to_serialize(self):
|
||||||
return {
|
dict = {
|
||||||
"id": self.id,
|
"id": self.id,
|
||||||
"payer_id": self.payer_id,
|
"payer_id": self.payer_id,
|
||||||
"owers": self.owers,
|
"owers": self.owers,
|
||||||
|
@ -372,6 +373,9 @@ class Bill(db.Model):
|
||||||
"creation_date": self.creation_date,
|
"creation_date": self.creation_date,
|
||||||
"what": self.what,
|
"what": self.what,
|
||||||
}
|
}
|
||||||
|
if self.document:
|
||||||
|
dict["document"] = self.document
|
||||||
|
return dict
|
||||||
|
|
||||||
def pay_each(self):
|
def pay_each(self):
|
||||||
"""Compute what each share has to pay"""
|
"""Compute what each share has to pay"""
|
||||||
|
|
|
@ -290,7 +290,8 @@ footer .footer-left {
|
||||||
}
|
}
|
||||||
|
|
||||||
.bill-actions > .delete,
|
.bill-actions > .delete,
|
||||||
.bill-actions > .edit {
|
.bill-actions > .edit,
|
||||||
|
.bill-actions > .see {
|
||||||
font-size: 0px;
|
font-size: 0px;
|
||||||
display: block;
|
display: block;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
|
@ -308,6 +309,10 @@ footer .footer-left {
|
||||||
background: url("../images/edit.png") no-repeat right;
|
background: url("../images/edit.png") no-repeat right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bill-actions > .see {
|
||||||
|
background: url("../images/see.png") no-repeat right;
|
||||||
|
}
|
||||||
|
|
||||||
#bill_table {
|
#bill_table {
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
|
|
BIN
ihatemoney/static/images/see.png
Normal file
BIN
ihatemoney/static/images/see.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 502 B |
|
@ -95,6 +95,7 @@
|
||||||
{{ 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.document, 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>
|
||||||
|
|
|
@ -128,6 +128,9 @@
|
||||||
<td class="bill-actions">
|
<td class="bill-actions">
|
||||||
<a class="edit" href="{{ url_for(".edit_bill", bill_id=bill.id) }}" title="{{ _("edit") }}">{{ _('edit') }}</a>
|
<a class="edit" href="{{ url_for(".edit_bill", bill_id=bill.id) }}" title="{{ _("edit") }}">{{ _('edit') }}</a>
|
||||||
<a class="delete" href="{{ url_for(".delete_bill", bill_id=bill.id) }}" title="{{ _("delete") }}">{{ _('delete') }}</a>
|
<a class="delete" href="{{ url_for(".delete_bill", bill_id=bill.id) }}" title="{{ _("delete") }}">{{ _('delete') }}</a>
|
||||||
|
{% if bill.document %}
|
||||||
|
<a class="see" href="{{ bill.document }}" target="_blank" title="{{ _("see") }}">{{ _('see') }} </a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
Loading…
Reference in a new issue