minor: add payment

Admins can now add payments for their users.
This commit is contained in:
Lunaresk 2023-05-28 09:07:54 +02:00
parent 597725f46c
commit b21284f640
17 changed files with 121 additions and 15 deletions

1
.gitignore vendored
View File

@ -348,3 +348,4 @@ test.*
.flaskenv*
!.env.project
!.env.vault
*.ps1

View File

@ -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 ###

View File

@ -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),

View File

@ -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.list import bp as bp_list
bp.register_blueprint(bp_list)
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)
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.payment import bp as bp_payment
bp.register_blueprint(bp_payment)

View File

@ -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('/<establishment_id>', methods=['GET'])
@bp.route('/<int:establishment_id>', 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:

View File

@ -0,0 +1,5 @@
from flask import Blueprint
bp = Blueprint('payment', __name__, url_prefix='/payment')
from src.establishment.payment import routes

View File

@ -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

View File

@ -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('/<int:establishment_id>', 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)

View File

@ -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

View File

@ -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"<Bought Object>"

View File

@ -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))

View File

@ -4,8 +4,8 @@
{% if establishment %}
{% if current_user.id == establishment.owner %}
<button type="button" class="btn btn-outline-dark px-2" data-bs-toggle="button" autocomplete="off"
onclick="window.location.href='{{ url_for('establishment.overview.get_report_from_user', establishment_id=establishment.id) }}'">
Abrechnung
onclick="window.location.href='{{ url_for('establishment.payment.insert_payment', establishment_id=establishment.id) }}'">
Zahlung hinzufügen
</button>
{% endif %}
{% endif %}

View File

@ -0,0 +1,6 @@
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
{% include 'establishment/payment/new_payment_form.html' %}
{% endblock %}

View File

@ -0,0 +1,8 @@
{% from 'utils/form/_render_field.html' import render_field %}
<form action="" method="post">
{{ form.hidden_tag() }}
{{ render_field(form.token) }}
{{ render_field(form.date) }}
{{ render_field(form.amount) }}
{{ form.submit }}
</form>

View File

@ -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

View File

@ -8,6 +8,11 @@
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<mat-sidenav-container>
<mat-sidenav>Start</mat-sidenav>
<mat-sidenav-content>
<app-root></app-root>
</mat-sidenav-content>
</mat-sidenav-container>
</body>
</html>

Binary file not shown.