88import os
99import uuid
1010import xml .etree .cElementTree as ETree
11- import zipfile
1211from collections .abc import Sequence
1312from typing import List
1413
15- from django . core . exceptions import ObjectDoesNotExist
14+ from janeway_ftp import helpers as deposit_helpers
1615
1716import plugins .editorial_manager_transfer_service .consts as consts
1817import plugins .editorial_manager_transfer_service .logger_messages as logger_messages
1918from core .models import File
2019from journal .models import Journal
20+ from plugins .editorial_manager_transfer_service .enums .report_state import ReportState
2121from plugins .editorial_manager_transfer_service .enums .transfer_log_message_type import TransferLogMessageType
2222from plugins .editorial_manager_transfer_service .models import TransferLogs
23+ from plugins .editorial_manager_transfer_service .utils .jats import get_xml_license_code , generate_jats_metadata
24+ from plugins .editorial_manager_transfer_service .utils .settings import get_license_code , get_submission_partner_code , \
25+ get_journal_code
26+ from plugins .editorial_manager_transfer_service .utils .transfer_report import get_or_create_transfer_report , \
27+ resolve_transfer_report
28+ from plugins .production_transporter .utilities import data_fetch
29+ from plugins .production_transporter .utilities .file_utils import copy_files_to_temp_deposit_folder
2330from submission .models import Article
24- from utils import setting_handler
2531from utils .logger import get_logger
2632
2733logger = get_logger (__name__ )
@@ -55,6 +61,8 @@ def __init__(self, janeway_journal_code: str, article_id: int | None) -> None:
5561 self .article : Article | None = None
5662 self .journal : Journal | None = None
5763 self .export_folder : str | None = None
64+ self .xml_filepath : str | None = None
65+ self .__temp_folder : str | None = None
5866
5967 # Gets the journal
6068 self .journal : Journal | None = self .__fetch_journal (janeway_journal_code )
@@ -74,6 +82,9 @@ def __init__(self, janeway_journal_code: str, article_id: int | None) -> None:
7482 return
7583 self .export_folder = export_folders
7684
85+ # Creates or fetches a report to track where this process is.
86+ self .transfer_report = get_or_create_transfer_report (self .journal , self .article )
87+
7788 # Start export process
7889 self .__create_export_file ()
7990
@@ -108,12 +119,17 @@ def __create_export_file(self):
108119 self .in_error_state = True
109120 return
110121
111- # TODO: Attempt to create the metadata file.
112- # metadata_file: File | None = self.__create_metadata_file(self.article)
113- # if metadata_file is None:
114- # logger.error(logger_messages.process_failed_fetching_metadata(self.article_id))
115- # self.in_error_state = True
116- # return
122+ prefix : str = "{0}_{1}" .format (self .get_submission_partner_code (), uuid .uuid4 ())
123+
124+ self .zip_filepath : str = os .path .join (self .export_folder , "{0}.zip" .format (prefix ))
125+ self .__temp_folder = os .path .join (self .export_folder , "{0}" .format (prefix ))
126+ os .makedirs (self .__temp_folder , exist_ok = True )
127+
128+ # Attempt to get the metadata file.
129+ if self .__get_xml_filepath () is None :
130+ logger .error (logger_messages .process_failed_fetching_metadata (self .article_id ))
131+ self .in_error_state = True
132+ return
117133
118134 # Attempt to fetch the article files.
119135 article_files : Sequence [File ] = self .__fetch_article_files (self .article )
@@ -122,28 +138,26 @@ def __create_export_file(self):
122138 self .in_error_state = True
123139 return
124140
125- prefix : str = "{0}_{1}" . format ( self . get_submission_partner_code (), uuid . uuid4 ())
141+ filenames : List [ str ] = []
126142
127- self .zip_filepath : str = os .path .join (self .export_folder , "{0}.zip" .format (prefix ))
128- with zipfile .ZipFile (self .zip_filepath , "w" ) as zipf :
129- # TODO: zipf.write(metadata_file.get_file_path(self.article))
130- for article_file in article_files :
131- zipf .write (article_file .get_file_path (self .article ))
132- filenames : Sequence [str ] = zipf .namelist ()
133- zipf .close ()
143+ # Move files to temp folder.
144+ for article_file in article_files :
145+ filepath : str = article_file .get_file_path (self .article )
146+ copy_files_to_temp_deposit_folder (filepath , self .__temp_folder )
147+ filenames .append (os .path .basename (filepath ))
134148
135- # Remove the manuscript
149+ deposit_helpers . zip_temp_folder ( temp_folder = self . __temp_folder )
136150
137- # TODO: Remove below and replace with 'self.__create_go_xml_file(metadata_file.uuid_filename, filenames, prefix)'
138- self .__create_go_xml_file ("fake name" , filenames , prefix )
151+ # Remove the manuscript
152+ self .__create_go_xml_file (os . path . basename ( self . __get_xml_filepath ()) , filenames , prefix )
139153
140154 def get_license_code (self ) -> str :
141155 """
142156 Gets the license code for exporting files.
143157 :return: The license code or None, if the process failed.
144158 """
145159 if not self .__license_code :
146- self .__license_code : str = self .get_setting ( consts . PLUGIN_SETTINGS_LICENSE_CODE )
160+ self .__license_code : str = get_license_code ( self .journal )
147161 return self .__license_code
148162
149163 def get_journal_code (self ) -> str :
@@ -152,7 +166,7 @@ def get_journal_code(self) -> str:
152166 :return: The journal code or None, if the process failed.
153167 """
154168 if not self .__journal_code :
155- self .__journal_code : str = self .get_setting ( consts . PLUGIN_SETTINGS_JOURNAL_CODE )
169+ self .__journal_code : str = get_journal_code ( self .journal )
156170 return self .__journal_code
157171
158172 def get_submission_partner_code (self ) -> str :
@@ -161,7 +175,7 @@ def get_submission_partner_code(self) -> str:
161175 :return: The submission partner code or None, if the process failed.
162176 """
163177 if not self .__submission_partner_code :
164- self .__submission_partner_code : str = self .get_setting ( consts . PLUGIN_SETTINGS_SUBMISSION_PARTNER_CODE )
178+ self .__submission_partner_code : str = get_submission_partner_code ( self .journal )
165179 return self .__submission_partner_code
166180
167181 def can_export (self ) -> bool :
@@ -176,20 +190,6 @@ def can_export(self) -> bool:
176190 self .get_journal_code () is not None and
177191 self .get_submission_partner_code () is not None )
178192
179- def get_setting (self , setting_name : str ) -> str :
180- """
181- Gets the setting for the given setting name.
182- :param setting_name: The name of the setting to get the value for.
183- :return: The value for the given setting or a blank string, if the process failed.
184- """
185- try :
186- return setting_handler .get_setting (setting_group_name = consts .PLUGIN_SETTINGS_GROUP_NAME ,
187- setting_name = setting_name , journal = self .journal , ).processed_value
188- except ObjectDoesNotExist as e :
189- self .log_error ("Could not get the following setting, '{0}'" .format (setting_name ), e )
190- self .in_error_state = True
191- return ""
192-
193193 def __create_go_xml_file (self , metadata_filename : str , article_filenames : Sequence [str ], filename : str ):
194194 """
195195 Creates the go xml file for the export process for Editorial Manager.
@@ -219,8 +219,7 @@ def __create_go_xml_file(self, metadata_filename: str, article_filenames: Sequen
219219 parameters : ETree .Element = ETree .SubElement (header , consts .GO_FILE_ELEMENT_TAG_PARAMETERS )
220220 parameter : ETree .Element = ETree .SubElement (parameters , consts .GO_FILE_ELEMENT_TAG_PARAMETER )
221221 parameter .set (consts .GO_FILE_ATTRIBUTE_ELEMENT_NAME_KEY , consts .GO_FILE_PARAMETER_ELEMENT_NAME_VALUE )
222- parameter .set (consts .GO_FILE_PARAMETER_ELEMENT_VALUE_KEY ,
223- "{0}_{1}" .format (self .get_submission_partner_code (), self .get_license_code ()))
222+ parameter .set (consts .GO_FILE_PARAMETER_ELEMENT_VALUE_KEY , get_xml_license_code (self .journal ))
224223
225224 # Begin the filegroup.
226225 filegroup : ETree .Element = ETree .SubElement (go , consts .GO_FILE_ELEMENT_TAG_FILEGROUP )
@@ -239,13 +238,20 @@ def __create_go_xml_file(self, metadata_filename: str, article_filenames: Sequen
239238 self .go_filepath = os .path .join (self .export_folder , "{0}.go.xml" .format (filename ))
240239 tree .write (self .go_filepath )
241240
242- def __create_metadata_file (self , article : Article ) -> File | None :
241+ def __get_xml_filepath (self ) -> str | None :
243242 """
244243 Creates the metadata file based on the given article.
245- :param article: The article to convert to JATS.
246- :return:
244+ :return:The filepath to the JATS XML file.
247245 """
248- pass
246+ if not self .xml_filepath :
247+ filepath = generate_jats_metadata (self .journal , self .article , self .__temp_folder )
248+
249+ if not filepath :
250+ self .in_error_state = True
251+ return None
252+
253+ self .xml_filepath = filepath
254+ return self .xml_filepath
249255
250256 def __fetch_article (self , journal : Journal | None , article_id : int | None ) -> Article | None :
251257 """
@@ -254,22 +260,14 @@ def __fetch_article(self, journal: Journal | None, article_id: int | None) -> Ar
254260 :param article_id: The ID of the article.
255261 :return: The article object with the given article ID.
256262 """
257- # If no article ID or journal, return an error.
258- if not article_id or article_id <= 0 :
259- self .log_error (logger_messages .process_failed_no_article_id_provided ())
260- self .in_error_state = True
261- return None
262-
263- article : Article | None = None
264-
265263 logger .debug (logger_messages .process_fetching_article (article_id ))
266- try :
267- article = Article .get_article (journal , "id" , article_id )
268- logger .debug (logger_messages .process_finished_fetching_article (article_id ))
269- except Article .DoesNotExist as e :
270- self .log_error (logger_messages .process_failed_fetching_article (article_id ), e )
264+
265+ article : Article | None = data_fetch .fetch_article (journal , article_id )
266+ if article is None :
271267 self .in_error_state = True
268+ return None
272269
270+ logger .debug (logger_messages .process_finished_fetching_article (article_id ))
273271 return article
274272
275273 def __fetch_journal (self , janeway_journal_code : str | None ) -> Journal | None :
@@ -278,43 +276,51 @@ def __fetch_journal(self, janeway_journal_code: str | None) -> Journal | None:
278276 :param janeway_journal_code: The code of the Janeway journal to fetch.
279277 :return: The journal object with the given Janeway journal code, if there is one. None otherwise.
280278 """
281- # If no journal code, return an error.
282- if not janeway_journal_code or len (janeway_journal_code ) <= 0 :
283- self .log_error (logger_messages .process_failed_no_janeway_journal_code_provided ())
284- self .in_error_state = True
285- return None
286-
287- journal : Journal | None = None
288-
289279 # Attempt to get the journal.
290280 logger .debug (logger_messages .process_fetching_journal (janeway_journal_code ))
291- try :
292- journal = Journal .objects .get (code = janeway_journal_code )
293- logger .debug (logger_messages .process_finished_fetching_journal (janeway_journal_code ))
294- except Journal .DoesNotExist as e :
295- self .log_error (logger_messages .process_failed_fetching_journal (janeway_journal_code ), e )
281+
282+ journal : Journal | None = data_fetch .fetch_journal_data (janeway_journal_code )
283+ if journal is None :
296284 self .in_error_state = True
285+ return None
286+
287+ logger .debug (logger_messages .process_finished_fetching_journal (janeway_journal_code ))
297288
298289 return journal
299290
300- def log_error (self , message : str , error : Exception = None ) -> None :
291+ def log_error (self , message : str , error : Exception = None ,
292+ stage : ReportState = ReportState .FAILED_BUNDLING ) -> None :
301293 """
302294 Logs the given error message in both the database and plaintext logs.
303295 :param message: The message to log.
304296 :param error: The exception, if there is one.
297+ :param stage: Specify which stage this transfer is in.
305298 """
306299 logger .exception (error )
307300 logger .error (message )
308- TransferLogs .objects .create (journal = self .journal , article = self .article , message = message ,
301+ if self .transfer_report .report_state != stage :
302+ self .transfer_report .report_state = stage
303+ self .transfer_report .save ()
304+ TransferLogs .objects .create (report = self .transfer_report , journal = self .journal , article = self .article ,
305+ message = message ,
309306 message_type = TransferLogMessageType .EXPORT , success = False )
310307
311- def log_success (self ) -> None :
308+ def log_success_go_file (self ) -> None :
309+ """
310+ Logs a success message in both the database and plaintext logs.
311+ """
312+ TransferLogs .objects .create (report = self .transfer_report , journal = self .journal , article = self .article ,
313+ message = logger_messages .export_go_file_process_succeeded (self .article_id ),
314+ message_type = TransferLogMessageType .EXPORT , success = True )
315+
316+ def log_success_zip_file (self ) -> None :
312317 """
313318 Logs a success message in both the database and plaintext logs.
314319 """
315- TransferLogs .objects .create (journal = self .journal , article = self .article ,
316- message = logger_messages .export_process_succeeded (self .article_id ),
320+ TransferLogs .objects .create (report = self . transfer_report , journal = self .journal , article = self .article ,
321+ message = logger_messages .export_zip_file_process_succeeded (self .article_id ),
317322 message_type = TransferLogMessageType .EXPORT , success = True )
323+ resolve_transfer_report (self .transfer_report )
318324
319325 @staticmethod
320326 def __fetch_article_files (article : Article ) -> List [File ]:
0 commit comments