From b21284f640eaec4397800c1b41e008454f21db0e Mon Sep 17 00:00:00 2001 From: Lunaresk Date: Sun, 28 May 2023 09:07:54 +0200 Subject: [PATCH] minor: add payment Admins can now add payments for their users. --- .gitignore | 3 +- ...4fec22c35530_delete_unnecessary_columns.py | 38 ++++++++++++++++++ ...854a6e2a0_establishment_candidate_table.py | 2 +- backend/src/establishment/__init__.py | 10 +++-- backend/src/establishment/overview/routes.py | 4 +- backend/src/establishment/payment/__init__.py | 5 +++ backend/src/establishment/payment/forms.py | 17 ++++++++ backend/src/establishment/payment/routes.py | 24 +++++++++++ backend/src/item/new/forms.py | 3 +- backend/src/models/bought.py | 1 - backend/src/models/payment.py | 2 +- .../establishment/overview/overview.html | 4 +- .../establishment/payment/new_payment.html | 6 +++ .../payment/new_payment_form.html | 8 ++++ boot.sh | 2 + frontend/src/index.html | 7 +++- requirements.txt | Bin 1220 -> 1368 bytes 17 files changed, 121 insertions(+), 15 deletions(-) create mode 100644 backend/migrations/versions/4fec22c35530_delete_unnecessary_columns.py create mode 100644 backend/src/establishment/payment/__init__.py create mode 100644 backend/src/establishment/payment/forms.py create mode 100644 backend/src/establishment/payment/routes.py create mode 100644 backend/src/templates/establishment/payment/new_payment.html create mode 100644 backend/src/templates/establishment/payment/new_payment_form.html diff --git a/.gitignore b/.gitignore index 1e42f46..2820fad 100644 --- a/.gitignore +++ b/.gitignore @@ -347,4 +347,5 @@ test.* .env* .flaskenv* !.env.project -!.env.vault \ No newline at end of file +!.env.vault +*.ps1 \ No newline at end of file diff --git a/backend/migrations/versions/4fec22c35530_delete_unnecessary_columns.py b/backend/migrations/versions/4fec22c35530_delete_unnecessary_columns.py new file mode 100644 index 0000000..6ff039c --- /dev/null +++ b/backend/migrations/versions/4fec22c35530_delete_unnecessary_columns.py @@ -0,0 +1,38 @@ +"""Delete unnecessary columns + +Revision ID: 4fec22c35530 +Revises: 610854a6e2a0 +Create Date: 2023-05-28 08:10:27.689070 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '4fec22c35530' +down_revision = '610854a6e2a0' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('bought', schema=None) as batch_op: + batch_op.drop_column('registered') + + with op.batch_alter_table('login_token', schema=None) as batch_op: + batch_op.drop_column('paid') + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('login_token', schema=None) as batch_op: + batch_op.add_column(sa.Column('paid', sa.BIGINT(), server_default=sa.text("'0'::bigint"), autoincrement=False, nullable=False)) + + with op.batch_alter_table('bought', schema=None) as batch_op: + batch_op.add_column(sa.Column('registered', sa.BOOLEAN(), server_default=sa.text('false'), autoincrement=False, nullable=False)) + + # ### end Alembic commands ### diff --git a/backend/migrations/versions/610854a6e2a0_establishment_candidate_table.py b/backend/migrations/versions/610854a6e2a0_establishment_candidate_table.py index fc0457a..be24572 100644 --- a/backend/migrations/versions/610854a6e2a0_establishment_candidate_table.py +++ b/backend/migrations/versions/610854a6e2a0_establishment_candidate_table.py @@ -26,7 +26,7 @@ def upgrade(): sa.PrimaryKeyConstraint('user', 'establishment') ) op.create_table('payment', - sa.Column('id', sa.BigInteger(), nullable=False), + sa.Column('id', sa.BigInteger(), nullable=False, autoincrement=True), sa.Column('token', sa.String(length=15), nullable=False), sa.Column('date', sa.Date(), server_default=sa.text('now()'), nullable=False), sa.Column('amount', sa.BigInteger(), server_default='0', nullable=False), diff --git a/backend/src/establishment/__init__.py b/backend/src/establishment/__init__.py index 04282a4..fc27635 100644 --- a/backend/src/establishment/__init__.py +++ b/backend/src/establishment/__init__.py @@ -1,11 +1,13 @@ from flask import Blueprint bp = Blueprint('establishment', __name__, url_prefix='/establishment') -from src.establishment.new import bp as bp_new -bp.register_blueprint(bp_new) +from src.establishment.candidates import bp as bp_candidates +bp.register_blueprint(bp_candidates) from src.establishment.list import bp as bp_list bp.register_blueprint(bp_list) +from src.establishment.new import bp as bp_new +bp.register_blueprint(bp_new) from src.establishment.overview import bp as bp_overview bp.register_blueprint(bp_overview) -from src.establishment.candidates import bp as bp_candidates -bp.register_blueprint(bp_candidates) \ No newline at end of file +from src.establishment.payment import bp as bp_payment +bp.register_blueprint(bp_payment) \ No newline at end of file diff --git a/backend/src/establishment/overview/routes.py b/backend/src/establishment/overview/routes.py index ad68a9d..d3429bc 100644 --- a/backend/src/establishment/overview/routes.py +++ b/backend/src/establishment/overview/routes.py @@ -7,10 +7,10 @@ from src.models import Establishment from src.utils import view_utils, database_utils from src.utils.routes_utils import render_custom_template as render_template -@bp.route('/', methods=['GET']) +@bp.route('/', methods=['GET']) @login_required def get_report_from_user(establishment_id): - establishment = Establishment.query.filter_by(id=int(establishment_id)).first_or_404() + Establishment.query.filter_by(id=int(establishment_id)).first_or_404() if current_user.is_anonymous: abort(403) if 'month' in request.args: diff --git a/backend/src/establishment/payment/__init__.py b/backend/src/establishment/payment/__init__.py new file mode 100644 index 0000000..44ddbe2 --- /dev/null +++ b/backend/src/establishment/payment/__init__.py @@ -0,0 +1,5 @@ +from flask import Blueprint + +bp = Blueprint('payment', __name__, url_prefix='/payment') + +from src.establishment.payment import routes \ No newline at end of file diff --git a/backend/src/establishment/payment/forms.py b/backend/src/establishment/payment/forms.py new file mode 100644 index 0000000..5e8aeb8 --- /dev/null +++ b/backend/src/establishment/payment/forms.py @@ -0,0 +1,17 @@ +from src.models import LoginToken +from flask_wtf import FlaskForm +from wtforms import DateField, FloatField, IntegerField, SelectField, SelectMultipleField, StringField, SubmitField +from wtforms.validators import DataRequired, Optional + +class NewPaymentForm(FlaskForm): + token = SelectField("User", validators=[DataRequired()], render_kw={"class": "form-control"}) + date = DateField("Date", validators=[DataRequired()], render_kw={"class": "form-control"}) + amount = IntegerField("Amount (in ct)", validators=[DataRequired()], render_kw={"class": "form-control"}) + submit = SubmitField("Submit", render_kw={"class": "btn btn-primary mt-3"}) + + @classmethod + def new(cls, establishment_id): + form = cls() + tokens_for_establishment = LoginToken.query.filter_by(establishment=int(establishment_id)).order_by("user").all() + form.token.choices = [(t.token, t.User.email) for t in tokens_for_establishment] + return form \ No newline at end of file diff --git a/backend/src/establishment/payment/routes.py b/backend/src/establishment/payment/routes.py new file mode 100644 index 0000000..7ff4a18 --- /dev/null +++ b/backend/src/establishment/payment/routes.py @@ -0,0 +1,24 @@ +from flask import abort, redirect, url_for +from flask_login import current_user, login_required +from src import db, LOGGER +from src.establishment.payment import bp +from src.establishment.payment.forms import NewPaymentForm +from src.models import Establishment, Payment +from src.utils.routes_utils import render_custom_template as render_template + + +@bp.route('/', methods=['GET', 'POST']) +@login_required +def insert_payment(establishment_id: int): + establishment = Establishment.query.get(int(establishment_id)) + if current_user.is_anonymous or current_user.id != establishment.owner: + abort(403) + form = NewPaymentForm.new(establishment_id=establishment_id) + if form.validate_on_submit(): + new_payment = Payment(token = form.token.data, + date = form.date.data, + amount = form.amount.data) + db.session.add(new_payment) + db.session.commit() + return redirect(url_for("main.index")) + return render_template('establishment/payment/new_payment.html', form=form) \ No newline at end of file diff --git a/backend/src/item/new/forms.py b/backend/src/item/new/forms.py index a2c59e8..e3ff3e8 100644 --- a/backend/src/item/new/forms.py +++ b/backend/src/item/new/forms.py @@ -1,5 +1,4 @@ -from src.models.brand import Brand -from src.models.category import Category +from src.models import Brand, Category from flask_wtf import FlaskForm from wtforms import DateField, FloatField, IntegerField, SelectField, SelectMultipleField, StringField, SubmitField from wtforms.validators import DataRequired, Optional diff --git a/backend/src/models/bought.py b/backend/src/models/bought.py index b58f431..e2b2c2a 100644 --- a/backend/src/models/bought.py +++ b/backend/src/models/bought.py @@ -5,7 +5,6 @@ class Bought(db.Model): item = db.Column(db.ForeignKey('item.id'), primary_key=True, server_onupdate=db.FetchedValue()) date = db.Column(db.Date, primary_key=True) amount = db.Column(db.SmallInteger, nullable=False) - registered = db.Column(db.Boolean, nullable=False, server_default=str(False)) def __repr__(self) -> str: return f"" \ No newline at end of file diff --git a/backend/src/models/payment.py b/backend/src/models/payment.py index c7fe333..8f2ad6c 100644 --- a/backend/src/models/payment.py +++ b/backend/src/models/payment.py @@ -1,7 +1,7 @@ from src import db class Payment(db.Model): - id = db.Column(db.BigInteger, primary_key=True) + id = db.Column(db.BigInteger, primary_key=True, autoincrement=True) token = db.Column(db.ForeignKey('login_token.token'), primary_key=True, server_onupdate=db.FetchedValue()) date = db.Column(db.Date, nullable=False, server_default=db.func.now()) amount = db.Column(db.BigInteger, nullable=False, server_default=str(0)) diff --git a/backend/src/templates/establishment/overview/overview.html b/backend/src/templates/establishment/overview/overview.html index 5f8a909..2b8bb84 100644 --- a/backend/src/templates/establishment/overview/overview.html +++ b/backend/src/templates/establishment/overview/overview.html @@ -4,8 +4,8 @@ {% if establishment %} {% if current_user.id == establishment.owner %} {% endif %} {% endif %} diff --git a/backend/src/templates/establishment/payment/new_payment.html b/backend/src/templates/establishment/payment/new_payment.html new file mode 100644 index 0000000..0b5dc0a --- /dev/null +++ b/backend/src/templates/establishment/payment/new_payment.html @@ -0,0 +1,6 @@ +{% extends "base.html" %} +{% import 'bootstrap/wtf.html' as wtf %} + +{% block app_content %} + {% include 'establishment/payment/new_payment_form.html' %} +{% endblock %} \ No newline at end of file diff --git a/backend/src/templates/establishment/payment/new_payment_form.html b/backend/src/templates/establishment/payment/new_payment_form.html new file mode 100644 index 0000000..9350664 --- /dev/null +++ b/backend/src/templates/establishment/payment/new_payment_form.html @@ -0,0 +1,8 @@ +{% from 'utils/form/_render_field.html' import render_field %} +
+ {{ form.hidden_tag() }} + {{ render_field(form.token) }} + {{ render_field(form.date) }} + {{ render_field(form.amount) }} + {{ form.submit }} +
\ No newline at end of file diff --git a/boot.sh b/boot.sh index 4da83cf..72cbde2 100644 --- a/boot.sh +++ b/boot.sh @@ -1,6 +1,8 @@ #!/bin/bash +echo "Activating venv" source venv/bin/activate cd backend +echo "Upgrading database" for i in {0..5} do flask db upgrade 2be4d1ae5493-1 diff --git a/frontend/src/index.html b/frontend/src/index.html index 3af61ec..d439d52 100644 --- a/frontend/src/index.html +++ b/frontend/src/index.html @@ -8,6 +8,11 @@ - + + Start + + + + diff --git a/requirements.txt b/requirements.txt index c2dd8e6bd77fd947b225e8624475f7350cebfb53..34875a7e692d64f5e3d9e0add971f8d26e4e47d4 100644 GIT binary patch delta 172 zcmX@Yd4p?$1iK-F0fQcc@kCi$Rx=>OXk)Y}qqs9eK0^^hF@r4-8UsZ^N`MMC$1_f4 zbkAi-1WRTxfLJ*|n9ooSS8B*$3D&^Nz{OAiluu^J29oIvnGAVA5@ete*hs_4@0s)& l%_hq;&lD^M%2t5o48azeO3d9MJ7zH^1E&w!S OG?Q%vF99%