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().
(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') });
}
}
})();
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.
(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')
});
}
})();
{{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
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:
- A scoped application with a finalized data model (Week 25 §2), reference fields correctly dot-walkable, and no admin-only shortcuts left in place.
- Row-level ACLs verified by impersonation, not just configured (Week 25 §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.
- At least two passing ATF tests covering the backend branch logic (Week 25 §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).
- The finished app packaged via Git-based source control or a complete Update Set, importable on a fresh instance (Week 26 §4).
- 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.
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?
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?
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?
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?
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.