Compare commits
	
		
			No commits in common. "37179e65a168d57a7c8e00e2d7c5884126b3cdd0" and "38c827d0d8de2ed037412e0fac263cf6b307334a" have entirely different histories.
		
	
	
		
			37179e65a1
			...
			38c827d0d8
		
	
		
| @ -1 +0,0 @@ | |||||||
| - [ ] Fix date handling in entry |  | ||||||
| @ -3,13 +3,7 @@ import json | |||||||
| 
 | 
 | ||||||
| from flask import Flask, render_template | from flask import Flask, render_template | ||||||
| 
 | 
 | ||||||
| from . import ( | from . import db, inventory, location, template_utils | ||||||
|     db, |  | ||||||
|     entry, |  | ||||||
|     inventory, |  | ||||||
|     location, |  | ||||||
|     template_utils |  | ||||||
| ) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def create_app(): | def create_app(): | ||||||
| @ -27,7 +21,6 @@ def create_app(): | |||||||
| 
 | 
 | ||||||
|     app.register_blueprint(location.bp) |     app.register_blueprint(location.bp) | ||||||
|     app.register_blueprint(inventory.bp) |     app.register_blueprint(inventory.bp) | ||||||
|     app.register_blueprint(entry.bp) |  | ||||||
|     @app.route("/") |     @app.route("/") | ||||||
|     def index(): |     def index(): | ||||||
|         return render_template("index.html") |         return render_template("index.html") | ||||||
|  | |||||||
| @ -1,6 +0,0 @@ | |||||||
| SELECT |  | ||||||
|   group_id, |  | ||||||
|   group_name |  | ||||||
| FROM garfield.inventory_item_groups |  | ||||||
| ORDER BY |  | ||||||
|   group_name ASC |  | ||||||
| @ -1,11 +0,0 @@ | |||||||
| SELECT |  | ||||||
|   * |  | ||||||
| FROM garfield.inventory_map |  | ||||||
| LEFT JOIN garfield.snacks USING (snack_id) |  | ||||||
| LEFT JOIN garfield.snacks_available USING (snack_id) |  | ||||||
| LEFT JOIN garfield.tax_groups USING (tax_group_id) |  | ||||||
| LEFT JOIN garfield.locations USING (location_id) |  | ||||||
| WHERE snack_barcode = %(snack_barcode)s |  | ||||||
| ORDER BY |  | ||||||
|   snack_available DESC, |  | ||||||
|   snack_timestamp DESC |  | ||||||
| @ -1,59 +0,0 @@ | |||||||
| import datetime |  | ||||||
| import zoneinfo |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| from flask import Blueprint, redirect, render_template, request, session |  | ||||||
| 
 |  | ||||||
| from . import db |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| bp = Blueprint("entry", __name__, url_prefix="/entry") |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| @bp.get("/") |  | ||||||
| def index(): |  | ||||||
|     return render_template("entry/index.html") |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| @bp.route("/edit-item-data", methods=["GET", "POST"]) |  | ||||||
| def edit_item_data(): |  | ||||||
|     if "entry" not in session: |  | ||||||
|         session["entry"] = dict() |  | ||||||
| 
 |  | ||||||
