minor: display payments on overview

Payments are now displayed at the bottom of the lists.
Also, receipts can now be uploaded without necessarily
providing an image of the original.
This commit is contained in:
Lunaresk 2024-02-18 17:37:06 +01:00
parent 7ae57ae3a4
commit b57dbba5d6
11 changed files with 67 additions and 18 deletions

View File

@ -4,7 +4,7 @@ from src import db
class Payment(db.Model): class Payment(db.Model):
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True) id = db.Column(db.BigInteger, primary_key=True, autoincrement=True)
token = db.Column(db.ForeignKey('login_token.token'), token = db.Column(db.ForeignKey('login_token.token'),
primary_key=True, server_onupdate=db.FetchedValue()) 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))

View File

@ -38,6 +38,7 @@ def get_report_from_user(establishment_id):
result_list = [] result_list = []
# LOGGER.debug(result_list) # LOGGER.debug(result_list)
if request.content_type == "application/json": if request.content_type == "application/json":
LOGGER.debug("Returning JSON")
return jsonify(result_list) return jsonify(result_list)
else: else:
return render_template("establishment/overview/overview.html", results=result_list, establishment=Establishment.query.get(int(establishment_id))) return render_template("establishment/overview/overview.html", results=result_list, establishment=Establishment.query.get(int(establishment_id)))

View File

@ -138,9 +138,11 @@ def sum_entries(grouped_result_list, login_token_dates):
result_user['sum'] -= entry_people_per_date.get('sum')/len(entry_people_per_date.get('people')) result_user['sum'] -= entry_people_per_date.get('sum')/len(entry_people_per_date.get('people'))
def calculate_payments(grouped_result_list): def calculate_payments(grouped_result_list):
LOGGER.debug("Calculating Payments")
for result_user in grouped_result_list: for result_user in grouped_result_list:
payments:list[Payment] = Payment.query.filter_by(token=result_user.get('id')).all() payments:list[Payment] = Payment.query.filter_by(token=result_user.get('id')).order_by(Payment.date).all()
if payments: if payments:
LOGGER.debug(f"Payments found for user {result_user.get('id')}")
result_user['payments'] = [{"date": x.date, "amount": x.amount} for x in payments] result_user['payments'] = [{"date": x.date, "amount": x.amount} for x in payments]
paymentsum = sum([x.amount for x in payments]) paymentsum = sum([x.amount for x in payments])
LOGGER.debug(f"Adding payments of a total of {paymentsum} to {result_user.get('id')}") LOGGER.debug(f"Adding payments of a total of {paymentsum} to {result_user.get('id')}")

View File

@ -1,7 +1,16 @@
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from flask_wtf.file import FileAllowed, FileField, FileRequired from flask_wtf.file import FileAllowed, FileField, FileRequired
from wtforms import SubmitField from wtforms import DateField, SelectField, SubmitField
from models import Establishment
class UploadReceiptForm(FlaskForm): class UploadReceiptForm(FlaskForm):
pdfReceipt = FileField("PDF", validators=[FileRequired(), FileAllowed(["pdf"], "Invalid Format, must be .pdf")]) user = SelectField("User", choices=[], render_kw={"class": "form-control"})
date = DateField("Insert Date", render_kw={"class": "form-control"})
pdfReceipt = FileField("PDF", validators=[FileAllowed(["pdf"], "Invalid Format, must be .pdf")])
submit = SubmitField("Submit", render_kw={"class": "btn btn-primary mt-3"}) submit = SubmitField("Submit", render_kw={"class": "btn btn-primary mt-3"})
@classmethod
def new(cls, establishment):
form = cls()
form.user.choices = [(None, "")]+[(t.token, t.User.email) for t in Establishment.query.get(establishment).LoginToken.order_by("user").all()]
return form

View File

@ -18,19 +18,29 @@ def upload_receipt(establishment: int):
if current_user.is_anonymous: if current_user.is_anonymous:
abort(403) abort(403)
if LoginToken.query.filter_by(establishment=establishment, user=current_user.id).first(): if LoginToken.query.filter_by(establishment=establishment, user=current_user.id).first():
form = UploadReceiptForm() form = UploadReceiptForm.new(establishment)
LOGGER.debug(form.pdfReceipt.data) LOGGER.debug(form.pdfReceipt.data)
if form.validate_on_submit(): if form.validate_on_submit():
pdfReceipt = form.pdfReceipt.data pdfReceipt = form.pdfReceipt.data
pdfReceipt.save(f"{PDFDir}/temp.pdf") receipt_date = form.date.data
with open(f"{PDFDir}/temp.pdf") as doc: bonid = None
receipt = PDFReceipt(doc) if form.user.data:
dbReceipt = Receipt(bonid = receipt.id, date = receipt.date, from_user = form.user.data
from_user = LoginToken.query.filter_by(establishment=establishment, user=current_user.id).first().token) else:
from_user = LoginToken.query.filter_by(establishment=establishment, user=current_user.id).first_or_404().token
if pdfReceipt:
pdfReceipt.save(f"{PDFDir}/temp.pdf")
with open(f"{PDFDir}/temp.pdf") as doc:
receipt = PDFReceipt(doc)
bonid = receipt.id
if receipt.date:
receipt_date = receipt.date
dbReceipt = Receipt(date = receipt_date, from_user = from_user, bonid = bonid)
db.session.add(dbReceipt) db.session.add(dbReceipt)
db.session.commit() db.session.commit()
rename(f"{PDFDir}/temp.pdf", f"{PDFDir}{secure_filename(f'{dbReceipt.id}.pdf')}") if pdfReceipt:
LOGGER.debug(receipt.text) rename(f"{PDFDir}/temp.pdf", f"{PDFDir}{secure_filename(f'{dbReceipt.id}.pdf')}")
LOGGER.debug(receipt.text)
return redirect(url_for("receipts.check_items.confirm_receipt_items", receipt_id = dbReceipt.id)) return redirect(url_for("receipts.check_items.confirm_receipt_items", receipt_id = dbReceipt.id))
else: else:
LOGGER.debug(form.errors) LOGGER.debug(form.errors)

