Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d6e8e08b10 | |||
| ddb6ab82ad | |||
| baefc55257 | |||
| 6c359089cd | |||
| 479cf3d98c | |||
| f00e7d8f74 | |||
| 7af729ac88 | |||
| 847349b419 |
+14
-4
@@ -4349,10 +4349,14 @@ def api_library_scan_action():
|
||||
|
||||
due_date = now + datetime.timedelta(days=borrow_duration_days)
|
||||
|
||||
it.update_item_status(item_id, False, borrower_name)
|
||||
app.logger.info(f"Library scan action: borrowing item {item_id} for student card {student_card_id} until {due_date.isoformat()}")
|
||||
borrower_user = us.get_user_by_student_card(student_card_id)
|
||||
app.logger.info(f"Found borrower user: {borrower_user}")
|
||||
if not borrower_user or not borrower_user.get('_id'):
|
||||
app.logger.warning(f"No user found for student card {student_card_id}. Cannot record borrowing in ausleihungen.")
|
||||
return jsonify({'ok': False, 'message': 'Kein Benutzer für diesen Schülerausweis gefunden.'}), 404
|
||||
|
||||
it.update_item_status(item_id, False, borrower_name)
|
||||
au.add_ausleihung(
|
||||
item_id,
|
||||
str(borrower_user['_id']),
|
||||
@@ -4367,7 +4371,7 @@ def api_library_scan_action():
|
||||
'channel': 'library_scan',
|
||||
'item_id': item_id,
|
||||
'item_name': item_doc.get('Name', ''),
|
||||
'borrower':borrower_name,
|
||||
'borrower': borrower_name,
|
||||
'student_card_id': student_card_id,
|
||||
'borrow_duration_days': borrow_duration_days,
|
||||
}
|
||||
@@ -4457,6 +4461,7 @@ def api_item_detail(item_id):
|
||||
db = client[MONGODB_DB]
|
||||
ausleihungen_col = db['ausleihungen']
|
||||
items_col = db['items']
|
||||
student_cards_col = db['student_cards']
|
||||
|
||||
# Determine parent/group id (if this is a child, use its ParentItemId)
|
||||
parent_id = str(item.get('ParentItemId') or str(item.get('_id')))
|
||||
@@ -4499,8 +4504,10 @@ def api_item_detail(item_id):
|
||||
if rec.get('Status') == 'active' and rec.get('User'):
|
||||
try:
|
||||
user_raw = rec.get('User')
|
||||
if user_raw is not None:
|
||||
borrower_value = decrypt_text(str(user_raw))
|
||||
user_doc = student_cards_col.find_one({'_id': ObjectId(user_raw)}) if user_raw else None
|
||||
app.logger.debug(f"Line 4508: Found user_doc for borrower: {user_doc}")
|
||||
if user_doc:
|
||||
borrower_value = decrypt_text(str(user_doc.get('SchülerName', ''))) if user_doc.get('SchülerName') else str(user_doc.get('AusweisId', ''))
|
||||
except Exception:
|
||||
borrower_value = str(rec.get('User', ''))
|
||||
break
|
||||
@@ -4508,8 +4515,10 @@ def api_item_detail(item_id):
|
||||
if not borrower_value and item.get('User'):
|
||||
try:
|
||||
item_user = item.get('User')
|
||||
app.logger.debug(f"Line 4518: Found item_user for borrower: {item_user}")
|
||||
if item_user is not None:
|
||||
borrower_value = decrypt_text(str(item_user))
|
||||
app.logger.debug(f"Line 4521: Decrypted borrower_value from item.User: {borrower_value}")
|
||||
except Exception:
|
||||
borrower_value = str(item.get('User', ''))
|
||||
|
||||
@@ -4526,6 +4535,7 @@ def api_item_detail(item_id):
|
||||
|
||||
for rec in borrow_records[:3]:
|
||||
user_raw = rec.get('User')
|
||||
app.logger.debug(f"Line 4538: Processing borrow record: {rec}")
|
||||
try:
|
||||
user = decrypt_text(user_raw) if user_raw is not None else ''
|
||||
except Exception:
|
||||
|
||||
@@ -697,7 +697,7 @@ def get_user_by_student_card(student_card_id):
|
||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||
db = _get_tenant_db(client)
|
||||
users = db['student_cards']
|
||||
found_user = users.find_one({'SchülerName': normalized})
|
||||
found_user = users.find_one({'AusweisId': normalized})
|
||||
client.close()
|
||||
|
||||
# Do not call dp.decrypt_text() here because found_user is a MongoDB dictionary.
|
||||
|
||||
@@ -266,6 +266,11 @@
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.code-search-label {
|
||||
color: #b93845;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.search-button {
|
||||
padding: 8px 12px;
|
||||
background-color: #007bff;
|
||||
@@ -284,10 +289,10 @@
|
||||
}
|
||||
|
||||
#code-search.searching {
|
||||
background-color: #fff3cd;
|
||||
background-color: #fff5f5;
|
||||
transition: background-color 0.3s;
|
||||
border: 2px solid #ffc107;
|
||||
box-shadow: 0 0 8px rgba(255, 193, 7, 0.5);
|
||||
border: 2px solid #d65a62;
|
||||
box-shadow: 0 0 8px rgba(190, 55, 66, 0.28);
|
||||
}
|
||||
|
||||
/* QR Scanner styles */
|
||||
@@ -564,9 +569,11 @@
|
||||
|
||||
.items-navigation {
|
||||
display: grid;
|
||||
grid-template-columns: 44px minmax(0, 1fr) 44px;
|
||||
grid-template-columns: 42px minmax(0, 1fr) 42px;
|
||||
align-items: center;
|
||||
column-gap: 18px;
|
||||
column-gap: 16px;
|
||||
width: calc(100% + 116px);
|
||||
margin-left: -58px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
@@ -576,17 +583,39 @@
|
||||
}
|
||||
|
||||
.navigation-button {
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
border: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
padding: 0;
|
||||
background: var(--ui-surface-soft);
|
||||
color: var(--ui-title);
|
||||
border: 1px solid var(--ui-border);
|
||||
box-shadow: var(--ui-shadow-sm);
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
border-radius: 10px;
|
||||
font-size: 1.15rem;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
transition: transform 160ms ease, box-shadow 160ms ease, background-color 160ms ease, border-color 160ms ease;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.navigation-button:hover {
|
||||
background-color: #0056b3;
|
||||
background: var(--ui-surface);
|
||||
border-color: var(--module-accent-color);
|
||||
box-shadow: var(--ui-shadow-md);
|
||||
transform: translateY(-2px) scale(1.04);
|
||||
}
|
||||
|
||||
.navigation-button:active {
|
||||
transform: translateY(0) scale(0.96);
|
||||
}
|
||||
|
||||
.navigation-button:focus-visible {
|
||||
outline: 3px solid rgba(37, 99, 235, 0.35);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
/* Modal styles */
|
||||
@@ -749,15 +778,15 @@
|
||||
}
|
||||
|
||||
.code-match {
|
||||
border: 2px solid #17a2b8 !important;
|
||||
box-shadow: 0 0 15px rgba(23, 162, 184, 0.5) !important;
|
||||
border: 2px solid #d65a62 !important;
|
||||
box-shadow: 0 0 15px rgba(190, 55, 66, 0.28) !important;
|
||||
position: relative;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.exact-code-match {
|
||||
border: 3px solid #28a745 !important;
|
||||
box-shadow: 0 0 20px rgba(40, 167, 69, 0.7) !important;
|
||||
border: 3px solid #b93845 !important;
|
||||
box-shadow: 0 0 20px rgba(185, 56, 69, 0.42) !important;
|
||||
position: relative;
|
||||
z-index: 11;
|
||||
}
|
||||
@@ -1640,6 +1669,8 @@
|
||||
/* Navigation buttons mobile */
|
||||
.items-navigation {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
.navigation-button-slot {
|
||||
@@ -2510,7 +2541,7 @@ document.addEventListener('DOMContentLoaded', ()=>{
|
||||
|
||||
<div class="filter-group search-field">
|
||||
<div class="filter-header">
|
||||
<label for="code-search">Code suchen:</label>
|
||||
<label class="code-search-label" for="code-search">Code suchen:</label>
|
||||
<button type="button" class="clear-filter" onclick="clearCodeSearch()">Clear</button>
|
||||
</div>
|
||||
<div class="search-container">
|
||||
|
||||
Reference in New Issue
Block a user