From 238859b7793a3db8b7373b4df0cc89edf2eb4278 Mon Sep 17 00:00:00 2001 From: Catherine Fritz <111930712+fivetran-catfritz@users.noreply.github.com> Date: Wed, 21 Oct 2026 10:14:43 -0500 Subject: [PATCH 1/2] Anchor first_reply_time at ticket creation when a reply already predates it (v1.9.1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #278 correctly delayed sla_applied_at to Zendesk's logged clock start, but an agent can reply publicly before that point (Zendesk delays the clock until the customer's own first public comment, not the agent's). That early reply was being ignored, and the model would wait for the agent's *next* reply, producing a false breach. sla_applied_at for first_reply_time now anchors at ticket creation whenever a public agent/admin reply already exists before the logged instance, which covers both this case and the #279 re-application case through the same mechanism. Replaces the #279 fix's "earliest logged instance" check with a simpler, more precisely scoped "earliest already-given reply" check, since that's what's actually evidenced: Zendesk marks the metric met once a reply has already happened, not simply whichever instance was logged first. Verified against 4 real tickets reported in a reopened customer complaint (420358, 407147, 360783, 331197) — all now resolve to met. Checked the broader population in digital-arbor-400.zendesk_new: 714 tickets flip from falsely breached to met, zero regressions in the other direction (the fix can only move a ticket toward met). Co-Authored-By: Claude Sonnet 5 --- dbt_project.yml | 2 +- integration_tests/dbt_project.yml | 2 +- .../int_zendesk__sla_policy_applied.sql | 25 ++++++++++++++++--- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/dbt_project.yml b/dbt_project.yml index 2889922e..1421d250 100644 --- a/dbt_project.yml +++ b/dbt_project.yml @@ -1,5 +1,5 @@ name: 'zendesk' -version: '1.9.0' +version: '1.9.1' config-version: 2 require-dbt-version: [">=1.3.0", "<3.0.0"] diff --git a/integration_tests/dbt_project.yml b/integration_tests/dbt_project.yml index ad7eed1c..fd361745 100644 --- a/integration_tests/dbt_project.yml +++ b/integration_tests/dbt_project.yml @@ -1,7 +1,7 @@ config-version: 2 name: 'zendesk_integration_tests' -version: '1.9.0' +version: '1.9.1' profile: 'integration_tests' diff --git a/models/sla_policy/int_zendesk__sla_policy_applied.sql b/models/sla_policy/int_zendesk__sla_policy_applied.sql index edb4720e..366795ed 100644 --- a/models/sla_policy/int_zendesk__sla_policy_applied.sql +++ b/models/sla_policy/int_zendesk__sla_policy_applied.sql @@ -23,6 +23,15 @@ with ticket_field_history as ( select * from {{ ref('int_zendesk__ticket_aggregates') }} +), earliest_reply as ( + + select + source_relation, + ticket_id, + min(reply_at) as earliest_reply_at + from {{ ref('int_zendesk__commenter_reply_at') }} + group by 1, 2 + {% if check_sla_policy_metric_history %} ), sla_policy_metrics as ( @@ -49,10 +58,14 @@ with ticket_field_history as ( -- Zendesk logs first_reply_time the moment it actually starts that clock (immediate or -- delayed), so we just read it directly, same as the other three metrics below. ticket_field_history.valid_starting_at as sla_applied_at, - -- Only first_reply_time dedupes to one row per ticket, so only it needs the earliest instance - -- (a re-application, e.g. priority change, shouldn't discard an earlier, already-met one). + -- Only first_reply_time dedupes to one row per ticket. If an agent already replied publicly + -- before this instance's logged start -- whether a later re-application (e.g. priority change) + -- discarded an earlier, already-met instance, or the agent replied before Zendesk delayed the + -- clock to the customer's own first public comment -- anchor at ticket creation instead, so + -- that reply isn't ignored. case when ticket_field_history.field_name = 'first_reply_time' - then min(ticket_field_history.valid_starting_at) over (partition by ticket_field_history.ticket_id, ticket_field_history.field_name {{ fivetran_utils.partition_by_source_relation(package_name='zendesk', alias='ticket_field_history') }}) + and earliest_reply.earliest_reply_at < ticket_field_history.valid_starting_at + then ticket.created_at else ticket_field_history.valid_starting_at end as earliest_sla_applied_at, cast({{ fivetran_utils.json_parse('ticket_field_history.value', ['minutes']) }} as {{ dbt.type_int() }} ) as target, @@ -64,6 +77,9 @@ with ticket_field_history as ( join ticket on ticket.ticket_id = ticket_field_history.ticket_id and ticket.source_relation = ticket_field_history.source_relation + left join earliest_reply + on earliest_reply.ticket_id = ticket_field_history.ticket_id + and earliest_reply.source_relation = ticket_field_history.source_relation where ticket_field_history.value is not null and ticket_field_history.field_name in ('next_reply_time', 'first_reply_time', 'agent_work_time', 'requester_wait_time') @@ -137,7 +153,8 @@ with ticket_field_history as ( add_sla_policy_id.ticket_current_status, add_sla_policy_id.metric, add_sla_policy_id.latest_sla, - -- earliest_sla_applied_at equals sla_applied_at except for first_reply_time re-applications. + -- earliest_sla_applied_at only differs from sla_applied_at when an agent already replied + -- publicly before this logged instance (see the comment above where it's computed). add_sla_policy_id.earliest_sla_applied_at as sla_applied_at, coalesce(sla_policy_metrics.target, add_sla_policy_id.target) as target, add_sla_policy_id.in_business_hours, From e75e02db485b020c048d10cd60409930922efb76 Mon Sep 17 00:00:00 2001 From: Catherine Fritz <111930712+fivetran-catfritz@users.noreply.github.com> Date: Wed, 21 Oct 2026 10:15:23 -0500 Subject: [PATCH 2/2] Add CHANGELOG entry for v1.9.1 Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 040c2099..d3e426fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# dbt_zendesk v1.9.1 + +[PR #287](https://github.com/fivetran/dbt_zendesk/pull/287) includes the following updates: + +## Bug Fix +- Fixes false `first_reply_time` SLA breaches in `zendesk__sla_policies` when an agent already replied publicly before Zendesk delayed the SLA clock to the customer's own first public comment. `sla_applied_at` now anchors to ticket creation in this case, so that earlier reply counts instead of the model waiting for a later one. + - As above, `sla_event_id` also changes for the `first_reply_time` events affected by this fix. + # dbt_zendesk v1.9.0 [PR #278](https://github.com/fivetran/dbt_zendesk/pull/278) includes the following updates: