mdsol / rwslib

Provide a (programmer) friendly client library to Rave Web Services (RWS).
MIT License
31 stars 13 forks source link

class rwslib.builders.clinicaldata.MdsolQuery does not contain re-query definition #107

Closed DevaRajan19 closed 3 years ago

DevaRajan19 commented 3 years ago

Hello Team,

We were programming the RWS calls using python builders for query opening, cancelling, closing and re-opening on the log fields of AETERM, AESTDAT and AEENDAT in AE form. Please find below the code:

#Declarations
URL1 = 'innovateURL' #Masked
UserID1 = 'ID1' #Masked
Password1 = 'Pass1' #Masked
Study_Name = 'Study' #Masked
Study_Env = 'UAT'
Study_Metadata = '2'
Study_site = '0001' #Masked
Subject_ID = 'TEST0005'
Folderoid_1 = 'AE'
Formoid_1 = 'AE'
ItemGroup_1 = 'AE'
ItemGroup_RepKey = '1'
ItemData1OID = 'AETERM'
ItermData1Value = 'TestItemIgnore'
ItemData2OID = 'AESTDAT'
ItermData2Value = '20 FEB 2020'
ItemData3OID = 'AEENDAT'
ItermData3Value = '25 APR 2020'
ItemDataTransactionTyp = 'Context'

#Query Text String to open
QT1 = 'TestQueryField1'
QT2 = 'TestQueryField2'
QT3 = 'TestQueryField3'

#Query Text Status
QT_Status_Open = QueryStatusType.Open
QT_Status_Close = QueryStatusType.Closed
QT_Status_Cancel = QueryStatusType.Cancelled
QT_Status_Answered = QueryStatusType.Answered
QT_Status_Forward = QueryStatusType.Forwarded

#Query Requires Response(true/false)
QT_ReqResp = 'true'

#Query Text string for the response
QT_Response = 'This is the response of the Query'

#Query Text Recipient
QT_MG = 'Site from DM'

#Query ID from the DB
QT_RepeatKey1='123' #AETERM #Masked
QT_RepeatKey2='456' #AESTDAT #Masked
QT_RepeatKey3='789' #AEENDAT #Masked

#Main Program starts here
rwscon = RWSConnection(URL1, UserID1, Password1)
Odm = ODM("TestData")
Clinical_data = ClinicalData(projectname=Study_Name, environment=Study_Env, metadata_version_oid=Study_Metadata)
subject_data = SubjectData(site_location_oid=Study_site, subject_key=Subject_ID)
event_data = StudyEventData(study_event_oid=Folderoid_1)
form_data = FormData(formoid=Formoid_1)
itemgroup1= ItemGroupData(itemgroupoid =ItemGroup_1, item_group_repeat_key=ItemGroup_RepKey)
itemdata1 = ItemData(itemoid=ItemData1OID, value=ItermData1Value, transaction_type=ItemDataTransactionTyp)
itemdata2 = ItemData(itemoid=ItemData2OID, value=ItermData2Value, transaction_type=ItemDataTransactionTyp)
itemdata3 = ItemData(itemoid=ItemData3OID, value=ItermData3Value, transaction_type=ItemDataTransactionTyp)

#Unomment the query1 variable based on the action needed before running the code.
#To Open Queries
#query1 = MdsolQuery(value=QT1, requires_response = QT_ReqResp, recipient=QT_MG, status=QT_Status_Open)

#To Cancel Queries
#query1 = MdsolQuery(query_repeat_key = QT_RepeatKey1, recipient=QT_MG, status=QT_Status_Cancel)

#To Close Queries
#query1 = MdsolQuery(query_repeat_key = QT_RepeatKey1, recipient=QT_MG, status=QT_Status_Close)

#To Requery, Note enter previous query repeat key
#query1 = MdsolQuery(value=QT1, query_repeat_key = QT_RepeatKey1, requires_response = QT_ReqResp, recipient=QT_MG, status=QT_Status_Open)

itemgroup1 << itemdata1 << query1
Odm << Clinical_data << subject_data << event_data << form_data << itemgroup1
print(str(Odm))
responseobject = rwscon.send_request(PostDataRequest(str(Odm)))
print(str(responseobject))

As per the RWS tutorials in Knowledge Space https://learn.mdsol.com/api/rws/use-field-queries-95587384.html, we find that for re-query action we need the following parameters

  1. PrecedingQueryRepeatKey - Please confirm what this denotes! Is it denoting Query ID of the Response provided or the Initial Query Raised
  2. Query Value - Query Text
  3. Query Status - Open

We observed a few issues with the Re-Query part mainly

Could you please confirm if there is an option to re-query (along with requires response) and provide us the snippet for the same.

iansparks commented 3 years ago

Hi. Not sure I can answer all questions. First, you can make your own MdsolQuery subclass to add requery action. It's not as easy as it should be but:

from rwslib.builders.clinicaldata import MdsolQuery, QueryStatusType
from rwslib.builders.common import bool_to_yes_no

