Thursday, August 1, 2013
How to disable Query on an Applet?
Wednesday, July 27, 2011
Child Field Read Only depending on Parent Field Value
Today, I am going to discuss a very simple requirement you might have faced earlier.
Requirement
I have two applet exposed on the UI: 1) Opportunity Form Applet 2) Quote List applet.
Opportunity being the parent applet and quote as the child as per below screen shot.

The simple requirement is to make "Comments" field on Quote List Applet editable, if and only if Sales Stage of Opportunity = Data Entry.
very simple isn't it! Anyone can easily say, go and use "Field Read Only Field" user property at Quote business component and you are done. I reacted to it in the similar manner and followed the below steps:
1. Pull "Sales Stage" value on Quote BC.
2. Create a calc field to set to Y, if Sales Stage = "Data Entry"

3. Create a BC User property, Field Read Only Field based on calc field.

Compile the SRF.
Navigate to Opportuity -> Quote view to verify the results. I created an Opportunity record, set the Sales Stage to "Data Entry" and then created a Quote record. "Comments" field was editable. Then I changed the Sales Stage to "Submitted" and per configuration I was expecting the "Comments" field to be read only, but to my surprise, it was not. Still, I was able to edit the field.

It might happen that change of "Sales Stage" at the Opportunity level is not getting reflected at the quote level. Let me try running a blank query (Alt+Q, then enter) to refresh and now..... yes, "Comments" field get read-only. So, basically the problem is, Quote BC is not aware of the change in Sales Stage at Opportunity level, unless you refresh it.
(Note: this is not the case with "Parent Read Only Field" user property. Change at parent field immediately gets reflected at the child level. You can refer this post for more details.)
Now, the problem here is to get the Quote list applet refreshed, if some change happens at Opportunity. One might point out that you should have "Immediate Post Changes" as True for "Sales Stage". But, keep in mind that "Immediate Post Changes" will only refresh the fields of the same business component, not of the child BC.
One solution, I can think of is to refresh the Opportunity business component in such a way that it should not loose the record context and consequently, Quote BC will automatically gets refreshed. But, I didn't want to do the scripting on Opportunity WriteRecord event, just to refresh the Quote BC, something like:
function BusComp_WriteRecord ()
{
TheApplication().GetService("FINS Teller UI Navigation").InvokeMethod("RefreshCurrentApplet", TheApplication().NewPropertySet(), TheApplication().NewPropertySet());}
So, I found a better way to achieve to refresh the Opportunity form applet. Just create the following user property on the Opportunity applet:

Compile the SRF and check the result on the UI. Voila, everything is working as desired now.

.
Friday, July 15, 2011
How to make all Child BCs read-only when Parent BC becomes read-only?
Actual scenario goes like this:
As per the business requirement, we need to have the Opportunity business component read-only when Sales Stage is Approved. For this simple requirement we configure the BC User Property: "BC Read Only Field" based on a calculated field "OpptyReadOnlyCalc" as defined below:
User Property
Name = BC Read Only Field
Value = OpptyReadOnlyCalc
Field Details
Name = OpptyReadOnlyCalc
Calculated = True
Calculated Value = IIf([Sales Stage] = "Approved", "Y", "N")
This was working pretty fine, but complexity get added to it when we are required to make all Child business components read-only as well. Though the Opportunity record was coming read-only on the UI, but it was allowing us to create the child record as per below screen-shot:

You can see in the above screen shot (marked in Red), all the vanilla buttons i.e. Add, New, Delete are enabled. Requirement was to disable these buttons and user not allowed to do any operation on the child BCs as well as soon as Opportunity become read-only.
Solution:
To achieve this requirement, you are required to create two more BC user properties on Opportunity Business component.
User Properties
Name = Aspect Child BC ReadOnly: ReadOnly
Value = OpptyReadOnlyCalc
Name = Default Aspect
Value = ReadOnly
Thats it, compile the SRF and VoilĂ , now observe the difference on the UI.

