Compare commits
2 Commits
470cd32745
...
ae89f55446
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ae89f55446 | ||
![]() |
3ebb364322 |
263
add_products.py
263
add_products.py
@@ -4,66 +4,249 @@ from app import db, SuggestedProduct, app
|
||||
|
||||
CATEGORIES = {
|
||||
"Przyprawa": [
|
||||
"przyprawa", "pieprz", "sól", "bazylia", "oregano", "papryka", "majeranek", "czosnek",
|
||||
"tymianek", "rozmaryn", "kolendra", "curry", "imbir", "goździki", "chili", "koper",
|
||||
"kminek", "liść laurowy", "ziele angielskie", "kurkuma", "musztarda", "chrzan"
|
||||
"przyprawa",
|
||||
"pieprz",
|
||||
"sól",
|
||||
"bazylia",
|
||||
"oregano",
|
||||
"papryka",
|
||||
"majeranek",
|
||||
"czosnek",
|
||||
"tymianek",
|
||||
"rozmaryn",
|
||||
"kolendra",
|
||||
"curry",
|
||||
"imbir",
|
||||
"goździki",
|
||||
"chili",
|
||||
"koper",
|
||||
"kminek",
|
||||
"liść laurowy",
|
||||
"ziele angielskie",
|
||||
"kurkuma",
|
||||
"musztarda",
|
||||
"chrzan",
|
||||
],
|
||||
"Mięso": [
|
||||
"kurczak", "piersi z kurczaka", "udka z kurczaka", "wołowina", "mielona wołowina",
|
||||
"wieprzowina", "schab", "łopatka", "szynka", "boczek", "indyk", "filet z indyka",
|
||||
"gulasz", "pasztet", "karkówka", "żeberka", "kiełbasa", "parówki", "salami", "kabanos"
|
||||
"kurczak",
|
||||
"piersi z kurczaka",
|
||||
"udka z kurczaka",
|
||||
"wołowina",
|
||||
"mielona wołowina",
|
||||
"wieprzowina",
|
||||
"schab",
|
||||
"łopatka",
|
||||
"szynka",
|
||||
"boczek",
|
||||
"indyk",
|
||||
"filet z indyka",
|
||||
"gulasz",
|
||||
"pasztet",
|
||||
"karkówka",
|
||||
"żeberka",
|
||||
"kiełbasa",
|
||||
"parówki",
|
||||
"salami",
|
||||
"kabanos",
|
||||
],
|
||||
"Ryba i owoce morza": [
|
||||
"łosoś", "dorsz", "mintaj", "makrela", "pstrąg", "karp", "śledź", "tuńczyk",
|
||||
"morszczuk", "sardynka", "szproty", "anchois", "tilapia", "sandacz", "halibut",
|
||||
"sum", "flądra", "ostrobok", "paluszki rybne", "konserwa rybna"
|
||||
"łosoś",
|
||||
"dorsz",
|
||||
"mintaj",
|
||||
"makrela",
|
||||
"pstrąg",
|
||||
"karp",
|
||||
"śledź",
|
||||
"tuńczyk",
|
||||
"morszczuk",
|
||||
"sardynka",
|
||||
"szproty",
|
||||
"anchois",
|
||||
"tilapia",
|
||||
"sandacz",
|
||||
"halibut",
|
||||
"sum",
|
||||
"flądra",
|
||||
"ostrobok",
|
||||
"paluszki rybne",
|
||||
"konserwa rybna",
|
||||
],
|
||||
"Nabiał": [
|
||||
"mleko", "jogurt", "ser żółty", "ser biały", "twaróg", "śmietana", "masło",
|
||||
"kefir", "maślanka", "serek wiejski", "serek topiony", "mozzarella", "feta",
|
||||
"parmezan", "gouda", "emmental", "ser pleśniowy", "ser homogenizowany",
|
||||
"serek mascarpone", "ser ricotta"
|
||||
"mleko",
|
||||
"jogurt",
|
||||
"ser żółty",
|
||||
"ser biały",
|
||||
"twaróg",
|
||||
"śmietana",
|
||||
"masło",
|
||||
"kefir",
|
||||
"maślanka",
|
||||
"serek wiejski",
|
||||
"serek topiony",
|
||||
"mozzarella",
|
||||
"feta",
|
||||
"parmezan",
|
||||
"gouda",
|
||||
"emmental",
|
||||
"ser pleśniowy",
|
||||
"ser homogenizowany",
|
||||
"serek mascarpone",
|
||||
"ser ricotta",
|
||||
],
|
||||
"Warzywo": [
|
||||
"pomidor", "ogórek", "marchew", "cebula", "sałata", "papryka", "ziemniak",
|
||||
"kapusta", "brokuł", "kalafior", "cukinia", "bakłażan", "szpinak", "rukola",
|
||||
"seler", "por", "burak", "dynia", "rzodkiewka", "fasola"
|
||||
"pomidor",
|
||||
"ogórek",
|
||||
"marchew",
|
||||
"cebula",
|
||||
"sałata",
|
||||
"papryka",
|
||||
"ziemniak",
|
||||
"kapusta",
|
||||
"brokuł",
|
||||
"kalafior",
|
||||
"cukinia",
|
||||
"bakłażan",
|
||||
"szpinak",
|
||||
"rukola",
|
||||
"seler",
|
||||
"por",
|
||||
"burak",
|
||||
"dynia",
|
||||
"rzodkiewka",
|
||||
"fasola",
|
||||
],
|
||||
"Owoc": [
|
||||
"jabłko", "banan", "gruszka", "truskawka", "winogrono", "malina", "borówka",
|
||||
"czereśnia", "wiśnia", "brzoskwinia", "nektaryna", "śliwka", "ananas",
|
||||
"mango", "kiwi", "cytryna", "limonka", "pomarańcza", "mandarynka", "grejpfrut"
|
||||
"jabłko",
|
||||
"banan",
|
||||
"gruszka",
|
||||
"truskawka",
|
||||
"winogrono",
|
||||
"malina",
|
||||
"borówka",
|
||||
"czereśnia",
|
||||
"wiśnia",
|
||||
"brzoskwinia",
|
||||
"nektaryna",
|
||||
"śliwka",
|
||||
"ananas",
|
||||
"mango",
|
||||
"kiwi",
|
||||
"cytryna",
|
||||
"limonka",
|
||||
"pomarańcza",
|
||||
"mandarynka",
|
||||
"grejpfrut",
|
||||
],
|
||||
"Pieczywo i zboża": [
|
||||
"chleb", "bułka", "bagietka", "kajzerka", "pumpernikiel", "chleb razowy",
|
||||
"chleb żytni", "tost", "grahamka", "croissant", "tortilla", "pizza",
|
||||
"pierogi", "ryż", "makaron", "kasza jaglana", "kasza gryczana", "owsianka",
|
||||
"płatki kukurydziane", "musli"
|
||||
"chleb",
|
||||
"bułka",
|
||||
"bagietka",
|
||||
"kajzerka",
|
||||
"pumpernikiel",
|
||||
"chleb razowy",
|
||||
"chleb żytni",
|
||||
"tost",
|
||||
"grahamka",
|
||||
"croissant",
|
||||
"tortilla",
|
||||
"pizza",
|
||||
"pierogi",
|
||||
"ryż",
|
||||
"makaron",
|
||||
"kasza jaglana",
|
||||
"kasza gryczana",
|
||||
"owsianka",
|
||||
"płatki kukurydziane",
|
||||
"musli",
|
||||
],
|
||||
"Słodycze i przekąski": [
|
||||
"czekolada", "baton", "ciastko", "wafel", "lody", "cukierek", "żelki",
|
||||
"herbatnik", "paluszki", "chipsy", "orzeszki", "popcorn", "krakersy",
|
||||
"ciasto", "muffin", "pączek", "drożdżówka", "babeczka", "piernik", "beza"
|
||||
"czekolada",
|
||||
"baton",
|
||||
"ciastko",
|
||||
"wafel",
|
||||
"lody",
|
||||
"cukierek",
|
||||
"żelki",
|
||||
"herbatnik",
|
||||
"paluszki",
|
||||
"chipsy",
|
||||
"orzeszki",
|
||||
"popcorn",
|
||||
"krakersy",
|
||||
"ciasto",
|
||||
"muffin",
|
||||
"pączek",
|
||||
"drożdżówka",
|
||||
"babeczka",
|
||||
"piernik",
|
||||
"beza",
|
||||
],
|
||||
"Napoje": [
|
||||
"woda", "sok jabłkowy", "sok pomarańczowy", "sok multiwitamina", "cola",
|
||||
"pepsi", "napój gazowany", "kawa", "herbata", "piwo", "wino czerwone",
|
||||
"wino białe", "tonik", "lemoniada", "napój izotoniczny", "kompot",
|
||||
"napój mleczny", "maślanka pitna", "koktajl owocowy", "nektar"
|
||||
"woda",
|
||||
"sok jabłkowy",
|
||||
"sok pomarańczowy",
|
||||
"sok multiwitamina",
|
||||
"cola",
|
||||
"pepsi",
|
||||
"napój gazowany",
|
||||
"kawa",
|
||||
"herbata",
|
||||
"piwo",
|
||||
"wino czerwone",
|
||||
"wino białe",
|
||||
"tonik",
|
||||
"lemoniada",
|
||||
"napój izotoniczny",
|
||||
"kompot",
|
||||
"napój mleczny",
|
||||
"maślanka pitna",
|
||||
"koktajl owocowy",
|
||||
"nektar",
|
||||
],
|
||||
"Tłuszcze i oleje": [
|
||||
"oliwa", "olej rzepakowy", "olej słonecznikowy", "masło klarowane",
|
||||
"margaryna", "smalec", "masło orzechowe", "tłuszcz kokosowy",
|
||||
"olej lniany", "olej z pestek winogron", "olej sezamowy",
|
||||
"olej ryżowy", "olej z awokado", "olej kukurydziany", "olej arachidowy",
|
||||
"olej palmowy", "olej konopny", "olej sojowy", "olej dyniowy", "olej z orzechów włoskich"
|
||||
"oliwa",
|
||||
"olej rzepakowy",
|
||||
"olej słonecznikowy",
|
||||
"masło klarowane",
|
||||
"margaryna",
|
||||
"smalec",
|
||||
"masło orzechowe",
|
||||
"tłuszcz kokosowy",
|
||||
"olej lniany",
|
||||
"olej z pestek winogron",
|
||||
"olej sezamowy",
|
||||
"olej ryżowy",
|
||||
"olej z awokado",
|
||||
"olej kukurydziany",
|
||||
"olej arachidowy",
|
||||
"olej palmowy",
|
||||
"olej konopny",
|
||||
"olej sojowy",
|
||||
"olej dyniowy",
|
||||
"olej z orzechów włoskich",
|
||||
],
|
||||
"Dania gotowe": [
|
||||
"pizza", "hamburger", "hot dog", "zupa", "gulasz", "pierogi ruskie",
|
||||
"pierogi z mięsem", "lasagne", "sałatka warzywna", "kanapka",
|
||||
"wrap", "tortilla", "zapiekanka", "sushi", "falafel", "kebab",
|
||||
"pyzy", "kluski śląskie", "kotlet schabowy", "gołąbki"
|
||||
]
|
||||
"pizza",
|
||||
"hamburger",
|
||||
"hot dog",
|
||||
"zupa",
|
||||
"gulasz",
|
||||
"pierogi ruskie",
|
||||
"pierogi z mięsem",
|
||||
"lasagne",
|
||||
"sałatka warzywna",
|
||||
"kanapka",
|
||||
"wrap",
|
||||
"tortilla",
|
||||
"zapiekanka",
|
||||
"sushi",
|
||||
"falafel",
|
||||
"kebab",
|
||||
"pyzy",
|
||||
"kluski śląskie",
|
||||
"kotlet schabowy",
|
||||
"gołąbki",
|
||||
],
|
||||
}
|
||||
|
||||
produkty = []
|
||||
|
@@ -2,6 +2,7 @@ import os
|
||||
from datetime import datetime
|
||||
from app import db, app, Receipt
|
||||
|
||||
|
||||
def extract_list_id(filename):
|
||||
if filename.startswith("list_"):
|
||||
parts = filename.split("_", 2)
|
||||
@@ -9,6 +10,7 @@ def extract_list_id(filename):
|
||||
return int(parts[1])
|
||||
return None
|
||||
|
||||
|
||||
def migrate_missing_receipts():
|
||||
with app.app_context():
|
||||
folder = app.config["UPLOAD_FOLDER"]
|
||||
@@ -30,7 +32,9 @@ def migrate_missing_receipts():
|
||||
skipped += 1
|
||||
continue
|
||||
|
||||
new_receipt = Receipt(list_id=list_id, filename=file, uploaded_at=datetime.utcnow())
|
||||
new_receipt = Receipt(
|
||||
list_id=list_id, filename=file, uploaded_at=datetime.utcnow()
|
||||
)
|
||||
db.session.add(new_receipt)
|
||||
added += 1
|
||||
print(f"📄 {file} dodany do Receipt (list_id={list_id})")
|
||||
@@ -38,5 +42,6 @@ def migrate_missing_receipts():
|
||||
db.session.commit()
|
||||
print(f"\n✅ Dodano: {added}, pominięto (już były): {skipped}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
migrate_missing_receipts()
|
@@ -46,3 +46,6 @@ CREATE TABLE receipt (
|
||||
uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (list_id) REFERENCES shopping_list(id)
|
||||
);
|
||||
|
||||
ALTER TABLE receipt ADD COLUMN filesize INTEGER;
|
||||
|
||||
|
43
app.py
43
app.py
@@ -48,7 +48,7 @@ from functools import wraps
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(Config)
|
||||
register_heif_opener() # pillow_heif dla HEIC
|
||||
register_heif_opener() # pillow_heif dla HEIC
|
||||
|
||||
ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg", "gif", "webp", "heic"}
|
||||
SQLALCHEMY_ECHO = True
|
||||
@@ -142,13 +142,14 @@ class Expense(db.Model):
|
||||
receipt_filename = db.Column(db.String(255), nullable=True)
|
||||
list = db.relationship("ShoppingList", backref="expenses", lazy=True)
|
||||
|
||||
|
||||
class Receipt(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
list_id = db.Column(db.Integer, db.ForeignKey("shopping_list.id"), nullable=False)
|
||||
filename = db.Column(db.String(255), nullable=False)
|
||||
uploaded_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
shopping_list = db.relationship("ShoppingList", backref="receipts", lazy=True)
|
||||
filesize = db.Column(db.Integer, nullable=True)
|
||||
|
||||
|
||||
with app.app_context():
|
||||
@@ -935,6 +936,8 @@ def upload_receipt(list_id):
|
||||
return redirect(request.referrer) """
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
@app.route("/upload_receipt/<int:list_id>", methods=["POST"])
|
||||
def upload_receipt(list_id):
|
||||
@@ -953,11 +956,22 @@ def upload_receipt(list_id):
|
||||
|
||||
save_resized_image(file, file_path)
|
||||
|
||||
new_receipt = Receipt(list_id=list_id, filename=webp_filename)
|
||||
filesize = os.path.getsize(file_path) if os.path.exists(file_path) else None
|
||||
uploaded_at = datetime.utcnow()
|
||||
|
||||
new_receipt = Receipt(
|
||||
list_id=list_id,
|
||||
filename=webp_filename,
|
||||
filesize=filesize,
|
||||
uploaded_at=uploaded_at,
|
||||
)
|
||||
db.session.add(new_receipt)
|
||||
db.session.commit()
|
||||
|
||||
if request.is_json or request.headers.get("X-Requested-With") == "XMLHttpRequest":
|
||||
if (
|
||||
request.is_json
|
||||
or request.headers.get("X-Requested-With") == "XMLHttpRequest"
|
||||
):
|
||||
url = url_for("uploaded_file", filename=webp_filename)
|
||||
socketio.emit("receipt_added", {"url": url}, to=str(list_id))
|
||||
return jsonify({"success": True, "url": url})
|
||||
@@ -967,13 +981,6 @@ def upload_receipt(list_id):
|
||||
|
||||
return _receipt_error("Niedozwolony format pliku")
|
||||
|
||||
def _receipt_error(message):
|
||||
if request.is_json or request.headers.get("X-Requested-With") == "XMLHttpRequest":
|
||||
return jsonify({"success": False, "message": message}), 400
|
||||
flash(message, "danger")
|
||||
return redirect(request.referrer)
|
||||
|
||||
|
||||
|
||||
@app.route("/uploads/<filename>")
|
||||
def uploaded_file(filename):
|
||||
@@ -1196,8 +1203,6 @@ def delete_user(user_id):
|
||||
return redirect(url_for("list_users"))
|
||||
|
||||
|
||||
import os
|
||||
|
||||
@app.route("/admin/receipts/<id>")
|
||||
@login_required
|
||||
@admin_required
|
||||
@@ -1216,14 +1221,9 @@ def admin_receipts(id):
|
||||
flash("Nieprawidłowe ID listy.", "danger")
|
||||
return redirect(url_for("admin_panel"))
|
||||
|
||||
for r in receipts:
|
||||
path = os.path.join(app.config["UPLOAD_FOLDER"], r.filename)
|
||||
r.filesize = os.path.getsize(path) if os.path.exists(path) else 0
|
||||
|
||||
return render_template("admin/receipts.html", receipts=receipts)
|
||||
|
||||
|
||||
|
||||
@app.route("/admin/delete_receipt/<filename>")
|
||||
@login_required
|
||||
@admin_required
|
||||
@@ -1255,7 +1255,6 @@ def delete_receipt(filename):
|
||||
return redirect(next_url or url_for("admin_receipts", id="all"))
|
||||
|
||||
|
||||
|
||||
@app.route("/admin/delete_selected_lists", methods=["POST"])
|
||||
@login_required
|
||||
@admin_required
|
||||
@@ -1291,7 +1290,11 @@ def edit_list(list_id):
|
||||
db.session.query(Item).filter_by(list_id=list_id).order_by(Item.id.desc()).all()
|
||||
)
|
||||
|
||||
receipts = Receipt.query.filter_by(list_id=list_id).order_by(Receipt.uploaded_at.desc()).all()
|
||||
receipts = (
|
||||
Receipt.query.filter_by(list_id=list_id)
|
||||
.order_by(Receipt.uploaded_at.desc())
|
||||
.all()
|
||||
)
|
||||
|
||||
if request.method == "POST":
|
||||
action = request.form.get("action")
|
||||
|
21
config.py
21
config.py
@@ -1,14 +1,15 @@
|
||||
import os
|
||||
|
||||
|
||||
class Config:
|
||||
SECRET_KEY = os.environ.get('SECRET_KEY', 'D8pceNZ8q%YR7^7F&9wAC2')
|
||||
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL', 'sqlite:///shopping.db')
|
||||
SECRET_KEY = os.environ.get("SECRET_KEY", "D8pceNZ8q%YR7^7F&9wAC2")
|
||||
SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL", "sqlite:///shopping.db")
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
SYSTEM_PASSWORD = os.environ.get('SYSTEM_PASSWORD', 'admin')
|
||||
DEFAULT_ADMIN_USERNAME = os.environ.get('DEFAULT_ADMIN_USERNAME', 'admin')
|
||||
DEFAULT_ADMIN_PASSWORD = os.environ.get('DEFAULT_ADMIN_PASSWORD', 'admin123')
|
||||
UPLOAD_FOLDER = os.environ.get('UPLOAD_FOLDER', 'uploads')
|
||||
AUTHORIZED_COOKIE_VALUE = os.environ.get('AUTHORIZED_COOKIE_VALUE', 'cookievalue')
|
||||
AUTH_COOKIE_MAX_AGE = int(os.environ.get('AUTH_COOKIE_MAX_AGE', 86400))
|
||||
HEALTHCHECK_TOKEN = os.environ.get('HEALTHCHECK_TOKEN', 'alamapsaikota1234')
|
||||
SESSION_TIMEOUT_MINUTES = int(os.environ.get('SESSION_TIMEOUT_MINUTES', 10080))
|
||||
SYSTEM_PASSWORD = os.environ.get("SYSTEM_PASSWORD", "admin")
|
||||
DEFAULT_ADMIN_USERNAME = os.environ.get("DEFAULT_ADMIN_USERNAME", "admin")
|
||||
DEFAULT_ADMIN_PASSWORD = os.environ.get("DEFAULT_ADMIN_PASSWORD", "admin123")
|
||||
UPLOAD_FOLDER = os.environ.get("UPLOAD_FOLDER", "uploads")
|
||||
AUTHORIZED_COOKIE_VALUE = os.environ.get("AUTHORIZED_COOKIE_VALUE", "cookievalue")
|
||||
AUTH_COOKIE_MAX_AGE = int(os.environ.get("AUTH_COOKIE_MAX_AGE", 86400))
|
||||
HEALTHCHECK_TOKEN = os.environ.get("HEALTHCHECK_TOKEN", "alamapsaikota1234")
|
||||
SESSION_TIMEOUT_MINUTES = int(os.environ.get("SESSION_TIMEOUT_MINUTES", 10080))
|
||||
|
@@ -6,6 +6,7 @@ from app import db, app, Receipt
|
||||
ALLOWED_EXTS = ("jpg", "jpeg", "png", "gif", "heic")
|
||||
UPLOAD_FOLDER = None
|
||||
|
||||
|
||||
def convert_to_webp(input_path, output_path):
|
||||
try:
|
||||
image = Image.open(input_path).convert("RGB")
|
||||
@@ -15,6 +16,7 @@ def convert_to_webp(input_path, output_path):
|
||||
print(f"Błąd konwersji {input_path}: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def extract_list_id(filename):
|
||||
if filename.startswith("list_"):
|
||||
parts = filename.split("_", 2)
|
||||
@@ -22,6 +24,7 @@ def extract_list_id(filename):
|
||||
return int(parts[1])
|
||||
return None
|
||||
|
||||
|
||||
def migrate():
|
||||
global UPLOAD_FOLDER
|
||||
with app.app_context():
|
||||
@@ -53,13 +56,19 @@ def migrate():
|
||||
|
||||
if convert_to_webp(src_path, dst_path):
|
||||
os.remove(src_path)
|
||||
r = Receipt.query.filter_by(list_id=list_id, filename=webp_filename).first()
|
||||
r = Receipt.query.filter_by(
|
||||
list_id=list_id, filename=webp_filename
|
||||
).first()
|
||||
if r:
|
||||
print(f"Już istnieje w Receipt: {webp_filename}")
|
||||
existing += 1
|
||||
continue
|
||||
|
||||
new_receipt = Receipt(list_id=list_id, filename=webp_filename, uploaded_at=datetime.utcnow())
|
||||
new_receipt = Receipt(
|
||||
list_id=list_id,
|
||||
filename=webp_filename,
|
||||
uploaded_at=datetime.utcnow(),
|
||||
)
|
||||
db.session.add(new_receipt)
|
||||
created += 1
|
||||
print(f"{file} → {webp_filename} + zapis do Receipt")
|
||||
@@ -69,5 +78,6 @@ def migrate():
|
||||
print(f"Pominięte (webp istniało): {skipped}")
|
||||
print(f"Duplikaty w bazie: {existing}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
migrate()
|
||||
|
@@ -202,13 +202,24 @@
|
||||
</a>
|
||||
<div class="card-body text-center">
|
||||
<p class="small text-truncate mb-1">{{ r.filename }}</p>
|
||||
|
||||
{% if r.filesize and r.filesize >= 1024 * 1024 %}
|
||||
<p class="small mb-1">Rozmiar: {{ (r.filesize / 1024 / 1024) | round(2) }} MB</p>
|
||||
{% elif r.filesize %}
|
||||
<p class="small mb-1">Rozmiar: {{ (r.filesize / 1024) | round(1) }} kB</p>
|
||||
{% else %}
|
||||
<p class="small mb-1 text-muted">Rozmiar nieznany</p>
|
||||
{% endif %}
|
||||
|
||||
<p class="small mb-1">Wgrano: {{ r.uploaded_at.strftime('%Y-%m-%d %H:%M') }}</p>
|
||||
|
||||
<a href="{{ url_for('delete_receipt', filename=r.filename) }}?next={{ url_for('edit_list', list_id=list.id) }}"
|
||||
class="btn btn-sm btn-outline-danger w-100">🗑️ Usuń</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
|
||||
{% if not receipts %}
|
||||
|
@@ -21,15 +21,19 @@
|
||||
<div class="card-body text-center">
|
||||
<p class="small text-truncate mb-1">{{ r.filename }}</p>
|
||||
<p class="small mb-1">Wgrano: {{ r.uploaded_at.strftime('%Y-%m-%d %H:%M') }}</p>
|
||||
{% if r.filesize >= 1024 * 1024 %}
|
||||
{% if r.filesize and r.filesize >= 1024 * 1024 %}
|
||||
<p class="small mb-1">Rozmiar: {{ (r.filesize / 1024 / 1024) | round(2) }} MB</p>
|
||||
{% else %}
|
||||
{% elif r.filesize %}
|
||||
<p class="small mb-1">Rozmiar: {{ (r.filesize / 1024) | round(1) }} kB</p>
|
||||
{% else %}
|
||||
<p class="small mb-1 text-muted">Brak danych o rozmiarze</p>
|
||||
{% endif %}
|
||||
|
||||
<a href="{{ url_for('edit_list', list_id=r.list_id) }}" class="btn btn-sm btn-outline-light w-100 mb-2">✏️
|
||||
Edytuj listę #{{ r.list_id }}</a>
|
||||
<a href="{{ url_for('delete_receipt', filename=r.filename) }}?next={{ request.path }}"
|
||||
<a href="{{ url_for('delete_receipt', filename=r.filename|urlencode) }}?next={{ request.path }}"
|
||||
class="btn btn-sm btn-outline-danger w-100">🗑️ Usuń</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
44
update_missing_image_data.py
Normal file
44
update_missing_image_data.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import os
|
||||
from datetime import datetime
|
||||
from app import app, db, Receipt
|
||||
|
||||
|
||||
def update_missing_receipt_fields():
|
||||
with app.app_context():
|
||||
folder = app.config["UPLOAD_FOLDER"]
|
||||
updated = 0
|
||||
|
||||
receipts = Receipt.query.filter(
|
||||
(Receipt.filesize == None)
|
||||
| (Receipt.filesize == 0)
|
||||
| (Receipt.uploaded_at == None)
|
||||
).all()
|
||||
|
||||
for r in receipts:
|
||||
path = os.path.join(folder, r.filename)
|
||||
if not os.path.exists(path):
|
||||
print(f"Brak pliku: {r.filename}")
|
||||
continue
|
||||
|
||||
changed = False
|
||||
|
||||
if not r.filesize:
|
||||
r.filesize = os.path.getsize(path)
|
||||
changed = True
|
||||
print(f"{r.filename} → filesize: {r.filesize} B")
|
||||
|
||||
if not r.uploaded_at:
|
||||
timestamp = os.path.getmtime(path)
|
||||
r.uploaded_at = datetime.fromtimestamp(timestamp)
|
||||
changed = True
|
||||
print(f"{r.filename} → uploaded_at: {r.uploaded_at}")
|
||||
|
||||
if changed:
|
||||
updated += 1
|
||||
|
||||
db.session.commit()
|
||||
print(f"\nZaktualizowano {updated} rekordów.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
update_missing_receipt_fields()
|
Reference in New Issue
Block a user