Presentation is loading. Please wait.

Presentation is loading. Please wait.

ABL to C# BPM Conversion

Similar presentations


Presentation on theme: "ABL to C# BPM Conversion"— Presentation transcript:

1 ABL to C# BPM Conversion
Ahmed Hamidi Lead Software Architect

2 Topics 3 ABL to C# conversion exercises Common Errors
Common Progress Commands Questions

3 Exercise 1 – Default Field
This example will default today’s date in Sale Order Entry, after Get New is called. - post processing method directive on Sales Order – GetNew. ABL Code: FOR FIRST ttOrderHed WHERE ttOrderHed.RowMod <> “” NO-LOCK.   ASSIGN ttOrderHed.OrderDate = TODAY.   END. C# Code: foreach(var ttOrderHed_iterator in(from ttOrderHed_Row in ttOrderHed where ttOrderHed_Row.RowMod != “” select ttOrderHed_Row)) { var ttOrderHedRow = ttOrderHed_iterator; ttOrderHedRow.OrderDate = DateTime.Now; }

4 Exercise 1 – Translation
ABL Code: FOR FIRST ttOrderHed WHERE ttOrderHed.RowMod <> “” NO-LOCK.   ASSIGN ttOrderHed.OrderDate = TODAY.   END. C# Code: foreach(var ttOrderHed_iterator in(from ttOrderHed_Row in ttOrderHed where ttOrderHed_Row.RowMod != “” select ttOrderHed_Row)) { var ttOrderHedRow = ttOrderHed_iterator; ttOrderHedRow.OrderDate = DateTime.Now; }

5 Exercise 1 – ERROR Converted C# syntax:
foreach(var ttOrderHed_iterator in(from ttOrderHed_Row in ttOrderHed where ttOrderHed_Row.RowMod != “” select ttOrderHed_Row)) Proper C# syntax: foreach(var ttOrderHed_iterator in(from ttOrderHed_Row in ttOrderHed where String.Equals( ttOrderHed_Row.RowMod, “”)

6 Exercise 2 – Cross reference validation
This example will validate the State entered in the Customer Maintenance screen, which is free form, against a UD table. PreProcessing directive on Customer Update method ABL Code: FOR FIRST ttCustomer WHERE ttCustomer.RowMod = “A” NO-LOCK.           IF CAN-FIND(UD40 WHERE UD40.Company = CUR-COMP AND UD40.Key1 = ttCustomer.State AND UD40.Key2 = ‘’ AND UD40.Key3 = ‘’ AND UD40.Key4 = ‘’ AND UD40.Key5 = ‘’) = FALSE THEN DO:                                        {lib/PublishEx.i &ExMsg    = "'Invalid State'"}                                        {&THROW_PUBLIC}.   END.   END . C# Code: object THROW_PUBLIC = null; Ice.Tables.UD40 UD40; foreach(var ttCustomer_iterator in(from ttCustomer_Row in ttCustomer where ttCustomer_Row.RowMod == “A” select ttCustomer_Row)) { var ttCustomerRow = ttCustomer_iterator; if(((from UD40_Row in Db.UD40 where UD40_Row.Company == Session.CompanyID && UD40_Row.Key1 == ttCustomerRow.State && UD40_Row.Key2 == ‘’ && UD40_Row.Key3 == ‘’ && UD40_Row.Key4 == ‘’ && UD40_Row.Key5 == ‘’ select UD40_Row).Count() != 0) == false) CallContext.Current.ExceptionManager.AddBLException("Invalid State"); THROW_PUBLIC = null; }

7 Exercise 2 – Translation
ABL Code: FOR FIRST ttCustomer WHERE ttCustomer.RowMod = “A” NO-LOCK.           IF CAN-FIND(UD40 WHERE UD40.Company = CUR-COMP AND UD40.Key1 = ttCustomer.State AND UD40.Key2 = ‘’ AND UD40.Key3 = ‘’ AND UD40.Key4 = ‘’ AND UD40.Key5 = ‘’) = FALSE THEN DO:                                        {lib/PublishEx.i &ExMsg    = "'Invalid State'"}                                        {&THROW_PUBLIC}.   END.   END . C# Code: object THROW_PUBLIC = null; Ice.Tables.UD40 UD40; foreach(var ttCustomer_iterator in(from ttCustomer_Row in ttCustomer where ttCustomer_Row.RowMod == “A” select ttCustomer_Row)) { var ttCustomerRow = ttCustomer_iterator; if(((from UD40_Row in Db.UD40 where UD40_Row.Company == Session.CompanyID && UD40_Row.Key1 == ttCustomerRow.State && UD40_Row.Key2 == ‘’ && UD40_Row.Key3 == ‘’ && UD40_Row.Key4 == ‘’ && UD40_Row.Key5 == ‘’ select UD40_Row).Count() != 0) == false) CallContext.Current.ExceptionManager.AddBLException("Invalid State"); THROW_PUBLIC = null; }

8 Exercise 3 – Run Persistent
This example will use a business object to create a new row in UD01 when an ABCCode entry is updated. Action File to BPM Custom Code. PreProcessing directive on ABCCode Update method C#: /* TO DO: replace DataSet variables with typed datasets. Add contract reference if necessary. */ var UD01DataSet = new System.Data.DataSet(); var ttAbccode_xRow = (from ttAbccode_Row in ttAbccode select ttAbccode_Row).FirstOrDefault(); hUD01 = Ice.Assemblies.ServiceRenderer.GetService<Ice.Contracts.UD01SvcContract>(Db); if (hUD01 != null) { hUD01.GETANEWUD01(UD01DataSet); var ttUD01_xRow = (from ttUD01_Row in ttUD01 where string.Equals(ttUD01_Row.RowMod, IceRow.ROWSTATE_ADDED, StringComparison.OrdinalIgnoreCase) select ttUD01_Row).FirstOrDefault(); if (ttUD01_xRow != null) ttUD01_xRow.Company = Session.CompanyID; ttUD01_xRow.Key1 = "AbcCode"; /*Table that was affected*/ ttUD01_xRow.Key2 = "CountFreq"; /*Field that was affected*/ ttUD01_xRow.Key3 = System.Convert.TimeToString(DateTime.Now, "HH:MM:SS"); /*Time*/ ttUD01_xRow.Key4 = ttUD01_xRow.SysRowID; /*To make the records unique*/ ttUD01_xRow["Date01"] = DateTime.Now; /*Date*/ ttUD01_xRow["Number01"] = ttAbccode_xRow.CountFreq; /*New Value*/ ttUD01_xRow["ShortChar01"] = Session.UserID; /*User id*/ /*Commit record*/ hUD01.UPDATE(UD01DataSet); }/*IF available ttUD01*/ /*Clean up*/ hUD01.Dispose(); } ABL: {Bpm/Bpm.i &OBJECT_NAME=AbcCode} {bo/UD01/UD01_ds.i} procedure UpdateBefore: define input-output parameter table for ttAbcCode. {&TRY_PRIVATE} define variable hUD01 as handle. find first ttAbccode no-lock no-error. RUN bo\UD01\UD01.p PERSISTENT SET hUD01. IF VALID-HANDLE (hUD01) THEN DO: /*Create new record*/ RUN GETANEWUD01 IN hUD01 ( {&input-output_dataset_UD01DataSet} ) NO-ERROR. find first ttUD01 where ttUD01.ROWMOD = 'A' no-lock no-error. IF available ttUD01 THEN DO: /*Populate fields*/ assign ttUD01.Company = CUR-COMP ttUD01.Key = "AbcCode" /*Table that was affected*/ ttUD01.Key = "CountFreq" /*Field that was affected*/ ttUD01.Key = STRING(TIME,"HH:MM:SS") /*Time*/ ttUD01.Key = STRING(RECID(ttUD01)) /*To make the records unique*/ ttUD01.Date = TODAY /*Date*/ ttUD01.Number01 = ttAbcCode.CountFreq /*New Value*/ ttUD01.ShortChar01 = DCD-USERID /*User id*/ /*Commit record*/ RUN UPDATE IN hUD01 ( {&input-output_dataset_UD01DataSet} ) NO-ERROR. END. /*IF available ttUD01*/ /*Clean up*/ delete object hUD01. END. /*IF VALID-HANDLE (hUD01)*/ {&CATCH_PRIVATE} end procedure.

