78 lines
2.7 KiB
Python
78 lines
2.7 KiB
Python
import csv
|
|
import io
|
|
from flask import Blueprint, request, render_template, redirect, flash
|
|
from werkzeug.utils import secure_filename
|
|
from app.neo4j_utils import get_neo4j_handler
|
|
from plugins.plant.models import db, Plant, PlantCommon, PlantScientific
|
|
|
|
bp = Blueprint("importer", __name__, template_folder="templates")
|
|
|
|
@bp.route("/import/", methods=["GET", "POST"])
|
|
def upload():
|
|
if request.method == "POST":
|
|
file = request.files.get("file")
|
|
if not file:
|
|
flash("No file uploaded.", "error")
|
|
return redirect(request.url)
|
|
|
|
try:
|
|
# Handle UTF-8 BOM (Byte Order Mark) if present
|
|
decoded = file.read().decode("utf-8-sig")
|
|
stream = io.StringIO(decoded)
|
|
reader = csv.DictReader(stream)
|
|
|
|
neo = get_neo4j_handler()
|
|
|
|
for row in reader:
|
|
uuid = row.get("uuid")
|
|
name = row.get("name")
|
|
sci_name = row.get("scientific_name")
|
|
plant_type = row.get("plant_type", "plant")
|
|
mother_uuid = row.get("mother_uuid")
|
|
|
|
if not all([uuid, name, sci_name]):
|
|
continue # skip incomplete rows
|
|
|
|
# Common Name
|
|
common = PlantCommon.query.filter_by(name=name).first()
|
|
if not common:
|
|
common = PlantCommon(name=name)
|
|
db.session.add(common)
|
|
db.session.flush()
|
|
|
|
# Scientific Name
|
|
scientific = PlantScientific.query.filter_by(name=sci_name).first()
|
|
if not scientific:
|
|
scientific = PlantScientific(name=sci_name, common_id=common.id)
|
|
db.session.add(scientific)
|
|
db.session.flush()
|
|
|
|
# Plant
|
|
plant = Plant.query.filter_by(uuid=uuid).first()
|
|
if not plant:
|
|
plant = Plant(
|
|
uuid=uuid,
|
|
common_id=common.id,
|
|
scientific_id=scientific.id,
|
|
plant_type=plant_type
|
|
)
|
|
db.session.add(plant)
|
|
|
|
# Neo4j
|
|
neo.create_plant_node(uuid, name)
|
|
if mother_uuid and mother_uuid.strip():
|
|
neo.create_plant_node(mother_uuid.strip(), "Parent")
|
|
neo.create_lineage(uuid, mother_uuid.strip())
|
|
|
|
db.session.commit()
|
|
neo.close()
|
|
|
|
flash("CSV imported successfully with lineage.", "success")
|
|
|
|
except Exception as e:
|
|
flash(f"Import failed: {str(e)}", "error")
|
|
|
|
return redirect(request.url)
|
|
|
|
return render_template("importer/upload.html")
|