assettrack/routes/upload.py

129 lines
4.4 KiB
Python

from flask import Blueprint, request, render_template, redirect, session, flash
from definitions.models import Asset, db
from functions.process_csv import get_csv_data
from functions.validate_values import validate_values
from config import item_attributes
upload_bp = Blueprint('uploadcsv', __name__)
def _process_csv_file(file, mode):
"""
Helper function to process CSV file and separate entries based on mode.
mode: 'import' or 'edit'
"""
# Extract CSV data
csvdata = get_csv_data(file)
# Validate each row of data
errors = []
for i, row in enumerate(csvdata, start=1):
error = validate_values(row)
if error:
errors.append(f"Row {i}: {error}")
if errors:
return None, errors
# Separate entries based on mode
primary_attrib = next((attrib for attrib in item_attributes if attrib.primary), None)
if not primary_attrib:
return None, ["Primary attribute not defined in configuration."]
new_entries = []
existing_entries = []
invalid_entries = []
for row in csvdata:
primary_value = row[primary_attrib.attrib_name]
asset_exists = Asset.query.filter_by(**{primary_attrib.attrib_name: primary_value}).first()
if mode == 'import':
if asset_exists:
invalid_entries.append(row) # Existing entries are invalid for import
else:
new_entries.append(row)
elif mode == 'edit':
if asset_exists:
existing_entries.append(row) # Existing entries are valid for edit
else:
invalid_entries.append(row) # Non-existing entries are invalid for edit
return {
'new_entries': new_entries,
'existing_entries': existing_entries,
'invalid_entries': invalid_entries
}, None
@upload_bp.route('/import_from_csv', methods=['GET', 'POST'])
def import_from_csv():
if request.method == 'POST':
# Check if a file was uploaded
if 'file' not in request.files:
flash("No file uploaded.", "error")
return redirect(request.url)
file = request.files['file']
# Check if the file is a CSV
if file.filename == '' or not file.filename.endswith('.csv'):
flash("Please upload a valid CSV file.", "error")
return redirect(request.url)
# Process the CSV file
result, errors = _process_csv_file(file, mode='import')
if errors:
for error in errors:
flash(error, "error")
return redirect(request.url)
# Store entries in session for further processing
session['new_entries'] = result['new_entries']
session['invalid_entries'] = result['invalid_entries']
# Redirect to preview page
return render_template(
'csv_preview.html',
new_entries=result['new_entries'],
invalid_entries=result['invalid_entries'],
item_attributes=item_attributes
)
# Render the upload page for GET requests
return render_template('upload.html', mode="addnew")
@upload_bp.route('/edit_using_csv', methods=['GET', 'POST'])
def edit_using_csv():
if request.method == 'POST':
# Check if a file was uploaded
if 'file' not in request.files:
flash("No file uploaded.", "error")
return redirect(request.url)
file = request.files['file']
# Check if the file is a CSV
if file.filename == '' or not file.filename.endswith('.csv'):
flash("Please upload a valid CSV file.", "error")
return redirect(request.url)
# Process the CSV file
result, errors = _process_csv_file(file, mode='edit')
if errors:
for error in errors:
flash(error, "error")
return redirect(request.url)
# Store entries in session for further processing
session['existing_entries'] = result['existing_entries']
session['invalid_entries'] = result['invalid_entries']
# Redirect to preview page
return render_template(
'csv_preview.html',
existing_entries=result['existing_entries'],
invalid_entries=result['invalid_entries'],
item_attributes=item_attributes
)
# Render the upload page for GET requests
return render_template('upload.html', mode="update")