Tuesday, February 10, 2015

Administration Pain Points

It is known for many administrators and developers of the ClickSoftware platform, that the current Service Optimization version 8.X administration tool comes with few pain points. I'm sure that version 9 will come with great new administration capabilities, but what about all the existing version 8 systems?

There are three pain points that kept coming back to me, so I've developed a small tool, to serve at times that the current remote administration tool is falling short.

First Pain Point - Large Collections

The generic approach of the current administration and the fact it was developed more than a decade ago, is a point for appreciation. However, systems today are much bigger and the amount of data is growing. The inability of the current tool to handle large collections is due to several limitations, which I will not detail here. The new advanced tool I wrote is taking advantage of a newer capability to perform SXP queries with paging. This is a very powerful service, which was added to allow the development of the Silverlight based client of ClickSchedule. The new tool allows not only to page through the data, but is taking advantage of the ability to define the sorting of the page. This means that columns are sortable and the data is still page-able.

Second Paint Point - Defining The TreeView

The management tool shows a TreeView on the left and a ListView on the right, but editing these views is an undocumented art. The definition is encapsulated in a huge XML, which is stored in a Setting object. The new advanced tool includes dialogs to edit this complex XML. There are 4 new dialogs to add and edit nodes of the TreeView:

(1) Folder Node - which shows more nodes under it,

(2) Objects Node - which is a leaf node, means it shows objects in the ListView,

(3) Collections Nodes - which is actually a set of Objects Nodes (for Dictionaries or Business Collections or both), and

(4) Values Nodes - which is a set of Objects Nodes for specific collection, but each node is of separate value (for example showing Tasks nodes per Region).

The truth is that due to the amount of details needed to define these nodes, more sub-dialogs can be opened from the above dialogs. The sub-dialogs define the columns of the ListView and the actions allowed on the objects. It is now easier to explain to administrators how to deal with this tree view.

Third Pain Point - Live Monitor

While the Agents Schedule dialog is pretty good monitor, it is querying a single server, which the tool is connected to. Also, the dialog includes a lot of text and it is not made for "stay on the screen" monitoring. The new advanced tool allows better monitoring capabilities, by supplying new special monitoring form. It is querying all registered SO servers and displaying the servers availability. Most important is additional status line for the agents. When querying about agents, if the server is going down, it cycles to the next server.

Next Pain Point - Disabling Events

This feature is not yet complete, however, the UI for it is done.
Many times we wish we can turn off specific events when editing or creating objects. The new tool will allow just this. When using the generic object editing option, it includes Events tab, which allows to turn off or on events for a single update.

Next Action - Join Beta Testing

If you would like to test this tool, send me an email to mysnir.work[at]gmail.com and specify your details, so I can get in contact with you.

Thanks, Yoram ;-)

Wednesday, February 1, 2012

Better SQL Server database backup

Sometimes when I restore SQL Server database from a BAK file, I get huge log file or even fail to complete the task due to lack of disk space, but it could be solved if the backup of the database was generated with small log file.

So, before you backup SQL Server database, do the following: Detach from the database. This will allow you to handle database files without SQL Server locking the files.

Then you should delete the log file. Please note that it may be better to put the file in temporary location, just in case you have many files with similar names.

Now attach the main database file again.

Note that it includes a reference to the deleted log file.

Remove the 'Not Found' log file and complete the re-attachment. This will generate new, very small, log file. Now go ahead and backup the database. When you will have much better file to restore.

Friday, December 17, 2010

Enhancing ClickSchedule Silverlight Client

I installed Service Optimization 8.1.2 and spent long hours fighting with it, just to open the ClickSchedule Web client, or as I prefer to call it, ClickSchedule Silverlight client. To make it short, the web.config file in the ClickScheduleWebClient directory had a wrong configuration that prevented me from opening the client. Assume that you have a working ClickSchedule Silverlight client, here are two steps into customizing the Gantt in a very special way.

