Mobile apps are awesome, but there’s always a “but”

If you’re learning to code because you want to build mobile apps, there’s a perspective on the current state of affairs that you should be familiar with. Jeff Atwood, one of the developers behind and a pretty cool mechanical keyboard, has a blog that I’m really coming to enjoy. He published a post yesterday on some of the bigger problems caused by an increasingly massive mobile app market, including why it’s so frustrating for users–something app developers need to think about if they want their app to win over an audience and become profitable. It’s not a unique perspective, but Atwood is a good writer and articulates the problems well. Plus, it includes a couple of pretty funny cartoons.

Atwood’s post is apocalyptic, as its title suggests, and there’s no reason you have to agree with him. I think he’s pretty insightful, and I’ve gained a lot from some of his posts. Most of them aren’t for beginners, but this one should be accessible to anybody who’s used a smartphone for longer than about a day. Plus, who knows? You’re new to the coding game and not already invested in or bogged down by the existing infrastructure. Maybe you’ll be the one to solve the problems Atwood points out. But even if all you get out of it is a clear picture of the hurdles you have to clear as a mobile app developer, you’ll be a step ahead of a lot of folks who can’t be bothered to care. Like these guys:

Love and kisses,



Learn to Code from Someone Else

If my pace isn’t fast enough for you, or if you just need more fodder for your insatiable hunger to learn everything you can about programming right this second, you might be interested in this post by Scott Hanselman that popped up on my radar today. It has a Venn diagram (or is it an Euler diagram? Are you nerdy enough to find out?) that explains the difference between some key terms like hacker, coder, developer, and, if you follow one of the links, dweeb. He also compares coding to going to Ikea, which is inaccurate. As miserable as coding makes me sometimes, it has never made me as miserable as a trip to Ikea.

I don’t have first-hand experience with all of the resources he points to, but I have used a few of them. The ones I know are good, and the others look like they’d be worth getting to know better. I noticed that Code, the book I mentioned in my first Learn to Code post, came up in Hanselman’s post, as well. That’s two out of two blogs connected to this blog that recommend that book! You can keep thinking about it if you want, but sooner or later, you’re going to read it. I’m as sure of that as I am that Oreos are going to get mentioned in this post.

One point Hanselman makes (that I made in a slightly different way and will echo here) is that where you should start learning to code depends heavily on where you want to end up–assuming you know where you want to end up. I’m trying to keep a pretty general view in my posts as I get started, since if you’re starting completely from scratch, there are basics that will come in handy no matter which direction you go. But if you already know that you want to build robots to reenact scenes from Saved By the Bell in your local community theater, you can probably find some materials elsewhere that will give you a foundation targeted more specifically toward that, and the list on Hanselman’s post is a good place to start.

Don’t forget about this guy!

So go ahead and browse around. There’s lots of good stuff out there. I’d love to hear some feedback on which resources you like best if you’re not coming at it from a STEM background.

Love and kisses,


The Cheater’s Code: Recording Macros


Remember, my target goal for these Learn to Code posts is non-programmers and non-computer science geeks. I’m trying to make as few assumptions as possible about your existing knowledge of programming and computer software in general. When I was learning programming, I needed something to fill in the dummy gaps, and my goal is to provide some of that for the folks who might be coming up behind me.

This post is heavier on abstract ideas than practical solutions, as I feel a need to explain why I’m offering a cheat first rather than following a more traditional route into the code. So get ready for some rambling! If you want to skip some of my philosophizing on programming tutorials and just get straight into recording macros, you can gostraight to the section under Microsoft Word’s Macro Recorder.

Scope of Application

Today’s post relies on Microsoft Word 2013 running on a Windows 8.1 machine. But what I’ll cover applies at least as far back as Word 2007 and Windows XP and the equivalent versions of Word for the Mac. If you don’t have Word, you can get a trial copy from Microsoft’s website.

Hello, World!

Most “Learn to Program” guides start with what’s called a “Hello, world!” program (HWP). These are minimal programs that get your computer to display the text “Hello, world!” on the screen. They’re designed as introductory learning tools. But somebody recently sent me this image about programming tutorials, and it reminded me of some of the challenges of introducing people to programming:

hello world draw an owl

Hello, World! Next step, build Google.

I’m no artist, but I can draw some circles… Ok, I can’t. My circles always turn out looking like ovals that somebody put in the microwave to see what would happen. But that’s lucky for you. If I could draw circles, what would the butterfly effect of that be? Probably wouldn’t be here writing this blog. So my sucky drawing skills say “You’re welcome.”

Anyway, I can draw deformed ovals. I’m also excellent at “Hello, world!” programs–as you undoubtedly will be. And I’ve got nothing against them. HWPs are great for doing something quick and easy in a new language, and I love instant gratification. It’s why I binge-watch TV and buy M&M’s at the gas station. (Nabisco, if you don’t sponsor my blog, I’ll buy more other things at the gas stations. Those M&M’s could have been Oreos.) But HWPs (Hello World Programs) aren’t as great introductions for total noobs as they’re sometimes thought to be.

To oversimplify, HWPs work best as an introduction to driving an unfamiliar car. “Hey, you know how in your car, the windshield wiper control is on the right?  Well, here, it’s on the left. And those stereo controls on the wheel? This car doesn’t have them. Oh, and the headlights aren’t on that lever on the steering column. There’s a button on the dash over there–yeah, that’s it.”

Any two cars have the same basic functionality, but the location of controls and how they’re labeled might vary greatly. And maybe one has heated seats and the other doesn’t. Programming languages are the same way. They share an incredibly long list of basic functions, but the names of those functions and how you access them can seem worlds apart at first glance. And every language has its own set of bells and whistles. Imagine, though, that you’ve never seen a car before, or that what you really want to understand is how turning that knob on the lever sticking out of the steering column makes the windshield wipers move. You would be looking for a different entry point to the conversation.

It’s unfair to say that all HWPs are sub-par introductions to first-time programmers with no computer science background. But how are those noobs supposed to recognize the difference between an HWP that will appeal to someone starting from scratch and one that is built for experienced users transitioning to a new language? Tutorials are getting better at identifying prerequisite knowledge or experience, but I think the inspiration for the owl cartoon above is the vast majority of tutorials that take a reader’s knowledge for granted. For self-starters who don’t have a mentor or a safe space to ask questions, those tutorials can be a huge turnoff. They make programming seem as mysterious as quantum physics or the rise of bronies.

I’ve done my fair share of HWPs and still do. They’ll always serve the appropriate audience well. But I found a side door into the code that was really instructive for me. It’s cheating, for sure. But it was the best learning tool I could have asked for: recording macros. It won’t land you a job at Amazon or anything. (Trust me. They were not at all impressed with my macro skills when I interviewed there.) But it will give you a leg up if you have a mind like mine–and I’m assuming you do, or else you’d be out doing an HWP in Python right now.


You’ve heard of macros, right? Some nerd at your office or in one of your classes makes their own macros or downloads them from the internet. The term macro can actually be applied to certain structures of computer code in general, but they’re most commonly associated with Microsoft’s Office suite of programs–especially Excel.

We need a quick definition of macro for our discussion, so I’m going to say you can think of a macro as a recipe. Say we have a macro called “Peanut Butter Sandwich.” We write the step-by-step instructions for making the sandwich only once. From then on, any time we want the computer to make a peanut butter sandwich (which should probably be the ultimate goal of computing), we just say “Peanut Butter Sandwich.” The computer then reads that recipe and does each of the steps.

Dummary (dummy’s summary): As long as we know the recipe’s name (macro name), we can prompt the computer to do all the steps in the recipe just by telling it the name.

Wait, wait, wait… I hear software developers referring to themselves as JavaScript Ninjas and Agile Samurais–or the less cool sounding but still endearing “Code Monkey.” You make it sound as if they’re more like a bunch of Julia Childs… Julia Children?… Rachel Rays.

Umm… I think there’s a healthy middle ground:

Chef Louis from Disney’s The Little Mermaid

Microsoft’s Office suite has a set of tools that allows you to create your own macros to automate tasks you do over and over again. But instead of having to write the recipe, you can record it. The software will then let you name your recipe and designate a way to call it up and tell the computer to follow it.

Microsoft Word’s Macro Recorder

More and more tools are emerging that demonstrate code in action in real time, but the one that really served me starting out was Microsoft Word’s macro recorder. It’s actually pretty awesome, and if this is the closest you ever get to programming, it will be a big value add in most professional environments. Excel and PowerPoint have the same tools, but I’m going to focus on Word for now.

Recording macros is easy, but before you can do it, you have to give yourself access to the macro tools by turning on the Developer tab in the ribbon.

