Thursday, March 30, 2017

Mint chocolate

Considering my enthusiasm for mint chocolate, I'm slightly surprised at myself for not recording the fact that I've found a type of chocolate which is 90% of what I want. It's not as good as the unobtainable Italian chocolate, but it is accessible and certainly tasty (I would like a little more mint)! As opposed to one type which I tried, which had 75% cocoa, this has 60%, which is just right.

I buy it from IHerb, where it costs about $3 per bar; I order four or five bars a month to save on shipping. I find that I can go a week without any chocolate then finish a bar in a day.

There are several months in the year when the chocolate is not shipped, in order to preserve its quality. My intention is to stockpile a certain amount so that I won't have to undergo withdrawal during the summer.

Wednesday, March 29, 2017

The label number bug

Priority, in common with old fashioned versions of BASIC or even Pascal, has labels which are numbered. A label is the target of a GOTO or LOOP command, and unfortunately is the only loop control structure available to the Priority programmer. One feature which distinguishes Priority labels from BASIC labels is that in BASIC, each label has to be unique, whereas in Priority, one can use the same label several times in the same procedure/trigger. This normally helps, as I can copy entire loops out of one procedure then paste them into another without causing a syntax error. Unfortunately, of course, there is a downside to this.

Consider a post-update trigger which I wrote some time ago and started misbehaving a few days ago. It used to start like this:
GOTO 99 WHERE :$.BRANCHNAME <> '400'; #INCLUDE ORDERS/YYYY_BUF1 GOTO 1 WHERE :$.ORDSTATUSDES = :$1.ORDSTATUSDES; /* do something */ LABEL 1; GOTO 99 WHERE (:$.BRANCHNAME <> '400') OR (:$.MODELNAME IN ('CAD', 'F2D')); ... LABEL 99;
I was looking at this trigger the other day when it occurred to me that there was no point in checking the value of BRANCHNAME twice: if it's not 400, then execution should go to label 99, which is at the end of the trigger. So I deleted the second comparison of BRANCHNAME which occurs just after label 1. Today, a part of the trigger executed, despite the fact that BRANCHNAME <> 400. What happened?

It took me a while to figure it out: I had been bitten by the 'label number' bug. The second line in the snippet above includes a second trigger, and when I looked at that trigger, I saw that the final line in it was LABEL 99! In other words, the effective code was this
GOTO 99 WHERE :$.BRANCHNAME <> '400'; /* INCLUDE ORDERS/YYYY_BUF1 */ GOTO 99 WHERE :$.BRANCHNAME <> '400'; :YYYY_TOTO = 0; /* do something */ LABEL 99; /* end of ORDERS/YYYY_BUF1, back to the original trigger */ GOTO 1 WHERE :$.ORDSTATUSDES = :$1.ORDSTATUSDES; /* do something */ LABEL 1; GOTO 99 WHERE :$.MODELNAME IN ('CAD', 'F2D'); ... LABEL 99;
What happened was that the first line of the second trigger once again checked the value of BRANCHNAME, and because it was not 400, execution jumped to LABEL 99 which is at the end of the included trigger. But in the context of the first trigger, LABEL 99 was not at the very end of the trigger, but rather in the middle, so when the comparison :$.MODELNAME IN ('CAD', 'F2D') was executed (and failed), part of the trigger executed, even though it was not supposed to.

Moral of the story: each trigger should use its own labels, especially for 'procedure end'. I have changed the labels inside the included trigger to be 888 instead of 99. This really is only a problem when the trigger is a 'buffer' - common code which is called by other triggers - but one can never be sure. The entire problem would not have arisen had the final line of the above trigger been the inclusion of YYYY_BUF1; true, there would have been an unnecessary extra comparison of BRANCHNAME, but that's better than having code mis-execute.

Tuesday, March 28, 2017

Priority tip: creating business rules with functions

Priority comes equipped with something called a 'business rule generator'; this allows a user to define actions to be taken dependent on certain conditions, without having to program a trigger. For example, in the 'Customer Shipments' screen, I defined a rule
If 'Billable?' is equal to N 
and 'To ConsignmtWarehs' is blank
then Display error message
"Not able to close shipment form when 'billable' is not set"

(this is a rough translation of the Hebrew text). One is able to set up to three different conditions (in the rule above, the first condition is that field 'Billable?' is equal to N), which is sufficient for most cases. Unfortunately, every now and then, one would like to write a rule which is dependent on four conditions, or one condition is complex (e.g. display an error message when the agent number is not '031' or '046', where the numbers are not contiguous).

I'm not sure that I have a solution yet for four conditions, but I have discovered (by means of the Israeli Priority Users Forum) a technique for complex conditions. Existing functionality enables one to define an expression to be used in a condition, but as usual, this functionality is only partly documented.


One presses the button marked in yellow to display an 'enter expression form'.


