Maximo scripting cannot load second MboSet - jython

I've a script with an object launchpoint on INVOICELINE.
For the mbo I want to get all INVOICELINES with the same PONUM as the current MBO (since they could be in other then the current mbo's invoice)
In the script I find the PO like so: (to test for status)
from psdi.server import MXServer
from psdi.mbo import Mbo
from psdi.mbo import MboConstants
from psdi.security import UserInfo
from psdi.server import MXServer
myMXServer = MXServer.getMXServer()
userInfo = mbo.getThisMboSet().getUserInfo()
# find the PO
poSet = myMXServer.getMboSet("PO", userInfo)
poSetWhere = "ponum='" + mbo.getString("PONUM") + "' and siteid='" + mbo.getString("POSITEID") + "' and status not in " + poNoUpdate
poSet.setWhere(poSetWhere)
poMbo = poSet.getMbo(0)
which works great.
then later I do the very same for the set of invoicelines:
ilSet = myMXServer.getMboSet("INVOICELINE", userInfo)
ilSetWhere = "ponum='" + mbo.getString("PONUM") + "' and positeid='" + mbo.getString("POSITEID") + "'"
ilSet.setWhere(ilSetWhere)
ilMbo = ilSet.moveFirst()
while ilMbo is not None:
...
which results in a error on the setWhere line. Curiously, logging (which I removed for readability) indicates that ilSet contains all invoicelines records after the getMboSet (as expected), the ilSetWhere has a valid query that you can copy-paste in SQL Developer.
Does Maximo need some index or so before it can execute this setWhere?
Here is the logging result for the two setWhere strings:
ponum='4140006682' and siteid='mysite' and status not in ('CLOSED','CAN','GESLTN','ANN')
and
ponum='4140006682' and positeid='mysite'
The error I get is a generic BMXAA7837E java.lang.NullPointerException in script at line... (the line refers to the line with the ilSet.setWhere(ilSetWhere) expression. I'm out of ideas how to fix this and have no clue how to work around it.

Now we have an error to work with!
Maximo effectively insists that an INVOICELINE set has an "owner", which you have not set up in your code example. Think of an owner as a parent set. Specifically, it is the MBOSet used to fetch the current set off of. It doesn't actually have to be related to the current set, but most of the time it will be (and it makes the most sense to fetch sets that way). An owner can be injected into the set after it's fetched (to change it or trick Maximo), but this is rarely good code.
Instead of getting a fresh set (no other ties or possible data caching) from the server in its own transaction, you might be best off getting the invoiceline set off of your current MBO. I don't know your exact use case, but generally you want to do something like this instead of getting a new set like you did. At the least, it will give your new set an "owner". You may even want to make the SQL a "relationship" instead of hard-coding it.
ilSetWhere = "ponum='" + mbo.getString("PONUM") + "' and positeid='" + mbo.getString("POSITEID") + "'"
ilSet = mbo.getMboSet("$TempInvoiceLineRelationship", "INVOICELINE", ilSetWhere)
ilMbo = ilSet.moveFirst()
I'm going from memory for this code, so I don't know if it is exactly correct. That form of "getMboSet" takes three parameters. The first is a relationship name. If Maximo finds that relationship name already "registered" from this starting object, it will ignore the next two parameters and use that relationship to get you that set. If it doesn't find that relationship "registered" it registers it for the scope of this code (so you can re-use it later in this code if you wanted). The second parameter defines what destination object to create the temporary relationship to. The third parameter defines the "where clause" of this temporary relationship.
Original Answer:
What is the error you are getting?
Also, you say you log "ilSet" after the "myMXServer.getMboSet..." line? That is going to cause Maximo to run the query and load the objects into the set at that point (it waits to run the query until it has to). As a result of that, you won't see the effects of your where clause change until you "reset()" the set.

Related

How to read automatically-created variants

I need to read automatically-created variants, to get the selection screen parameters and other selection criteria. The names of such variants begin with symbol & (for example, &0000000000425). Such variants are created once you schedule any background job from se80/se38 or any transaction without choosing any existing variant (from the selection screen, menu Program -> Execute in background).
The function module RS_VARIANT_CONTENTS works fine for normal variants (which can be seen via se80/se38), but not for the automatically-created ones (that begin with &). I looked into the FM and found that the VARI table was read by the next code:
IMPORT %_VARI40C TO P_VARI
%_VARI40 TO L_VARI_40
%_VARI TO L_VARI
%_VARIVDAT TO P_VARIVDAT
* %_VARIDYN40 TO P_VARIDYN
%_VARIVDAT_DYN40 TO P_VDATDYN
DYNS_FIELDS TO OLD_DYNSFIELDS
DYNS_TEXPRI TO OLD_TEXPRI
DYNS_EXPR TO OLD_EXPR
DYNS_FIELD_TAB TO DYNS_FIELDS
DYNS_TEXPR TO DYN_SEL-TEXPR
FROM DATABASE VARI(VB) CLIENT L_CLIENT ID P_RKEY
ignoring structure boundaries
IGNORING CONVERSION ERRORS.
However the import returns nothing for the & variants. It looks like the values for & variants are stored within a format which is different from the format used by FM RS_VARIANT_CONTENTS.
Is there any way to find a proper format/data structure for & variants values?
Update: I created ZBC_TEST program and scheduled it as a job. I see a record in VARI table:
MANDT RELID REPORT VARIANT SRTF2
200 VB ZBC_TEST &0000000000425 0
So, the &0000000000425 variant exists in VARI table. VARI-CLUSTD field is not empty for the record. I use this code:
CALL FUNCTION 'RS_VARIANT_CONTENTS'
EXPORTING
REPORT = 'ZBC_TEST'
VARIANT = '&0000000000425'
MOVE_OR_WRITE = 'W'
IMPORTING
SP = lv_sp
TABLES
VALUTAB = lt_valtab.
The FM has been performed without any exception and sy-subrc=0, but lt_valtab table is empty...
The function module is working correctly: Since your program does not have any parameters, the returned value set is empty.

Understanding PsychoPy codes for trialHandler and responses

I am new to coding, and would like help in understanding the script used by the PsychoPy program.
To be more specific, I would like to understand the codes that are in line 6 to 15. I am aware that this is used to manage the multiple trials, but I am hoping someone can help me clarify those bits? I also noted that removing the codes from line 6-8 doesn't change the experiment, but removing the codes from line 10-15 essentially stop the experiment from running.
trialsAll = data.TrialHandler(trialList=data.importConditions('trialType.xlsx'), nReps=10, method='random', name='trialsAll', dataTypes='corr')
thisExp = data.ExperimentHandler(name='Ours')
thisExp.addLoop(trialsAll) #adds a loop to the experiment
thisTrial = trialsAll.trialList[0]
if thisTrial != None:
for paramName in thisTrial.keys():
exec(paramName + '= thisTrial.' + paramName)
# Loop through trials
for thisTrial in trialsAll:
currentLoop=trialsAll
if thisTrial != None:
for paramName in thisTrial.keys():
exec(paramName + '=thisTrial.' + paramName)
My second question would be about getting responses. Is there a reason that thisResp is equalled to None?
#get response
thisResp=None
while thisResp==None:
allKeys=event.waitKeys()
Thanks a lot for any help. I appreciate it.
Regards,
Cash
if thisTrial != None:
for paramName in thisTrial.keys():
exec(paramName + '= thisTrial.' + paramName)
This code allows the use of abbreviations. For example, say your conditions file has a field called 'angle', you can refer to this directly rather than via the keys of that trial's dictionary (e.g. thisTrial['angle'] ) or using dot notation ( thisTrial.angle ). i.e., in this example:
angle = thisTrial.angle
for thisTrial in trialsAll:
is fundamental to running a psychoPy trial loop. It will cycle though each trial that is contained in the TrialHandler object that is created to manage trials, connected to a given conditions file.
#get response
thisResp=None
while thisResp==None:
allKeys=event.waitKeys()
The line 'while thisResp==None:' requires that the variable 'thisResp' actually exists if we are going to be able to check its value. So in the immediately preceding line, it is created and given an initial null value so that the next line will run OK. Note that at this stage, it is just an arbitrary variable, which doesn't have any actual connection to the subject's response. That will presumably occur later in the code, when it gets assigned a value other than None.

Zoho Creator making a custom function for a report

Trying to wrap my head around zoho creator, its not as simple as they make it out to be for building apps… I have an inventory database, and i have four fields that I call to fill a field called Inventory Number (Inv_Num1) –
First Name (First_Name)
Last Name (Last_Name)
Year (Year)
Number (Number)
I have a Custom Function script that I call through a Custom Action in the form report. What I am trying to do is upload a CSV file with 900 entries. Of course, not all of those have those values (first/last/number) so I need to bulk edit all of them. However when I do the bulk edit, the Inv_Num1 field is not updated with the new values. I use the custom action to populate the Inv_Num1 field with the values of the other 4 fields.
Heres is my script:
void onetime.UpdateInv()
{
for each Inventory_Record in Management
{
FN = Inventory_Record.First_Name.subString(0,1);
LN = Inventory_Record.Last_Name.subString(0,1);
YR = Inventory_Record.Year.subString(2,4);
NO = Inventory_Record.Number;
outputstr = FN + LN + YR + NO;
Inventory_Record.Inv_Num1 = outputstr;
}
}
I get this error back when I try to run this function
Error.
Error in executing UpdateInv workflow.
Error in executing For Each Record task.
Error in executing Set Variable task. Unable to update template variable FN.
Error evaluating STRING expression :
Even though there is a First Name for example, it still thinks there is none. This only happens on the fields I changed with Bulk Edit. If I do each one by hand, then the custom action works—but of course then the Inv_Num1 is already updated through my edit on success functions and makes the whole thing moot.
this may be one year late, you might have found the solution but just to highlight, the error u were facing was just due to the null value in first name.
you just have put a null check on each field and u r good to go.
you can generate the inv_number on the time of bulk uploading also by adding null check in the same code on and placing the code on Add> On Submt.( just the part inside the loop )
the Better option would be using a formula field, you just have to put this formula in that formula field and you'll get your inventory_number autogenerated , you can rename the formula_field to Inv Number or whaterver u want.
Since you are using substring directly in year Field, I am assuming the
year field as string.else you would have to user Year.tostring().substring(2,4) & instead of if(Year=="","",...) you have to put if(Year==null , null,...);
so here's the formula
if(First_Name=="","",First_Name.subString(0,1))+if(Last_Name =="","",Last_Name.subString(0,1)) + if(Year=="","",Year.subString(2,4)+Number
Let me know ur response if u implement this.
Without knowing the datatype its difficult to fix, but making the assumption that your Inventory_Record.number is a numeric data item you are adding a string to a number:
The "+" is used for string Concatenation - Joiner but it also adds two numbers together so think "a" + "b" = "ab" for strings but for numbers 1 + 2 = 3.
All good, but when you do "a" + 2 the system doesn't know whether to add or concatenate so gives an error.

Volusion's generic SQL folder, functionality

I found this response very helpful
How to write join query in Volusion API
What I'm looking for is a way to add my own .SQL and .XSD files to the /vspfiles/schema/Generic folder and be able to pass parameters to it. Does anyone know if that's possible.
A very basic example of the SQL would be something like this...
select * from Orders where order_id = "-ORDERID-"
...and I'd be able to pass in the "-ORDERID-" as a variable.
Or even better the SQL file would just be this "-SQL-" and I could pass in the entire SQL string myself. Thanks!
Thanks user357034 for getting me here (I'd "up" your answer but I'm new and don't have any reputation). I wanted to post the code I used in case others run into this. And also get any feedback if you see anything that looks goofy here.
First, I created an ASP file like so
Dim orderid
Dim status
orderid = Request.QueryString("orderid")
status = Request.QueryString("status")
sql = " update Orders " & _
" set OrderStatus = '" + status + "' " & _
" where Orderid in (" + orderid + ") " ;
set fs=Server.CreateObject("Scripting.FileSystemObject")
set f=fs.OpenTextFile(Server.MapPath("./MY_FILE.sql"),2,true)
f.WriteLine(sql)
f.Close
set f=Nothing
set fs=Nothing
I FTPed that up to the "generic" folder on Volusion.
Next, in PHP, I call this file, similar to this...
$asp = file("http://MY_SITE/v/vspfiles/schema/generic/MY_FILE.asp?
orderid=11,12&status=Processing");
foreach ( $asp as $line )
{
echo ($line);
}
NOTE: I already FTPed an XSD file to the same folder with the same name, like MY_FILE.xsd.
And finally, I make a web service call to my service, like this...
$url = "http://MY_SITE/net/WebService.aspx?
Login=XXXX&EncryptedPassword=YYYYY&API_Name=Generic\MY_FILE"
Works great. I go into the Volusion admin site, look at the Orders 11 and 12, and they were updated. I'm using this method for several areas in Volusion where their API is lacking. Thanks!
While technically one could pass in text comprised of a complete SQL query, however I would strongly caution against such practice as it would open up your site to malicious activity and/or possible security issues. I would limit the scope to a specific query and only allow one or more parameters to be used.
To accomplish this you have to create an custom ASP page in Volusion that would gather the parameters from the user, in your case "order id" and then insert them into the set SQL query, write that SQL query as a text file to the server in the correct location as shown in https://stackoverflow.com/a/29134928/357034 and then execute the query. All this is done in the custom ASP page.
UPDATE: If you just want a simple order id query with all fields returned you don't even have to use the the SQL method as Volusion already has a built in method to return this data. You just have to use a custom ASP page to insert the order id parameter and then execute the URL with the parameter attached. In your ASP page you would insert the order id in place of the xxxxx
http://www.yoursiteurl.com/net/WebService.aspx?Login=name#yoursiteurl.com&EncryptedPassword=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxC&EDI_Name=Generic\Orders&SELECT_Columns=*&WHERE_Column=o.OrderID&WHERE_Value=xxxxx

NHibernate SQL query issue with string parameter

I got a problem with this code:
string sql = "select distinct ruoli.c_tip_usr"
+ " from vneczx_ute_app_trn ruoli"
+ " join vnecyd_ent_prf ind"
+ " on ruoli.c_ent = ind.c_ent"
+ " where ruoli.c_app = :appCode"
+ " and ruoli.c_ute_mat = :matricola"
+ " and ind.t_des_ent = :indirizzo";
var ruoli = session.CreateSQLQuery(sql)
.SetString("appCode", Config.Configurator.Istance.ApplicationCode)
.SetString("matricola", user.Matricola)
.SetString("indirizzo", indirizzoCasella)
.List<string>();
This code is correctly executed, the query logged is correct, and the parameter passed correctly evaluated... but it doesn't return any result at all.
Copying the query from the debug console and executing it directly in an Oracle client application (SQL Developer), it gets 2 results (the results I expect to be right).
I found out that the problem is in the last parameter indirizzo, and should depend on the fact that it contains a special char # (indirizzo is an email address).
So I ended up using this solution:
string sql = "select distinct ruoli.c_tip_usr"
+ " from vneczx_ute_app_trn ruoli"
+ " join vnecyd_ent_prf ind"
+ " on ruoli.c_ent = ind.c_ent"
+ " where ruoli.c_app = :appCode"
+ " and ruoli.c_ute_mat = :matricola"
+ " and ind.t_des_ent = '" + indirizzoCasella + "'";
var ruoli = session.CreateSQLQuery(sql)
.SetString("appCode", Config.Configurator.Istance.ApplicationCode)
.SetString("matricola", user.Matricola)
.List<string>();
But it gives me thrills! Aren't the parameters in a query supposed to handle specifically this situation, and thus handle themselves situations with special char, and so on?
Why here a string concatenation works better that a parametric query?
Isn't there a way to force the NHibernate engine to escape some special char?
Update:
I found out how to solve this particular issue: usign the trim command on the field who raise the problem, the problem disappears.
So last line of my sql string now is:
+ " and trim(ind.t_des_ent) = :indirizzo";
I can't understand why it solves the problem thought. Not the field, nor the variable contains empty chars and copying th query on SQL Developer works in both way.
So we have some luck soving the problem, but we have no idea why now it works?
Any thoughts?
even I was facing the same issue, but your hint using TRIM for column saved my day. Since I was looking for a long time, but not able to figure it out.
Along with that, I was able solve my issue by doing the below changes as well:
We were using CHAR datatype some of the columns which used in the query where clause. This was causing the issue to fetch the data from NHibernate. We changed the data type of that column from CHAR to VARCHAR2 and even updated the data with actual size and removed the TRIM from Where clause, the TRICK WORKED!!!! :)
So, any one face this kind of issue, first check whether you are having any column with CHAR and then change to VARCHAR2.
But one more thing you have to remember is: if you are running your application from ASP.Net Development Server, close it and re-run your application. Since if the opening Asp.Net Development Server and if you make any changes to datatype that will NOT be refreshed in your oracle connection. So, better you close the ASP.Net Development server and then re run the application.
Hope my points will help somebody in future!!
Regards,
Sree Harshavardhana
You are not using parameters in a SQL query if you want SQL parameters use a SQL stored proc