Your ribbon in Word should look something like the screenshot below. I’m using Word 2013, so the style of yours may be different, but the content should be more or less the same.


We’re going to click the File tab, and select “Options.”


In the dialog window that pops up, select “Customize Ribbon” from the panel on the left:


When those options load, you’ll see a box on the right with a list of all the tabs. All the ones with check marks by them are on and available when you open Word. Anything without a check mark is turned off.


Just past the halfway point on that list, you should see the value “Developer,” and unless you’ve already been fiddling with macros, the box next to it is probably not checked. Click the checkbox or the word “Developer” to turn it on:


Click the “Ok” button on the dialog window, and now you’ll see the Developer tab in your ribbon:


Go ahead and click on it to open it up. It should look something like this:


There’s a lot here, but we’re going to concern ourselves only with the Code group on the left:


Quick diversion

In case you’re not familiar with the terminology of Word’s thingamajigs, here’s a quick review:

  • That big bar along the top that showed up around 2007 is the ribbon. If you used Word before then, you were mad about it for at least a couple years. If you didn’t get to college before 2008, you don’t understand what all the fuss was about. You also don’t know who Clippy is and why this clip from NPR’s Wait Wait… Don’t Tell Me! is hilarious.
  • The ribbon is divided into tabs, which is pretty standard currency. You’ve got a grip on that.
  • The tabs are divided into groups, which are usually separated with a vertical bar or pipe. On the Home tab, for example, the three left-most groups are Clipboard, Font, and Paragraph. See those vertical bars in between?


That’s where one group ends and the next begins. Some of them are a little arbitrary, but most of them make sense.

  • Within the groups are controls. Every little button and dropdown is a control.
  • Dummary: When you click the big bold B to make text bold, you’re using the bold control within the Font group on the Home tab of the Word ribbon.

Back on Track

You see where this is going. There’s a record button staring you in the face.

Don’t Write Code. Watch it Happen!

When I was first learning to code, I read a lot of sample programs. We’ll talk about that more later. The problem is that programs of any complexity get unwieldy pretty quickly. Sophisticated programs require sophisticated setup. So even when I wanted my code to reproduce existing actions in a program like Word, I didn’t know how to find that particular action in sample code. I kept thinking, “What if I could just see the code for what I’m doing right now separate from everything else?” Turns out the macro recorder makes that possible. It has some limits, of course, but it let’s you essentially watch code being built.

First, write or copy a couple of paragraphs in Word. I borrowed mine from Don Quixote, because it keeps coming up and I’m trying to remind myself that I should read it.

I’m going to keep this really simple. When I was working in the document production department of a law firm, one of the things we constantly came across was a difference in preferences among the lawyers about whether they wanted one or two spaces after a period. I’m a one-space-after-the-period kind of guy. I have my reasons, but I’ll save that discussion for when we meet at a dinner party somewhere. Cuz that’s the best dinner party conversation I have. I don’t want to use it up here.

You probably already know that Word has a Find and Replace feature. You just hit Ctrl + H, and that little box comes up.


I put a period and a single space(“. “) in the Find box and a period followed by two spaces (“.  “) in the Replace with box, click Replace All, and the work is done. Yeah, if there were abbreviations like “Dr.” and “Ms.” then I have to go back and fix a few things. I’m going to get to that in a later post. Suffice it to say for now that this couldn’t be much easier.

Here’s the rub: I know that I’m potentially going to do this 100 times a week. While hitting Ctrl-H and typing a couple periods and a few spaces only takes a few seconds, I also make the occasional typing mistake. Plus, 3 seconds 100 times a week is 300 seconds. That’s 5 minutes a week, 50 weeks a year… Over 4 hours! That’s 4 x my hourly rate every year to have me do something that the computer could do almost instantly if I had a button for it.

That might seem ridiculous, but if you’re part of a mid-sized or large organization, some number cruncher somewhere is doing calculations like that, or they’ll hire some Six Sigma black belt to come do it when they want to improve efficiency. Thinking about these things is also how you add business value. “Hey, boss, if you let me implement this solution with my team, it’ll cost you nothing and save you $2,000 over the next 5 years.” (Yes, on a team of document production folks in a mid-sized company, a simple macro could theoretically save a company that amount of money over that range of time. No joke. Of course, few custom programming solutions cost nothing. This is pretty unique ROI.)

So how do I take this one task and turn it into a macro? Record it.

Record Your First Macro

On the Developer tab, click the Record Macro button.


A Record Macro dialog will come up asking you to name the macro and assign it to a button or a keystroke. For now, just give it a name and click Ok. I’m going to walk you through how to add it as a button later. Your pointer now has a little cassette tape attached to it, because recording stuff used to have something to do with magnetic strips inside plastic cassette cases. Look it up, kids.


The record button also has changed to a Stop Recording button, and the Pause Recording button is clickable:


The first time I did this, I thought time mattered. Why else would there be a Pause button? Turns out that your macro recorder doesn’t care how much time you spend doing anything. It doesn’t track time; it only tracks actions. So while you’re reading this paragraph, Word isn’t recording anything. The time between when you hit the Record button and when you actually do something it will record won’t be part of the macro.

The Pause button tells Word to ignore actions. You can leave out stuff you want to do now but that you don’t want the macro to repeat in the future.

You could just go straight into recording the macro, but I want you to see some of the magic happening, so hit Alt + F11. This opens up a code editor that looks something like this:


We’ll look at all the bells and whistles later. Right now, look for a window on the left that says “Project – Normal” at the top. This is the Project Explorer Window. If you don’t see it, press Ctrl + R.

Within that window, you should see a selection tree that looks something like this:


Double-click the label “NewMacros.” Don’t worry about that weird symbol next to it for now. A text editing window opens up with the code for your macro.


See how it has the name “singleDouble” at the top? It’s calling it a Sub, which, again, we won’t worry about for right now. (“Don’t worry about that right now” is a mantra for all Learn-to-Code tutorials. There’s just no getting around it.)

The line that’s in there right now, “ShowVisualBasicEditor = True”, was recorded when we opened up this code editor. Next time you run the macro, it’s going to do that again. You can erase it if you want. I’m going to leave it in mine for now.

Leave that window up where you can see it, and go back to your sample document in Word. Press Ctrl+H. Nothing happens in your code window. Don’t worry. It’s still recording.

Enter your find and replace terms: period followed by one space (“. “) and period followed by two spaces (“.  “).  Still, nothing happens in your code window. I promise it’s still recording. Your cassette is still there.

Click Replace All and then clear any dialogs that come up. Did your code window just fill up?


Yeah it did. In the next post, I’m going to go over all of this in excruciating detail. Right now, I want you to go back to your Developer tab and hit Stop Recording.

You did it. You recorded a macro. But I stopped you from assigning it to a button or a keystroke earlier. So you can’t run it again without going into this code editor, pulling it up, and hitting the play button in there.


Crud. Ok. I’ll show you how to add a button to your Quick Access toolbar, but then I’m folding laundry and watching Downton Abbey.

Your Quick Access toolbar is that strip of buttons that resides just above or just below your ribbon, depending on your preferences. I keep mine below the ribbon. Yours may look a little different than mine, but it will have small icons and a little down arrow on the far end of it:


Click that arrow and select “More Commands…” from the menu that appears.


Your Options dialog comes up focused on the section for customizing the Quick Access toolbar. The column on the left is all the things you can choose from, and the column on the right is all the stuff currently in your Quick Access toolbar.


Find the dropdown above the column on the left labeled “Choose Commands From” and select Macros.


Unless you’ve got some extra add-ins or other custom tools installed, the only thing in the list should be the macro you just recorded.


It’s got a weird symbol next to it and a longer name than you thought you gave it, but that’s definitely it. Hit the “Add>>” button to include it in the Quick Access toolbar, and then click Ok. A button for your macro with that weird symbol should now show up on your toolbar.


Click it! Click it! Then click it again! And again! You’re excited!

Uh-oh… Every time you run it, it adds more space between the period and the next sentence. This is not exactly what we wanted. But there’s some good news here, too. Even though it didn’t do what you wanted it to, or what you thought it would, it did exactly what you told it to. It works! You pushed a button and made something happen that Word didn’t do on its own. You’re a (cheater) programmer!

This might be a little frustrating, but I’m going to end this post here and leave you with a couple challenges. First, figure out why the macro keeps adding space. Then, see if you can fix it. In the next post, I’m going to keep my promise and elaborate on the code in detail. I’m going to really drag it out and fill in the dummy gaps.

