添加 & 删除生产工单组件
我们都非常熟悉生产订单的创建以及对现有操作和组件的修改。 但是,如果我们需要删除现有组件并将组件添加到给定的production order中,该怎么办?
一般我们通过CO02事务,然后到组件概览并进行操作来进行组件的添加或删除。 但是如果我们需要从程序级别来做呢?
以下代码片段可用于创建生产订单、删除现有组件和添加新组件,然后发布生产订单。
创建生产订单:
可以使用 BAPI_PRODORD_CREATE 创建生产订单。 它可以如下面的代码片段所示使用。
*** Production Order Creation
DATA: ls_orderdata TYPE bapi_pp_order_create,
ls_return TYPE bapiret2,
lv_order_number TYPE bapi_order_key-order_number,
lv_order_type TYPE bapi_order_copy-order_type.
* Assign data to BAPI Header to create Production order
ls_orderdata-material = '000000000000000001'.
ls_orderdata-plant = '0001'.
ls_orderdata-order_type = 'PP01'.
ls_orderdata-basic_start_date = sy-datum.
ls_orderdata-basic_start_time = sy-uzeit.
ls_orderdata-basic_end_date = sy-datum.
ls_orderdata-basic_end_time = sy-uzeit.
ls_orderdata-quantity = 1.
CALL FUNCTION 'UNIT_OF_MEASURE_ISO_TO_SAP'
EXPORTING
iso_code = 'PCE'
IMPORTING
sap_code = ls_orderdata-quantity_uom
EXCEPTIONS
not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
IF NOT ls_orderdata IS INITIAL.
* BAPI Create Production Order
CALL FUNCTION 'BAPI_PRODORD_CREATE'
EXPORTING
orderdata = ls_orderdata
IMPORTING
return = ls_return
order_number = lv_order_number
order_type = lv_order_type.
IF ( ls_return-type = 'S' OR
ls_return-type = 'I' OR
ls_return-type = 'W' ) OR
ls_return IS INITIAL.
* Commit data
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.
ELSE.
* Data Rollback
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ENDIF.
ENDIF.
工单组件删除:
创建生产订单后,从订单物料的 BOM 中获取组件。 如果我们要删除特定组件或所有组件,则可以使用 CO_XT_COMPONENT_DELETE 功能模块来完成,如下面的代码片段所示。 其中CO_XT_ORDER_PREPARE_COMMIT 和 CO_XT_ORDER_INITIALIZE用于提交更改并初始化处理过程中所需的所有其他表.
*** Deleting Components from Production Order
DATA: lt_resbkeys TYPE coxt_t_resbdel,
lt_return TYPE STANDARD TABLE OF bapiret2,
lv_error TYPE flag.
* Fetch existing components of given Production Order
SELECT rsnum, rspos INTO TABLE @DATA(lt_resb)
FROM resb
WHERE aufnr = @lv_order_number. " Previously created order
IF sy-subrc EQ 0.
lt_resbkeys = CORRESPONDING #( lt_resb ).
ENDIF.
IF NOT lt_resbkeys[] IS INITIAL.
* BAPI to delete the components of Production Order
CALL FUNCTION 'CO_XT_COMPONENTS_DELETE'
EXPORTING
it_resbkeys_to_delete = lt_resbkeys
IMPORTING
e_error_occurred = lv_error
TABLES
ct_bapireturn = lt_return
EXCEPTIONS
delete_failed = 1
OTHERS = 2.
IF lv_error = space.
CALL FUNCTION 'CO_XT_ORDER_PREPARE_COMMIT'
IMPORTING
es_bapireturn = ls_return
e_error_occurred = lv_error.
IF ( ls_return-type = 'S' OR
ls_return-type = 'W' OR
ls_return-type = 'I' ) OR
ls_return IS INITIAL.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.
CALL FUNCTION 'CO_XT_ORDER_INITIALIZE'.
ELSE.
CLEAR: lv_error,
ls_return.
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ENDIF.
ELSE.
CLEAR lv_error.
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ENDIF.
ENDIF.
向工单添加组件:
如果我们需要向生产订单添加组件,可以使用 CO_XT_COMPONENT_ADD 功能模块来完成。 其中需要使用 CO_XT_ORDER_PREPARE_COMMIT 和 CO_XT_ORDER_INITIALIZE
提交更改并初始化处理期间所需的所有其他表。但是通过使用上述功能模块,我们有一个小问题: 添加的组件中将缺少项目编号。 这是由于 I_POSNO(功能模块 I 中的参数)和 RESB-POSNR 的类型不兼容.
所以为了解决这个问题,我们将通过在DB更新之前将其分配给内部表来修改POSNR,以更正组件中的空白项目编号.
*** Adding components to Production Order
DATA: ls_storage_location TYPE coxt_s_storage_location,
ls_storage_locationx TYPE coxt_s_storage_locationx,
ls_requ_quan TYPE coxt_s_quantity,
lv_operation TYPE co_aplzl,
lv_batch TYPE coxt_batch,
lv_batchx TYPE coxt_batchx,
lv_postp TYPE postp,
lv_sequence TYPE plnfolge,
lv_material TYPE matnr,
lv_positionno TYPE positionno,
lv_numc TYPE numc4.
TYPES: BEGIN OF ty_resb_bt.
INCLUDE TYPE resbb.
TYPES: indold TYPE syst_tabix.
TYPES: no_req_upd TYPE syst_datar.
TYPES: END OF ty_resb_bt.
TYPES tt_resb_bt TYPE TABLE OF ty_resb_bt.
FIELD-SYMBOLS: <ft_resb_bt> TYPE tt_resb_bt,
<fs_resb_bt> TYPE ty_resb_bt.
ls_storage_location-werks = '0001'.
ls_storage_locationx-werks = 'X'.
ls_storage_location-lgort = 'LGOT'.
ls_storage_locationx-lgort = 'X'.
lv_batch = '0000000001'.
lv_batchx = 'X'.
ls_requ_quan-quantity = 1.
CALL FUNCTION 'UNIT_OF_MEASURE_ISO_TO_SAP'
EXPORTING
iso_code = 'PCE'
IMPORTING
sap_code = ls_requ_quan-uom
EXCEPTIONS
not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
lv_positionno = '0010'.
lv_postp = 'L'.
lv_material = '000000000000000002'.
SELECT SINGLE aufnr, aufpl INTO @DATA(ls_afko)
FROM afko
WHERE aufnr = @lv_order_number.
IF sy-subrc EQ 0.
* Fetch operation to which it has to be assigned
SELECT SINGLE aufpl, aplzl, plnfl INTO @DATA(ls_afvc)
FROM afvc
WHERE aufpl = @ls_afko-aufpl.
IF sy-subrc EQ 0.
lv_operation = ls_afvc-aplzl.
lv_sequence = ls_afvc-plnfl.
ENDIF.
ENDIF.
* BAPI to add components to Production Order
CALL FUNCTION 'CO_XT_COMPONENT_ADD'
EXPORTING
is_order_key = lv_order_number
i_material = lv_material
is_requ_quan = ls_requ_quan
i_operation = lv_operation
i_sequence = lv_sequence
is_storage_location = ls_storage_location
is_storage_locationx = ls_storage_locationx
i_batch = lv_batch
i_batchx = lv_batchx
i_postp = lv_postp
i_posno = lv_positionno
IMPORTING
es_bapireturn = ls_return
e_error_occurred = lv_error.
IF lv_error = space.
CLEAR: lv_numc,
ls_return.
* Modify POSNR via ASSIGN before DB update to correct the blank
* item number in Components due to incompatible types of I_POSNO
* (type CIF_R3RES-POSITIONNO) and RESB-POSNR
ASSIGN ('(SAPLCOBC)RESB_BT[]') TO <ft_resb_bt>.
LOOP AT <ft_resb_bt> ASSIGNING <fs_resb_bt>.
lv_numc = sy-tabix * 10.
<fs_resb_bt>-posnr = lv_numc.
CLEAR lv_numc.
ENDLOOP.
* Commit transaction
CALL FUNCTION 'CO_XT_ORDER_PREPARE_COMMIT'
IMPORTING
es_bapireturn = ls_return
e_error_occurred = lv_error.
IF ( ls_return-type = 'S' OR
ls_return-type = 'W' OR
ls_return-type = 'I' ) OR
ls_return IS INITIAL.
* Commit data
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.
CALL FUNCTION 'CO_XT_ORDER_INITIALIZE'.
ELSE.
CLEAR: lv_error,
ls_return.
* Data Rollback
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ENDIF.
ELSE.
CLEAR: lv_error,
ls_return.
* Data Rollback
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ENDIF.
Release生产工单:
创建订单后,可以通过以下代码片段Release它。.
*** Release Created Production Order
DATA: lt_order TYPE STANDARD TABLE OF bapi_order_key,
ls_order TYPE bapi_order_key.
SELECT SINGLE a~aufnr, a~objnr, b~stat INTO @DATA(ls_aufk)
FROM aufk AS a
INNER JOIN jest AS b
ON a~objnr = b~objnr
WHERE a~aufnr = @lv_order_number
AND b~stat = 'I0002'
AND b~inact = @space.
IF sy-subrc NE 0.
ls_order-order_number = lv_order_number.
* If production order is not released then append the order to table
* LT_ORDER to release the order
APPEND ls_order TO lt_order.
CLEAR ls_order.
ENDIF.
IF NOT lt_order[] IS INITIAL.
CLEAR ls_return.
* Release Production order
CALL FUNCTION 'BAPI_PRODORD_RELEASE'
IMPORTING
return = ls_return
TABLES
orders = lt_order.
IF ( ls_return-type = 'S' OR
ls_return-type = 'W' OR
ls_return-type = 'I' ) OR
ls_return IS INITIAL.
CLEAR ls_return.
* Commit Data
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.
ELSE.
* Data Rollback
CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
CLEAR ls_return.
ENDIF.
ENDIF.
对于更改现有组件,我们可以使用 CO_XT_COMPONENT_CHANGE 配合 CO_XT_ORDER_PREPARE_COMMIT 和 CO_XT_ORDER_INITIALIZE来一起完成。
注意:CO_XT_COMPONENT_CHANGE / CO_XT_COMPONENT_ADD 这些都是 SAP 未发布的常规功能模块,使用时需要谨慎。