2025-11-25 08:33:38 +00:00
|
|
|
from fastapi import FastAPI, BackgroundTasks
|
|
|
|
|
from qgis_bootstrap import start_qgis
|
2025-11-26 07:18:46 +00:00
|
|
|
from uuid import uuid4
|
2025-11-25 08:33:38 +00:00
|
|
|
# from cleansing_service import load_layer, cleansing_layer
|
|
|
|
|
from full_cleansing_service import load_layer, cleansing_layer
|
|
|
|
|
|
|
|
|
|
app = FastAPI()
|
|
|
|
|
|
|
|
|
|
qgs = start_qgis()
|
|
|
|
|
|
|
|
|
|
@app.get("/")
|
|
|
|
|
def root():
|
|
|
|
|
return {"status": "QGIS Cleansing API Running"}
|
|
|
|
|
|
|
|
|
|
@app.get("/clean/{table_name}")
|
|
|
|
|
def clean_table(table_name: str):
|
|
|
|
|
|
|
|
|
|
layer = load_layer(table_name)
|
|
|
|
|
if not layer.isValid():
|
|
|
|
|
return {"error": f"Table '{table_name}' tidak valid atau tidak ditemukan."}
|
|
|
|
|
|
|
|
|
|
print(layer)
|
|
|
|
|
result = cleansing_layer(layer)
|
|
|
|
|
|
|
|
|
|
summary = result["summary"]
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
"table": table_name,
|
|
|
|
|
"summary": summary,
|
|
|
|
|
"message": "Cleansing selesai"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.post("/process/{table_name}")
|
|
|
|
|
def process_table(table_name: str, background: BackgroundTasks):
|
2025-11-26 07:18:46 +00:00
|
|
|
job_id = uuid4().hex
|
|
|
|
|
background.add_task(run_clean_table, table_name, job_id)
|
|
|
|
|
return {
|
|
|
|
|
"status": "ACCEPTED",
|
|
|
|
|
"job_id": job_id,
|
|
|
|
|
"table": table_name
|
|
|
|
|
}
|
2025-11-25 08:33:38 +00:00
|
|
|
|
|
|
|
|
|
2025-11-26 07:18:46 +00:00
|
|
|
|
|
|
|
|
def run_clean_table(table_name: str, job_id: str):
|
2025-11-25 08:33:38 +00:00
|
|
|
print(f"\n=== Mulai cleansing untuk tabel: {table_name} ===")
|
|
|
|
|
|
|
|
|
|
layer = load_layer(table_name)
|
|
|
|
|
if not layer.isValid():
|
2025-11-26 07:18:46 +00:00
|
|
|
print(f"[ERROR] Table '{table_name}' tidak valid.")
|
2025-11-25 08:33:38 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
|
|
result = cleansing_layer(layer)
|
|
|
|
|
summary = result["summary"]
|
|
|
|
|
clean_layer = result["clean_layer"]
|
|
|
|
|
|
2025-11-26 07:18:46 +00:00
|
|
|
# STEP 1 — simpan hasil ke PostGIS
|
|
|
|
|
save_to_postgis(clean_layer, table_name)
|
|
|
|
|
|
|
|
|
|
# STEP 2 — kirim callback ke backend utama
|
|
|
|
|
callback_payload = {
|
|
|
|
|
"job_id": job_id,
|
|
|
|
|
"table": table_name,
|
|
|
|
|
"summary": summary,
|
|
|
|
|
"status": "FINISHED"
|
|
|
|
|
}
|
2025-11-25 08:33:38 +00:00
|
|
|
|
2025-11-26 07:18:46 +00:00
|
|
|
import requests
|
|
|
|
|
requests.post(
|
|
|
|
|
"http://backend-utama:8000/jobs/callback",
|
|
|
|
|
json=callback_payload
|
|
|
|
|
)
|
2025-11-25 08:33:38 +00:00
|
|
|
|
|
|
|
|
print(f"=== Cleansing selesai untuk tabel: {table_name} ===\n")
|
2025-11-26 07:18:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from qgis.core import (
|
|
|
|
|
QgsVectorLayer,
|
|
|
|
|
QgsVectorLayerExporter,
|
|
|
|
|
QgsDataSourceUri
|
|
|
|
|
)
|
|
|
|
|
from database import POSTGIS
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def save_to_postgis(clean_layer: QgsVectorLayer, table_name: str):
|
|
|
|
|
"""
|
|
|
|
|
Menghapus isi tabel dan menulis ulang hasil cleansing ke PostGIS.
|
|
|
|
|
Geometry harus MULTIPOLYGON dan SRID sudah benar.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
print(f"[DB] Menyimpan hasil cleansing ke tabel {table_name}")
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------
|
|
|
|
|
# 1. Build URI PostGIS target
|
|
|
|
|
# -------------------------------------------
|
|
|
|
|
uri = QgsDataSourceUri()
|
|
|
|
|
uri.setConnection(
|
|
|
|
|
POSTGIS['host'],
|
|
|
|
|
str(POSTGIS['port']),
|
|
|
|
|
POSTGIS['db'],
|
|
|
|
|
POSTGIS['user'],
|
|
|
|
|
POSTGIS['password']
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Nama schema & tabel
|
|
|
|
|
schema = "public"
|
|
|
|
|
uri.setDataSource(schema, table_name, "geom") # geometry column = geom
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------
|
|
|
|
|
# 2. Export layer ke PostGIS (replace mode)
|
|
|
|
|
# -------------------------------------------
|
|
|
|
|
|
|
|
|
|
options = QgsVectorLayerExporter.ExportOptions()
|
|
|
|
|
options.actionOnExistingFile = QgsVectorLayerExporter.ActionOnExistingFile.OverwriteLayer
|
|
|
|
|
|
|
|
|
|
err_code, err_msg = QgsVectorLayerExporter.exportLayer(
|
|
|
|
|
clean_layer, # layer input
|
|
|
|
|
uri.uri(), # postgis connection uri
|
|
|
|
|
"postgres", # provider
|
|
|
|
|
clean_layer.crs(), # CRS layer
|
|
|
|
|
options
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if err_code != QgsVectorLayerExporter.NoError:
|
|
|
|
|
print("[DB][ERROR] Gagal menyimpan:", err_msg)
|
|
|
|
|
else:
|
|
|
|
|
print("[DB] Berhasil update tabel", table_name)
|