But before that, let me recommend the beta version of .NET Reflector, which integrates with Visual Studio 2010 and allow a very good debugging of the Silverlight client.

Step 1: Switch Gantt in the Settings

We will instruct the client to load the Gantt from a new assembly, which we will create in the next step, by editing the Body XML of the Administrative Settings of the client. Then we will verify that we have under the root configuration, views node with its name attribute. Under that, mainViews node and its name attribute. Under that, schedulingView node and its name attribute. We will override the default Gantt by adding type attribute with the following string: W6.Web.UI.Extra.W6SchedulingViewEx,W6.Web.UI.Extra, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

Step 2: Enhanced Gantt

Rename the file W6.Web.UI.xap to W6.Web.UI.zip and extract the files out. Keep them in a sub-folder to reference them later. In Visual Studio 2010, create new C# Silverlight Class Library project, name it W6.Web.UI.Extra and add reference to W6.Web.Controls.dll and W6.Web.UI.dll, rename the existing class to W6SchedulingViewEx, and paste the following code:

using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using W6.Web.UI.View;
using W6.Web.UI.GanttChart;

namespace W6.Web.UI.Extra
{
  public class W6SchedulingViewEx : W6SchedulingView
  {
    public override void Refresh()
    {
      base.Refresh();

      Rectangle r = new Rectangle();
      r.Fill = new SolidColorBrush(Colors.Green);
      r.VerticalAlignment =
        System.Windows.VerticalAlignment.Top;
      r.HorizontalAlignment =
        System.Windows.HorizontalAlignment.Left;
      r.Height = this.ResourceGantt.RowHeight;

      // from the begining of the loaded Gantt
      double minutesToStart = 720;
      // from the start of the rectangle
      double minutesToFinish = 60.0;
      // zero based index of the engineer
      double engineer = 4;

      r.Width = minutesToFinish
        * this.ResourceGantt.PixelPerMinute;
      r.Margin = new System.Windows.Thickness(
        minutesToStart
          * this.ResourceGantt.PixelPerMinute,
        engineer * this.ResourceGantt.RowHeight,
        -1.0, 0.0);

      ((Grid)((W6CalendarLayer)this.ResourceGantt
        .GanttChartLayers[0]
        ).Content).Children.Add(r);
    }
  }
}

Build the project and copy the DLL onto the W6.Web.UI.zip file. Edit the extracted file AppManifest.xaml and add new assembly part:

<AssemblyPart
  x:Name="W6.Web.UI.Extra"
  Source="W6.Web.UI.Extra.dll" />

Drag the AppManifest.xaml file onto the W6.Web.UI.zip file, Choose to replace the existing one, and rename the ZIP file back to W6.Web.UI.xap and open the client, using: http://localhost/ClickScheduleWebClient/default.aspx

In the client, select the Refresh button and a green rectangle should appear on the Gantt's lowest layer, the calendar layer. From here, you can enhance the Gantt with a lot of flexibility.

Wednesday, August 11, 2010

iPhone Client Update


ClickMobile client for the Windows platform is developed for long time already, and therefor includes many features. In this update we can see that the client's Calendar list is complete with support for coloring, icons, list of properties, etc.

When selecting task from the list, the client needs to follow the form configuration from the server. The editor is built for Windows platform, but in general we can look on it as list of Tabs that each is a list of Fields or Properties.


The iPhone client is showing the first Tab, while the other Tabs are listed as sections below.

Selecting the second Tab is natural for iPhone users, while following the separation made by the administrator, which configure the form.

Still there is more work, but it looks like it getting some shape.

Monday, July 12, 2010

Sending And Receiving SXP from iPhone

When developing client application you always need to learn the server API. In the case of ClickMobile, there is more than few Special SXP calls to learn.

The beauty of ClickMobile is in the details (as Prof. Ben-Bassat always said: the strength of Service Optimization is in the details, years of experience in this field made the solution of ClickSoftware so comprehensive).