class MdsolQuery2(MdsolQuery):
    """MdsolQuery type with preceding_query_repeat_key"""
    def __init__(self, **kwargs):
        self.preceding_query_repeat_key = kwargs.pop("preceding_query_repeat_key", None)
        MdsolQuery.__init__(self, **kwargs)

    def build(self, builder):
        """
        Build XML by appending to builder
        """
        params = {}

        if self.value is not None:
            params["Value"] = str(self.value)

        if self.query_repeat_key is not None:
            params["QueryRepeatKey"] = str(self.query_repeat_key)

        # ADDED PART ---
        if self.preceding_query_repeat_key is not None:
            params["PrecedingQueryRepeatKey"] = str(self.preceding_query_repeat_key)
        # --- ADDED PART

        if self.recipient is not None:
            params["Recipient"] = str(self.recipient)

        if self.status is not None:
            params["Status"] = self.status.value

        if self.requires_response is not None:
            params["RequiresResponse"] = bool_to_yes_no(self.requires_response)

        # When closing a query
        if self.response is not None:
            params["Response"] = str(self.response)

        builder.start("mdsol:Query", params)
        builder.end("mdsol:Query")

#Query Text String to open
QT1 = 'TestQueryField1'

#Query Text Status
QT_Status_Open = QueryStatusType.Open

#Query Requires Response(true/false)
QT_ReqResp = 'true'

#Query Text string for the response
QT_Response = 'This is the response of the Query'

#Query Text Recipient
QT_MG = 'Site from DM'

#Query ID from the DB
QT_RepeatKey1='123' #AETERM #Masked

query1 = MdsolQuery2(value=QT1, query_repeat_key = QT_RepeatKey1, requires_response = QT_ReqResp, recipient=QT_MG, status=QT_Status_Open,
                    preceding_query_repeat_key=99
)
print(str(query1))
#  <mdsol:Query Value="TestQueryField1" QueryRepeatKey="123" PrecedingQueryRepeatKey="99" Recipient="Site from DM" Status="Open" RequiresResponse="Yes" />
#                                                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I personally have not used the PrecedingQueryRepeatKey to re-open a query and I can't test right now. Maybe you can experiment with the above to see what works for you.

DevaRajan19 commented 3 years ago

Thanks for the help @iansparks. I will verify the code and let you know.

So basically what I understood with the code is that we are creating a user defined sub class of the MdsolQuery class and defining the parameters.

Could you confirm that apart from using PrecedingQueryRepeatKey, are there any other way we can re-query using the existing predefined functions(Open?

iansparks commented 3 years ago

So basically what I understood with the code is that we are creating a user defined sub class of the MdsolQuery class and defining the parameters.

Yes. An update to the library should be made to add this parameter to the existing MdsolQuery class. I'll see if I can do that.

Could you confirm that apart from using PrecedingQueryRepeatKey, are there any other way we can re-query using the existing predefined functions(Open?

By re-query you mean re-open a query that has been answered/closed by the user. I haven't tried this myself, it seems like the PrecedingQueryRepeatKey is the (database?) ID of a query that was already opened. So you open a query with your original request:

#To Open Queries
query1 = MdsolQuery(value=QT1, requires_response = QT_ReqResp, recipient=QT_MG, status=QT_Status_Open)

What response do you get back from that? Does it include some kind of Query ID? in other words, what is printed when you do:

responseobject = rwscon.send_request(PostDataRequest(str(Odm)))
print(str(responseobject))

Sorry I can't test this myself at the moment.

iansparks commented 3 years ago

Hi @DevaRajan19 I was able to do a bit of testing with help from @anewbigging

I was writing a query to a standard field. When I ran the "OpenQuery" ODM I got back:

 <Response ReferenceNumber="d4891797-147d-4d97-8cae-6898e2511cb2" InboundODMFileOID="3b5acb0a-25de-4a24-8a9b-d1dca57eb621" IsTransactionSuccessful="1" SuccessStatistics="Rave objects touched: Subjects=0; Folders=0; Forms=0; Fields=1; LogLines=0" NewRecords=""><Query ID="153083" FieldOID="SVSTDTC"/></Response>

And the query appeared in Rave. Notice the Query ID="153083" that's going to be what you need to work with this query in future. Then I could close it:

query1 = MdsolQuery(query_repeat_key = "153083", recipient=QT_MG, status=QT_Status_Close)

and then I could re-open it:

query1 = MdsolQuery2(value=QT1, requires_response = QT_ReqResp, recipient=QT_MG, status=QT_Status_Open,
                    preceding_query_repeat_key="153083")

Requeried:

requery

iansparks commented 3 years ago

Thanks to @glow-mdsol for merging the PR which includes preceding_query_repeat key in the MdsolQuery object. version 1.2.5.

DevaRajan19 commented 3 years ago

Hi @iansparks @anewbigging and @glow-mdsol; Apologies for the delayed response.

Once I had defined the custom MdsolQuery2 subClass and called the function for opening the queries using preceding key, it worked!

Thanks for the help!