|     if request.method == "POST": |  | ||||||
|         session["entry"] = { |  | ||||||
|             "item_bought": datetime.datetime.strptime(request.form.get("item_bought"), "%Y-%m-%d"), |  | ||||||
|             "item_barcode": request.form.get("item_barcode"), |  | ||||||
|             "item_name": request.form.get("item_name"), |  | ||||||
|             "item_group_id": int(request.form.get("item_group")), |  | ||||||
|             "item_net_unit_price": float(request.form.get("item_net_unit_price")), |  | ||||||
|             "item_tax_group_id": int(request.form.get("item_tax_group")), |  | ||||||
|             "item_amount": int(request.form.get("item_amount")), |  | ||||||
|             "item_location_id": int(request.form.get("item_location")) |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         return redirect("/entry/select-snack-entry") |  | ||||||
| 
 |  | ||||||
|     groups = db.run_query("get_groups.sql").fetchall() |  | ||||||
|     locations = db.run_query("get_locations.sql").fetchall() |  | ||||||
| 
 |  | ||||||
|     return render_template("entry/edit-item-data.html", **{ |  | ||||||
|         "groups": groups, |  | ||||||
|         "locations": locations, |  | ||||||
|         "entry": session["entry"] |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| @bp.route("/select-snack-entry", methods=["GET", "POST"]) |  | ||||||
| def edit_snack_data(): |  | ||||||
|     if "entry" not in session: |  | ||||||
|         return redirect("/entry/edit-item-data") |  | ||||||
| 
 |  | ||||||
|     snacks = db.run_query("get_snacks_by_barcode.sql", { |  | ||||||
|         "snack_barcode": session["entry"]["item_barcode"] |  | ||||||
|     }).fetchall() |  | ||||||
| 
 |  | ||||||
|     return render_template("entry/select-snack-entry.html", **{ |  | ||||||
|         "entry": session["entry"], |  | ||||||
|         "snacks": snacks |  | ||||||
|     }) |  | ||||||
| @ -1,6 +1,3 @@ | |||||||
| import datetime |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def format_currency(x): | def format_currency(x): | ||||||
|     # It would be nicer to format this using the German locale |     # It would be nicer to format this using the German locale | ||||||
|     # Too lazy to bother tho. |     # Too lazy to bother tho. | ||||||
| @ -13,18 +10,3 @@ def format_date(d): | |||||||
| 
 | 
 | ||||||
| def format_bool(x): | def format_bool(x): | ||||||
|     return "✅" if x else "❌" |     return "✅" if x else "❌" | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def now(): |  | ||||||
|     return datetime.datetime.now() |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def get_garfield_price(net_unit_price, tax_group_id): |  | ||||||
|     if tax_group_id == 1: |  | ||||||
|         tax_factor = 1.19 |  | ||||||
|     elif tax_group_id == 2: |  | ||||||
|         tax_factor = 1.07 |  | ||||||
|     else: |  | ||||||
|         raise Error("Unknown tax group ID") |  | ||||||
| 
 |  | ||||||
|     return net_unit_price * tax_factor + 0.01 |  | ||||||
|  | |||||||
| @ -62,13 +62,6 @@ | |||||||
|           font-size: 8px; |           font-size: 8px; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|       .form-input > label { |  | ||||||
|         font-size: .8em; |  | ||||||
|       } |  | ||||||
|       .form-input > input:not([type=radio]), |  | ||||||
|       .form-input > select { |  | ||||||
|         display: block; |  | ||||||
|       } |  | ||||||
|     </style> |     </style> | ||||||
|   </head> |   </head> | ||||||
|   <body> |   <body> | ||||||
| @ -78,7 +71,6 @@ | |||||||
|         <ul> |         <ul> | ||||||
|           <li {{ "class=current-page" if request.path == "/" else "" }}><a href="/">Home</a></li> |           <li {{ "class=current-page" if request.path == "/" else "" }}><a href="/">Home</a></li> | ||||||
|           <li {{ "class=current-page" if request.path.startswith("/inventory") else "" }}><a href="/inventory">Inventar</a></li> |           <li {{ "class=current-page" if request.path.startswith("/inventory") else "" }}><a href="/inventory">Inventar</a></li> | ||||||
|           <li {{ "class=current-page" if request.path.startswith("/entry") else "" }}><a href="/entry">Eintragen</a></li> |  | ||||||
|           <li {{ "class=current-page" if request.path.startswith("/location") else "" }}> |           <li {{ "class=current-page" if request.path.startswith("/location") else "" }}> | ||||||
|             <a href="/location"> |             <a href="/location"> | ||||||
|             {% if "location" not in session %} |             {% if "location" not in session %} | ||||||
|  | |||||||
| @ -1,56 +0,0 @@ | |||||||
| {% extends "base.html" %} |  | ||||||
| 
 |  | ||||||
| {% block content %} |  | ||||||
| <pre>{{ entry }}</pre> |  | ||||||
| 
 |  | ||||||
| <fieldset> |  | ||||||
|   <legend>Neuer Inventareintrag</legend> |  | ||||||
| 
 |  | ||||||
|   <form method="POST" action="/entry/edit-item-data"> |  | ||||||
|     <div class="form-input"> |  | ||||||
|       <label for="item_bought">Kaufdatum</label> |  | ||||||
|       <input name="item_bought" id="item_bought" type="date" value="{{ (entry.item_bought or now()).strftime('%Y-%m-%d') }}"> |  | ||||||
|     </div> |  | ||||||
|     <div class="form-input"> |  | ||||||
|       <label for="item_barcode">Barcode</label> |  | ||||||
|       <input name="item_barcode" id="item_barcode" type="text" value="{{ entry.item_barcode }}" placeholder="Barcode"> |  | ||||||
|     </div> |  | ||||||
|     <div class="form-input"> |  | ||||||
|       <label for="item_name">Artikel</label> |  | ||||||
|       <input name="item_name" id="item_name" type="text" value="{{ entry.item_name }}" placeholder="Artikel"> |  | ||||||
|     </div> |  | ||||||
|     <div class="form-input"> |  | ||||||
|       <label for="item_group">Gruppe</label> |  | ||||||
|       <select name="item_group" id="item_group"> |  | ||||||
|         {% for group in groups %} |  | ||||||
|         <option value="{{ group.group_id }}"{% if entry.item_group_id == group.group_id %} selected{% endif %}>{{ group.group_name }} ({{ group.group_id }})</option> |  | ||||||
|         {% endfor %} |  | ||||||
|       </select> |  | ||||||
|     </div> |  | ||||||
|     <div class="form-input"> |  | ||||||
|       <label for="item_net_unit_price">Stückpreis (Netto) in €</label> |  | ||||||
|       <input name="item_net_unit_price" id="item_net_unit_price" type="number" step="0.01" value="{{ entry.item_net_unit_price }}" placeholder="Stückpreis (Netto) in €"> |  | ||||||
|     </div> |  | ||||||
|     <div class="form-input"> |  | ||||||
|       <input name="item_tax_group" id="item_tax_group_1" type="radio" value="1"{% if entry.item_tax_group_id == 1 %} selected{% endif %}> |  | ||||||
|       <label for="item_tax_group_1">Volle Umsatzsteuer (19%)</label> |  | ||||||
| 
 |  | ||||||
|       <input name="item_tax_group" id="item_tax_group_2" type="radio" value="2"{% if entry.item_tax_group_id == 2 %} selected{% endif %}> |  | ||||||
|       <label for="item_tax_group_2">Ermäßigte Umsatzsteuer (7%)</label> |  | ||||||
|     </div> |  | ||||||
|     <div class="form-input"> |  | ||||||
|       <label for="item_amount">Anzahl</label> |  | ||||||
|       <input name="item_amount" id="item_amount" type="number" value="{{ entry.item_amount }}" placeholder="Anzahl"> |  | ||||||
|     </div> |  | ||||||
|     <div class="form-input"> |  | ||||||
|       <label for="item_group">Raum</label> |  | ||||||
|       <select name="item_location" id="item_location"> |  | ||||||
|         {% for location in locations %} |  | ||||||
|         <option value="{{ location.location_id }}"{% if entry.item_location_id == location.location_id or ("item_location" not in entry and (session.location.location_id == location.location_id)) %} selected{% endif %}>{{ location.location_name }} ({{ location.location_id }})</option> |  | ||||||
|         {% endfor %} |  | ||||||
|       </select> |  | ||||||
|     </div> |  | ||||||
|     <button>Weiter zu den Snackeinträgen</button> |  | ||||||
|   </form> |  | ||||||
| </fieldset> |  | ||||||
| {% endblock %} |  | ||||||
| @ -1,5 +0,0 @@ | |||||||
| {% extends "base.html" %} |  | ||||||
| 
 |  | ||||||
| {% block content %} |  | ||||||
| <a href="/entry/edit-item-data">Neuer Eintrag</a> |  | ||||||
| {% endblock %} |  | ||||||
| @ -1,83 +0,0 @@ | |||||||
| {% extends "base.html" %} |  | ||||||
| 
 |  | ||||||
| {% block content %} |  | ||||||
| <pre>{{ entry }}</pre> |  | ||||||
| 
 |  | ||||||
| <fieldset> |  | ||||||
|   <legend>Neuer Inventareintrag</legend> |  | ||||||
|   <table> |  | ||||||
|     <tr> |  | ||||||
|       <th class="--align-left">ID</th> |  | ||||||
|       <td>{{ entry.item_id }}</td> |  | ||||||
|     </tr> |  | ||||||
|     <tr> |  | ||||||
|       <th class="--align-left">Barcode</th> |  | ||||||
|       <td><code>{{ entry.item_barcode }}</code></td> |  | ||||||
|     </tr> |  | ||||||
|     <tr> |  | ||||||
|       <th class="--align-left">Name</th> |  | ||||||
|       <td>{{ entry.item_name }}</td> |  | ||||||
|     </tr> |  | ||||||
|     <tr> |  | ||||||
|       <th class="--align-left">Einkaufspreis (Netto)</th> |  | ||||||
|       <td>{{ format_currency(entry.item_net_unit_price) }}</td> |  | ||||||
|     </tr> |  | ||||||
|     <tr> |  | ||||||
|       <th class="--align-left">Empfohlener Garfield-Verkaufspreis</th> |  | ||||||
|       <td>{{ format_currency(get_garfield_price(entry.item_net_unit_price, entry.item_tax_group_id)) }}</td> |  | ||||||
|     </tr> |  | ||||||
|     <tr> |  | ||||||
|       <th class="--align-left">Kaufdatum</th> |  | ||||||
|       <td>{{ format_date(entry.item_bought) }}</td> |  | ||||||
|     </tr> |  | ||||||
|     <tr> |  | ||||||
|       <th class="--align-left">Gruppe</th> |  | ||||||
|       <td>{{ entry.item_group_name }} ({{ entry.item_group_id }})</td> |  | ||||||
|     </tr> |  | ||||||
|     <tr> |  | ||||||
|       <th class="--align-left">Anzahl</th> |  | ||||||
|       <td>{{ entry.item_amount }}</td> |  | ||||||
|     </tr> |  | ||||||
|     <tr> |  | ||||||
|       <th class="--align-left">Raum</th> |  | ||||||
|       <td>{{ entry.item_location_name }} ({{ entry.item_location_id }})</td> |  | ||||||
|     </tr> |  | ||||||
|   </table> |  | ||||||
| </fieldset> |  | ||||||
| 
 |  | ||||||
| <fieldset> |  | ||||||
|   <legend>Snackeinträge mit Barcode <code>{{ entry.item_barcode }}</code></legend> |  | ||||||
| 
 |  | ||||||
|   <table> |  | ||||||
|     <tr> |  | ||||||
|       <th>ID</th> |  | ||||||
|       <th>Barcode</th> |  | ||||||
|       <th>Name</th> |  | ||||||
|       <th>Verkaufspreis (Brutto)</th> |  | ||||||
|       <th>Eintragedatum</th> |  | ||||||
|       <th>Steuersatz</th> |  | ||||||
|       <th>Raum</th> |  | ||||||
|       <th>Aktiv?</th> |  | ||||||
|       <th>Aktionen</th> |  | ||||||
|     </tr> |  | ||||||
|     {% for snack in snacks %} |  | ||||||
|     <tr> |  | ||||||
|       <td>{{ snack.snack_id }}</td> |  | ||||||
|       <td><code>{{ snack.snack_barcode }}</code></td> |  | ||||||
|       <td>{{ snack.snack_name }}</td> |  | ||||||
|       <td class="--align-right">{{ format_currency(snack.snack_price) }}</td> |  | ||||||
|       <td>{{ format_date(snack.snack_timestamp) }}</td> |  | ||||||
|       <td>{{ snack.description }} ({{ snack.tax_group_id }})</td> |  | ||||||
|       <td>{{ snack.location_name }} ({{ snack.location_id }})</td> |  | ||||||
|       <td>{{ format_bool(snack.snack_available) }}</td> |  | ||||||
|       <td> |  | ||||||
|         <form method="POST" action="/entry/select-snack-entry"> |  | ||||||
|           <input type="hidden" name="snack_id" value="{{ snack.snack_id }}"> |  | ||||||
|           <button>Snackeintrag übernehmen</button> |  | ||||||
|         </form> |  | ||||||
|       </td> |  | ||||||
|     </tr> |  | ||||||
|     {% endfor %} |  | ||||||
|   </table> |  | ||||||
| </fieldset> |  | ||||||
| {% endblock %} |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user