The Windows CE mobile client is using SQL Server CE to synchronize local database with the server database (SQL Server CE? not with iPhone). But the way the client sends SXP calls and receives the response is another layer on top of that.

The server maintains two tables for requests and responses. The client pull and push records from and to these tables using synchronization of local replica. The server scans the requests table using background process (agent), which performs a scan every few seconds (configurable interval). For each processed request it's generates response record. But the server also generates response records as a result of Server Events (like Task Update, etc.).

So, to send and receive SXP, like ClickMobile, from platform that cannot use SQL Server CE, you need to: (A) Create replacement for SQL Server CE database synchronization. (B) Insert special ClickMobile SXP calls into special request records. (C) Synchronize the requests table. (D) Constantly synchronize the responses table. (E) Get the SXP results from the response records. (F) Clean used response records (or let the server do so after few days).

Important note regarding The requests and responses tables: each user should only use records that aimed to him. Synchronizing records of all clients is costly and unnecessary.

OK, so now I can tell you that I'm already passed this stage. Now let's connect the background service with the UI...

Saturday, June 5, 2010

What iPad Can Do For ClickSchedule?

While the iPad sales are going great guns with consumers, the usage of such delicate device in the field as enterprise client is questionable. The first thing I got on my mind was to play with the device and decide if it's good as ClickSchedule client (ClickMobile client). After seeing how fragile the device is, I'm not sure if it worth the effort developing for. Maybe a ClickAnalyze client is more appropriate for the iPad.

For sure the iPhone is still a great device for ClickMobile. We just need to wait a litle bit more (for Monday's keynote) and then see what news Apple going to bring to the enterprise.

Tuesday, May 11, 2010

iPad Wi-Fi+3G glass is cracking [u]

While learning more about my new iPad, I found a scratch on the glass after less than a week. I was not sure how, but I blamed myself for the first scratch. Today, I found another three scratches. I looked carefully and found that my screen is cracking. We'll see what Apple will do with it in couple days. In the attached picture, I marked the visible scratches with pairs of arrows. The flash shows the cracks that are not visible in room light (the screen is very clean, but the flash just pop any crack and dust).
Update: Apple was very kind to replace the iPad with a new one. It took me 10 minutes at the local Apple store and I'm now posting from a new iPad.

Saturday, April 24, 2010

ClickAnalyze Insight Agent for all Nightly Reports

You have just configured new ClickSchedule report using the Service Optimization Administration console. Now you need to configure an agent to run the report once a night.

I strongly suggest to use the ClickAnalyze Insight agent for any nightly report, with the cost of the new time table needed for the agent. You can create such table using the following SQL:
create table W6RP_MY_REPORT_TIME(PK_Date date not null,
Date_Name varchar2(50) null,
constraint PK_MY_REPORT_TIME primary key (PK_Date)
using index tablespace USERS) tablespace USERS;
Populate the table with single record for two days ago:
TimeCmd "Provider=OraOLEDB.Oracle;User Id=W6ADMIN;
Password=****;Data Source=CAR_ALIAS"
W6RP_MY_REPORT_TIME en-US -2 -2
Create foreign key relation between the tables:
alter table W6RP_MY_REPORT
add constraint FK_MY_REPORT1 foreign key (Time_Start)
references W6RP_MY_REPORT_TIME;
Now just set a new ClickAnalyze Insight agent setting to process the time table and the report:
Owner:        [Application]
Category:     Agent
Sub Category: Insight
Name:         My Report
Body:
<InsightAgent>
  <Connections>
    <Connection>
      <TargetConnection
        Key="-1">(local)</TargetConnection>
      <TimeTable>W6RP_MY_REPORT_TIME</TimeTable>
      <Culture>en-US</Culture>
      <RelativeTo>-1</RelativeTo>
    </Connection>
  </Connections>
  <Reports>
    <Report>
      <Name>My Report</Name>
    </Report>
  </Reports>
  <Notifications>
    <Notification Active="true">
      <Type>Email</Type>
      <From>click@acme.com</From>
      <To>
        <Recipient>dispatcher@acme.com</Recipient>
      </To>
      <Subject>My Report Execution Result</Subject>
      <Importance>2</Importance>
    </Notification>
  </Notifications>
</InsightAgent>
What you will get is the better error handling of the agent, which rollback partial processing. You can add multiple reports to run in sequence. Just remember, one error will rollback all the reports.

After error, you can try and fix the problem and rerun the agent. If the agent run successfully, then rerun is not going to do any processing, since the time table is already with the processing date.

Thursday, April 8, 2010

Mobile iPhone Client and Multitasking

As we all know, Apple previewed today some features of the next major upgrade for the iPhone OS. Especially important for me is the multitasking implementation (we all know it was just matter of developing the correct UI and waiting for 1GHz CPU, which probably be in the next generation iPhone hardware).

While still offering the push notifications option, it is much easier to implement a thread that polls the remote server. I will have to check carefully, what is allowed under the updated platform.

I feel that I started the development at the right time, when the OS is maturing. I will probably aim to the end of 2010, so I can benefit from the iPhone OS 4 improvements.

Wednesday, March 17, 2010

Short iPhone Client Update

I have a WebService working on the server side. I have a WebServiceClient working asynchronously on the iPhone. Still need to finish the SQLite code for the client side database. I have initial UI components. Also, adding some barcode reading code, just in case ;-)