It’s about to get fun. Programming is problem-solving. That’s the primary aim. And it’s mostly about solving problems you didn’t expect, like this one. If you figure it out between now and the next post, leave your answer in the comments. I’ll be back soon with my answer.

Love and kisses,


OTRS Config Part III: The Admin Interface and Common Tasks


This will be the last of my planned posts on OTRS configuration. If you missed Part 1 or Part 2, be sure to check them out.  This post covers more concrete tasks and is less concerned with the abstract ideas covered in the first two posts. The content here was prompted by particular business needs, but based on my experience so far, it should have a pretty wide scope of application. Speaking of which…

Scope of Application

The descriptions and screenshots in this document were generated for and from a Linux system with the following setup:

  • CentOS 6.4 or 6.5 | OpenSuSE 13.1
  • MySQL 5.1.71
  • OTRS 3.3.3 | OTRS 3.3.4
  • Apache 2.2.15 (Unix)
  • Viewed with Firefox 26

You might want to install a similar setup to follow along. But you can do all the same things on a Windows or Mac.

Admin Interface

The majority of the system configuration you do will be through the Admin tools in the OTRS web interface. This includes tasks we’ve already reviewed, like creating Groups, Roles, and Queues; assigning permissions; and associating different elements. OTRS has a relatively sophisticated set of administrative tools. The relationships of the various modules will take time and practice to master, but they are ultimately quite simple to navigate.

The one possible exception is the SysConfig interface, which we will look at next. Once you understand how it organizes the configuration modules, you will be able to take advantage of its power and convenience.


Much of the configuration of OTRS can be done through the SysConfig interface. Access the SysConfig interface by logging into OTRS and clicking the Admin tab. (If you do not have Admin access in OTRS, you will not see this tab.) SysConfig is in the System Administration group.


When you first open the SysConfig, there’s not much to see. The default view shows no modules. You begin navigating using the Actions sidebar on the left.


You can type specific terms into the search field, or you can filter by config groups. These groups take a little getting used to. As you get more familiar with the naming conventions used by OTRS, navigating to specific modules and properties via the config groups will get easier. The nice thing about OTRS being so popular is that you can find a lot of help online. (Note the self-fulfilling prophecy I just made!)

Before we get to looking at any of the modules, let’s Export the current settings.[1]

Exporting and Importing Settings

It is important to get into the habit of exporting the configuration settings before you make any changes—and especially before importing another collection of configuration settings.

Click the “Export Settings” button. You should see a dialog prompting you to save a Perl module file


Save the file somewhere that you can access it easily.

To import settings, click the “Import settings” button, browse for the file, and click “Submit.”

Module Access

Turn off Agents < – > Groups Assignments

Out of the box, OTRS allows you to assign Group rights directly to individual Agents.[2]


We’ve already reviewed the reasons that motivate us to assign Agent rights through roles exclusively. To enforce compliance with this policy, we can turn off access to the module that allows us to associate Agents directly with Groups.[3]

Note that turning off access to the module is not the same as disabling it. Any Agent-to-Group associations that have already been made will still be in place. Also, any action that redirects to the Agent-to-Group assignment will still be able to reach the module. The primary advantage of turning it off is that it eliminates accidental clicks and the amount of options you have to process as you perform administrative tasks.

Follow these steps to turn off the link:

  1. Navigate to the SysConfig interface.
  2. Select “Framework” from the dropdown on the left.


  3. Locate the module Frontend::Admin::ModuleRegistration and open it.


  4. Locate the property Frontend::Module###AdminUserGroup.


  5. Uncheck the box next to this property.


  6. Scroll to the bottom of the page and click Update.
  7. To make sure you’ve turned off the link, go back to the Admin interface. You should no longer see “Agents < – > Groups” under the Agent Management settings.



It is possible to change the workflow routes of OTRS, helping to prompt users through the experience they prefer.

Set the page Customers see at login

By default, when customers log on they see an overview of their open tickets. If that’s what your customers are used to, that’s great. But many customers are used to seeing a ticket entry screen when they log on to their help desk. To ease the transition to OTRS for these folks, we would want to preserve that experience.

  1. Navigate to the SysConfig interface
  2. Select “Ticket” from the dropdown on the left
  3. Locate and select Frontend::Customer
  4. Locate CustomerFrontend::CommonParam###Action. By default, this is set to CustomerTicketOverviewcustomerfrontend-action-overview
  5. Change the value to CustomerTicketMessagecustomerfrontend-action-message
  6. Click “Update”
  7. Log into the Customer portal to confirm that you are redirected to the new ticket view by default

Tip: You can often find out the name/value of a particular view by visiting that page and examining the URL


Changing the Appearance of OTRS

Change the Headline and Logo

default-headline                                                                          default-logo

OTRS uses its own logos and icons by default. Wouldn’t you? To place your own brand on the environment, you need to change the headline and logo. First, you’ll need an image. The OTRS blog recommends that the image be 135 x 50 pixels, but you can figure out the best size for your image through experimentation. In our case, let’s assume the image is named HelpBrand.jpg.

  1. Place the image in $OTRS:var/httpd/htdocs/skins/[Agent | Customer][4]/default/img
  2. Navigate to the SysConfig interface in OTRS
  3. Select “Framework” from the dropdown on the left
  4. Locate and select Frontend::Customer
  5. Change CustomerHeadline from “Example Company Support” to your desired text
  6. Find the group of CustomerLogo settings and change the URL to skins/Customer/default/img/HelpBrand.jpg
  7. Click “Update”
  8. Navigate to the Customer portal. You should see your changes reflected there

This help desk is gonna fly now!


To change the logo on the Agent side, adjust the corresponding AgentLogo settings in Frontend::Agent.

Ticket Settings

This section covers different ways to change what users and agents can and must input when filling out a ticket.

Make Time Units Mandatory

Agent tickets have time accounting turned on by default, but it is not a required field. Many organizations want time accounting to be required. Here’s how to do that:

  1. Navigate to the SysConfig interface
  2. Search for “time units”
  3. Depending on what packages you have installed, you may see only see one result here: Frontend::Agent. If you have the iPhone module installed, you will see more results. Select the subgroup “Frontend::Agent” in the group “Ticket.”
  4. There are a couple dozen settings here. You can use Ctrl + F to search for “time” or “account.”
  5. Ticket::Frontend::AccountTime should be set to “Yes”ticket-frontend-accounttime
  6. We are specifically looking for “NeedAccountedTime.” OTRS uses “Need” as a keyword to indicate that a field is required.[5] By default, this is set to “No.” Change it to “Yes.”ticket-frontend-accounttime-drpdwn
  7. Click “Update”
  8. Create a new ticket as an Agent by clicking Tickets>New Email Ticket
  9. Scroll down until you see the “Time units” field. It should have a star by it and be in black text instead of gray.


Add a New Ticket button to the customer interface

Out of the box, OTRS includes the “New Ticket” button in a dropdown menu in the Customer’s Ticket Overview interface.


While this may be accessible enough and intuitive to the vast majority of users, the dummies like me need a button that they can access a little more directly. Otherwise, we spend the first couple of weeks filling out phone request tickets for how to access the New Ticket button.

  1. Navigate to the SysConfig interface
  2. Choose “Ticket” from the dropdown on the left
  3. Find and select Frontend::Customer::ModuleRegistration
  4. The first group of settings is CustomerFrontEnd::Module###CustomerTicketOverview. This defines what the customer will see in the various menus and submenus throughout the customer interface. We’re going to stay within the CustomerTicketOverview section, but I recommend that you look over all of these settings and get familiar with them.sysconfig-customerticketoverview
  5. Notice the NavBarName property. By naming the NavBar, we are able to group and order actions, as well as persist a single NavBar across views.
  6. Scroll to the bottom of the NavBar entries, for CustomerTicketOverview. If you’ve made no changes, there are two of them: “Tickets” and “My Tickets.”
  7. Find the plus sign after the last entry, and click it.sysconfig-customerticketoverview-detail-filled
  8. The page will reload and give you an empty set of parameters. Fill them in as follows:
    • Description:       New Ticket
    • Name:                   New Ticket
    • Link:                      Action=CustomerTicketMessage
    • Priority:                90
    • AccessKey            n
  9. Click “Update”
  10. Log into the Customer portal. You should now see the “New Ticket” button in the NavBar


Dynamic Fields

Dynamic fields are how you gather information the developers of OTRS either didn’t think about or didn’t care about when they designed the system. Every organization has their own interests, and OTRS provides the flexibility to customize what data you’re tracking and presenting. We’ll look at one example: adding a branch name to a ticket. Warning: This is a long one! Adding dynamic fields and confirming they work takes quite a bit of setup.

