diff --git a/README.md b/README.md index b2d6b12..40800df 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# AssetManager 0.5.5.83 +# AssetManager 0.5.5.84 AssetManager is a self-hosted web application for managing IT equipment and other organizational assets. It provides asset inventory, software inventory, remote job execution, reporting, privacy/retention documentation, and optional integration with MeshCentral. @@ -8,7 +8,7 @@ The project is licensed under the **Apache License 2.0** and may be used, modifi - configurable asset categories, fields, status values, images, and assignments - asset lists, detail views, history, bulk editing, Excel import/export, duplicate merging, and tree views -- hardware and software inventory with comparison and aggregation views +- hardware and software inventory with comparison, aggregation views, and Excel export - static Setup Analyzer for Windows installer technology, silent parameters, deployment-script export, and persistent software-package creation - install, uninstall, and reinstall software-package jobs with MeshCentral file transfer, callback tracking, process control, and optional post-install application launch - job definitions and remote job execution with status tracking, callbacks, retries, and logs diff --git a/VERSION b/VERSION index 1a6b779..6204fa0 100755 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.5.83 +0.5.5.84 diff --git a/app/i18n.py b/app/i18n.py index a5c42c3..c7193ca 100755 --- a/app/i18n.py +++ b/app/i18n.py @@ -931,7 +931,8 @@ BASE_TRANSLATIONS.update({ "software.summary_table": ("Aggregated entries", "Kumulierte Einträge"), "software.table_filter_help": ("Use the filter row below the column headings to narrow the list.", "Die Filterzeile unterhalb der Spaltenüberschriften grenzt die Liste ein."), "software.numeric_filter_help": ("Numeric columns support operators such as < 2, >= 5, 1..10 or 'between 1 and 10'.", "Numerische Spalten unterstützen Operatoren wie < 2, >= 5, 1..10 oder „zwischen 1 und 10“."), - "software.numeric_filter_placeholder": ("e.g. < 2 or 1..5", "z. B. < 2 oder 1..5") + "software.numeric_filter_placeholder": ("e.g. < 2 or 1..5", "z. B. < 2 oder 1..5"), + "software.export_excel": ("Export Excel", "Excel exportieren") }) diff --git a/app/main.py b/app/main.py index acba534..680845f 100755 --- a/app/main.py +++ b/app/main.py @@ -6200,6 +6200,91 @@ def software_installations_page(request: Request, db: Session = Depends(get_db)) return response +@app.get("/software/installations/export.xlsx") +def software_installations_export_excel(request: Request, db: Session = Depends(get_db)): + _require_admin(request) + language_code = _request_language(request) + software_entries = _software_installation_rows(db) + + headers = [ + translate(db, language_code, "common.assets", "Assets"), + translate(db, language_code, "common.name", "Name"), + translate(db, language_code, "about.version", "Version"), + translate(db, language_code, "software.publisher", "Publisher"), + translate(db, language_code, "software.architecture", "Architecture"), + translate(db, language_code, "software.platform", "Platform"), + translate(db, language_code, "software.install_date", "Installation date"), + translate(db, language_code, "software.last_seen", "Last seen"), + ] + + rows = [] + for entry in software_entries: + platform = str(entry.platform or "unknown") + rows.append([ + entry.asset_name or "", + entry.name or "", + entry.version or "", + entry.publisher or "", + entry.architecture or "", + translate(db, language_code, f"software.platform.{platform}", platform), + entry.install_date or "", + entry.last_seen_at or "", + ]) + + return _xlsx_response( + "assetmanager-software-installations.xlsx", + headers, + rows, + ) + + +@app.get("/software/summary/export.xlsx") +def software_summary_export_excel(request: Request, db: Session = Depends(get_db)): + _require_admin(request) + language_code = _request_language(request) + allowed_groupings = {"name_platform", "software", "version"} + grouping = str( + request.query_params.get("grouping") + or request.session.get("software_summary_grouping") + or "software" + ).strip().lower() + if grouping not in allowed_groupings: + grouping = "software" + + software_summary = _software_summary_rows(db, grouping) + + headers = [ + translate(db, language_code, "common.name", "Name"), + translate(db, language_code, "software.publisher", "Publisher"), + translate(db, language_code, "software.platform", "Platform"), + translate(db, language_code, "software.versions", "Versions"), + translate(db, language_code, "software.version_count", "Number of versions"), + translate(db, language_code, "software.unique_asset_count", "Unique assets"), + translate(db, language_code, "software.inventory_entry_count", "Inventory entries"), + translate(db, language_code, "software.last_seen", "Last seen"), + ] + + rows = [] + for row in software_summary: + platform = str(row.get("platform") or "unknown") + rows.append([ + row.get("name") or "", + row.get("publisher") or "", + translate(db, language_code, f"software.platform.{platform}", platform), + row.get("versions") or "", + row.get("version_count") or 0, + row.get("asset_count") or 0, + row.get("entries") or 0, + row.get("last_seen_at") or "", + ]) + + return _xlsx_response( + f"assetmanager-software-summary-{grouping}.xlsx", + headers, + rows, + ) + + @app.get("/software/summary") def software_summary_page(request: Request, db: Session = Depends(get_db)): _require_admin(request) diff --git a/app/templates/software_installations.html b/app/templates/software_installations.html index c827bb0..5964027 100755 --- a/app/templates/software_installations.html +++ b/app/templates/software_installations.html @@ -5,7 +5,10 @@
{{ t('software.all_installations_help') }}
- {{ t('common.back') }} +{{ t('software.aggregated_list_help') }}
- {{ t('common.back') }} +