Thursday, March 4, 2010

Sample Data

Any demo is better when showing "full and real" data. Means that, all engineers are scheduled in the past, the demo system is fully functional, and all clients are showing the most complete picture of the demoed company.

However, when the demo data needs to include ClickAnalyze data, including single district is not enough. You need at least 2 regions, each with 5 districts, and history for at least 3 years. For a recent demo, I made just that.

Now I need to find some time to: (A) Make the code more generic, so it can fit other demos. (B) Add the option to see trends over time, probably I need to create new engineers over time, to show growth. and (C) Story. It would be best if the demo will include points in time that can be shown with correlation to the story.

After seeing only few demos during my years in ClickSoftware, and after this recent demo, which I helped to prepare small part of it, I can definitely say that ClickAnalyze is lagging behind in the demo-sphere.

Sunday, November 22, 2009

SQL Server CE ? not with iPhone

The first hurdle with creating the iPhone client is to overcome the SQL Server CE synchronization of the current ClickMobile client. In this post, I describe in short the decision I took in the replacement of this technology.

The current ClickMobile solution is storing all the data and the communication into local SQL Server CE database. Then the client taking advantage of the built-in technology of SQL Server CE to synchronize the local instance with the centralized instance on the remote server.

SQL Server CE includes a special "Remote Data Access" object, that communicate with the central SQL Server over HTTP. This object exposes special PUSH and PULL methods for table synchronization. On the server, ClickMobile is an agent, which runs in the background and poll the SQL Server database. This agent is responsible for processing the "requests" records.

I want to have the iPhone client communicating using the same "channel". So I started by creating a WebService with PUSH and PULL methods. This WebService allows the client to perform the table synchronization without running SQL Server CE.

It is now the time to create the client side component. I think it should be a SQLite to SOAP and SOAP to SQLite gateway. The SOAP messages are proprietary and are not following any standard (except of being SOAP messages). Following this client side development, I may also develop compression to save on bandwidth.

Well, off to work now...

Friday, November 6, 2009

ClickMobile for the iPhone

I have decided to develop an engineer client application for the iPhone (similar to ClickMobile). I guess I will have this blog updated with my progress from time to time.

Here is a short status of what I did already:

1. It took me few days to have a running environment of Service Optimization on VirtualBox (including both server side of ClickMobile, as well as PC client of ClickMobile).

