diff --git a/lib/towerops/gaiia.ex b/lib/towerops/gaiia.ex index e37da734..59478394 100644 --- a/lib/towerops/gaiia.ex +++ b/lib/towerops/gaiia.ex @@ -189,20 +189,14 @@ defmodule Towerops.Gaiia do @doc """ Suggest Towerops Devices that might match a Gaiia Inventory Item. - Matching strategies (in confidence order): - - IP address exact match (:high confidence) - - Name containment match (:low confidence) + Matches by IP address only (:high confidence). Name matching was removed + because inventory item names are model names (e.g. "ePMP 3000"), causing + every device of the same model to match incorrectly. - Returns a list of `%{entity: device, match_type: type, confidence: level}`, - sorted by confidence (high first). Each device appears at most once per match type. + Returns a list of `%{entity: device, match_type: "ip", confidence: :high}`. """ def suggest_device_matches(organization_id, %InventoryItem{} = item) do - ip_matches = find_ip_matches(organization_id, item.ip_address) - name_matches = find_name_matches(organization_id, item.name) - - (ip_matches ++ name_matches) - |> Enum.uniq_by(fn %{entity: d, match_type: t} -> {d.id, t} end) - |> Enum.sort_by(fn %{confidence: c} -> confidence_rank(c) end) + find_ip_matches(organization_id, item.ip_address) end defp find_ip_matches(_organization_id, nil), do: [] @@ -216,24 +210,6 @@ defmodule Towerops.Gaiia do |> Enum.map(fn device -> %{entity: device, match_type: "ip", confidence: :high} end) end - defp find_name_matches(_organization_id, nil), do: [] - defp find_name_matches(_organization_id, ""), do: [] - - defp find_name_matches(organization_id, name) do - search_term = "%#{name}%" - - Device - |> where(organization_id: ^organization_id) - |> where([d], ilike(d.name, ^search_term) or ilike(^name, fragment("'%' || ? || '%'", d.name))) - |> Repo.all() - |> Repo.preload(:site) - |> Enum.map(fn device -> %{entity: device, match_type: "name", confidence: :low} end) - end - - defp confidence_rank(:high), do: 0 - defp confidence_rank(:medium), do: 1 - defp confidence_rank(:low), do: 2 - # --- Aggregate Queries --- @doc "Sum subscriber count and MRR across all Gaiia network sites for an organization." diff --git a/lib/towerops/gaiia/client.ex b/lib/towerops/gaiia/client.ex index b9807070..e43b8b1e 100644 --- a/lib/towerops/gaiia/client.ex +++ b/lib/towerops/gaiia/client.ex @@ -112,6 +112,14 @@ defmodule Towerops.Gaiia.Client do ... on NetworkSite { id } } } + fields(first: 10) { + edges { + node { + data + modelField { name } + } + } + } } } pageInfo { diff --git a/lib/towerops/gaiia/sync.ex b/lib/towerops/gaiia/sync.ex index cb3c6435..5c65e04c 100644 --- a/lib/towerops/gaiia/sync.ex +++ b/lib/towerops/gaiia/sync.ex @@ -127,7 +127,7 @@ defmodule Towerops.Gaiia.Sync do name: get_in(node, ["model", "name"]), status: node["status"], serial_number: nil, - mac_address: nil, + mac_address: extract_mac_address(node), ip_address: node["ipAddressV4"], model_name: get_in(node, ["model", "name"]), manufacturer_name: get_in(node, ["model", "manufacturer", "name"]), @@ -138,6 +138,19 @@ defmodule Towerops.Gaiia.Sync do } end + defp extract_mac_address(node) do + edges = get_in(node, ["fields", "edges"]) || [] + + Enum.find_value(edges, fn + %{"node" => %{"data" => data, "modelField" => %{"name" => field_name}}} + when is_binary(data) and is_binary(field_name) -> + if String.contains?(String.downcase(field_name), "mac"), do: data + + _ -> + nil + end) + end + defp map_billing_subscription(node) do price_cents = get_in(node, ["productVersion", "price"]) diff --git a/lib/towerops_web/components/layouts.ex b/lib/towerops_web/components/layouts.ex index 70cffbcf..95363d02 100644 --- a/lib/towerops_web/components/layouts.ex +++ b/lib/towerops_web/components/layouts.ex @@ -193,7 +193,7 @@ defmodule ToweropsWeb.Layouts do