@cspeach/cli 0.9.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/intent-system-prompt.js +1 -1
  3. package/dist/agent/loop.js +209 -20
  4. package/dist/agent/providers/license-gate.js +44 -0
  5. package/dist/agent/skill-checkpoint.js +1 -1
  6. package/dist/agent/tool-dispatch.js +15 -0
  7. package/dist/approvals/canonical.js +91 -0
  8. package/dist/approvals/jwt.js +39 -2
  9. package/dist/auth/org-anthropic-key.js +25 -0
  10. package/dist/classifier/client.js +18 -3
  11. package/dist/commands/config-set.js +95 -0
  12. package/dist/commands/login.js +31 -14
  13. package/dist/commands/plan-model-tier.js +83 -0
  14. package/dist/commands/plan-resume.js +148 -21
  15. package/dist/config/loader.js +95 -1
  16. package/dist/doctor/checks/_http-probe.js +1 -0
  17. package/dist/doctor/checks/cert.js +14 -3
  18. package/dist/doctor/checks/sap.js +30 -8
  19. package/dist/doctor/checks/zcspeach.js +19 -4
  20. package/dist/one-shot.js +52 -4
  21. package/dist/projects/answer-blockers.js +137 -0
  22. package/dist/projects/extract-cca.js +108 -16
  23. package/dist/projects/extract-modernize.js +1 -1
  24. package/dist/projects/extract-plan.js +130 -37
  25. package/dist/projects/extract-spec-gap.js +34 -7
  26. package/dist/projects/extract-test-coverage.js +1 -1
  27. package/dist/projects/extract-upgrade.js +113 -22
  28. package/dist/projects/index.js +5 -2
  29. package/dist/projects/merge-cca.js +292 -0
  30. package/dist/projects/merge-upgrade.js +173 -0
  31. package/dist/projects/migration.js +103 -1
  32. package/dist/projects/output-paths.js +27 -0
  33. package/dist/projects/plan-run.js +159 -25
  34. package/dist/projects/plan-schema.js +63 -3
  35. package/dist/projects/promote-command.js +25 -2
  36. package/dist/projects/promote.js +128 -0
  37. package/dist/projects/save-command.js +247 -20
  38. package/dist/projects/status.js +3 -1
  39. package/dist/projects/validate.js +1 -1
  40. package/dist/projects/workspace.js +164 -20
  41. package/dist/renderer/notices.js +64 -0
  42. package/dist/renderer/progress-chatter.js +8 -0
  43. package/dist/renderer/tool-widget.js +18 -4
  44. package/dist/renderer/tty.js +43 -4
  45. package/dist/renderer/verify-chain.js +77 -0
  46. package/dist/repl/at-picker.js +60 -7
  47. package/dist/repl/builtin-commands.js +37 -0
  48. package/dist/repl/early-line-buffer.js +68 -0
  49. package/dist/repl/inquirer-guard.js +70 -5
  50. package/dist/repl/numbered-menu.js +131 -0
  51. package/dist/repl/post-turn-status.js +2 -2
  52. package/dist/repl/rule8-detector.js +17 -2
  53. package/dist/repl/safety-confirm.js +111 -2
  54. package/dist/repl/safety-mode-state.js +19 -3
  55. package/dist/repl/slash-picker.js +10 -15
  56. package/dist/repl.js +301 -35
  57. package/dist/router/classifier.js +150 -6
  58. package/dist/sap/capability-matrix.js +20 -0
  59. package/dist/sap/capability-matrix.json +11236 -0
  60. package/dist/sap/capability.js +146 -0
  61. package/dist/sap/connection-manager.js +19 -1
  62. package/dist/sap/onboarding.js +42 -4
  63. package/dist/session/pending.js +27 -0
  64. package/dist/skill-catalog.js +48 -43
  65. package/dist/skills/bundled-skills.js +279 -1
  66. package/dist/skills/promotion-dispatch.js +23 -0
  67. package/dist/tools/_command-shared.js +36 -12
  68. package/dist/tools/_filesystem-shared.js +139 -4
  69. package/dist/tools/_flag.js +25 -0
  70. package/dist/tools/approval.js +64 -21
  71. package/dist/tools/ask-question.js +96 -4
  72. package/dist/tools/capability/tool.js +74 -0
  73. package/dist/tools/dispatch-skill.js +22 -1
  74. package/dist/tools/extend-model/anchored-insert.js +810 -0
  75. package/dist/tools/extend-model/tool.js +188 -0
  76. package/dist/tools/filesystem/extract-document.js +57 -0
  77. package/dist/tools/filesystem/file-edit.js +12 -2
  78. package/dist/tools/filesystem/file-read.js +2 -2
  79. package/dist/tools/filesystem/file-write.js +11 -2
  80. package/dist/tools/filesystem/glob.js +11 -0
  81. package/dist/tools/filesystem/grep.js +10 -0
  82. package/dist/tools/filesystem/read-document.js +107 -0
  83. package/dist/tools/fiori/apply.js +50 -0
  84. package/dist/tools/fiori/bin.js +3 -0
  85. package/dist/tools/fiori/catalog/index.js +27 -0
  86. package/dist/tools/fiori/catalog/value-help.js +230 -0
  87. package/dist/tools/fiori/catalog/viz-chart.js +177 -0
  88. package/dist/tools/fiori/cli.js +71 -0
  89. package/dist/tools/fiori/deploy-config.js +73 -0
  90. package/dist/tools/fiori/fe-scaffold.js +45 -0
  91. package/dist/tools/fiori/i18n.js +39 -0
  92. package/dist/tools/fiori/manifest.js +70 -0
  93. package/dist/tools/fiori/render.js +77 -0
  94. package/dist/tools/fiori/scaffold.js +39 -0
  95. package/dist/tools/fiori/tools.js +356 -0
  96. package/dist/tools/fiori/types.js +1 -0
  97. package/dist/tools/local-build.js +76 -0
  98. package/dist/tools/local-files.js +31 -0
  99. package/dist/tools/project/_merge-shared.js +68 -0
  100. package/dist/tools/project/cca_merge.js +164 -0
  101. package/dist/tools/project/playbook_get.js +1 -1
  102. package/dist/tools/project/upgrade_merge_progress.js +206 -0
  103. package/dist/tools/sap-read.js +53 -9
  104. package/dist/tools/sap-write.js +530 -21
  105. package/dist/tools/shell/shell_exec.js +41 -6
  106. package/dist/tools/snapshot.js +37 -14
  107. package/dist/tools/subagent/background_run.js +17 -1
  108. package/dist/tools/transport-resolution.js +86 -0
  109. package/dist/tools/transport.js +224 -5
  110. package/dist/tools/write-mode.js +4 -0
  111. package/dist/ui/app.js +6 -2
  112. package/dist/ui/body.js +13 -0
  113. package/dist/ui/footer.js +20 -6
  114. package/dist/ui/line-resolution.js +17 -6
  115. package/dist/ui/session-timeline.js +1 -0
  116. package/dist/ui/text-input.js +150 -0
  117. package/dist/ui/widgets/ask-question-modal.js +4 -1
  118. package/package.json +19 -3
  119. package/bench/README.md +0 -78
  120. package/bench/prompts/abap-document-cds.md +0 -44
  121. package/bench/prompts/abap-explain-bdef-handler.md +0 -57
  122. package/bench/prompts/abap-test-method.md +0 -42
  123. package/bench/results/abap-document-cds/claude-haiku-4-5.md +0 -189
  124. package/bench/results/abap-document-cds/claude-opus-4-7.md +0 -120
  125. package/bench/results/abap-document-cds/claude-sonnet-4-6.md +0 -151
  126. package/bench/results/abap-explain-bdef-handler/claude-haiku-4-5.md +0 -112
  127. package/bench/results/abap-explain-bdef-handler/claude-opus-4-7.md +0 -101
  128. package/bench/results/abap-explain-bdef-handler/claude-sonnet-4-6.md +0 -101
  129. package/bench/results/abap-test-method/claude-haiku-4-5.md +0 -186
  130. package/bench/results/abap-test-method/claude-opus-4-7.md +0 -193
  131. package/bench/results/abap-test-method/claude-sonnet-4-6.md +0 -234