View File

@ -56,5 +56,8 @@ class PDFReceipt:
return (intReceiptNumber, date, items) return (intReceiptNumber, date, items)
def getPDFReceiptFromFile(strPDFFile: str, parser: str = "edeka"): def getPDFReceiptFromFile(strPDFFile: str, parser: str = "edeka"):
with open(strPDFFile) as doc: try:
return PDFReceipt(doc, parser) with open(strPDFFile) as doc:
return PDFReceipt(doc, parser)
except FileNotFoundError as e:
return PDFReceipt(None)

View File

@ -1,6 +1,7 @@
from datetime import date from datetime import date
from flask import render_template from flask import render_template
from flask_login import current_user from flask_login import current_user
from src import LOGGER
def get_base_infos(): def get_base_infos():
@ -15,4 +16,5 @@ def get_base_infos():
return infos return infos
def render_custom_template(*args, **kwargs): def render_custom_template(*args, **kwargs):
LOGGER.debug("Rendering template")
return render_template(*args, **kwargs, **get_base_infos()) return render_template(*args, **kwargs, **get_base_infos())

View File

@ -1,10 +1,13 @@
{% extends "base.html" %} {% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %} {% import 'bootstrap/wtf.html' as wtf %}
{% from 'utils/form/_render_field.html' import render_field %}
{% block app_content %} {% block app_content %}
<form action="" method="post" novalidate enctype="multipart/form-data"> <form action="" method="post" novalidate enctype="multipart/form-data">
{{ form.hidden_tag() }} {{ render_field(form.hidden_tag) }}
{{ wtf.form_field(form.pdfReceipt, class=form.pdfReceipt.render_kw["class"] or "form-control") }} {{ render_field(form.user) }}
{{ wtf.form_field(form.submit, class=form.submit.render_kw["class"] or "btn btn-primary mt-3") }} {{ render_field(form.date) }}
{{ render_field(form.pdfReceipt) }}
{{ render_field(form.submit) }}
</form> </form>
{% endblock %} {% endblock %}

View File

@ -1,12 +1,18 @@
{% from 'utils/form/_render_radio_button.html' import render_field as render_radio %} {% from 'utils/form/_render_radio_button.html' import render_field as render_radio %}
{% from 'utils/form/_render_generic_field.html' import render_field as render_generic %} {% from 'utils/form/_render_generic_field.html' import render_field as render_generic %}
{% from 'utils/form/_render_hidden_field.html' import render_field as render_hidden %} {% from 'utils/form/_render_hidden_field.html' import render_field as render_hidden %}
{% from 'utils/form/_render_submit_field.html' import render_field as render_submit %}
{% from 'utils/form/_render_file_field.html' import render_field as render_file %}
{% macro render_field(field) %} {% macro render_field(field) %}
{% if field.__class__.__name__ == "RadioField" %} {% if field.__class__.__name__ == "RadioField" %}
{{ render_radio(field) }} {{ render_radio(field) }}
{% elif field.__class__.__name__ == "HiddenField" %} {% elif field.__class__.__name__ == "HiddenField" %}
{{ render_hidden(field) }} {{ render_hidden(field) }}
{% elif field.__class__.__name__ == "SubmitField" %}
{{ render_submit(field) }}
{% elif field.__class__.__name__ == "FileField" %}
{{ render_file(field) }}
{% else %} {% else %}
{{ render_generic(field)}} {{ render_generic(field)}}
{% endif %} {% endif %}

View File

@ -0,0 +1,7 @@
{% macro render_field(field) %}
<div class="form-group">
File upload<br>
{{ field(**kwargs)|safe }}
{% include "utils/form/_render_field_errors.html" %}
</div>
{% endmacro %}

View File

@ -0,0 +1,6 @@
{% macro render_field(field) %}
<div class="form-group">
{{ field(**kwargs)|safe }}
{% include "utils/form/_render_field_errors.html" %}
</div>
{% endmacro %}