Generator: pilot analysis and fixes; G0002-G0021 tasks; handover notes merged

- Static bundle checks (name length, seed type, reserved words, contract test classes,
  testclasses_file), local abaplint parser check before SAP, max_tokens, robust JSON parse
- Runner: G2 for CDS views with parameters, contract_check detail in report
- G0020 and G0013 fixed by review and revalidated (oracle 100, null 0)
- Pilot results in docs/faz1-tasarim.md 11e; handover notes merged into CLAUDE.md and docs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kral
2026-10-03 05:04:23 +02:00
parent 15eb9f1bb2
commit 5de5e2851c
162 changed files with 9943 additions and 23 deletions

View File

@@ -0,0 +1,29 @@
{
"id": "G0003",
"pool": "eval",
"object_type": "CLAS",
"category": "B",
"attempts": [
{
"stage": "validate",
"oracle": null,
"null": null
},
{
"stage": "validate",
"oracle": null,
"null": null
},
{
"stage": "validate",
"oracle": 0,
"null": 0
},
{
"stage": "validate",
"oracle": 100.0,
"null": 0
}
],
"accepted": true
}

View File

@@ -0,0 +1,119 @@
CLASS {{P}}T02_HIDDEN DEFINITION PUBLIC FINAL CREATE PUBLIC
FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA mo_environment TYPE REF TO if_osql_test_environment.
DATA mo_cut TYPE REF TO {{P}}COURSE_BOOKING.
CLASS-METHODS class_setup.
CLASS-METHODS class_teardown.
METHODS setup.
METHODS fill_test_data.
METHODS free_seats_open_course FOR TESTING.
METHODS free_seats_never_neg FOR TESTING.
METHODS free_seats_unknown FOR TESTING.
METHODS bookable_exact_free FOR TESTING.
METHODS not_bookable_too_many FOR TESTING.
METHODS not_bookable_unknown FOR TESTING.
METHODS not_bookable_zero_seats FOR TESTING.
METHODS list_filter_cat_seats FOR TESTING.
METHODS list_sorted_by_course FOR TESTING.
METHODS list_empty_without_match FOR TESTING.
METHODS list_excludes_full FOR TESTING.
ENDCLASS.
CLASS {{P}}T02_HIDDEN IMPLEMENTATION.
METHOD class_setup.
mo_environment = cl_osql_test_environment=>create( VALUE #( ( '{{P}}COURSE' ) ) ).
ENDMETHOD.
METHOD class_teardown.
mo_environment->destroy( ).
ENDMETHOD.
METHOD setup.
mo_environment->clear_doubles( ).
fill_test_data( ).
mo_cut = NEW {{P}}COURSE_BOOKING( ).
ENDMETHOD.
METHOD fill_test_data.
DATA lt_course TYPE STANDARD TABLE OF {{P}}COURSE WITH EMPTY KEY.
lt_course = VALUE #(
( mandt = sy-mandt course_id = 'ABAP101' category = 'IT' title = 'ABAP Basics' capacity = 20 booked = 5 )
( mandt = sy-mandt course_id = 'ABAP102' category = 'IT' title = 'ABAP Advanced' capacity = 10 booked = 10 )
( mandt = sy-mandt course_id = 'ABAP103' category = 'IT' title = 'ABAP Expert' capacity = 12 booked = 15 )
( mandt = sy-mandt course_id = 'SQL101' category = 'DB' title = 'SQL Basics' capacity = 30 booked = 10 )
( mandt = sy-mandt course_id = 'SQL102' category = 'DB' title = 'SQL Tuning' capacity = 8 booked = 8 )
( mandt = sy-mandt course_id = 'HR101' category = 'HR' title = 'HR Basics' capacity = 6 booked = 1 ) ).
INSERT {{P}}COURSE FROM TABLE @lt_course.
ENDMETHOD.
METHOD free_seats_open_course.
cl_abap_unit_assert=>assert_equals( exp = 15
act = mo_cut->get_free_seats( 'ABAP101' )
msg = 'ABAP101 must have 15 free seats' ).
ENDMETHOD.
METHOD free_seats_never_neg.
cl_abap_unit_assert=>assert_equals( exp = 0
act = mo_cut->get_free_seats( 'ABAP102' )
msg = 'full course' ).
cl_abap_unit_assert=>assert_equals( exp = 0
act = mo_cut->get_free_seats( 'ABAP103' )
msg = 'overbooked course' ).
ENDMETHOD.
METHOD free_seats_unknown.
cl_abap_unit_assert=>assert_equals( exp = 0
act = mo_cut->get_free_seats( 'XX999' ) ).
ENDMETHOD.
METHOD bookable_exact_free.
cl_abap_unit_assert=>assert_true( mo_cut->is_bookable( iv_course_id = 'SQL101' iv_seats = 20 ) ).
ENDMETHOD.
METHOD not_bookable_too_many.
cl_abap_unit_assert=>assert_false( mo_cut->is_bookable( iv_course_id = 'SQL101' iv_seats = 21 ) ).
ENDMETHOD.
METHOD not_bookable_unknown.
cl_abap_unit_assert=>assert_false( mo_cut->is_bookable( iv_course_id = 'XX999' iv_seats = 1 ) ).
ENDMETHOD.
METHOD not_bookable_zero_seats.
cl_abap_unit_assert=>assert_false( mo_cut->is_bookable( iv_course_id = 'SQL101' iv_seats = 0 ) ).
cl_abap_unit_assert=>assert_false( mo_cut->is_bookable( iv_course_id = 'SQL101' iv_seats = -5 ) ).
ENDMETHOD.
METHOD list_filter_cat_seats.
DATA(lt_result) = mo_cut->list_bookable_courses( iv_category = 'DB' iv_seats = 5 ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_result ) ).
cl_abap_unit_assert=>assert_equals( exp = 'SQL101' act = lt_result[ 1 ]-course_id ).
cl_abap_unit_assert=>assert_equals( exp = 'SQL Basics' act = lt_result[ 1 ]-title ).
cl_abap_unit_assert=>assert_equals( exp = 20 act = lt_result[ 1 ]-free_seats ).
ENDMETHOD.
METHOD list_sorted_by_course.
DATA(lt_result) = mo_cut->list_bookable_courses( iv_category = 'IT' iv_seats = 0 ).
cl_abap_unit_assert=>assert_equals( exp = 3 act = lines( lt_result ) ).
cl_abap_unit_assert=>assert_equals( exp = 'ABAP101' act = lt_result[ 1 ]-course_id ).
cl_abap_unit_assert=>assert_equals( exp = 'ABAP102' act = lt_result[ 2 ]-course_id ).
cl_abap_unit_assert=>assert_equals( exp = 'ABAP103' act = lt_result[ 3 ]-course_id ).
cl_abap_unit_assert=>assert_equals( exp = 0 act = lt_result[ 3 ]-free_seats ).
ENDMETHOD.
METHOD list_empty_without_match.
DATA(lt_hr) = mo_cut->list_bookable_courses( iv_category = 'HR' iv_seats = 6 ).
cl_abap_unit_assert=>assert_initial( lt_hr ).
DATA(lt_unknown) = mo_cut->list_bookable_courses( iv_category = 'XX' iv_seats = 1 ).
cl_abap_unit_assert=>assert_initial( lt_unknown ).
ENDMETHOD.
METHOD list_excludes_full.
DATA(lt_result) = mo_cut->list_bookable_courses( iv_category = 'IT' iv_seats = 1 ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_result ) ).
cl_abap_unit_assert=>assert_equals( exp = 'ABAP101' act = lt_result[ 1 ]-course_id ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,94 @@
CLASS {{P}}COURSE_BOOKING DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES ty_course_id TYPE c LENGTH 10.
TYPES ty_category TYPE c LENGTH 10.
TYPES:
BEGIN OF ty_course_info,
course_id TYPE ty_course_id,
title TYPE c LENGTH 40,
free_seats TYPE i,
END OF ty_course_info.
TYPES tt_course_info TYPE STANDARD TABLE OF ty_course_info WITH EMPTY KEY.
METHODS get_free_seats
IMPORTING iv_course_id TYPE ty_course_id
RETURNING VALUE(rv_free_seats) TYPE i.
METHODS is_bookable
IMPORTING iv_course_id TYPE ty_course_id
iv_seats TYPE i
RETURNING VALUE(rv_bookable) TYPE abap_bool.
METHODS list_bookable_courses
IMPORTING iv_category TYPE ty_category
iv_seats TYPE i
RETURNING VALUE(rt_courses) TYPE tt_course_info.
PRIVATE SECTION.
TYPES:
BEGIN OF ty_course,
course_id TYPE ty_course_id,
title TYPE c LENGTH 40,
capacity TYPE i,
booked TYPE i,
END OF ty_course.
METHODS read_course
IMPORTING iv_course_id TYPE ty_course_id
RETURNING VALUE(rs_course) TYPE ty_course.
METHODS calculate_free_seats
IMPORTING is_course TYPE ty_course
RETURNING VALUE(rv_free) TYPE i.
ENDCLASS.
CLASS {{P}}COURSE_BOOKING IMPLEMENTATION.
METHOD get_free_seats.
rv_free_seats = calculate_free_seats( read_course( iv_course_id ) ).
ENDMETHOD.
METHOD is_bookable.
IF iv_seats < 1.
rv_bookable = abap_false.
RETURN.
ENDIF.
rv_bookable = xsdbool( iv_seats <= calculate_free_seats( read_course( iv_course_id ) ) ).
ENDMETHOD.
METHOD list_bookable_courses.
DATA lt_course TYPE STANDARD TABLE OF ty_course WITH EMPTY KEY.
SELECT course_id, title, capacity, booked
FROM {{P}}COURSE
WHERE category = @iv_category
INTO TABLE @lt_course.
LOOP AT lt_course INTO DATA(ls_course).
DATA(lv_free) = calculate_free_seats( ls_course ).
IF lv_free < iv_seats.
CONTINUE.
ENDIF.
rt_courses = VALUE #( BASE rt_courses
( course_id = ls_course-course_id
title = ls_course-title
free_seats = lv_free ) ).
ENDLOOP.
SORT rt_courses BY course_id.
ENDMETHOD.
METHOD read_course.
SELECT SINGLE course_id, title, capacity, booked
FROM {{P}}COURSE
WHERE course_id = @iv_course_id
INTO @rs_course.
ENDMETHOD.
METHOD calculate_free_seats.
rv_free = is_course-capacity - is_course-booked.
IF rv_free < 0.
rv_free = 0.
ENDIF.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,63 @@
CLASS ltc_course_booking DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA mo_environment TYPE REF TO if_osql_test_environment.
DATA mo_cut TYPE REF TO {{P}}COURSE_BOOKING.
CLASS-METHODS class_setup.
CLASS-METHODS class_teardown.
METHODS setup.
METHODS fill_test_data.
METHODS free_seats_open_course FOR TESTING.
METHODS free_seats_full_course FOR TESTING.
METHODS bookable_enough_seats FOR TESTING.
METHODS not_bookable_full FOR TESTING.
METHODS list_matching_courses FOR TESTING.
ENDCLASS.
CLASS ltc_course_booking IMPLEMENTATION.
METHOD class_setup.
mo_environment = cl_osql_test_environment=>create( VALUE #( ( '{{P}}COURSE' ) ) ).
ENDMETHOD.
METHOD class_teardown.
mo_environment->destroy( ).
ENDMETHOD.
METHOD setup.
mo_environment->clear_doubles( ).
fill_test_data( ).
mo_cut = NEW {{P}}COURSE_BOOKING( ).
ENDMETHOD.
METHOD fill_test_data.
DATA lt_course TYPE STANDARD TABLE OF {{P}}COURSE WITH EMPTY KEY.
lt_course = VALUE #(
( mandt = sy-mandt course_id = 'ABAP101' category = 'IT' title = 'ABAP Basics' capacity = 20 booked = 5 )
( mandt = sy-mandt course_id = 'SQL101' category = 'DB' title = 'SQL Basics' capacity = 30 booked = 30 ) ).
INSERT {{P}}COURSE FROM TABLE @lt_course.
ENDMETHOD.
METHOD free_seats_open_course.
cl_abap_unit_assert=>assert_equals( exp = 15 act = mo_cut->get_free_seats( 'ABAP101' ) ).
ENDMETHOD.
METHOD free_seats_full_course.
cl_abap_unit_assert=>assert_equals( exp = 0 act = mo_cut->get_free_seats( 'SQL101' ) ).
ENDMETHOD.
METHOD bookable_enough_seats.
cl_abap_unit_assert=>assert_true( mo_cut->is_bookable( iv_course_id = 'ABAP101' iv_seats = 10 ) ).
ENDMETHOD.
METHOD not_bookable_full.
cl_abap_unit_assert=>assert_false( mo_cut->is_bookable( iv_course_id = 'SQL101' iv_seats = 1 ) ).
ENDMETHOD.
METHOD list_matching_courses.
DATA(lt_result) = mo_cut->list_bookable_courses( iv_category = 'IT' iv_seats = 1 ).
cl_abap_unit_assert=>assert_equals( exp = 1 act = lines( lt_result ) ).
cl_abap_unit_assert=>assert_equals( exp = 'ABAP101' act = lt_result[ 1 ]-course_id ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,8 @@
define table {{P}}COURSE {
key mandt : abap.clnt not null;
key course_id : abap.char(10) not null;
category : abap.char(10);
title : abap.char(40);
capacity : abap.int4;
booked : abap.int4;
}

View File

@@ -0,0 +1,9 @@
@EndUserText.label : 'Training courses'
define table {{P}}COURSE {
key mandt : abap.clnt not null;
key course_id : abap.char(10) not null;
category : abap.char(10);
title : abap.char(40);
capacity : abap.int4;
booked : abap.int4;
}

View File

@@ -0,0 +1,13 @@
@EndUserText.label : 'Training courses'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table {{P}}COURSE {
key mandt : abap.clnt not null;
key course_id : abap.char(10) not null;
category : abap.char(10);
title : abap.char(40);
capacity : abap.int4;
booked : abap.int4;
}

View File

@@ -0,0 +1,24 @@
CLASS {{P}}SEED_COURSES DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
ENDCLASS.
CLASS {{P}}SEED_COURSES IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DELETE FROM {{P}}COURSE.
DATA lt_course TYPE STANDARD TABLE OF {{P}}COURSE WITH EMPTY KEY.
lt_course = VALUE #(
( mandt = sy-mandt course_id = 'ABAP101' category = 'IT' title = 'ABAP Basics' capacity = 20 booked = 5 )
( mandt = sy-mandt course_id = 'ABAP102' category = 'IT' title = 'ABAP Advanced' capacity = 10 booked = 10 )
( mandt = sy-mandt course_id = 'ABAP103' category = 'IT' title = 'ABAP Expert' capacity = 12 booked = 15 )
( mandt = sy-mandt course_id = 'SQL101' category = 'DB' title = 'SQL Basics' capacity = 30 booked = 10 )
( mandt = sy-mandt course_id = 'SQL102' category = 'DB' title = 'SQL Tuning' capacity = 8 booked = 8 )
( mandt = sy-mandt course_id = 'HR101' category = 'HR' title = 'HR Basics' capacity = 6 booked = 1 ) ).
INSERT {{P}}COURSE FROM TABLE @lt_course.
out->write( |Courses written: { sy-dbcnt }| ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,68 @@
# 1. Goal
A training provider sells seats in courses. The booking program needs one service that
answers three questions:
- How many seats are free in a course?
- Can we book a given number of seats in a course?
- Which courses of a category still have enough free seats?
# 2. Open questions
None.
# 3. Context
- The database table {{P}}COURSE exists in package $TMP. It has these columns:
MANDT (client), COURSE_ID (CHAR 10, key), CATEGORY (CHAR 10), TITLE (CHAR 40),
CAPACITY (INT4), BOOKED (INT4).
- CAPACITY is the number of seats of the course. BOOKED is the number of seats that
are already sold.
- The class {{P}}SEED_COURSES fills the table with example data. It is active.
# 4. Contract
- Create the class {{P}}COURSE_BOOKING in package $TMP.
- The class is public, final, and has a public constructor without parameters.
- The class has these public types:
- TY_COURSE_ID, type C, length 10.
- TY_CATEGORY, type C, length 10.
- TY_COURSE_INFO, a structure with the components COURSE_ID (type TY_COURSE_ID),
TITLE (type C, length 40) and FREE_SEATS (type I).
- TT_COURSE_INFO, a standard table of TY_COURSE_INFO with an empty key.
- The class has these public methods:
- GET_FREE_SEATS, importing IV_COURSE_ID type TY_COURSE_ID,
returning RV_FREE_SEATS type I.
- IS_BOOKABLE, importing IV_COURSE_ID type TY_COURSE_ID and IV_SEATS type I,
returning RV_BOOKABLE type ABAP_BOOL.
- LIST_BOOKABLE_COURSES, importing IV_CATEGORY type TY_CATEGORY and IV_SEATS type I,
returning RT_COURSES type TT_COURSE_INFO.
- Do not add other public methods.
# 5. Business rules
Free seats
1. Read the course with the course ID.
2. If the table has no course with this ID, the free seats are 0.
3. The free seats are the capacity minus the booked seats.
4. If the capacity minus the booked seats is less than 0, the free seats are 0.
GET_FREE_SEATS returns the free seats of the course.
IS_BOOKABLE
5. If IV_SEATS is less than 1, the result is false.
6. If the table has no course with this ID, the result is false.
7. The result is true if IV_SEATS is less than or equal to the free seats of the
course. Else the result is false.
LIST_BOOKABLE_COURSES
8. Read all courses with the category IV_CATEGORY.
9. Use only the courses whose free seats are greater than or equal to IV_SEATS.
10. Sort the result in ascending order by COURSE_ID.
11. Each result row has the COURSE_ID, the TITLE and the free seats of the course.
12. If no course matches, the result is empty.
# 6. Constraints
- Release target: 8.16.
- Coding standards: Clean ABAP. Method length below 40 statements. No global variables.
No comment that restates the code.
- Out of scope: do not change the table {{P}}COURSE and the class {{P}}SEED_COURSES.
# 7. Acceptance
- The class is active and has no syntax error.
- The hidden tests pass.
- Write your own ABAP Unit tests for the class.

View File

@@ -0,0 +1,58 @@
{
"id": "G0003",
"category": "B",
"object_type": "CLAS",
"difficulty": 2,
"release_target": "v816",
"expected_outcome": "implement",
"budget": {
"max_tool_calls": 60,
"max_activations": 15
},
"seed": [
{
"type": "TABL",
"name": "{{P}}COURSE",
"file": "seed/course.tabl.asddls",
"description": "Training course table with capacity and booked seats"
},
{
"type": "CLAS",
"name": "{{P}}SEED_COURSES",
"file": "seed/seed_courses.clas.abap",
"description": "Fills the course table with example data",
"run": true
}
],
"contract": [
{
"type": "CLAS",
"name": "{{P}}COURSE_BOOKING"
}
],
"out_of_scope": [
"{{P}}COURSE",
"{{P}}SEED_COURSES"
],
"hidden_tests": [
{
"type": "CLAS",
"name": "{{P}}T02_HIDDEN",
"file": "hidden/t02_hidden.clas.abap",
"description": "T02 hidden tests"
}
],
"reference": [
{
"type": "CLAS",
"name": "{{P}}COURSE_BOOKING",
"file": "reference/course_booking.clas.abap",
"description": "Course booking service",
"testclasses_file": "reference/course_booking.testclasses.abap"
}
],
"craft_checks": [
"method_length",
"db_operation_in_loop"
]
}