Pressing any of the buttons on this form brings up data connected with dates - for example, the documentation shows how to use an expression to display an error message when the supply date of an order is less than five days from today.

In order to display an error when the consignment warehouse is not one of the values '23' or '999', one has to do the following: the rule has to read 'Display an error message when the value of consignment warehouse differs from', with the following expression

(:$.TOWARHSNAME IN ('23', '999') ? :$.TOWARHSNAME : '!!!')
Translated into English, this means: if the value of 'consignment warehouse' is either '23' or '999' then return the value of 'consignment warehouse', else return the value '!!!'. If the value of the warehouse were '12', then this expression would return '!!!' which is different from the value of the warehouse ('12') and so an error message would be displayed. This is an example of the convoluted logic with which us Priority developers have to struggle every day. Most importantly, the 'screen name' of the variable (:$.TOWARHSNAME) must be used and not its title ('Consignment warehouse').

Having documented this, I now need to find a real life example. There are certain advantages to using this technique over using a trigger, as well as some disadvantages. These are listed below in the order of thinking of them.

Advantages:
  1. Theoretically, 'anyone' can do this, not only developers, although I'd like to see them try!
  2. No need to 'build the form'
  3. The rule can be defined for specific users in specific companies 
Disadvantages:
  1. No ability to add comments
  2. Difficult to see the rule (a trigger can be viewed in a code editor)
  3. Not easily copied
[SO: 4442; 5,21,43
MPP: 802; 1,4,6
ELL: 926; 0,2,7]

Monday, March 27, 2017

Thesis update

I see that it has been three weeks since I last wrote about my new thesis. Whilst there has been communication with the university, I have yet to hear anything definite about the research's future. It would seem that the university is not a flexible SME (small/medium enterprise)! In the mean time, I have been working on the thesis, applying what I learnt from the first version.

In the past three weeks, I have expanded the introduction, writing mainly about the strategic value of information systems. I also included a paragraph about SAP, which claims to be the best selling program in the ERP market whilst being complex and suitable only for large organisations; I thought this necessary as much of the literature refers to SAP implementations.

The literature survey has been greatly expanded, beginning with a section on SME flexibility (hence the joke in the opening paragraph). Following this is a brief section on 'Not Invented Here' syndrome, which I think is relevant; as most of the current literature on this subject is about something called 'open innovation', I only cited a few papers without giving any details. Then come expanded sections on misfits and enhancements, followed finally by the literature synthesis. 

The third chapter, methodology, is the one that gave me the most problems in its previous incarnation, and it still is problematic for me. As the methodology which I am going to use is the opposite of what was before, most of the prior material was useless, although I was able to use a certain amount by converting it to the new methodology. Whilst looking for literature about case studies, I came across a recent DBA thesis (not from my university) about the success of CRM (Customer Relationship Management) programs; Priority has an underdeveloped CRM module which I have expanded somewhat by means of enhancements, but it isn't used very much. This other thesis should theoretically be very useful, but I found it jargon-loaded and very hard to read. Its major contribution to me was that it mentioned using Grounded Theory as its basis.

