Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 55f34e0462 | |||
| 5a3a180b88 | |||
| 07ad592bd9 | |||
| fa299cde06 |
@@ -299,7 +299,7 @@
|
||||
<div class="muted">{{ e.item_author or '—' }}</div>
|
||||
<div class="mono">{{ e.item_code or '—' }}</div>
|
||||
<div style="margin-top:6px;">
|
||||
<a class="btn btn-outline-secondary btn-sm" href="{{ url_for('library_item_invoices', item_id=e.item_id) }}">Rechnungen</a>
|
||||
<a class="btn btn-outline-secondary btn-sm" href="{{ url_for('library_item_invoices', item_id=e.item_id) }}">Rechnungen / Historie</a>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
@@ -322,9 +322,9 @@
|
||||
{% if e.invoice_number %}
|
||||
<div class="mono">{{ e.invoice_number }}</div>
|
||||
<div class="muted">{{ e.invoice_amount }}</div>
|
||||
{% if e.invoice_corrections_count %}
|
||||
<!--{% if e.invoice_corrections_count %}
|
||||
<div class="muted" style="color:#7c2d12;">{{ e.invoice_corrections_count }} Korrektur(en)</div>
|
||||
{% endif %}
|
||||
{% endif %} -->
|
||||
<div style="margin-top:6px;">
|
||||
<a class="btn btn-outline-primary btn-sm" href="{{ url_for('admin_view_invoice_pdf', borrow_id=e.id) }}" target="_blank" rel="noopener">PDF öffnen</a>
|
||||
</div>
|
||||
@@ -363,13 +363,13 @@
|
||||
<button type="button" class="btn btn-warning btn-sm" onclick="openRepairModal('{{ e.item_id }}', '{{ e.item_code }}')">Reparieren / Ersetzen</button>
|
||||
{% endif %}
|
||||
|
||||
{% if e.invoice_number %}
|
||||
<!--{% if e.invoice_number %}
|
||||
<form method="post" action="{{ url_for('admin_add_invoice_correction', borrow_id=e.id) }}" onsubmit="return confirm('Korrekturbuchung hinzufügen?');" style="display: flex; gap: 6px; align-items: center; flex-wrap: wrap;">
|
||||
<input type="text" name="correction_reason" value="Korrektur zu {{ e.invoice_number }}" placeholder="Korrekturgrund" required style="padding:6px; border:1px solid #ddd; border-radius:6px; min-width:160px; max-width:180px;">
|
||||
<input type="text" name="amount_delta" placeholder="z.B. -{{ e.invoice_amount }}" style="padding:6px; border:1px solid #ddd; border-radius:6px; width:120px;">
|
||||
<button type="submit" class="btn btn-outline-danger btn-sm">Korrektur</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}-->
|
||||
|
||||
{% if e.status in ['active', 'planned'] %}
|
||||
<form method="post" action="{{ url_for('admin_reset_borrowing', borrow_id=e.id) }}" onsubmit="return confirm('Ausleihe zurücksetzen?');">
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
</div>
|
||||
<div class="head-actions">
|
||||
<a class="btn btn-outline-secondary" href="{{ url_for('library_loans_admin') }}">Zur Bibliotheks-Ausleihenverwaltung</a>
|
||||
<a class="btn btn-secondary" href="{{ url_for('library_admin') }}">Bibliothek öffnen</a>
|
||||
<a class="btn btn-secondary" href="{{ url_for('library_view') }}">Bibliothek öffnen</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
+115
-83
@@ -1523,78 +1523,8 @@
|
||||
document.getElementById('new-location-input').value = '';
|
||||
}
|
||||
|
||||
// Function to fetch book information from ISBN
|
||||
function fetchBookInfo(formType) {
|
||||
if (!libraryModuleEnabled) {
|
||||
alert('Bibliotheks-Modul ist deaktiviert.');
|
||||
return;
|
||||
}
|
||||
const isbnField = document.getElementById('isbn');
|
||||
const infoContainer = document.getElementById('book-info-container');
|
||||
|
||||
if (!isbnField || !infoContainer) {
|
||||
alert('Fehler: Erforderliche Formularelemente nicht gefunden.');
|
||||
return;
|
||||
}
|
||||
|
||||
const isbn = normalizeIsbnClient(isbnField.value);
|
||||
|
||||
if (!isbn) {
|
||||
infoContainer.innerHTML = '<div class="error-message">Bitte geben Sie eine ISBN oder einen Barcode ein.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading indicator
|
||||
infoContainer.innerHTML = '<div class="loading-spinner">Informationen werden abgerufen...</div>';
|
||||
|
||||
// Make API request to fetch book data
|
||||
fetch(`/fetch_book_info/${isbn}`)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
throw new Error('Buch nicht gefunden. Überprüfen Sie die ISBN.');
|
||||
} else {
|
||||
throw new Error('Fehler beim Abrufen der Buchinformationen');
|
||||
}
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
infoContainer.innerHTML = `<div class="error-message">${data.error}</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
// Store book data globally for import functionality
|
||||
currentBookData = data;
|
||||
|
||||
// Display book information with import button
|
||||
infoContainer.innerHTML = `
|
||||
<div class="book-info">
|
||||
<h4>${data.title}</h4>
|
||||
${data.authors ? `<p><strong>Autor(en):</strong> ${data.authors}</p>` : ''}
|
||||
${data.publisher ? `<p><strong>Verlag:</strong> ${data.publisher}</p>` : ''}
|
||||
${data.publishedDate ? `<p><strong>Erscheinungsdatum:</strong> ${data.publishedDate}</p>` : ''}
|
||||
${data.pageCount ? `<p><strong>Seitenanzahl:</strong> ${data.pageCount}</p>` : ''}
|
||||
${data.price ? `<p><strong>Preis:</strong> ${data.price}</p>` : ''}
|
||||
${data.thumbnail ? `<img src="${data.thumbnail}" alt="Buchcover" class="book-thumbnail">` : ''}
|
||||
${data.description ? `
|
||||
<div class="book-description">
|
||||
<h5>Beschreibung:</h5>
|
||||
<p>${data.description}</p>
|
||||
</div>
|
||||
` : ''}
|
||||
<button type="button" class="import-book-button" onclick="importBookInfo('${formType}')">
|
||||
Buchdaten in Formular übernehmen
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
})
|
||||
.catch(error => {
|
||||
infoContainer.innerHTML = `<div class="error-message">${error.message}</div>`;
|
||||
currentBookData = null;
|
||||
});
|
||||
}
|
||||
let currentFetchedIsbn = null;
|
||||
let currentBookData = null;
|
||||
|
||||
// Function to import book information into form
|
||||
function importBookInfo(formType) {
|
||||
@@ -1602,23 +1532,23 @@
|
||||
alert('Keine Buchdaten verfügbar zum Import.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Get form fields
|
||||
const nameField = document.getElementById('name');
|
||||
const descriptionField = document.getElementById('beschreibung');
|
||||
const priceField = document.getElementById('anschaffungskosten'); // <-- NEU
|
||||
|
||||
const priceField = document.getElementById('anschaffungskosten');
|
||||
|
||||
if (!nameField || !descriptionField) {
|
||||
alert('Fehler: Formularfelder nicht gefunden.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Generate book title
|
||||
let bookTitle = currentBookData.title || '';
|
||||
if (currentBookData.authors && currentBookData.authors !== 'Unknown Author') {
|
||||
bookTitle += ` - ${currentBookData.authors}`;
|
||||
}
|
||||
|
||||
|
||||
// Generate description
|
||||
let description = '';
|
||||
if (currentBookData.description && currentBookData.description !== 'No description available') {
|
||||
@@ -1639,11 +1569,11 @@
|
||||
description += `\nSeiten: ${currentBookData.pageCount}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Import the data into form fields
|
||||
nameField.value = bookTitle;
|
||||
descriptionField.value = description;
|
||||
|
||||
|
||||
// Preis in das Formularfeld eintragen
|
||||
if (priceField && currentBookData.price !== null && currentBookData.price !== undefined) {
|
||||
// Wandelt den Float (z.B. 12.25) in einen String mit Komma (12,25) um
|
||||
@@ -1651,18 +1581,31 @@
|
||||
priceField.value = formattedPrice;
|
||||
}
|
||||
|
||||
// Download and import book cover image if available
|
||||
// Download and import book cover image if available (mit Sicherheits-Check)
|
||||
if (currentBookData.thumbnail) {
|
||||
downloadBookCover(currentBookData.thumbnail);
|
||||
if (typeof downloadBookCover === 'function') {
|
||||
try {
|
||||
downloadBookCover(currentBookData.thumbnail);
|
||||
} catch (e) {
|
||||
console.warn("Cover konnte nicht heruntergeladen werden:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Show success message
|
||||
const infoContainer = document.getElementById('book-info-container');
|
||||
|
||||
// Alte Erfolgsmeldung entfernen, falls jemand mehrfach klickt
|
||||
const oldMessage = infoContainer.querySelector('.import-success-message');
|
||||
if (oldMessage) {
|
||||
oldMessage.remove();
|
||||
}
|
||||
|
||||
const successMessage = document.createElement('div');
|
||||
successMessage.className = 'import-success-message';
|
||||
successMessage.textContent = 'Buchdaten erfolgreich in das Formular übernommen!';
|
||||
infoContainer.appendChild(successMessage);
|
||||
|
||||
|
||||
// Remove success message after 3 seconds
|
||||
setTimeout(() => {
|
||||
if (successMessage.parentNode) {
|
||||
@@ -1671,6 +1614,95 @@
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// Function to fetch book information from ISBN
|
||||
function fetchBookInfo(formType) {
|
||||
if (typeof libraryModuleEnabled !== 'undefined' && !libraryModuleEnabled) {
|
||||
alert('Bibliotheks-Modul ist deaktiviert.');
|
||||
return;
|
||||
}
|
||||
const isbnField = document.getElementById('isbn');
|
||||
const infoContainer = document.getElementById('book-info-container');
|
||||
|
||||
if (!isbnField || !infoContainer) {
|
||||
alert('Fehler: Erforderliche Formularelemente nicht gefunden.');
|
||||
return;
|
||||
}
|
||||
|
||||
const isbn = typeof normalizeIsbnClient === 'function'
|
||||
? normalizeIsbnClient(isbnField.value)
|
||||
: isbnField.value.trim();
|
||||
|
||||
if (!isbn) {
|
||||
infoContainer.innerHTML = '<div class="error-message">Bitte geben Sie eine ISBN oder einen Barcode ein.</div>';
|
||||
currentFetchedIsbn = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// --- DER FIX FÜR DAS DOPPELKLICK-PROBLEM ---
|
||||
// Wenn das Buch bereits erfolgreich geladen wurde und auf dem Bildschirm steht,
|
||||
// unterbrechen wir hier. Das schützt den Button vor dem Überschreiben.
|
||||
if (currentFetchedIsbn === isbn && currentBookData !== null) {
|
||||
return;
|
||||
}
|
||||
// -------------------------------------------
|
||||
|
||||
// Sperre für den aktuellen Suchbegriff setzen
|
||||
currentFetchedIsbn = isbn;
|
||||
|
||||
// Show loading indicator
|
||||
infoContainer.innerHTML = '<div class="loading-spinner">Informationen werden abgerufen...</div>';
|
||||
|
||||
// Make API request to fetch book data
|
||||
fetch(`/fetch_book_info/${isbn}`)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
throw new Error('Buch nicht gefunden. Überprüfen Sie die ISBN.');
|
||||
} else {
|
||||
throw new Error('Fehler beim Abrufen der Buchinformationen');
|
||||
}
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
infoContainer.innerHTML = `<div class="error-message">${data.error}</div>`;
|
||||
currentFetchedIsbn = null; // Freigabe bei Fehler
|
||||
return;
|
||||
}
|
||||
|
||||
// Store book data globally for import functionality
|
||||
currentBookData = data;
|
||||
|
||||
// Display book information with import button
|
||||
infoContainer.innerHTML = `
|
||||
<div class="book-info">
|
||||
<h4>${data.title}</h4>
|
||||
${data.authors ? `<p><strong>Autor(en):</strong> ${data.authors}</p>` : ''}
|
||||
${data.publisher ? `<p><strong>Verlag:</strong> ${data.publisher}</p>` : ''}
|
||||
${data.publishedDate ? `<p><strong>Erscheinungsdatum:</strong> ${data.publishedDate}</p>` : ''}
|
||||
${data.pageCount ? `<p><strong>Seitenanzahl:</strong> ${data.pageCount}</p>` : ''}
|
||||
${data.price ? `<p><strong>Preis:</strong> ${data.price}</p>` : ''}
|
||||
${data.thumbnail ? `<img src="${data.thumbnail}" alt="Buchcover" class="book-thumbnail">` : ''}
|
||||
${data.description ? `
|
||||
<div class="book-description">
|
||||
<h5>Beschreibung:</h5>
|
||||
<p>${data.description}</p>
|
||||
</div>
|
||||
` : ''}
|
||||
<button type="button" class="import-book-button" onclick="importBookInfo('${formType}')">
|
||||
Buchdaten in Formular übernehmen
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
})
|
||||
.catch(error => {
|
||||
infoContainer.innerHTML = `<div class="error-message">${error.message}</div>`;
|
||||
currentBookData = null;
|
||||
currentFetchedIsbn = null;
|
||||
});
|
||||
}
|
||||
|
||||
function downloadBookCover(imageUrl) {
|
||||
if (!imageUrl) {
|
||||
console.log('No image URL provided');
|
||||
|
||||
Reference in New Issue
Block a user