December 20, 2025 / admin

TL;DR (≈ 90 words)

C-level sponsors want slick Fiori apps, but SAP backlogs say “six-month rollout.” In this guide we show how a Micro-GCC squad shipped six Fiori Elements apps in 20 working days by:

  1. Autogenerating UIs straight from CDS annotations.
  2. Using an Adaptive Cards factory for micro-tasks (approve, reject, comment) that embed in MS Teams.
  3. Wiring a GitHub CI pipeline that builds, tests and cache-busts UI5 in under six minutes.

Copy-paste Yeoman commands, CAP annotations, and Azure Bot JSON included.

Why Traditional Fiori Projects Drag 

Waterfall Fiori plan: design workshop ➝ SAP Build wire-frames ➝ hand-coded UI5 ➝ QA ➝ cut-over.
Pain points:

  • Five layers of hand-offs—design → dev → Basis → QA → DevOps.
  • UI regression each transport—static resources cached on every laptop.
  • Business users need micro-approvals in Teams, not another SAP tile.

Our fix: Generate 80 % of UI from CDS, keep logic in CAP, deliver micro-approvals through Adaptive Cards—two-sprint cadence.

Reference Stack 

LayerToolWhy
UI generatorFiori Elements + Fiori Tools YeomanNo hand-coded XML for CRUD screens
Micro-tasksAdaptive Cards + Teams Bot90-second approvals without launching SAP
OData serviceCAP Node.js (srv)Shares annotations & logic
StateHANA CloudSingle source of truth
CI/CDGitHub Actions + Cloud Transport Management (CTMS)Zero manual transports
Cache bustingsap-ui-cachebuster + CDN headersUsers always get latest JS/CSS

Total dev image size: 850 MB; pipeline duration: ≈ 6 min.

Sprint 1 — Generate Three CRUD Apps 

3.1 Scaffold UI Project

bash

CopyEdit

npm install -g @sap/generator-fiori

yo @sap/fiori-freestyle myorders \

   –platform cp \

   –odata https://<cap>/v4/sales \

   –entity SalesOrder \

   –list yes \

   –detail yes

Yeoman creates:

markdown

CopyEdit

myorders/

  webapp/

    pages/

    manifest.json

    ui5.yaml

3.2 Add CDS Annotations

db/schema.cds

cds

CopyEdit

using { cuid } from ‘@sap/cds/common’;

entity SalesOrder : cuid {

  key SalesOrderID  : String(10);

  @title  : ‘Net Value’

  NetValue : Decimal(15,2);

  @title  : ‘Currency’

  Currency : String(5);

}

srv/annotations.cds

cds

CopyEdit

using my.sales as sales from ‘../db/schema’;

annotate sales.SalesOrder with {

  @UI : {

    LineItem  : [ {Value : sales.SalesOrderID}, {Value : sales.NetValue} ],

    Identifiable : { Title : {Value : sales.SalesOrderID} }

  }

}

Re-run cds deploy → metadata changes auto-appear in UI after cache-buster.

3.3 CI Build & Deploy

ui5.yaml

yaml

CopyEdit

builder:

  customTasks:

    – name: ui5-task-cachebuster

github/workflows/ui.yml

yaml

CopyEdit

jobs:

  build-deploy:

    runs-on: ubuntu-latest

    steps:

      – uses: actions/checkout@v4

      – name: Install tooling

        run: npm ci

      – name: Build

        run: ui5 build –all

      – name: Deploy

        run: cf deploy myorders.zip –dest dev-space

Pipeline time: 3 m 40 s.

By Sprint 1 Demo Friday, business users saw live list-report and object pages for Sales Orders, Customers, and Pricing Conditions.

Sprint 2 — Adaptive Cards Factory 

4.1 Adaptive Card Template

cards/approve.json

json

CopyEdit

{

  “$schema”: “http://adaptivecards.io/schemas/adaptive-card.json”,

  “type”:”AdaptiveCard”,

  “version”:”1.5″,

  “body”:[

    {“type”:”TextBlock”,”text”:”Sales Order ${SalesOrderID}”,”weight”:”Bolder”},

    {“type”:”TextBlock”,”text”:”Net Value: ${NetValue} ${Currency}”},

    {“type”:”Input.Text”,”id”:”comment”,”placeholder”:”Optional comment”}

  ],

  “actions”:[

    {“type”:”Action.Submit”,”title”:”Approve”,”data”:{“action”:”approve”}},

    {“type”:”Action.Submit”,”title”:”Reject”,”style”:”destructive”,”data”:{“action”:”reject”}}

  ]

}

4.2 Node Bot for Teams

bot/app.js

js

CopyEdit

const { TeamsActivityHandler, CardFactory } = require(‘@microsoft/teams-ai’);

bot.onMessage(async (ctx) => {

  const so = await SELECT.one.from(SalesOrder).where({SalesOrderID: ctx.message.text});

  const card = CardFactory.adaptiveCard(require(‘./cards/approve.json’), so);

  await ctx.sendActivity({ attachments: [ card ] });

});

bot.onInvokeActivity(async (ctx) => {

  const { action } = ctx.activity.value;

  if (action === ‘approve’) await patchStatus(ctx, ‘APPROVED’);

  else await patchStatus(ctx, ‘REJECTED’);

  return { status: 200 };

});

4.3 CI Deployment

bot/workflows/ci.yml builds Docker image, pushes to Azure Container Apps, updates Teams manifest via Graph API.

4.4 Results
KPIBefore (Email Workflow)After (Adaptive Card)
Median approval time6 h 20 m21 m
Missed SLA (>24 h)13 %0.5 %
Mobile engagementN/A72 % of actions

Two-Sprint Timeline Overview 

DayActivity
Sprint 1 Day 1Yeoman scaffolds 3 apps; GitHub pipeline ready.
Day 3CDS annotations complete; first demos.
Day 5AT tests pass; deploy to QA.
Sprint 2 Day 1Teams Bot scaffold; Adaptive card template.
Day 3Webhook to CAP service for status updates.
Day 4Security & persona tests.
Day 520 % pilot group; cut-over Monday next sprint.

Total dev hours: ~64; feedback loop < 24 h each sprint.

Pitfalls & Fixes 

PitfallFix
Cache-busting ignoredAdd cachebuster-info.json & CDN header cache-control: max-age=0
CDS enum not rendered in listUse @Common.ValueList annotation referencing DDIC domain
Adaptive card timeoutIncrease Bot Azure Timeout to 10 s or pre-warm function
CAP OData $batch not enabledSet odata.version: 4 and odata.batch: true in package.json
Transport collisions (Neo)Use Cloud Transport Management; lock older transport serial

 Time & Cost Benchmarks 

MetricLegacy WorkflowTwo-Sprint Factory
Dev effort / CRUD app120 h18 h
Median user click → approve6 h21 m
UI regression bugs / rel.92
Infra cost (BTP HTML5 repo)€0.04/hrsame

ROI: 6× faster dev, 88 % faster approvals, happier auditors (mobile audit trail).

Take-Home Checklist 

  1. Scaffold Fiori Elements with Yeoman.
  2. Drive UI from CDS annotations, not XML.
  3. Ship CI build with cache-buster.
  4. Scaffold Adaptive Cards bot for micro-tasks.
  5. Route 20 % pilot traffic; measure approval SLA.