wwpdb.apps.msgmodule 0.175__tar.gz → 0.176__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/PKG-INFO +1 -1
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/__init__.py +1 -1
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/depict/MessagingDepict.py +24 -9
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/io/MessagingIo.py +24 -10
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/util/AutoMessage.py +8 -7
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/util/ExtractMessage.py +115 -5
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/webapp/MessagingWebApp.py +11 -1
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb.apps.msgmodule.egg-info/PKG-INFO +1 -1
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/README.md +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/setup.cfg +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/setup.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/__init__.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/__init__.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/depict/MessagingTemplates.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/depict/__init__.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/io/DateUtil.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/io/EmHeaderUtils.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/io/MessagingDataExport.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/io/MessagingDataImport.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/io/__init__.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/models/Message.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/models/__init__.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/util/__init__.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/webapp/__init__.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/webapp/wsgi.py +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb.apps.msgmodule.egg-info/SOURCES.txt +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb.apps.msgmodule.egg-info/dependency_links.txt +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb.apps.msgmodule.egg-info/not-zip-safe +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb.apps.msgmodule.egg-info/requires.txt +0 -0
- {wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb.apps.msgmodule.egg-info/top_level.txt +0 -0
|
@@ -83,8 +83,8 @@ class MessagingDepict(object):
|
|
|
83
83
|
self.rltvEdtrSessionPath = None
|
|
84
84
|
#
|
|
85
85
|
self.__expMethodList = []
|
|
86
|
-
if self.__verbose:
|
|
87
|
-
|
|
86
|
+
# if self.__verbose:
|
|
87
|
+
# logger.info("CStrack+++ initiate MessagingDepict class")
|
|
88
88
|
|
|
89
89
|
def doRender(self, p_reqObj, p_bIsWorkflow):
|
|
90
90
|
"""Render HTML used as starter page/container for the wwPDB Messaging interface
|
|
@@ -205,6 +205,7 @@ class MessagingDepict(object):
|
|
|
205
205
|
tmpltFile = "msging_launch_embed_tmplt.html" if embeddedVw.lower() == "true" else "msging_launch_tmplt.html"
|
|
206
206
|
|
|
207
207
|
oL.append(self.processTemplate(tmpltPth=tmpltPath, fn=tmpltFile, parameterDict=myD))
|
|
208
|
+
logger.info("CStrack+++ use html template of *%s*", tmpltFile)
|
|
208
209
|
#
|
|
209
210
|
return oL
|
|
210
211
|
|
|
@@ -217,6 +218,9 @@ class MessagingDepict(object):
|
|
|
217
218
|
|
|
218
219
|
"""
|
|
219
220
|
#
|
|
221
|
+
logger.info("CStrack+++ dump input web request obj for templates generation")
|
|
222
|
+
logger.info("".join(p_reqObj.dump()))
|
|
223
|
+
|
|
220
224
|
oL = []
|
|
221
225
|
#
|
|
222
226
|
strParamDict = {}
|
|
@@ -240,8 +244,8 @@ class MessagingDepict(object):
|
|
|
240
244
|
if self.__verbose:
|
|
241
245
|
logger.info("\n -- dep_id is:%s", depId)
|
|
242
246
|
#
|
|
243
|
-
if self.__verbose:
|
|
244
|
-
|
|
247
|
+
# if self.__verbose:
|
|
248
|
+
# logger.info("CStrack+++ call MessagingIo class from MessagingDepict.getMsgTmplts()")
|
|
245
249
|
msgingIo = MessagingIo(p_reqObj, self.__verbose, self.__lfh)
|
|
246
250
|
msgingIo.initializeDataStore() # THIS CALL MUST BE MADE HERE TO SUPPORT ALL DOWNSTREAM PROCESSING IN NEED OF DATA PARSED FROM THE COORDINATE FILE
|
|
247
251
|
msgingIo.getMsgTmpltDataItems(strParamDict)
|
|
@@ -259,7 +263,7 @@ class MessagingDepict(object):
|
|
|
259
263
|
|
|
260
264
|
# CS 2022-02-27 add map-only withdrawn template;
|
|
261
265
|
# CS 2023-10-20 start, further seperate all scenarios of EM model-map, model-only, and map-only. The selection process needs to be optimized later.
|
|
262
|
-
logger.info("strParamDict: %s", strParamDict)
|
|
266
|
+
# logger.info("strParamDict: %s", strParamDict)
|
|
263
267
|
if b_em:
|
|
264
268
|
logger.info("CStrack+++ EM-ENTRY")
|
|
265
269
|
if strParamDict.get("pdb_id", "") == "[PDBID NOT AVAIL]": # EM map-only
|
|
@@ -317,8 +321,16 @@ class MessagingDepict(object):
|
|
|
317
321
|
) # noqa: E501
|
|
318
322
|
strParamDict["msg_tmplt_maponly-authstatus-em"] = (MessagingTemplates.msgTmplt_mapOnly_authStatus_em % strParamDict) if b_em else ""
|
|
319
323
|
|
|
324
|
+
logger.info("CStrack+++ dump parameter dict for templates")
|
|
325
|
+
logger.info("\n".join(list(strParamDict.keys())))
|
|
326
|
+
# logger.info(strParamDict["msg_tmplt_vldtn"])
|
|
327
|
+
# logger.info(strParamDict["msg_tmplt_approval-expl"])
|
|
328
|
+
|
|
320
329
|
oL.append(self.processTemplate(tmpltPth=tmpltPath, fn="msg_tmplts.html", parameterDict=strParamDict))
|
|
330
|
+
logger.info("CStrack+++ use html template of *msg_tmplts.html*")
|
|
321
331
|
#
|
|
332
|
+
logger.info(''.join(oL))
|
|
333
|
+
|
|
322
334
|
return oL
|
|
323
335
|
|
|
324
336
|
def doRenderAllCorrespondence(self, p_reqObj):
|
|
@@ -369,6 +381,7 @@ class MessagingDepict(object):
|
|
|
369
381
|
# tmpltFile = "msging_launch_embed_tmplt.previewMsg.html" if embeddedVw.lower() == "true" else "msging_launch_tmplt.previewMsg.20150622.html"
|
|
370
382
|
|
|
371
383
|
oL.append(self.processTemplate(tmpltPth=tmpltPath, fn=tmpltFile, parameterDict=myD))
|
|
384
|
+
logger.info("CStrack+++ use html template of *%s*", tmpltFile)
|
|
372
385
|
#
|
|
373
386
|
return oL
|
|
374
387
|
|
|
@@ -445,8 +458,8 @@ class MessagingDepict(object):
|
|
|
445
458
|
############################################################################
|
|
446
459
|
# get message template data from MessagingIo
|
|
447
460
|
############################################################################
|
|
448
|
-
if self.__verbose:
|
|
449
|
-
|
|
461
|
+
# if self.__verbose:
|
|
462
|
+
# logger.info("CStrack+++ call MessagingIo class from MessagingDepict.doRenderDisplayMsg()")
|
|
450
463
|
msgingIo = MessagingIo(p_reqObj, self.__verbose, self.__lfh)
|
|
451
464
|
msgingIo.getMsgTmpltDataItems(myD)
|
|
452
465
|
|
|
@@ -491,6 +504,8 @@ class MessagingDepict(object):
|
|
|
491
504
|
tmpltFile = "display_msg_tmplt.html"
|
|
492
505
|
oL.append(self.processTemplate(tmpltPth=tmpltPath, fn=tmpltFile, parameterDict=myD))
|
|
493
506
|
#
|
|
507
|
+
logger.info("CStrack+++ use html template of *%s*", tmpltFile)
|
|
508
|
+
|
|
494
509
|
return oL
|
|
495
510
|
|
|
496
511
|
# ####### BEGIN -- Specific to DataTable Implementation ##################
|
|
@@ -547,8 +562,8 @@ class MessagingDepict(object):
|
|
|
547
562
|
sContentType = p_reqObj.getValue("content_type")
|
|
548
563
|
bCommHstryRqstd = True if sContentType == "commhstry" else False
|
|
549
564
|
#
|
|
550
|
-
if self.__verbose:
|
|
551
|
-
|
|
565
|
+
# if self.__verbose:
|
|
566
|
+
# logger.info("CStrack+++ call MessagingIo class from MessagingDepict.getDataTableTemplate()")
|
|
552
567
|
msgingIo = MessagingIo(p_reqObj, self.__verbose, self.__lfh)
|
|
553
568
|
bOk, msgColList = msgingIo.getMsgColList(bCommHstryRqstd)
|
|
554
569
|
#
|
{wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/io/MessagingIo.py
RENAMED
|
@@ -123,6 +123,7 @@
|
|
|
123
123
|
# 2023-11-06 CS Update logic for __getDefaultMsgTmpltType(), i.e. default message pop-up for StatusMod
|
|
124
124
|
# 2023-11-20 EP Add anyUnactionApprovalWithoutCorrection() to determine if any pendingapproval without corrections that need to be acted upon
|
|
125
125
|
# 2023-11-23 EP autoMsg() add support for explicit-approved autogenerated message
|
|
126
|
+
# 2024-04-04 CS Add context_type to autoMsg() and sendSingle() to match frontend message-to-depositor drop-down list
|
|
126
127
|
##
|
|
127
128
|
"""
|
|
128
129
|
Class to manage persistence/retrieval of messaging data
|
|
@@ -1253,8 +1254,10 @@ class MessagingIo(object):
|
|
|
1253
1254
|
|
|
1254
1255
|
def autoMsg(self, p_depIdList, p_tmpltType="release-publ", p_isEmdbEntry=False, p_sender="auto"):
|
|
1255
1256
|
"""
|
|
1256
|
-
|
|
1257
|
-
|
|
1257
|
+
Send message based on template type p_tmpltType, invoked by 'auto' batch operation rather than frontend UI selection.
|
|
1258
|
+
Originally deleveloped as a method to enable release message to be automatically sent by another server-side
|
|
1259
|
+
python module (e.g. Release module) (i.e. as opposed to being invoked via URL request).
|
|
1260
|
+
The message is then archived in notes-from-annotator.
|
|
1258
1261
|
|
|
1259
1262
|
:Helpers:
|
|
1260
1263
|
|
|
@@ -1276,7 +1279,7 @@ class MessagingIo(object):
|
|
|
1276
1279
|
#
|
|
1277
1280
|
rtrnDict = {}
|
|
1278
1281
|
#
|
|
1279
|
-
contextType =
|
|
1282
|
+
contextType = p_tmpltType # CS 2024-04-04 record message type
|
|
1280
1283
|
contextVal = None
|
|
1281
1284
|
#
|
|
1282
1285
|
# Added by ZF
|
|
@@ -1305,7 +1308,7 @@ class MessagingIo(object):
|
|
|
1305
1308
|
self.__reqObj.setValue("em_map_and_model", "false")
|
|
1306
1309
|
|
|
1307
1310
|
useAnnotatorName = False
|
|
1308
|
-
if p_tmpltType in ["remind-unlocked", "
|
|
1311
|
+
if p_tmpltType in ["remind-unlocked", "approval-impl"]: # CS 2024-04-04 change implicit-approved to approval-impl to match frontend drop-down
|
|
1309
1312
|
useAnnotatorName = True
|
|
1310
1313
|
|
|
1311
1314
|
# Trigger lookup of annotator initial to name if desired by template
|
|
@@ -1374,13 +1377,13 @@ class MessagingIo(object):
|
|
|
1374
1377
|
# Need all ids
|
|
1375
1378
|
accstr = templateDict["accession_ids"]
|
|
1376
1379
|
subject = "ARCHIVED: Please attend to your unlocked deposition session - " + accstr
|
|
1377
|
-
elif p_tmpltType == "implicit-approved
|
|
1380
|
+
elif p_tmpltType == "approval-impl": # CS 2024-04-04 change implicit-approved to approval-impl to match frontend drop-down
|
|
1378
1381
|
msgTmplt = MessagingTemplates.msgTmplt_approvalImplicit_em if p_isEmdbEntry else MessagingTemplates.msgTmplt_approvalImplicit
|
|
1379
1382
|
attachFiles = False
|
|
1380
1383
|
# Need all ids
|
|
1381
1384
|
accstr = templateDict["accession_ids"]
|
|
1382
1385
|
subject = "Implicit Approval of Your Structure - " + accstr
|
|
1383
|
-
elif p_tmpltType == "explicit-approved
|
|
1386
|
+
elif p_tmpltType == "approval-expl": # CS 2024-04-04 change explicit-approved to approval-expl to match frontend drop-down
|
|
1384
1387
|
msgTmplt = MessagingTemplates.msgTmplt_approvalExplicit_em if p_isEmdbEntry else MessagingTemplates.msgTmplt_approvalExplicit
|
|
1385
1388
|
attachFiles = False
|
|
1386
1389
|
# Need all ids
|
|
@@ -1398,7 +1401,7 @@ class MessagingIo(object):
|
|
|
1398
1401
|
msgTmplt = MessagingTemplates.msgTmplt_obsolete_model
|
|
1399
1402
|
subject = "Obsoletion of " + templateDict["obs_ids"]
|
|
1400
1403
|
attachFiles = False
|
|
1401
|
-
elif p_tmpltType == "remind-feedback
|
|
1404
|
+
elif p_tmpltType == "reminder": # CS 2024-04-04 change type from remind-feedback to reminder to match frontend drop-down
|
|
1402
1405
|
msgTmplt = MessagingTemplates.msgTmplt_reminder_em if p_isEmdbEntry else MessagingTemplates.msgTmplt_reminder
|
|
1403
1406
|
attachFiles = False
|
|
1404
1407
|
isNote = True
|
|
@@ -1473,8 +1476,19 @@ class MessagingIo(object):
|
|
|
1473
1476
|
#
|
|
1474
1477
|
return rtrnDict
|
|
1475
1478
|
|
|
1476
|
-
def sendSingle(self, depId, subject, msg, p_sender="auto", p_testemail=None):
|
|
1477
|
-
"""Sends a single message for depId with subject and msg.
|
|
1479
|
+
def sendSingle(self, depId, subject, msg, p_sender="auto", p_testemail=None, p_tmpltType="other"): # CS 2024-04-04 add p_tmpltType arg
|
|
1480
|
+
"""Sends a single message for depId with subject and msg. If p_testemail is set - will send notification there
|
|
1481
|
+
Different from autoMsg, this function sends customized message pre-composed and passed by subject and msg args.
|
|
1482
|
+
Although template type p_tmpltType is an arg, the message doesn't base on the template type which is only provided for record.
|
|
1483
|
+
The message is then archived in notes-from-annotator.
|
|
1484
|
+
The function is invoked by programmatic process rather than frontend UI selection including the following:
|
|
1485
|
+
(1) WFM manager use the function to send confirmation message
|
|
1486
|
+
(2) AutoMessage uses this to send auto messages
|
|
1487
|
+
(3) OnholdEntryReminder
|
|
1488
|
+
(4) SessionExpiringNotice
|
|
1489
|
+
(5) CitationRequest
|
|
1490
|
+
|
|
1491
|
+
"""
|
|
1478
1492
|
logger.info("Depid %s", depId)
|
|
1479
1493
|
logger.info("Subject %s", subject)
|
|
1480
1494
|
logger.info("Message %s", msg)
|
|
@@ -1497,7 +1511,7 @@ class MessagingIo(object):
|
|
|
1497
1511
|
# We are archiving notes
|
|
1498
1512
|
isNote = True
|
|
1499
1513
|
|
|
1500
|
-
contextType =
|
|
1514
|
+
contextType = p_tmpltType # CS 2024-04-04 record message type, following frontend message-to-depositor drop-down list, default at "other"
|
|
1501
1515
|
contextVal = None
|
|
1502
1516
|
|
|
1503
1517
|
messageDict = {
|
{wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/util/AutoMessage.py
RENAMED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# Update:
|
|
6
6
|
"""
|
|
7
7
|
Support for automatic scripts to send template drive email messages and archive in normal message stream/notes
|
|
8
|
-
|
|
8
|
+
Auto messages are archived in notes-from-annotator
|
|
9
9
|
|
|
10
10
|
"""
|
|
11
11
|
__docformat__ = "restructuredtext en"
|
|
@@ -61,13 +61,13 @@ class AutoMessage(object):
|
|
|
61
61
|
|
|
62
62
|
def sendRemindFeedback(self, depidlist):
|
|
63
63
|
""" Sends a reminder that depositor has not responded to validation report """
|
|
64
|
-
self._sendReminderBulk(depidlist, p_tmplt="
|
|
64
|
+
self._sendReminderBulk(depidlist, p_tmplt="reminder")
|
|
65
65
|
|
|
66
66
|
def sendImplicitApproved(self, depidlist):
|
|
67
|
-
self._sendReminderBulk(depidlist, p_tmplt="implicit-approved
|
|
67
|
+
self._sendReminderBulk(depidlist, p_tmplt="approval-impl") # CS 2024-04-04 change implicit-approved to approval-impl to match frontend drop-down
|
|
68
68
|
|
|
69
69
|
def sendExplicitApproved(self, depidlist):
|
|
70
|
-
self._sendReminderBulk(depidlist, p_tmplt="explicit-approved
|
|
70
|
+
self._sendReminderBulk(depidlist, p_tmplt="approval-expl") # CS 2024-04-04 change explicit-approved to approval-expl to match frontend drop-down
|
|
71
71
|
|
|
72
72
|
def _sendReminderBulk(self, depidlist, p_tmplt):
|
|
73
73
|
"""Sends the bulk messages - handling setting EM flag"""
|
|
@@ -111,7 +111,7 @@ class AutoMessage(object):
|
|
|
111
111
|
pdbents.append(depid)
|
|
112
112
|
return (pdbents, ements)
|
|
113
113
|
|
|
114
|
-
def sendSingleMessage(self, depid, subject, msg, testemail=None):
|
|
114
|
+
def sendSingleMessage(self, depid, subject, msg, testemail=None, p_tmpltType="other"):
|
|
115
115
|
"""Sends a message to depid, without using templates. No attachments.
|
|
116
116
|
|
|
117
117
|
Args:
|
|
@@ -119,14 +119,15 @@ class AutoMessage(object):
|
|
|
119
119
|
subject (str): Subject string for message
|
|
120
120
|
msg (str): Multiline message to send
|
|
121
121
|
testemail (str): If set overrides entry recipients for testing
|
|
122
|
+
p_tmpltType as template type
|
|
122
123
|
|
|
123
124
|
returns:
|
|
124
125
|
bool: True if successfule or else false
|
|
125
126
|
"""
|
|
126
127
|
|
|
127
128
|
mio = self.__getmsgio()
|
|
128
|
-
ret = mio.sendSingle(depid, subject, msg, p_testemail=testemail)
|
|
129
|
-
ret = True
|
|
129
|
+
ret = mio.sendSingle(depid, subject, msg, p_testemail=testemail, p_tmpltType=p_tmpltType)
|
|
130
|
+
# ret = True
|
|
130
131
|
return ret
|
|
131
132
|
|
|
132
133
|
def tagMessageStatus(self, depId, msgidlist, actionReqd="N", forReleaseFlg="N"):
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
# Update:
|
|
6
6
|
# 2023-11-10 CS Refactor code to add general process to parse message file; Add functions to retrieve datetime of last messages of various type.
|
|
7
7
|
# 2023-11-23 EP Add getApprovalNoCorrectSubjects() and getPendingDepositorMessages()
|
|
8
|
+
# 2024-04-04 CS Use context_type and context_value to find target message, and default to subject/title parsing as was used previously.
|
|
8
9
|
#
|
|
9
10
|
##
|
|
10
11
|
"""
|
|
@@ -128,6 +129,93 @@ class ExtractMessage(object):
|
|
|
128
129
|
logger.error("Error processing message file for %s, %s", self.__depid, e)
|
|
129
130
|
return ret
|
|
130
131
|
|
|
132
|
+
# CS 2024-04-04 add search below by context_type
|
|
133
|
+
def __selectLastMsgByContextType(self, l_context_type_to_search):
|
|
134
|
+
""" return datetime of the lastest message based on context type
|
|
135
|
+
|
|
136
|
+
input: arg l_context_type_to_search is a list of the context types to search for.
|
|
137
|
+
list is used because some searches invole multiple context_type, e.g. ["release-publ", "release-nopubl"]
|
|
138
|
+
|
|
139
|
+
output: return datetime
|
|
140
|
+
|
|
141
|
+
"""
|
|
142
|
+
ret = None
|
|
143
|
+
dc0 = self.__lc[0]
|
|
144
|
+
catObj = dc0.getObj("pdbx_deposition_message_info")
|
|
145
|
+
if catObj is None:
|
|
146
|
+
logger.warning("cannot find pdbx_deposition_message_info category in the message file for %s", self.__depid)
|
|
147
|
+
return None
|
|
148
|
+
else:
|
|
149
|
+
itDict = {}
|
|
150
|
+
itNameList = catObj.getItemNameList()
|
|
151
|
+
for idxIt, itName in enumerate(itNameList):
|
|
152
|
+
itDict[str(itName).lower()] = idxIt
|
|
153
|
+
#
|
|
154
|
+
idxOrdinalId = itDict["_pdbx_deposition_message_info.ordinal_id"]
|
|
155
|
+
idxLastCommDate = itDict["_pdbx_deposition_message_info.timestamp"]
|
|
156
|
+
idxContextType = itDict["_pdbx_deposition_message_info.context_type"]
|
|
157
|
+
|
|
158
|
+
maxOrdId = 0
|
|
159
|
+
for row in catObj.getRowList():
|
|
160
|
+
try:
|
|
161
|
+
ordinalId = int(row[idxOrdinalId])
|
|
162
|
+
context_type_recorded = row[idxContextType]
|
|
163
|
+
|
|
164
|
+
if context_type_recorded in l_context_type_to_search:
|
|
165
|
+
if ordinalId > maxOrdId:
|
|
166
|
+
maxOrdId = ordinalId
|
|
167
|
+
ret = self.convertStrToDatetime(str(row[idxLastCommDate]))
|
|
168
|
+
|
|
169
|
+
except Exception as e:
|
|
170
|
+
logger.error("Error processing message file for %s, %s", self.__depid, e)
|
|
171
|
+
return ret
|
|
172
|
+
|
|
173
|
+
# CS 2024-04-04 add validation letter search below by context_type/context_value
|
|
174
|
+
def __getLastValidationByContextType(self):
|
|
175
|
+
"""Returns (datetime, major issue) of the last time a validation was sent as determined by
|
|
176
|
+
context_type and context_value
|
|
177
|
+
"""
|
|
178
|
+
|
|
179
|
+
lastvalid = None
|
|
180
|
+
major = None
|
|
181
|
+
|
|
182
|
+
dc0 = self.__lc[0]
|
|
183
|
+
catObj = dc0.getObj("pdbx_deposition_message_info")
|
|
184
|
+
if catObj is None:
|
|
185
|
+
logger.warning("cannot find pdbx_deposition_message_info category in the message file for %s", self.__depid)
|
|
186
|
+
return None
|
|
187
|
+
else:
|
|
188
|
+
itDict = {}
|
|
189
|
+
itNameList = catObj.getItemNameList()
|
|
190
|
+
for idxIt, itName in enumerate(itNameList):
|
|
191
|
+
itDict[str(itName).lower()] = idxIt
|
|
192
|
+
#
|
|
193
|
+
idxOrdinalId = itDict["_pdbx_deposition_message_info.ordinal_id"]
|
|
194
|
+
idxLastCommDate = itDict["_pdbx_deposition_message_info.timestamp"]
|
|
195
|
+
idxContextType = itDict["_pdbx_deposition_message_info.context_type"]
|
|
196
|
+
idxContextValue = itDict["_pdbx_deposition_message_info.context_value"]
|
|
197
|
+
|
|
198
|
+
maxOrdId = 0
|
|
199
|
+
for row in catObj.getRowList():
|
|
200
|
+
try:
|
|
201
|
+
ordinalId = int(row[idxOrdinalId])
|
|
202
|
+
context_type_recorded = row[idxContextType]
|
|
203
|
+
context_value_recorded = row[idxContextValue]
|
|
204
|
+
|
|
205
|
+
if context_type_recorded == "vldtn":
|
|
206
|
+
if ordinalId > maxOrdId:
|
|
207
|
+
maxOrdId = ordinalId
|
|
208
|
+
lastvalid = self.convertStrToDatetime(str(row[idxLastCommDate]))
|
|
209
|
+
if context_value_recorded == "major-issue-in-validation":
|
|
210
|
+
major = True
|
|
211
|
+
else:
|
|
212
|
+
major = False
|
|
213
|
+
|
|
214
|
+
except Exception as e:
|
|
215
|
+
logger.error("Error processing message file for %s, %s", self.__depid, e)
|
|
216
|
+
|
|
217
|
+
return (lastvalid, major)
|
|
218
|
+
|
|
131
219
|
def convertStrToDatetime(self, s_datetime):
|
|
132
220
|
return datetime.datetime.strptime(str(s_datetime), "%Y-%m-%d %H:%M:%S")
|
|
133
221
|
|
|
@@ -174,7 +262,11 @@ class ExtractMessage(object):
|
|
|
174
262
|
ret = None
|
|
175
263
|
self.__readMsgFile(depid, contentType="notes-from-annotator", b_use_cache=b_use_cache, test_folder=test_folder)
|
|
176
264
|
if len(self.__lc) >= 1:
|
|
177
|
-
|
|
265
|
+
ret_by_context_type = self.__selectLastMsgByContextType(["reminder"]) # CS 2024-04-04 search by context_type first
|
|
266
|
+
if ret_by_context_type:
|
|
267
|
+
ret = ret_by_context_type
|
|
268
|
+
else:
|
|
269
|
+
ret = self.__selectLastMsgByTitlePhrase(phrase='Still awaiting feedback for')
|
|
178
270
|
else:
|
|
179
271
|
logger.info("Deposition %s empty message file", depid)
|
|
180
272
|
|
|
@@ -187,7 +279,11 @@ class ExtractMessage(object):
|
|
|
187
279
|
ret = None
|
|
188
280
|
self.__readMsgFile(depid, contentType="messages-to-depositor", b_use_cache=b_use_cache, test_folder=test_folder)
|
|
189
281
|
if len(self.__lc) >= 1:
|
|
190
|
-
|
|
282
|
+
ret_by_context_type = self.__selectLastMsgByContextType(["reminder"]) # CS 2024-04-04 search by context_type first
|
|
283
|
+
if ret_by_context_type:
|
|
284
|
+
ret = ret_by_context_type
|
|
285
|
+
else:
|
|
286
|
+
ret = self.__selectLastMsgByTitlePhrase(phrase='Still awaiting feedback for')
|
|
191
287
|
else:
|
|
192
288
|
logger.info("Deposition %s empty message file", depid)
|
|
193
289
|
|
|
@@ -199,7 +295,11 @@ class ExtractMessage(object):
|
|
|
199
295
|
ret = None
|
|
200
296
|
self.__readMsgFile(depid, contentType="messages-to-depositor", b_use_cache=b_use_cache, test_folder=test_folder)
|
|
201
297
|
if len(self.__lc) >= 1:
|
|
202
|
-
|
|
298
|
+
ret_by_context_type = self.__selectLastMsgByContextType(["release-publ", "release-nopubl"]) # CS 2024-04-04 search by context_type first
|
|
299
|
+
if ret_by_context_type:
|
|
300
|
+
ret = ret_by_context_type
|
|
301
|
+
else:
|
|
302
|
+
ret = self.__selectLastMsgByTitlePhrase(phrase='Release of')
|
|
203
303
|
else:
|
|
204
304
|
logger.info("Deposition %s empty message file", depid)
|
|
205
305
|
|
|
@@ -258,14 +358,16 @@ class ExtractMessage(object):
|
|
|
258
358
|
idxOrdinalId = itDict["_pdbx_deposition_message_info.ordinal_id"]
|
|
259
359
|
idxLastCommDate = itDict["_pdbx_deposition_message_info.timestamp"]
|
|
260
360
|
idxMsgSubj = itDict["_pdbx_deposition_message_info.message_subject"]
|
|
361
|
+
idxContextType = itDict["_pdbx_deposition_message_info.context_type"]
|
|
261
362
|
|
|
262
363
|
maxUnlockOrdId = 0
|
|
263
364
|
for row in catObj.getRowList():
|
|
264
365
|
try:
|
|
265
366
|
ordinalId = int(row[idxOrdinalId])
|
|
266
367
|
msgsubj = row[idxMsgSubj]
|
|
368
|
+
context_type_recorded = row[idxContextType]
|
|
267
369
|
|
|
268
|
-
if msgsubj == "System Unlocked":
|
|
370
|
+
if context_type_recorded == "system-unlocked" or msgsubj == "System Unlocked":
|
|
269
371
|
if ordinalId > maxUnlockOrdId:
|
|
270
372
|
maxUnlockOrdId = ordinalId
|
|
271
373
|
ret = str(row[idxLastCommDate])
|
|
@@ -308,6 +410,14 @@ class ExtractMessage(object):
|
|
|
308
410
|
self.__readMsgFile(depid, contentType="messages-to-depositor", b_use_cache=b_use_cache, test_folder=test_folder)
|
|
309
411
|
|
|
310
412
|
if len(self.__lc) >= 1:
|
|
413
|
+
logger.info("start searching for last validation letter by context_type")
|
|
414
|
+
(lastvalid, major) = self.__getLastValidationByContextType() # CS 2024-04-04 first search by context_type/context_value
|
|
415
|
+
if lastvalid:
|
|
416
|
+
logger.info("found last validation letter by context_type")
|
|
417
|
+
return (lastvalid, major) # return if find message by context_type/context_value
|
|
418
|
+
|
|
419
|
+
logger.info("fail to find last validation letter by context_type, default to search by subject/text parsing")
|
|
420
|
+
|
|
311
421
|
c0 = self.__lc[0]
|
|
312
422
|
catObj = c0.getObj("pdbx_deposition_message_file_reference")
|
|
313
423
|
if catObj is None:
|
|
@@ -394,8 +504,8 @@ class ExtractMessage(object):
|
|
|
394
504
|
else:
|
|
395
505
|
logger.debug("Deposition %s empty message file", depid)
|
|
396
506
|
|
|
507
|
+
logger.info("finished searching for last validation letter by subject/text parsing")
|
|
397
508
|
logger.info("Returning (%s, %s)", lastvalid, major)
|
|
398
|
-
|
|
399
509
|
return (lastvalid, major)
|
|
400
510
|
|
|
401
511
|
def _majorValidation(self, msgText):
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
# notes archived via BMRB emails (vs. standard annotator authored notes).
|
|
37
37
|
# 2016-09-14 ZF Added __checkGroupDeposition() function to support for group deposition
|
|
38
38
|
# 2023-11-20 EP Added __checkAnyApprovalFlags() and set approriate database flags if set
|
|
39
|
+
# 2024-04-04 CS Add process on context_type/context_value of message-to-depositor recorded by frontend JavaScript and passed here through wsgi message submit URL
|
|
39
40
|
##
|
|
40
41
|
"""
|
|
41
42
|
wwPDB Messaging web request and response processing modules.
|
|
@@ -60,6 +61,7 @@ import os
|
|
|
60
61
|
import sys
|
|
61
62
|
import time
|
|
62
63
|
import traceback
|
|
64
|
+
import re
|
|
63
65
|
|
|
64
66
|
try:
|
|
65
67
|
from html import unescape
|
|
@@ -1345,7 +1347,15 @@ class MessagingWebAppWorker(object):
|
|
|
1345
1347
|
self.__getSession()
|
|
1346
1348
|
#
|
|
1347
1349
|
rtrnDict = {}
|
|
1348
|
-
|
|
1350
|
+
|
|
1351
|
+
# CS 2024-04-04 start processing context_value, add "major-issue-in-validation" if frontend submitted validation message contains major issue
|
|
1352
|
+
if self.__reqObj.getValue("context_type") == "vldtn":
|
|
1353
|
+
if not self.__reqObj.getValue("context_value").strip():
|
|
1354
|
+
message_text = self.__reqObj.getValue("message")
|
|
1355
|
+
if re.search("major issue", message_text.lower()) and re.search("outstanding issue", message_text.lower()):
|
|
1356
|
+
self.__reqObj.setValue("context_value", "major-issue-in-validation")
|
|
1357
|
+
# CS 2024-04-04 end
|
|
1358
|
+
|
|
1349
1359
|
self.__reqObj.setReturnFormat(return_format="json")
|
|
1350
1360
|
self.__reqObj.setValue("message_state", p_msgState) # setting here for downstream processing, used only for processing purposes
|
|
1351
1361
|
# NOTE: this field is not part of the PdbxMessage data structure, and thus is not persisted to data file.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/depict/__init__.py
RENAMED
|
File without changes
|
{wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/io/DateUtil.py
RENAMED
|
File without changes
|
{wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/io/EmHeaderUtils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/io/__init__.py
RENAMED
|
File without changes
|
{wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/models/Message.py
RENAMED
|
File without changes
|
{wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/models/__init__.py
RENAMED
|
File without changes
|
{wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/util/__init__.py
RENAMED
|
File without changes
|
{wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/webapp/__init__.py
RENAMED
|
File without changes
|
{wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb/apps/msgmodule/webapp/wsgi.py
RENAMED
|
File without changes
|
{wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb.apps.msgmodule.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb.apps.msgmodule.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{wwpdb.apps.msgmodule-0.175 → wwpdb.apps.msgmodule-0.176}/wwpdb.apps.msgmodule.egg-info/requires.txt
RENAMED
|
File without changes
|
|
File without changes
|