There were a few paragraphs about Grounded Theory in one of the DBA preparatory courses (I haven't been able to find them again) which I didn't particularly understand when I first read it. This time, I devoted some time to the subject, looking for suitable references and papers. I found a very good paper from 2013 which explains not only what GT is, but how it is applied, what criteria must be met, etc. Quoting this material certainly fills out the section about GT; I can then refer to the criteria when discussing my case study-based methodology.

At the moment, I think that I have reached the objectives which I set myself a few weeks ago: the introduction includes a great deal of material, the literature survey covers (to a certain extent) the four topics that I consider relevant, and the methodology chapter is covers what it should. I probably should add some material which shows how my methodology meets the criteria of GT - or not; I don't think that it is 'GT complete', but this is not necessarily required.

The thesis ends at the moment with a restating of the questions which the research intends to address; I don't know at the moment how to continue from here but expect to hear from my advisers what to write.

So now, I'm going to cease work for the time being in anticipation of a favourable message from the university.

Sunday, March 12, 2017

How to exclude rows from summation

In Priority, it is easy to mark a report column containing numerical data so that its total appears at the bottom of the report (it's also possible to mark a column so that sub-totals appear). This is normally the required behaviour, but every now and then there are problems with this mechanism. I have been working on a technique which allows users to assign tasks to documents, although this name is not always apt. Two similar examples are 'samples' - goods have been sent to a customer for evaluation and we want to record communications with the customer about the return of the goods, and 'outstanding debts' - we want to record communications with the customer about the payment of the debt. It is quite conceivable that an invoice might have more than one task connected to it (e.g. on 01/03/17, we spoke to the customer; on 02/03/17, we sent a copy of the invoice, etc). In an unaware implementation, having two tasks per document (open invoice) will cause two lines to appear in the report, and the debt will be summed twice. Not good.

The technique which I have developed is to have a separate procedural stage before the report in which the tasks are stored along with the invoice. This is necessary as I have not found a way of displaying in the same report debts with tasks and those without (there is a problem with what is known as 'left joins' which I haven't been able to resolve). The technique to prevent repeated summing is to store not only the primary key to each task, but also store the ordinal number of the task (i.e. this is the first task, this is the second task, etc). In the report, the value of the unpaid invoice is displayed only if this ordinal number is less than 2. This way, each invoice is summed only once, regardless of how many tasks are connected to it.

In the procedural stage, the pre-defined variable SQL.LINE will give the ordinal number of each task.

Monday, March 06, 2017

Priority technique for 'choose screens'

It sometimes happens that I need to create a form from which users can choose values intended for a procedure. For example, I developed a program which allows a manager to choose lines from an existing customer order, have those lines inserted into a new order which the program creates, and have the original lines zeroed out.

Why would I need to develop such a form when from the "input parameters" dialog of a procedure, one can press F6 twice and open the base form of the parameter (e.g. the customers form, the parts form)? The reason is that pressing F6 twice can only open what the documentation calls "a root form (having no upper-level form of its own)". In the above example, data is required from the 'orderitems' table, whose form is not a root form (its upper level form is, of course, the 'orders' form).

Normally, the way I have solved this in the past is to define a specific table for this task and then develop a form based on that table. Today I discovered an easier way of solving this problem.

One still has to write a procedure which at the least will consist of two stages, a form and procedural code, but there is no need to define a specific table upon which the form will be based. Let's say that I want to re-implement the example which I gave at the beginning. I can define a form which is based on the 'orderitems' table, showing the fields which I want, along with the parent order number (which will appear on every line). The trick is that the procedure passes to the form a file parameter, into which will be stored the lines that are displayed on the form. This file parameter is then passed to the procedural code which acts on the lines in the file (table) - that are the lines which were displayed on the form!

For my own reference, the original example where I found this technique is a procedure called TEC_CALCINVLEVEL, which unfortunately for my readers is not part of standard Priority, but rather was developed in the early days of my company using Priority - before I arrived on the scene. Whoever it was didn't bother in signing their work, let alone documenting it.

I doubt that I'm going to rewrite the various programs of this type which I've already written, but I'll try and bear this technique in mind in the future.

Sunday, March 05, 2017

New thesis is up and running

After my series of blogs last week about what I intended to research, I wrote - mainly for my own benefit - an abstract for my new thesis. Once this was done, I started work writing the new thesis. About 50% of the first chapter is recycled from my original thesis - a brief history of ERP, the ERP life cycle and Priority. Some of the material which originally appeared in the 'misfits' section of the introduction has been moved to chapter 2, the literature survey, as this is now the more suitable location. I added two pages describing my taxonomy of enhancements, giving a lengthy example in each case. To close the chapter, I added a section entitled 'Organisational impact of enhancements', which states the economic reasons for enhancements.

When I finished this (last Thursday), I sent a copy to my supervisor, without knowing what might be decided about my future as a doctoral candidate. I thought it best to show some completed work, so that any discussions which might take place in the university would have a background. On Friday afternoon I received a reply, thanking me for my material and informing me that another lecturer, who is apparently an expert in both organisational behaviour (he came to lecture us in Israel several years ago when I was taking the OB course) and case study-based research, has been appointed as my co-supervisor. But he's gone on holiday for a week!

Whilst this is encouraging, it doesn't actually tell me where I stand with regard to obligations. Do I have to write a research proposal and have it accepted by the research committee? Can I skip the proposal and create an intermediate submission (everything bar the research itself) for approval? Can I skip the intermediate submission and start work on the complete thesis? No doubt I will get some form of answer at the end of this week.

In the mean time, I have been working on the literature survey for the thesis. It turns out that my original sources aren't particularly suitable for my new direction, so I've been looking for more material. I have found a few papers, but most of these are about the implementation phase, based on SAP and are concerned with defining misfits. I am researching the post-implementation phase in Priority installations, examining the benefits of enhancements, so there is a definite research gap.

The literature survey will definitely be shorter than its predecessor; I think that I will be lucky if I manage to find 20 papers which are suitable. This is not necessarily a bad thing. As a joke, I included a short paragraph surveying the paper which I presented in Florence two years ago; there is some relevance. It will be interesting to see whether anyone remarks upon it.

It occurred to me this morning that I could post a request on the Priority Users Forum, asking people to send me examples of enhancements, listing what the misfit was, how it was overcome (I need a better word for this) and what the benefits accrued from doing so. Unfortunately, as fate would have it, the forum's web site is down today and it is not clear when it will be available again.

The title is now Researching the benefits of enhancing ERP programs in the post-implementation phase; this almost certainly will be the final title.