drobne poprawki
This commit is contained in:
135
app.py
135
app.py
@@ -109,7 +109,6 @@ SESSION_COOKIE_SECURE = app.config.get("SESSION_COOKIE_SECURE")
|
||||
|
||||
app.config["COMPRESS_ALGORITHM"] = ["zstd", "br", "gzip", "deflate"]
|
||||
app.config["PERMANENT_SESSION_LIFETIME"] = timedelta(minutes=SESSION_TIMEOUT_MINUTES)
|
||||
# app.config["SESSION_COOKIE_SECURE"] = True if app.config.get("SESSION_COOKIE_SECURE") is True else False
|
||||
|
||||
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1)
|
||||
DEBUG_MODE = app.config.get("DEBUG_MODE", False)
|
||||
@@ -135,7 +134,7 @@ login_manager.login_view = "login"
|
||||
|
||||
# flask-session
|
||||
app.config["SESSION_TYPE"] = "sqlalchemy"
|
||||
app.config["SESSION_SQLALCHEMY"] = db # instancja SQLAlchemy
|
||||
app.config["SESSION_SQLALCHEMY"] = db
|
||||
Session(app)
|
||||
|
||||
|
||||
@@ -162,7 +161,6 @@ class User(UserMixin, db.Model):
|
||||
password_hash = db.Column(db.String(512), nullable=False)
|
||||
is_admin = db.Column(db.Boolean, default=False)
|
||||
|
||||
|
||||
# Tabela pośrednia
|
||||
shopping_list_category = db.Table(
|
||||
"shopping_list_category",
|
||||
@@ -280,19 +278,14 @@ def check_password(stored_hash, password_input):
|
||||
|
||||
|
||||
def set_authorized_cookie(response):
|
||||
|
||||
secure_flag = app.config["SESSION_COOKIE_SECURE"] # wartość z config.py
|
||||
secure_flag = app.config["SESSION_COOKIE_SECURE"]
|
||||
max_age = app.config.get("AUTH_COOKIE_MAX_AGE", 86400)
|
||||
print("ENV SESSION_COOKIE_SECURE =", os.environ.get("SESSION_COOKIE_SECURE"))
|
||||
print("CONFIG SESSION_COOKIE_SECURE =", app.config["SESSION_COOKIE_SECURE"])
|
||||
response.set_cookie(
|
||||
"authorized",
|
||||
AUTHORIZED_COOKIE_VALUE,
|
||||
max_age=max_age,
|
||||
secure=secure_flag,
|
||||
httponly=True,
|
||||
samesite="Lax",
|
||||
path="/",
|
||||
httponly=True
|
||||
)
|
||||
return response
|
||||
|
||||
@@ -327,14 +320,11 @@ with app.app_context():
|
||||
)
|
||||
db.session.commit()
|
||||
|
||||
# --- Predefiniowane kategorie ---
|
||||
default_categories = app.config["DEFAULT_CATEGORIES"]
|
||||
|
||||
existing_names = {
|
||||
c.name for c in Category.query.filter(Category.name.isnot(None)).all()
|
||||
}
|
||||
|
||||
# ignorujemy wielkość liter przy porównaniu
|
||||
existing_names_lower = {name.lower() for name in existing_names}
|
||||
|
||||
missing = [
|
||||
@@ -352,12 +342,8 @@ with app.app_context():
|
||||
@static_bp.route("/static/js/<path:filename>")
|
||||
def serve_js(filename):
|
||||
response = send_from_directory("static/js", filename)
|
||||
# response.cache_control.no_cache = True
|
||||
# response.cache_control.no_store = True
|
||||
# response.cache_control.must_revalidate = True
|
||||
response.headers["Cache-Control"] = app.config["JS_CACHE_CONTROL"]
|
||||
response.headers.pop("Content-Disposition", None)
|
||||
# response.headers.pop("Etag", None)
|
||||
return response
|
||||
|
||||
|
||||
@@ -366,7 +352,6 @@ def serve_css(filename):
|
||||
response = send_from_directory("static/css", filename)
|
||||
response.headers["Cache-Control"] = app.config["CSS_CACHE_CONTROL"]
|
||||
response.headers.pop("Content-Disposition", None)
|
||||
# response.headers.pop("Etag", None)
|
||||
return response
|
||||
|
||||
|
||||
@@ -375,7 +360,6 @@ def serve_js_lib(filename):
|
||||
response = send_from_directory("static/lib/js", filename)
|
||||
response.headers["Cache-Control"] = app.config["LIB_JS_CACHE_CONTROL"]
|
||||
response.headers.pop("Content-Disposition", None)
|
||||
# response.headers.pop("Etag", None)
|
||||
return response
|
||||
|
||||
|
||||
@@ -384,10 +368,8 @@ def serve_css_lib(filename):
|
||||
response = send_from_directory("static/lib/css", filename)
|
||||
response.headers["Cache-Control"] = app.config["LIB_CSS_CACHE_CONTROL"]
|
||||
response.headers.pop("Content-Disposition", None)
|
||||
# response.headers.pop("Etag", None)
|
||||
return response
|
||||
|
||||
|
||||
app.register_blueprint(static_bp)
|
||||
|
||||
|
||||
@@ -481,10 +463,9 @@ def save_resized_image(file, path):
|
||||
raise ValueError("Nieprawidłowy plik graficzny")
|
||||
|
||||
try:
|
||||
# Automatyczna rotacja według EXIF (np. zdjęcia z telefonu)
|
||||
image = ImageOps.exif_transpose(image)
|
||||
except Exception:
|
||||
pass # ignorujemy, jeśli EXIF jest uszkodzony lub brak
|
||||
pass
|
||||
|
||||
try:
|
||||
image.thumbnail((2000, 2000))
|
||||
@@ -542,7 +523,7 @@ def delete_receipts_for_list(list_id):
|
||||
print(f"Nie udało się usunąć pliku {filename}: {e}")
|
||||
|
||||
|
||||
def _receipt_error(message):
|
||||
def receipt_error(message):
|
||||
if request.is_json or request.headers.get("X-Requested-With") == "XMLHttpRequest":
|
||||
return jsonify({"success": False, "error": message}), 400
|
||||
flash(message, "danger")
|
||||
@@ -637,7 +618,7 @@ def get_total_expenses_grouped_by_list_created_at(
|
||||
lists_query = lists_query.filter(ShoppingList.owner_id == user_id)
|
||||
|
||||
if category_id:
|
||||
if str(category_id) == "none": # Bez kategorii
|
||||
if str(category_id) == "none":
|
||||
lists_query = lists_query.filter(~ShoppingList.categories.any())
|
||||
else:
|
||||
try:
|
||||
@@ -649,7 +630,6 @@ def get_total_expenses_grouped_by_list_created_at(
|
||||
shopping_list_category.c.shopping_list_id == ShoppingList.id,
|
||||
).filter(shopping_list_category.c.category_id == cat_id_int)
|
||||
|
||||
# Obsługa nowych zakresów
|
||||
today = datetime.now(timezone.utc).date()
|
||||
|
||||
if range_type == "last30days":
|
||||
@@ -770,15 +750,12 @@ def get_admin_expense_summary():
|
||||
)
|
||||
return {"total": total, "year": year_total, "month": month_total}
|
||||
|
||||
# baza wspólna
|
||||
base = db.session.query(func.sum(Expense.amount)).join(
|
||||
ShoppingList, ShoppingList.id == Expense.list_id
|
||||
)
|
||||
|
||||
# wszystkie listy
|
||||
all_lists = calc_sum(base)
|
||||
|
||||
# aktywne listy
|
||||
active_lists = calc_sum(
|
||||
base.filter(
|
||||
ShoppingList.is_archived == False,
|
||||
@@ -790,10 +767,8 @@ def get_admin_expense_summary():
|
||||
)
|
||||
)
|
||||
|
||||
# archiwalne
|
||||
archived_lists = calc_sum(base.filter(ShoppingList.is_archived == True))
|
||||
|
||||
# wygasłe
|
||||
expired_lists = calc_sum(
|
||||
base.filter(
|
||||
ShoppingList.is_archived == False,
|
||||
@@ -811,19 +786,6 @@ def get_admin_expense_summary():
|
||||
}
|
||||
|
||||
|
||||
""" def category_to_color(name):
|
||||
hash_val = int(hashlib.md5(name.encode("utf-8")).hexdigest(), 16)
|
||||
r = (hash_val & 0xFF0000) >> 16
|
||||
g = (hash_val & 0x00FF00) >> 8
|
||||
b = hash_val & 0x0000FF
|
||||
# Rozjaśnienie (pastel)
|
||||
r = (r + 255) // 2
|
||||
g = (g + 255) // 2
|
||||
b = (b + 255) // 2
|
||||
return f"#{r:02x}{g:02x}{b:02x}"
|
||||
"""
|
||||
|
||||
|
||||
def category_to_color(name):
|
||||
hash_val = int(hashlib.md5(name.encode("utf-8")).hexdigest(), 16)
|
||||
hue = (hash_val % 360) / 360.0
|
||||
@@ -847,7 +809,7 @@ def get_total_expenses_grouped_by_category(
|
||||
lists_query = lists_query.filter(ShoppingList.owner_id == user_id)
|
||||
|
||||
if category_id:
|
||||
if str(category_id) == "none": # Bez kategorii
|
||||
if str(category_id) == "none":
|
||||
lists_query = lists_query.filter(~ShoppingList.categories.any())
|
||||
else:
|
||||
try:
|
||||
@@ -899,13 +861,11 @@ def get_total_expenses_grouped_by_category(
|
||||
|
||||
all_labels.add(key)
|
||||
|
||||
# Specjalna obsługa dla filtra "Bez kategorii"
|
||||
if str(category_id) == "none":
|
||||
if not l.categories:
|
||||
data_map[key]["Bez kategorii"] += total_expense
|
||||
continue # 🔹 Pomijamy dalsze dodawanie innych kategorii
|
||||
continue
|
||||
|
||||
# Standardowa logika
|
||||
if not l.categories:
|
||||
data_map[key]["Bez kategorii"] += total_expense
|
||||
else:
|
||||
@@ -943,10 +903,10 @@ def get_total_expenses_grouped_by_category(
|
||||
|
||||
def preprocess_image_for_tesseract(image):
|
||||
image = ImageOps.autocontrast(image)
|
||||
image = image.point(lambda x: 0 if x < 150 else 255) # mocniejsza binarizacja
|
||||
image = image.point(lambda x: 0 if x < 150 else 255)
|
||||
image = image.resize(
|
||||
(image.width * 2, image.height * 2), Image.BICUBIC
|
||||
) # większe powiększenie
|
||||
)
|
||||
return image
|
||||
|
||||
|
||||
@@ -992,7 +952,6 @@ def extract_total_tesseract(image):
|
||||
except:
|
||||
continue
|
||||
|
||||
# Tylko w liniach priorytetowych: sprawdzamy spaced fallback
|
||||
if is_priority:
|
||||
spaced = re.findall(r"\d{1,4}\s\d{2}", line)
|
||||
for match in spaced:
|
||||
@@ -1003,7 +962,6 @@ def extract_total_tesseract(image):
|
||||
except:
|
||||
continue
|
||||
|
||||
# Preferujemy linie priorytetowe
|
||||
preferred = [(val, line) for val, line, is_pref in candidates if is_pref]
|
||||
|
||||
if preferred:
|
||||
@@ -1016,7 +974,6 @@ def extract_total_tesseract(image):
|
||||
if best_val < 99999:
|
||||
return round(best_val, 2), lines
|
||||
|
||||
# Fallback: największy font + bold
|
||||
data = pytesseract.image_to_data(
|
||||
image, lang="pol", config="--psm 4", output_type=Output.DICT
|
||||
)
|
||||
@@ -1037,7 +994,6 @@ def extract_total_tesseract(image):
|
||||
continue
|
||||
|
||||
if font_candidates:
|
||||
# Preferuj najwyższy font z sensownym confidence
|
||||
best = max(font_candidates, key=lambda x: (x[1], x[2]))
|
||||
return round(best[0], 2), lines
|
||||
|
||||
@@ -1077,10 +1033,8 @@ def attempts_remaining(ip):
|
||||
|
||||
|
||||
def get_client_ip():
|
||||
# Obsługuje: X-Forwarded-For, X-Real-IP, fallback na remote_addr
|
||||
for header in ["X-Forwarded-For", "X-Real-IP"]:
|
||||
if header in request.headers:
|
||||
# Pierwszy IP w X-Forwarded-For jest najczęściej klientem
|
||||
ip = request.headers[header].split(",")[0].strip()
|
||||
if ip:
|
||||
return ip
|
||||
@@ -1089,7 +1043,6 @@ def get_client_ip():
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(user_id):
|
||||
# return User.query.get(int(user_id))
|
||||
return db.session.get(User, int(user_id))
|
||||
|
||||
|
||||
@@ -1112,8 +1065,6 @@ def inject_is_blocked():
|
||||
@app.before_request
|
||||
def require_system_password():
|
||||
endpoint = request.endpoint
|
||||
|
||||
# Wyjątki: lib js/css zawsze przepuszczamy
|
||||
if endpoint in ("static_bp.serve_js_lib", "static_bp.serve_css_lib"):
|
||||
return
|
||||
|
||||
@@ -1133,7 +1084,6 @@ def require_system_password():
|
||||
and endpoint != "favicon"
|
||||
):
|
||||
|
||||
# Dla serve_js przepuszczamy tylko toasts.js
|
||||
if endpoint == "static_bp.serve_js":
|
||||
requested_file = request.view_args.get("filename", "")
|
||||
if requested_file == "toasts.js":
|
||||
@@ -1142,7 +1092,6 @@ def require_system_password():
|
||||
return redirect(url_for("system_auth", next=request.url))
|
||||
return
|
||||
|
||||
# Blokujemy pozostałe static_bp
|
||||
if endpoint.startswith("static_bp."):
|
||||
return
|
||||
|
||||
@@ -1274,7 +1223,6 @@ def main_page():
|
||||
)
|
||||
return query
|
||||
|
||||
# Pobranie list
|
||||
if current_user.is_authenticated:
|
||||
user_lists = (
|
||||
date_filter(
|
||||
@@ -1327,7 +1275,6 @@ def main_page():
|
||||
.all()
|
||||
)
|
||||
|
||||
# Dodajemy statystyki
|
||||
all_lists = user_lists + public_lists + archived_lists
|
||||
all_ids = [l.id for l in all_lists]
|
||||
|
||||
@@ -1425,8 +1372,6 @@ def system_auth():
|
||||
@app.route("/toggle_archive_list/<int:list_id>")
|
||||
@login_required
|
||||
def toggle_archive_list(list_id):
|
||||
# l = ShoppingList.query.get_or_404(list_id)
|
||||
|
||||
l = db.session.get(ShoppingList, list_id)
|
||||
if l is None:
|
||||
abort(404)
|
||||
@@ -1466,8 +1411,9 @@ def edit_my_list(list_id):
|
||||
categories = Category.query.order_by(Category.name.asc()).all()
|
||||
selected_categories_ids = {c.id for c in l.categories}
|
||||
|
||||
next_page = request.args.get("next") or request.referrer
|
||||
|
||||
if request.method == "POST":
|
||||
# Obsługa zmiany miesiąca utworzenia listy
|
||||
move_to_month = request.form.get("move_to_month")
|
||||
if move_to_month:
|
||||
try:
|
||||
@@ -1479,12 +1425,11 @@ def edit_my_list(list_id):
|
||||
f"Zmieniono datę utworzenia listy na {new_created_at.strftime('%Y-%m-%d')}",
|
||||
"success",
|
||||
)
|
||||
return redirect(url_for("edit_my_list", list_id=list_id))
|
||||
return redirect(next_page or url_for("main_page"))
|
||||
except ValueError:
|
||||
flash("Nieprawidłowy format miesiąca", "danger")
|
||||
return redirect(url_for("edit_my_list", list_id=list_id))
|
||||
return redirect(next_page or url_for("main_page"))
|
||||
|
||||
# Pozostała aktualizacja pól
|
||||
new_title = request.form.get("title", "").strip()
|
||||
is_public = "is_public" in request.form
|
||||
is_temporary = "is_temporary" in request.form
|
||||
@@ -1494,7 +1439,7 @@ def edit_my_list(list_id):
|
||||
|
||||
if not new_title:
|
||||
flash("Podaj poprawny tytuł", "danger")
|
||||
return redirect(url_for("edit_my_list", list_id=list_id))
|
||||
return redirect(next_page or url_for("main_page"))
|
||||
|
||||
l.title = new_title
|
||||
l.is_public = is_public
|
||||
@@ -1508,16 +1453,14 @@ def edit_my_list(list_id):
|
||||
l.expires_at = expires_dt.replace(tzinfo=timezone.utc)
|
||||
except ValueError:
|
||||
flash("Błędna data lub godzina wygasania", "danger")
|
||||
return redirect(url_for("edit_my_list", list_id=list_id))
|
||||
return redirect(next_page or url_for("main_page"))
|
||||
else:
|
||||
l.expires_at = None
|
||||
|
||||
# Obsługa wyboru kategorii
|
||||
update_list_categories_from_form(l, request.form)
|
||||
|
||||
db.session.commit()
|
||||
flash("Zaktualizowano dane listy", "success")
|
||||
return redirect(url_for("main_page"))
|
||||
return redirect(next_page or url_for("main_page"))
|
||||
|
||||
return render_template(
|
||||
"edit_my_list.html",
|
||||
@@ -1551,8 +1494,6 @@ def delete_user_list(list_id):
|
||||
@app.route("/toggle_visibility/<int:list_id>", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def toggle_visibility(list_id):
|
||||
# l = ShoppingList.query.get_or_404(list_id)
|
||||
|
||||
l = db.session.get(ShoppingList, list_id)
|
||||
if l is None:
|
||||
abort(404)
|
||||
@@ -1609,7 +1550,6 @@ def create_list():
|
||||
is_temporary = request.form.get("temporary") == "1"
|
||||
token = generate_share_token(8)
|
||||
|
||||
# expires_at = datetime.utcnow() + timedelta(days=7) if is_temporary else None
|
||||
expires_at = (
|
||||
datetime.now(timezone.utc) + timedelta(days=7) if is_temporary else None
|
||||
)
|
||||
@@ -1751,7 +1691,6 @@ def expenses():
|
||||
)
|
||||
totals_map = {t.list_id: t.total_expense or 0 for t in totals}
|
||||
|
||||
# Tabela wydatków
|
||||
expense_table = [
|
||||
{
|
||||
"title": e.shopping_list.title if e.shopping_list else "Nieznana",
|
||||
@@ -1761,7 +1700,6 @@ def expenses():
|
||||
for e in expenses
|
||||
]
|
||||
|
||||
# Lista z danymi i kategoriami (dla JS)
|
||||
lists_data = [
|
||||
{
|
||||
"id": l.id,
|
||||
@@ -1943,15 +1881,12 @@ def upload_receipt(list_id):
|
||||
|
||||
l = db.session.get(ShoppingList, list_id)
|
||||
|
||||
# if l is None or l.owner_id != current_user.id:
|
||||
# return _receipt_error("Nie masz uprawnień do tej listy.")
|
||||
|
||||
if "receipt" not in request.files:
|
||||
return _receipt_error("Brak pliku")
|
||||
return receipt_error("Brak pliku")
|
||||
|
||||
file = request.files["receipt"]
|
||||
if file.filename == "":
|
||||
return _receipt_error("Nie wybrano pliku")
|
||||
return receipt_error("Nie wybrano pliku")
|
||||
|
||||
if file and allowed_file(file.filename):
|
||||
file_bytes = file.read()
|
||||
@@ -1960,7 +1895,7 @@ def upload_receipt(list_id):
|
||||
|
||||
existing = Receipt.query.filter_by(file_hash=file_hash).first()
|
||||
if existing:
|
||||
return _receipt_error("Taki plik już istnieje")
|
||||
return receipt_error("Taki plik już istnieje")
|
||||
|
||||
now = datetime.now(timezone.utc)
|
||||
timestamp = now.strftime("%Y%m%d_%H%M")
|
||||
@@ -1971,7 +1906,7 @@ def upload_receipt(list_id):
|
||||
try:
|
||||
save_resized_image(file, file_path)
|
||||
except ValueError as e:
|
||||
return _receipt_error(str(e))
|
||||
return receipt_error(str(e))
|
||||
|
||||
filesize = os.path.getsize(file_path)
|
||||
uploaded_at = datetime.now(timezone.utc)
|
||||
@@ -1997,7 +1932,7 @@ def upload_receipt(list_id):
|
||||
flash("Wgrano paragon", "success")
|
||||
return redirect(request.referrer or url_for("main_page"))
|
||||
|
||||
return _receipt_error("Niedozwolony format pliku")
|
||||
return receipt_error("Niedozwolony format pliku")
|
||||
|
||||
|
||||
@app.route("/uploads/<filename>")
|
||||
@@ -2217,7 +2152,6 @@ def admin_panel():
|
||||
}
|
||||
)
|
||||
|
||||
# Top produkty
|
||||
top_products = (
|
||||
db.session.query(Item.name, func.count(Item.id).label("count"))
|
||||
.filter(Item.purchased.is_(True))
|
||||
@@ -2228,13 +2162,9 @@ def admin_panel():
|
||||
)
|
||||
|
||||
purchased_items_count = Item.query.filter_by(purchased=True).count()
|
||||
|
||||
# Nowe podsumowanie wydatków
|
||||
expense_summary = get_admin_expense_summary()
|
||||
|
||||
# Statystyki systemowe
|
||||
process = psutil.Process(os.getpid())
|
||||
app_mem = process.memory_info().rss // (1024 * 1024) # MB
|
||||
app_mem = process.memory_info().rss // (1024 * 1024)
|
||||
|
||||
db_engine = db.engine
|
||||
db_info = {
|
||||
@@ -2369,8 +2299,6 @@ def admin_receipts(id):
|
||||
try:
|
||||
if id == "all":
|
||||
receipts = Receipt.query.order_by(Receipt.uploaded_at.desc()).all()
|
||||
|
||||
# Szukaj sierot tylko dla "all"
|
||||
upload_folder = app.config["UPLOAD_FOLDER"]
|
||||
all_db_filenames = set(r.filename for r in receipts)
|
||||
files_on_disk = set(os.listdir(upload_folder))
|
||||
@@ -2388,7 +2316,7 @@ def admin_receipts(id):
|
||||
.order_by(Receipt.uploaded_at.desc())
|
||||
.all()
|
||||
)
|
||||
stale_files = [] # brak sierot
|
||||
stale_files = []
|
||||
except ValueError:
|
||||
flash("Nieprawidłowe ID listy.", "danger")
|
||||
return redirect(url_for("admin_panel"))
|
||||
@@ -2438,7 +2366,6 @@ def delete_receipt(receipt_id=None, filename=None):
|
||||
flash("Plik już nie istnieje.", "warning")
|
||||
return redirect(url_for("admin_receipts", id="all"))
|
||||
|
||||
# tryb z rekordem w bazie
|
||||
try:
|
||||
delete_receipt_by_id(receipt_id)
|
||||
flash("Paragon usunięty", "success")
|
||||
@@ -2508,7 +2435,6 @@ def delete_selected_lists():
|
||||
ids = request.form.getlist("list_ids")
|
||||
for list_id in ids:
|
||||
|
||||
# lst = ShoppingList.query.get(int(list_id))
|
||||
lst = db.session.get(ShoppingList, int(list_id))
|
||||
|
||||
if lst:
|
||||
@@ -2525,7 +2451,6 @@ def delete_selected_lists():
|
||||
@login_required
|
||||
@admin_required
|
||||
def edit_list(list_id):
|
||||
# Pobieramy listę z powiązanymi danymi jednym zapytaniem
|
||||
l = db.session.get(
|
||||
ShoppingList,
|
||||
list_id,
|
||||
@@ -2541,7 +2466,6 @@ def edit_list(list_id):
|
||||
if l is None:
|
||||
abort(404)
|
||||
|
||||
# Suma wydatków z listy
|
||||
total_expense = get_total_expense_for_list(l.id)
|
||||
|
||||
categories = Category.query.order_by(Category.name.asc()).all()
|
||||
@@ -2615,7 +2539,6 @@ def edit_list(list_id):
|
||||
)
|
||||
return redirect(url_for("edit_list", list_id=list_id))
|
||||
|
||||
# aktualizacja kategorii
|
||||
update_list_categories_from_form(l, request.form)
|
||||
|
||||
db.session.add(l)
|
||||
@@ -2718,7 +2641,6 @@ def edit_list(list_id):
|
||||
flash("Nie znaleziono produktu", "danger")
|
||||
return redirect(url_for("edit_list", list_id=list_id))
|
||||
|
||||
# Dane do widoku
|
||||
users = User.query.all()
|
||||
items = l.items
|
||||
receipts = l.receipts
|
||||
@@ -2740,11 +2662,9 @@ def edit_list(list_id):
|
||||
@admin_required
|
||||
def list_products():
|
||||
items = Item.query.order_by(Item.id.desc()).all()
|
||||
# users = User.query.all()
|
||||
users = db.session.query(User).all()
|
||||
users_dict = {user.id: user.username for user in users}
|
||||
|
||||
# Stabilne sortowanie sugestii
|
||||
suggestions = SuggestedProduct.query.order_by(SuggestedProduct.name.asc()).all()
|
||||
suggestions_dict = {s.name.lower(): s for s in suggestions}
|
||||
|
||||
@@ -2930,7 +2850,6 @@ def handle_delete_item(data):
|
||||
|
||||
@socketio.on("edit_item")
|
||||
def handle_edit_item(data):
|
||||
# item = Item.query.get(data["item_id"])
|
||||
item = db.session.get(Item, data["item_id"])
|
||||
|
||||
new_name = data["new_name"]
|
||||
@@ -2968,7 +2887,6 @@ def handle_join(data):
|
||||
active_users[room] = set()
|
||||
active_users[room].add(username)
|
||||
|
||||
# shopping_list = ShoppingList.query.get(int(data["room"]))
|
||||
shopping_list = db.session.get(ShoppingList, int(data["room"]))
|
||||
|
||||
list_title = shopping_list.title if shopping_list else "Twoja lista"
|
||||
@@ -3083,12 +3001,10 @@ def handle_add_item(data):
|
||||
|
||||
@socketio.on("check_item")
|
||||
def handle_check_item(data):
|
||||
# item = Item.query.get(data["item_id"])
|
||||
item = db.session.get(Item, data["item_id"])
|
||||
|
||||
if item:
|
||||
item.purchased = True
|
||||
# item.purchased_at = datetime.utcnow()
|
||||
item.purchased_at = datetime.now(UTC)
|
||||
|
||||
db.session.commit()
|
||||
@@ -3109,7 +3025,6 @@ def handle_check_item(data):
|
||||
|
||||
@socketio.on("uncheck_item")
|
||||
def handle_uncheck_item(data):
|
||||
# item = Item.query.get(data["item_id"])
|
||||
item = db.session.get(Item, data["item_id"])
|
||||
|
||||
if item:
|
||||
@@ -3208,7 +3123,6 @@ def handle_add_expense(data):
|
||||
|
||||
@socketio.on("mark_not_purchased")
|
||||
def handle_mark_not_purchased(data):
|
||||
# item = Item.query.get(data["item_id"])
|
||||
item = db.session.get(Item, data["item_id"])
|
||||
|
||||
reason = data.get("reason", "")
|
||||
@@ -3225,7 +3139,6 @@ def handle_mark_not_purchased(data):
|
||||
|
||||
@socketio.on("unmark_not_purchased")
|
||||
def handle_unmark_not_purchased(data):
|
||||
# item = Item.query.get(data["item_id"])
|
||||
item = db.session.get(Item, data["item_id"])
|
||||
|
||||
if item:
|
||||
|
Reference in New Issue
Block a user