diff --git a/inventory/routes/inventory.py b/inventory/routes/inventory.py index a78eecd..48855a1 100644 --- a/inventory/routes/inventory.py +++ b/inventory/routes/inventory.py @@ -214,6 +214,22 @@ def delete_inventory_item(id): @main.route("/api/inventory/export", methods=["POST"]) def get_inventory_csv(): + def export_value(item, col): + try: + match col: + case "brand": + return item.brand.name + case "location": + return item.location.full_name + case "owner": + return item.owner.full_name + case "type": + return item.item.description + case _: + return getattr(item, col, "") + except Exception: + return "" + data = request.get_json() ids = data.get('ids', []) @@ -225,13 +241,26 @@ def get_inventory_csv(): output = io.StringIO() writer = csv.writer(output) - model = Inventory - columns = [c.key for c in inspect(model).mapper.column_attrs] + columns = [ + "id", + "timestamp", + "condition", + "type", + "name", + "serial", + "model", + "notes", + "owner", + "brand", + "location", + "barcode", + "shared" + ] writer.writerow(columns) for item in rows: - writer.writerow([getattr(item, col) for col in columns]) + writer.writerow([export_value(item, col) for col in columns]) csv_string = output.getvalue() output.close() diff --git a/inventory/routes/user.py b/inventory/routes/user.py index a1fcad1..fb70c9a 100644 --- a/inventory/routes/user.py +++ b/inventory/routes/user.py @@ -1,3 +1,7 @@ +import base64 +import csv +import io + from flask import render_template, request, jsonify from . import main @@ -15,7 +19,8 @@ def list_users(): header = user_headers, rows = [{"id": user.id, "cells": [fn(user) for fn in user_headers.values()]} for user in users], title = "Users", - entry_route = 'user' + entry_route = 'user', + csv_route = 'user' ) @main.route("/user/") @@ -120,4 +125,53 @@ def update_user(id): except Exception as e: db.session.rollback() - return jsonify({"success": False, "error": str(e)}), 400 \ No newline at end of file + return jsonify({"success": False, "error": str(e)}), 400 + +@main.route("/api/user/export", methods=["POST"]) +def get_user_csv(): + def export_value(user, col): + try: + match col: + case "location": + return user.location.full_name + case "supervisor": + return user.supervisor.full_name + case _: + return getattr(user, col, "") + except Exception: + return "" + + data = request.get_json() + ids = data.get('ids', []) + + if not ids: + return jsonify({"success": False, "error": "No IDs provided"}), 400 + + rows = eager_load_user_relationships(db.session.query(User).filter(User.id.in_(ids))).all() + + output = io.StringIO() + writer = csv.writer(output) + + columns = [ + "id", + "staff", + "active", + "last_name", + "first_name", + "location", + "supervisor" + ] + + writer.writerow(columns) + + for user in rows: + writer.writerow([export_value(user, col) for col in columns]) + + csv_string = output.getvalue() + output.close() + + return jsonify({ + "success": True, + "csv": base64.b64encode(csv_string.encode()).decode(), + "count": len(rows) + }) \ No newline at end of file diff --git a/inventory/routes/worklog.py b/inventory/routes/worklog.py index 57aa884..3604cb6 100644 --- a/inventory/routes/worklog.py +++ b/inventory/routes/worklog.py @@ -1,4 +1,7 @@ +import base64 +import csv import datetime +import io from flask import request, render_template, jsonify @@ -9,15 +12,15 @@ from ..models import WorkLog, User, Inventory, WorkNote from ..utils.load import eager_load_worklog_relationships, eager_load_user_relationships, eager_load_inventory_relationships @main.route("/worklog") -def list_worklog(page=1): - page = request.args.get('page', default=1, type=int) +def list_worklog(): query = eager_load_worklog_relationships(db.session.query(WorkLog)) return render_template( 'table.html', header=worklog_headers, rows=[{"id": log.id, "cells": [fn(log) for fn in worklog_headers.values()]} for log in query.all()], title="Work Log", - entry_route='worklog_entry' + entry_route='worklog_entry', + csv_route='worklog' ) @main.route("/worklog/") @@ -143,3 +146,58 @@ def delete_worklog(id): except Exception as e: db.session.rollback() return jsonify({"success": False, "error": str(e)}), 400 + +@main.route("/api/worklog/export", methods=["POST"]) +def get_worklog_csv(): + def export_value(log, col): + try: + match col: + case "contact": + return log.contact.full_name + case "work_item": + return log.work_item.identifier + case "latest_update": + if log.updates: + return log.updates[-1].content + return "" + case _: + return getattr(log, col, "") + except Exception: + return "" + + data = request.get_json() + ids = data.get('ids', []) + + if not ids: + return jsonify({"success": False, "error": "No IDs provided"}), 400 + + rows = eager_load_worklog_relationships(db.session.query(WorkLog).filter(WorkLog.id.in_(ids))).all() + + output = io.StringIO() + writer = csv.writer(output) + + columns = [ + "id", + "start_time", + "end_time", + "complete", + "followup", + "contact", + "work_item", + "analysis", + "latest_update" + ] + + writer.writerow(columns) + + for user in rows: + writer.writerow([export_value(user, col) for col in columns]) + + csv_string = output.getvalue() + output.close() + + return jsonify({ + "success": True, + "csv": base64.b64encode(csv_string.encode()).decode(), + "count": len(rows) + }) \ No newline at end of file diff --git a/inventory/templates/table.html b/inventory/templates/table.html index 0211ca7..3945816 100644 --- a/inventory/templates/table.html +++ b/inventory/templates/table.html @@ -36,10 +36,10 @@ URL.revokeObjectURL(url); } else { - renderToast({ message: `Export failed: ${result.error}` }); + renderToast({ message: `Export failed: ${result.error}`, type: 'danger' }); } } catch (err) { - renderToast({ message: `Export failed: ${err}` }); + renderToast({ message: `Export failed: ${err}`, type: 'danger' }); } {% endset %} {% set toolbarButtons %}