If you want to learn about Aspect User Properties, follow the below link:
http://download.oracle.com/docs/cd/B40099_02/books/ToolsDevRef/ToolsDevRef_UserProps43.html
.
Thursday, May 19, 2011
Query performance issue : Dedicated Client Vs Thin Client
So while working on any performance issue, you always want to see the performance on dedicated client as well, so I did the same.
1. Took the same SRF running in thin client, and connect it to the Dedicated client.
2. Followed the same steps: open the pick applet and queried the Purchase Order#
To my surprise, on dedicated client the PO# query took only 6 seconds which is quite acceptable performance. So, this is the issue I faced first time when the query is running slow in thin client but not in dedicated. Now, lets try to find out what exactly is going on behind the scene.
I referred the spool file and took out the culprit query. Execution time mentioned in the query was same around 6 seconds. I ran the "Alter Sessions" commands as mentioned in my earlier post and ran the query. It again took only 6 seconds.
***** SQL Statement Execute Time: 6.014 seconds *****
I was looking into the issue more and found that when I did a query in PO# field with value "1234" and it returned multiple records with PO# like: 1234, 12345, 1234a etc. So, it is quite clear that "AutomaticTrailingWildCards" parameter in the CFG was not set to False. But, anyways the query should perform similar in both the dedicated and thin client, no matter this parameter is set to False or not. Though, this thought is quite logical but even then I wanted to give a try by disabling it. So, I thought of disabling it only on the "PO#" field on the pick applet, so that whenever user do a query on PO# field, system should not put the "like" keyword in the SQL generated at the backend.
I put the following User Property on the business component:
Name : Disable Automatic Trailing Wildcard Field ListI compiled the SRF, tested it in dedicated client, it worked fine. Now it is the time to test it in thin client as well. At this moment I was not sure how it would behave. I put the same SRF on thin client and performed the same steps for querying the Purchase Order#, I got the result in around 6 seconds. A big smile and relief too, but again I don't have the correct explanation yet for this problem why is it happening, but this user property came as the life saver :)
Value : Purchase Order Number
If you ever faced this kind of performance issue and know the exact reason please comment.
Saturday, January 16, 2010
Difference between Today() and TimeStamp() while used in Calculated field !!
So the exact requirement was :
Capture the timestamp of the record when the Status of the Service Request changes to Approved. The field used for this purpose named as "SR Approved On".
Everything looks okayy, but the only thing I wonder is that "SR Approved On" stores the correct date but not the time. "Time" it stores as "12:00:00" for each record.a) Name : On Field Update Set 1b) Value : "Status", "SR Approved On", "IIF ([Status] = 'Approved', Today(), "")"
a) Underlying column for "SR Approved On" is of type "UTC Date Time".b) Type of "SR Approved On" at the BusComp level is "DTYPE_UTCDATETIME".
a) Field Name : Current Timeb) Calculated : Truec) Calculated Value : Today()
Well, that means we cannot get current timestamp out of "Today()". I need to used something else and let me tell you this was my totally wild guess of using "TimeStamp()" function, which I never used before and it worked pretty well when I changed the Calculated value to "TimeStamp()".
Might be helpful for you, if not used it before !!a) Name : On Field Update Set 1b) Value : "Status'', "SR Approved On", "IIF ([Status] = 'Approved', TimeStamp(), "")"
Friday, December 18, 2009
How to apply Oracle hint in query via Siebel Configuration?
SELECT T1.CONFLICT_ID, T1.LAST_UPD, T1.CREATED, T1.LAST_UPD_BY,
T1.CREATED_BY, T1.MODIFICATION_NUM, T1.ROW_ID,
T1.ACCNT_TYPE_CD, T1.NAME, T1.OU_NUM, T1.DOM_ULT_DUNS_NUM, T1.BU_IDFROM
SIEBEL.S_ORG_EXT T1WHERE(T1.ACCNT_TYPE_CD = 'Establishment')
But why this simple query is taking time?? This seems to be a very simple query which is resulting in performance issue. Ok, no probs, lets try running this query at the database and see how it behaves, so I followed the instructions I mentioned in my earlier post. i.e.
After setting the session parameters, I ran the query and it took 105 seconds. hmmm..... then I checked the execution plan and found that it was doing the Full Table scan. If you look at the query, you will easily point out that create a index on ACCNT_TYPE_CD and hopefully you are done, but this is not the case. We already have a index on this field but not sure why it is not being used in the query, then you might say that get the statistics regenerated for it your issue get resolved, but that we have already tried, still not able to figure out what the cause is. Finally, our DBA helped us out here. DBAs are just magician of databases, I don't know what kind of magic stick they just use and sql query itself come to them and tell them what needs to be done here. :)..... anyways, joke apart, our DBA analysed the query and suggested that we should use "ALL_ROWS" in the query, the resultset is coming in just 2 seconds. I was surprised after hearing this because I never came across a scenario where oracle hint ALL_ROWS actually solves the performance issue, and also Siebel itself uses the Optimizer Mode = FIRST_ROWS, for session it establish with the oracle database, before running any sql query. But to my surprise, after putting the hint into the query, it ran fine with just 2 seconds on the database.
Anyways, this is also the first time learning for me, but the challenge is how to put this Oracle Hint "ALL_ROWS" in the query from Siebel configuration? And after lot much of search I found something that is worth sharing here. But before applying this, you need to very careful and get the approval from DBAs or your solution architects, so that it should not impact anywhere else in the application. Now, here is below how you can force a Siebel query to use the Oracle Hint. Identify the business component and add the following User Property there :
Property Name : OracleCBOHint
Compile the SRF and check the spool. You will see the difference in the query this time.
Check it out !!!
.
Thursday, August 27, 2009
Error while running blank query on an applet !!
There were more rows than could be returned. Please refine your query to bring back fewer rows(SBL-DAT-00500).
In the very first sight, it seems query is bringing a large number of records which Siebel can't handle. hmmm... okayy, lets try running a query which will bring less records so I put a query on "Type" field on the applet and ran the query and it worked fine. That means there is some limitation in Siebel while fetching the records and if the number of records goes beyond that limit it gives up. So, one might ask what is that upper limit??
Upper limit for number of records that Siebel can pull from a single query is equal to the value set for "MaxCursorSize" parameter available in your siebel.cfg file. Here below can be the values :
a) 0 : If this parameter set to 0 (zero), that means Siebel can fetch 10,000 records in a single query. This is the recommended value.
b) -1 : it indicates infinite number of records, results in low performance and not recommended by Siebel.
c) >0 : any number greater than 0 will fetch that many records in one query.
So, what happens is if you run a query on UI and you try to scroll the records and crosses the limit what has been set by "MaxCursorSize" parameter, you will get the above mentioned error. Moreover, the parameter is applied for each and every query that Siebel runs with the exception that it might override by "Maximum Cursor Override" property at the business component level.
I checked for the value of "MaxCursorSize" parameter in CFG and it was set to 0. Just to cross verify I also ran a query in the database and confirmed that number of records in S_ASSET records were more than 10,000 records. But, wait a minute, I didn't even scroll once on the Asset Screen and I just tried to navigate on the default view of the screen and still I received this error. This is something else is going on here, isn't it?
One more thing to notice here is that I realized that even I have more than 10,000 Accounts records in the application, but there is no issue when I navigate to All Accounts view. That means something special does exist with Asset business component which is causing this issue. And here below is the reason for it :
"Hierarchy Parent Field" property of business component was set to "Parent Asset Id" and due to this while running a blank query on the Assets UI, resulted in putting a "/*+ ALL_ROWS */" hint in the SQL that Siebel runs in the background. This is the difference I observed when I just removed the "Hierachy Parent Field" and compiled the SRF again and blank query worked fine this time. No issues. But this doesn't mean that this is the solution for the issue, you can't just remove this property to avoid this error because it get reflect in all the applet based on this business component. So here is the solution for this :
Use "Disable Buscomp Hierarchy", a user property available on the applet and set its value to True. Since it is applet based user property, only applies to the applet on which it is used.
Disable Buscomp Hierarchy = True
What it does is : it will just ignore the effect of "Hierarchy Parent Field" on the business component and run the query without "/*+ ALL_ROWS */" hint in the background to bring the records as per the normal process.
I put this user property on the All Assets List Applet and ran a blank query again, everything worked fine.
Hope it helps !!
Monday, April 6, 2009
BC Read Only Field v/s Parent Read Only Field : A Case Study
We got one requirement to make the Child and Parent Child Applet readonly in a view, if the GrandParent (the applet which is driving the visibility of the view) has got the Status = "Inactive". Sounds interesting, right?
Okayy, let me rephrase it and try to explain you with more details what exactly we want to see.
We have a View in which the following applets are exposed :
a) Accounts Form Applet - Parent
b) Service Request Form Applet - Child
c) Activities List Applet - Grandchild
Accounts applet has a field "Status" exposed on the UI and the requirement is that once Account Status = "Inactive", user cannot do any modification/insertion/deletion on Service Request and Activities applet. Both Child (Service Request) and Grandchild (Activities) applet should become readonly.
I can think of two different User Properties that we can use to achieve this. Lets see the both solution :
First Solution
So, the very first BC user property comes into mind is "BC Read Only Field", which just require a BC Field as a value and depending upon the field's value (Y/N), the BC become readonly. To achieve the solution with this user property, follow the below steps :
a) Create Calc field in Service Request BC:
Field Name : SRReadOnly
Calculated : TRUE
Calc Value : iif(ParentBCName() = "Account" AND ParentFieldValue("Status") = "Inactive", "Y", "N")
b) Create BC User Property in Service Request:
Name : BC Read Only Field
Value : SRReadOnly
c) Create Calc field in Action BC :
Field Name : ActivityReadOnly
Calculated : TRUE
Calc Value : iif(ParentBCName() = "Service Request", ParentFieldValue("SRReadOnly"), "N")
d) Create BC User Property in Action :
Name : BC Read Only Field
Value : ActivityReadOnly
e) Set Link Specification = True for "Status" field at Account BC.
Second Solution
The next BC User property that we can use here is "Parent Read Only Field", which can be used as follows :
Name : Parent Read Only Field: <_parentbuscompname>
Value : <_parentfieldname>
a) Create a calc field on Account BC :
Name : AccntInactive
Calc : TRUE
Calc Value : iif([Status] = "Inactive", "Y", "N")
b) Create a BC User Property in Service Request :
Name : Parent Read Only Field: Account
Value : AccntInactive
c) Create a calc field on Service Request BC :
Name : AccntInactive
Calc : TRUE
Calc Value : iif(ParentBCName() = "Account", ParentFieldValue("AccntInactive"), "N")
d) Create BC User Property in Action :
Name : Parent Read Only Field: Service Request
Value : AccntInactive
Compile the SRf after using each solution and observe the changes by setting Account Status Active/Inactive.
If you would compare the two solution, both looks same from configuration perspective as both require two calc fields and two user properties in all. But from scalability standpoint, second solution is better as you can easily use as many instances of "Parent Read Only Field" you want, in case Activities/Service Request need to show read only, when exposed under some other Parent BC like Opportunity, Quote etc. While in case of "BC Read Only field" you need to accomodate the business logic inside the calc field itself, as we can have only one instance of this user property at one time.
Third Solution
I can think of one more solution for this problem by, and I think the most efficient, by using both user property. Here it goes :
a) Create a calc field on Service Request BC :
Name : AccntInactive
Calc : TRUE
Calc Value : iif(ParentBCName() = "Account" AND ParentFieldValue("Status") = "Inactive", "Y", "N")
b) Create a BC User Property in Service Request :
Name : BC Read Only Field
Value : AccntInactive
d) Create BC User Property in Action :
Name : Parent Read Only Field: Service Request
Value : AccntInactive
Third solution, we can actually save one more calc field and solution is achieved by creating 1 Calc field and 2 user properties.
Your comments are most welcome, incase you have any other good ideas around this scenario.
Keep commenting !!!!!
.
Wednesday, February 4, 2009
How to Enable a Customized button on an Applet?
So, whenever there is a requirement to put a Customized button on any applet, it is required to enable that button so that user can click on it. Siebel provides various ways to enable a button on any applet, today we will talk about all those ways :
a) PreCanInvoke Event Script
All the above listed ways are serving the same purpose i.e. enable a button on applet UI. Lets see in detail, how each one of them works. Lets assume the method being invoked by button click is : "siebelmantratestmethod".
1. First Method - PreCanInvoke Event Script
if (MethodName == "siebelmantratestmethod"){CanInvoke = "True";return (CancelOperation);}
2. Second Method - Named Method n : Applet User Property
Create an applet user property with the following details :Name : Named Method 1: siebelmantratestmethodValue : 'INVOKE', 'siebelmantratestmethod'
3. Third Method - "EventMethod" methods
a) No need to create an user property.b) No need to write script on PreCanInvoke eventc) Just prefix "EventMethod" with the name of the "Method Invoked" (property of the control).Method Invoked = EventMethodsiebelmantratestmethod
4. Fourth Method - "CanInvokeMethod" applet user property (Only available in Siebel 8.0 and above)
Create an applet user user property with the following details :Name = CanInvokeMethod: siebelmantratestmethodValue = TRUE
Points to be noted :
b) EventMethod and NamedMethod are the mostly used ways and recommended ways for enabling the button. I am still not sure what is difference between the two. If you know about this, your comments are most welcome.
c) CanInvokeMethod - applet user property gives us the advantage of conditionally enabling of a button. But only available in Siebel 8.0 and above.
.
Required : A Field User Property
a) "Required" property of BusComp's field. Setting this property to TRUE, made the field mandatory while saving the record.
b) "Required", a field user property which calculates an expression to decide whether the field should be mandatory or not. This is very useful for making field mandatory, conditionally.
c) Last one is writing script on "PreWriteRecord" event of business component.
I got the requirement to make "Spouse Name" field mandatory on the UI, when user checked the field "Married" to True.
The requirement sounds very simple but we should decide the best possible way to implement it. As I mentioned above, we can implement this requirement via two ways : first one is by writing code on PreWriteRecord event and the second one is by using "Required" field user property. Lets see the both implementation.
First Implementation - Scripting on PreWriteRecord() Event
if (this.GetFieldValue("Married") == "Y" && this.GetFieldValue("Spouse Name") == ""){TheApplication().RaiseErrorText("Spouse Name is a mandatory field");}
Create Field User Prop for "Spouse Name" field :Name : RequiredValue : IIf ([Married] = "Y", "Y", "N")
Pros & Cons
1. Scripting solution is good if you need to show a customized message to the user, in case he forget to fill in the mandatory field. But scripting should be avoided as much as we can.
.
Monday, February 2, 2009
Field Read Only Field : Business Component User Property
Some might of you already know which User Property I am talking about. This is BusComp User Property : "Field Read Only Field".
Purpose :
Lets take an example and try to configure it. Suppose, on Opportunity business Component, there are two fields : a) Sales Stage b) Revenue. The requirement is as soon as "Sales Stage" = "Lost", user is not allowed to make any more change in "Revenue" field.
Lets how we can achieve this :
Name = Revenue Read Only CalcCalculated = TRUECalculated Value = iif([Sales Stage] = "Lost", "Y", "N")
Name = Field Read Only Field: RevenueValue = Revenue Read Only Calc
That's it !! Compile the Opportunity Business Component and try to change the value of Sales Stage on the UI.
You can play with the Calculated expression to test some more scenarios using AND, OR clause.
Monday, January 26, 2009
Error retrieving next record from the database.
So, as generally we do, I checked the Siebel Object Manager log and tried to find out what exactly was happening in the background. I queried for error code "(SBL-DBC-00104)" in the log file and found an Oracle code with error saying : "ORA-24345 Truncation or Null Fetch Error".
I checked for the possible reason due to which Oracle returns this error. Oracle says : "Please ensure that the buffer size is long enough to store the returned data.".
That means I was going into the right direction and data which is being displayed in "All Quotes View" was creating this problem. If I could relate this particular issue with Siebel, we have one Field User Property : "Text Length Override", which restricts the field to display some specific number of characters, no matter what is there in the database.
So, when I checked for all the fields in "Quote" business component, there was one field "Comments" which has been restricted to show only 500 charcters while its length was 1000. Now the only thing I need to confirm was if there is any record in S_DOC_QUOTE table having comments > 500 characters.
select row_id, commentsfrom S_DOC_QUOTEwhere len(comments) > 500
And I was lucky to find one. So I just truncated it to 500 characters and again tried navigating to "All Quotes View" and eveything worked fine.
.