Add a Branch field to the ticket

  1. Navigate to the Dynamic Fields Management interfaceticket-settings-tools
  2. Select “Dropdown” from the Ticket dropdown on the left.dynamicfieldsmanagement-overviewticket-dropdown
  3. Fill out form with the following details:
    • Name:             ddBranch
    • Label:             Branch
    • Field order:    1 (don’t worry about replacing anything that’s there)
    • Validity:         Valid
  4. Click the plus sign next to Add valueadd-value
  5. Set the Key to “101” and the Value to “Support Group”
  6. Set the Default Value to “Support Group”drpdwn-settings-supportgroup
  7. Leave the remaining settings as they are, and click “Save”
  8. Your new Dynamic Field should appear in the Dynamic Fields Listdynamic-fiels-list
  9. Navigate to the SysConfig interface
  10. Choose “Ticket” from the dropdown on the left
  11. Find and Select Frontend::Customer::Ticket::ViewNew
  12. Find Ticket::Frontend::CustomerTicketMessage###DynamicFieldticket-frontend-dynamicfield
  13. Click the plus sign
  14. Enter the key of your Dynamic Field (in this case “ddBranch”) and set the Content value to 1 (Enabled)key-content-filled
  15. Click “Update”
  16. Go back to the SysConfig interface
  17. Choose “Ticket” from the dropdown on the left
  18. Find and Select Frontend::Agent::Ticket::ViewZoom
  19. Scroll down to Ticket::Frontend::AgentTicketZoom###DynamicField
  20. Click the plus sign.
  21. Enter the key of your Dynamic Field (in this case “ddBranch”) and set the Content value to 1 (Enabled)
  22. Click “Update”
  23. We’re almost finished, but we need to make sure that OTRS displays the entire value of the field without truncating it. So go back to the SysConfig interface one more time
  24. Choose “Ticket” from the dropdown on the left
  25. Locate and select Frontend::Agent
  26. Locate Ticket::Frontend::DynamicFieldsZoomMaxSizeSidebar
  27. The default value is 18 characters. Set it to 140 (or whatever length you know you need)fields-zoom-max-sidebar
  28. Click “Update”
  29. Log into the customer interface
  30. You should see your  new field at the end of the default fields with your default value selectedbranch-dropdown
  31. Fill out and submit a test ticket
  32. Log into the Agent interface
  33. Locate and open your test ticket
  34. You should now see your Dynamic Field in the Ticket Information sidebar



I’ll continue to use OTRS and so may come across something new to share from time to time, but this ends my original trilogy of configuration posts. OTRS has plenty more features to explore, but we’ve covered all the major bases.  If you followed me this far, you should be able to tackle quite a bit more on your own. Feel free to use the comments here to drop a line and ask me questions. If there’s any way I can lend a hand, I will.

Love and kisses,


[1] Technically, OTRS actually stores all of its default settings. Anything you change in the SysConfig can be reset to the defaults pretty easily. Backing up the settings will become increasingly important as you customize the environment further.

[2] If you are not sure what Group rights are, review the OTRS documentation on Groups.

[3] Of course, the System Administrator will always be able to turn access to this module back on, but removing the option from plain sight will help us avoid mistakes.

[4] [Agent | Customer] should be read as “Agent or Customer,” and indicates that you will need to put it in each of the directories. The tree structure is otherwise the same. In the example, we’ll be changing the image on the Customer side.

[5] OTRS also sometimes uses the word “Mandatory” instead of “Needed.” See Ticket::Frontend::CustomerTicketMessage###ServiceMandatory.

OTRS Config Part II: A Sample Workflow


This post builds on OTRS Config Part 1. If you ended up here first somehow, you might want to go back and check that one out first. This is a more grounded, concrete example of the high-level ideas introduced in that post. Hopefully it brings a lot of that stuff home. And there’s more in Part 3, if you’re the kind of person who likes to skip ahead.

Scope of Application

The descriptions and screenshots in this document were generated for and from a Linux system with the following setup:

  • CentOS 6.4 or 6.5 | OpenSuSE 13.1
  • MySQL 5.1.71
  • OTRS 3.3.3 | OTRS 3.3.4
  • Apache 2.2.15 (Unix)
  • Viewed with Firefox 26

You might want to install a similar setup to follow along. But you can do all the same things on a Windows or Mac.

An OTRS Workflow

Below I have built on the abstract workflow included in the previous post. In this example, a user sends in a request for help installing a new printer. Review the workflow carefully. Try to answer the following questions:

  • What Queues, Groups, and Roles will we need?
    • Hint: The “Printer” Queue is a Sub-Queue of the “Hardware” Queue
  • What rights do the techs in the respective Roles need to the Queues


By my count, we need the following:

  • Queues
    • Unassigned
    • Hardware
    • Printer, as a Sub-Queue of Hardware
    • QA[1]
  • Groups
    • Tier 1
    • Tier 2
  • Roles
    • Tier 1
    • Tier 2[2]

As we discussed before, when you create a Queue in OTRS, you must associate it with a Group, so we’ll start by creating our Groups.

Create a Group

Log into OTRS and go to the Admin interface. Under Agent Management, you will find a link to the Group Management interface.


When you click it, you’ll first see a list of existing Groups. In a fresh installation, there will be only three: admin, stats, and users. If you have installed additional modules, such as the FAQ, there will be more. We’re going to create a new one called “Tier 1 Group” by clicking the Add Group button on the left.


It really couldn’t be any easier. There’s one required field: Name.


You can add a comment to elaborate on what the Group is or why you’ve added it, but it’s not necessary.

By default, the validity of the group is “valid,” which means that it is active and accessible to those with rights to it. When something is “invalid,” it becomes inaccessible to everyone who is not an administrator.

I’ve created the group as follows:


You should have noticed that I used “Group” in the name. This is because I’m also going to create a Role called “Tier 1,” and having “Group” and “Role” in the names of each one will help me keep them straight.

After you click “Submit,” you’ll be redirected to the Agent-Group relationship management interface. Remember that we don’t want to associate Agents directly with Groups, so you should just cancel out of this step or go back to the overview.

When you return to the list of Groups, you should see yours in the list.[3]


Repeat these steps to create the Tier 2 Group (and a Tier 3 Group if you think you’re going to need one), and then move on to creating Roles.

Create a Role

Creating Roles is just as easy as creating Groups. Go to the Role Management interface by clicking the Roles link in the Admin interface.


Click the “Add Role” button on the left. Just as you did with the Group before, give your Role a name and a descriptive comment. I filled mine out as follows:


Upon clicking “Submit,” you should be redirected to the Role Management interface where you will see your Role in the list.


Follow the same steps to create the Tier 2 Role (and Tier 3 if you need it), then go back to the Admin interface.

Relate a Role to a Group

Now we need to set up the Role-Group relationship. Click on the Roles <-> Groups link to enter the Role-Group management interface:


Remember that you can approach this in one of two ways: you can select a Group and set up access for multiple Roles, or you can select a Role and set up access to multiple Groups. We’re going to pick a Role at a time. You should see your Tier 1 and Tier 2 Roles on the left, with your Groups on the right.


Click the Tier 1 Role to open up the relationship manager for this Role:


We created the Tier 1 Role to grant all Agents with Tier 1 responsibilities access to all the Queues in the Tier 1 Group. To do so, click all the boxes in the Tier 1 Group row.


Click “Submit” to return to the Role-Group relationship management interface. Repeat the same steps to grant the proper rights to the Tier 2 Role, except you’ll want to include rights to both the Tier 1 and Tier 2 Groups.


Unfortunately, we cannot duplicate Role-Group relationships and build on top of them. You have to start each one from scratch. Of  course, that’s still better than having to do it for every single Agent.

We’re giving the Tier 2 Role rights to both groups here so that we can give each Agent a single assignment (Tier 1 or Tier 2) later. An alternative method would be to give the Tier 2 Role rights to only the Tier 2 Group, then to assign Agents with Tier 2 responsibilities to both the Tier 1 and Tier 2 Roles. This is a matter of preference.

Create a Queue

We’re going to venture beyond the Agent Management tools now and use the Queue Settings.


You can see that there are a lot of settings related to Queues. We’re going to do a pretty basic setup that sticks to the system defaults, but you should take some time to explore your options. Queues can have a variety of Auto Responses (messages that the system sends back to Customers automatically based on certain events), Templates (default text Agents can use when replying to Customers), a store of Attachments to associate with different Templates, and Salutations and Signatures that you can sandwich around your Templates. The system comes with a few of these built in, but you’ll have to modify things like the company name and address to reflect your organization.

