UPDATE using CRM_ORDER_MAINTAIN simple example (for those new to CRM and/or ABAP)
In a previous blog http://scn.sap.com/community/crm/blog/2013/02/07/crmorderread-simple-example-for-those-new-to-crm-andor-abap I gave a very simple example of how to use CRM_ORDER_MAINTAIN to create a new order.
This blog will show you how to UPDATE an order in CRM using ABAP.
I’ve tried to make this as simple as possible but while including the most important (useful) information.
In this example I will only update the orderadm and opport (opportunity) tables.
include crm_object_names_con.
data:
lt_opport_h type crmt_opport_h_comt,
ls_opport_h type line of crmt_opport_h_comt,
lt_orderadm_h type crmt_orderadm_h_comt,
ls_orderadm_h type crmt_orderadm_h_com,
*Other important things
lt_input_fields type crmt_input_field_tab,
ls_input_fields type crmt_input_field,
lt_nametab type crmt_input_field_names_tab,
ls_nametab type crmt_input_field_names,
lt_save_guid type crmt_object_guid_tab,
ls_save_guid type crmt_object_guid,
lt_saved_objects type crmt_return_objects,
ls_saved_objects type crmt_return_objects_struc,
lv_lin type i,
lv_order_object_id type crmt_object_id,
lv_order_object_guid type crmt_object_guid32.
* 1. Update the description of the opportunity
clear: ls_nametab, lt_nametab[],
ls_input_fields.
ls_orderadm_h-description = ‘this is the new description’.
ls_nametab = 'DESCRIPTION'.
append ls_nametab to lt_nametab.
*** for help on how to change a CHAR32 to a RAW16 see my CRM_ORDER_READ blog ***
ls_orderadm_h-guid = ‘this is the GUID type RAW16’.
append ls_orderadm_h to lt_orderadm_h.
ls_input_fields-ref_kind = 'A'.
ls_input_fields-ref_guid = ‘this is the GUID again, in RAW16’.
ls_input_fields-objectname = 'ORDERADM_H'.
ls_input_fields-field_names[] = lt_nametab[].
insert ls_input_fields into table lt_input_fields.
* 2. Update the opportunity data in opport_h table – update the current phase and end date
clear: ls_nametab, lt_nametab[], ls_input_fields.
ls_opport_h-curr_phase = ‘code for new sales stage’.
ls_nametab = 'CURR_PHASE'.
append ls_nametab to lt_nametab.
ls_opport_h-expect_end = ‘new date for expected end date’.
ls_nametab = 'EXPECT_END'.
append ls_nametab to lt_nametab.
ls_opport_h-ref_guid = ‘this is the GUID again, in RAW16’.
append ls_opport_h to lt_opport_h.
ls_input_fields-ref_guid = ‘this is the GUID again, in RAW16’.
ls_input_fields-ref_kind = 'A'.
ls_input_fields-objectname = 'OPPORT_H'.
ls_input_fields-field_names[] = lt_nametab[].
insert ls_input_fields into table lt_input_fields.
* 3. DONE, call CRM_ORDER_MAINTAIN on this information
call function 'CRM_ORDER_MAINTAIN'
exporting
it_opport_h = lt_opport_h
importing
et_exception = lt_exception1
changing
ct_orderadm_h = lt_orderadm_h
ct_input_fields = lt_input_fields
exceptions
error_occurred = 1
document_locked = 2
no_change_allowed = 3
no_authority = 4
others = 5.
case sy-subrc.
when 0.
ls_save_guid = iv_guid.
append ls_save_guid to lt_save_guid.
endcase.
* 4. SAVE the changes (all updates must be saved and committed before they change in CRM)
call function 'CRM_ORDER_SAVE'
exporting
it_objects_to_save = lt_save_guid
importing
et_saved_objects = lt_saved_objects
exceptions
document_not_saved = 1
others = 2.
case sy-subrc.
when '0'.
clear lv_lin.
describe table lt_saved_objects lines lv_lin.
if lv_lin = 1.
read table lt_saved_objects into ls_saved_objects index 1.
lv_order_object_guid = ls_saved_objects-guid.
lv_order_object_id = ls_saved_objects-object_id.
* 5. Call the function to COMMIT the changes to CRM.
call function 'BAPI_TRANSACTION_COMMIT'.
endif.
endcase.
*DONE, your opportunity has now been updated.
Hello,
Can i have an example for creating contract (items and header) with CRM_ORDER_MAINTAIN.
Thanks in advance.
Best regards,
S.
Just typing up an example for you.
I will POST it here as soon as I've got one together 🙂
Hi MZK Sanaa,
Here is some code which I hope will help you:
The structure needed in the crm_order_maintain call are:
Exporting "IT_SCHEDLIN_I" (for the quantities)
Changing "CT_INPUT_FIELDS" (for the fields you're populating) and "CT_ORDERADM_I" (the actual items)
How to populate these tables (this should give the right idea):
I hope this is helpful - after the order_maintain, call CRM_ORDER_SAVE and BAPI_TRANSACTION_COMMIT
Let me know how you get along with this,
Lindsay
Thank you for your reply Lindsay.
This example may help me to resolve my issue.
Best regards,
Sanaa
Hi Lindsay:
I love that attitude towards other people. Somebody who after being sacrificed digging to get to know something, is willing to share. Thank you very much indeed.
Lindsay this is part out of this topic, but do you happen to have any experience with SAP workflow? We are trying to use WF to work with Business Object BUS2000116, aswe want to create a WF task (item) to be assigned to users (Agents). So far we have been able to use your function to read the business transaction (we already had another way of reading the data, but CRM_ORDER_READ is the way to go to make it generic and we had no clue how to use it as ABAP is not my main area of expertise).
We also use BRFPlus to retrieve some HR data related to one of the BPs actor of the Business Transaction; Evaluation paths to obtain the list of the so called Agents and also a Rule to retrieve those agents, etc. So far, we are almost ready, but the problem is that SAP delivers an example WF related for ChaRM for BO BUS2000116 that uses Method ChangeWithDialogAsyn to create the task, but the method does not necessarily apply to what we need. In other words, we need to create our own method that will create the task to be delivered to the Agents' worklist.
Once all that is complete our goal is to publish it in SCN as one of the big challenges for people using SAP CHaRM has been the ability of sending multiple e-mails or tasks to Agents. I believe that once many understand WF applied to CHaRM, there is going to be a lot of freedom for many people to adapt any potential scenario.
We are still investigation on our side, but seeing your disposition, any help is appreciated.
Regards,
Juan
You might want to consider posting your comment as a question so it gets more attention instead. However if you need a different method on a existing business object you can subtype the existing business object and use delegation to replace the parent BUS2000116 with your new subtype that contains your custom method. That's how I would do it in a CRM based system when I need to add a new attribute or method to an existing BUS2000xxx business object. The nice part about delegation is that all the other event listening etc will still apply so you don't have to develop a new business object from scratch.
Take care,
Stephen
Many thanks Stephen.
Good point that invites me to clarify. We already have a subtype and the proper delegation setup. No problem with that.
We are just looking for an ABAP (BOR) example ofa method that creates a WF task (item) for an Agent. A method associated to any CRM Business Object BUS2001* will do the work. Why BUS20001* in particular? Because most of the Business Objects use WF related methods that call transactions, so when the Agent gets the workflow item in the worklist, in order to process it, a transaction gets launched. In the case of BUS20001*, the methods are related to WEB UI processing, not transactions.
The approach for creating the WF task is different when using WEB UI.
We understandthe task creates an instance linkage in table SWFDVEVTY1 (transaction SWE3), associating the Business Transaction GUID to an event. Once the event gets triggered (we know how to do that), as per WF task outcome, the created entry in SWFDVEVTY1 is supposed to be remove and the WF continues to the next step.
Almost all pieces together except the one that tells how to create the task in a BOR method.
Regards,
Juan
Good day:
For the records, the already delivered method BUS2000116.ChangeWithDialogAsyn does the work. We did not have to create a new method. The issue we had is with the multiple condition we were using.
My apologies for the inconvenience.
Juan
PS. The documentation of all what we did will be posted soon. Only one piece to go now that the workflow is working fine.
Hi Juan,
I'm so sorry it has taken me this long to reply to your messages, and I apologise for not being able to help! Coincidentally I have just now been learning about workflows myself, and working with them for the last 4 months, it's all fairly new to me too so I will be interested to see your solution!
Thank you,
Lindsay
Hi Lindsay:
We are on the same boat. With all the struggles we had for months to sort things out and put all the scenario together, leaning towards your approach of sharing knowledge, we decided to write a blog to explain different areas of expertise involved in our solution.
The initial blog link is http://scn.sap.com/community/it-management/alm/solution-manager/blog/2014/01/21/sap-crmsolman-charm-multiple-target-agents-via-sap-workflow--minimal-abap-development
Is quite basic honestly, but who knows who is going to run into it, so we can not assume.
Part #4 has some bibliography at the end and some links.
No problem for the lack of time Lindsay. We all are on the same boat.
Regards,
Juan Carlos
Hi lindsay Thank you a lot for the sharing. Please i have an issue about the same program if i make a loop to mass update the opportunities. the program only update one opportunity How can i transform your program to make it valid for mass opportunities update ? thank you Best regards
Hi Akrem,
I haven't done this myself, but off the top of my head the way to perform mass updates is to do exactly as you see in this example here, but add more values to the internal tables being passed into the ORDER_MAINTAIN function - which are all related by their GUIDs back to an entry in the header table (OREDADM_H). Does this make sense? Let me know how you get on 🙂
The best way to find out for sure would be to put a break point in CRM_ORDER_MAINTAIN and then perform a mass update through the CRM_UI, and see what parameters it passes in.
Thanks for you question, I hope this help,
Lindsay
Hi Lindsay ,
can you help me in creating Service request using CRM_ORDER_MAITAIN (parameters to be passed )and save..
Hi Krishna,
My advice would be this: set a break-point (use BP) in CRM_ORDER_MAINTAIN and then create the service request as you would, in a non-ABAP way (I imagine using the CRM_UI web interface?)
When it hits the BP you will see what tables are populated and how.
Sometimes the standard SAP way of creating things will in-fact call this FM multiple times, to add different bits to the object each time, but this can usually be condensed into one call, by taking all the inputs from the various calls, and passing them in in one go.
Sorry I can't be more help - I haven't' created a service request this way yet.
But once you set a break point and see how it works, it should be come clearer how to proceed 🙂
Hi Lindsay Stanger,
thanks For replay..., Well done like that only and passed values but itn's not working you can see my discussion thread.
Hi Lindsay,
I was looking for such a post from quite a few days .
Thanks For sharing .
Hi Lindsay,
First of all thank you for making life easier for beginners of SAP CRM. Can you please exaplin the tables that you have used and why have you used them ? i'm unable to find much on the tables that you have used. Are those custom tables or predefned ones?
Hi Rahul,
The tables that are used in the ABAP above are the standard importing tables used by the function-module CRM_ORDER_MAINTAIN. None of the ones specified are custom.
For example: "lt_orderadm_h type crmt_orderadm_h_comt" this local table which I use is based on the database table CRMD_ORDERADM_H, the order header data is stored.
If you look at the Function Module and look under the Import tab you will see descriptions beside most of the importing parameters to tell you what these tables are about.
My best advice if you are looking to understand this function module better is to set a breakpoint in the FM, and then make a change to an order (opportunity, lead, sales document) - and see what tables are populated when the debug session opens.
I hope this is helpful to you.
Thank you for your comments,
Lindsay
Rahul,
If you want a very quick overview take a look here:
http://wiki.scn.sap.com/wiki/display/CRM/CRM+Business+Transactions
There are other resources available on the topic if you do a quick search.
Take care,
Stephen
Lindsay,
I have some Itab coming from a process type of quote coming from crm_order_read need to insert into sales order. I need to insert those itab lines into sales order line items how will I do it with crm_order_maintain please let me know some example of it .
Regards,
Girish
Hi Lindsay,
I am creating Contract using FM CRM_ORDER_MAINTAIN. However my Sold to Party is not getting populated. I am populating Org data, External Reference number. Except sold to part rest of the data is getting populated. Please help.
Please refer my code:
*Process Type
CLEAR ls_orderadm_h.
ls_orderadm_h-process_type = 'ZWN'.
ls_orderadm_h-mode = 'A'.
APPEND ls_orderadm_h TO lt_orderadm_h.
**Preapre Field list table
CLEAR: ls_nametab,
ls_input_fields.
REFRESH lt_nametab[].
ls_nametab = lc_mode.
APPEND ls_nametab TO lt_nametab.
ls_nametab = lc_proc_type.
APPEND ls_nametab TO lt_nametab.
ls_input_fields-ref_kind = lc_a.
ls_input_fields-objectname = 'ORDERADM_H'.
ls_input_fields-field_names[] = lt_nametab[].
INSERT ls_input_fields INTO TABLE lt_input_fields.
*Sold-To-Party
CLEAR ls_partner.
ls_partner-ref_kind = 'A'.
ls_partner-ref_partner_handle = '0001'.
ls_partner-display_type = 'BP'.
ls_partner-kind_of_entry = 'C'.
ls_partner-no_type = 'BP'.
ls_partner-partner_fct = '00000001'.
ls_partner-partner_no = '0001040406'.
APPEND ls_partner TO lt_partner.
**Preapre Field list table
CLEAR: ls_nametab,
ls_input_fields.
REFRESH lt_nametab[].
ls_nametab = 'DISPLAY_TYPE'.
APPEND ls_nametab TO lt_nametab.
ls_nametab = 'KIND_OF_ENTRY'.
APPEND ls_nametab TO lt_nametab.
ls_nametab = 'NO_TYPE'.
APPEND ls_nametab TO lt_nametab.
ls_nametab = 'PARTNER_FCT'.
APPEND ls_nametab TO lt_nametab.
ls_nametab = 'PARTNER_HANDLE'.
APPEND ls_nametab TO lt_nametab.
ls_nametab = 'PARTNER_NO'.
APPEND ls_nametab TO lt_nametab.
ls_input_fields-ref_kind = 'A'.
ls_input_fields-objectname = 'PARTNER'.
ls_input_fields-logical_key = '0001'.
ls_input_fields-field_names[] = lt_nametab[].
INSERT ls_input_fields INTO TABLE lt_input_fields.
CALL FUNCTION 'CRM_ORDER_MAINTAIN'
EXPORTING
it_partner = lt_partner
IMPORTING
et_exception = lt_exception
CHANGING
ct_orderadm_h = lt_orderadm_h
ct_input_fields = lt_input_fields
EXCEPTIONS
error_occurred = 1
document_locked = 2
no_change_allowed = 3
no_authority = 4
OTHERS = 5.
IF sy-subrc EQ 0.
CLEAR ls_orderadm_h.
READ TABLE lt_orderadm_h INTO ls_orderadm_h INDEX 1.
ls_save_guid = ls_orderadm_h-guid.
APPEND ls_save_guid TO lt_save_guid.
CALL FUNCTION 'CRM_ORDER_SAVE'
EXPORTING
it_objects_to_save = lt_save_guid
IMPORTING
et_saved_objects = lt_saved_objects
EXCEPTIONS
document_not_saved = 1
OTHERS = 2.
IF sy-subrc EQ '0'.
CLEAR lv_lin.
DESCRIBE TABLE lt_saved_objects LINES lv_lin.
IF lv_lin = 1.
READ TABLE lt_saved_objects INTO ls_saved_objects INDEX 1.
lv_order_object_guid = ls_saved_objects-guid.
lv_order_object_id = ls_saved_objects-object_id.
* Call the function to COMMIT the changes to CRM.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
wait = abap_true.
Hello together,
I have problem with CRM_ORDER_SAVE. I use this method at a PPF by saving of orders. The Problem this method will be executed twice, because of my PPF and the SAP standard run of this method. However, the problem that, with my updated data in CRM_ORDER_MAINTAIN method, it will be also updated for example SLA data and it leads to redundant calculation of SLA.
Any suggestions, how can I implement the logic, without influencing of storing data, which should not be stored.
Thx in advance.
Best regards
Georg