Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 613c1e11e4 | |||
| 9e3b54c1b1 | |||
| a8bce26eab | |||
| 36c391e99c | |||
| 40c3970719 | |||
| e7f4b1ce9d |
+35
-12
@@ -42,6 +42,7 @@ import Web.modules.database.termine as termin
|
||||
import Web.modules.log.audit_log as al
|
||||
import push_notifications as pn
|
||||
import Web.modules.inventarsystem.pdf_export as pdf_export
|
||||
import Web.modules.inventarsystem.excel_export as excel_export
|
||||
import datetime
|
||||
from apscheduler.schedulers.background import BackgroundScheduler
|
||||
from bson.objectid import ObjectId
|
||||
@@ -2476,6 +2477,7 @@ def _upload_excel_items(scope='inventory'):
|
||||
parent_item_id=parent_item_id,
|
||||
isbn=row['isbn'],
|
||||
item_type=row['item_type'],
|
||||
is_library=False
|
||||
)
|
||||
if not item_id:
|
||||
import_errors.append((row['row_number'], 'Fehler beim Anlegen des Artikels'))
|
||||
@@ -2979,33 +2981,50 @@ def library_export_excel(scope='all'):
|
||||
username = session['username']
|
||||
is_admin_user = us.check_admin(username)
|
||||
|
||||
import Web.modules.inventarsystem.excel_export as excel_export
|
||||
client = MongoClient(MONGODB_HOST, MONGODB_PORT)
|
||||
db = client[cfg.MONGODB_DB]
|
||||
items_collection = db['items']
|
||||
|
||||
query = {'ItemType': {'$in': LIBRARY_ITEM_TYPES}, 'Deleted': {'$ne': True}}
|
||||
# Base query
|
||||
query = {
|
||||
'ItemType': {'$in': LIBRARY_ITEM_TYPES},
|
||||
'Deleted': {'$ne': True}
|
||||
}
|
||||
|
||||
# Scope modifications
|
||||
if scope == 'borrowed_by_me':
|
||||
query['User'] = username
|
||||
query['Verfuegbar'] = False
|
||||
filename = f"Bibliothek_Ausgeliehen_{username}.xlsx"
|
||||
|
||||
elif scope == 'all_borrowed':
|
||||
if not is_admin_user:
|
||||
# Consider adding a flash message here before redirecting
|
||||
return redirect('/library')
|
||||
query['Verfuegbar'] = False
|
||||
filename = "Bibliothek_Alle_Ausleihen.xlsx"
|
||||
|
||||
elif scope == 'schulbuecher':
|
||||
# Overwrites the base $in query, which is fine
|
||||
query['ItemType'] = 'schulbuch'
|
||||
filename = "Schulbuecher_Bestand.xlsx"
|
||||
|
||||
elif scope == 'all_books':
|
||||
# FIX: Keep the library item types restriction, but exclude 'general'
|
||||
query['ItemType'] = {'$in': [t for t in LIBRARY_ITEM_TYPES if t != 'general']}
|
||||
filename = "Bibliothek_Buecher.xlsx"
|
||||
|
||||
else:
|
||||
# 'all'
|
||||
# 'all' scope
|
||||
filename = "Bibliothek_Gesamtbestand.xlsx"
|
||||
|
||||
# Database interaction
|
||||
client = MongoClient(MONGODB_HOST, MONGODB_PORT)
|
||||
db = client[cfg.MONGODB_DB]
|
||||
items_collection = db['items']
|
||||
|
||||
items = list(items_collection.find(query))
|
||||
client.close()
|
||||
|
||||
# Generate and send file
|
||||
excel_file = excel_export.generate_library_excel(items)
|
||||
|
||||
return send_file(
|
||||
excel_file,
|
||||
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
@@ -5115,6 +5134,8 @@ def upload_item():
|
||||
if 'username' not in session:
|
||||
return jsonify({'success': False, 'message': 'Nicht angemeldet'}), 401
|
||||
|
||||
item_is_library = False
|
||||
|
||||
# Check if user may insert items
|
||||
username = session['username']
|
||||
permissions = _get_current_user_permissions() or us.build_default_permission_payload('standard_user')
|
||||
@@ -5159,6 +5180,9 @@ def upload_item():
|
||||
item_type_input = sanitize_form_value(request.form.get('item_type_input', ''))
|
||||
library_category = sanitize_form_value(request.form.get('library_category', ''))
|
||||
|
||||
if library_caregory != '':
|
||||
item_is_library = True
|
||||
|
||||
try:
|
||||
item_count = int(item_count_raw) if item_count_raw else 1
|
||||
except (TypeError, ValueError):
|
||||
@@ -5227,7 +5251,7 @@ def upload_item():
|
||||
return redirect(url_for(success_redirect_endpoint))
|
||||
|
||||
item_isbn = ''
|
||||
item_type = 'general'
|
||||
item_type = 'other'
|
||||
if cfg.MODULES.is_enabled('library') and isbn_raw:
|
||||
normalized_isbn = normalize_and_validate_isbn(isbn_raw)
|
||||
if normalized_isbn:
|
||||
@@ -5235,8 +5259,7 @@ def upload_item():
|
||||
item_type = 'book'
|
||||
else:
|
||||
item_isbn = isbn_raw
|
||||
if upload_mode == 'library':
|
||||
item_type = 'book'
|
||||
|
||||
if item_type_input != "":
|
||||
item_type = item_type_input
|
||||
|
||||
@@ -5253,7 +5276,6 @@ def upload_item():
|
||||
return jsonify({'success': False, 'message': error_msg}), 400
|
||||
flash(error_msg, 'error')
|
||||
return redirect(url_for('library_admin'))
|
||||
item_type = 'book'
|
||||
|
||||
# Only check for images if not duplicating and no duplicate images provided and no book cover
|
||||
# For library mode, skip this check as images come only from ISBN fetch
|
||||
@@ -6047,7 +6069,8 @@ def upload_item():
|
||||
parent_item_id=parent_item_id,
|
||||
isbn=item_isbn,
|
||||
item_type=item_type,
|
||||
library_category=library_category
|
||||
library_category=library_category,
|
||||
is_library=item_is_library
|
||||
)
|
||||
if not item_id:
|
||||
break
|
||||
|
||||
@@ -24,7 +24,7 @@ import Web.modules.database.settings as cfg
|
||||
from Web.modules.database.settings import MongoClient
|
||||
|
||||
|
||||
LIBRARY_ITEM_TYPES = ('book', 'cd', 'dvd', 'other', 'schoolbook')
|
||||
LIBRARY_ITEM_TYPES = ('book', 'cd', 'dvd', 'other', 'schoolbook', 'Buch', 'Schulbuch', 'schulbuch')
|
||||
|
||||
|
||||
def _non_library_query(extra_query=None):
|
||||
@@ -49,7 +49,7 @@ def add_item(name, ort, beschreibung, images=None, filter=None, filter2=None, fi
|
||||
ansch_jahr=None, ansch_kost=None, code_4=None, reservierbar=True,
|
||||
series_group_id=None, series_count=1, series_position=1,
|
||||
is_grouped_sub_item=False, parent_item_id=None,
|
||||
isbn=None, item_type='general', library_category=None):
|
||||
isbn=None, item_type='general', library_category=None, is_library=False):
|
||||
"""
|
||||
Add a new item to the inventory.
|
||||
|
||||
@@ -102,6 +102,7 @@ def add_item(name, ort, beschreibung, images=None, filter=None, filter2=None, fi
|
||||
'ISBN': isbn,
|
||||
'library_category': library_category,
|
||||
'ItemType': item_type,
|
||||
'is_library': is_library,
|
||||
'SeriesGroupId': series_group_id,
|
||||
'SeriesCount': series_count,
|
||||
'SeriesPosition': series_position,
|
||||
|
||||
@@ -37,20 +37,23 @@ def generate_library_excel(items):
|
||||
item.get("ReturnDate", ""),
|
||||
item.get("Anschaffungskosten", "")
|
||||
]
|
||||
ws.append(row)
|
||||
|
||||
for col in ws.columns:
|
||||
max_length = 0
|
||||
column = col[0].column_letter
|
||||
for cell in col:
|
||||
try:
|
||||
if len(str(cell.value)) > max_length:
|
||||
max_length = len(str(cell.value))
|
||||
except:
|
||||
pass
|
||||
ws.column_dimensions[column].width = min(max_length + 2, 50)
|
||||
# FIX: Clean the row data INSIDE the loop for every single item
|
||||
clean_row = []
|
||||
for value in row:
|
||||
if isinstance(value, list):
|
||||
# Converts ['A', 'B'] to "A, B" and an empty list [] to an empty string ""
|
||||
clean_row.append(", ".join(map(str, value)) if value else "")
|
||||
elif isinstance(value, dict):
|
||||
# Just in case there is an embedded MongoDB sub-document
|
||||
clean_row.append(str(value))
|
||||
else:
|
||||
clean_row.append(value)
|
||||
|
||||
# Append the safe, flattened row to the worksheet
|
||||
ws.append(clean_row)
|
||||
|
||||
excel_buffer = io.BytesIO()
|
||||
wb.save(excel_buffer)
|
||||
excel_buffer.seek(0)
|
||||
return excel_buffer
|
||||
return excel_buffer
|
||||
@@ -451,7 +451,7 @@
|
||||
<option value="card_only">Nur Ausweis erfassen</option>
|
||||
<option value="quick_toggle">Schnellmodus: Ausweis + Mediencode</option>
|
||||
</select>
|
||||
<input type="text" id="activeStudentCard" placeholder="Aktiver Ausweis (gescannt)" readonly>
|
||||
<input type="text" id="activeStudentCard" placeholder="Aktiver Ausweis (gescannt)">
|
||||
<button id="resetCardBtn" class="button" type="button">Ausweis löschen</button>
|
||||
<button id="toggleScannerBtn" class="button" type="button">Scanner starten</button>
|
||||
</div>
|
||||
@@ -503,6 +503,10 @@
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="8" y1="13" x2="16" y2="13"></line><line x1="8" y1="17" x2="16" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
|
||||
Alle ausgeliehen Excel
|
||||
</button>
|
||||
<button class="button" style="background: #10b981; color: white; display: flex; align-items: center; gap: 0.5rem;" onclick="window.location.href='/library/export/all_books'">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="8" y1="13" x2="16" y2="13"></line><line x1="8" y1="17" x2="16" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
|
||||
Alle Bücher Excel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user