For now, let’s just build a Queue. We’ll start with the “Unassigned” Queue, as every message that comes in should go there.

Click the Queues link to access the Queue Management interface.


The first thing you’ll see is a list of the built-in Queues.


To add your own, click the “Add queue” button on the left. Creating a Queue is quite a bit more involved than creating a Group or a Role, as you can see from the form.


Luckily, it fills in most of the required fields with system defaults for us. Let’s take a look at each of them.


First, there’s the Name field. If you’re still not sure what to do here, you might not be system administrator material.


Note that I didn’t include “Queue” as part of the name here. This, again, is a matter of preference. Queues are easy to differentiate from other system elements—unlike Groups and Roles, which are virtually identical in form and function.

Sub-Queue of

Next, we have the Sub-queue field. It’s not required, and because “Unassigned” is a top-level Queue in our case, we’re not going to make it the Sub-queue of anything. We’ll revisit this in a bit.


Everyone should have access to the “Unassigned” Queue, so we’ll associate it with the Tier 1 Group.


Unlock timeout

The next setting has to do with ticket accessibility. When a ticket is “locked,” only the Agent who has locked it can take certain actions on the ticket. To prevent situations where a ticket can’t be worked because an Agent is unexpectedly out of the office or has simply neglected too many tickets, you can set an “Unlock timeout” for each Queue.


The system will automatically unlock any tickets that pass the timeout so that any Agent with access to that Queue can take appropriate action on that ticket. By default, this is empty, which establishes no timeout. We’re going to leave it that way in this example.

The next three settings are for escalation. These are also empty by default, which means tickets in this Queue won’t escalate. We’ll leave those blank, but I’ll provide a brief overview of what the settings are, as this is something that we had to review several times before we were all on the same page about how they work:

  • Escalation – first response time
    • The number of minutes from the time the ticket is created until a ticket with the “new” state-type will escalate.
    • You prevent this escalation by taking one of two actions on the ticket:
      • Phone Call Outbound
      • Reply to Customer
      • Note that you must have communication with the Customer recorded on the ticket to prevent escalation
      • Example: If the first response time escalation is set to 10 minutes, you must respond to the customer within 10 minutes of ticket creation to prevent escalation
  • Escalation – update time
    • The number of minutes from the time a ticket acquires an “open” state-type until a ticket with an “open” state-type will escalate.
    • You prevent this escalation by taking one of two actions on the ticket:
      • Phone Call Outbound
      • Reply to Customer
      • Once you make contact with the customer, this timer resets to 0 on that ticket and starts counting again.
      • Example: If the update time escalation is set to 20 minutes, you must communicate with the customer every 20 minutes to prevent escalation.
  • Escalation – solution time
    • The number of minutes from the time the ticket is created until a ticket will escalate if it does not acquire a “closed” state-type.
    • You prevent escalation by closing the ticket.


Notify by

Each escalation type also has a “Notify by” setting.


This tells the system that when a ticket in this Queue is XX% close to the escalation point, send out a notification of that ticket’s escalation progress. Who receives that notification depends on your notification settings.

Follow up Option

Next we have the Follow up Option.


I’ll briefly describe these settings:

  • New ticket – customer replies to closed tickets in this Queue will open a new ticket
  • Possible – customer replies to closed tickets in this Queue will reopen the existing ticket
  • Reject – customer replies to closed tickets in this Queue will be rejected, and the customer will receive an email letting them know their request was rejected.

The default is “possible,” and we’ll leave it there.

Ticket lock after a follow up


The next setting is closely related to the Follow up Option. “Ticket lock after a follow up” determines whether or not the ticket is locked to the ticket’s previous owner when a customer follows up. For example, say I own a ticket that was closed yesterday. Today, the customer realizes that the issue is not completely resolved. (I’m kind of a slacker.) She replies to the closed ticket, either via email or the customer web portal, and that reopens the ticket. If “Ticket lock after a follow up” is set to “Yes,” that ticket will automatically be locked to me. If it is set to “No,” I will still be the Owner, but the ticket will be unlocked.

The default setting is “No.”

System address

If you have configured outgoing mail, you will be able to select which address should appear in the “From” field in emails from this Queue.


You have to choose an address. The system default is otrs@localhost.

Default sign key

If you are using PGP, you can specify a sign key with this setting.

Salutation and Signature


These settings are self-explanatory. If you think of your reply emails as a sandwich, the Salutation and Signature are the bread, and the Template is the marshmallow fluff. (The attachment is the side of bacon.)


Calendars really deserve their own discussion. The basic point is that you can define up to 9 different calendars (plus a system default) in the SysConfig. Each Queue can be associated with any single calendar, but not multiple calendars. If you don’t select one of the 9 named calendars, the Queue will follow the system default.



You’ve seen this everywhere else you’ve created an element with the system. You can turn Queues on and off with this setting.


Add a descriptive comment to the Queue to help explain what it is.


When you hit “Submit,” you will be redirected to the Template-Queue relationship manager interface. Since we haven’t set up any templates yet, you should only see the “empty answer” template. It’s not necessary to associate a Queue with a template immediately (or ever, for that matter). You can come back and manage Queue-Template relationships in much the same way that you manage other relationships.

That’s it. You’ve added a Queue. Follow the same instructions for the “Hardware” and “QA” Queues. You’ve probably already figured out what to do to add the “Printer” Queue, but just to make sure I’m not uncharacteristically concise,  I’m going to explain it in the next section anyway.


It is not possible to add a top-level Queue and a Sub-queue at the same time in OTRS. Even though we knew we needed a top-level Queue for “Hardware” tickets and a Sub-queue specifically for “Printer” hardware, we can only create them one at a time. While we can go back and make one Queue a Sub-queue of an existing Queue at any time, it makes the most sense to have our top-level Queues in place first.

Since you already created your “Hardware” Queue, we’re ready to add the “Printer” Sub-queue. All the steps for adding a Sub-queue are exactly the same as adding a top-level Queue. When making a Sub-queue, we’re just going to select a value in the “Sub-queue of” field.


Once you create a Sub-queue, OTRS uses the notation “Queue::Sub-Queue” to indicate the relationship among Queues.


It is possible to make Sub-queues of Sub-queues, but I am not aware how many levels deep you are allowed to go or if there is a limit.

Once you create a Sub-queue, the top-level Queue is still useable. In other words, you can still use the “Hardware” Queue even after you’ve added Sub-queues. That may seem intuitive, but not all systems work this way.


That about does it for the basics. Between this post and the previous one, you should have a pretty good idea of how to get rolling with OTRS. I’ve got a few more examples of how to get around in the administration interface and do some common tasks in Part 3, so be sure to check that out, too. Again, it’s not that this stuff is that hard to do, but it might save you from spinning your wheels.

Love and kisses,


[1] In this model, QA is a separate Queue. This is a matter of preference. You might prefer to add “QA” as a ticket state, which would not require us to move the ticket and would probably provide more accurate statistics—otherwise, all tickets will be closed from the QA Queue. Creating a separate Queue for QA simplifies the example, so that’s what we’ll do here.

[2] It’s not required that your Roles and Groups match exactly, but it makes the relationships clear and explicit.

[3] Note that alphabetization in OTRS is case-sensitive. “Tier 1 Group” is first in this list because it starts with a capital T.

OTRS Config Part I: Understanding Queues, Groups, and Roles


This is a reference for folks configuring (or thinking about configuring) an OTRS Help Desk in-house. OTRS Help Desk is an open-source trouble ticket system. It’s one of the most sophisticated and widely-used technical support systems out there. I’ve helped implement a few help desk systems over the last year, and I’ve been especially impressed with OTRS, especially considering that it’s free!
The documentation and community support for OTRS are equally impressive, but I found a few bits and pieces  a little difficult to wrap my head around at first. The official documentation was a good start, and there were some forum discussions that helped. But, I’m a dummy. And as I am wont to do, I started making notes to explain it to myself. I’m in the habit of doing this for two reasons.
First, projects stall out. You work hard on something for a month, you’re just getting into a groove and reaching maximum productivity when you have to stop work on project A and move to project B. Two weeks later, project A is top priority again. You’ve forgotten most of what was at the front of your mind, and now you have to start the learning process all over again. When I make my own notes, that re-ramp goes a lot quicker.
The second reason I make myself notes is turnover. You never know when you’re going to be out sick, find another job, or have to hand a project off to someone else for any number of reasons. There are things about any implementation that are unique to your organization, and having that stuff documented, at least in some form, makes for much smoother transitions.
I’m not officially a trainer, but documentation also helps with training. You don’t have to rely on your own memory for everything, and you can give people homework! (Maybe that’s how you ended up here right now!)
Anyway, I thought these notes might be of use to others trying to set up OTRS for the first time. This will be the first part of a series of posts on configuring OTRS. It will cover some of the high-level concepts about how to organize access rights within OTRS. If you’re planning to implement OTRS, this can help you plan an effective setup and possibly save you some refactoring of your environment later.

