1616from collective .dms .scanbehavior .behaviors .behaviors import IScanFields
1717from collective .documentgenerator import _ as _dg
1818from collective .documentgenerator .utils import convert_and_save_file
19+ from collective .documentgenerator .utils import convert_odt
1920from collective .documentgenerator .utils import get_original_template
2021from collective .documentgenerator .utils import odfsplit
2122from collective .documentgenerator .utils import update_dict_with_validation
23+ from collective .documentviewer .convert import Converter
2224from collective .iconifiedcategory .adapter import CategorizedObjectInfoAdapter
2325from collective .iconifiedcategory .utils import get_category_object
2426from collective .iconifiedcategory .utils import update_categorized_elements
5052from imio .helpers .content import uuidToCatalogBrain
5153from imio .helpers .content import uuidToObject
5254from imio .helpers .emailer import validate_email_address
55+ from imio .helpers .pdf import merge_pdf
5356from imio .helpers .workflow import do_transitions
5457from imio .pm .wsclient .interfaces import ISendableAnnexesToPM
5558from imio .prettylink .adapters import PrettyLinkAdapter
6164from plone .app .contentmenu .menu import FactoriesSubMenuItem as OrigFactoriesSubMenuItem
6265from plone .app .contentmenu .menu import WorkflowMenu as OrigWorkflowMenu
6366from plone .app .contenttypes .indexers import _unicode_save_string_concat
67+ from plone .dexterity .utils import createContentInContainer
6468from plone .indexer import indexer
6569from plone .namedfile .file import NamedBlobFile
6670from plone .registry .interfaces import IRegistry
@@ -1617,8 +1621,11 @@ def approve_file(self, afile, userid, values=None, transition=None, c_a=None):
16171621 message = _ (
16181622 u"The file '${file}' has been approved by ${user}. However, there is/are yet ${nb} files "
16191623 u"to approve on this mail." ,
1620- mapping = {"file" : safe_unicode (afile .Title ()), "user" : safe_unicode (fullname ),
1621- "nb" : len (yet_to_approve )},
1624+ mapping = {
1625+ "file" : safe_unicode (afile .Title ()),
1626+ "user" : safe_unicode (fullname ),
1627+ "nb" : len (yet_to_approve ),
1628+ },
16221629 ),
16231630 request = request ,
16241631 type = "info" ,
@@ -1635,8 +1642,10 @@ def approve_file(self, afile, userid, values=None, transition=None, c_a=None):
16351642 self .context .reindexObjectSecurity () # to update local roles from adapter
16361643 message += u"Next approval number is ${nb}."
16371644 api .portal .show_message (
1638- message = _ (message , mapping = {"file" : safe_unicode (afile .Title ()), "user" : safe_unicode (fullname ),
1639- "nb" : c_a + 1 }),
1645+ message = _ (
1646+ message ,
1647+ mapping = {"file" : safe_unicode (afile .Title ()), "user" : safe_unicode (fullname ), "nb" : c_a + 1 },
1648+ ),
16401649 request = request ,
16411650 type = "info" ,
16421651 )
@@ -1714,6 +1723,31 @@ def unapprove_file(self, afile, signer_userid):
17141723
17151724 self .start_approval_process ()
17161725
1726+ def _render_download_template_to_pdf (self , download_template , download_url ):
1727+ """Render the download subtemplate (QR code page) to PDF bytes.
1728+
1729+ :param download_template: the POD template object to render
1730+ :param download_url: the URL to encode in the QR/barcode
1731+ :return: PDF bytes, or empty string on failure
1732+ """
1733+ helper_view = getMultiAdapter (
1734+ (self .context , self .context .REQUEST ),
1735+ name = "document_generation_helper_view" ,
1736+ )
1737+ helper_view .pod_template = download_template .UID ()
1738+ helper_view .output_format = "pdf"
1739+ gen_context = {
1740+ "context" : self .context ,
1741+ "portal" : api .portal .get (),
1742+ "view" : helper_view ,
1743+ "download_barcode" : generate_barcode (download_url ).read (),
1744+ "download_url" : download_url ,
1745+ "max_download_date" : get_max_download_date (None , adate = datetime .date .today ()),
1746+ "render_download_barcode" : True ,
1747+ }
1748+ template_file = NamedBlobFile (download_template .get_file ().data , filename = u"download_template.odt" )
1749+ return convert_odt (template_file , fmt = "pdf" , gen_context = gen_context )
1750+
17171751 def _create_pdf_file (self , orig_fobj , nbf , f_title , f_uid , file_index , session_file_uids ):
17181752 """Create a pdf version file.
17191753
@@ -1728,32 +1762,72 @@ def _create_pdf_file(self, orig_fobj, nbf, f_title, f_uid, file_index, session_f
17281762 new_filename = u"{}.pdf" .format (f_title )
17291763 if nbf .contentType == "application/pdf" :
17301764 pdf_file = orig_fobj
1765+ download_template = api .portal .get ().templates .om .get ("download_barcode" )
1766+ if download_template :
1767+ new_uid = uuid .uuid4 ().hex
1768+ dl_url , _ = get_file_download_url (new_uid , short_uid = get_suid_from_uuid (new_uid ))
1769+ sub_pdf_data = self ._render_download_template_to_pdf (download_template , dl_url )
1770+ if sub_pdf_data :
1771+ merged = merge_pdf (nbf .data , sub_pdf_data )
1772+ file_object = NamedBlobFile (merged , filename = safe_unicode (new_filename ))
1773+ pdf_file = createContentInContainer (
1774+ self .context ,
1775+ orig_fobj .portal_type ,
1776+ title = safe_unicode (new_filename ),
1777+ file = file_object ,
1778+ content_category = orig_fobj .content_category ,
1779+ scan_id = orig_fobj .scan_id ,
1780+ conv_from_uid = f_uid ,
1781+ ** {"_plone.uuid" : new_uid }
1782+ )
1783+ annot = IAnnotations (pdf_file )
1784+ annot ["documentgenerator" ] = {"conv_from_uid" : f_uid }
1785+ pdf_file .to_sign = True
1786+ pdf_file .to_approve = False
1787+ pdf_file .approved = orig_fobj .approved
1788+ update_categorized_elements (
1789+ self .context ,
1790+ pdf_file ,
1791+ get_category_object (self .context , pdf_file .content_category ),
1792+ limited = True ,
1793+ sort = False ,
1794+ logging = True ,
1795+ )
17311796 elif nbf .contentType in get_allowed_omf_content_types (esign = True ):
17321797 gen_context = {}
17331798 new_uid = uuid .uuid4 ().hex
17341799 download_url , s_uid = get_file_download_url (new_uid , short_uid = get_suid_from_uuid (new_uid ))
17351800 orig_template = get_original_template (orig_fobj )
1801+ doc_cb_download_added = False
17361802 if orig_template and nbf .contentType == "application/vnd.oasis.opendocument.text" : # own document
1737- helper_view = getMultiAdapter ((self .context , self .context .REQUEST ),
1738- name = 'document_generation_helper_view' )
1803+ helper_view = getMultiAdapter (
1804+ (self .context , self .context .REQUEST ), name = "document_generation_helper_view"
1805+ )
17391806 helper_view .pod_template = orig_template .UID ()
17401807 helper_view .output_format = "pdf"
17411808 gen_context = {"context" : self .context , "portal" : api .portal .get (), "view" : helper_view }
17421809 # update_dict_with_validation(gen_context, self._get_context_variables(pod_template),
17431810 # _("Error when merging context_variables in generation context"))
1744- merge_templates = [dic ["template" ] for dic in orig_template .merge_templates
1745- if dic ["pod_context_name" ] == "doc_cb_download" ]
1811+ merge_templates = [
1812+ dic ["template" ]
1813+ for dic in orig_template .merge_templates
1814+ if dic ["pod_context_name" ] == "doc_cb_download"
1815+ ]
17461816 if merge_templates :
17471817 download_template = uuidToObject (merge_templates [0 ])
17481818 if download_template :
17491819 gen_context ["doc_cb_download" ] = download_template
17501820 update_dict_with_validation (
17511821 gen_context ,
1752- {"download_barcode" : generate_barcode (download_url ).read (), "download_url" : download_url ,
1753- "max_download_date" : get_max_download_date (None , adate = datetime .date .today ()),
1754- "render_download_barcode" : True },
1822+ {
1823+ "download_barcode" : generate_barcode (download_url ).read (),
1824+ "download_url" : download_url ,
1825+ "max_download_date" : get_max_download_date (None , adate = datetime .date .today ()),
1826+ "render_download_barcode" : True ,
1827+ },
17551828 _dg ("Error when merging 'download_barcode' in generation context" ),
17561829 )
1830+ doc_cb_download_added = True
17571831
17581832 # TODO which pdf format to choose ?
17591833 pdf_file = convert_and_save_file (
@@ -1783,10 +1857,19 @@ def _create_pdf_file(self, orig_fobj, nbf, f_title, f_uid, file_index, session_f
17831857 sort = False ,
17841858 logging = True ,
17851859 )
1860+
1861+ # For non-ODT files (e.g. DOC, DOCX), the subtemplate cannot be merged during conversion.
1862+ # Render it to PDF separately and append it to the converted PDF.
1863+ if not doc_cb_download_added :
1864+ download_template = api .portal .get ().templates .om .get ("download_barcode" )
1865+ if download_template :
1866+ sub_pdf_data = self ._render_download_template_to_pdf (download_template , download_url )
1867+ if sub_pdf_data :
1868+ merged = merge_pdf (pdf_file .file .data , sub_pdf_data )
1869+ pdf_file .file = NamedBlobFile (merged , filename = pdf_file .file .filename )
1870+ Converter (pdf_file )() # Refresh pdf preview
17861871 else :
1787- raise NotImplementedError (
1788- "Cannot convert file of type '{}' to pdf for signing." .format (nbf .contentType )
1789- )
1872+ raise NotImplementedError ("Cannot convert file of type '{}' to pdf for signing." .format (nbf .contentType ))
17901873 pdf_uid = pdf_file .UID ()
17911874 self .pdf_files_uids [file_index ].append (pdf_uid )
17921875 # we rename the pdf filename to include pdf uid. So after the file is later consumed, we can retrieve object
@@ -1856,21 +1939,28 @@ def add_mail_files_to_session(self):
18561939 signers .append ((signer , email , name , label ))
18571940 watcher_users = api .user .get_users (groupname = "esign_watchers" )
18581941 watcher_emails = [user .getProperty ("email" ) for user in watcher_users ]
1859- session_id , session = add_files_to_session (signers , session_file_uids , bool (self .context .seal ),
1860- title = _ ("[ia.docs] Session {sign_id}" ),
1861- watchers = watcher_emails )
1942+ session_id , session = add_files_to_session (
1943+ signers ,
1944+ session_file_uids ,
1945+ bool (self .context .seal ),
1946+ title = _ ("[ia.docs] Session {sign_id}" ),
1947+ watchers = watcher_emails ,
1948+ )
18621949 self .annot ["session_id" ] = session_id
18631950 session_len = len (session_file_uids )
18641951 if session_len > 1 :
1865- return True , _ ("${count} files added to session number ${session_id}" ,
1866- mapping = {"count" : session_len , "session_id" : session_id })
1952+ return True , _ (
1953+ "${count} files added to session number ${session_id}" ,
1954+ mapping = {"count" : session_len , "session_id" : session_id },
1955+ )
18671956 else :
1868- return True , _ ("${count} file added to session number ${session_id}" ,
1869- mapping = {"count" : session_len , "session_id" : session_id })
1957+ return True , _ (
1958+ "${count} file added to session number ${session_id}" ,
1959+ mapping = {"count" : session_len , "session_id" : session_id },
1960+ )
18701961
18711962
18721963class DmsCategorizedObjectInfoAdapter (CategorizedObjectInfoAdapter ):
1873-
18741964 def get_infos (self , category , limited = False ):
18751965 base_infos = super (DmsCategorizedObjectInfoAdapter , self ).get_infos (category , limited = limited )
18761966 base_infos ["scan_id" ] = getattr (self .obj , "scan_id" , None )
0 commit comments