Sage 100

 View Only
  • 1.  PO Line Script to update data in SO Lines

    Posted 10-23-2020 18:26
    Looking for feedback (tips, gotchas, etc.) for a script concept.  Customer wants a column Post-Validate event on the PO Lines Required Date field.  They do NOT do any automatic PO's from SO's (or drop-ships), so there is no embedded link between SO's and PO's.  The script would make a connection to SO_SalesOrderDetail_bus object, find all lines with the same ItemCode as the current PO Line, and change the SO_SalesOrderDetail.PromiseDate to match the PO Line Required Date.  I've read in SageCity that making connections directly to detail objects (i.e. SO Order Detail) in general is ill-advised, but looking for feedback if anyone has had luck with this type of idea. 

    I'm having trouble just making a connection to SO_SalesOrderDetail from the PO_PurchaseOrderDetail object.  I can connect to SO_SalesOrder (header) just fine.  I'm using the same syntax to connect to the Detail:

    If Not(IsObject(oSOLine)) Then
       Set oSOLine = oSession.AsObject(oSession.GetObject("SO_SalesOrderDetail_Bus"))
    End If

    retSetKeyValue = oSOLine.SetKeyValue("SalesOrderNo$", sSONum)
    retSetKeyValue = oSOLine.SetKeyValue("LineKey$", sSOLineKey)

    retVal = oSOLine.SetKey()

    I've tried the PaddedKey approach as well.  I've tried Find() just to see if I can make a connection, although I really do need SetKey() since I need to update.  

    LastErrorMsg (although I'm a rookie at debugging) shows "The  is invalid." (with a space between "the" and "is").

    FYI, @Alnoor Cassim hooked me up with some great ideas for the actual project, including using the SetBrowserIndex() and ​KITEMTYPE alternate key to find the matching item numbers. But I can't even get started on that until I can instantiate the SOLine object.

    Thanks for any ideas everyone.

    ------------------------------
    Rob Neal
    ------------------------------


  • 2.  RE: PO Line Script to update data in SO Lines

    Posted 10-26-2020 03:19
    Edited by David Speck II 10-27-2020 12:20
    You can use the detail bus object to read lines using GetResultSets or with a browse filter however you can not directly update lines from a detail bus object that was not spawned by the appropriate header object. So you could use one copy of the detail object to get the key information you need for each record and then use a copy of the header bus to first set the header to the correct sales order and then use its Lines property to update the appropriate lines.

    I will add however that this project has room for some nasty issues to pop up, particularly around the timing of the update against the lines and the risk of one or more users having one of the affected sales orders open. In version 2018, if i open a sales order in Sales Order Entry and then use a script to open the same sales order using SO_SalesOrder_bus, i don't get any errors or warnings during the SetKey or SetValues, it isn't until i go to do the Write that it fails and the LastErrorMsg is "The record is in use by another user.".

    These kind of things can be tricky depending on the target record to be updated since different objects behave differently when the same record is open by more than one user. CI_ItemCode_bus is one of these where it doesn't matter who opens the record first, the first instance to write changes to the record succeeds and any subsequent attempts to write changes where the record in memory is from before the changes written by the first instance will fail with the message that "the record has been changed by another user and the changes will not be saved.". This is due to the fact that when a task reads a record for Entry/Maintenance purposes, it keeps the original record's values in memory and compares that to the record's current values when attempting to write any changes to the record. If there is a mismatch, you get the message i described earlier. You can see this in action yourself with Item Maintenance, launch two of them and select the item code in each, you won't get any warnings. Then make a change in one and accept the changes, go to the other, make a change and attempt to accept the changes, you should then get the message i described earlier.

    If you decide to pursue this, you will need to come up with some way to defer updates if the record is in use or figure out how you want to address these exceptions. Using a UDT could work to write the changes required to it with the key as the primary key for SO_SalesOrderDetail, a field for just the sales order number, a field for the line key, a field for the new date, you may want a field to act as a time stamp of sort for sorting purposes, and maybe a field to act has a flag of some sort depending on how you pursue the deferred update. You could try a table script on the UDT to attempt to update the sales order, if the update fails, then the record stays in the UDT, if the update succeeds, delete the record from the UDT (you could defer this logic to the scripts mentioned below). You could then use a scheduled VI Import job set up to use ODBC as the source and point it to either a silent DSN on the SOTAMAS90 DSN and use the key button to enter the user and company separated by the vertical pipe symbol and the password. You would then set up the query to just pull from the UDT and using each of the fields in it, you should be able to update the lines. You should sort the record set by time stamp if you decided to use it and then by the sales order number and line key. You would need a script on the sales order detail to check the UDT, this would probably be best on the detail's post write, in which you would need to get the key information and the promise date that was just set and then look for a matching record, if a matching record is found, you would then want to set a storage variable to act as a flag using the script object of either the header object or the session object so a script on the post write of the header can check if the flag was set, since this is in the post write, you can be positive the promise date was updated, you would then either need to loop through the lines again to find the matching lines between the detail and the UDT to delete the correct records from the UDT or use another storage variable to hold a delimited string compiled for each primary key of the matching records found in the UDT that was handled earlier by the detail's post write. Another way to handle clearing the correct records from the UDT would be to use a flag field in the UDT, so, on the post write of the detail, you would set the flag of the matching UDT record to something, then in the post write of the header, you could use GetResultSets against the UDT on the sales order number field and the flag field so they match the current sales order and whatever flag value you decide on. Also, i don't recall of the top of my head whether or not a sales order line can be linked to more than on PO (one to many), if it can, you are going to want to address this too, such as if one PO is expected to come in sooner but doesn't have sufficient quantity for the line, which required date should you use? 

    Depending on how close to real time they want the promise date updated, you might be able to just get away with a scheduled VI Import job set to run daily at a time when the client is positive sales orders are not going to be maintained, you would then just query against sage 100 like i described earlier but craft the SQL statement to have all the right info needed to update the lines from the queried PO data.

    These are just some ideas but as you can see, it can get pretty messy. I'm sure there are other potential ways to handle this as well. 

    Just make sure you determine how critical that promise date is to your client and determine if you want to accept liability for when/if you solution fails to update a promise date because of the timing.

    Well, enough of my ramblings, good luck.

    ------------------------------
    David Speck II
    Tennessee Software Solutions
    ------------------------------



  • 3.  RE: PO Line Script to update data in SO Lines

    Posted 10-26-2020 08:09
    Is there a way to check for "Sales Order in use" at the start of the script?

    ------------------------------
    Phil McIntosh
    President
    Friendly Systems, Inc.
    Asheville NC
    678.273.4010 ext 5
    ------------------------------



  • 4.  RE: PO Line Script to update data in SO Lines

    Posted 10-26-2020 10:05
    Yes, you can check the EditState of the Sales Order [Header].

    ------------------------------
    Michelle Taylor
    ERP Consulting Manager, CS3 Technology
    918-388-9772
    ------------------------------



  • 5.  RE: PO Line Script to update data in SO Lines

    Posted 10-26-2020 12:22
    Great ideas everyone.  Thanks for all the great info.  I'll keep you posted!

    ------------------------------
    Rob Neal
    ------------------------------



  • 6.  RE: PO Line Script to update data in SO Lines

    Posted 10-26-2020 15:38

    oBusObj.SecurityAccess

    if oBusObj.SecurityAccess = 0 then ' Inquiry screen or user only has View permission.

     

    0 equals View only.

    2 equals Modify with View implied.

    3 equals Create with View and Modify implied.

    4 equals Remove with View implied.

    6 equals Modify and Remove with View implied.

    7 equals Create, Modify, and Remove with View implied.



    ------------------------------
    Kevin Moyes
    Technical Systems Analyst
    Munjal White Consulting Co.
    Toronto ON
    ------------------------------



  • 7.  RE: PO Line Script to update data in SO Lines

    Posted 10-27-2020 12:26
    Just tested oBusObj.EditState on a sales order i had opened prior in another Sales Order Entry and it returned a 1, so i think that is out of the question. oBusObj.SecurityAccess does indeed work. Hadn't thought of using it that way, think i have only ever used it to check if the task being launched was an "Inquiry" version of the entry task or to see if a user had specific level of access. Didn't realize the object would set it to 0 in this scenario, good to know.


    ------------------------------
    David Speck II
    Tennessee Software Solutions
    ------------------------------