Scope of Application

(The “scope of application” section is a convention I’ll be using regularly. Software gets updated, blog posts go out of date, etc. It can be really useful to know what the original author was working with to figure out if any of it applies to you–and how directly.)

The descriptions and screenshots in this document were generated for and from a Linux system with the following setup:

  • CentOS 6.4 or 6.5 | OpenSuSE 13.1
  • MySQL 5.1.71
  • OTRS 3.3.3 | OTRS 3.3.4
  • Apache 2.2.15 (Unix)
  • Viewed with Firefox 26

You might want to set up your own installation (they have it for Windows and Mac, too) to follow along. But I’ll provide plenty of screenshots.


This is the first of three posts. If you like what you read here, you might want to check out Part 2 and Part 3.

Queues, Groups, and Roles

If you’re going to use OTRS, you will benefit from a detailed understanding of Queues, Groups, and Roles—and the relationships between them. Read the OTRS documentation on these subjects, and accept that mastery of these concepts will require some practice. I provide a brief description of each item here, and I follow that with a concrete example.

(Settle in for it. This is a long one!)

(Also, just so you know, I’m going to be weird about capitalizing the terms Queue, Group, and Role. It just helps me keep everything straight.)


When a customer reports an issue or incident, whether through the web interface or by sending an email directly into the system, this is a “Ticket.” We can organize or collect tickets into user-defined Queues. It might be helpful to think of Queues as issue categories or problem types.

In a shop of any size, it’s not hard to imagine a period of a few hours where tickets come in for a variety of issues: hardware, software, network, phone, etc. By collecting tickets into common buckets that reflect the type of problem at hand, we can target our focus and our efforts. It can also help managers make faster and more accurate decisions about how to prioritize the current workload.

You define what Queues and Sub-queues you want to use. OTRS provides a few out of the box, but they are non-descript. By default, tickets flow into a single Queue, and you can reassign them from there based on the content of the ticket. As you gain a better understanding of the system features, you can start filtering tickets to specific Queues or use multiple incoming email addresses (or aliases) to direct tickets to the desired Queue.

When you create a Queue, you will need to associate it with a Group. Group rights are how you define Queue access. Before you create your Queues, you’ll need to create some Groups.

Tip: It would probably be a good idea to define your Queues and Groups on paper first. In my mind, you would want to define Queues first, and then you can define the Groups that should have access to those Queues. Once these are defined, in OTRS you would create the Groups first, and then the Queues. You can experiment with creating the Groups and Roles within OTRS as you define them, but keep in mind that you cannot delete them from the system. You will avoid clutter by defining Queues, Groups, and Roles before you start creating them in the system.


Groups in OTRS should be thought of as collections of access rights. To some extent, you can also think of Groups as collections of Queues, though that limits their scope a bit. There are a few modules, including Stats (reporting) and FAQs, that don’t have Queues associated with them by default, but you still define access rights to their functionality through Groups. For this reason, you should not get in the habit of thinking of Groups exclusively as collections of Queues.

Groups define the following rights:

  • MOVE_INTO (move tickets into these queues)
  • CREATE (create tickets/articles in these queues)
  • NOTE (add notes to tickets in these queues)
  • OWNER (change the owner of tickets in these queues)
  • PRIORITY (change the priority of tickets in these queues)
  • RW (read-write access to tickets/modules in this group)
  • RO (read-only access to tickets/modules in this group)

You can see that the first five rights apply primarily to Queues, while the last two (RW/RO) are more closely related to modules like Stats and FAQ. Nevertheless, there is some overlap. Develop a bias toward thinking of Groups as collections of rights rather than collections of Queues.

When you associate a Queue with a Group, you are granting all the access rights defined by that Group to the selected Queue. (Don’t worry, there will be pictures soon.)


Now that you have some Queues that allow you to classify tickets, and you have Groups that define access rights to those Queues, you need to find a way to grant those rights to an Agent. There are two ways to do this. The first is to assign Agents directly to Groups. This is not generally regarded as best practice for large implementations. Instead, I recommend setting up Roles. Using Roles instead of assigning Group rights directly to Agents offers the following advantages:

  • You only have to configure the rights once, for the role.
  • You can associate multiple Agents with a Role in one swoop.
  • When Agents assume or discard a Role, you can add/remove rights by disassociating them from the Role—no need to update multiple rights on multiple groups.
  • When the responsibilities of a Role change, you only have to update them once for everyone associated with that Role.

The trade-off of using Roles is it requires a little more work up front. You have to define your Groups and Roles clearly to make sure that Agents get the rights they need. In the long-run, though, it will simplify administration.

Concrete Example of Queues, Groups, and Roles

Our Company and Where We’re Starting From

You work for the IT Department of Anonymous Business Company (ABC), a company of about 1500 employees with branches spread throughout the United States. You have a central IT location, so the vast majority of your support is handled remotely.

You have been using a home-brew Help Desk system for several years. Now that the company has grown, you’ve decided to implement OTRS to add functionality and features to your Help Desk that won’t require an investment in custom software development. You know that OTRS is powerful software that will bring you a lot of advantages, but it’s up to you to get the configuration right so this will be a smooth transition.

You’ve read through the OTRS documentation and understand that creating the right Queues, Groups, and Roles are vital to setting up an efficient workflow. Luckily, you’ve been in business for quite some time already. You’ve got a pretty effective workflow. There’s room for improvement, but you don’t have to start from scratch.

What OTRS calls Queues, you’ve called Categories—or work categories. OTRS is going to upgrade how you work with those categories, but the basic concept is the same. What they call Roles, you’ve also called Roles—Tier 1, Tier 2, Tier 3, Manager. What they call Groups, though, is new to you. You’re not quite sure where those fit. You know Groups define system access rights, but your home-brew system only had one set of rights. If you were in the system, you could do anything. Access and rights were enforced through training team members on what tickets they were responsible for and which ones they shouldn’t touch.

Let’s look at our current workflow. Before we start trying to upgrade or make changes, we’ll just try to match what we’ve got now as closely as possible.

Existing Workflow (Simplified)


Note: Oversimplification

The above example is, admittedly, oversimplified. To design your Queues, Groups, and Roles, you’ll need to have an intimate understanding of your entire process. For example, which Roles are allowed to review requests? When they assign it to a category, how do they determine which category it should be? When they assign it to an individual, how do they determine which individual should work the ticket? What does it mean to “work a ticket” or to “QA the work”?

I don’t attempt to answer those questions. Instead, I offer a more abstract example that doesn’t distract from primary concepts by going too deep into details that may or may not match your workflow. The above pattern should match that of any IT department that has committed to or is working toward industry best practices.

Matching the Existing Workflow

Based on the workflow above, we know we’re going to need OTRS equivalents for the following:

  • A web interface for entering requests
  • A way to label tickets as “Unassigned”
  • An account with permission to view and assign tickets
  • An account with permission to work a ticket
  • Multiple ticket categories and a way to label a ticket with its category
  • A way to label tickets as “In-Progress”
  • A way to label tickets as “QA”
  • An account with permission to view, update, and either reassign or close tickets labeled as QA

First, let’s just see if there’s a direct translation in OTRS for each of these:

Current System OTRS
Web Interface Web Interface
Way to label tickets “Unassigned” User-defined Queues
Account w/permission to view and assign Group/Role combinations to define and grant rights
Account w/permission to work a ticket Ditto
Multiple ticket categories and a way to label a ticket with its category User-defined Queues
A way to label tickets as “In-Progress” Combination of user- and system-defined ticket states
A way to label tickets as “QA” Multiple solutions. No one-to-one match
Account with permission to view, update, close QA tickets Group/Role combinations to define and grant rights

Not everything has a one-to-one match, but we’re pretty close. So let’s go ahead and try to create this workflow in OTRS.

Defining Queue-Group-Role Relationships

Before we create any Queues, we should really have some Groups and Roles in place. Earlier we identified Tier 1, Tier 2, Tier 3, and Manager as Roles in our current environment. They represent different scopes and levels of responsibility. But tickets go into Queues, and Roles can’t access Queues directly. They have to access them through associations with Groups… Ugh!

Before we try to tackle that, let’s see what the Queue-to-Role relationships are.

Consider the following relationship diagram, where the boxes are the Queues, and the figures with the checkmarks by their heads are the Roles:


