Skip to main content

C4C Message Handling insights

Submitted by Stefan Barsuhn on

Wow, this is one for the history books ...

So we had this weird issue during replication from ERP that C4C would throw an error 

The BO 'CUSTOMER_QUOTE' supplied with the message does not match the BO of the current service call; within a service call, it is not allowed to raise messages for other BOs; application component 'LOD-LE-CQP

Nothing was showing in the Dump logs and the Incident Context was inconclusive.

So raised an incident with SAP. Unfortunately, the ticket got stuck with the folks in India, who usually just copy and paste you the ABAP dump logs they see on their end and don't seem to know that we have to deal with ABSL.

They pointed to the following line in a CustomerQuote.Root.AfterLoading script:

var parties = cq.Party;

 ... and (here comes) claimed that this line was raising the error 

PDI_ABSL_RSC 006 with AMOUNT-CURRENCY_CODEImporting parameter &1 is initial

I kid you not! Of course it was no use telling them that this doesn't make any sense - how would the retrieval of a Party node raise a currency error??? They just kept repeating that this is what they see on their end and that I should talk to the PDI partner if I needed more information (If you're familiar with the crazy house in "The Twelve Tasks of Asterix" - that's how I felt).

When I tried to have this escalated to Brazil (where people actually know a thing or two about C4C), my favorite C4C engineer was on leave, so I was stuck with India for another two weeks, in which they managed to produce no new information other than asking me for sample data to be able to reproduce the issue. After 2 months! I’m still contemplating if they said that to actually understand the issue (because if that’s the case, why didn’t they ask for it like 2 months ago?) or if that was just to get the ticket out of their bucket again.

Luckily, I didn’t have to find out as a) my support engineer was back from leave and b) I was lucky that someone else had raised an unrelated incident, managed to get somebody in Brazil to analyze it and they found that the root cause is the same.

And this brings me to the interesting part where we can learn something about the internal workings of C4C:

I’ll copy and paste the answer from SAP first:

The messages are getting raised from line 434 of /YXXXXXX_MAIN/SRC/SalesOrderQuote/RLCustomerQuote-Function-CurrencyCalculations.absl that has the below code in place:   Z_Cons_Contrib_MarginGC = Z_Cons_Contrib_MarginGC.Round();   Here, Z_Cons_Contrib_MarginGC is initial, and so Z_Cons_Contrib_MarginGC-currencyCode is blank. The error is getting raised over here due to this reason for the following "quote_id"s: 00000000000000000000000000000216099 00000000000000000000000000000216099 00000000000000000000000000000477698 00000000000000000000000000001849130 00000000000000000000000000000308245 00000000000000000000000000001890612 00000000000000000000000000002372309   In order to avoid this, partner code can introduce a check to ensure that the Round() is only called when the field Z_Cons_Contrib_MarginGC is not initial.

After this on line 157 of /YXXXXXX_MAIN/SRC/SalesOrderQuote/CustomerQuote-Root-Event-BeforeSave.absl partner is trying to load a CustomerQuote instance from the Opportunity-BTDR node using the below line: var quote = ref.CustomerQuote;   Since the Business Object requesting for the association is Opportunity, the expectation from from famework is that if any messages get raised, they should be raised for Opportunity alone, and not for any other Business Object.   However, the loading of the CustomerQuote instance ends up triggering the corresponding AfterLoading event (/YXXXXXX _MAIN/SRC/SalesOrderQuote/CustomerQuote-Root-Event-AfterLoading.absl), in which, partner has the below line of code on line 43 var parties = cq.Party;   When an association is fetched, the corresponding error messages pertaining to that BO are refreshed in the Framework buffer.   However, over here, the messages are raised with a CustomerQuote context, whereas the parent context is still Opportunity(from the BeforeSave call).   This results in the exception getting raised from Framework with the below message:   "The BO 'CUSTOMER_QUOTE' supplied with the message does not match the BO of the current service call; within a service call, it is not allowed to raise messages for other BOs; application component 'LOD-LE-CQP'"   As already mentioned earlier, this issue will be resolved once the partner code maintains the correct data as per their code, or adjusts the code to handle empty currency codes.

I’ll admit that we have a lot of complex logic in our system. When you update a quote, it updates related opportunities, which in turn may update other related quotes.

So what SAP is saying here, is: While updating one of the quotes we’re doing some currency calculations. As part of those calculations, we’re using the built-in Round() function. One thing I hate about these built-in functions is that they always have to print error messages that you can’t suppress. What’s a user going to do when they see some weird error about import parameter missing in the Round function? This is all ABSL so either we’re able to handle this gracefully or don’t show the error at all and apply some common-sense logic (like simply return the input value).

So apparently this Round() function is throwing an error because I’m calling it on an initial Amount field (no currency code). But this error is not thrown in that script file (where I would have been able to spot the issue immediately) – no, it appears to stay suppressed until, at a later point, in a totally unrelated piece of code, I’m accessing the Party entity of the CustomerQuote. This apparently leads to a flushing of the message buffer. But as this is a different context now (we’ve navigated from Quote A to Opportunity to Quote B), the system can’t raise this message. So it raises the weird message about the BO not matching the BO of the service call.

Wow. First of all, I’ve sent the analyst my deepest appreciation for being able to produce this spot-on analysis in the first reply we received to that incident. But second, I’m still amazed at how complex C4C is not only on the frontend, but in the backend as well. How contrives stuff like this? I should write another post about “Finalize Ordering” – and ask SAP if they one day give me a factory tour of C4C ;-).

Tags