From 5f2ad63611acc09017f717291c73563ffac36c44 Mon Sep 17 00:00:00 2001 From: zsh <60062@sangfor.com> Date: Sat, 3 Oct 2026 14:20:32 +0800 Subject: [PATCH] vendors: map Freshdesk native export headers (Created time / Closed time / Resolved time) A Freshdesk standard ticket export labels its timestamps "Created time", "Closed time" and "Resolved time" (Freshworks support: "How do I export my tickets from Freshdesk?"). After lower() those keep the space, so none of the three matched the alias table and a native export silently lost both timestamps - the recount could not place a single line in time. Adds the three space-form headers to registry/vendor-rules.json column_aliases ("Resolved time" joins the existing Zendesk "Solved at" mapping to closed_at). registry/ stays the single source of truth: the healthcheck copy is synced and website/vendor-rules.js is regenerated with scripts/gen_web_rules.py. Tests: 452 -> 454 (Freshdesk style headers map; Resolved time maps closed_at). --- healthcheck/am_healthcheck/vendor-rules.json | 7 +++-- healthcheck/tests/test_vendors.py | 30 ++++++++++++++++++++ registry/vendor-rules.json | 7 +++-- website/vendor-rules.js | 7 +++-- 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/healthcheck/am_healthcheck/vendor-rules.json b/healthcheck/am_healthcheck/vendor-rules.json index 35e8960..1560cfd 100644 --- a/healthcheck/am_healthcheck/vendor-rules.json +++ b/healthcheck/am_healthcheck/vendor-rules.json @@ -37,7 +37,8 @@ "created_at", "created", "created at", - "conversation created at" + "conversation created at", + "created time" ], "closed_at": [ "closed_at", @@ -45,7 +46,9 @@ "solved_at", "resolved_at", "solved at", - "closed at" + "closed at", + "closed time", + "resolved time" ], "human_agent_participated": [ "human_agent_participated", diff --git a/healthcheck/tests/test_vendors.py b/healthcheck/tests/test_vendors.py index 27af096..8eaaff5 100644 --- a/healthcheck/tests/test_vendors.py +++ b/healthcheck/tests/test_vendors.py @@ -265,3 +265,33 @@ def test_intercom_label_headers_map(self): export = load_export(path) self.assertIn("conversation_id", export["columns_found"]) self.assertIn("opened_at", export["columns_found"]) + + def test_freshdesk_style_headers_map(self): + """Freshdesk's standard ticket export labels its timestamps + "Created time" / "Closed time" / "Resolved time" (Freshworks support: + "How do I export my tickets from Freshdesk?"). None of those space + forms were in the alias table, so a native export silently lost both + timestamps and the recount could not place a single line in time.""" + from am_healthcheck.vendors import load_export + path = self._export([ + "Ticket ID", "Created time", "Closed time", + "human_agent_participated", "issue_addressed", + "customer_recontacted_within_window", "vendor_billed"]) + export = load_export(path) + self.assertIn("conversation_id", export["columns_found"]) + self.assertIn("opened_at", export["columns_found"]) + self.assertIn("closed_at", export["columns_found"]) + self.assertEqual(export["columns_missing"], []) + + def test_freshdesk_resolved_time_maps_to_closed_at(self): + """Freshdesk splits "Resolved time" (status 4) from "Closed time" + (status 5); either one ends the conversation, so both map to + closed_at, matching the existing Zendesk "Solved at" alias.""" + from am_healthcheck.vendors import load_export + path = self._export([ + "Ticket ID", "Created time", "Resolved time", + "human_agent_participated", "issue_addressed", + "customer_recontacted_within_window", "vendor_billed"]) + export = load_export(path) + self.assertIn("closed_at", export["columns_found"]) + self.assertEqual(export["columns_missing"], []) diff --git a/registry/vendor-rules.json b/registry/vendor-rules.json index 35e8960..1560cfd 100644 --- a/registry/vendor-rules.json +++ b/registry/vendor-rules.json @@ -37,7 +37,8 @@ "created_at", "created", "created at", - "conversation created at" + "conversation created at", + "created time" ], "closed_at": [ "closed_at", @@ -45,7 +46,9 @@ "solved_at", "resolved_at", "solved at", - "closed at" + "closed at", + "closed time", + "resolved time" ], "human_agent_participated": [ "human_agent_participated", diff --git a/website/vendor-rules.js b/website/vendor-rules.js index 473d52a..e6236ba 100644 --- a/website/vendor-rules.js +++ b/website/vendor-rules.js @@ -29,7 +29,9 @@ "solved_at", "resolved_at", "solved at", - "closed at" + "closed at", + "closed time", + "resolved time" ], "conversation_id": [ "conversation_id", @@ -71,7 +73,8 @@ "created_at", "created", "created at", - "conversation created at" + "conversation created at", + "created time" ], "vendor_billed": [ "vendor_billed",