This may or may not match your organization’s relationships exactly, but you can see that those with a Manager Role have responsibility for 6 Queues where those with a Tier 1 Role only have responsibility for (and therefore access to) only 3 Queues. You probably have a similar hierarchical model, whether formal or informal.

  • Standard requests can be fielded by any member of the team.
  • Network outages will be assigned to Tier 2 and above because these folks have enough training and familiarity with the environment to respond with the appropriate urgency.
  • Only Tier 3 and above can respond to VIP requests, as VIPs require distinct treatment.
  • Finally, only Managers have permission to approve and execute large hardware expenses.

Think about how your department handles different categories of problems with varying degrees of severity. You can probably come up with a diagram a lot like the one above to similarly define the Roles and Queues you’ll use in your organization.

The scope of responsibilities for each Role ends up looking something like this, growing with each additional Role:


Okay. We have an idea of a few Queues we want to use, and we have some idea of what Roles we’ll need and what kind of access they should be granted. How do Groups fit in?

To get a better sense of how using Roles can make your life easier, let’s take a look at the Agent Management tools in OTRS.


For a moment, let’s assume you don’t trust me. (And why should you?) You don’t buy this whole notion of using Roles to intermediate between Agents and Groups. OTRS provides a way to assign Agents directly to Groups, so let’s just do that.


When you manage Agent-Group relationships, you can either select a single Agent and make multiple Group assignments or select a single Group and make multiple Agent assignments.


Let’s start by selecting a Group.


Notice that this is actually pretty accessible. If you want to give all users MOVE_INTO rights to Queues in this Group, you just click the top checkbox in that column, and everyone gets those rights.


There are a couple limitations, though. You can only set rights for one agent or one group at a time. There’s no way, for example, to give Manny Manager and Tami Threetier Tier 1, Tier 2, and Tier 3 rights at the same time. You’d have to either give Manny rights to the three groups, then give Tami rights to the same three groups, or you’d have to give them both rights to Tier 1, then to Tier 2, then to Tier 3. Now imagine that you have half a dozen Groups and fifty Agents.

Actually, let’s look at an example with a larger user group. Here would be the Tier 1 Group access settings in a system with 16 Agents (including root):


Simple. Everyone who is an Agent is at least a Tier 1. Just click that top check box on each column (7 clicks). But say that only five of my folks are Tier 3. To set my Tier 3 rights to the below costs 35 clicks:


And now imagine that you want Tier 2 people to have MOVE_INTO rights to Queues in the Tier 3 Group. You don’t want them working those tickets, but you want to give them a chance to direct them to the right place. Clickety-click-click.

Three weeks later, tmoore is relieved of Tier 3 duties. The poor fella just wasn’t ready. That’s 7 more clicks to take those rights away. Two months after that, four Tier 2 folks get promoted to Tier 3—28 more clicks. The relationship looks a little like this:


We have to manage 16 individual relationships with the Tier 1 Group. That’s a lot of maintenance.

With Roles we simplify administration and cut down on potential and actual errors by reducing the number of clicks. The initial setup will seem just as labor-intensive, but if you design the relationships well, it will make long-term maintenance exponentially easier.

Let’s look at Queue-to-Role relationship with the Groups intervening (Manager Role and Group omitted for the sake of space):


Instead of having to manage 16 relationships with the Tier 1 Group, we only have to manage 4 (including the Manager Role—not pictured).

I know what you’re thinking. There are still 16 relationships to manage. How is throwing Roles into the mix making that easier? Don’t we have to manage 20 relationships now? Well, technically yes. But before you throw out the baby with the bathwater, let’s look at the Admin interface in OTRS again.

Managing Role-Group relationships is exactly the same as managing Agent-Group relationships. You can manage the relationship between a single Role and multiple Groups or between a single Group and multiple Roles.


In our case, it makes more sense to manage a single Role with multiple Groups. For the sake of this example, we have Groups and Roles for Tier 1, Tier 2, Tier 3, and Manager. Look at the settings below in order:

Tier 1 Role:


Tier 2 Role:


Tier 3 Role:


Manager Role:


These assignments should remind you of something…


It’s clear that administering these four relationships instead of 16 will be easier. We’ve cut out 75% of the effort. Well, almost. We still have to manage Agent-Role relationships.

The first thing you’ll notice is that the Agent-Role relationship management interface looks exactly like the other relationship management interfaces:


So what’s the difference? Let’s look at our Tier 3 assignments:


Instead of setting 7 rights per Group for each Agent, we only have to click once per Agent to assign them all the appropriate rights for the Role. By setting up the Role permissions correctly once, we’ve eliminated the need to set them up again for each Agent. And remember how we set up the Tier 3 Role so it includes all the rights to the Tier 2 and Tier 1 Groups? When we manage the Tier 2 Role relationships, if we forget to put a check next to tmoore’s name, he’ll still have all the rights he needs (until a couple weeks from now when he gets demoted again).

Remember the situation we considered before where we determined that folks in the Tier 2 Role should have MOVE_INTO rights on Tier 3 tickets so they can redirect tickets to the proper Queues. Suppose we have 10 Tier 2 people at that time. To change the rights for all 10 people, we only have to click once in the Tier 2 Role.


Easy peasy. Right?


There is a trade-off. It’s a minor one, in my opinion, but it’s worth noting. When you make direct Agent-to-Group assignments, you can refine the rights to a much higher degree. This may offer certain advantages in smaller shops where there aren’t really defined Roles (and you have the administrative slack to edit the access granted to individuals completely willy-nilly). Hopefully it’s clear that in larger organizations, you’d just be asking for trouble trying to administer every individual’s rights to every Group—especially where positions are fluid or turnover is high.

If Groups, Roles, and Queues still seem completely mysterious, I have some exercises designed to walk you through setting up a system to accommodate a sample workflow in Part 2. There’s also a Part 3, if you want to skip Part 2.

Love and kisses,


Of Course You Should Learn to Code. But Where to Start?

Everybody’s Who’s Anybody is Doing It

Almost everyone I talk to has at least a latent interest in coding. We all recognize the value of it. From Excel macros to personal web sites to Big Data (buzzword!) services, we’re all consumers of code–and eventually every one of us has that big app idea. “What if there were an app that could…?” “I wish I had an app that…” “They can make computers drive a car, tell me when my baby’s hungry, and spy on everyone in America, but why can’t my smartphone tell me…” (I’m having trouble coming up with something to finish that line. What can’t smartphones do now?)

Of course, there’s always going back to school. But only the nerdiest nerds find that path appealing. More often than not, the people I talk to want some tips on what they could do in their downtime at work and on the weekends at home to learn something useful. Since that’s kind of how I got into the game, I thought I’d share what I found useful. Again, this is just How This Dummy Did It. If you’ve done the same thing but different (and maybe better), I’d love to hear about it.

An Embarrassment of Riches

Truth is, there are more resources available to you than there are fans of Double Stuff Oreos. (Dear Nabisco, please sponsor this blog. Oreos preferred, cash acceptable.) Things have changed a lot over the last decade. When I started learning to code there was already an incredible wealth of information–a lot of it for free if you had access to the interwebs. But there were shelves and shelves of “Teach Yourself [Insert Technology Here] in 24 Hours” books well within reach of my allowance, too. Those kinds of books are still around, by the way. So there’s tip #1. If you already know what technology you want to learn, find a book on it.

As much as there was out there for the taking as soon as I got my first NetZero account, what’s available to the general public today is stunning. Coding has been called the literacy of the 21st century, and that’s not hyperbole. The job market demands more and more sophisticated computer skills. Knowing basic word processing no longer counts as being computer literate. And the number of technologies available just keeps growing.

The same thing that makes all of this overwhelming is the same thing that makes it awesome. There’s a website, a blog post, a discussion forum, an online pdf, a something-something for everything. This places you in the resource paradox presented by the interwebs: with so much info and so many resources available, where do I start?

Learner Matrix

Where you start learning to code will depend on a number of factors. I’ve come up with the following matrix–not to help you decide, but because this is how my brain is starting to work. (Unfortunately, it’s not interactive. You can click it if you want, but you’ll be disappointed. Unless you get satisfaction just from clicking the mouse. You like that “click-click” sound.)

Learner Matrix Image

There’s a pretty big spectrum available within that matrix. For the sake of argument, I’m going to imagine you fit a particular profile (the profile I fit when I got started) and take it from there.

