►
From YouTube: Support Ops - Zendesk - ZD Main-SFDC Sync
Description
Jason Colyer, Support Operations Manager, takes us through how the ZD-SFDC sync works
A
Greetings
all
my
name
is
jason.
I'm
the
support
operations
manager
here
at
git
lab
and
today
I
figured
we'd-
go
over
the
we
kind
of
go
over
the
zendesk
salesforce
sync
for
the
main
zendesk
instance.
This
is
what
handles
the
vast
majority
of
the
syncs
from
salesforce
to
zendesk.
On
the
you
know
the
main
instance,
not
the
us
federal.
This
also
doesn't
handle
like
partners,
the
open,
select,
the
alliance.
B
And
yeah
share
my
screen
cool.
A
A
Awesome:
okay,
now
I've
got
audio.
So
that's
what
I
need
all
right
cool,
so
these
run
out
of
the
ops
gitlab
instance.
The
reason
for
that
is,
they
do
show
customer
data
in
the
cicd
pipelines.
A
So
for
the
greatest
amount
of
access
control.
We
could
do
these
currently
run
out
of
the
ops
instance.
They're
very
access
controlled,
not
a
lot
of
people
can
see
them.
I
do
have
plans
in
the
future
to
mirror
them
to
like
the
toolbox
or
something
so
the
code's
at
least
visible,
with
the
caveat
of
like.
Obviously,
it
won't
run
through
this
code
through
the
toolbox,
but
it
won't
at
least
be
visible.
A
So
this
is
our
basic
readme
file,
there's
not
a
lot
to
this
other,
and
it
tells
you
kind
of
what
gems
it's
using
json,
which
is
arguably
more
of
a
library
than
a
gym,
but
it's
also
kind
of
a
gem
of
oga,
which
is
a
nice
little
gem
that
kind
of
takes
http
output
headers
and
such
and
converts
it
to
ruby
objects
makes
them
very
beatable.
A
A
This
will
use
faraday
for
like
the
zendesk
portion
of
it,
but
for
the
sales
force
I
found.
Restforce
is
a
fantastic
gym,
so
I've
been
using
that
if
the
readme's
got
a
file
tree,
which
is
basically
just
saying,
here's
all
the
files
and
then
it
shows
the
soql
queries
used
for
the
main
instance,
but
we'll
go
over
that
as
we
go
over
the
script.
A
So
the
main
part
of
this
would
be
obviously
the
jlabci
file.
That's
what's
going
to
actually
run
all
the
jobs
and
the
fun
stuff
like
that,
which
is
what
we'll
actually
use
to
actually
do
the
sync
it
does
it
in
three
stages:
the
gather
data
stage,
the
compare
stage
of
the
sync
stage.
A
Fun
fact
about
me:
I'm
not
original
naming,
so
you
can
pretty
much
guess
what
each
stage
is
doing
the
before
script.
It's
always
going
to
do
a
ruby
dashbee.
This
is
just
for
debugging
purposes
if
I
ever
need
to
look
make
sure
it's
using
the
right
ruby
version,
occasionally
I'll
have
an
issue
with
like.
Oh,
this
was
made
in
ruby
2.6.5,
but
the
you
know,
ruby
version
is
2.6.7.
A
So
it's
good
for
me
to
be
able
to
quickly
see
the
ruby
version
that
it
reported
that
way.
Look
through
it,
we're
going
to
run
gym,
installed,
bundler
and
then
we're
going
to
run
bundle.
This
will
use
the
gem
file.
That's
in
this
repo
to
quickly
install
the
required
gems.
A
Obviously
it's
in
the
4
script
because
we
need
it
to
you
know
run
these
each
time.
We
need
to
make
sure
we
have
the
required
gems
to
actually
run
because
the
script's
going
to
fail.
Otherwise
our
gathered
data
stage,
pretty
much
is
composed
of
the
precinct
zd
or
report
in
the
precinct.
Sf
org
reports,
like
I
said
not
original
on
naming,
but
the
precinct
zd
org
report
is
basically
just
gathering
the
zendesk
organizations.
All
it's
going
to
do
is
on
a
schedule.
It
will
run
the
gathers
and
desk
organization.
A
Script
that'll
create
the
artifact
senddesk.json,
which
will
expire
in
four
hours,
and
the
precinct
sf
org
report
is
going
to
run.
The
gather
salesforce
account
script
on
a
schedule
and
it'll
make
two
artifacts
for
us,
the
salesforce.json,
which
will
contain
the
syncable
data
and
then
the
salesforceproblem.json
which
will
contain
other.
You
know
the
problems
that
basically
say.
I
can't
sync
these,
so
here's
a
list
of
the
problems.
A
You
should
probably
fix
these,
it's
good
for
reference
to
find
out
why
something
hasn't
synced
or
if
there's
duplicate
naming
issues
and
such
the
compare
stage
will
run
the
pre-sync
board
comparison
report.
This
only
runs
via
schedule.
I've
got
it
meeting
both
of
these
precinct
org
reports
here,
which
basically
means
this
job
will
not
run
without
those
paths
to
succeeding.
The
reason
for
that
is
it's
going
to
run
the
compare
organizations
which
will
use
those
artifacts
previous
jobs,
and
it's
going
to
create
two
that
creates.json
and
the
updates.json.
A
A
So
I'm
going
to
go
over
one
of
the
scripts
and
the
reason
I'm
only
going
to
go
over
one
of
them
is
because
they
pretty
much
all
follow
the
same
exact
format.
It's
the
ruby
script.
I've
got
the
frozen
string.
Literal
just
rubru
cop
likes
you
to
do
that.
I'm
requiring
the
zd
sftc6
main
file
and
then
I'm
going
to
call
the
zendesk
salesforce
main
zendesk
gather
run
the
other
scripts.
Basically
do
the
same
thing:
the
salesforce
one
would
run
salesforce,
you
know,
run
sale
force
gather
whatever
it
is.
A
The
compare
would
run
compare
and
the
sync
will
run
zendesk
sync
run
they
pretty
much.
Do
the
exact
same
thing
it's
just
so
I
can
quickly
call
these
files
without
having
to
tell
the
gem
file.
Oh
require
this
and
then
do
this
and
do
this
and
do
this.
It's
a
lot
easier.
Just
to
have
the
script
files
there.
A
The
gem
file,
it's
not
complex,
you'll,
see
it
pretty
much.
It's
just
requiring
json,
oj
and
res
force.
The
reason
I'm
using
4.2.2
on
this
is
sometimes
salesforce
pushes
major
versions
to
this
and
they're.
They
change
functions.
They
change
classes
radically.
A
A
So
that
brings
us
to
the
lib
files.
The
first
one
is
the
main
one.
You
saw
it's
requiring
that
cd
sftc,
sync
main.rb
and
all
this
is
doing
is
declaring
the
modules
and
salesforce
sync
main,
and
then
I've
got
these
two
right
here
that
require
bundler
setup
and
bundler
required
default.
This
is
a
really
cool
set
of
commands
that
basically
just
tells
it
hey,
require
everything
that
was
in
the
gem
file,
all
those
gems
we
installed
yeah,
we
need
them,
require
them.
It's
a
I
like
it.
A
I
think
it's
a
lot
cleaner
than
saying
require
json
require
oj,
require
rest
force,
especially
if
you
end
up
having
a
gym
file
with
like
20
gems.
I
don't
want
to
have
to
put
require
for
20
different
gyms.
This
is
a
lot
quicker
and
I
think,
a
little
cleaner
beyond
that
we're
going
to
require
the
zd
sfdc,
sync
main
slash,
client
files.
A
So
the
client
file
once
again
we're
calling
that
modules
and
salesforce
sync
main,
unfortunately,
you're-
probably
going
to
get
tired
of
me
saying
that
exact
wording,
because
it
is
present
a
lot
beyond
that.
We
create
a
class
clients
from
this
client,
I'm
going
to
require
the
compare,
salesforce
and
z
desk
files
and
then
we're
going
to
create
a
couple
functions
that
will
be
used
by
these
other
files.
A
A
This
is
going
to
be
passed
to
faraday,
to
tell
it
how
to
handle
failures,
and
specifically,
we
want
to
handle
connection
fail
and
timeout
error
if
it
occurs
with
these
it'll
basically
go
to
this
okay,
I
have
five
retries
I
can
do.
The
interval
between
recharge
should
start
at
a
second,
I
want
interval
randomness
at
0.5
and
the
back
off
factor
of
2..
A
This
is
basically
just
saying
I
want
intervals
somewhere,
but
somewhere
in
the
point
five
to
one.
You
know
in
the
point
somewhere
0.5
from
the
one
second,
so
maybe
half
a
second,
maybe
one
and
a
half.
Second,
the
back
off
factor
is
two
basically
saying
hey.
You
should
back
off
between
these
three
tries
just
to
make
sure
nothing
happens.
A
In
this
case,
I
got
two
seconds
because
zendesk
tends
to
require
a
second
if
it
hits
the
connection
field
timeout
stuff,
I
did
two
seconds
just
to
kind
of
be
safe
and
then
five
retries
at
that
point.
If
it
fails
past
five,
it's
just
gonna
fail
completely,
but
that's
kind
of
what
we
would
expect
to
happen.
We
want
that
to
happen.
A
The
next
thing
we've
got
is
the
salesforce
declaration,
you'll
notice,
I'm
using
these
double
pipe
equals.
That's
a
cool
little
trick
in
ruby.
That
basically
says
set
this
variable
to
something
unless
it
already
has
a
value,
so
I
can
call
the
salesforce
function
15
times
it's
only
going
to
actually
run
this
restforce
new,
the
first
time
all
the
other
times.
It'll
just
use
the
object
it's
already
built.
A
This
is
a
good
little
memory
saver,
at
least
in
my
opinion,
there's
everyone's
got
the
perfect
way
of
coding
and
has
different
opinions,
but
I
found
this
is
a
really
nice
way
to
do
it.
A
A
We
also
make
a
zendesk
function
here,
which
basically
just
makes
a
zendesk
global
variable,
this
one's
actually
using
faraday
instead
of
a
preset
gem
and
all
I'm
doing-
is
setting
a
new
faraday
connection
to
the
zendesk
api
url
and
in
the
config
I'm
telling
it.
You
know
the
requests
retry
value
is
these
retry
options
from
up.
B
A
The
adapters,
whatever
the
default
faraday
adapter
is,
I
want
to
make
sure
the
content
type
is
application
json,
because
we're
going
to
be
passing
and
receiving
json
from
zendesk.
So
it's
important
you
know
zendesk
recommends
to
set
it
that
way.
It's
not
required
on
get
requests,
but
it
is
required
on
the
put
in
the
post
that
we'll
use
with
syncs
and
creates
and
such
and
then
we've
got
the
basic
auth.
This
is
making
username
slash
token
and
then
using
a
zendesk
api
token.
A
A
Then
we've
got
a
function
called
request.
This
is
taking
http
method,
a
url
and
a
parameter.
Our
parameters
are
option
because
it
defaults
them
to
a
hash,
and
basically
this
is
just
using
this
faraday
connection
to
make
a
public
send
to
the
http
method.
So
git
post
put
delete
all
that
fun,
all
that
fun
stuff.
It's
going
to
take
a
url.
A
This
url
is
going
to
be
appended
on
the
actual
environment
url
we
sent
here.
So
that's
an
important
thing
to
keep
in
mind
and
then
any
parameters
we
are
passing
to
it
and
basically
it's
going
to
make
this
request
and
then
oj
is
going
to
load
the
response
body
into
a
nice.
Pretty
neat
hash
that
we
can
easily
parse.
A
So
once
again,
you've
got
that
zest,
salesforce,
sync
main
module
declaration,
we're
making
a
new
class
called
clients
or
sorry
salesforce
this
this
right
here,
this
less
than
sign
client
is
basically
saying
inherit
from
clients.
This
is
useful,
so
I
don't
have
to
say
zendesk
salesforce,
sync
main
colon,
colon
client
dot
salesforce
to
get
that
salesforce
function
we
made
instead
I'll
just
be
able
to
say
salesforce,
it's
already
there,
it's
preloaded
for
us,
our
run
function
we
saw
from
the
script
is
going
to
gather,
verify,
report
and
artifacts.
A
This
is
just
a
nice.
Little
wrapper
function
to
do
all
these
other
things
so
that
the
scripts
can
be
nice
and
simple
and
just
say
yes,
just
run
the
thing
it
doesn't
have
to
say.
Oh,
do
gather
then
verify
that
report
and
artifacts.
Instead,
I've
got
a
nice
little
wrapper
function.
For
me
to
do
that,
the
gather,
script
or
gather
function.
I'm
sorry!
A
The
gather
function
is
just
going
to
print
out
a
nice
message,
letting
us
know
it's
gathering
the
data
and
it's
going
to
call
the
data
function,
and
then
it's
going
to
tell
us
when
it's
done.
The
data
function
is
where
we'll
actually
do
the
gathering
and
what
this
is
going
to
do
is
use
that
salesforce
object
to
be
built
in
the
client
and
it's
going
to
call
the
query
function
which
will
run
an
soql
query.
A
That's
salesforce
object,
query
language,
a
lot
like
sql,
so
if
you're
familiar
with
sql
it'll,
look
very
familiar
to
you,
but
basically
we're
going
to
run
a
query
string
which
we
define
down
here
and
then
we're
going
to
map
this
to
account
objects
which
we'll
go
over
to
bits
for
duplicates.
This
is
we'll
go
over
this
in
a
bit,
but
basically
I'm
making
a
variable
called
duplicates
and
running
determined
duplicates.
This
is
just
to
get
the
duplicates,
so
I
can
so
we
can
make
that
salesforceproblems.json
file
later.
A
It
probably
won't
get
smaller,
it'll,
probably
just
get
bigger
and
bigger,
as
we
sync
more
complex
data,
but
a
lot
of
this
is
just
information
we
like
to
have
in
our
zendesk
tickets,
like
the
salesforce
id
and
the
account
name
and
the
arr,
and
you
know
the
sale
segmentation,
the
owner,
the
number
of
seats,
the
type,
the
tam,
the
support
level,
the
manual
support,
upgrade
in
case
of
prospects
region,
the
gain
site,
health
score
color,
which
is
determined
through
a
bunch
of
factors
and
gain
sight.
A
Admittedly,
I
don't
fully
understand
it,
but
the
general
sense
of
green
is
good.
Yellow
is
warning
and
red
is
extreme
warning.
So
probably
you
know
you're
kind
of
universal
with
the
colors
there.
Next
renewal
date
is
supposed
to
take
all
their
subscriptions
and
calculate
a
this
is
when
their
next
expiration
happens,
and
then
we've
got
these.
These
are
the
newer
parts
of
this,
but
I'm
calling
a
select
in
this
to
get
basically
all
the
subscriptions
they
have
that
are
active.
A
This
will
be
used
later
in
the
script,
to
double
check.
The
support
level
make
sure
everything's
good
to
go
kind
of
the
same
thing
here,
except
this
time,
we're
gathering
from
zumora
subscriptions
and
we're
doing
that
where
it's
active
we
found
sometimes
there's
like
a
glitch
in
zora,
and
it
doesn't
quite
sync
the
subscriptions.
So
sometimes
these
customer
subscriptions
are
blank
which,
for
scripting
purposes,
is
bad
because
it's
gonna
say:
oh,
they
have
no
subscriptions.
They
must
be
expired,
which
isn't
necessarily
true.
A
So
what
we're
doing
is
gathering
from
both
it
might
be
overkill
in
some
cases,
but
overkill's
actually
good.
Here.
We
would
rather
over
check
than
under
check
in
this
case,
because
you
know
expired,
customers
don't
get
support
and
we
definitely
don't
want
to
do
that
to
somebody
who
is
actively
paying
for
support.
A
So
beyond
that,
we've
got
this.
Where
clause
the
account
type,
we
only
sync
customer
and
former
customer
or
we'll
sync
prospect
or
prospect
ce
user,
which
I
believe
this
is
a
deprecated
type,
but
it's
one
we
account
for
anyway,
and
we
only
sync
those
in
cases
where
the
manual
support
upgrade
is
true,
and
then
we've
got
this
where
we're
syncing
this
one
specific
account
included
in
this.
That's
just
because
this
account
is
a
very
special
account.
A
A
So
it
takes
this
query
and
runs
it
in
salesforce.
Then
it's
mapping
each
return
from
this
query
to
an
account
object
which
is
going
to
start
by
running.
This
check
account
so
we'll
go
over
that
real
quick
check.
Account
is
basically
going
to
look
at
the
subscriptions
and
it's
going
to
determine
the
plans
from
them.
It's
going
to
look
at
zoora
subscriptions
and
it'll
determine
the
plans
from
them,
and
then
it's
going
to
call
unique
on
the
plans
just
to
make
sure
we
don't
have
duplicates
it's
going
to
delete
expired.
A
If
there
are
other
plans,
it's
going
to
map
them
out
to
make
them
nice
and
pretty,
and
then
it's
going
to
set
the
support
level
to
the
minimum,
which
is
going
to
be
basically
the
well
we'll
go
over
that
in
a
bit
so
determine
plans
you'll
see
how
we've
got
these
numbers
before
each
plan,
like
nine
expired,
seven
community,
two
gold,
one
ultimate.
A
The
reason
for
these
numbers
is
so
that
we
can
use
this
min
function
up
here
and
basically
say
right.
Ultimate
and
gold
are
going
to
be
the
highest
ones.
We
want
to
account
for
expires,
the
least
one
when
we
say
men
we're
taking
essentially
the
highest
plan
level
and
setting
that
to
the
support
level
up
here.
A
So
beyond
that
and
that's
basically
all
this
check
account
is
doing,
is
setting
these
subscriptions
and
the
support
levels
so
that
it
can
figure
out
not
only
what
is
their
true
support
level,
but
do
they
have
other
plans?
This
is
good
for
accounting
of
oh
well.
They
have
ultimate
in
silver
and
bronze
and
starter.
This
will
ensure
that
later
in
the
sync
those
tags
get
added
to
the
orange,
so
they
have
all
of
that
presence.
A
So,
beyond
that,
we
have
a
couple
of
different
things.
We
do
we
take
the
type
from
salesforce,
we
do
down
case
and
we
replace
any
spaces
with
underscores.
That's
to
make
it
a
nice,
pretty
format
for
zendesk
we've
got
the
determine
priority,
support
function,
which
is
down
here.
All
this
is
doing
is
basically
saying
well
yeah,
it's
false.
If
it's
a
customer,
it's
false,
if
it's
a
former
customer,
otherwise
just
return
manual
support
upgrade.
This
is
because
only
a
prospect
can
be
a
priority
prospect.
A
B
A
Where
is
it
there
we
go
all
this
does
is
if
it's
blank,
it's
returning
an
empty
space.
Otherwise
it's
just
pre-pending
it
with
the
org
region,
underscore
stuff
that
way
it's
in
zendesk
format
and
then
it's
down
casing
the
actual
region
itself.
That's
all
just
to
make
it
in
the
format
that
zendesk
expects
it
in
it'll
make
it
a
lot
easier
to
compare
when
we
get
that
zendesk
data.
If
they
look
the
same.
A
Subscriptions
we
get
from
those
subscriptions
we
set
down
below.
We
set
the
health
score
to
lower
case,
but
mostly
this
is
just
setting
a
hash
in
a
specific
format
that
we'll
then
use
later
to
compare
and
make
sure
it's
the
right.
It's
correct,
so
the
verified
data
is
just
going
to
subtract.
Duplicates
from
all
that
query
data
we
got
and
all
the
duplicates
is
doing.
A
Is
it's
grouping
all
that
data
by
the
account's
name
down
case,
because
we
do
not
want
to
have
to
worry
about
case
and
sensitivity,
because
zendesk
is
case
sensitive
on
the
name,
so
I
could
call
my
account
bob
and
then
another
one
with
lowercase
bob
and
another
one
with
all
capitals
bob.
As
far
as
zendesk
is
concerned,
those
are
all
three
of
the
same
name,
so
they
will
error
out
because
you
can
only
have
one
account
name
account.
A
Names
are
unique
in
10
desk,
but
essentially
we're
just
we're
grouping
it
by
that
and
we're
calling
the
values
and
then
we're
selecting
any
of
them
where
the
size
of
this
grouping
is
over
one
meaning
there
are
duplicate
names.
A
So
that's
how
we're
determining
duplicates
and
then
we're
basically
just
subtracting
that
from
data,
because
we
cannot
sync
duplicates
there's
no
real
way.
Scripting
wise.
We
could
look
at
two
accounts
with
the
same
name
and
say:
oh
that's,
clearly
the
right
one.
Until
there
is
a
point
when
someone
says
oh,
this
field
will
tell
you
which
one's
the
right
one
and
then
we
can
kind
of
account
for
that
a
little
better,
but
currently
no
real
way
to
know
which
one's
the
duplicate.
A
So
we
do
this
and
we
subtract
them
and
we
will
report
that
in
the
salesforceproblems.json
file
the
report
is
just
going
to
tell
us
hey.
I
found
this
many
accounts.
This
is
how
many
duplicates
I
found
and
then
it's
going
to
print
out
each
duplicate
account
name
so
that
we
can
easily
see
them
in
the
ci
job
blog.
A
But
it's
also
going
to
make
these
two
artifacts,
the
salesforce.json,
which
will
have
our
data
minus
the
duplicates
and
then
our
salesforce
problems,
which
is
just
going
to
have
our
duplicates
and
that's
all
there
is
to
the
salesforce
portion
of
the
script.
Real
quick.
Does
anybody
have
a
question
they
want
to
voice
before
we
go.
A
On
cool
we'll
go
on
to
the
next
one,
so
we've
got
the
zendesk
file.
All
this
is
doing
is
calling
it
class
zendesk
and
then
requiring
the
gather
in
the
sync
scripts.
So
we'll
go
to
those
we'll
start
with
gather
and
we'll
come
back
to
sync
since
the
final
one.
A
Once
again,
we
declare
that
module
the
zendesk
salesforce
sync
main.
We
basically
call
the
classes
end
desk
and
then
we're
making
a
new
class
called
gather
and
once
again
we're
inheriting
from
client
that
way,
I
don't
have
to
call
zendesk
salesforce
main
or
sync
main
colon,
colon
client,
dot
or
zendesk
dot
request
or
whatever
I
can.
Instead,
just
call
request
calls
in
desk
the
run.
Script
is
just
gonna
generate
the
artifact
and
report.
A
So
all
data
does
is
gather
the
orgs
which
all
we're
doing
for
that
is
essentially
looping
over
the
organizations.json
api
endpoint
and
we're
using
the
page
nation
and
we're
going
page
by
page
to
gather
every
single
organization
in
zendesk,
as
you
can
expect,
since
the
max
returns
from
the
pages
100
orgs
and
last
I
checked,
we
have
something
like
30,
almost
40,
000
orgs.
This
takes
a
bit
of
time.
It
has
a
lot
to
loop
through
it
takes
a
good
chunk
of
api.
A
When
it's
done,
it'll
tell
done
you'll
notice,
I
have
it
printing
dots,
so
I
can
quickly
check
and
debug
later
and
see
how
many
dots
that
went,
how
many
pages
it
hit
before
to
timeout
or
something
like
that
at
the
end
of
it,
I
return
orgs
fun
fact
with
ruby.
The
last
thing
that
is
actually
done
in
a
function
is
the
return.
A
If
you
don't
explicitly
say
to
return
so
in
this
case,
if
I
say
orgs,
it's
returning
orgs,
so
the
org
object,
you'll
notice,
it
looks
very
very
similar
to
what
salesforce
was
doing
because
we're
going
to
compare
them
and
we
want
them
to
look
as
close
as
possible,
with
the
exception
of
it's
going
to
have
a
zendesk
id
and
it's
going
to
have
tags
the
rest
of
this.
You
know
it'll
be
determined,
but
the
support
level.
Essentially,
the
only
thing
this
does
is
yeah
return,
the
store
support
level.
A
If
it
says
it's
starter,
you
know
if
it
says
it's
basic
return.
It
is
starter
because
basic's,
an
old
name
starter,
was
the
newer
name,
but
we
are
deprecating,
starter
and
bronze,
but
for
the
time
being
we
don't
want
it
to
say.
Oh
yeah,
the
support
plan
is
basic
because
that's
an
old
name.
We
don't
use
that
at
all.
We
wanted
to
say
starter,
that's
the
name
that
we
all
recognize
at
this
point
for
determined
subscriptions.
A
If
you
can't
tell
I've
had
to
type
those
and
say
those
a
lot,
so
I've
gotten
pretty
good
at
saying
them
fast.
Essentially,
I'm
duplicating
the
tags,
which
is
what
dot
dupe.
Does
it
basically
says,
give
me
an
exact
copy
of
what
I
just
called.
A
This
is
useful
if
I
need
to
mingle
what
the
like
the
tags
in
this
case,
but
I
don't
want
to
actually
edit
the
original
tags
and
basically
from
this,
it's
just
selecting
the
allowed
tags.
So
these
and
it's
basically
saying
yeah,
these
are
the
subscriptions.
If
there
were
no
subscriptions
found,
it's
gonna
say
it's
expired.
Otherwise,
it's
gonna
return,
an
array
of
subscription
tags
and
clean
tags
is
kind
of
doing
the
same,
but
in
the
opposite
it
has
the
allowed
tags.
A
It's
duplicating
the
tags.
It's
basically
just
deleting
the
plan
tags
because
we're
already
handling
those
in
subscriptions
and
then
it's
calling
a
sort
on
them
just
so
they're
in
nice,
pretty
format
that
way
we
can
compare
them
easily
when
we
generate
that
and
compare
script.
That's
because,
technically
speaking,
if
you
have
an
array,
that's
a
b
c
and
another
one,
that's
cba!
A
They
are
not
the
same
array:
they
do
not
equal
one
another
because
they're
different
orders.
They
have
different
index
values,
so
sorting
them
ensures
it
will
be
in
nice
format.
It's
not
to
say
we
couldn't
sort
them
later.
When
we
do
the
comparison,
I
just
have
it
being
done
here,
but
that's
all
really.
A
A
It
will
report
how
many
orgs
it
found
to
sync
which
is
useful,
but
also
something
I
could
easily
find
in
zendesk's.
You
know
admin
panel
by
just
going
to
the
organizations
and
seeing
the
count
so,
but
there
is
like
a
limit,
I
think,
after
a
hundred
thousand,
they
stop
showing
it
just
says
a
hundred
thousand
plus.
So
this
will
be
useful
at
that
point,
but
not
really
at
this
point
any
questions
on
the
zendesk
gather
side
of
this.
Before
I
keep
going.
A
Cool,
so
the
next
thing
that
it
does
is
the
comparison
once
again,
modules
end
up
sales
for
sync
main
we're
calling
the
class
compare.
I
don't
need
to
inherit
from
client
on
this
one,
because
I'm
not
actually
calling
salesforce
or
zendesk
in
this
case,
I'm
just
comparing
two
json
files,
I'm
setting
up
some.
You
know
I've
got
to
compare,
generate
and
generate
artifacts
and
report.
That's
what
the
run
function
does
I
set
some
variables
for
myself.
We
got
creates
updates,
do
nothing.
A
These
will
be
used
on
reporting
and
generating
artifacts
later,
but
the
actual
compare
script
is
essentially
going
to
determine
the
sync
needs.
This
is
a
nice
pretty
way
of
giving
me
a
count
of
how
many
it's
working
on
it's
going
to
be
a
rapid
number
that
goes
up.
That's
the
slash
r
at
the
end
of
this
stuff
is
basically
just
going
back
and
overwriting
it.
A
It's
mostly
just
nice
for
when
you
run
the
script
via
cli,
so
I
can
see
where
it's
at,
because
otherwise
it
says
that,
but
does
nothing
and
you're
like
I
don't
know
if
you're
actually
running
and
one
thing
I
get
paranoid
about,
is
when
a
script
says
it's
running
and
you
know
I
run
a
script
and
no
output
nothing's
happening,
I
get
a
little
paranoid
of
difference.
Did
my
computer
freeze?
Is
it
running
so
this
is
mostly
just
for
you
know
myself,
my
own
sanity,
but
anyone
else
who
actually
feels
the
same
way.
A
But
beyond
that,
what
it's
essentially
going
to
do
is
take
the
zendesk
organizations
and
organizations.
I
believe
we
define
somewhere
yeah
organizations.
It's
going
to
read
the
zendesk
accounts,
it's
going
to
read
the
salesforce
file,
but
essentially
what
we're
doing
is
it's
doing
a
detect
and
saying?
Okay,
so
find
me,
the
organization
that
matches
the
salesforce
id
on
the
account
itself
on
the
salesforce
return?
A
What
it's
going
to
say
is
if
you
couldn't
find
that
in
zendesk
it
means
we
need
to
create
it.
So
it's
going
to
make
it's
going
to
push
this
to
creates,
which
we
called
up
here.
It's
going
to
make
it
create
object,
we'll
go
over
that
a
bit.
A
Otherwise
it's
going
to
determine
the
updates.
Unless
zendesk
is
nil
and
when
it's
done
it'll
say
it's
done
so
determine
updates
just
going
to
basically
make
a
comparable
object,
which
is
a
fun
function.
That's
saying
I
don't
need
to
I'm,
not
comparing
the
zendesk
id
that
doesn't
exist
in
salesforce,
I'm
not
comparing
tags
because
that
doesn't
exist
in
salesforce.
A
I
need
to
make
sure
all
the
subscriptions
are
sorted,
so
they
compare
right
and
I
need
to
make
the
health
score.
Is
you
know
a
string?
This
is
for
the
few
cases
where
it's
empty
and
set
to
null
and
null
won't
compare
to
a
string
correctly.
So
that's
literally
what
that's
for
is
just
to
make
sure
it's
always
set
to
an
empty
string
if
it
was
null.
A
A
A
In
this
case
you
know,
we've
got
the
name,
the
organization
fields
and
then
from
there
we've
got
most
of
the
meat
and
potatoes
of
what
we
actually
want,
and
then
we've
got
the
tags
for
create.
We
don't
have
to
worry
about
pre-existing
tags
because
it
didn't
exist
for
update.
We
do
have
to
worry
about
the
existing
tags
because
we
obviously
don't
want
to
overwrite
some
of
the
custom
tags
we've
added,
so
we
got
to
make
sure
that's
there
and
all
the
update
tags
do.
Is
it
duplicates
the
you
know
the
tags
from
there?
A
It
makes
sure
it
adds
the
subscription
tags
and
then
it
does
a
sort
of
unique
without
the
sort
and
without
the
unique.
What
you
would
have
is
like
premium
premium
premium
premium
premium,
and
we
obviously
don't
want
to
tell
it
to
try
to
add
that
tag
15
times.
So
this
just
cleans
that
up
the
sort
is
actually
not
necessary
at
this
point,
but
I
do
it
anyway,
just
in
case
I
have
to
debug
stuff.
I
like
things
in
alphabetical
order.
A
But
beyond
that,
we're
going
to
create
two
artifacts,
the
creates
and
the
updates.json
and
then
we're
going
to
report
on
it.
Here's
how
many
we
have
to
create,
update
and
do
nothing
about
and
from
there
it
will
go
to
the
sync
function.
Before
I
go
over
the
sync
script,
does
anybody
have
any
questions.
A
Cool,
so
the
zendesk
sync
is
the
final
portion
of
this,
and
this
one
does
inherit
from
the
client,
because
I'm
going
to
have
to
call
that
zendesk
api
and
the
run
is
going
to
do
a
created,
updated
errors
create
orgs,
sync
words
all
created
is
doing.
Is
I'm
calling
these
functions
to
set
these
variables
because
I'm
going
to
be
calling
them
a
lot
later
to
increment
to
them?
A
So
I
know:
what's
going
on,
we've
got
the
errors,
which
is
just
an
empty
array,
but
that
will
catalog
errors
that
happen
during
the
create
portion,
but
yeah
so
all
creates
doing.
Is
it's
going
over
that
creates
artifact
file
and
it's
once
again
doing
that
count
for
me
and
it's
just
calling
create
org,
which
is
making
a
post
request
to
the
organizations.json
using
that
create
object,
that's
just
taking
the
object
we
already
have
and
once
and
doing
the
final
like
this
is
the
exact
json
format.
A
We
have
to
send
it
in
if
you
don't
send
it
in
this
way,
it
doesn't
work
right
and,
that's
basically
to
say
it's
an
organization
and
then
here's
all
that
information
and
at
the
end
we
call
to
json
to
give
it
a
giant
json
string,
that's
exactly
what
zendesk
wants.
I've
played
around
a
lot
with
it.
If
you
don't
give
it
exactly
what
it
wants,
it
will
annoyingly
say
it
did
something
when
it
didn't
that's
just
the
way
it
is.
A
But
if
the
response
has
an
error
in
it,
it
will
report
handle
the
error
which
we'll
go
over
in
a
bit,
but
essentially
it's
just
putting
an
error
string
into
the
array
for
us.
Otherwise,
it's
adding
one
to
created,
so
we
can
report
on
it
later.
A
The
update
object
is
pretty
much
the
same
as
the
create
object,
but
there's
a
bit
of
a
difference
in
that
we
often
have
to
update
way
more
than
create,
so
we're
actually
going
to
use
the
update
mini
api,
which
down
here
for
the
sync
words
you
can
see.
We
call
like
the
sync
is
setting
the
organizations
to
this
giant.
A
You
know
org
object
of
the
update
objects
and
then
it's
just
doing
a
put
request
to
organization
update
mini
this
allows
me
to
take
up
to
100
and
just
do
one
giant
bulk
update,
which
is
nice,
because
otherwise
we
would
need
a
hundred
api
calls,
and
that
is
a
ton
of
api
calls.
It
will
easily
hit
limits
at
that
point.
A
That's
why
you'll
notice
I
take
the
updates
and
I
slice
them
into
100.
I
this
I
like
this
ruby
function,
it's
pretty
convenient
a
huge
slice.
Integer
basically
says
yeah.
So
take
this
array
and
split
it
into
objects
that
are
100
in
size
and
2a
is
just
setting
them
to
an
array,
and
then
you
know
that's
when
we
do
the
request
to
do
the
update
mini.
A
I
have
this
giving
a
job
status
id,
which
is
mostly
useless
until
we
have
to
debug,
and
I
can
quickly
go
look
up
that
job
status
and
actually
see
what
happens
super
convenient
to
have
it
that
way
and
then
basically
we're
just
adding
adding
whatever
the
count
of
the
organization's
loop
we're
doing
the
actual
update
org.
This
is
something
we're
not
actually
using,
but
I
kept
it
in
here
in
case.
A
I
need
it
in
the
future,
but
that's
how
you
would
update
one
specific
organization
we
used
to
do
it
that
way,
but
again
like
when
we
had
to
update
100
orgs
it
took
forever
and
it
made
100
plus
api
calls.
So
we
definitely
didn't
want
to
do
that
report's
just
going
to
tell
us.
I
created
this
many.
I
synced
this
many
and
it'll
print
out
any
errors
that
happened
for
the
airport.
A
It's
literally
just
going
to
print
out
the
error
strings,
which
we
got
from
this
handle
error,
and
all
that
is
going
to
tell
us
is
you
know
the
salesforce
id
could
not
be
synced,
and
this
is
why,
most
the
time
the
y
is
duplicate
name,
so
that's
normally
something
we
kind
of
check
on
and
go
figure
out.
Why
there's
one
that
exists
in
zendesk,
but
doesn't
have
the
sales
force
id?
Normally
it's
because
of
a
merge
account
was
deleted
or
something
along
those
lines.
A
Yeah,
that's
yeah!
That's
pretty
much
the
end
of
the
script!
At
that
point,
that's
pretty
much.
The
meat
and
potatoes
of
how
this
really
works,
then
I'm
sure
my
screen
here
but
yeah.
That's
that's!
Really
the
meat
and
potatoes
of
how
the
sync
script
works
that
all
runs
via
ci
cd
on
a
schedule.
I
believe
it's
currently
running
every
30
minutes,
it's
using
zendesk
environment
variables,
salesforce
environment
variables
to
pass
those
to
the
script
and
run
all
of
this
yeah.
So
that's
currently
how
we're
doing
that?
C
I
have
a
question
regarding
the
ci
consumption
users.
How
do
we
keep
track
of
them?
Like
I
saw
an
organization
in
salesforce,
it
was
a
prospect
and
then
they
did
not
get
any
subscription.
Instead,
they
just
purchased
ci
and
storage.
A
So
ci,
like
it's
a
really
new
problem
that
we've
been
trying
to
figure
out.
The
basic
stance
we
took
was
we're
going
to
mark
them
as
expired,
because
they
don't
technically
have
a
plan.
But
then
we've
got
zendesk
itself
configured.
A
A
So
that's
kind
of
how
we're
handling
it
here
like
on
the
salesforce
side.
They
don't
have
a
plan,
it
doesn't
show
as
a
support
level.
That's
not
accounted
for.
Currently,
it's
not
to
say
in
the
future.
There
will
be
a
new
like
support
level
or
something
along
that
added
called
like
consumption
only
or
something
at
which
point.
A
We
can
sync
that
over
and
set
up
zendesk
to
handle
it
that
way
and
clean
up
some
things,
but
currently
because
they
don't
have
a
plan
and
they
would
be
classified
as
expired
when
they
pass
over
to
you
know
to
zendesk.
We
have
it
configured
that
if
the
customer
selects
their
consumption-
and
they
don't
have
a
paid
plan
to
mark
them
as
consumption,
only
give
them
sla
with
the
updates
to
the
scripts.
A
Most
of
them
are
actually
getting
the
custom
tag,
which
is
much
better
than
saying.
They're
expired,
at
which
point
the
same
kind
of
concept
you
know,
goes
into
play
of
they'll,
say
their
consumption
on
their
forms.
When
they
submit
their
tickets.
They'll
get
that
consumption
only
tag
they'll
get
an
sla.
Then
they
get
the
assistance
that
they're
looking
for.
A
Oh
yeah,
no
problem,
you'll,
probably
see
tickets
with
the
custom
tag
more
often
now
that's
basically
just
the
script's
way
of
saying
they
had
a
subscription,
but
I
had
no
way
of
knowing
what
this
is
and
a
good
example
is
like
the
oh:
they
bought
a
thousand
ci
minutes
cool
that
doesn't
translate
to
any
plan.
I
have
no
idea
what
that
is.
The
script
doesn't
know
what
it
is.
So
it
says,
custom
it's
something
we
just
don't
know
what
it
is.
A
Those
with
custom
tags
will
show
in
that
free
tickets
view
currently
remove
the
tag
if
they
have
a
paid
plan,
not
a
big
deal.
If
they
don't
it's
good
that
they're
showing
somewhere.
A
Right,
I
don't
well
I'll
call
it
like
that
hope
this
was
educational.
I
hope
this
was
useful
and
yeah
look
forward
to
seeing
you
all
in
the
future.