Auto-commit local changes before build (2026-01-15 14:36:50)
This commit is contained in:
parent
49f6d41715
commit
49fd29a6f2
@ -1 +1 @@
|
||||
v20260115-11-autotask-companyname-unwrap
|
||||
v20260115-12-autotask-customers-refreshall-mappings
|
||||
|
||||
@ -259,6 +259,73 @@ def api_customer_autotask_mapping_refresh(customer_id: int):
|
||||
return jsonify({"status": "error", "message": str(exc) or "Refresh failed."}), 400
|
||||
|
||||
|
||||
@main_bp.post("/api/customers/autotask-mapping/refresh-all")
|
||||
@login_required
|
||||
@roles_required("admin", "operator")
|
||||
def api_customers_autotask_mapping_refresh_all():
|
||||
"""Refresh mapping status for all customers that have an Autotask company ID."""
|
||||
|
||||
from ..integrations.autotask.client import AutotaskError
|
||||
|
||||
customers = Customer.query.filter(Customer.autotask_company_id.isnot(None)).all()
|
||||
if not customers:
|
||||
return jsonify({"status": "ok", "refreshed": 0, "counts": {"ok": 0, "renamed": 0, "missing": 0, "invalid": 0}})
|
||||
|
||||
try:
|
||||
client = _get_autotask_client_or_raise()
|
||||
except Exception as exc:
|
||||
return jsonify({"status": "error", "message": str(exc) or "Autotask is not configured."}), 400
|
||||
|
||||
counts = {"ok": 0, "renamed": 0, "missing": 0, "invalid": 0}
|
||||
refreshed = 0
|
||||
|
||||
for c in customers:
|
||||
company_id = getattr(c, "autotask_company_id", None)
|
||||
if not company_id:
|
||||
continue
|
||||
try:
|
||||
company = client.get_company(int(company_id))
|
||||
name = _normalize_company_name(company)
|
||||
|
||||
prev = (getattr(c, "autotask_company_name", None) or "").strip()
|
||||
if prev and name and prev != name:
|
||||
c.autotask_company_name = name
|
||||
c.autotask_mapping_status = "renamed"
|
||||
counts["renamed"] += 1
|
||||
else:
|
||||
c.autotask_company_name = name
|
||||
c.autotask_mapping_status = "ok"
|
||||
counts["ok"] += 1
|
||||
c.autotask_last_sync_at = datetime.utcnow()
|
||||
refreshed += 1
|
||||
except AutotaskError as exc:
|
||||
try:
|
||||
code = getattr(exc, "status_code", None)
|
||||
except Exception:
|
||||
code = None
|
||||
|
||||
if code == 404:
|
||||
c.autotask_mapping_status = "invalid"
|
||||
counts["invalid"] += 1
|
||||
else:
|
||||
c.autotask_mapping_status = "missing"
|
||||
counts["missing"] += 1
|
||||
c.autotask_last_sync_at = datetime.utcnow()
|
||||
refreshed += 1
|
||||
except Exception:
|
||||
c.autotask_mapping_status = "missing"
|
||||
c.autotask_last_sync_at = datetime.utcnow()
|
||||
counts["missing"] += 1
|
||||
refreshed += 1
|
||||
|
||||
try:
|
||||
db.session.commit()
|
||||
return jsonify({"status": "ok", "refreshed": refreshed, "counts": counts})
|
||||
except Exception as exc:
|
||||
db.session.rollback()
|
||||
return jsonify({"status": "error", "message": str(exc) or "Failed to refresh all mappings."}), 400
|
||||
|
||||
|
||||
@main_bp.route("/customers/create", methods=["POST"])
|
||||
@login_required
|
||||
@roles_required("admin", "operator")
|
||||
|
||||
@ -19,6 +19,11 @@
|
||||
</form>
|
||||
|
||||
<a class="btn btn-outline-secondary btn-sm" href="{{ url_for('main.customers_export') }}">Export CSV</a>
|
||||
|
||||
{% if autotask_enabled and autotask_configured %}
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm" id="autotaskRefreshAllMappingsBtn" style="white-space: nowrap;">Refresh all Autotask mappings</button>
|
||||
<span class="small text-muted" id="autotaskRefreshAllMappingsMsg"></span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@ -219,6 +224,10 @@
|
||||
var nameInput = document.getElementById("edit_customer_name");
|
||||
var activeInput = document.getElementById("edit_customer_active");
|
||||
|
||||
// Top-level refresh-all (only present when integration is enabled/configured)
|
||||
var refreshAllBtn = document.getElementById("autotaskRefreshAllMappingsBtn");
|
||||
var refreshAllMsg = document.getElementById("autotaskRefreshAllMappingsMsg");
|
||||
|
||||
// Autotask mapping UI (only present when integration is enabled/configured)
|
||||
var atCurrent = document.getElementById("autotaskCurrentMapping");
|
||||
var atCurrentMeta = document.getElementById("autotaskCurrentMappingMeta");
|
||||
@ -233,6 +242,20 @@
|
||||
var currentCustomerId = null;
|
||||
var selectedCompanyId = null;
|
||||
|
||||
function setRefreshAllMsg(text, isError) {
|
||||
if (!refreshAllMsg) {
|
||||
return;
|
||||
}
|
||||
refreshAllMsg.textContent = text || "";
|
||||
if (isError) {
|
||||
refreshAllMsg.classList.remove("text-muted");
|
||||
refreshAllMsg.classList.add("text-danger");
|
||||
} else {
|
||||
refreshAllMsg.classList.remove("text-danger");
|
||||
refreshAllMsg.classList.add("text-muted");
|
||||
}
|
||||
}
|
||||
|
||||
function setMsg(text, isError) {
|
||||
if (!atMsg) {
|
||||
return;
|
||||
@ -302,6 +325,32 @@
|
||||
return data;
|
||||
}
|
||||
|
||||
if (refreshAllBtn) {
|
||||
refreshAllBtn.addEventListener("click", async function () {
|
||||
if (!confirm("Refresh mapping status for all mapped customers?")) {
|
||||
return;
|
||||
}
|
||||
refreshAllBtn.disabled = true;
|
||||
setRefreshAllMsg("Refreshing...", false);
|
||||
try {
|
||||
var data = await postJson("/api/customers/autotask-mapping/refresh-all", {});
|
||||
var counts = (data && data.counts) ? data.counts : null;
|
||||
if (counts) {
|
||||
setRefreshAllMsg(
|
||||
"Done. OK: " + (counts.ok || 0) + ", Renamed: " + (counts.renamed || 0) + ", Missing: " + (counts.missing || 0) + ", Invalid: " + (counts.invalid || 0) + ".",
|
||||
false
|
||||
);
|
||||
} else {
|
||||
setRefreshAllMsg("Done.", false);
|
||||
}
|
||||
window.location.reload();
|
||||
} catch (e) {
|
||||
setRefreshAllMsg(e && e.message ? e.message : "Refresh failed.", true);
|
||||
refreshAllBtn.disabled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var editButtons = document.querySelectorAll(".customer-edit-btn");
|
||||
editButtons.forEach(function (btn) {
|
||||
btn.addEventListener("click", function () {
|
||||
|
||||
@ -94,6 +94,12 @@ Changes:
|
||||
- Improved company lookup handling to support different response shapes (single item and collection wrappers).
|
||||
- Ensured the cached Autotask company name is stored and displayed consistently after mapping and refresh.
|
||||
|
||||
## v20260115-12-autotask-customers-refreshall-mappings
|
||||
|
||||
- Added a “Refresh all Autotask mappings” button on the Customers page to validate all mapped customers in one action.
|
||||
- Implemented a new backend endpoint to refresh mapping status for all customers with an Autotask Company ID and return a status summary (ok/renamed/missing/invalid).
|
||||
- Updated the Customers UI to call the refresh-all endpoint, show a short result summary, and reload to reflect updated mapping states.
|
||||
|
||||
***
|
||||
|
||||
## v0.1.21
|
||||
|
||||
Loading…
Reference in New Issue
Block a user