But take that matrix at least a little seriously. Setting some realistic goals and plotting a learning path that’s right for you is going to be tremendously influenced by things like your self-startion. If you’re not a self-starter, you probably need at least a group of demanding friends with similar interests who will push you a bit. (Low on self-startion? Better be high on mentors!) If you have a really focused vision that involves programming mobile apps that call custom web services, but you have no equipment and no money, you might be backing yourself into a corner. That’s where the daring-do (yup–My Little Pony spelling; you’re on the interwebs now, brony!) comes in. If you’re low on current knowledge but high on smarts, you might be able to take a more accelerated approach than someone who’s low on smarts. So figure out where you are and where you want to go. If you have just have a vague, tangential interest in “coding” but no goal in mind, it won’t hold your interest.

Starting from Scratch (SFS)

So here’s your profile: you wouldn’t characterize yourself as knowing nothing. After all, you fired up your iPad and found your way to this blog. You know your way around a touch screen and how to navigate the web. But as soon as people start talking HTML and C++, here comes the flop sweat. You barely got out of high school French with a D, and now you’re expected to learn how to talk to a machine? At least on that trip to Paris, people understood your pee-pee dance. You and this computer have only one thing in common–not matter how you behave, it’s never good enough for your mother.

Oh, and you have time, but no money.

If you’re starting from scratch (you have no real knowledge of code, you have no money, but you have time and the desire to learn (if you don’t have time, you should find some blogs on time management, work on that, then come back here when you have time (I like to use a lot of nested parentheticals))), you’re what they call a noob. They will ridicule you for it. It’s not your fault, but you’re just going to have to accept your position at the bottom of the totem pole.

To start, I’d highly recommend Charles Petzold’s book, Code. I started it a little over a week ago, and I’ve only had time to get about 70 pages into it. But I’m already recommending it to everyone because it’s the most brilliant crash course in the fundamentals of computers that I’ve read. And it’s actually a fun read! I owe Sean Owen a debt for gifting me a copy of it. I should point out, though, that it’s not a how-to. It’s a Miyagi. You want to learn how to fight, and Petzold is going to teach you how to catch a fly with chopsticks.

“Tyler, I don’t want that,” you say. “I appreciate what Miyagi did for Daniel, but I’ve got plans and ideas! I don’t need to read about the history of the telegraph and Boolean algebra to get it. I need to write code!” I hear ya! I’m also an impatient jerk. So I’m going to give you the same direction I gave myself.

Learn HTML. It’s easy, it’s free, and nearly everything uses HTML or some technology that resembles it (XML and XAML come to mind). It used to be primarily for web, but since everything is web, mobile, or has a mobile/web component to it, it’s everywhere.

Learn the new stuff: HTML 5. And since you’re learning the new stuff, you’ll need to learn CSS. Also free and easy.

One of the nice things about HTML is that it’s really hard to break your computer with it. You might have some trepidation about that while learning to code. You know people who built applications that rendered their computers useless. HTML doesn’t carry any risk. You’ll learn more about this, but HTML is really just a way of telling your computer how to dress up your content. HTML5 has put more functionality into the language, but for the most part it still doesn’t do much of anything.

I’m not going to make a whole lot of suggestions about where you should learn HTML and CSS. That depends on you. I’m kind of a book learner, but there’s so much online that it really makes the most sense to find some web tutorials. I like W3schools, but it’s not the most dummy-friendly. It usually assumes some working knowledge of a few things. They’re also some of the best about listing prerequisites, though, so give it a go. If you just want to start trying to write HTML, there’s a cool test bed that will show you what it looks like when it’s rendered. I’ve also heard good things about Codecademy and Skillcrush. I haven’t tried either myself, so let me know if you like them!

A big chunk of learning how to code will be learning how to search for what you need to know online. Unless you’re really good at memorizing and have the time and the initiative to read the HTML5 specification, you’re eventually going to have to Google something. And since new resources crop up every day, Googling stuff is always worthwhile. That thing you couldn’t figure out how to do yesterday? Six people published blog posts about it last night. Not about you not being able to do it. They’re not out to embarrass you or anything. They were just trying to solve the same problem and shared their solutions. (Get a Stack Overflow account. When you need help and no one will answer your calls, some nerd will have an answer to your question there.)

Another advantage HTML offers the aspiring coder is that you can look at everyone else’s. You can basically look at the source code of every website ever. Right-click any web page and select “View Source” or “Inspect Element,” and you can sneak a peek at how everything’s put together. I’m not saying it’s always an easy read, but if you want to know how this was made, with enough time and persistence, you could figure it out and mimic it. That’s a really nice feature to have when you’re learning. You can find an example of what you want to do, copy-paste, and tweak to your heart’s content. This is true of a few other languages, as well, but there’s no source as widely available as HTML.

In addition to being free and easy, HTML is a good base for other things. You can use HTML to render mobile applications. A lot of hosted services for things like this blog allow you to customize their templates and tools with your own HTML, which means you don’t have to build everything from scratch. You can find existing templates for almost anything and then change the markup in a few places to make something surprisingly unique. Knowing the format of HTML will make also make learning XML easier, which will definitely come in handy.

Before you head off into the night with reckless abandon…

I mentioned this before, and I’ll mention it again. Have a project. Build a personal website to post your favorite recipes or display pictures of your dog (or the pictures you’ve been taking of your neighbor’s dog because you’re some kind of weirdo). Start a blog on a host like and write all your posts in raw HTML to practice. Make sure you use headings and images and fun stuff like that. Build a website to host your personal brand, or for that company you keep starting in your basement. It doesn’t have to be pretty. You don’t even have to publish it to the world. You can just have it on your own machine. (The tutorials will show you how.) If you don’t have a project, that’s what makes learning code difficult. There are too many things you can do with a little bit of computing power and a little knowledge. If you don’t know what your goal is, you’ll just get lost in a sea of tutorials trying to tell you things you have no idea how to apply. Figure out what you want to do, then target your learning toward that.

Coming soon…

So that’s one way in. In future posts, I’ll talk about the path I followed into making my computer do stuff. HTML is a great, low-risk introduction to coding. But I didn’t get really interested in code until I started to learn how to make my computer automate things for me. It’s easier than you think!

Love and kisses,



Why shouldn’t a blog have a foreword? With the brilliant literary precedent set in the print world by Sarah Silverman’s Midword, I think it’s time to rethink the blogular form. But that discussion really belongs on my personal blog, Love Calls Us. I’m already messing this up. And that brings us to the blog title.

I’m kind of a dummy–in the usual way. There are a handful of things I do really well. Then there are the other things: the things I’m fumbling my way through on my way to absolute awesomeness. One of those things has been a transition from teaching English for a living to being a professional software developer. I’m getting pretty good at parts of it.

My training as a writer has come in handy. I learn well through writing, and it helps me be more productive. You’ve had that experience where you study something really hard for a few days and then don’t actually need the knowledge until a couple months later, right? And then you have to start studying all over again? Well, I try to avoid those experiences by writing references for myself. They usually supplement a product’s official documentation with concrete examples I can wrap my head around… after I’ve done it half a dozen ways that didn’t work or that I realized later were miserable solutions.

I named the blog “How this Dummy Did It” based on those wrong ways. I like to document my process as I’m putting the pieces together (that’s what I call “failing” so I don’t have to call it “failing”). It’s a good learning strategy for me, and it helps me go back and put the bigger picture together a lot faster when I learn new stuff. Maybe if I get to a point where I’m not fumbling as much, I can change the title to “How This Developer Did It.” Or when I just do everything right the first time and better than everyone else, I can graduate to “How This Deodate Did It.” (Deodate means “gift from God.” It’s what they were going to call Oreos until some guy in the marketing department pointed out that people might think they were selling sweet fruits. This, of course, would make his job harder, and he wasn’t interested in that.) For now, though, Dummy seems about right. It’s mildly self-deprecating without completely discounting my self esteem.

I don’t come from a CS background like a lot of programmers, and there are more people like myself in the field of software development than I expected. I’ve probably met more people who came to programming from another field than I have people with CS degrees. There are a lot of materials in print and online that you can use to teach yourself to program. And the equipment and tools you need to learn and practice on are widely available–mostly for little or no cost. I’ve been on that journey for a little while, and I thought it would be fun to start sharing some of my progress. I’ve gotten where I am because other folks are willing to blog and share code and answer my questions on Stack Exchange. Maybe I can give someone else a leg up here and there by sharing what I learn. (Plus, I can use my blog as an online repository of these growing references! Take that, Google Drive!)

Ok, this is a tech blog (or it will be starting after this post). As I mentioned, I have a personal blog, which is where this kind of rambling will usually go. I just wanted to set the tone. This is my voice. Soak it in. And come back infrequently, cuz that’s how I post!

Love and kisses,