427 lines
18 KiB
ABAP
427 lines
18 KiB
ABAP
" TARGET OBJECT : class ZZBP_R_CHANGEAPPROVAL000 - LOCAL TYPES include (Local Types tab in ADT)
|
|
" abap: URI : abap:/repotree-v1/0M7DEJI/System%20Library/ZLOCAL/ZARENA_PLM/Source%20Code%20Library/Classes/ZZBP_R_CHANGEAPPROVAL000/zzbp_r_changeapproval000.clas.locals_imp.abap
|
|
" ACTION : replace entire content, then activate the class (BDEF ZZR_CHANGEAPPROVAL000 must be active first).
|
|
"
|
|
" Sources (all verified 2026-09-15):
|
|
" handler class inherits from CL_ABAP_BEHAVIOR_HANDLER (released) [sap-released-objects public_cloud A]
|
|
" FOR INSTANCE FEATURES signature + result via %tky / %features-%action-<name> / if_abap_behv=>fc-o-enabled|disabled
|
|
" [abap-docs /abap-docs-cloud/ABAPHANDLER_METH_FEATURES, ABAPDERIVED_TYPES_FEATURES, ABENBDL_ACTIONS_FC]
|
|
" FOR MODIFY ... FOR ACTION with RESULT; %param carries the action parameter (keys) and the result ($self)
|
|
" [abap-docs /abap-docs-cloud/ABENBDL_ACTION2_ABEXA, ABAPDERIVED_TYPES_PARAM]
|
|
" READ ENTITIES ... IN LOCAL MODE ... FIELDS ( ) WITH CORRESPONDING #( keys ) RESULT ... FAILED failed
|
|
" [abap-docs /abap-docs-cloud/ABENBDL_ACTIONS_FC example]
|
|
" MODIFY ENTITIES ... IN LOCAL MODE (skips feature control and authorization) with UPDATE FIELDS
|
|
" [abap-docs /abap-docs-cloud/ABAPMODIFY_ENTITY_ENTITIES, ABAPMODIFY_ENTITY_ENTITIES_OP, ABENBDL_AUTHORIZATION]
|
|
" %msg = new_message_with_text( ... ) into reported [abap-docs /abap-docs-cloud/ABENBDL_ACTIONS_FC example]
|
|
" FOR DETERMINE ON MODIFY signature [abap-docs /abap-docs-cloud/ABAPHANDLER_METH_DET]
|
|
" utclong_current( ) [abap-docs /abap-docs-cloud/ABENUTCLONG_CURRENT]
|
|
" cl_abap_context_info=>get_user_technical_name( ) (released class) [sap-docs sap-help loio 7be24435b3e24540a9edad9a2535175a;
|
|
" sap-released-objects CL_ABAP_CONTEXT_INFO public_cloud A]
|
|
" Design notes:
|
|
" - Status transitions are enforced twice: get_instance_features disables the action (UI greys it out / EML fails
|
|
" with an entry in failed [ABENBDL_ACTIONS_FC]) AND each action re-checks the current status so an EML caller
|
|
" IN LOCAL MODE cannot skip the state machine.
|
|
" - The six actions repeat the same read/check/update/read pattern on purpose: each action has its own derived
|
|
" key type, so a generic helper would need additional derived-type plumbing that is not worth it for six methods.
|
|
" - RequestedBy is the technical user of the creator (for the A2X flow: the worker's communication user).
|
|
" If the Arena requester should be shown instead, make RequestedBy mandatory:create in the BDEF and drop it
|
|
" from the determination.
|
|
|
|
CLASS lhc_changeapproval DEFINITION INHERITING FROM cl_abap_behavior_handler.
|
|
PRIVATE SECTION.
|
|
|
|
CONSTANTS:
|
|
BEGIN OF status,
|
|
pending TYPE zzchngpproval000-status VALUE 'PENDING',
|
|
approved TYPE zzchngpproval000-status VALUE 'APPROVED',
|
|
executing TYPE zzchngpproval000-status VALUE 'EXECUTING',
|
|
synced TYPE zzchngpproval000-status VALUE 'SYNCED',
|
|
rejected TYPE zzchngpproval000-status VALUE 'REJECTED',
|
|
failed TYPE zzchngpproval000-status VALUE 'FAILED',
|
|
END OF status.
|
|
|
|
METHODS get_instance_features FOR INSTANCE FEATURES
|
|
IMPORTING keys REQUEST requested_features FOR ChangeApproval RESULT result.
|
|
|
|
METHODS approve FOR MODIFY
|
|
IMPORTING keys FOR ACTION ChangeApproval~approve RESULT result.
|
|
|
|
METHODS reject FOR MODIFY
|
|
IMPORTING keys FOR ACTION ChangeApproval~reject RESULT result.
|
|
|
|
METHODS retrySync FOR MODIFY
|
|
IMPORTING keys FOR ACTION ChangeApproval~retrySync RESULT result.
|
|
|
|
METHODS markExecuting FOR MODIFY
|
|
IMPORTING keys FOR ACTION ChangeApproval~markExecuting RESULT result.
|
|
|
|
METHODS markSynced FOR MODIFY
|
|
IMPORTING keys FOR ACTION ChangeApproval~markSynced RESULT result.
|
|
|
|
METHODS markFailed FOR MODIFY
|
|
IMPORTING keys FOR ACTION ChangeApproval~markFailed RESULT result.
|
|
|
|
METHODS setInitialStatus FOR DETERMINE ON MODIFY
|
|
IMPORTING keys FOR ChangeApproval~setInitialStatus.
|
|
|
|
ENDCLASS.
|
|
|
|
|
|
CLASS lhc_changeapproval IMPLEMENTATION.
|
|
|
|
METHOD get_instance_features.
|
|
READ ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
FIELDS ( Status )
|
|
WITH CORRESPONDING #( keys )
|
|
RESULT DATA(approvals)
|
|
FAILED failed.
|
|
|
|
result = VALUE #( FOR approval IN approvals
|
|
( %tky = approval-%tky
|
|
%features-%action-approve = COND #( WHEN approval-Status = status-pending
|
|
THEN if_abap_behv=>fc-o-enabled
|
|
ELSE if_abap_behv=>fc-o-disabled )
|
|
%features-%action-reject = COND #( WHEN approval-Status = status-pending
|
|
THEN if_abap_behv=>fc-o-enabled
|
|
ELSE if_abap_behv=>fc-o-disabled )
|
|
%features-%action-retrySync = COND #( WHEN approval-Status = status-failed
|
|
THEN if_abap_behv=>fc-o-enabled
|
|
ELSE if_abap_behv=>fc-o-disabled )
|
|
%features-%action-markExecuting = COND #( WHEN approval-Status = status-approved
|
|
THEN if_abap_behv=>fc-o-enabled
|
|
ELSE if_abap_behv=>fc-o-disabled )
|
|
%features-%action-markSynced = COND #( WHEN approval-Status = status-executing
|
|
THEN if_abap_behv=>fc-o-enabled
|
|
ELSE if_abap_behv=>fc-o-disabled )
|
|
%features-%action-markFailed = COND #( WHEN approval-Status = status-executing
|
|
THEN if_abap_behv=>fc-o-enabled
|
|
ELSE if_abap_behv=>fc-o-disabled ) ) ).
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD approve.
|
|
" PENDING -> APPROVED; records the decision, never writes SapChangeNumber (PRD RAP-1)
|
|
READ ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
FIELDS ( Status )
|
|
WITH CORRESPONDING #( keys )
|
|
RESULT DATA(approvals)
|
|
FAILED failed.
|
|
|
|
LOOP AT keys INTO DATA(key).
|
|
ASSIGN approvals[ ID = key-ID ] TO FIELD-SYMBOL(<approval>).
|
|
IF sy-subrc <> 0.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
IF <approval>-Status <> status-pending.
|
|
APPEND VALUE #( %tky = <approval>-%tky ) TO failed-changeapproval.
|
|
APPEND VALUE #( %tky = <approval>-%tky
|
|
%msg = new_message_with_text(
|
|
severity = if_abap_behv_message=>severity-error
|
|
text = |Only PENDING records can be approved (status is { <approval>-Status })| ) )
|
|
TO reported-changeapproval.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
MODIFY ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
UPDATE FIELDS ( Status DecidedBy DecidedOn )
|
|
WITH VALUE #( ( %tky = <approval>-%tky
|
|
Status = status-approved
|
|
DecidedBy = cl_abap_context_info=>get_user_technical_name( )
|
|
DecidedOn = utclong_current( ) ) )
|
|
FAILED DATA(update_failed)
|
|
REPORTED DATA(update_reported).
|
|
ENDLOOP.
|
|
|
|
READ ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
ALL FIELDS WITH CORRESPONDING #( keys )
|
|
RESULT DATA(updated).
|
|
|
|
result = VALUE #( FOR row IN updated ( %tky = row-%tky %param = row ) ).
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD reject.
|
|
" PENDING -> REJECTED with a mandatory reason (PRD RAP-2); REJECTED is terminal
|
|
READ ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
FIELDS ( Status )
|
|
WITH CORRESPONDING #( keys )
|
|
RESULT DATA(approvals)
|
|
FAILED failed.
|
|
|
|
LOOP AT keys INTO DATA(key).
|
|
ASSIGN approvals[ ID = key-ID ] TO FIELD-SYMBOL(<approval>).
|
|
IF sy-subrc <> 0.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
IF <approval>-Status <> status-pending.
|
|
APPEND VALUE #( %tky = <approval>-%tky ) TO failed-changeapproval.
|
|
APPEND VALUE #( %tky = <approval>-%tky
|
|
%msg = new_message_with_text(
|
|
severity = if_abap_behv_message=>severity-error
|
|
text = |Only PENDING records can be rejected (status is { <approval>-Status })| ) )
|
|
TO reported-changeapproval.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
IF key-%param-RejectReason IS INITIAL.
|
|
APPEND VALUE #( %tky = <approval>-%tky ) TO failed-changeapproval.
|
|
APPEND VALUE #( %tky = <approval>-%tky
|
|
%msg = new_message_with_text(
|
|
severity = if_abap_behv_message=>severity-error
|
|
text = 'A reject reason is required' ) )
|
|
TO reported-changeapproval.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
MODIFY ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
UPDATE FIELDS ( Status RejectReason DecidedBy DecidedOn )
|
|
WITH VALUE #( ( %tky = <approval>-%tky
|
|
Status = status-rejected
|
|
RejectReason = key-%param-RejectReason
|
|
DecidedBy = cl_abap_context_info=>get_user_technical_name( )
|
|
DecidedOn = utclong_current( ) ) )
|
|
FAILED DATA(update_failed)
|
|
REPORTED DATA(update_reported).
|
|
ENDLOOP.
|
|
|
|
READ ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
ALL FIELDS WITH CORRESPONDING #( keys )
|
|
RESULT DATA(updated).
|
|
|
|
result = VALUE #( FOR row IN updated ( %tky = row-%tky %param = row ) ).
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD retrySync.
|
|
" FAILED -> EXECUTING; clears the previous error so the worker re-executes the staged payload (ARN-002 amendment)
|
|
READ ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
FIELDS ( Status )
|
|
WITH CORRESPONDING #( keys )
|
|
RESULT DATA(approvals)
|
|
FAILED failed.
|
|
|
|
LOOP AT keys INTO DATA(key).
|
|
ASSIGN approvals[ ID = key-ID ] TO FIELD-SYMBOL(<approval>).
|
|
IF sy-subrc <> 0.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
IF <approval>-Status <> status-failed.
|
|
APPEND VALUE #( %tky = <approval>-%tky ) TO failed-changeapproval.
|
|
APPEND VALUE #( %tky = <approval>-%tky
|
|
%msg = new_message_with_text(
|
|
severity = if_abap_behv_message=>severity-error
|
|
text = |Only FAILED records can be retried (status is { <approval>-Status })| ) )
|
|
TO reported-changeapproval.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
MODIFY ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
UPDATE FIELDS ( Status ErrorMessage )
|
|
WITH VALUE #( ( %tky = <approval>-%tky
|
|
Status = status-executing
|
|
ErrorMessage = '' ) )
|
|
FAILED DATA(update_failed)
|
|
REPORTED DATA(update_reported).
|
|
ENDLOOP.
|
|
|
|
READ ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
ALL FIELDS WITH CORRESPONDING #( keys )
|
|
RESULT DATA(updated).
|
|
|
|
result = VALUE #( FOR row IN updated ( %tky = row-%tky %param = row ) ).
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD markExecuting.
|
|
" APPROVED -> EXECUTING (worker claims the record; the UI never offers Approve on an executing record, PRD RAP-6)
|
|
READ ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
FIELDS ( Status )
|
|
WITH CORRESPONDING #( keys )
|
|
RESULT DATA(approvals)
|
|
FAILED failed.
|
|
|
|
LOOP AT keys INTO DATA(key).
|
|
ASSIGN approvals[ ID = key-ID ] TO FIELD-SYMBOL(<approval>).
|
|
IF sy-subrc <> 0.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
IF <approval>-Status <> status-approved.
|
|
APPEND VALUE #( %tky = <approval>-%tky ) TO failed-changeapproval.
|
|
APPEND VALUE #( %tky = <approval>-%tky
|
|
%msg = new_message_with_text(
|
|
severity = if_abap_behv_message=>severity-error
|
|
text = |Only APPROVED records can start executing (status is { <approval>-Status })| ) )
|
|
TO reported-changeapproval.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
MODIFY ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
UPDATE FIELDS ( Status )
|
|
WITH VALUE #( ( %tky = <approval>-%tky
|
|
Status = status-executing ) )
|
|
FAILED DATA(update_failed)
|
|
REPORTED DATA(update_reported).
|
|
ENDLOOP.
|
|
|
|
READ ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
ALL FIELDS WITH CORRESPONDING #( keys )
|
|
RESULT DATA(updated).
|
|
|
|
result = VALUE #( FOR row IN updated ( %tky = row-%tky %param = row ) ).
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD markSynced.
|
|
" EXECUTING -> SYNCED (terminal success); SAP is the ledger, the change number is the receipt (ARN-006)
|
|
READ ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
FIELDS ( Status )
|
|
WITH CORRESPONDING #( keys )
|
|
RESULT DATA(approvals)
|
|
FAILED failed.
|
|
|
|
LOOP AT keys INTO DATA(key).
|
|
ASSIGN approvals[ ID = key-ID ] TO FIELD-SYMBOL(<approval>).
|
|
IF sy-subrc <> 0.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
IF <approval>-Status <> status-executing.
|
|
APPEND VALUE #( %tky = <approval>-%tky ) TO failed-changeapproval.
|
|
APPEND VALUE #( %tky = <approval>-%tky
|
|
%msg = new_message_with_text(
|
|
severity = if_abap_behv_message=>severity-error
|
|
text = |Only EXECUTING records can be marked synced (status is { <approval>-Status })| ) )
|
|
TO reported-changeapproval.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
IF key-%param-SapChangeNumber IS INITIAL.
|
|
APPEND VALUE #( %tky = <approval>-%tky ) TO failed-changeapproval.
|
|
APPEND VALUE #( %tky = <approval>-%tky
|
|
%msg = new_message_with_text(
|
|
severity = if_abap_behv_message=>severity-error
|
|
text = 'The SAP change number is required to mark a record synced' ) )
|
|
TO reported-changeapproval.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
MODIFY ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
UPDATE FIELDS ( Status SapChangeNumber ErrorMessage )
|
|
WITH VALUE #( ( %tky = <approval>-%tky
|
|
Status = status-synced
|
|
SapChangeNumber = key-%param-SapChangeNumber
|
|
ErrorMessage = '' ) )
|
|
FAILED DATA(update_failed)
|
|
REPORTED DATA(update_reported).
|
|
ENDLOOP.
|
|
|
|
READ ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
ALL FIELDS WITH CORRESPONDING #( keys )
|
|
RESULT DATA(updated).
|
|
|
|
result = VALUE #( FOR row IN updated ( %tky = row-%tky %param = row ) ).
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD markFailed.
|
|
" EXECUTING -> FAILED with the error text; distinct from REJECTED (predecessor defect, ARN-002)
|
|
READ ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
FIELDS ( Status )
|
|
WITH CORRESPONDING #( keys )
|
|
RESULT DATA(approvals)
|
|
FAILED failed.
|
|
|
|
LOOP AT keys INTO DATA(key).
|
|
ASSIGN approvals[ ID = key-ID ] TO FIELD-SYMBOL(<approval>).
|
|
IF sy-subrc <> 0.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
IF <approval>-Status <> status-executing.
|
|
APPEND VALUE #( %tky = <approval>-%tky ) TO failed-changeapproval.
|
|
APPEND VALUE #( %tky = <approval>-%tky
|
|
%msg = new_message_with_text(
|
|
severity = if_abap_behv_message=>severity-error
|
|
text = |Only EXECUTING records can be marked failed (status is { <approval>-Status })| ) )
|
|
TO reported-changeapproval.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
IF key-%param-ErrorMessage IS INITIAL.
|
|
APPEND VALUE #( %tky = <approval>-%tky ) TO failed-changeapproval.
|
|
APPEND VALUE #( %tky = <approval>-%tky
|
|
%msg = new_message_with_text(
|
|
severity = if_abap_behv_message=>severity-error
|
|
text = 'An error message is required to mark a record failed' ) )
|
|
TO reported-changeapproval.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
MODIFY ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
UPDATE FIELDS ( Status ErrorMessage )
|
|
WITH VALUE #( ( %tky = <approval>-%tky
|
|
Status = status-failed
|
|
ErrorMessage = key-%param-ErrorMessage ) )
|
|
FAILED DATA(update_failed)
|
|
REPORTED DATA(update_reported).
|
|
ENDLOOP.
|
|
|
|
READ ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
ALL FIELDS WITH CORRESPONDING #( keys )
|
|
RESULT DATA(updated).
|
|
|
|
result = VALUE #( FOR row IN updated ( %tky = row-%tky %param = row ) ).
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD setInitialStatus.
|
|
" Every created record starts PENDING with the requester audit fields (ARN-002)
|
|
READ ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
FIELDS ( Status )
|
|
WITH CORRESPONDING #( keys )
|
|
RESULT DATA(approvals).
|
|
|
|
DELETE approvals WHERE Status IS NOT INITIAL.
|
|
IF approvals IS INITIAL.
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
MODIFY ENTITIES OF zzr_changeapproval000 IN LOCAL MODE
|
|
ENTITY ChangeApproval
|
|
UPDATE FIELDS ( Status RequestedBy RequestedOn )
|
|
WITH VALUE #( FOR approval IN approvals
|
|
( %tky = approval-%tky
|
|
Status = status-pending
|
|
RequestedBy = cl_abap_context_info=>get_user_technical_name( )
|
|
RequestedOn = utclong_current( ) ) )
|
|
REPORTED DATA(update_reported).
|
|
|
|
reported = CORRESPONDING #( DEEP update_reported ).
|
|
ENDMETHOD.
|
|
|
|
ENDCLASS.
|