Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# dbt_zendesk v1.9.0-a2

[PR #277](https://github.com/fivetran/dbt_zendesk/pull/277) includes the following updates:

## Bug Fix
- Fixes false `first_reply_time` SLA breaches for tickets with no real external requester (e.g. an agent filing a ticket on their own behalf). The a1 fix below disqualified an agent's early reply until "the customer" engaged, but on these tickets no customer ever will, so the reply now counts normally against the ticket's creation time, matching Zendesk's behavior.

# dbt_zendesk v1.9.0-a1

[PR #273](https://github.com/fivetran/dbt_zendesk/pull/273) includes the following updates:
Expand Down
4 changes: 3 additions & 1 deletion DECISIONLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ Without this handling, `int_zendesk__sla_policy_applied.sql` would set `sla_appl
A ticket is treated as "privately created" for a given internal public comment when **all** of the following hold:
- it is the ticket's first-ever public comment,
- the ticket already had other (private) comments before it — so this isn't simply the ticket's very first activity, such as an agent proactively opening a ticket with an immediate public post, and
- the customer hasn't said anything yet, publicly or privately, as of that comment's timestamp.
- the customer has a later comment, publicly or privately, that comes after that comment's timestamp.

That last condition requires a real, eventual customer comment to exist — not just "none yet." Some tickets never have a true external commenter at all (e.g. an agent filing a ticket on their own behalf for an internal process); there, no one is ever coming, so the agent's early public comment isn't held disqualified indefinitely waiting for a customer who won't show up — it counts as the reply, anchored to `ticket.created_at` like any normal ticket. Zendesk's own SLA application timestamp confirms this: for these tickets it logs a single `first_reply_time` entry at ticket creation, with no later re-application, unlike genuine privately-created tickets where Zendesk visibly re-applies the target at the customer's real engagement.

When all three hold, that agent comment no longer counts as a reply in `int_zendesk__commenter_reply_at.sql`, and `sla_applied_at` in `int_zendesk__sla_policy_applied.sql` shifts to the customer's first comment (public or private) instead of `ticket.created_at`. We deliberately did not key this off of "any prior private comment," since a private comment can also come from the customer themselves (e.g. a message routed in privately before an agent replies publicly) — in that case the customer has already engaged, and the original `ticket.created_at` anchor is correct. Because the disqualified comment no longer counts as a reply, `zendesk__sla_policies` now also looks for the next real reply after the customer engages — which can surface breaches that were previously hidden by treating that comment as met.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Include the following zendesk package version in your `packages.yml` file:
```yml
packages:
- package: fivetran/zendesk
version: 1.9.0-a1
version: 1.9.0-a2
```
> All required sources and staging models are now bundled into this transformation package. Do not include `fivetran/zendesk_source` in your `packages.yml` since this package has been deprecated.

Expand Down
4 changes: 3 additions & 1 deletion integration_tests/seeds/ticket_comment_data.csv
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ id,_fivetran_synced,body,created,facebook_comment,public,ticket_id,tweet,user_id
20001002,2020-09-01 10:05:30.000,body_first_public,2020-09-01 10:05:00,FALSE,TRUE,20001,FALSE,1111,FALSE
20001003,2020-09-01 14:00:30.000,body_customer_private_reply,2020-09-01 14:00:00,FALSE,FALSE,20001,FALSE,2222,FALSE
20001004,2020-09-01 14:20:30.000,body_agent_real_reply,2020-09-01 14:20:00,FALSE,TRUE,20001,FALSE,1111,FALSE
20001005,2020-09-05 09:00:30.000,body_customer_public_reply,2020-09-05 09:00:00,FALSE,TRUE,20001,FALSE,2222,FALSE
20001005,2020-09-05 09:00:30.000,body_customer_public_reply,2020-09-05 09:00:00,FALSE,TRUE,20001,FALSE,2222,FALSE
20002001,2020-09-10 10:00:30.000,body_internal_ticket_creation,2020-09-10 10:00:00,FALSE,FALSE,20002,FALSE,1111,FALSE
20002002,2020-09-10 10:05:30.000,body_agent_first_public_no_customer,2020-09-10 10:05:00,FALSE,TRUE,20002,FALSE,1111,FALSE
1 change: 1 addition & 0 deletions integration_tests/seeds/ticket_data.csv
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ id,_fivetran_synced,allow_channelback,assignee_id,brand_id,created_at,descriptio
6171,2020-06-01 02:11:39.760,FALSE,396334400494,360003529474,2020-05-17 17:50:31,description1,,,,360006965034,FALSE,TRUE,370295713034,,,email@email.com,410930434074,closed,subject1,410930434074,,360002048693,,2020-05-31 23:03:46,https://zendesk.com/api/v2/tickets/6171.json,email,,,,example@email.com,Support,[],,,,FALSE
6605,2020-06-10 02:10:24.202,FALSE,396315360434,360003529474,2020-05-26 22:29:50,description1,,,,360006965034,FALSE,TRUE,370295719754,,,email@email.com,410416672973,closed,subject1,410416672973,,360002048693,,2020-06-09 23:03:49,https://zendesk.com/api/v2/tickets/6605.json,email,,,,example@email.com,Support,[],,,,FALSE
20001,2020-09-05 09:05:30.000,FALSE,1111,360003529474,2020-09-01 10:00:00,Ticket to test SLA clock anchoring when the customer's first reply is private,,,,360006965034,FALSE,TRUE,,normal,,email@email.com,2222,solved,Private first reply SLA test,2222,,360002048693,,2020-09-05 09:05:00,https://zendesk.com/api/v2/tickets/20001.json,email,,,,X,Support,[],,,,FALSE
20002,2020-09-11 12:00:30.000,FALSE,1111,360003529474,2020-09-10 10:00:00,Ticket to test SLA when the requester is internal and no external customer ever comments,,,,360006965034,FALSE,TRUE,,normal,,email@email.com,1111,solved,Internal-only ticket SLA test,1111,,360002048693,,2020-09-11 12:00:00,https://zendesk.com/api/v2/tickets/20002.json,email,,,,X,Support,[],,,,FALSE
4 changes: 4 additions & 0 deletions integration_tests/seeds/ticket_field_history_data.csv
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,7 @@ status,20001,2020-09-01 10:00:00,2020-09-05 09:05:30.000,,new
priority,20001,2020-09-01 10:00:00,2020-09-05 09:05:30.000,,normal
first_reply_time,20001,2020-09-01 10:00:00,2020-09-05 09:05:30.000,,"{""minutes"":480,""seconds"":28800,""in_business_hours"":false}"
status,20001,2020-09-05 09:05:00,2020-09-05 09:05:30.000,,solved
status,20002,2020-09-10 10:00:00,2020-09-11 12:00:30.000,,new
priority,20002,2020-09-10 10:00:00,2020-09-11 12:00:30.000,,normal
first_reply_time,20002,2020-09-10 10:00:00,2020-09-11 12:00:30.000,,"{""minutes"":480,""seconds"":28800,""in_business_hours"":false}"
status,20002,2020-09-11 12:00:00,2020-09-11 12:00:30.000,,solved
6 changes: 4 additions & 2 deletions models/sla_policy/int_zendesk__sla_policy_applied.sql
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@ with ticket_field_history as (
select
comments_enriched.source_relation,
comments_enriched.ticket_id,
-- Requires a real later external comment to exist -- if none ever does (e.g. an internal
-- ticket with no external requester), there's no one to wait for, so this isn't
-- privately-created in the sense that matters here.
max(case when comments_enriched.previous_commenter_role = 'first_comment'
and comments_enriched.commenter_role = 'internal_comment'
and comments_enriched.previous_internal_comment_count > 0
and (first_external_comment.first_external_comment_at is null
or comments_enriched.valid_starting_at < first_external_comment.first_external_comment_at)
and comments_enriched.valid_starting_at < first_external_comment.first_external_comment_at
then 1 else 0 end) = 1 as is_privately_created,
-- Any visibility, not just public: a private message from the customer still counts as engagement.
max(first_external_comment.first_external_comment_at) as first_customer_comment_at
Expand Down
13 changes: 8 additions & 5 deletions models/sla_policy/reply_time/int_zendesk__commenter_reply_at.sql
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ with comments_enriched as (
select
public_comments.*,
-- True when this is the ticket's first public comment, it was posted before the customer
-- said anything (public or private), and private comments already preceded it.
(public_comments.previous_commenter_role = 'first_comment'
and public_comments.previous_internal_comment_count > 0
and (first_external_comment.first_external_comment_at is null
or public_comments.valid_starting_at < first_external_comment.first_external_comment_at)
-- said anything (public or private), and private comments already preceded it. Requires a
-- real later external comment to exist -- if none ever does (e.g. an internal ticket with no
-- external requester), there's no one to wait for, so this comment counts as the reply.
coalesce(
public_comments.previous_commenter_role = 'first_comment'
and public_comments.previous_internal_comment_count > 0
and public_comments.valid_starting_at < first_external_comment.first_external_comment_at,
false
) as is_unengaged_first_comment
from public_comments
left join first_external_comment
Expand Down
Loading