2. It took me another day to bridge the host OS and the guest OS securely, so the iPhone Simulator can talk to the WebService on the virtual machine.

3. Another day I spent on creating small iPhone app, that can send SOAP message to WebService in the ClickMobileSync directory, and parse the SOAP response.

Now, since there is no SQL Server Mobile for iPhone, I will need to go with custom solution (hope this wont be too long).

If you have any comments, requests, or priorities for such application, please leave a blog comment or call me. I would be more than happy to hear from you ;-)

Monday, September 28, 2009

Geographic Domain in Client Add-in

When writing add-in to the ClickSchedule client, I was trying to get the full navigation tree from ClickSchedule client. I have made this short code:
' Option 1 - using the client's loaded domain
Public Function DoAddIn( _
ByRef objCallingApp As Object, _
ByRef objCallingDoc As Object, _
ByRef lDocType As Integer, _
ByRef varSelectedEngineers As Object, _
ByRef varSelectedTasks As Object, _
ByRef varSelectedAssignments As Object) _
As Boolean

' Get the client domain navigation tree
Dim navObj As Object = _
CType(CType(objCallingApp, _
W6BFClient.W6BFClient).Domain, _
W6BFClient.Domain).NavigationTree
If Not IsArray(navObj) Then Return False
Dim navArr As System.Array = navObj

' Request full navigation tree
Dim request As XmlDocument = New XmlDocument
request.LoadXml( _
"<SXPServerGetTree Revision=""7.5.0"">" & _
"<NavigationTree/></SXPServerGetTree>")
Dim ids As XmlNode = _
request.DocumentElement.FirstChild

' Set the collection ids
Dim first As System.Array = navArr(0)
For index As Integer = _
first.GetUpperBound(0) To 2 Step -3

ids.AppendChild(request.CreateElement( _
"CollectionID")).InnerText = _
first(index).ToString()
Next

' Create connection object (this is add-in, _
' connection already open by the client)
Dim sxp As W6Logon.Connection = _
New W6Logon.Connection
Dim response As XmlDocument = sxp.Send(request)
End Function

The problem with this option is the requirement for the user to have one or more districts loaded in the client, prior to opening this add-in. So, here is the second option:
' Option 2 - not using the client's loaded domain
Public Function DoAddIn( _
ByRef objCallingApp As Object, _
ByRef objCallingDoc As Object, _
ByRef lDocType As Integer, _
ByRef varSelectedEngineers As Object, _
ByRef varSelectedTasks As Object, _
ByRef varSelectedAssignments As Object) _
As Boolean

' Get the client app manager
Dim clientAppManager As _
W6BFClient.IW6BFClientAppManager = _
CType(objCallingApp, _
W6BFClient.IW6BFClientAppManager)

' Request admin setting
Dim requestAdmin As XmlDocument = New XmlDocument
requestAdmin.LoadXml( _
"<SXPServerGetObjects Revision=""7.5.0"">" & _
"<ObjectType>UserSetting</ObjectType>" & _
"<Indexes><Distinct>0</Distinct>" & _
"<Index><LowBound><Property>" & _
"<Name>Category</Name>" & _
"<Value>Power Scheduler Client</Value>" & _
"</Property><Property>" & _
"<Name>SubCategory</Name>" & _
"<Value>Administrative Settings</Value>" & _
"</Property></LowBound><HighBound>" & _
"<Property><Name>Category</Name>" & _
"<Value>Power Scheduler Client</Value>" & _
"</Property><Property>" & _
"<Name>SubCategory</Name>" & _
"<Value>Administrative Settings</Value>" & _
"</Property></HighBound></Index></Indexes>" & _
"<RequestedProperties>" & _
"<Item>Key</Item><Item>Owner</Item>" & _
"</RequestedProperties>" & _
"</SXPServerGetObjects>")
Dim responseAdmin As XmlDocument = SendSxp( _
"SXPServerGetObjects Administrative" & _
" Settings", requestAdmin)

