Trigger immediate Cove import on link and enrich run details
This commit is contained in:
parent
06abd8c7a3
commit
f68f92e63a
@ -59,6 +59,21 @@ STATUS_MAP: dict[int, str] = {
|
||||
12: "Warning", # Restarted
|
||||
}
|
||||
|
||||
# Mapping from Cove status code to readable label
|
||||
STATUS_LABELS: dict[int, str] = {
|
||||
1: "In process",
|
||||
2: "Failed",
|
||||
3: "Aborted",
|
||||
5: "Completed",
|
||||
6: "Interrupted",
|
||||
7: "Not started",
|
||||
8: "Completed with errors",
|
||||
9: "In progress with faults",
|
||||
10: "Over quota",
|
||||
11: "No selection",
|
||||
12: "Restarted",
|
||||
}
|
||||
|
||||
# Datasource label mapping (column prefix → human-readable label)
|
||||
DATASOURCE_LABELS: dict[str, str] = {
|
||||
"D1": "Files & Folders",
|
||||
@ -210,6 +225,16 @@ def _map_status(code: Any) -> str:
|
||||
return "Warning"
|
||||
|
||||
|
||||
def _status_label(code: Any) -> str:
|
||||
"""Map a Cove status code (int) to a human-readable label."""
|
||||
if code is None:
|
||||
return "Unknown"
|
||||
try:
|
||||
return STATUS_LABELS.get(int(code), f"Code {int(code)}")
|
||||
except (ValueError, TypeError):
|
||||
return "Unknown"
|
||||
|
||||
|
||||
def _ts_to_dt(value: Any) -> datetime | None:
|
||||
"""Convert a Unix timestamp (int or str) to a naive UTC datetime."""
|
||||
if value is None:
|
||||
@ -223,6 +248,13 @@ def _ts_to_dt(value: Any) -> datetime | None:
|
||||
return None
|
||||
|
||||
|
||||
def _fmt_utc(dt: datetime | None) -> str:
|
||||
"""Format a naive UTC datetime to readable text for run object messages."""
|
||||
if not dt:
|
||||
return "unknown"
|
||||
return dt.strftime("%Y-%m-%d %H:%M UTC")
|
||||
|
||||
|
||||
def run_cove_import(settings) -> tuple[int, int, int, int]:
|
||||
"""Fetch Cove account statistics and update the staging table + JobRuns.
|
||||
|
||||
@ -381,13 +413,20 @@ def _process_account(account: dict) -> bool:
|
||||
return False
|
||||
|
||||
status = _map_status(last_status_code)
|
||||
run_remark = (
|
||||
f"Cove account: {account_name or account_id} | "
|
||||
f"Computer: {computer_name or '-'} | "
|
||||
f"Customer: {customer_name or '-'} | "
|
||||
f"Last status: {_status_label(last_status_code)} ({last_status_code if last_status_code is not None else '-'}) | "
|
||||
f"Last run: {_fmt_utc(last_run_at)}"
|
||||
)
|
||||
|
||||
run = JobRun(
|
||||
job_id=job.id,
|
||||
mail_message_id=None,
|
||||
run_at=last_run_at,
|
||||
status=status,
|
||||
remark=None,
|
||||
remark=run_remark,
|
||||
missed=False,
|
||||
override_applied=False,
|
||||
source_type="cove_api",
|
||||
@ -422,6 +461,11 @@ def _persist_datasource_objects(
|
||||
continue
|
||||
|
||||
status = _map_status(status_code)
|
||||
ds_last_ts = _ts_to_dt(flat.get(f"{ds_prefix}F15"))
|
||||
status_msg = (
|
||||
f"Cove datasource status: {_status_label(status_code)} "
|
||||
f"({status_code}); last session: {_fmt_utc(ds_last_ts)}"
|
||||
)
|
||||
|
||||
# Upsert customer_objects
|
||||
customer_object_id = conn.execute(
|
||||
@ -461,10 +505,11 @@ def _persist_datasource_objects(
|
||||
text(
|
||||
"""
|
||||
INSERT INTO run_object_links (run_id, customer_object_id, status, error_message, observed_at)
|
||||
VALUES (:run_id, :customer_object_id, :status, NULL, :observed_at)
|
||||
VALUES (:run_id, :customer_object_id, :status, :error_message, :observed_at)
|
||||
ON CONFLICT (run_id, customer_object_id)
|
||||
DO UPDATE SET
|
||||
status = EXCLUDED.status,
|
||||
error_message = EXCLUDED.error_message,
|
||||
observed_at = EXCLUDED.observed_at
|
||||
"""
|
||||
),
|
||||
@ -472,6 +517,7 @@ def _persist_datasource_objects(
|
||||
"run_id": run_id,
|
||||
"customer_object_id": customer_object_id,
|
||||
"status": status,
|
||||
"observed_at": observed_at,
|
||||
"error_message": status_msg,
|
||||
"observed_at": ds_last_ts or observed_at,
|
||||
},
|
||||
)
|
||||
|
||||
@ -9,6 +9,7 @@ import re
|
||||
|
||||
from .routes_shared import * # noqa: F401,F403
|
||||
from .routes_shared import _log_admin_event
|
||||
from ..cove_importer import CoveImportError, run_cove_import
|
||||
|
||||
from ..models import CoveAccount, Customer, Job, SystemSettings
|
||||
|
||||
@ -129,6 +130,8 @@ def cove_account_link(cove_account_db_id: int):
|
||||
|
||||
action = (request.form.get("action") or "").strip() # "create" or "link"
|
||||
|
||||
linked_job_name = ""
|
||||
|
||||
if action == "create":
|
||||
# Create a new job from the Cove account data
|
||||
customer_id_raw = (request.form.get("customer_id") or "").strip()
|
||||
@ -171,11 +174,8 @@ def cove_account_link(cove_account_db_id: int):
|
||||
f"Created job {job.id} and linked Cove account {cove_acc.account_id} ({cove_acc.account_name})",
|
||||
details=f"customer={customer.name}, job_name={job_name}",
|
||||
)
|
||||
flash(
|
||||
f"Job '{job_name}' created for customer '{customer.name}'. "
|
||||
"Runs will appear after the next Cove import.",
|
||||
"success",
|
||||
)
|
||||
linked_job_name = job_name
|
||||
flash(f"Job '{job_name}' created for customer '{customer.name}'.", "success")
|
||||
|
||||
elif action == "link":
|
||||
# Link to an existing job
|
||||
@ -204,14 +204,62 @@ def cove_account_link(cove_account_db_id: int):
|
||||
f"Linked Cove account {cove_acc.account_id} ({cove_acc.account_name}) to existing job {job.id}",
|
||||
details=f"job_name={job.job_name}",
|
||||
)
|
||||
flash(
|
||||
f"Cove account linked to job '{job.job_name}'. "
|
||||
"Runs will appear after the next Cove import.",
|
||||
"success",
|
||||
)
|
||||
linked_job_name = job.job_name or ""
|
||||
flash(f"Cove account linked to job '{job.job_name}'.", "success")
|
||||
|
||||
else:
|
||||
flash("Unknown action.", "warning")
|
||||
return redirect(url_for("main.cove_accounts"))
|
||||
|
||||
# Trigger an immediate import so the latest Cove run appears right away
|
||||
# after linking (instead of waiting for the next scheduled/manual import).
|
||||
settings = SystemSettings.query.first()
|
||||
if settings and getattr(settings, "cove_enabled", False):
|
||||
try:
|
||||
total, created, skipped, errors = run_cove_import(settings)
|
||||
_log_admin_event(
|
||||
"cove_import_after_link",
|
||||
(
|
||||
"Triggered immediate Cove import after account link. "
|
||||
f"accounts={total}, created={created}, skipped={skipped}, errors={errors}"
|
||||
),
|
||||
)
|
||||
if created > 0:
|
||||
flash(
|
||||
(
|
||||
f"Immediate import complete for '{linked_job_name}'. "
|
||||
f"New runs: {created} (accounts: {total}, skipped: {skipped}, errors: {errors})."
|
||||
),
|
||||
"success" if errors == 0 else "warning",
|
||||
)
|
||||
else:
|
||||
flash(
|
||||
(
|
||||
f"Immediate import complete for '{linked_job_name}', but no new run was found yet. "
|
||||
f"(accounts: {total}, skipped: {skipped}, errors: {errors})"
|
||||
),
|
||||
"info" if errors == 0 else "warning",
|
||||
)
|
||||
except CoveImportError as exc:
|
||||
_log_admin_event(
|
||||
"cove_import_after_link_error",
|
||||
f"Immediate Cove import after account link failed: {exc}",
|
||||
)
|
||||
flash(
|
||||
"Account linked, but immediate import failed. "
|
||||
"You can run import again from Cove settings.",
|
||||
"warning",
|
||||
)
|
||||
except Exception as exc:
|
||||
_log_admin_event(
|
||||
"cove_import_after_link_error",
|
||||
f"Unexpected immediate Cove import error after account link: {exc}",
|
||||
)
|
||||
flash(
|
||||
"Account linked, but immediate import encountered an unexpected error. "
|
||||
"You can run import again from Cove settings.",
|
||||
"warning",
|
||||
)
|
||||
|
||||
return redirect(url_for("main.cove_accounts"))
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user