@@ -1,189 +0,0 @@
1
- # abap-document-cds — claude-haiku-4-5
2
-
3
- - **skill:** abap-document
4
- - **description:** Document a CDS interface view with associations + currency annotation
5
- - **latency:** 26816 ms
6
- - **input tokens:** 2,688
7
- - **output tokens:** 2,623
8
- - **cost:** $0.0158
9
-
10
- ---
11
-
12
- # abap-document — ZI_SalesOrder
13
-
14
- ## TL;DR
15
-
16
- **Headline:** Interface view for sales order header data with customer and item associations, read-only with authorization check.
17
-
18
- **Top 3 (priority order):**
19
- 1. **Authorization enforced:** `#CHECK` mode requires `DSOD` and sales order read authority at runtime — verify user roles before consuming downstream.
20
- 2. **Fuzzy search enabled on CustomerID:** `fuzzinessThreshold: 0.8` will match partial/misspelled customer names; test with typical fat-finger errors in UAT.
21
- 3. **No filtering logic:** View exposes all rows from `zsales_order` table — upstream consumers must apply their own `WHERE` clauses; no automatic date range or status filtering.
22
-
23
- **Verdict:** Safe foundation view for consumption in analytics, APIs, or reporting. Confirm downstream apps implement business rule filtering (e.g., active orders only, date ranges).
24
-
25
- ---
26
-
27
- ## ZI_SalesOrder (CDS VIEW ENTITY)
28
-
29
- ### Overview
30
-
31
- **Package:** (not yet read — see below)
32
- **Type:** CDS View Entity (Interface Layer)
33
- **Annotations:** Authorization check enabled, search enabled, end-user label "Sales Order — Interface View"
34
-
35
- **Summary:**
36
- Exposes sales order header data from the custom table `zsales_order` with associations to customer master, line items, and SAP currency data. Designed as a read-only interface view for analytics, reporting, and API consumption.
37
-
38
- ---
39
-
40
- ### Purpose
41
-
42
- This view serves as the **interface layer** for sales order headers in the custom data model. It:
43
-
44
- 1. **Presents domain data cleanly** — maps technical table column names (`sales_order_id`, `customer_id`) to business-readable field names (`SalesOrderID`, `CustomerID`).
45
- 2. **Enforces authorization** — restricts read access to users with appropriate sales order query authority.
46
- 3. **Enables semantic search** — makes customer name searchable via fuzzy matching (0.8 threshold = allow 20% typos).
47
- 4. **Links related business entities** — connects to customer master, line items, and currency metadata via associations (no data duplication, navigation-based joins).
48
- 5. **Supports consumption layers** — designed for downstream consumption by reporting tools, OData APIs, or analytical views.
49
-
50
- ---
51
-
52
- ### Interface
53
-
54
- **Key Field:**
55
- - `SalesOrderID` (Header.sales_order_id) — unique identifier for the sales order
56
-
57
- **Header-Level Fields:**
58
-
59
- | Field Name | Source | Type | Purpose |
60
- |------------|--------|------|---------|
61
- | SalesOrderID | Header.sales_order_id | key | Sales order unique identifier |
62
- | CustomerID | Header.customer_id | string | References customer master |
63
- | OrderDate | Header.order_date | date | Date order was placed |
64
- | CustomerIDForSearch | Header.customer_id | string | Fuzzy-searchable copy for customer lookup |
65
- | NetAmount | Header.net_amount | decimal | Order value (currency-aware via annotation) |
66
- | CurrencyCode | Header.currency_code | string | ISO currency code |
67
- | CreatedAt | Header.created_at | timestamp | Audit: creation timestamp |
68
- | CreatedBy | Header.created_by | user | Audit: creator user |
69
- | LastChangedAt | Header.last_changed_at | timestamp | Audit: last change timestamp |
70
- | LastChangedBy | Header.last_changed_by | user | Audit: last change user |
71
-
72
- **Associations (Navigation):**
73
-
74
- | Association | Target View | Cardinality | Join Condition | Purpose |
75
- |-------------|-------------|-------------|-----------------|---------|
76
- | `_Customer` | ZI_Customer | 0..1 | CustomerID | Navigate to customer master data |
77
- | `_SalesOrderItem` | ZI_SalesOrderItem | 0..* | SalesOrderID | Navigate to line items for this order |
78
- | `_Currency` | I_Currency (SAP standard) | 0..1 | CurrencyCode | Navigate to SAP currency details |
79
-
80
- **Authorization & Search:**
81
- - Authorization check: `#CHECK` — runtime check required (user must have query authority for sales order).
82
- - Default search element: `CustomerIDForSearch` with fuzzy matching (80% match threshold).
83
- - Searchable: all marked fields indexed for full-text search.
84
-
85
- ---
86
-
87
- ### Logic Flow
88
-
89
- **Data Origin & Transformation:**
90
-
91
- 1. **Source:** Read all rows from custom table `zsales_order` (Header alias).
92
- 2. **Projection:** Map technical columns to semantic field names:
93
- - `sales_order_id` → `SalesOrderID` (key)
94
- - `customer_id` → `CustomerID`
95
- - `order_date` → `OrderDate`
96
- - `net_amount` → `NetAmount` (with currency semantic)
97
- - `currency_code` → `CurrencyCode`
98
- - Audit fields (created/changed by/at) mapped as-is.
99
- 3. **Duplicate CustomerID:** `CustomerIDForSearch` is a copy of `CustomerID` explicitly marked for full-text search (allows UI to search by customer name via the association).
100
- 4. **Associations:** Three navigation paths added (not joins — lazy-loaded):
101
- - To customer master for customer details.
102
- - To line items for order composition.
103
- - To SAP currency master for exchange rates, decimals, etc.
104
- 5. **Authorization Gate:** View enforces `#CHECK` at query time — SAP will validate user authority before returning rows.
105
-
106
- **No filtering logic:** View is a "raw interface" — all rows from the source table are exposed. Upstream consumers must filter by date, status, or other business rules.
107
-
108
- ---
109
-
110
- ### Data Access
111
-
112
- | Table/View | Operation | Purpose |
113
- |------------|-----------|---------|
114
- | `zsales_order` (custom) | **READ** | Source table for all header fields (sales_order_id, customer_id, order_date, net_amount, currency_code, audit fields) |
115
- | `ZI_Customer` (custom view) | **READ** (via association) | Customer master lookup; enriches orders with customer details |
116
- | `ZI_SalesOrderItem` (custom view) | **READ** (via association) | Line items for the order; enables per-item navigation |
117
- | `I_Currency` (SAP standard) | **READ** (via association) | SAP currency master; provides conversion rates, decimal places |
118
-
119
- **No writes:** This is a read-only interface view. No INSERT, UPDATE, or DELETE allowed.
120
-
121
- ---
122
-
123
- ### Dependencies
124
-
125
- **Called by (Upstream Consumers):**
126
- Unknown without further analysis — use `sap_usage_references` to identify (e.g., analytics views, OData services, reports using this view).
127
-
128
- **Calls (Dependencies):**
129
- - `zsales_order` — custom table (no option to change this view without understanding the source table schema).
130
- - `ZI_Customer` — custom customer interface view (ensure it is available and stable).
131
- - `ZI_SalesOrderItem` — custom sales order item interface view (ensure it exists).
132
- - `I_Currency` (SAP standard) — standard SAP currency master (no custom risk; always available post-installation).
133
-
134
- ---
135
-
136
- ### Authorization & Security
137
-
138
- **Authorization Check:** `#CHECK` mode
139
- - When a user queries this view, SAP **enforces** a dynamic authorization check at runtime.
140
- - The specific check depends on SAP's authority object mapping for CDS views (typically `DSOD` → Data Source Object Definition or equivalent).
141
- - **Action required:** Verify that user roles define query access for this view; otherwise, queries will fail with "Authorization error."
142
-
143
- **Search & Indexing:**
144
- - `CustomerIDForSearch` with `fuzzinessThreshold: 0.8` allows typo-tolerant search (e.g., "APLE" matches "APPLE").
145
- - Useful for user-facing search UIs; may return false positives in strict filter scenarios.
146
-
147
- ---
148
-
149
- ### Data Model & Semantics
150
-
151
- **Semantic Annotations:**
152
- - `@Semantics.amount.currencyCode: 'CurrencyCode'` on `NetAmount` — tells consuming systems that this field is a currency amount and which field holds the currency code. Tools like SAP Analytics Cloud will format it correctly.
153
- - `@ObjectModel.text.element: [ '_Customer.CustomerName' ]` on `CustomerIDForSearch` — tells UI frameworks to display the customer **name** (not ID) when showing this field.
154
-
155
- **Searchability:**
156
- - View is marked `@Search.searchable: true` — all fields with `@Search.defaultSearchElement: true` are indexed.
157
- - Only `CustomerIDForSearch` is explicitly indexed; other fields are not full-text searchable by default.
158
-
159
- ---
160
-
161
- ### Notes & Considerations
162
-
163
- 1. **No status filtering:** View exposes all orders regardless of status (open, closed, cancelled). If you need only active orders, add a downstream view or consuming WHERE clause.
164
-
165
- 2. **Audit trail:** `CreatedBy`, `LastChangedBy`, `CreatedAt`, `LastChangedAt` are available for compliance; confirm these are populated in the source table `zsales_order`.
166
-
167
- 3. **Association multiplicity:**
168
- - Customer is 0..1 (every order may not have a customer — nullable FK?). Verify business rule: must a sales order always have a customer?
169
- - Line items are 0..* (orders with no items are allowed). Confirm with business if this is intentional.
170
- - Currency is 0..1 (may not exist in SAP currency master for custom codes). Test with unusual currency codes.
171
-
172
- 4. **Search on CustomerID not CustomerName:** The view exposes `CustomerID` for search but links to `_Customer.CustomerName`. If users expect to search by customer **name**, ensure the downstream OData/UI binding is configured to search on `CustomerIDForSearch` and display `_Customer.CustomerName`.
173
-
174
- 5. **No performance optimizations:** View is a simple 1:1 projection. For large `zsales_order` tables (millions of rows), consider:
175
- - Adding a semantic partitioning hint in the view definition.
176
- - Creating secondary indexes on frequently filtered columns (e.g., `OrderDate`, `CustomerID`).
177
- - Testing query response times with large datasets.
178
-
179
- 6. **Missing fields?** Confirm with business that all required order header fields are in the projection. If fields exist in `zsales_order` but not exposed here, add them or create a second view variant.
180
-
181
- ---
182
-
183
- ## Next Steps
184
-
185
- 1. **Trace consumers:** Run `sap_usage_references` to identify which views, APIs, and reports consume this view.
186
- 2. **Verify source table:** Run `sap_get_source` on `zsales_order` to confirm the schema matches the projection.
187
- 3. **Check related views:** Retrieve `ZI_Customer` and `ZI_SalesOrderItem` to ensure the associations are compatible (key cardinality, join conditions).
188
- 4. **Authorization testing:** Create a test user with appropriate authority and verify they can query this view without "Authorization failed" errors.
189
- 5. **Search testing:** Test fuzzy search with intentional typos (e.g., customer name "ACME Corp" vs. search "ACME Crp") to confirm the 0.8 threshold behavior.
@@ -1,120 +0,0 @@
1
- # abap-document-cds — claude-opus-4-7
2
-
3
- - **skill:** abap-document
4
- - **description:** Document a CDS interface view with associations + currency annotation
5
- - **latency:** 42479 ms
6
- - **input tokens:** 6
7
- - **output tokens:** 2,798
8
- - **cost:** $0.2099
9
-
10
- ---
11
-
12
- ## abap-document — ZI_SalesOrder (CDS Interface View)
13
-
14
- ## TL;DR
15
-
16
- **Headline:** `ZI_SalesOrder` is a sales order header interface view exposing `zsales_order` with associations to customer, items, and currency, search-enabled on customer ID.
17
-
18
- **Top 3 (priority order — most important first):**
19
- 1. **Interface view in a VDM-style layering** — naming prefix `ZI_` and associations to `ZI_Customer` / `ZI_SalesOrderItem` indicate this is the I-layer; consumption should happen via a `ZC_` view, not directly.
20
- 2. **Search + text association configured on `CustomerIDForSearch`** — fuzzy search (threshold 0.8) with text resolved via `_Customer.CustomerName`; this field is a duplicate exposure of `customer_id` purely for search semantics.
21
- 3. **Amount/currency reference pair (`NetAmount` ↔ `CurrencyCode`)** is correctly annotated; `_Currency` association to `I_Currency` makes this view S/4-VDM-compliant for currency handling.
22
-
23
- **Verdict:** Clean, well-annotated interface view. No code-level concerns — main thing to confirm with the team is whether a consumption view (`ZC_SalesOrder`) exists on top and whether `CustomerIDForSearch` duplication is intentional.
24
-
25
- ---
26
-
27
- > ⚠️ **Note:** This documentation is based solely on the source you pasted. I did not call `sap_get_source`, `sap_object_structure`, or `sap_usage_references`, so package, author, change history, and where-used data are not included. If you want the full document with dependencies and metadata, re-run and I'll pull it from the system.
28
-
29
- ## ZI_SalesOrder (DDLS — CDS View Entity)
30
-
31
- ### Overview
32
- Package: *not retrieved* | Author: *not retrieved* | Last changed: *not retrieved*
33
-
34
- `ZI_SalesOrder` is an **interface-layer CDS view entity** over the custom sales order header table `zsales_order`. It exposes header fields, exposes associations to customer, items, and currency, and enables fuzzy search on the customer ID with the customer name surfaced as text.
35
-
36
- ### Purpose
37
- Provide a reusable, semantically annotated interface for sales order header data following VDM (Virtual Data Model) conventions:
38
-
39
- - Acts as the **single source of truth for the sales order header** in the I-layer.
40
- - Wires up the **associations** that downstream consumption views, Fiori elements apps, and analytical views can navigate (customer, items, currency).
41
- - Enables **enterprise search** over the order's customer with name resolution.
42
- - Establishes **currency semantics** so amounts render correctly in UIs and analytics.
43
-
44
- It does **not** implement business logic, filtering, or authorization beyond `#CHECK` (DCL-based row-level auth, if a DCL exists for this entity).
45
-
46
- ### Interface
47
-
48
- **Type:** `define view entity` (modern CDS, not legacy `define view`)
49
-
50
- **Source:** `zsales_order` (aliased as `Header`)
51
-
52
- **Key:**
53
- | Field | Type source | Notes |
54
- |---|---|---|
55
- | `SalesOrderID` | `Header.sales_order_id` | Primary key |
56
-
57
- **Exposed fields:**
58
- | Element | Source | Semantics / Annotations |
59
- |---|---|---|
60
- | `SalesOrderID` (key) | `sales_order_id` | — |
61
- | `CustomerID` | `customer_id` | — |
62
- | `OrderDate` | `order_date` | — |
63
- | `CustomerIDForSearch` | `customer_id` | `@Search.defaultSearchElement: true`, fuzziness 0.8, text from `_Customer.CustomerName` |
64
- | `NetAmount` | `net_amount` | `@Semantics.amount.currencyCode: 'CurrencyCode'` |
65
- | `CurrencyCode` | `currency_code` | Currency reference field |
66
- | `CreatedAt` | `created_at` | Admin field |
67
- | `CreatedBy` | `created_by` | Admin field |
68
- | `LastChangedAt` | `last_changed_at` | Admin field |
69
- | `LastChangedBy` | `last_changed_by` | Admin field |
70
-
71
- **Associations (exposed):**
72
- | Name | Cardinality | Target | Join condition |
73
- |---|---|---|---|
74
- | `_Customer` | `[0..1]` | `ZI_Customer` | `CustomerID = _Customer.CustomerID` |
75
- | `_SalesOrderItem` | `[0..*]` | `ZI_SalesOrderItem` | `SalesOrderID = _SalesOrderItem.SalesOrderID` |
76
- | `_Currency` | `[0..1]` | `I_Currency` (SAP standard) | `CurrencyCode = _Currency.Currency` |
77
-
78
- **View-level annotations:**
79
- - `@AccessControl.authorizationCheck: #CHECK` — DCL authorization is checked at runtime if a DCL is defined; otherwise warnings issued.
80
- - `@EndUserText.label: 'Sales Order — Interface View'`
81
- - `@Search.searchable: true` — view participates in enterprise search.
82
-
83
- ### Logic Flow
84
-
85
- There is no procedural logic — this is a projection view. At runtime:
86
-
87
- 1. **Select** header rows from `zsales_order`.
88
- 2. **Apply DCL** (`#CHECK`) if a corresponding DCL role exists on `ZI_SalesOrder`.
89
- 3. **Expose** the renamed fields and forward the three associations to consumers.
90
- 4. On association navigation, the database joins to `ZI_Customer`, `ZI_SalesOrderItem`, or `I_Currency` as needed.
91
- 5. For search queries, `CustomerIDForSearch` is the entry point; the engine performs fuzzy matching (threshold 0.8) and shows `_Customer.CustomerName` as descriptive text.
92
-
93
- ### Data Access
94
- | Table/View | Operation | Purpose |
95
- |---|---|---|
96
- | `zsales_order` | READ | Source table — header data |
97
- | `ZI_Customer` (via `_Customer`) | READ on navigation | Customer master for text and details |
98
- | `ZI_SalesOrderItem` (via `_SalesOrderItem`) | READ on navigation | Child items |
99
- | `I_Currency` (via `_Currency`) | READ on navigation | Standard currency master (TCURC) |
100
-
101
- ### Dependencies
102
-
103
- *Where-used not retrieved — re-run with system access to populate.*
104
-
105
- **Calls (compile-time dependencies):**
106
- - Source table: `zsales_order`
107
- - Associated views: `ZI_Customer`, `ZI_SalesOrderItem`, `I_Currency`
108
-
109
- **Called by:** *unknown — typically a `ZC_SalesOrder` consumption view, OData service bindings, or analytical views; confirm via `sap_usage_references`.*
110
-
111
- ### Error Handling
112
- None at view level. Authorization failures via DCL would result in rows being filtered out, not exceptions. If `zsales_order` or any associated view is inactive or missing, the view itself will not activate.
113
-
114
- ### Notes / Observations
115
- - **`CustomerIDForSearch` duplicates `CustomerID`** — this is a common pattern to keep `CustomerID` "clean" (no search annotations) while a separate element carries the search semantics. Confirm this is intentional and not legacy.
116
- - **`@AccessControl.authorizationCheck: #CHECK`** requires a DCL role (`define role` on `ZI_SalesOrder`) to actually enforce anything. Verify a DCL exists; otherwise this is effectively `#NOT_REQUIRED` with an activation warning.
117
- - **VDM naming** (`ZI_` prefix) suggests this is part of a layered model. Best practice: do not consume this view directly from UIs — build a `ZC_SalesOrder` on top.
118
- - **`I_Currency`** is the SAP-standard currency interface view; the association is correctly modeled for S/4HANA-style currency reference.
119
- - **No `@Metadata.allowExtensions` annotation** — if extension is expected (CDS view extensions for customer fields), add `@Metadata.allowExtensions: true`.
120
- - **Purpose of `CustomerIDForSearch`** is clear from annotations, but the broader business process (order-to-cash? B2B sales?) **is not derivable from the source** — confirm with the business team.
@@ -1,151 +0,0 @@
1
- # abap-document-cds — claude-sonnet-4-6
2
-
3
- - **skill:** abap-document
4
- - **description:** Document a CDS interface view with associations + currency annotation
5
- - **latency:** 45194 ms
6
- - **input tokens:** 3
7
- - **output tokens:** 2,460
8
- - **cost:** $0.0369
9
-
10
- ---
11
-
12
- ## ZI_SalesOrder (CDS View Entity)
13
-
14
- ## TL;DR
15
-
16
- **Headline:** `ZI_SalesOrder` is a search-enabled interface view entity exposing sales order header data with associations to customer, line items, and currency — the foundational read layer for sales order consumption.
17
-
18
- **Top 3 (priority order — most important first):**
19
- 1. **Dual customer ID fields** — `CustomerID` and `CustomerIDForSearch` both map to `Header.customer_id`; the search field carries fuzzy-search and text-element annotations while the key field is clean — consumers must understand which to use for display vs. filtering.
20
- 2. **Access control is enforced (`#CHECK`)** — a DCL (`ZI_SalesOrder.dcls` or equivalent) must exist and be correct, or all data access will be silently blocked; verify the DCL is maintained before consuming in new apps.
21
- 3. **Interface ("I\_") naming convention** — the `ZI_` prefix marks this as a reuse/interface view intended to be the stable contract for consumption views (`ZC_`) and OData services; it should not be modified lightly, as changes ripple to all consumers.
22
-
23
- **Verdict:** Well-structured interface view following SAP VDM conventions; safe to consume but verify the DCL and confirm the `zsales_order` base table schema matches expected field types before exposing via OData.
24
-
25
- ---
26
-
27
- ## ZI_SalesOrder (DDLS — CDS View Entity)
28
-
29
- ### Overview
30
-
31
- | Attribute | Value |
32
- |-----------|-------|
33
- | **Object Type** | CDS View Entity (`define view entity`) |
34
- | **Base Table** | `zsales_order` (aliased as `Header`) |
35
- | **End-User Label** | Sales Order — Interface View |
36
- | **VDM Role** | Interface View (`ZI_` prefix) |
37
- | **Search-enabled** | Yes (`@Search.searchable: true`) |
38
- | **Access Control** | Enforced (`@AccessControl.authorizationCheck: #CHECK`) |
39
-
40
- **Summary:** A sales order header interface view that selects from the custom table `zsales_order` and exposes key business attributes — order identity, customer, amount, currency, and audit timestamps. It publishes three associations (customer master, order items, currency) for use by consumption layers.
41
-
42
- ---
43
-
44
- ### Purpose
45
-
46
- `ZI_SalesOrder` sits at the **interface layer** of a Virtual Data Model (VDM) for sales order processing. Its responsibilities are:
47
-
48
- 1. **Stable contract** — provide a named, annotated projection of `zsales_order` that upstream consumption views (`ZC_SalesOrder`, OData services, Fiori apps) can depend on without coupling directly to the physical table.
49
- 2. **Search enablement** — expose fuzzy customer search over sales orders via `CustomerIDForSearch` with a fuzziness threshold of 0.8.
50
- 3. **Association hub** — publish navigation paths to related entities (customer, line items, currency) so consumers can traverse the model without re-joining.
51
-
52
- ---
53
-
54
- ### Interface (Exposed Fields)
55
-
56
- | Field Name | Source Column | Key | Notes |
57
- |---|---|---|---|
58
- | `SalesOrderID` | `Header.sales_order_id` | ✅ | Primary key |
59
- | `CustomerID` | `Header.customer_id` | — | Use for filtering / key navigation |
60
- | `OrderDate` | `Header.order_date` | — | |
61
- | `CustomerIDForSearch` | `Header.customer_id` | — | Search field; carries fuzzy search & text element annotations — see note below |
62
- | `NetAmount` | `Header.net_amount` | — | Annotated with `@Semantics.amount.currencyCode: 'CurrencyCode'` |
63
- | `CurrencyCode` | `Header.currency_code` | — | Reference field for `NetAmount` |
64
- | `CreatedAt` | `Header.created_at` | — | Audit: creation timestamp |
65
- | `CreatedBy` | `Header.created_by` | — | Audit: creating user |
66
- | `LastChangedAt` | `Header.last_changed_at` | — | Audit: last change timestamp |
67
- | `LastChangedBy` | `Header.last_changed_by` | — | Audit: last changing user |
68
-
69
- **Exposed Associations**
70
-
71
- | Association | Target View | Cardinality | Join Condition |
72
- |---|---|---|---|
73
- | `_Customer` | `ZI_Customer` | `[0..1]` | `CustomerID = _Customer.CustomerID` |
74
- | `_SalesOrderItem` | `ZI_SalesOrderItem` | `[0..*]` | `SalesOrderID = _SalesOrderItem.SalesOrderID` |
75
- | `_Currency` | `I_Currency` (SAP standard) | `[0..1]` | `CurrencyCode = _Currency.Currency` |
76
-
77
- ---
78
-
79
- ### Logic Flow
80
-
81
- This is a pure projection view — there is no filtering, aggregation, or conditional logic. The runtime behavior is:
82
-
83
- 1. **Full read** of `zsales_order` — no `WHERE` clause, so all header records are exposed (access is controlled by the DCL, not SQL predicates).
84
- 2. **Association resolution on demand** — `_Customer`, `_SalesOrderItem`, and `_Currency` are lazy; joins only occur when a consumer explicitly selects or navigates through them.
85
- 3. **Search index population** — the `@Search.searchable` and `@Search.defaultSearchElement` annotations instruct the search framework to index `CustomerIDForSearch` for Enterprise Search / Fiori search help.
86
- 4. **Amount/currency pairing** — the `@Semantics.amount` annotation links `NetAmount` to `CurrencyCode` so OData/Fiori clients render the currency symbol automatically.
87
-
88
- ---
89
-
90
- ### Data Access
91
-
92
- | Object | Type | Operation | Purpose |
93
- |---|---|---|---|
94
- | `zsales_order` | Database Table | READ | Source of all sales order header fields |
95
- | `ZI_Customer` | CDS View Entity | READ (via assoc.) | Resolve customer name and attributes |
96
- | `ZI_SalesOrderItem` | CDS View Entity | READ (via assoc.) | Resolve line items for a given order |
97
- | `I_Currency` | SAP Standard CDS | READ (via assoc.) | Resolve currency description |
98
-
99
- ---
100
-
101
- ### Annotations Explained
102
-
103
- | Annotation | Location | Effect |
104
- |---|---|---|
105
- | `@AccessControl.authorizationCheck: #CHECK` | View level | A DCL for `ZI_SalesOrder` **must exist**; access is denied if no matching DCL condition passes |
106
- | `@Search.searchable: true` | View level | Registers the view with the SAP Enterprise Search / SADL search framework |
107
- | `@Search.defaultSearchElement: true` | `CustomerIDForSearch` | This field is indexed as the primary fuzzy-match target |
108
- | `@Search.fuzzinessThreshold: 0.8` | `CustomerIDForSearch` | 80% match tolerance — typos and partial matches are accepted |
109
- | `@ObjectModel.text.element: ['_Customer.CustomerName']` | `CustomerIDForSearch` | Instructs UI to display customer name as the human-readable label for this ID |
110
- | `@Semantics.amount.currencyCode: 'CurrencyCode'` | `NetAmount` | Pairs the amount field with its currency — required for correct OData metadata and Fiori rendering |
111
-
112
- ---
113
-
114
- ### Dependencies
115
-
116
- **Calls (depends on):**
117
-
118
- | Object | Type | Relationship |
119
- |---|---|---|
120
- | `zsales_order` | Database Table | Data source |
121
- | `ZI_Customer` | CDS View Entity | Association target |
122
- | `ZI_SalesOrderItem` | CDS View Entity | Association target |
123
- | `I_Currency` | SAP Standard CDS View | Association target |
124
-
125
- **Called by (likely consumers — verify with where-used):**
126
-
127
- Typical consumers of a `ZI_` interface view in this pattern would be:
128
- - `ZC_SalesOrder` — a consumption view adding UI annotations for Fiori
129
- - OData service definitions referencing this view
130
- - Other CDS views joining via the published associations
131
-
132
- > ⚠️ Where-used analysis was not run against the live system for this session. Run `sap_usage_references` on `ZI_SalesOrder` to get the confirmed caller list before making any changes to this view's field list or key structure.
133
-
134
- ---
135
-
136
- ### Error Handling & Authorization
137
-
138
- - **No exception handling** — this is a declarative CDS view; runtime errors surface as SQL exceptions to the consumer.
139
- - **Authorization:** `#CHECK` means the framework looks for a DCL object named `ZI_SalesOrder`. If the DCL is missing or its conditions are never satisfied, **no data will be returned** without an explicit error message — a common silent failure. Confirm the DCL is active and correctly maintained.
140
-
141
- ---
142
-
143
- ### Notes & Observations
144
-
145
- | # | Observation |
146
- |---|---|
147
- | 1 | **Dual `customer_id` fields** (`CustomerID` + `CustomerIDForSearch`) is a deliberate SAP VDM pattern — the search field carries annotations that would be inappropriate on a key field. This is correct but must be documented for consumers so they don't treat `CustomerIDForSearch` as a second key. |
148
- | 2 | **`I_Currency` is an SAP-delivered view** — coupling to standard content is intentional for currency semantics but means upgrades could theoretically affect the association if SAP changes `I_Currency`'s key field name. Low risk, worth noting. |
149
- | 3 | **No `@VDM.viewType` annotation is present** — adding `@VDM.viewType: #BASIC` would make the VDM role explicit and improve tooling support (e.g. ABAP Development Tools VDM explorer). |
150
- | 4 | **No client handling** — `zsales_order` is assumed to be client-dependent (standard for custom tables). Verify the table has a `client` field and that ABAP CDS implicit client handling is active, otherwise cross-client data leakage is possible in multi-client systems. |
151
- | 5 | **`[0..1]` on `_Customer`** — assumes one customer per order. If `customer_id` can be null (guest orders, etc.), the association cardinality is correct but consumers should handle the null navigation case. |
@@ -1,112 +0,0 @@
1
- # abap-explain-bdef-handler — claude-haiku-4-5
2
-
3
- - **skill:** abap-explain
4
- - **description:** Explain a managed RAP behavior pool with a validation + determination
5
- - **latency:** 29022 ms
6
- - **input tokens:** 2
7
- - **output tokens:** 2,535
8
- - **cost:** $0.0127
9
-
10
- ---
11
-
12
- ## abap-explain — lhc_salesorder behavior pool
13
-
14
- ## TL;DR
15
-
16
- **Headline:** This is a behavior handler that enforces two automatic rules on sales orders: dates must not be in the past, and net amount must be calculated from quantity × unit price.
17
-
18
- **Top 3 (priority order — most important first):**
19
- 1. **validateorderdate runs on SAVE and blocks invalid orders.** If order date is before today, the order fails validation and is rejected with an error message. The user cannot save.
20
- 2. **determinenetamount runs on MODIFY and auto-calculates a field.** Whenever quantity or unit price changes, net amount is automatically recalculated and written back — the user does not manually enter it.
21
- 3. **Both methods use LOCAL MODE, meaning they bypass authorization checks.** This is intentional for internal calculation but could be a security blind spot if sensitive logic depends on user permissions.
22
-
23
- **Verdict:** This is a straightforward and safe behavior handler. The only risk is that `determinenetamount` silently overwrites any manual entry to NetAmount — document this user-facing behavior.
24
-
25
- ---
26
-
27
- ### What This Code Does
28
-
29
- This is a **behavior handler** — a behind-the-scenes enforcer for a sales order business object in SAP's modern application development framework (RAP, Restful ABAP Programming). It contains two rules:
30
-
31
- 1. **Order dates cannot be in the past.** If someone tries to save an order dated yesterday, the save fails and an error message appears.
32
- 2. **Net amount is automatically calculated.** Whenever quantity or unit price is entered or changed, the net amount (quantity × unit price) is computed and stored automatically. The user does not type it in.
33
-
34
- These rules execute transparently whenever the sales order is created or modified, whether via UI, API, or batch job.
35
-
36
- ---
37
-
38
- ### Step by Step
39
-
40
- 1. **Class declaration and inheritance**
41
- This class (`lhc_salesorder`) inherits from `cl_abap_behav_handler`, which is SAP's base class for behavior handlers. Inheriting from this class registers this code as the enforcer for the sales order business object (`zr_salesorder`). The two METHODS declarations define *what* will happen; the IMPLEMENTATION section defines *how*.
42
-
43
- 2. **validateorderdate: Entry point**
44
- This method is triggered whenever a user tries to **SAVE** a sales order. The `FOR VALIDATE ON SAVE` phrase means "run this code during the save validation phase, before the database is actually written." The method receives a list of sales order keys (IDs) that are being saved.
45
-
46
- 3. **validateorderdate: Read the order dates**
47
- The method queries the sales order entity (`SalesOrder`) in LOCAL MODE — a special read mode that does not check user permissions — and retrieves only the `OrderDate` field for each sales order being saved. The results go into a temporary list `lt_orders`.
48
-
49
- 4. **validateorderdate: Check each date**
50
- For each order, the code compares its `OrderDate` to today's date [retrieved via `cl_abap_context_info=>get_system_date( )`]. If the order date is in the past (less than today), two things happen: (a) the order is marked as **failed** in the `failed-salesorder` list, and (b) an error message is added to the `reported-salesorder` list with the text "Order date must be today or in the future."
51
-
52
- 5. **validateorderdate: Result**
53
- When the method finishes, SAP checks the `failed` and `reported` tables. If any order is in `failed`, the save is **blocked** — the database is not written, and the user sees the error message. The user must correct the date and retry.
54
-
55
- 6. **determinenetamount: Entry point**
56
- This method is triggered whenever a user **MODIFIES** (creates or changes) a sales order. The `FOR DETERMINE ON MODIFY` phrase means "run this code after a change is made, to calculate or update derived fields." The method receives the list of sales order keys that were modified.
57
-
58
- 7. **determinenetamount: Read quantity and unit price**
59
- The method reads the `Quantity` and `UnitPrice` fields for each modified order. Again, LOCAL MODE is used, so no permission checks happen.
60
-
61
- 8. **determinenetamount: Calculate net amount**
62
- A temporary update list `lt_update` is created. For each order, the code multiplies `Quantity × UnitPrice` to get the net amount, and appends an update instruction to the list. The `%control-NetAmount = if_abap_behv=>mk-on` instruction tells SAP "include this field in the update." [INFERRED: `mk-on` stands for "mark on," meaning "process this field."]
63
-
64
- 9. **determinenetamount: Write back to the entity**
65
- The `MODIFY ENTITIES` statement applies all the calculated net amounts back to the sales orders in memory. The `FIELDS ( NetAmount )` clause tells SAP "only update this one field." The changes are committed to the in-memory entity state, so when the user saves, the net amount is already populated.
66
-
67
- 10. **Return and chain**
68
- Both methods return implicitly. If validation fails (step 5), the save stops. If validation passes and `determinenetamount` has recalculated net amounts, the save proceeds with the updated values.
69
-
70
- ---
71
-
72
- ### SAP Concepts Explained
73
-
74
- | Term | What It Means |
75
- |------|--------------|
76
- | Behavior Handler | A class in SAP's modern application framework (RAP) that enforces business rules on an entity (like a sales order). It runs automatically during create, modify, and save operations without the application code having to call it explicitly. |
77
- | RAP (Restful ABAP Programming) | SAP's modern approach to building business applications. It separates the business logic (behavior handlers like this one) from the UI, so the same rules apply whether a user is using a web interface, a mobile app, or an API. |
78
- | FOR VALIDATE ON SAVE | A behavior method trigger that says "run this code during the save validation phase." It runs before the database write, giving the code a chance to reject invalid data. |
79
- | FOR DETERMINE ON MODIFY | A behavior method trigger that says "run this code whenever the entity is modified (created or changed)." Typically used to calculate derived fields or set defaults. |
80
- | READ ENTITIES OF | A RAP statement that fetches data from a business entity (like a view or table). It is the modern replacement for SELECT in behavior code. |
81
- | zr_salesorder | A data model object (CDS view) that defines the sales order entity structure. The "zr_" prefix indicates it is a custom object (not SAP standard). |
82
- | LOCAL MODE | A read/write mode that bypasses SAP's authorization checks. Used in behavior code so that automatic calculations and validations run regardless of the user's permissions. |
83
- | %tky | The technical key — a unique identifier (usually primary key fields) of an entity instance. Used to identify which specific sales order is being referenced. |
84
- | failed-salesorder | A structure SAP populates to mark which entities failed validation. If any entity is in this list at the end of validation, the save is rejected. |
85
- | reported-salesorder | A structure SAP populates with error messages to display to the user. Each entry includes the entity's key (%tky), the message text, and the severity (error, warning, info). |
86
- | MODIFY ENTITIES OF | A RAP statement that updates one or more entity instances in memory. Unlike a database UPDATE, this changes the in-memory state before the save. |
87
- | %control | A control structure that tells SAP which fields to include in an update. Setting `%control-NetAmount = if_abap_behv=>mk-on` means "include NetAmount in this update." |
88
- | if_abap_behv_message=>severity-error | A constant that marks a message as an error. Used in the reported structure to tell SAP this is a blocker, not a warning. |
89
- | cl_abap_context_info=>get_system_date( ) | A standard SAP class method that returns today's date in the system. Used here for date comparisons. |
90
-
91
- ---
92
-
93
- ### Key Things to Know
94
-
95
- 1. **Validation blocks the save; determination does not.** If `validateorderdate` marks an order as failed, the entire save is aborted — nothing is written to the database. If `determinenetamount` calculates a field, the value is always applied silently; there is no "reject" path. This is the intended behavior for business rules: validations are gates, determinations are auto-fills.
96
-
97
- 2. **Determination overwrites manual entry.** If a user manually enters a net amount and then changes the quantity, `determinenetamount` will recalculate and overwrite that entry. Document this in the UI — users may expect the field to be editable, but it is effectively read-only because it is always recalculated.
98
-
99
- 3. **LOCAL MODE bypasses all authorization.** Both methods read and write in LOCAL MODE, meaning they ignore AUTHORITY-CHECKs. This ensures the rules apply to all users equally. However, if sensitive calculations (e.g., discount logic, cost center assignment) are added to this handler, they will also bypass permission checks — use normal (non-LOCAL) mode for those and add explicit AUTHORITY-CHECKs.
100
-
101
- 4. **Order of execution matters.** `validateorderdate` runs during the SAVE phase (after all MODIFYs are done), so it validates the final state. `determinenetamount` runs during each MODIFY phase, so it recalculates net amount as soon as quantity or price changes. This is the correct order: calculate first, then validate the result.
102
-
103
- 5. **No error handling for date edge cases.** The code uses `<` (less than) to check if the date is in the past. A date exactly equal to today passes validation. Dates in the future always pass. If the system date is NULL or invalid, the comparison might not behave as expected — no explicit error handling is in place. [INFERRED: This is acceptable for most SAP systems, where the system date is always set correctly.]
104
-
105
- 6. **The messages are hardcoded, not translated.** The error message "Order date must be today or in the future" is English text baked into the code. For a production system, consider using message classes and message numbers for multi-language support.
106
-
107
- ---
108
-
109
- ### What Was Not Analyzed
110
- - The CDS view definition for `zr_salesorder` was not provided. The exact fields (OrderDate, Quantity, UnitPrice, NetAmount) and their types (date, decimal, etc.) are assumed based on usage in the code, but their definitions and constraints were not examined.
111
- - No parent behavior definitions or additional derived behavior handlers were provided. The sales order entity may have other rules defined elsewhere that interact with these two methods.
112
- - The UI layer (Fiori app, Web Dynpro, OData consumer) is not visible. How the user experiences the validation error and the silent net amount recalculation depends on the UI implementation.