' Get the template key
Dim template As String = _
clientAppManager.AdminTemplateName.ToLower()
Dim key As Integer = -1
For Each child As XmlNode In _
responseAdmin.DocumentElement.FirstChild.ChildNodes

Dim owner As String = child.SelectSingleNode( _
"Owner").InnerText.ToLower()
If template.Equals(owner) Then
key = CInt(child.SelectSingleNode( _
"Key").InnerText)
Exit For
End If
Next
If (key = -1) Then Return False

' Request template setting
Dim requestTemplate As XmlDocument = _
New XmlDocument
requestTemplate.LoadXml( _
"<SXPServerGetObjects Revision=""7.5.0"">" & _
"<ObjectType>UserSetting</ObjectType>" & _
"<KeySet><Key>" & key.ToString() & _
"</Key></KeySet><RequestedProperties>" & _
"<Item>Key</Item><Item>Body</Item>" & _
"</RequestedProperties></SXPServerGetObjects>")
Dim responseTemplate As XmlDocument = SendSxp( _
"SXPServerGetObjects AdminTemplateName", _
requestTemplate)

' Get the task property ids for the navigation tree
Dim body As XmlDocument = New XmlDocument
body.LoadXml( _
responseTemplate.DocumentElement.FirstChild. _
FirstChild.SelectSingleNode( _
"Body").InnerText)
Dim navigationProperties As XmlNode = _
body.DocumentElement.SelectSingleNode( _
"SOFTWARE/IET/W-6BreakFix/Client/" & _
"Administration/Navigation")

' Request task scheme
Dim requestTaskScheme As XmlDocument = _
New XmlDocument
requestTaskScheme.LoadXml( _
"<SXPServerGetCollectionsScheme " & _
"Revision=""7.5.0"">" & _
"<Collections><Collection><ID>2</ID>" & _
"</Collection></Collections>" & _
"</SXPServerGetCollectionsScheme>")
Dim responseTaskScheme As XmlDocument = SendSxp( _
"SXPServerGetCollectionsScheme", _
requestTaskScheme)

' Request full navigation tree
Dim request As XmlDocument = New XmlDocument
request.LoadXml( _
"<SXPServerGetTree Revision=""7.5.0"">" & _
"<NavigationTree/></SXPServerGetTree>")
Dim ids As XmlNode = _
request.DocumentElement.FirstChild

' Set the collection ids
For index As Integer = _
1 To navigationProperties.ChildNodes.Count