9 Exercise 3 – After Correction
Corrected C#: /* TO DO: replace DataSet variables with typed datasets. Add contract reference if necessary. */ var UD01DataSet = new System.Data.DataSet(); var ttAbccode_xRow = (from ttAbccode_Row in ttAbccode select ttAbccode_Row).FirstOrDefault(); hUD01 = Ice.Assemblies.ServiceRenderer.GetService<Ice.Contracts.UD01SvcContract>(Db); if (hUD01 != null) { hUD01.GETANEWUD01(UD01DataSet); var ttUD01_xRow = (from ttUD01_Row in ttUD01 where string.Equals(ttUD01_Row.RowMod, IceRow.ROWSTATE_ADDED, StringComparison.OrdinalIgnoreCase) select ttUD01_Row).FirstOrDefault(); if (ttUD01_xRow != null) ttUD01_xRow.Company = Session.CompanyID; ttUD01_xRow.Key1 = "AbcCode"; /*Table that was affected*/ ttUD01_xRow.Key2 = "CountFreq"; /*Field that was affected*/ ttUD01_xRow.Key3 = System.Convert.TimeToString(DateTime.Now, "HH:MM:SS"); /*Time*/ ttUD01_xRow.Key4 = ttUD01_xRow.SysRowID; /*To make the records unique*/ ttUD01_xRow["Date01"] = DateTime.Now; /*Date*/ ttUD01_xRow["Number01"] = ttAbccode_xRow.CountFreq; /*New Value*/ ttUD01_xRow["ShortChar01"] = Session.UserID; /*User id*/ /*Commit record*/ hUD01.UPDATE(UD01DataSet); }/*IF available ttUD01*/ /*Clean up*/ hUD01.Dispose(); } Converted C#: /* TO DO: replace DataSet variables with typed datasets. Add contract reference if necessary. */ var UD01DataSet = new System.Data.DataSet(); var ttAbccode_xRow = (from ttAbccode_Row in ttAbccode select ttAbccode_Row).FirstOrDefault(); hUD01 = Ice.Assemblies.ServiceRenderer.GetService<Ice.Contracts.UD01SvcContract>(Db); if (hUD01 != null) { hUD01.GETANEWUD01(UD01DataSet); var ttUD01_xRow = (from ttUD01_Row in ttUD01 where string.Equals(ttUD01_Row.RowMod, IceRow.ROWSTATE_ADDED, StringComparison.OrdinalIgnoreCase) select ttUD01_Row).FirstOrDefault(); if (ttUD01_xRow != null) ttUD01_xRow.Company = Session.CompanyID; ttUD01_xRow.Key1 = "AbcCode"; /*Table that was affected*/ ttUD01_xRow.Key2 = "CountFreq"; /*Field that was affected*/ ttUD01_xRow.Key3 = System.Convert.TimeToString(DateTime.Now, "HH:MM:SS"); /*Time*/ ttUD01_xRow.Key4 = ttUD01_xRow.SysRowID; /*To make the records unique*/ ttUD01_xRow["Date01"] = DateTime.Now; /*Date*/ ttUD01_xRow["Number01"] = ttAbccode_xRow.CountFreq; /*New Value*/ ttUD01_xRow["ShortChar01"] = Session.UserID; /*User id*/ /*Commit record*/ hUD01.UPDATE(UD01DataSet); }/*IF available ttUD01*/ /*Clean up*/ hUD01.Dispose(); }

10 Common Errors Case Sensitivity
Use Of Unassigned Local Variable Message E10 Equivalent to Row Mod = U or A

11 Case Sensitivity For those who do not work with C# often, remember that it is case sensitive. For example, look at the below simple query: var CustomerRecs = (from r in Db.customer from r_UD in Db.Customer_UD where r.SysRowID == r_UD.ForeignSysRowID && r.Company == Session.CompanyID && r.CustNum == ttOrderHedRow.CustNum select r_UD).FirstOrDefault(); This query will produce the following error message when you attempt to compile the BPM: Description: There is at least one compilation error. Details: Error CS1061: 'Erp.ErpContext' does not contain a definition for 'customer' and no extension method 'customer' accepting a first argument of type 'Erp.ErpContext' could be found (are you missing a using directive or an assembly reference?) Notice that the error message has customer with a lower case C? Change the following line Change the first line to an upper case C as below and the BPM compiles without error. var CustomerRecs = (from r in Db.Customer

