From b08df9b812818d7133baff3cb5ea89f657443c8f Mon Sep 17 00:00:00 2001 From: Marcel Diegelmann Date: Fri, 13 Feb 2026 16:34:43 +0100 Subject: [PATCH] =?UTF-8?q?Cleanup-Logik=20f=C3=BCr=20Baugruppen=20und=20B?= =?UTF-8?q?OM-Eintr=C3=A4ge=20im=20Statistik-Bereich=20=C3=BCberarbeiten?= =?UTF-8?q?=20bzw.=20erweitern?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../elements/part_search_controller.js | 4 +- .../pages/statistics_assembly_controller.js | 162 +++++++++++++++--- src/Controller/StatisticsController.php | 102 +++++++++-- src/Entity/Attachments/AssemblyAttachment.php | 1 - src/Services/Tools/StatisticsHelper.php | 15 ++ .../tools/statistics/statistics.html.twig | 21 ++- translations/frontend.cs.xlf | 12 ++ translations/frontend.da.xlf | 12 ++ translations/frontend.de.xlf | 12 ++ translations/frontend.el.xlf | 24 ++- translations/frontend.en.xlf | 12 ++ translations/frontend.es.xlf | 12 ++ translations/frontend.fr.xlf | 12 ++ translations/frontend.hu.xlf | 12 ++ translations/frontend.it.xlf | 12 ++ translations/frontend.ja.xlf | 44 +++-- translations/frontend.nl.xlf | 24 ++- translations/frontend.pl.xlf | 12 ++ translations/frontend.ru.xlf | 12 ++ translations/frontend.uk.xlf | 12 ++ translations/frontend.zh.xlf | 12 ++ translations/messages.cs.xlf | 56 ++++-- translations/messages.da.xlf | 36 +++- translations/messages.de.xlf | 38 ++-- translations/messages.el.xlf | 36 +++- translations/messages.en.xlf | 36 +++- translations/messages.es.xlf | 38 ++-- translations/messages.fr.xlf | 40 +++-- translations/messages.hu.xlf | 40 +++-- translations/messages.it.xlf | 40 +++-- translations/messages.ja.xlf | 40 +++-- translations/messages.nl.xlf | 36 +++- translations/messages.pl.xlf | 40 +++-- translations/messages.ru.xlf | 40 +++-- translations/messages.zh.xlf | 40 +++-- 35 files changed, 864 insertions(+), 233 deletions(-) diff --git a/assets/controllers/elements/part_search_controller.js b/assets/controllers/elements/part_search_controller.js index aeeb701d..78d947b9 100644 --- a/assets/controllers/elements/part_search_controller.js +++ b/assets/controllers/elements/part_search_controller.js @@ -227,7 +227,7 @@ export default class extends Controller { }, templates: { header({ html }) { - return html`${trans(STATISTICS_ASSEMBLIES)} + return html`${trans("assembly.labelp")}
`; }, item({ item, components, html }) { @@ -273,7 +273,7 @@ export default class extends Controller { }, templates: { header({ html }) { - return html`${trans(STATISTICS_PROJECTS)} + return html`${trans("project.labelp")}
`; }, item({ item, components, html }) { diff --git a/assets/controllers/pages/statistics_assembly_controller.js b/assets/controllers/pages/statistics_assembly_controller.js index b20ef3b3..248fe29d 100644 --- a/assets/controllers/pages/statistics_assembly_controller.js +++ b/assets/controllers/pages/statistics_assembly_controller.js @@ -2,44 +2,154 @@ import { Controller } from '@hotwired/stimulus'; export default class extends Controller { static values = { - url: String, - confirmMsg: String, - successMsg: String, - errorMsg: String + cleanupBomUrl: String, + cleanupPreviewUrl: String } - static targets = ["count"] + static targets = ["bomCount", "previewCount", "bomButton", "previewButton"] async cleanup(event) { - event.preventDefault(); - - if (!confirm(this.confirmMsgValue)) { - return; + if (event) { + event.preventDefault(); + event.stopImmediatePropagation(); } + const button = event ? event.currentTarget : null; + if (button) button.disabled = true; + try { - const response = await fetch(this.urlValue, { - method: 'POST', - headers: { - 'X-Requested-With': 'XMLHttpRequest' - } - }); + const data = await this.fetchWithErrorHandling(this.cleanupBomUrlValue, { method: 'POST' }); - if (response.ok) { - const data = await response.json(); - alert(this.successMsgValue.replace('%count%', data.count)); - // Update the count displayed in the UI - if (this.hasCountTarget) { - this.countTarget.innerText = '0'; + if (data.success) { + this.showSuccessMessage(data.message); + if (this.hasBomCountTarget) { + this.bomCountTarget.textContent = data.new_count; + } + if (data.new_count === 0 && this.hasBomButtonTarget) { + this.bomButtonTarget.remove(); } - // Reload page to reflect changes if needed, or just let the user see 0 - window.location.reload(); } else { - alert(this.errorMsgValue); + this.showErrorMessage(data.message || 'BOM cleanup failed'); } } catch (error) { - console.error('Cleanup failed:', error); - alert(this.errorMsgValue); + this.showErrorMessage(error.message || 'An unexpected error occurred during BOM cleanup'); + } finally { + if (button) button.disabled = false; } } + + async cleanupPreview(event) { + if (event) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + + const button = event ? event.currentTarget : null; + if (button) button.disabled = true; + + try { + const data = await this.fetchWithErrorHandling(this.cleanupPreviewUrlValue, { method: 'POST' }); + + if (data.success) { + this.showSuccessMessage(data.message); + if (this.hasPreviewCountTarget) { + this.previewCountTarget.textContent = data.new_count; + } + if (data.new_count === 0 && this.hasPreviewButtonTarget) { + this.previewButtonTarget.remove(); + } + } else { + this.showErrorMessage(data.message || 'Preview cleanup failed'); + } + } catch (error) { + this.showErrorMessage(error.message || 'An unexpected error occurred during Preview cleanup'); + } finally { + if (button) button.disabled = false; + } + } + + getHeaders() { + return { + 'X-Requested-With': 'XMLHttpRequest', + 'Accept': 'application/json', + } + } + + async fetchWithErrorHandling(url, options = {}, timeout = 30000) { + const controller = new AbortController() + const timeoutId = setTimeout(() => controller.abort(), timeout) + + try { + const response = await fetch(url, { + ...options, + headers: { ...this.getHeaders(), ...options.headers }, + signal: controller.signal + }) + + clearTimeout(timeoutId) + + if (!response.ok) { + const errorText = await response.text() + let errorMessage = `Server error (${response.status})`; + try { + const errorJson = JSON.parse(errorText); + if (errorJson && errorJson.message) { + errorMessage = errorJson.message; + } + } catch (e) { + // Not a JSON response, use status text + errorMessage = `${errorMessage}: ${errorText}`; + } + throw new Error(errorMessage) + } + + return await response.json() + } catch (error) { + clearTimeout(timeoutId) + + if (error.name === 'AbortError') { + throw new Error('Request timed out. Please try again.') + } else if (error.message.includes('Failed to fetch')) { + throw new Error('Network error. Please check your connection and try again.') + } else { + throw error + } + } + } + + showSuccessMessage(message) { + this.showToast('success', message) + } + + showErrorMessage(message) { + this.showToast('error', message) + } + + showToast(type, message) { + // Create a simple alert that doesn't disrupt layout + const alertId = 'alert-' + Date.now(); + const iconClass = type === 'success' ? 'fa-check-circle' : 'fa-exclamation-triangle'; + const alertClass = type === 'success' ? 'alert-success' : 'alert-danger'; + + const alertHTML = ` + + `; + + // Add alert to body + document.body.insertAdjacentHTML('beforeend', alertHTML); + + // Auto-remove after 5 seconds if not closed manually + setTimeout(() => { + const elementToRemove = document.getElementById(alertId); + if (elementToRemove) { + elementToRemove.remove(); + } + }, 5000); + } } diff --git a/src/Controller/StatisticsController.php b/src/Controller/StatisticsController.php index e3b378f1..baec7467 100644 --- a/src/Controller/StatisticsController.php +++ b/src/Controller/StatisticsController.php @@ -43,11 +43,13 @@ namespace App\Controller; use App\Services\Tools\StatisticsHelper; use App\Entity\AssemblySystem\AssemblyBOMEntry; +use App\Entity\AssemblySystem\Assembly; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; +use Symfony\Contracts\Translation\TranslatorInterface; class StatisticsController extends AbstractController { @@ -62,31 +64,95 @@ class StatisticsController extends AbstractController } #[Route(path: '/statistics/cleanup-assembly-bom-entries', name: 'statistics_cleanup_assembly_bom_entries', methods: ['POST'])] - public function cleanupAssemblyBOMEntries(EntityManagerInterface $em): JsonResponse - { + public function cleanupAssemblyBOMEntries( + EntityManagerInterface $em, + StatisticsHelper $helper, + TranslatorInterface $translator + ): JsonResponse { $this->denyAccessUnlessGranted('@tools.statistics'); - $qb = $em->createQueryBuilder(); - $qb->select('be', 'IDENTITY(be.part) AS part_id') - ->from(AssemblyBOMEntry::class, 'be') - ->leftJoin('be.part', 'p') - ->where('be.part IS NOT NULL') - ->andWhere('p.id IS NULL'); + try { + // We fetch the IDs of the entries that have a non-existent part. + // We use a raw SQL approach or a more robust DQL to avoid proxy initialization issues. + $qb = $em->createQueryBuilder(); + $qb->select('be.id', 'IDENTITY(be.part) AS part_id') + ->from(AssemblyBOMEntry::class, 'be') + ->leftJoin('be.part', 'p') + ->where('be.part IS NOT NULL') + ->andWhere('p.id IS NULL'); - $results = $qb->getQuery()->getResult(); - $count = count($results); + $results = $qb->getQuery()->getResult(); + $count = count($results); - foreach ($results as $result) { - /** @var AssemblyBOMEntry $entry */ - $entry = $result[0]; - $part_id = $result['part_id'] ?? 'unknown'; + foreach ($results as $result) { + $entryId = $result['id']; + $partId = $result['part_id'] ?? 'unknown'; - $entry->setPart(null); - $entry->setName(sprintf('part-id=%s not found', $part_id)); + $entry = $em->find(AssemblyBOMEntry::class, $entryId); + if ($entry instanceof AssemblyBOMEntry) { + $entry->setPart(null); + $entry->setName(sprintf('part-id=%s not found', $partId)); + } + } + + $em->flush(); + + return new JsonResponse([ + 'success' => true, + 'count' => $count, + 'message' => $translator->trans('statistics.cleanup_assembly_bom_entries.success', [ + '%count%' => $count, + ]), + 'new_count' => $helper->getInvalidPartBOMEntriesCount(), + ]); + } catch (\Exception $e) { + return new JsonResponse([ + 'success' => false, + 'message' => $translator->trans('statistics.cleanup_assembly_bom_entries.error') . ' ' . $e->getMessage(), + ], Response::HTTP_INTERNAL_SERVER_ERROR); } + } - $em->flush(); + #[Route(path: '/statistics/cleanup-assembly-preview-attachments', name: 'statistics_cleanup_assembly_preview_attachments', methods: ['POST'])] + public function cleanupAssemblyPreviewAttachments( + EntityManagerInterface $em, + StatisticsHelper $helper, + TranslatorInterface $translator + ): JsonResponse { + $this->denyAccessUnlessGranted('@tools.statistics'); - return new JsonResponse(['success' => true, 'count' => $count]); + try { + $qb = $em->createQueryBuilder(); + $qb->select('a') + ->from(Assembly::class, 'a') + ->leftJoin('a.master_picture_attachment', 'm') + ->where('a.master_picture_attachment IS NOT NULL') + ->andWhere('m.id IS NULL'); + + $assemblies = $qb->getQuery()->getResult(); + $count = count($assemblies); + + foreach ($assemblies as $assembly) { + if ($assembly instanceof Assembly) { + $assembly->setMasterPictureAttachment(null); + } + } + + $em->flush(); + + return new JsonResponse([ + 'success' => true, + 'count' => $count, + 'message' => $translator->trans('statistics.cleanup_assembly_preview_attachments.success', [ + '%count%' => $count, + ]), + 'new_count' => $helper->getInvalidAssemblyPreviewAttachmentsCount(), + ]); + } catch (\Exception $e) { + return new JsonResponse([ + 'success' => false, + 'message' => $translator->trans('statistics.cleanup_assembly_preview_attachments.error') . ' ' . $e->getMessage(), + ], Response::HTTP_INTERNAL_SERVER_ERROR); + } } } diff --git a/src/Entity/Attachments/AssemblyAttachment.php b/src/Entity/Attachments/AssemblyAttachment.php index bb9a11c8..c0c75c18 100644 --- a/src/Entity/Attachments/AssemblyAttachment.php +++ b/src/Entity/Attachments/AssemblyAttachment.php @@ -33,7 +33,6 @@ use Symfony\Component\Serializer\Attribute\Context; * @extends Attachment */ #[UniqueEntity(['name', 'attachment_type', 'element'])] -#[UniqueEntity(['name', 'attachment_type', 'element'])] #[ORM\Entity] class AssemblyAttachment extends Attachment { diff --git a/src/Services/Tools/StatisticsHelper.php b/src/Services/Tools/StatisticsHelper.php index a3da3fde..653d9635 100644 --- a/src/Services/Tools/StatisticsHelper.php +++ b/src/Services/Tools/StatisticsHelper.php @@ -190,4 +190,19 @@ class StatisticsHelper return (int) $qb->getQuery()->getSingleScalarResult(); } + + /** + * Returns the number of assemblies that have a master_picture_attachment that does not exist anymore. + */ + public function getInvalidAssemblyPreviewAttachmentsCount(): int + { + $qb = $this->em->createQueryBuilder(); + $qb->select('COUNT(a.id)') + ->from(Assembly::class, 'a') + ->leftJoin('a.master_picture_attachment', 'at') + ->where('a.master_picture_attachment IS NOT NULL') + ->andWhere('at.id IS NULL'); + + return (int) $qb->getQuery()->getSingleScalarResult(); + } } diff --git a/templates/tools/statistics/statistics.html.twig b/templates/tools/statistics/statistics.html.twig index ed817cbe..ed787270 100644 --- a/templates/tools/statistics/statistics.html.twig +++ b/templates/tools/statistics/statistics.html.twig @@ -64,10 +64,8 @@
@@ -85,14 +83,25 @@ + + + +
{% trans %}statistics.invalid_part_bom_entries_count{% endtrans %} - {{ helper.invalidPartBOMEntriesCount }} + {{ helper.invalidPartBOMEntriesCount }} {% if helper.invalidPartBOMEntriesCount > 0 %} - {% endif %}
{% trans %}statistics.invalid_assembly_preview_attachments_count{% endtrans %} + {{ helper.invalidAssemblyPreviewAttachmentsCount }} + {% if helper.invalidAssemblyPreviewAttachmentsCount > 0 %} + + {% endif %} +
diff --git a/translations/frontend.cs.xlf b/translations/frontend.cs.xlf index 4ba1f913..6c9011f8 100644 --- a/translations/frontend.cs.xlf +++ b/translations/frontend.cs.xlf @@ -49,6 +49,18 @@ Velmi silné + + + assembly.labelp + Sestavy + + + + + project.labelp + Projekty + + search.submit diff --git a/translations/frontend.da.xlf b/translations/frontend.da.xlf index 4b6a15b9..2e3807fa 100644 --- a/translations/frontend.da.xlf +++ b/translations/frontend.da.xlf @@ -49,6 +49,18 @@ Meget stærk + + + assembly.labelp + Samlinger + + + + + project.labelp + Projekter + + search.submit diff --git a/translations/frontend.de.xlf b/translations/frontend.de.xlf index 9ebd0d32..9479cc48 100644 --- a/translations/frontend.de.xlf +++ b/translations/frontend.de.xlf @@ -49,6 +49,18 @@ Sehr stark + + + assembly.labelp + Baugruppen + + + + + project.labelp + Projekte + + search.submit diff --git a/translations/frontend.el.xlf b/translations/frontend.el.xlf index bab41358..f8e55b3e 100644 --- a/translations/frontend.el.xlf +++ b/translations/frontend.el.xlf @@ -2,10 +2,22 @@ - - search.placeholder - Αναζήτηση - - + + search.placeholder + Αναζήτηση + + + + + assembly.labelp + Συναρμολογήσεις + + + + + project.labelp + Έργα + + - \ No newline at end of file + diff --git a/translations/frontend.en.xlf b/translations/frontend.en.xlf index 91617f79..55712493 100644 --- a/translations/frontend.en.xlf +++ b/translations/frontend.en.xlf @@ -49,6 +49,18 @@ Very strong + + + assembly.labelp + Assemblies + + + + + project.labelp + Projects + + search.submit diff --git a/translations/frontend.es.xlf b/translations/frontend.es.xlf index 7d339959..3093e719 100644 --- a/translations/frontend.es.xlf +++ b/translations/frontend.es.xlf @@ -49,6 +49,18 @@ Muy fuerte + + + assembly.labelp + Ensamblajes + + + + + project.labelp + Proyectos + + search.submit diff --git a/translations/frontend.fr.xlf b/translations/frontend.fr.xlf index 5ebfca51..49660bd4 100644 --- a/translations/frontend.fr.xlf +++ b/translations/frontend.fr.xlf @@ -49,6 +49,18 @@ Très fort + + + assembly.labelp + Assemblages + + + + + project.labelp + Projets + + search.submit diff --git a/translations/frontend.hu.xlf b/translations/frontend.hu.xlf index c303dedc..c1d1c393 100644 --- a/translations/frontend.hu.xlf +++ b/translations/frontend.hu.xlf @@ -49,6 +49,18 @@ Nagyon erős + + + assembly.labelp + Összeállítások + + + + + project.labelp + Projektek + + search.submit diff --git a/translations/frontend.it.xlf b/translations/frontend.it.xlf index f163e3e2..02bcfb09 100644 --- a/translations/frontend.it.xlf +++ b/translations/frontend.it.xlf @@ -49,6 +49,18 @@ Molto forte + + + assembly.labelp + Assemblaggi + + + + + project.labelp + Progetti + + search.submit diff --git a/translations/frontend.ja.xlf b/translations/frontend.ja.xlf index 90ffdf5f..327c4778 100644 --- a/translations/frontend.ja.xlf +++ b/translations/frontend.ja.xlf @@ -2,22 +2,34 @@ - - search.placeholder - 検索 - - + + search.placeholder + 検索 + + - - part.labelp - 部品 - - + + part.labelp + 部品 + + - - search.submit - 検索 - - + + search.submit + 検索 + + + + + assembly.labelp + アセンブリ一覧 + + + + + project.labelp + プロジェクト + + - \ No newline at end of file + diff --git a/translations/frontend.nl.xlf b/translations/frontend.nl.xlf index 13187f62..c3b30ed9 100644 --- a/translations/frontend.nl.xlf +++ b/translations/frontend.nl.xlf @@ -2,10 +2,22 @@ - - search.placeholder - Zoeken - - + + search.placeholder + Zoeken + + + + + assembly.labelp + Assemblages + + + + + project.labelp + Projecten + + - \ No newline at end of file + diff --git a/translations/frontend.pl.xlf b/translations/frontend.pl.xlf index fface684..2e50305e 100644 --- a/translations/frontend.pl.xlf +++ b/translations/frontend.pl.xlf @@ -49,6 +49,18 @@ Bardzo mocne + + + assembly.labelp + Zespoły + + + + + project.labelp + Projekty + + search.submit diff --git a/translations/frontend.ru.xlf b/translations/frontend.ru.xlf index f4665a74..f84e1a61 100644 --- a/translations/frontend.ru.xlf +++ b/translations/frontend.ru.xlf @@ -49,6 +49,18 @@ Очень сильный + + + assembly.labelp + Сборки + + + + + project.labelp + Проекты + + search.submit diff --git a/translations/frontend.uk.xlf b/translations/frontend.uk.xlf index fee1b03e..748bac5c 100644 --- a/translations/frontend.uk.xlf +++ b/translations/frontend.uk.xlf @@ -49,6 +49,18 @@ Дуже надійний + + + assembly.labelp + Збірки + + + + + project.labelp + Проєкти + + search.submit diff --git a/translations/frontend.zh.xlf b/translations/frontend.zh.xlf index 8bb063b8..0159f8f2 100644 --- a/translations/frontend.zh.xlf +++ b/translations/frontend.zh.xlf @@ -49,6 +49,18 @@ 非常强 + + + assembly.labelp + 装配列表 + + + + + project.labelp + 项目 + + search.submit diff --git a/translations/messages.cs.xlf b/translations/messages.cs.xlf index 9dff3038..8e398a65 100644 --- a/translations/messages.cs.xlf +++ b/translations/messages.cs.xlf @@ -1845,25 +1845,19 @@ Související prvky budou přesunuty nahoru. Projekty - + statistics.cleanup_assembly_bom_entries.error Při čištění došlo k chybě. - + statistics.cleanup_assembly_bom_entries.success %count% položek bylo úspěšně vyčištěno. - - - statistics.cleanup_assembly_bom_entries.confirm - Chcete vyčistit všechny neplatné položky kusovníku? Odkaz na díl bude odstraněn a název nastaven na "part-id=id not found". - - - + statistics.cleanup_assembly_bom_entries.button Vyčistit @@ -12320,14 +12314,38 @@ Vezměte prosím na vědomí, že se nemůžete vydávat za uživatele se zakáz Uživatelé - - - Do not remove! Used for datatables rendering. - - - datatable.datatable.lengthMenu - _MENU_ - - + + + Do not remove! Used for datatables rendering. + + + datatable.datatable.lengthMenu + _MENU_ + + + + + statistics.invalid_assembly_preview_attachments_count + Invalid assembly preview attachments (attachment not found) + + + + + statistics.cleanup_assembly_preview_attachments.button + Cleanup + + + + + statistics.cleanup_assembly_preview_attachments.success + %count% entries were successfully cleaned up. + + + + + statistics.cleanup_assembly_preview_attachments.error + An error occurred during cleanup. + + - \ No newline at end of file + diff --git a/translations/messages.da.xlf b/translations/messages.da.xlf index a125c32f..4e186e35 100644 --- a/translations/messages.da.xlf +++ b/translations/messages.da.xlf @@ -1803,25 +1803,19 @@ Underelementer vil blive flyttet opad. Projekter - + statistics.cleanup_assembly_bom_entries.error Der opstod en fejl under oprydningen. - + statistics.cleanup_assembly_bom_entries.success %count% poster blev ryddet op. - - - statistics.cleanup_assembly_bom_entries.confirm - Vil du rydde op i alle ugyldige stykliste-poster? Forbindelsen til delen vil blive slettet, og navnet sat til "part-id=id not found". - - - + statistics.cleanup_assembly_bom_entries.button Ryd op @@ -13748,5 +13742,29 @@ Buerklin API-godkendelsesserver: 10 anmodninger/minut pr. IP-adresse Opdatér til + + + statistics.invalid_assembly_preview_attachments_count + Invalid assembly preview attachments (attachment not found) + + + + + statistics.cleanup_assembly_preview_attachments.button + Cleanup + + + + + statistics.cleanup_assembly_preview_attachments.success + %count% entries were successfully cleaned up. + + + + + statistics.cleanup_assembly_preview_attachments.error + An error occurred during cleanup. + + diff --git a/translations/messages.de.xlf b/translations/messages.de.xlf index 5c7986dc..f8dff6f7 100644 --- a/translations/messages.de.xlf +++ b/translations/messages.de.xlf @@ -1826,25 +1826,19 @@ Subelemente werden beim Löschen nach oben verschoben. Ungültige Stücklisteneinträge (Teil nicht gefunden) - + statistics.cleanup_assembly_bom_entries.button Bereinigen - - - statistics.cleanup_assembly_bom_entries.confirm - Möchten Sie alle ungültigen Stücklisteneinträge bereinigen? Die Verknüpfung zum Teil wird gelöscht und der Name auf "part-id=id not found" gesetzt. - - - + statistics.cleanup_assembly_bom_entries.success %count% Einträge wurden erfolgreich bereinigt. - + statistics.cleanup_assembly_bom_entries.error Bei der Bereinigung ist ein Fehler aufgetreten. @@ -13121,7 +13115,7 @@ Bitte beachten Sie, dass dieses System derzeit experimentell ist und die hier de settings.ips.buerklin.help Buerklin-API-Zugriffsbeschränkungen: 100 Requests/Minute pro IP-Adresse -Buerklin-API-Authentication-Server: +Buerklin-API-Authentication-Server: 10 Requests/Minute pro IP-Adresse @@ -13887,5 +13881,29 @@ Buerklin-API-Authentication-Server: Letzte Inventur + + + statistics.invalid_assembly_preview_attachments_count + Ungültige Baugruppen-Vorschaubilder (Anhang nicht gefunden) + + + + + statistics.cleanup_assembly_preview_attachments.button + Bereinigen + + + + + statistics.cleanup_assembly_preview_attachments.success + %count% Einträge wurden erfolgreich bereinigt. + + + + + statistics.cleanup_assembly_preview_attachments.error + Bei der Bereinigung ist ein Fehler aufgetreten. + + diff --git a/translations/messages.el.xlf b/translations/messages.el.xlf index 9995d942..f9cf770f 100644 --- a/translations/messages.el.xlf +++ b/translations/messages.el.xlf @@ -1883,25 +1883,19 @@ Έργα - + statistics.cleanup_assembly_bom_entries.error Παρουσιάστηκε σφάλμα κατά την εκκαθάριση. - + statistics.cleanup_assembly_bom_entries.success %count% εγγραφές εκκαθαρίστηκαν με επιτυχία. - - - statistics.cleanup_assembly_bom_entries.confirm - Θέλετε να εκκαθαρίσετε όλες τις μη έγκυρες εγγραφές BOM; Ο σύνδεσμος προς το εξάρτημα θα διαγραφεί και το όνομα θα οριστεί σε "part-id=id not found". - - - + statistics.cleanup_assembly_bom_entries.button Εκκαθάριση @@ -1925,5 +1919,29 @@ Αριθμός [[Assembly]] + + + statistics.invalid_assembly_preview_attachments_count + Invalid assembly preview attachments (attachment not found) + + + + + statistics.cleanup_assembly_preview_attachments.button + Cleanup + + + + + statistics.cleanup_assembly_preview_attachments.success + %count% entries were successfully cleaned up. + + + + + statistics.cleanup_assembly_preview_attachments.error + An error occurred during cleanup. + + diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 47896b4e..b7757644 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -1827,25 +1827,19 @@ Sub elements will be moved upwards. Invalid BOM entries (part not found) - + statistics.cleanup_assembly_bom_entries.button Cleanup - - - statistics.cleanup_assembly_bom_entries.confirm - Do you want to cleanup all invalid BOM entries? The link to the part will be removed and the name set to "part-id=id not found". - - - + statistics.cleanup_assembly_bom_entries.success %count% entries were successfully cleaned up. - + statistics.cleanup_assembly_bom_entries.error An error occurred during cleanup. @@ -13781,6 +13775,30 @@ Buerklin-API Authentication server: Update to + + + statistics.invalid_assembly_preview_attachments_count + Invalid assembly preview attachments (attachment not found) + + + + + statistics.cleanup_assembly_preview_attachments.button + Cleanup + + + + + statistics.cleanup_assembly_preview_attachments.success + %count% entries were successfully cleaned up. + + + + + statistics.cleanup_assembly_preview_attachments.error + An error occurred during cleanup. + + part.gtin diff --git a/translations/messages.es.xlf b/translations/messages.es.xlf index b03886bb..a29fe277 100644 --- a/translations/messages.es.xlf +++ b/translations/messages.es.xlf @@ -1845,25 +1845,19 @@ Subelementos serán desplazados hacia arriba. Proyectos - + statistics.cleanup_assembly_bom_entries.error Ocurrió un error durante la limpieza. - + statistics.cleanup_assembly_bom_entries.success %count% entradas se limpiaron con éxito. - - - statistics.cleanup_assembly_bom_entries.confirm - ¿Desea limpiar todas las entradas de lista de materiales no válidas? El enlace a la pieza se eliminará y el nombre se establecerá en "part-id=id not found". - - - + statistics.cleanup_assembly_bom_entries.button Limpiar @@ -11098,5 +11092,29 @@ Por favor ten en cuenta que no puedes personificar a un usuario deshabilitado. S _MENU_ + + + statistics.invalid_assembly_preview_attachments_count + Invalid assembly preview attachments (attachment not found) + + + + + statistics.cleanup_assembly_preview_attachments.button + Cleanup + + + + + statistics.cleanup_assembly_preview_attachments.success + %count% entries were successfully cleaned up. + + + + + statistics.cleanup_assembly_preview_attachments.error + An error occurred during cleanup. + + - \ No newline at end of file + diff --git a/translations/messages.fr.xlf b/translations/messages.fr.xlf index 63159e5a..68a45b3f 100644 --- a/translations/messages.fr.xlf +++ b/translations/messages.fr.xlf @@ -1828,25 +1828,19 @@ Show/Hide sidebar Projets - + statistics.cleanup_assembly_bom_entries.error Une erreur est survenue lors du nettoyage. - + statistics.cleanup_assembly_bom_entries.success %count% entrées ont été nettoyées avec succès. - - - statistics.cleanup_assembly_bom_entries.confirm - Voulez-vous nettoyer toutes les entrées de nomenclature non valides ? Le lien vers la pièce sera supprimé et le nom sera défini sur "part-id=id not found". - - - + statistics.cleanup_assembly_bom_entries.button Nettoyer @@ -7554,7 +7548,31 @@ exemple de ville datatable.datatable.lengthMenu _MENU_ - + + + + + statistics.invalid_assembly_preview_attachments_count + Invalid assembly preview attachments (attachment not found) + + + + + statistics.cleanup_assembly_preview_attachments.button + Cleanup + + + + + statistics.cleanup_assembly_preview_attachments.success + %count% entries were successfully cleaned up. + + + + + statistics.cleanup_assembly_preview_attachments.error + An error occurred during cleanup. + - \ No newline at end of file + diff --git a/translations/messages.hu.xlf b/translations/messages.hu.xlf index b754bb4a..2cc63004 100644 --- a/translations/messages.hu.xlf +++ b/translations/messages.hu.xlf @@ -1756,25 +1756,19 @@ Projektek - + statistics.cleanup_assembly_bom_entries.error Hiba történt a tisztítás során. - + statistics.cleanup_assembly_bom_entries.success %count% tétel sikeresen törölve. - - - statistics.cleanup_assembly_bom_entries.confirm - Szeretné törölni az összes érvénytelen darabjegyzék tételt? Az alkatrészre mutató hivatkozás törlődik, a név pedig "part-id=id not found" lesz. - - - + statistics.cleanup_assembly_bom_entries.button Tisztítás @@ -11525,7 +11519,31 @@ datatable.datatable.lengthMenu _MENU_ - + + + + + statistics.invalid_assembly_preview_attachments_count + Invalid assembly preview attachments (attachment not found) + + + + + statistics.cleanup_assembly_preview_attachments.button + Cleanup + + + + + statistics.cleanup_assembly_preview_attachments.success + %count% entries were successfully cleaned up. + + + + + statistics.cleanup_assembly_preview_attachments.error + An error occurred during cleanup. + - \ No newline at end of file + diff --git a/translations/messages.it.xlf b/translations/messages.it.xlf index b2de4468..96121a4d 100644 --- a/translations/messages.it.xlf +++ b/translations/messages.it.xlf @@ -1845,25 +1845,19 @@ I sub elementi saranno spostati verso l'alto. Progetti - + statistics.cleanup_assembly_bom_entries.error Si è verificato un errore durante la pulizia. - + statistics.cleanup_assembly_bom_entries.success %count% voci sono state pulite con successo. - - - statistics.cleanup_assembly_bom_entries.confirm - Vuoi pulire tutte le voci della distinta base non valide? Il collegamento alla parte verrà rimosso e il nome impostato su "part-id=id not found". - - - + statistics.cleanup_assembly_bom_entries.button Pulisci @@ -11098,7 +11092,31 @@ Notare che non è possibile impersonare un utente disattivato. Quando si prova a datatable.datatable.lengthMenu _MENU_ - + + + + + statistics.invalid_assembly_preview_attachments_count + Invalid assembly preview attachments (attachment not found) + + + + + statistics.cleanup_assembly_preview_attachments.button + Cleanup + + + + + statistics.cleanup_assembly_preview_attachments.success + %count% entries were successfully cleaned up. + + + + + statistics.cleanup_assembly_preview_attachments.error + An error occurred during cleanup. + - \ No newline at end of file + diff --git a/translations/messages.ja.xlf b/translations/messages.ja.xlf index bd7119ab..c98355db 100644 --- a/translations/messages.ja.xlf +++ b/translations/messages.ja.xlf @@ -1828,25 +1828,19 @@ プロジェクト - + statistics.cleanup_assembly_bom_entries.error クリーンアップ中にエラーが発生しました。 - + statistics.cleanup_assembly_bom_entries.success %count% 個のエントリが正常にクリーンアップされました。 - - - statistics.cleanup_assembly_bom_entries.confirm - すべての無効な部品表エントリをクリーンアップしますか?部品へのリンクは削除され、名前は "part-id=id not found" に設定されます。 - - - + statistics.cleanup_assembly_bom_entries.button クリーンアップ @@ -7273,7 +7267,31 @@ Exampletown datatable.datatable.lengthMenu _MENU_ - + + + + + statistics.invalid_assembly_preview_attachments_count + Invalid assembly preview attachments (attachment not found) + + + + + statistics.cleanup_assembly_preview_attachments.button + Cleanup + + + + + statistics.cleanup_assembly_preview_attachments.success + %count% entries were successfully cleaned up. + + + + + statistics.cleanup_assembly_preview_attachments.error + An error occurred during cleanup. + - \ No newline at end of file + diff --git a/translations/messages.nl.xlf b/translations/messages.nl.xlf index cf022030..650b1cec 100644 --- a/translations/messages.nl.xlf +++ b/translations/messages.nl.xlf @@ -1560,25 +1560,19 @@ Projecten - + statistics.cleanup_assembly_bom_entries.error Er is een fout opgetreden tijdens het opschonen. - + statistics.cleanup_assembly_bom_entries.success %count% regels zijn succesvol opgeschoond. - - - statistics.cleanup_assembly_bom_entries.confirm - Wilt u alle ongeldige stuklijstregels opschonen? De koppeling naar het onderdeel wordt verwijderd en de naam wordt ingesteld op "part-id=id not found". - - - + statistics.cleanup_assembly_bom_entries.button Opschonen @@ -1602,5 +1596,29 @@ Aantal [[Assembly]] + + + statistics.invalid_assembly_preview_attachments_count + Invalid assembly preview attachments (attachment not found) + + + + + statistics.cleanup_assembly_preview_attachments.button + Cleanup + + + + + statistics.cleanup_assembly_preview_attachments.success + %count% entries were successfully cleaned up. + + + + + statistics.cleanup_assembly_preview_attachments.error + An error occurred during cleanup. + + diff --git a/translations/messages.pl.xlf b/translations/messages.pl.xlf index f253417e..4b981e2c 100644 --- a/translations/messages.pl.xlf +++ b/translations/messages.pl.xlf @@ -1842,25 +1842,19 @@ Po usunięciu pod elementy zostaną przeniesione na górę. Projekty - + statistics.cleanup_assembly_bom_entries.error Wystąpił błąd podczas czyszczenia. - + statistics.cleanup_assembly_bom_entries.success Pomyślnie wyczyszczono %count% wpisów. - - - statistics.cleanup_assembly_bom_entries.confirm - Czy chcesz wyczyścić wszystkie nieprawidłowe wpisy w zestawieniu? Link do części zostanie usunięty, a nazwa ustawiona na "part-id=id not found". - - - + statistics.cleanup_assembly_bom_entries.button Wyczyść @@ -10943,7 +10937,31 @@ Należy pamiętać, że nie możesz udawać nieaktywnych użytkowników. Jeśli datatable.datatable.lengthMenu _MENU_ - + + + + + statistics.invalid_assembly_preview_attachments_count + Invalid assembly preview attachments (attachment not found) + + + + + statistics.cleanup_assembly_preview_attachments.button + Cleanup + + + + + statistics.cleanup_assembly_preview_attachments.success + %count% entries were successfully cleaned up. + + + + + statistics.cleanup_assembly_preview_attachments.error + An error occurred during cleanup. + - \ No newline at end of file + diff --git a/translations/messages.ru.xlf b/translations/messages.ru.xlf index bf0ec4f5..45cedc02 100644 --- a/translations/messages.ru.xlf +++ b/translations/messages.ru.xlf @@ -1846,25 +1846,19 @@ Проекты - + statistics.cleanup_assembly_bom_entries.error Произошла ошибка при очистке. - + statistics.cleanup_assembly_bom_entries.success %count% записей успешно очищено. - - - statistics.cleanup_assembly_bom_entries.confirm - Вы хотите очистить все неверные записи в спецификации? Ссылка на деталь будет удалена, а имя установлено в "part-id=id not found". - - - + statistics.cleanup_assembly_bom_entries.button Очистить @@ -11043,7 +11037,31 @@ datatable.datatable.lengthMenu _MENU_ - + + + + + statistics.invalid_assembly_preview_attachments_count + Invalid assembly preview attachments (attachment not found) + + + + + statistics.cleanup_assembly_preview_attachments.button + Cleanup + + + + + statistics.cleanup_assembly_preview_attachments.success + %count% entries were successfully cleaned up. + + + + + statistics.cleanup_assembly_preview_attachments.error + An error occurred during cleanup. + - \ No newline at end of file + diff --git a/translations/messages.zh.xlf b/translations/messages.zh.xlf index 6b319f8b..e3ed318b 100644 --- a/translations/messages.zh.xlf +++ b/translations/messages.zh.xlf @@ -1845,25 +1845,19 @@ 项目 - + statistics.cleanup_assembly_bom_entries.error 清理过程中发生错误。 - + statistics.cleanup_assembly_bom_entries.success 成功清理了 %count% 条条目。 - - - statistics.cleanup_assembly_bom_entries.confirm - 您想清理所有无效的物料清单条目吗?部件链接将被删除,名称将设置为 "part-id=id not found"。 - - - + statistics.cleanup_assembly_bom_entries.button 清理 @@ -10928,7 +10922,31 @@ Element 3 datatable.datatable.lengthMenu _MENU_ - + + + + + statistics.invalid_assembly_preview_attachments_count + Invalid assembly preview attachments (attachment not found) + + + + + statistics.cleanup_assembly_preview_attachments.button + Cleanup + + + + + statistics.cleanup_assembly_preview_attachments.success + %count% entries were successfully cleaned up. + + + + + statistics.cleanup_assembly_preview_attachments.error + An error occurred during cleanup. + - \ No newline at end of file +