Dim propertyID As String = _
navigationProperties.SelectSingleNode( _
"Level" & index.ToString() & _
"/FieldNumber").InnerText.Replace("""", "")
Dim collectionID As String = _
responseTaskScheme.DocumentElement. _
SelectSingleNode( _
"Collections/Collection/Attributes" & _
"/Attribute[ID='" & _
propertyID & _
"']/KeyTypeInfo/ObjectType").InnerText
ids.AppendChild(request.CreateElement( _
"CollectionID")).InnerText = collectionID
Next

' Create connection object (this is add-in, _
' connection already open by the client)
Dim sxp As W6Logon.Connection = _
New W6Logon.Connection
Dim response As XmlDocument = sxp.Send(request)
End Function

The second option is longer, but works without loaded districts.

Tuesday, August 4, 2009

Cannot show owner of parent of UserSetting object

This is a small limitation of ClickAnalyze infrastructure. While you can define a report on UserSetting collection, which includes both Owner property as well as ParentUserSetting.Owner, the result is that the Owner property of the object is logged twice and the parent owner is not logged at all.

Saturday, July 18, 2009

Custom Calculator can skip SetValue

One of the less familiar features of ClickAnalyze infrastructure is the handling of a permutation full of nulls.

To be more clear, let say that a report is made of Time and Geography dimensions, and then 2 custom calculators. Assume that for the permutation "July 19, 2009", "North-East", "Boston" both calculators get short list of assignments. Both calculator find that the total they need to calculate is 0 (zero). This can happen due to the fact that this is Sunday and the calculators are considering the engineers' calendars.

So, let say that both calculators will include code that skip the SetValue method, when the value is zero:
If Not (totalSeconds = 0) Then
pCalculatorsRowItem.SetValue(0, totalSeconds)
End If

The ClickAnalyze infrastructure identifies this as permutation with no data, means that all calculators skip the SetValue. By default, each report includes advanced property "Include Permutation With No Data" set to False. This means that our permutation will not be written to the database. Changing the property to True will cause the permutation to be written with nulls. This of-course might result with many more records full of redundant data.

Friday, July 17, 2009

Table with NoRows

While trying to understand why a table or matrix is not rendered in some reports I recently made (under Reporting Services 2005), I found that actually there was no data available for the table.

The simple solution for this problem was to set the NoRows property of the table or the matrix.

Why the default value of this property is empty string? I don't know! but it would be much easier if it wasn't.

Saturday, June 20, 2009

Should I use the Resource Type measure

(Q) Why do I get records full of NULLs when I'm using the Resource Type measure?

(A) This question is about ClickAnalyze Reporting for ClickSchedule. More specifically it is raised in regards to the Resource Schedule report.

By now, you probably noticed that engineers with assignments have one record per assignment, but engineers with no assignments have one record full of NULL values. The NULL values are at the columns, which hold the assignment and task details.

Why there is no such record for engineer with assignments? Why engineer with no assignments, don't have zero records? Meaning that this NULLs record should not be written at all!

Well, the answer is in the question: the Resource Type measure.

When the reporting infrastructure initialize the calculators (measures), each calculator declares what type of objects it needs. In the first screen-shot we can see that Resource Type asks for Engineer objects (see the Conditions and Data Filter properties).

The "Task" measure is a Get Schedule measure type. It's also requires Engineer objects, but it returns matrix of values.

Here is the place to explain what is this "matrix of values": Each calculator defines list of columns that it can populate. The Get Schedule calculator defines this list from the parameters entered by the user (Task Properties and Assignment Properties). Assuming the list is made of 5 task properties and 3 assignment properties, then the calculator defines 8 sub-columns. Each time the infrastructure is calling the calculator with Engineer objects, it prepares array with 8 NULL values, and the calculator can write values into those places. But here comes the special part, the Get Schedule calculator fills the 8 values from the first task-assignment pair, and then calls the infrastructure to AddRow. The infrastructure duplicate all values of the preceding dimensions and measures and prepare new array of NULL values, so the calculator can now start writing the second row of the matrix, and so on.

When the Get Schedule calculator have no assignments to process, it leaves the array full of NULL values and exit. If the infrastructure finds that all measures are returning only NULL values, then the record is not written to the database.

BUT, in our case, the Resource Type measure always write a string value, so we get this record full of NULL values (the NULL values, which the Get Schedule measure did not fill).

We should note that by design, the special "matrix measures" should be the only measure in the report. It is by coincidence that the infrastructure supports one "matrix measure" as the last measure, even when it is preceding with other simple measures.

I would expect this Resource Type calculator to be removed. The same can be achieved by adding the properties to the "Resource" dimension. In this way, records full of NULL values, will not be written to the database.

Tuesday, June 16, 2009

Product vs Core. Why use low level API ?

Sometimes I wish that product API would not raise errors, but just return numeric result with the error number. This is what happening in the core API.

For example, the W6PTimeIntervals is a simple product wrapper for the W6TimeIntervals core class. Interesting is the fact that W6TimeInterval is a core class, which is used in the product without a wrapper.

However, the following short example of code is an implementation of a method, which is sometimes needed when dealing with time intervals. The error handling is general and there is no need to deal with "end of list" error:
Private Sub UnSetTimeIntervals( _
ByVal intervals As W6PTimeIntervals, _
ByVal unset As W6PTimeIntervals)

Try
Dim W6RC_MDL_TIME_INTERVALS_END_OF_LIST _
As Integer = 4120

Dim rc As Integer = 0

Dim timeInterval As W6TimeInterval
= New W6TimeInterval

' UnSet older intervals from the newer intervals,
' so only the new interval remains
rc = unset.RefW6TimeIntervals.GetFirst( _
timeInterval)

Do While (CatchRcExclude(rc, _
W6RC_MDL_TIME_INTERVALS_END_OF_LIST))

CatchRC( _
intervals.RefW6TimeIntervals.UnSetTimeInterval _
(timeInterval))

rc = unset.RefW6TimeIntervals.GetNext( _
timeInterval)

Loop

Catch ex As Exception
Call GeneralErrorHandling("UnSetTimeIntervals")
End Try
End Sub

Private Function CatchRcExclude( _
ByVal rc As Integer, _
ByVal exclude As Integer) As Boolean

If (rc = exclude) Then Return False
CatchRC(rc)

Return True
End Function

Private Sub CatchRC(ByVal rc As Integer)

If (rc = 0) Then Exit Sub

Dim errObject As W6ShPError = _
W6ShPErrorUtilities.W6CreateCoreError( _
rc, "", True, True)
End Sub

Tuesday, June 9, 2009

Add-in for custom report

When I was writing a custom ClickAnalyze report, I did not expect that the ClickSchedule client's wizard, which opens the report, will cause any troubles. But it was no ordinary report, and as such it did not include geography dimension (no region and no district). The wizard did not handle this well and actually I had to develop a simple add-in.

In order to create the add-in, I just needed to send SXP, Create the out-of-the-box form with the report viewer, and show it (well, it might be a bit more). And here is the code:
' This class should be visible to COM
Public Class W6CustomReportAddin

Public Function DoAddIn( _
ByRef objCallingApp As Object, _
ByRef objCallingDoc As Object, _
ByRef lDocType As Integer, _
ByRef varSelectedEngineers As Object, _
ByRef varSelectedTasks As Object, _
ByRef varSelectedAssignments As Object) _
As Boolean
Try
' Send SXP request and get the response
Dim request As Xml.XmlDocument = _
New Xml.XmlDocument

request.LoadXml( _
"<SXPServerReportProcess><Report>" & _
"<Name>Custom Report</Name>" & _
"</Report></SXPServerReportProcess>")

Dim conn As W6Logon.Connection = _
New W6Logon.Connection

Dim response As Xml.XmlDocument = _
conn.Send(request)

' Create the report viewer dialog and set
' the report properties
Dim dialog As W6ReportsClient.frmMainForm = _
New W6ReportsClient.frmMainForm( _
W6ReportsClient.ProductType.ClickSchedule)

Dim dataManager As _
W6ReportsClient.CW6DataManager = _
W6ReportsClient.CW6DataManager.GetInstance()

dialog.ReportsServerURL = _
dataManager.ReportServerURL

dialog.ReportPath = "/" & _
dataManager.RootFolder & "/" & _
dataManager.ClickScheduleFolderName & _
"/Day/Custom Report"

' Create client domain and set the instance id
Dim domain As _
W6ReportsClient.CW6ClientDomain = _
New W6ReportsClient.CW6ClientDomain( _
W6ReportsClient.ProductType.ClickSchedule)

domain.InstanceID = _
response.DocumentElement.SelectSingleNode( _
"InstanceID").InnerText

' Set the title and build the report
dialog.AddReportNameToTitle("Custom Report")
dialog.BuildReport(domain)

' Show the dialog as modal form
dialog.ShowDialog()

Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Error")
End Try
End Function

End Class
 
HTML Hit Counter