Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 69c8aa8700 | |||
| 1fa3dace17 | |||
| 6dced8b1a5 | |||
| 493ee2ea7f | |||
| 52a2ec0cad | |||
| b5f2c3c5c5 | |||
| 403c281c93 |
+38
-13
@@ -3567,15 +3567,20 @@ def api_item_detail(item_id):
|
||||
for rec in borrow_records:
|
||||
if rec.get('Status') == 'active' and rec.get('User'):
|
||||
try:
|
||||
borrower_value = decrypt_text(rec.get('User'))
|
||||
user_raw = rec.get('User')
|
||||
if user_raw is not None:
|
||||
borrower_value = decrypt_text(str(user_raw))
|
||||
except Exception:
|
||||
borrower_value = rec.get('User')
|
||||
borrower_value = str(rec.get('User', ''))
|
||||
break
|
||||
|
||||
if not borrower_value and item.get('User'):
|
||||
try:
|
||||
borrower_value = decrypt_text(item.get('User'))
|
||||
item_user = item.get('User')
|
||||
if item_user is not None:
|
||||
borrower_value = decrypt_text(str(item_user))
|
||||
except Exception:
|
||||
borrower_value = item.get('User')
|
||||
borrower_value = str(item.get('User', ''))
|
||||
|
||||
# Helper to format datetimes
|
||||
def fmt_dt(dt):
|
||||
@@ -3589,15 +3594,19 @@ def api_item_detail(item_id):
|
||||
if borrow_records:
|
||||
rows = []
|
||||
for rec in borrow_records:
|
||||
user_raw = rec.get('User') or ''
|
||||
user_raw = rec.get('User')
|
||||
try:
|
||||
user = decrypt_text(user_raw) if user_raw else ''
|
||||
# FIX: Cast to string before decrypting
|
||||
user = decrypt_text(str(user_raw)) if user_raw is not None else ''
|
||||
except Exception:
|
||||
user = user_raw
|
||||
# FIX: Ensure the fallback is also a string for html.escape
|
||||
user = str(user_raw) if user_raw is not None else ''
|
||||
|
||||
status = rec.get('Status', '')
|
||||
start = fmt_dt(rec.get('Start'))
|
||||
end = fmt_dt(rec.get('End'))
|
||||
notes = html.escape(str(rec.get('Notes') or ''))
|
||||
|
||||
rows.append(f"<li><strong>{html.escape(user or '-')}</strong> — {html.escape(status)} — {html.escape(start)} → {html.escape(end)}{(' — ' + notes) if notes else ''}</li>")
|
||||
borrows_html = f"<h3>Ausleihhistorie</h3><ul>{''.join(rows)}</ul>"
|
||||
|
||||
@@ -3605,9 +3614,13 @@ def api_item_detail(item_id):
|
||||
detail_html = f"""
|
||||
<h2>{html.escape(item.get('Name', 'Untitled'))}</h2>
|
||||
<p><strong>ISBN:</strong> {html.escape(item.get('ISBN', item.get('Code4', '-')))}</p>
|
||||
<p><strong>Anzahl:</strong> {html.escape(item.get('SeriesCount', '-'))}</p>
|
||||
<p><strong>Ort:</strong> {html.escape(item.get('Ort', '-'))}</p>
|
||||
<p><strong>Typ:</strong> {html.escape(item.get('ItemType', '-'))}</p>
|
||||
<p><strong>Kategorie:</strong> {html.escape(item.get('library_category', '-'))}</p>
|
||||
<p><strong>Beschreibung:</strong> {html.escape(item.get('Beschreibung', '-'))}</p>
|
||||
<p><strong>Status:</strong> {html.escape(status_label)}</p>
|
||||
{f'<p><strong>Ausgeliehen von:</strong> {html.escape(str(borrower_value))}</p>' if borrower_value and status_label == 'Ausgeliehen' else ''}
|
||||
{f'<p><strong>Ausgeliehen von:</strong> {html.escape(borrower_value)}</p>' if borrower_value and status_label == 'Ausgeliehen' else ''}
|
||||
{borrows_html}
|
||||
"""
|
||||
client.close()
|
||||
@@ -5143,6 +5156,7 @@ def upload_item():
|
||||
individual_codes_raw = sanitize_form_value(request.form.get('individual_codes', ''))
|
||||
item_count_raw = sanitize_form_value(request.form.get('item_count', '1'))
|
||||
item_type_input = sanitize_form_value(request.form.get('item_type_input', ''))
|
||||
library_category = sanitize_form_value(request.form.get('library_category', ''))
|
||||
|
||||
app.logger.info(f"Upload attempt by {encrypt_text(username)}: name={name!r}, ort={ort!r}, beschreibung length={len(beschreibung)}, images count={len(images)}, filters={filter_upload}, filters2={filter_upload2}, filters3={filter_upload3}, anschaffungs_jahr={anschaffungs_jahr}, anschaffungs_kosten={anschaffungs_kosten}, code_4={code_4}, isbn={isbn_raw!r}, upload_mode={upload_mode!r}, item_count={item_count_raw!r}, item_type_input={item_type_input!r}, individual_codes={individual_codes_raw!r}")
|
||||
try:
|
||||
@@ -5306,7 +5320,7 @@ def upload_item():
|
||||
# Validate every code in our master list against the database
|
||||
for code in all_item_codes:
|
||||
if not it.is_code_unique(code):
|
||||
|
||||
app.logger.info(f"DEBUG: Code '{code}' is not unique.")
|
||||
# Special case: If they only uploaded ONE item, redirect them to that existing item
|
||||
if item_count == 1:
|
||||
existing_item = it._get_items_collection().find_one({"code_4": code})
|
||||
@@ -5339,13 +5353,13 @@ def upload_item():
|
||||
if not base_code:
|
||||
return None
|
||||
|
||||
candidate = base_code if position == 1 else f"{base_code}-{position}"
|
||||
candidate = base_code if position == 1 else f"{base_code}"
|
||||
if it.is_code_unique(candidate):
|
||||
return candidate
|
||||
|
||||
suffix = 1
|
||||
while suffix <= 1000:
|
||||
alternative = f"{candidate}-{suffix}"
|
||||
alternative = f"{candidate}"
|
||||
if it.is_code_unique(alternative):
|
||||
return alternative
|
||||
suffix += 1
|
||||
@@ -6013,6 +6027,17 @@ def upload_item():
|
||||
|
||||
for position in range(1, item_count + 1):
|
||||
unique_code = None
|
||||
if position <= len(individual_codes):
|
||||
unique_code = individual_codes[position - 1]
|
||||
else:
|
||||
unique_code = generate_unique_batch_code(base_code, position)
|
||||
|
||||
if (base_code or individual_codes) and not unique_code:
|
||||
error_msg = 'Fehler bei der Code-Erzeugung für mehrere Artikel.'
|
||||
if is_mobile:
|
||||
return jsonify({'success': False, 'message': error_msg}), 400
|
||||
flash(error_msg, 'error')
|
||||
return redirect(url_for(success_redirect_endpoint))
|
||||
|
||||
parent_item_id = str(created_item_ids[0]) if created_item_ids else None
|
||||
item_id = it.add_item(
|
||||
@@ -6028,9 +6053,9 @@ def upload_item():
|
||||
is_grouped_sub_item=(position > 1),
|
||||
parent_item_id=parent_item_id,
|
||||
isbn=item_isbn,
|
||||
item_type=item_type
|
||||
item_type=item_type,
|
||||
library_category=library_category
|
||||
)
|
||||
app.logger.info(f"Created item {position}/{item_count}: ID={item_id}, parent={parent_item_id}, series_group={series_group_id}")
|
||||
if not item_id:
|
||||
break
|
||||
created_item_ids.append(item_id)
|
||||
|
||||
@@ -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'):
|
||||
isbn=None, item_type='general', library_category=None):
|
||||
"""
|
||||
Add a new item to the inventory.
|
||||
|
||||
@@ -70,6 +70,9 @@ def add_item(name, ort, beschreibung, images=None, filter=None, filter2=None, fi
|
||||
series_position (int, optional): Position inside the batch (1-based)
|
||||
is_grouped_sub_item (bool, optional): Whether this item is hidden as sub-item
|
||||
parent_item_id (str, optional): Parent item id if this is a sub-item
|
||||
isbn (str, optional): ISBN for books or media items
|
||||
item_type (str, optional): Type of the item (e.g., 'general', 'book', 'cd')
|
||||
library_category (str, optional): Library category for the item
|
||||
|
||||
Returns:
|
||||
ObjectId: ID of the new item or None if failed
|
||||
@@ -97,6 +100,7 @@ def add_item(name, ort, beschreibung, images=None, filter=None, filter2=None, fi
|
||||
'Anschaffungskosten': ansch_kost,
|
||||
'Code_4': code_4,
|
||||
'ISBN': isbn,
|
||||
'library_category': library_category,
|
||||
'ItemType': item_type,
|
||||
'SeriesGroupId': series_group_id,
|
||||
'SeriesCount': series_count,
|
||||
@@ -196,7 +200,7 @@ def get_group_item_ids(id):
|
||||
|
||||
def update_item(id, name, ort, beschreibung, images=None, verfuegbar=True,
|
||||
filter=None, filter2=None, filter3=None, ansch_jahr=None, ansch_kost=None, code_4=None, reservierbar=True,
|
||||
isbn=None, item_type='general'):
|
||||
isbn=None, item_type='general', library_category=None):
|
||||
"""
|
||||
Update an existing inventory item.
|
||||
|
||||
@@ -214,7 +218,7 @@ def update_item(id, name, ort, beschreibung, images=None, verfuegbar=True,
|
||||
ansch_kost (float, optional): Cost of acquisition
|
||||
code_4 (str, optional): 4-digit identification code
|
||||
reservierbar (bool, optional): Whether the item can be reserved in advance
|
||||
|
||||
library_category (str, optional): Library category for the item
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
@@ -241,6 +245,7 @@ def update_item(id, name, ort, beschreibung, images=None, verfuegbar=True,
|
||||
'Anschaffungskosten': ansch_kost,
|
||||
'Code_4': code_4,
|
||||
'ISBN': isbn,
|
||||
'library_category': library_category,
|
||||
'ItemType': item_type,
|
||||
'LastUpdated': datetime.datetime.now()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user