12 Unassigned Local Variable
The compiler will give an error message referring to an Unassigned Local Variable when the BPM’s logic is such that a variable may never get set. The below example Erp.Tables.Customer Customer; Erp.Tables.Customer_UD Customer_UD; foreach (var ttCustomer_Row in ttCustomer) { using (var txscope = IceDataContext.CreateDefaultTransactionScope()) Customer = (from Customer_Row in Db.Customer.With(LockHint.UpdLock) where Customer_Row.Company == ttCustomer_Row.Company && string.Compare(Customer_Row.CustID, ttCustomer_Row.CustID, true) == 0 select Customer_Row).FirstOrDefault(); if (Customer != null) Customer_UD = (from Customer_UD_Row in Db.Customer_UD.With(LockHint.UpdLock) where Customer.SysRowID == Customer_UD_Row.ForeignSysRowID select Customer_UD_Row).FirstOrDefault(); Customer_UD.CheckBox01 = true; Customer.CreditLimit = 0; Customer.CreditHold = false; Db.Validate(); txscope.Complete(); } will generate the following error upon compilation Server Side Exception There is at least one compilation error. Exception caught in: Epicor.ServiceModel Error Detail ============ Description: There is at least one compilation error Details: Error CS0165: Use of unassigned local variable 'Customer_UD' Notice that in the above example, the Customer_UD variable is only set when if (Customer != null) We can correct this error by changing the second line of the example to Erp.Tables.Customer_UD Customer_UD = null; This change ensures that the variable will be set to something regardless of the if statement.

13 E10 Equivalent to Row Mod = U or A
In many BPM’s the user wants to peform some action if the tt record is a new record or updated record. In 9.05 the RowMod = A or U was used. In 10, the equivalent is below foreach (var ttAPInvHed_iterator in (from ttAPInvHed_Row in ttAPInvHed where (string.Equals(ttAPInvHed_Row.RowMod, IceRow.ROWSTATE_ADDED, StringComparison.OrdinalIgnoreCase) || string.Equals(ttAPInvHed_Row.RowMod, IceRow.ROWSTATE_UPDATED, StringComparison.OrdinalIgnoreCase)) select ttAPInvHed_Row))

14 Common Progress Commands
FOR EACH (used to loop through a table) FOR FIRST (used to find the first record in a table which meets where clause) CAN-FIND (used to identify existence of record) RUN PERSISTENTLY (used to run business objects on the sever) EXCLUSIVE LOCK direct database updates Issue an exception Show informational message Send an

15 FOR EACH

16 FOR FIRST

17 RUN PERSISTENTLY Get an example of this .p calling into ud01
Client Side – uses adapter as before Server Side – use Service Renderer

18 Raise an exception

19 Show in informational message – custom code
Use PublishInfoMessage

20 Send an email // EMAIL BEGIN var splitter = new[] { ';' };
var mailer = new Epicor.Customization.Bpm.Implementation.AsyncSmtpMailer(); var message = new System.Net.Mail.MailMessage(); var from = BPM_from; 17 Revision 3 message.From = new System.Net.Mail.MailAddress(from); var to = BPM_to; foreach (var address in to.Split(splitter, StringSplitOptions.RemoveEmptyEntries)) { message.To.Add(new System.Net.Mail.MailAddress(address)); } var cc = BPM_cc; foreach (var address in cc.Split(splitter, StringSplitOptions.RemoveEmptyEntries)) message.CC.Add(new System.Net.Mail.MailAddress(address)); var subject = BPM_subject; message.Subject = subject; var body = BPM_body; message.Body = body; mailer.Send(this.Db, message, this.CompanyID); //

21 Programming Guide Accessible on code converter about page
Helpful hints and how-to info

22 Questions


Download ppt "ABL to C# BPM Conversion"

Similar presentations


Ads by Google