← Home
🔥0 DAY
0 XP
Interview Prep · CSM

CSM
INTERVIEW.

Four scenario lessons on Case management, Entitlements & Assets, the CSM/FSM data model, and ITSM integration — the exact Customer Service Management topics senior interview loops probe, each with a runnable simulator trace.

Pair with the ITSM guide and the HRSD guide for full platform coverage.

  1. 1. Case management — the CSM case lifecycle

    Walk me through what happens from the moment a customer submits a case in the portal to the moment it's resolved.

    How to answer

    • The base table is sn_customer_service_case (extends task). A case must be linked to an Account and a Contact — that's how entitlement lookups work.
    • State model: New → Open → Awaiting Info → Resolved → Closed. Assignment runs via matching rules or Advanced Work Assignment (AWA) when enabled.
    • Every case check-in touches the SLA engine (contract_sla) and, if the account has an entitlement, records service consumption on service_entitlement.
    • Closure requires resolution_code + resolution_notes; auto-close job (sn_customer_service.auto_close_resolved) moves Resolved → Closed after N days.

    Reference script

    // Before Insert BR on sn_customer_service_case
    if (!current.account) {
      gs.addErrorMessage('Case must be linked to an Account');
      current.setAbortAction(true);
    }
    if (!current.contact) {
      current.contact = new global.CSMContactResolver()
        .findByEmail(current.contact_email);
    }

    Pitfall

    Creating cases without an Account. Entitlements, SLAs and reporting all key off Account — an orphan case skips billing and never counts toward a contract.

  2. 2. Entitlements & Assets — proving the customer is covered

    A customer calls, but their contract is expired. What tables and checks decide whether we work the case?

    How to answer

    • Entitlements live on service_entitlement, linked to the Account (or a specific Product/Asset). Each has start_date, end_date, and units (cases, hours).
    • On case create, the Entitlement engine (EntitlementUtils) picks the best matching active entitlement — Account + Product + type — and stamps it on the case.
    • Assets (alm_asset / alm_hardware) that the customer owns are exposed as 'Install Base Items' on the account; a case can be tied to a specific asset for warranty checks.
    • If no active entitlement is found, the case is flagged 'not entitled' — agents can override with a manager role but the audit trail records the bypass.

    Reference script

    // Script Include: EntitlementUtils.check
    check: function(caseGr) {
      var ent = new GlideRecord('service_entitlement');
      ent.addQuery('account', caseGr.account);
      ent.addQuery('active', true);
      ent.addQuery('start_date', '<=', gs.nowDateTime());
      ent.addQuery('end_date',   '>=', gs.nowDateTime());
      ent.orderByDesc('priority');
      ent.setLimit(1);
      ent.query();
      return ent.next() ? ent.getUniqueValue() : null;
    }

    Pitfall

    Assuming an Account-level entitlement covers every product. If the entitlement is scoped to a Product (or Asset), the engine won't match cases about a different product — leaving customers 'not entitled' even though they pay.

  3. 3. CSM / FSM data model — Accounts, Contacts, and the split with FSM

    Explain the CSM data model and how it hands off to Field Service Management.

    How to answer

    • Core parties: customer_account (B2B), customer_contact (person at the account), consumer (B2C individuals). Contacts and Consumers both extend sys_user with restricted roles (sn_customerservice.customer, .consumer).
    • Products / Install Base: sn_customerservice_product_model → alm_asset instances the customer owns. Cases can reference either.
    • Case escalates to Field Service: from sn_customer_service_case → creates wm_order + wm_order_task on the FSM side. The case stays open until the work order closes.
    • Both share Territory and Skills tables — that's how AWA and Dynamic Scheduling route the same customer to the same tech across CSM & FSM.

    Reference script

    // Server-side transition: Case → Work Order
    var wo = new GlideRecord('wm_order');
    wo.initialize();
    wo.company           = current.account;
    wo.contact           = current.contact;
    wo.parent            = current.sys_id;   // links back to the case
    wo.short_description = 'Onsite for ' + current.number;
    wo.priority          = current.priority;
    wo.insert();
    current.work_notes = 'Field dispatch: ' + wo.number;

    Pitfall

    Duplicating Contacts. If a contact is created via portal self-registration AND the CRM sync, two sys_user rows point to the same email — entitlement and case history split across both.

  4. 4. CSM ↔ ITSM integration — when a case becomes an incident

    A customer reports an outage that's really a platform bug. How do we open an incident without losing the case audit trail?

    How to answer

    • Use the OOB 'Create Incident' UI action on the case — it copies short_description + description, sets parent = case sys_id, and stamps caller_id from the case contact's linked sys_user.
    • The case and incident are linked via task_relationship (or via the parent field on incident when using OOB). Case state moves to 'Awaiting Problem' while the incident is worked.
    • Assignment: incidents route through ITSM assignment groups (support tiers), not CSM matching rules. Keep the groups distinct — mixing CSM agents and ITSM engineers in one group breaks reporting.
    • When the incident is resolved, a Business Rule on incident.state=6 walks task_relationship, updates the parent case with resolution_notes, and reopens it for customer confirmation.

    Reference script

    // After Update BR on incident, when state changes to Resolved
    (function(current, previous) {
      if (current.state != 6 || previous.state == 6) return;
      var rel = new GlideRecord('task_relationship');
      rel.addQuery('child', current.sys_id);
      rel.addQuery('type.name', 'Duplicate');
      rel.query();
      while (rel.next()) {
        var cs = new GlideRecord('sn_customer_service_case');
        if (cs.get(rel.parent)) {
          cs.state = 16; // Awaiting Info (customer confirmation)
          cs.work_notes = 'Linked incident ' + current.number + ' resolved: ' + current.close_notes;
          cs.update();
        }
      }
    })(current, previous);

    Pitfall

    Closing the incident and forgetting the case. Without the relationship BR, the case stays 'Awaiting Problem' forever and gets flagged by SLA breach reports — customers get a ping from the SLA engine, not a resolution.

Keep going