duzo zmian, funkcji
This commit is contained in:
259
app.py
259
app.py
@ -49,7 +49,7 @@ class ShoppingList(db.Model):
|
||||
expires_at = db.Column(db.DateTime, nullable=True)
|
||||
owner = db.relationship('User', backref='lists', lazy=True)
|
||||
is_archived = db.Column(db.Boolean, default=False)
|
||||
|
||||
is_public = db.Column(db.Boolean, default=True)
|
||||
class Item(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
list_id = db.Column(db.Integer, db.ForeignKey('shopping_list.id'))
|
||||
@ -58,6 +58,7 @@ class Item(db.Model):
|
||||
added_by = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
|
||||
purchased = db.Column(db.Boolean, default=False)
|
||||
purchased_at = db.Column(db.DateTime, nullable=True)
|
||||
quantity = db.Column(db.Integer, default=1)
|
||||
note = db.Column(db.Text, nullable=True)
|
||||
|
||||
class SuggestedProduct(db.Model):
|
||||
@ -166,23 +167,6 @@ def system_auth():
|
||||
flash('Nieprawidłowe hasło do systemu','danger')
|
||||
return render_template('system_auth.html')
|
||||
|
||||
@app.route('/')
|
||||
def index_guest():
|
||||
now = datetime.utcnow()
|
||||
lists = ShoppingList.query.filter(
|
||||
((ShoppingList.expires_at == None) | (ShoppingList.expires_at > now)),
|
||||
ShoppingList.is_archived == False
|
||||
).order_by(ShoppingList.created_at.desc()).all()
|
||||
|
||||
for l in lists:
|
||||
items = Item.query.filter_by(list_id=l.id).all()
|
||||
l.total_count = len(items)
|
||||
l.purchased_count = len([i for i in items if i.purchased])
|
||||
|
||||
expenses = Expense.query.filter_by(list_id=l.id).all()
|
||||
l.total_expense = sum(e.amount for e in expenses)
|
||||
|
||||
return render_template('index.html', lists=lists)
|
||||
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(e):
|
||||
@ -197,6 +181,98 @@ def favicon():
|
||||
'''
|
||||
return svg, 200, {'Content-Type': 'image/svg+xml'}
|
||||
|
||||
@app.route('/')
|
||||
def index_guest():
|
||||
now = datetime.utcnow()
|
||||
|
||||
if current_user.is_authenticated:
|
||||
# Twoje listy
|
||||
user_lists = ShoppingList.query.filter_by(owner_id=current_user.id, is_archived=False).filter(
|
||||
(ShoppingList.expires_at == None) | (ShoppingList.expires_at > now)
|
||||
).order_by(ShoppingList.created_at.desc()).all()
|
||||
|
||||
# Publiczne listy innych użytkowników
|
||||
public_lists = ShoppingList.query.filter(
|
||||
ShoppingList.is_public == True,
|
||||
ShoppingList.owner_id != current_user.id,
|
||||
((ShoppingList.expires_at == None) | (ShoppingList.expires_at > now)),
|
||||
ShoppingList.is_archived == False
|
||||
).order_by(ShoppingList.created_at.desc()).all()
|
||||
else:
|
||||
user_lists = []
|
||||
public_lists = ShoppingList.query.filter(
|
||||
ShoppingList.is_public == True,
|
||||
((ShoppingList.expires_at == None) | (ShoppingList.expires_at > now)),
|
||||
ShoppingList.is_archived == False
|
||||
).order_by(ShoppingList.created_at.desc()).all()
|
||||
|
||||
# Liczenie produktów i wydatków
|
||||
for l in user_lists + public_lists:
|
||||
items = Item.query.filter_by(list_id=l.id).all()
|
||||
l.total_count = len(items)
|
||||
l.purchased_count = len([i for i in items if i.purchased])
|
||||
expenses = Expense.query.filter_by(list_id=l.id).all()
|
||||
l.total_expense = sum(e.amount for e in expenses)
|
||||
|
||||
return render_template("index.html", user_lists=user_lists, public_lists=public_lists)
|
||||
|
||||
@app.route('/archive_my_list/<int:list_id>')
|
||||
@login_required
|
||||
def archive_my_list(list_id):
|
||||
l = ShoppingList.query.get_or_404(list_id)
|
||||
if l.owner_id != current_user.id:
|
||||
flash('Nie masz uprawnień do tej listy', 'danger')
|
||||
return redirect(url_for('index_guest'))
|
||||
l.is_archived = True
|
||||
db.session.commit()
|
||||
flash('Lista została zarchiwizowana', 'success')
|
||||
return redirect(url_for('index_guest'))
|
||||
|
||||
@app.route('/edit_my_list/<int:list_id>', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def edit_my_list(list_id):
|
||||
l = ShoppingList.query.get_or_404(list_id)
|
||||
if l.owner_id != current_user.id:
|
||||
flash('Nie masz uprawnień do tej listy', 'danger')
|
||||
return redirect(url_for('index_guest'))
|
||||
|
||||
if request.method == 'POST':
|
||||
new_title = request.form.get('title')
|
||||
if new_title and new_title.strip():
|
||||
l.title = new_title.strip()
|
||||
db.session.commit()
|
||||
flash('Zaktualizowano tytuł listy', 'success')
|
||||
return redirect(url_for('index_guest'))
|
||||
else:
|
||||
flash('Podaj poprawny tytuł', 'danger')
|
||||
return render_template('edit_my_list.html', list=l)
|
||||
|
||||
@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)
|
||||
if l.owner_id != current_user.id:
|
||||
if request.is_json or request.method == 'POST':
|
||||
return {'error': 'Unauthorized'}, 403
|
||||
flash('Nie masz uprawnień do tej listy', 'danger')
|
||||
return redirect(url_for('index_guest'))
|
||||
|
||||
l.is_public = not l.is_public
|
||||
db.session.commit()
|
||||
|
||||
share_url = f"{request.url_root}share/{l.share_token}"
|
||||
|
||||
if request.is_json or request.method == 'POST':
|
||||
return {'is_public': l.is_public, 'share_url': share_url}
|
||||
|
||||
if l.is_public:
|
||||
flash('Lista została udostępniona publicznie', 'success')
|
||||
else:
|
||||
flash('Lista została ukryta przed gośćmi', 'info')
|
||||
|
||||
return redirect(url_for('index_guest'))
|
||||
|
||||
|
||||
@app.route('/login', methods=['GET', 'POST'])
|
||||
def login():
|
||||
if request.method == 'POST':
|
||||
@ -213,7 +289,7 @@ def login():
|
||||
def logout():
|
||||
logout_user()
|
||||
flash('Wylogowano pomyślnie', 'success')
|
||||
return redirect(url_for('login'))
|
||||
return redirect(url_for('index_guest'))
|
||||
|
||||
@app.route('/create', methods=['POST'])
|
||||
@login_required
|
||||
@ -257,6 +333,11 @@ def view_list(list_id):
|
||||
@app.route('/share/<token>')
|
||||
def share_list(token):
|
||||
shopping_list = ShoppingList.query.filter_by(share_token=token).first_or_404()
|
||||
|
||||
if not shopping_list.is_public:
|
||||
flash('Ta lista nie jest publicznie dostępna', 'danger')
|
||||
return redirect(url_for('index_guest'))
|
||||
|
||||
items = Item.query.filter_by(list_id=shopping_list.id).all()
|
||||
|
||||
receipt_pattern = f"list_{shopping_list.id}"
|
||||
@ -275,7 +356,6 @@ def share_list(token):
|
||||
total_expense=total_expense
|
||||
)
|
||||
|
||||
|
||||
@app.route('/guest-list/<int:list_id>')
|
||||
def guest_list(list_id):
|
||||
shopping_list = ShoppingList.query.get_or_404(list_id)
|
||||
@ -542,51 +622,6 @@ def delete_receipt(filename):
|
||||
flash('Plik nie istnieje', 'danger')
|
||||
return redirect(url_for('admin_receipts'))
|
||||
|
||||
@app.route('/admin/edit_list/<int:list_id>', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def edit_list(list_id):
|
||||
if not current_user.is_admin:
|
||||
return redirect(url_for('index_guest'))
|
||||
|
||||
l = ShoppingList.query.get_or_404(list_id)
|
||||
expenses = Expense.query.filter_by(list_id=list_id).all()
|
||||
total_expense = sum(e.amount for e in expenses)
|
||||
|
||||
if request.method == 'POST':
|
||||
new_title = request.form.get('title')
|
||||
new_amount_str = request.form.get('amount')
|
||||
is_archived = 'archived' in request.form
|
||||
|
||||
if new_title and new_title.strip():
|
||||
l.title = new_title.strip()
|
||||
|
||||
l.is_archived = is_archived
|
||||
|
||||
if new_amount_str:
|
||||
try:
|
||||
new_amount = float(new_amount_str)
|
||||
|
||||
|
||||
if expenses:
|
||||
for expense in expenses:
|
||||
db.session.delete(expense)
|
||||
db.session.commit()
|
||||
|
||||
new_expense = Expense(list_id=list_id, amount=new_amount)
|
||||
db.session.add(new_expense)
|
||||
db.session.commit()
|
||||
flash('Zaktualizowano tytuł, archiwizację i/lub kwotę wydatku', 'success')
|
||||
except ValueError:
|
||||
flash('Niepoprawna kwota', 'danger')
|
||||
return redirect(url_for('edit_list', list_id=list_id))
|
||||
else:
|
||||
db.session.commit()
|
||||
flash('Zaktualizowano tytuł i/lub archiwizację', 'success')
|
||||
|
||||
return redirect(url_for('admin_panel'))
|
||||
|
||||
return render_template('admin/edit_list.html', list=l, total_expense=total_expense)
|
||||
|
||||
|
||||
@app.route('/admin/delete_selected_lists', methods=['POST'])
|
||||
@login_required
|
||||
@ -625,6 +660,66 @@ def delete_all_items():
|
||||
return redirect(url_for('admin_panel'))
|
||||
|
||||
|
||||
@app.route('/admin/edit_list/<int:list_id>', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def edit_list(list_id):
|
||||
if not current_user.is_admin:
|
||||
return redirect(url_for('index_guest'))
|
||||
|
||||
l = ShoppingList.query.get_or_404(list_id)
|
||||
expenses = Expense.query.filter_by(list_id=list_id).all()
|
||||
total_expense = sum(e.amount for e in expenses)
|
||||
|
||||
users = User.query.all()
|
||||
|
||||
if request.method == 'POST':
|
||||
new_title = request.form.get('title')
|
||||
new_amount_str = request.form.get('amount')
|
||||
is_archived = 'archived' in request.form
|
||||
new_owner_id = request.form.get('owner_id')
|
||||
|
||||
if new_title and new_title.strip():
|
||||
l.title = new_title.strip()
|
||||
|
||||
l.is_archived = is_archived
|
||||
|
||||
if new_owner_id:
|
||||
try:
|
||||
new_owner_id_int = int(new_owner_id)
|
||||
if User.query.get(new_owner_id_int):
|
||||
l.owner_id = new_owner_id_int
|
||||
else:
|
||||
flash('Wybrany użytkownik nie istnieje', 'danger')
|
||||
return redirect(url_for('edit_list', list_id=list_id))
|
||||
except ValueError:
|
||||
flash('Niepoprawny ID użytkownika', 'danger')
|
||||
return redirect(url_for('edit_list', list_id=list_id))
|
||||
|
||||
if new_amount_str:
|
||||
try:
|
||||
new_amount = float(new_amount_str)
|
||||
|
||||
if expenses:
|
||||
for expense in expenses:
|
||||
db.session.delete(expense)
|
||||
db.session.commit()
|
||||
|
||||
new_expense = Expense(list_id=list_id, amount=new_amount)
|
||||
db.session.add(new_expense)
|
||||
db.session.commit()
|
||||
flash('Zaktualizowano tytuł, właściciela, archiwizację i/lub kwotę wydatku', 'success')
|
||||
except ValueError:
|
||||
flash('Niepoprawna kwota', 'danger')
|
||||
return redirect(url_for('edit_list', list_id=list_id))
|
||||
else:
|
||||
db.session.commit()
|
||||
flash('Zaktualizowano tytuł, właściciela i/lub archiwizację', 'success')
|
||||
|
||||
return redirect(url_for('admin_panel'))
|
||||
|
||||
return render_template('admin/edit_list.html', list=l, total_expense=total_expense, users=users)
|
||||
|
||||
|
||||
# =========================================================================================
|
||||
# SOCKET.IO
|
||||
# =========================================================================================
|
||||
@ -641,10 +736,28 @@ def handle_delete_item(data):
|
||||
def handle_edit_item(data):
|
||||
item = Item.query.get(data['item_id'])
|
||||
new_name = data['new_name']
|
||||
new_quantity = data.get('new_quantity', item.quantity)
|
||||
|
||||
if item and new_name.strip():
|
||||
item.name = new_name
|
||||
item.name = new_name.strip()
|
||||
|
||||
try:
|
||||
new_quantity = int(new_quantity)
|
||||
if new_quantity < 1:
|
||||
new_quantity = 1
|
||||
except:
|
||||
new_quantity = 1
|
||||
|
||||
item.quantity = new_quantity
|
||||
|
||||
db.session.commit()
|
||||
emit('item_edited', {'item_id': item.id, 'new_name': item.name}, to=str(item.list_id))
|
||||
|
||||
emit('item_edited', {
|
||||
'item_id': item.id,
|
||||
'new_name': item.name,
|
||||
'new_quantity': item.quantity
|
||||
}, to=str(item.list_id))
|
||||
|
||||
|
||||
@socketio.on('join_list')
|
||||
def handle_join(data):
|
||||
@ -657,9 +770,19 @@ def handle_join(data):
|
||||
def handle_add_item(data):
|
||||
list_id = data['list_id']
|
||||
name = data['name']
|
||||
quantity = data.get('quantity', 1)
|
||||
|
||||
try:
|
||||
quantity = int(quantity)
|
||||
if quantity < 1:
|
||||
quantity = 1
|
||||
except:
|
||||
quantity = 1
|
||||
|
||||
new_item = Item(
|
||||
list_id=list_id,
|
||||
name=name,
|
||||
quantity=quantity,
|
||||
added_by=current_user.id if current_user.is_authenticated else None
|
||||
)
|
||||
db.session.add(new_item)
|
||||
@ -669,9 +792,11 @@ def handle_add_item(data):
|
||||
db.session.add(new_suggestion)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
emit('item_added', {
|
||||
'id': new_item.id,
|
||||
'name': new_item.name,
|
||||
'quantity': new_item.quantity,
|
||||
'added_by': current_user.username if current_user.is_authenticated else 'Gość'
|
||||
}, to=str(list_id), include_self=True)
|
||||
|
||||
|
Reference in New Issue
Block a user