Week 26: Capstone: Service Portal Frontend, Packaging & Shipping

The last stretch: build the widgets end users actually interact with, wire them to the backend from Week 25, package the whole application the way Week 24 taught, and finish with something genuinely demoable — a scoped app with a real frontend, real tests, and a real approval workflow, built entirely by you.

Module 25 of 25 · Capstone, Part 2 Week 26 of 26 ~3–4 Hours Hands-on Exercise Included

By the end of this week, you'll be able to

  • Build a Service Portal request form and status-tracking widget for the capstone app
  • Wire both widgets to the backend built in Week 25, including the approval flow
  • Package the finished app via Update Set or Git and produce a portfolio-ready write-up

1. Building the Request Form Widget

Apply Weeks 10 and 12 together: a widget whose server script loads the catalog for a dropdown, and whose client controller submits a new request via c.server.update().

Server Script — equip-request-form
(function() {
  if (input && input.action === 'submit') {
    var gr = new GlideRecord('x_yourco_equip_request');
    gr.initialize();
    gr.requested_item = input.itemSysId;
    gr.quantity = input.quantity;
    gr.justification = input.justification;
    gr.caller_id = gs.getUserID();
    data.newSysId = gr.insert();
    data.submitted = true;
  } else {
    data.catalogItems = [];
    var cat = new GlideRecord('x_yourco_equip_catalog');
    cat.query();
    while (cat.next()) {
      data.catalogItems.push({ sysId: cat.getUniqueValue(), name: cat.getValue('item_name') });
    }
  }
})();
Client Controller — equip-request-form
function() {
  var c = this;
  c.data.quantity = 1;

  c.submitRequest = function() {
    c.data.action = 'submit';
    c.data.itemSysId = c.selectedItem;
    c.server.update().then(function() {
      c.submitted = c.data.submitted;
    });
  };
}

Notice the same action-flag pattern from Week 12 — one widget, two behaviors (load the catalog vs. submit a request) distinguished by what the client sends via input.

2. Building the Status-Tracking Widget

A second widget, applying Weeks 4 and 11: list the current user's requests with their live approval_status, styled distinctly per status using ng-class.

Server Script — equip-request-status
(function() {
  data.requests = [];
  var gr = new GlideRecord('x_yourco_equip_request');
  gr.addQuery('caller_id', gs.getUserID());
  gr.orderByDesc('sys_created_on');
  gr.query();
  while (gr.next()) {
    data.requests.push({
      number: gr.getValue('number'),
      item: gr.requested_item.item_name.toString(), // dot-walking, Week 2
      status: gr.getDisplayValue('approval_status'),
      statusValue: gr.getValue('approval_status')
    });
  }
})();
HTML Template — equip-request-status
{{r.number}} — {{r.item}} {{r.status}}

3. Assembling the Portal Page

Using the Service Portal from Week 9, build an "Equipment Requests" page with both widgets placed in containers, and confirm — logged in as a real requester, not admin — that submitting a request through the form widget immediately shows up in the status widget after a page refresh, with the correct auto-approved or pending status from Week 25's Business Rule.

4. Packaging & Shipping

Apply Week 24: connect the scoped app to a Git repository from Studio, commit the finished application, and confirm the repository contains real, readable files for your tables, widgets, Business Rule and ACLs — not just a single opaque export. If you'd rather demonstrate the Update Set path instead, export a complete Update Set XML containing every capstone artifact and confirm it imports cleanly on a second PDI.

5. The Capstone Project — Full Requirements

Capstone

Ship a complete, tested, secured ServiceNow scoped application

This is the full deliverable, spanning both Week 25 and Week 26's work — everything below should be true of your finished capstone.

Requirements:

  1. A scoped application with a finalized data model (Week 25 §2), reference fields correctly dot-walkable, and no admin-only shortcuts left in place.
  2. Row-level ACLs verified by impersonation, not just configured (Week 25 §3).
  3. A Business Rule and a Flow together implementing the auto-approval/manual-approval branch (Week 25 §4), each doing the part of the job it's actually suited for.
  4. At least two passing ATF tests covering the backend branch logic (Week 25 §5).
  5. A Service Portal page with a working request form widget and a live status widget, both correctly wired to the backend (Week 26 §1–3).
  6. The finished app packaged via Git-based source control or a complete Update Set, importable on a fresh instance (Week 26 §4).
  7. A short written summary (a paragraph or two) of the architecture decisions you made and why — which parts used a Business Rule vs. a Flow, and what your ACL model protects against.
What makes this a strong capstone

Not the size of the app — a small, fully-secured, tested, and correctly-packaged Equipment Request app is a far stronger portfolio piece and interview talking point than a larger app with no ACLs, no tests, and no clear story for how it would actually get deployed to a second instance.

6. Final Checklist

Before calling the capstone — and the course — done, confirm each of these honestly:

Does the full request → approval → status flow work end to end through the portal, logged in as a non-admin requester?

This is the single most important check — everything else in the checklist supports this one working flow being real and demonstrable, not just individually correct pieces that were never actually tested together.

Would your ACLs stop a requester from editing another user's request or approving their own?

If you haven't impersonated a second, distinct low-privilege test user and tried exactly this, you don't actually know the answer — confirm it directly rather than assuming the ACL configuration does what it looks like it should.

Do both ATF tests still pass after the frontend widgets were added?

Re-run the Week 25 test suite now — widget development sometimes involves small backend script tweaks along the way, and this is the check that nothing regressed in the process.

Could you hand your packaged Update Set or Git repository to someone else and have them stand up a working copy of this app on a different instance?

This is the real test of whether "packaging" (Week 24, Week 26 §4) actually worked — not just that an export file exists, but that it's complete and importable, which is exactly what shipping a real ServiceNow application requires.