Here is a trivial solution to implement Personalized Scripts for Lawson Smart Office that self-configure based on the program they are being executed in.
Problem
We often implement scripts which functionality can be applied to different M3 programs. For example, a script that makes a phone call based on the phone number displayed on the screen could be applied to any M3 program that has a phone number (Customers, Suppliers, etc.). As another example, a script that shows an address on Google Maps could be applied to any M3 program that has an address (CRS610/E, CRS622/E, etc.).
We could make one copy of the script for each target M3 program, but that would be a maintenance nightmare.
We could make the script re-usable and pass settings to the script, but that would require the installer to manually define the settings, which is time consuming and error prone.
As a general problem, I want to make a script re-usable and with zero configuration so it can be used anywhere in M3 where its functionality is needed.
Solution
The trivial solution is to pre-compute all the possible settings in advance, and apply the corresponding settings at runtime. We dynamically determine in which program we are currently executing the script by reading the HostTitle variable.
I call it a self-configuration script.
Pseudo-code:
HostTitle = controller.RenderEngine.Host.HostTitle if (HostTitle = X) then { SettingsX } if (HostTitle = Y) then { SettingsY } if (HostTitle = Z) then { SettingsZ }
Advantages
The advantage is reduced installation. In some cases we could completely eliminate configuration.
It’s also time saving, and error proof.
And it’s closer to plug’n play and Autonomic Computing.
Example
I had implemented a script that performs address validation.
The script checks the address that is entered by the user with a third-party software that validates if the address is correct or not.
The script needs to get a reference to the address fields: Address line 1 (CUA1), Address line 2 (CUA2), City (TOWN), State (ECAR), etc. In CRS610/E those fields will be WRCUA1, WRCUA2, WRTOWN, and WRECAR. Whereas in CRS622/E those fields will be WWADR1, WWADR2, WWTOWN, and WWECAR.
The fields are different in each M3 program. So I pre-computed the field names of the eight M3 programs and panels where I would be executing the script (CRS610/E, CRS235/E1, CRS300/E, CRS622/E, MNS100/E, OIS002/E, OPS500/I, and SOS005/E), and I hard-coded all the possible values in the script.
Sample source code
Here is part of the source code of my self-configuration script for address validation:
var HostTitle = controller.RenderEngine.Host.HostTitle; var settings = {}; if (HostTitle.IndexOf('CRS610/E') > 0) { // Customer. Open - CRS610/E settings = { FirmName: 'WRCUNM', AddressLine1: 'WRCUA1', AddressLine2: 'WRCUA2', AddressLine3: 'WRCUA3', AddressLine4: 'WRCUA4', City: 'WRTOWN', State: 'WRECAR', PostalCode: 'WRPONO', Country: 'WRCSCD', Latitude: '', Longitude: '' }; } else if (HostTitle.IndexOf('CRS622/E') > 0) { // Supplier. Connect Address - CRS622/E settings = { FirmName: 'WWSUNM', AddressLine1: 'WWADR1', AddressLine2: 'WWADR2', AddressLine3: 'WWADR3', AddressLine4: 'WWADR4', City: 'WWTOWN', State: 'WWECAR', PostalCode: 'WWPONO', Country: 'WWCSCD', Latitude: 'WEGEOY', Longitude: 'WEGEOX' }; } else if (HostTitle.IndexOf('OIS002/E') > 0) { // Customer. Connect Addresses - OIS002/E settings = { FirmName: 'WRCUNM', AddressLine1: 'WRCUA1', AddressLine2: 'WRCUA2', AddressLine3: 'WRCUA3', AddressLine4: 'WRCUA4', City: 'WRTOWN', State: 'WRECAR', PostalCode: 'WRPONO', Country: 'WRCSCD', Latitude: '', Longitude: '' }; } else if (HostTitle.IndexOf('CRS235/E1') > 0) { // Internal Address. Open - CRS235/E1 settings = { FirmName: 'WWCONM', AddressLine1: 'WWADR1', AddressLine2: 'WWADR2', AddressLine3: 'WWADR3', AddressLine4: 'WWADR4', City: 'WWTOWN', State: 'WWECAR', PostalCode: 'WWPONO', Country: 'WWCSCD', Latitude: 'WEGEOY', Longitude: 'WEGEOX' }; } else if (HostTitle.IndexOf('MNS100/E') > 0) { // Company. Connect Division - MNS100/E settings = { FirmName: 'WWCONM', AddressLine1: 'WWCOA1', AddressLine2: 'WWCOA2', AddressLine3: 'WWCOA3', AddressLine4: 'WWCOA4', City: 'WWTOWN', State: 'WWECAR', PostalCode: 'WWPONO', Country: 'WWCSCD', Latitude: '', Longitude: '' }; } else if (HostTitle.IndexOf('CRS300/E') > 0) { // Ship-Via Address. Open - CRS300/E settings = { FirmName: 'WWCONM', AddressLine1: 'WWADR1', AddressLine2: 'WWADR2', AddressLine3: 'WWADR3', AddressLine4: 'WWADR4', City: 'WWTOWN', State: 'WWECAR', PostalCode: 'WWPONO', Country: 'WWCSCD', Latitude: '', Longitude: '' }; } else if (HostTitle.IndexOf('SOS005/E') > 0) { // Service Order. Connect Delivery Address - SOS005/E settings = { FirmName: 'WPCONM', AddressLine1: 'WPADR1', AddressLine2: 'WPADR2', AddressLine3: 'WPADR3', AddressLine4: 'WPADR4', City: 'WPTOWN', State: 'WPECAR', PostalCode: 'WPPONO', Country: 'WPCSCD', Latitude: '', Longitude: '' }; } else if (HostTitle.IndexOf('OPS500/I') > 0) { // Shop. Open - OPS500/I settings = { FirmName: 'LBL_L21T2', AddressLine1: 'WICUA1', AddressLine2: 'WICUA2', AddressLine3: '', AddressLine4: '', City: 'WICUA3', State: '', PostalCode: '', Country: 'WICUA4', Latitude: '', Longitude: '' }; } else { // M3 panel not supported }
This has been tested in Lawson Smart Client (LSC), and in Lawson Smart Office (LSO).
Additionally, you can discriminate LSC vs. LSO with:
if (Application.Current.MainWindow.Title == 'Lawson Smart Client') { // running in LSC (not LSO) }
That’s it!
UPDATE
UPDATE 2012-07-24: We can also use controller.RenderEngine.PanelHeader to get just the program and panel (for example: CRS610/B1) instead of the entire host title; the result is a shorter syntax:
var PanelHeader = controller.RenderEngine.PanelHeader; if (PanelHeader == 'CRS610/E') { // CRS610/E } else if (PanelHeader == 'CRS622/E') { // CRS622/E } else if (PanelHeader == 'OIS002/E') { // OIS002/E } else if (PanelHeader == 'CRS235/E1') { // CRS235/E1 } else { // not supported }