minor: add payment
Admins can now add payments for their users.
This commit is contained in:
parent
597725f46c
commit
b21284f640
1
.gitignore
vendored
1
.gitignore
vendored
@ -348,3 +348,4 @@ test.*
|
|||||||
.flaskenv*
|
.flaskenv*
|
||||||
!.env.project
|
!.env.project
|
||||||
!.env.vault
|
!.env.vault
|
||||||
|
*.ps1
|
||||||
@ -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 ###
|
||||||
@ -26,7 +26,7 @@ def upgrade():
|
|||||||
sa.PrimaryKeyConstraint('user', 'establishment')
|
sa.PrimaryKeyConstraint('user', 'establishment')
|
||||||
)
|
)
|
||||||
op.create_table('payment',
|
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('token', sa.String(length=15), nullable=False),
|
||||||
sa.Column('date', sa.Date(), server_default=sa.text('now()'), nullable=False),
|
sa.Column('date', sa.Date(), server_default=sa.text('now()'), nullable=False),
|
||||||
sa.Column('amount', sa.BigInteger(), server_default='0', nullable=False),
|
sa.Column('amount', sa.BigInteger(), server_default='0', nullable=False),
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
|
|
||||||
bp = Blueprint('establishment', __name__, url_prefix='/establishment')
|
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
|
from src.establishment.candidates import bp as bp_candidates
|
||||||
bp.register_blueprint(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)
|
||||||
@ -7,10 +7,10 @@ from src.models import Establishment
|
|||||||
from src.utils import view_utils, database_utils
|
from src.utils import view_utils, database_utils
|
||||||
from src.utils.routes_utils import render_custom_template as render_template
|
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
|
@login_required
|
||||||
def get_report_from_user(establishment_id):
|
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:
|
if current_user.is_anonymous:
|
||||||
abort(403)
|
abort(403)
|
||||||
if 'month' in request.args:
|
if 'month' in request.args:
|
||||||
|
|||||||
5
backend/src/establishment/payment/__init__.py
Normal file
5
backend/src/establishment/payment/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
bp = Blueprint('payment', __name__, url_prefix='/payment')
|
||||||
|
|
||||||
|
from src.establishment.payment import routes
|
||||||
17
backend/src/establishment/payment/forms.py
Normal file
17
backend/src/establishment/payment/forms.py
Normal 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
|
||||||
24
backend/src/establishment/payment/routes.py
Normal file
24
backend/src/establishment/payment/routes.py
Normal 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)
|
||||||
@ -1,5 +1,4 @@
|
|||||||
from src.models.brand import Brand
|
from src.models import Brand, Category
|
||||||
from src.models.category import Category
|
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from wtforms import DateField, FloatField, IntegerField, SelectField, SelectMultipleField, StringField, SubmitField
|
from wtforms import DateField, FloatField, IntegerField, SelectField, SelectMultipleField, StringField, SubmitField
|
||||||
from wtforms.validators import DataRequired, Optional
|
from wtforms.validators import DataRequired, Optional
|
||||||
|
|||||||
@ -5,7 +5,6 @@ class Bought(db.Model):
|
|||||||
item = db.Column(db.ForeignKey('item.id'), primary_key=True, server_onupdate=db.FetchedValue())
|
item = db.Column(db.ForeignKey('item.id'), primary_key=True, server_onupdate=db.FetchedValue())
|
||||||
date = db.Column(db.Date, primary_key=True)
|
date = db.Column(db.Date, primary_key=True)
|
||||||
amount = db.Column(db.SmallInteger, nullable=False)
|
amount = db.Column(db.SmallInteger, nullable=False)
|
||||||
registered = db.Column(db.Boolean, nullable=False, server_default=str(False))
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f"<Bought Object>"
|
return f"<Bought Object>"
|
||||||
@ -1,7 +1,7 @@
|
|||||||
from src import db
|
from src import db
|
||||||
|
|
||||||
class Payment(db.Model):
|
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())
|
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())
|
date = db.Column(db.Date, nullable=False, server_default=db.func.now())
|
||||||
amount = db.Column(db.BigInteger, nullable=False, server_default=str(0))
|
amount = db.Column(db.BigInteger, nullable=False, server_default=str(0))
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
{% if establishment %}
|
{% if establishment %}
|
||||||
{% if current_user.id == establishment.owner %}
|
{% if current_user.id == establishment.owner %}
|
||||||
<button type="button" class="btn btn-outline-dark px-2" data-bs-toggle="button" autocomplete="off"
|
<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) }}'">
|
onclick="window.location.href='{{ url_for('establishment.payment.insert_payment', establishment_id=establishment.id) }}'">
|
||||||
Abrechnung
|
Zahlung hinzufügen
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
{% include 'establishment/payment/new_payment_form.html' %}
|
||||||
|
{% endblock %}
|
||||||
@ -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>
|
||||||
2
boot.sh
2
boot.sh
@ -1,6 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
echo "Activating venv"
|
||||||
source venv/bin/activate
|
source venv/bin/activate
|
||||||
cd backend
|
cd backend
|
||||||
|
echo "Upgrading database"
|
||||||
for i in {0..5}
|
for i in {0..5}
|
||||||
do
|
do
|
||||||
flask db upgrade 2be4d1ae5493-1
|
flask db upgrade 2be4d1ae5493-1
|
||||||
|
|||||||
@ -8,6 +8,11 @@
|
|||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<app-root></app-root>
|
<mat-sidenav-container>
|
||||||
|
<mat-sidenav>Start</mat-sidenav>
|
||||||
|
<mat-sidenav-content>
|
||||||
|
<app-root></app-root>
|
||||||
|
</mat-sidenav-content>
|
||||||
|
</mat-sidenav-container>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user