mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-19 20:44:16 +02:00
qet-mcp: count duplicate labels per plant and location
qet_check reported -F1 as a duplicate master when one sits in +UV1 and one in +UV2, although they are two devices: the place is part of the name, as the %M/%LM label formulas show it and as IEC 81346 tools treat it. Group the two duplicate-label checks by label and the effective place, the element's own plant/location or else its folio's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+18
-6
@@ -2772,22 +2772,34 @@ def tool_element_search(directory: str, query: str = "", link_type: str | None =
|
||||
# either would bury the real findings.
|
||||
# - "simple" elements are checked for duplicates too but only as a warning:
|
||||
# industrial.qet reuses V1..V6 across folios on purpose.
|
||||
#
|
||||
# A label names one device per place: the same "-F1" in two distribution
|
||||
# boards (+UV1-F1, +UV2-F1) is two devices, as in IEC 81346 / EPLAN. The
|
||||
# place is the element's own plant/location, else its folio's -- what the
|
||||
# label formulas %M/%LM show. element_nomenclature_view carries only the
|
||||
# element's, so these two checks read the tables.
|
||||
_LABELS_PER_PLACE_SQL = (
|
||||
"SELECT ei.label AS label, "
|
||||
"COALESCE(NULLIF(ei.plant,''), di.plant, '') AS plant, "
|
||||
"COALESCE(NULLIF(ei.location,''), di.locmach, '') AS location, COUNT(*) AS n "
|
||||
"FROM element_info ei JOIN element e ON ei.element_uuid = e.uuid "
|
||||
"JOIN diagram_info di ON di.diagram_uuid = e.diagram_uuid "
|
||||
"WHERE COALESCE(ei.label,'') <> '' AND e.type = '{type}' "
|
||||
"AND COALESCE(LOWER(TRIM(ei.exclude_from_bom)), '') NOT IN ('true', '1', 'yes', 'on') "
|
||||
"GROUP BY ei.label, 2, 3 HAVING n > 1 ORDER BY n DESC, ei.label")
|
||||
|
||||
CHECKS = {
|
||||
"duplicate_master_labels": {
|
||||
"severity": "error",
|
||||
"note": "Two master elements with the same label are ambiguous in every "
|
||||
"report that keys on it (BOM, cross-references, wiring list).",
|
||||
"sql": "SELECT label, COUNT(*) AS n FROM element_nomenclature_view "
|
||||
"WHERE COALESCE(label,'') <> '' AND element_type = 'master' "
|
||||
"GROUP BY label HAVING n > 1 ORDER BY n DESC, label",
|
||||
"sql": _LABELS_PER_PLACE_SQL.format(type="master"),
|
||||
},
|
||||
"duplicate_simple_labels": {
|
||||
"severity": "warning",
|
||||
"note": "Legitimate when a label is reused on purpose across folios "
|
||||
"(industrial.qet does); worth a look otherwise.",
|
||||
"sql": "SELECT label, COUNT(*) AS n FROM element_nomenclature_view "
|
||||
"WHERE COALESCE(label,'') <> '' AND element_type = 'simple' "
|
||||
"GROUP BY label HAVING n > 1 ORDER BY n DESC, label",
|
||||
"sql": _LABELS_PER_PLACE_SQL.format(type="simple"),
|
||||
},
|
||||
"unlabelled_masters": {
|
||||
"severity": "warning",
|
||||
|
||||
@@ -5828,6 +5828,22 @@ class Integration(unittest.TestCase):
|
||||
line = [l for l in (out["stdout"] + out["stderr"]).splitlines() if l.startswith("DB ")][0]
|
||||
self.assertEqual(json.loads(line[3:]), [{"wire_number": "W1"}])
|
||||
|
||||
def test_duplicate_labels_are_counted_per_location(self):
|
||||
"""-F1 in two distribution boards is two devices: the folio's
|
||||
location (+UV1, +UV2) is part of the name, as %LM shows it. KM1 on
|
||||
+UV1 and +UV2 is fine, a second KM1 on +UV2 is the finding."""
|
||||
base = self.sb.new(folios=3)
|
||||
ops = []
|
||||
for folio, ort in enumerate(("UV1", "UV2", "UV2")):
|
||||
ops += [{"op": "set_folio", "folio": folio, "property": "locmach", "value": ort},
|
||||
{"op": "add_element", "id": f"k{folio}", "folio": folio, "path": COIL,
|
||||
"x": 100, "y": 100},
|
||||
{"op": "set_label", "folio": folio, "element": f"$k{folio}", "label": "KM1"}]
|
||||
r = self.ok(self.sb.edit(base, ops))
|
||||
found = {f["check"]: f for f in m.tool_check(BINARY, r["output"])["findings"]}
|
||||
self.assertEqual(found["duplicate_master_labels"]["rows"],
|
||||
[{"label": "KM1", "plant": "", "location": "UV2", "n": 2}])
|
||||
|
||||
def test_check_fires_on_a_project_with_known_defects(self):
|
||||
"""Newly placed elements store NULL where a loaded file stores '', and
|
||||
`col = ''` matches only the second: the first version of these checks
|
||||
|
||||
Reference in New Issue
Block a user