Lesson 2 of 6
Generating a CAP app: model, service, data and logic
9 min
Listen to this lesson
Elena creates a Full-Stack Application project from the SAP Build lobby and opens it in Business Application Studio. The project opens on the storyboard, a graphical view of data models, services and UI apps. From here, Joule works in four steps that SAP documents: generate a data model or service, enhance it, enrich sample data, and add application logic. Each step ends the same way: Joule shows the generated code, you choose Accept, and you preview with Run and Debug.
- Describe the modelOpen Joule from the activity bar, pick the slash command for data models and services, describe the business objects
- Accept and inspectNew entities appear on the storyboard; open the .cds files and read them
- Enhance sample dataData Editor, Enhance: describe realistic test rows; Joule updates the CSV data
- Add application logicApplication Logic Editor, Open Code Editor, Application Logic: describe the rule; Joule writes the handler
- Run and DebugPreview the service with the sample data and try the logic
Step 1: the data model and service
Elena's prompt is specific, because vague prompts produce vague models: "Create a warranty claim app. A Claim has a claim number, customer name, product (default CMC-ALT-100), serial number, failure date, failure description, claimed amount in USD and a status of NEW, IN_REVIEW, APPROVED or REJECTED. A Claim has many ClaimItems with part number, quantity and unit cost. Expose a ClaimService for claim processors."
Joule produces a schema and a service. Before accepting anything into the team's repository, she reads it against a checklist that comes from CAP's own conventions, not from Joule:
| Check | What good looks like | Typical generated gap |
|---|---|---|
| Keys | Entities use cuid (UUID keys) from @sap/cds/common | Integer or string keys typed by hand |
| Audit fields | managed aspect adds createdAt, createdBy, modifiedAt, modifiedBy | Missing, so nobody knows who changed a claim |
| Header and items | ClaimItems is a Composition of many from Claim, so items live and die with the claim | A plain association, which lets orphan items survive |
| Status | An enum or a code list, and a default of NEW | Free-text status field |
| Validation | Annotations such as @mandatory and @assert.range on amounts | No input validation at all |
| Authorization | @requires or @restrict on the service | Service open to any authenticated user |
Review generated CAP models against CAP conventions before accepting them.
Step 2: sample data
Sample data is test data, and generated test data is only as good as the request. In the Data Editor, Elena chooses Enhance and asks for twenty claims that cover every status, two claims for the same serial number, a claim with a zero amount and one at the maximum the business allows. She checks that names are invented and that amounts are plausible: a claim on a single CMC-ALT-100 shouldn't exceed its 240.00 USD list price. CAP loads CSV files from db/data named after the namespace and entity, so the data is plain text and easy to review in a pull request.
Step 3: application logic
The rule Elena needs: a claim can only move to APPROVED from IN_REVIEW, and a claim older than 24 months from the failure date is rejected automatically. In the Application Logic Editor she opens the code editor for application logic, describes the rule, accepts Joule's handler and runs it. The generated handler works for the happy path. It doesn't handle a missing failure date, and it compares dates as strings. Neither shows up in the preview, because the sample data has no such rows. That gap is the subject of lesson 5.
Iterating with Joule from the storyboard
You don't have to get the model right in one prompt. From the storyboard, the Joule icon on the data model or service tile opens Joule with that context, and you describe an enhancement: "add a rejection reason that is mandatory when the status is REJECTED". Joule shows the change and a summary; Accept applies it and the storyboard updates. Small, specific prompts produce small, reviewable changes, and each one can be checked against the model checklist before the next. Big prompts that rewrite the whole model make review harder and tend to undo earlier manual fixes, so commit to git after each accepted change you've reviewed.
What would you do?
Joule generated the model and service in two minutes, the preview works, and the sprint review is tomorrow. Grace asks whether the team can merge the generated code as is and "clean it up later". What do you recommend?
- Joule's full-stack flow: generate model and service, enhance sample data, add logic, then Accept and Run and Debug.
- Review generated CDS against CAP conventions: cuid keys, managed, compositions, enums, validation and authorization.
- Ask for sample data that covers edge cases, and keep it free of personal data.
- A working preview proves only the happy path with the data you gave it.
Check your understanding · not graded
Lesson check
1. In Joule's full-stack flow, what do you do after Joule shows generated code?
2. Why should claim items be a composition of the claim rather than a plain association?
3. Where does CAP pick up CSV sample data from in a project?
4. The generated handler passes in preview. What is the most likely weakness?