|
35 | 35 | from bika.lims.interfaces import IAddSampleObjectInfo |
36 | 36 | from bika.lims.interfaces import IAddSampleRecordsValidator |
37 | 37 | from bika.lims.interfaces import IGetDefaultFieldValueARAddHook |
38 | | -from bika.lims.utils import tmpID |
39 | 38 | from bika.lims.utils.analysisrequest import create_analysisrequest as crar |
40 | 39 | from bika.lims.workflow import ActionHandlerPool |
41 | 40 | from BTrees.OOBTree import OOBTree |
|
45 | 44 | from plone.memoize.volatile import DontCache |
46 | 45 | from plone.memoize.volatile import cache |
47 | 46 | from plone.protect.interfaces import IDisableCSRFProtection |
48 | | -from Products.CMFPlone.utils import _createObjectByType |
49 | 47 | from Products.CMFPlone.utils import safe_unicode |
50 | 48 | from Products.Five.browser import BrowserView |
51 | 49 | from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile |
@@ -1086,6 +1084,56 @@ def to_field_value(self, obj): |
1086 | 1084 | "title": obj and api.get_title(obj) or "" |
1087 | 1085 | } |
1088 | 1086 |
|
| 1087 | + def to_attachment_record(self, fileupload): |
| 1088 | + """Returns a dict-like structure with suitable information for the |
| 1089 | + proper creation of Attachment objects |
| 1090 | + """ |
| 1091 | + if not fileupload.filename: |
| 1092 | + # ZPublisher.HTTPRequest.FileUpload is empty |
| 1093 | + return None |
| 1094 | + return { |
| 1095 | + "AttachmentFile": fileupload, |
| 1096 | + "AttachmentType": "", |
| 1097 | + "ReportOption": "", |
| 1098 | + "AttachmentKeys": "", |
| 1099 | + "Service": "", |
| 1100 | + } |
| 1101 | + |
| 1102 | + def create_attachment(self, sample, attachment_record): |
| 1103 | + """Creates an attachment for the given sample with the information |
| 1104 | + provided in attachment_record |
| 1105 | + """ |
| 1106 | + # create the attachment object |
| 1107 | + client = sample.getClient() |
| 1108 | + attachment = api.create(client, "Attachment", **attachment_record) |
| 1109 | + uid = attachment_record.get("Service") |
| 1110 | + if not uid: |
| 1111 | + # Link the attachment to the sample |
| 1112 | + sample.addAttachment(attachment) |
| 1113 | + return attachment |
| 1114 | + |
| 1115 | + # Link the attachment to analyses with this service uid |
| 1116 | + ans = sample.objectValues(spec="Analysis") |
| 1117 | + ans = filter(lambda an: an.getRawAnalysisService() == uid, ans) |
| 1118 | + for analysis in ans: |
| 1119 | + attachments = analysis.getRawAttachment() |
| 1120 | + analysis.setAttachment(attachments + [attachment]) |
| 1121 | + |
| 1122 | + # Assign the attachment to the given condition |
| 1123 | + condition_title = attachment_record.get("Condition") |
| 1124 | + if not condition_title: |
| 1125 | + return attachment |
| 1126 | + |
| 1127 | + conditions = sample.getServiceConditions() |
| 1128 | + for condition in conditions: |
| 1129 | + is_uid = condition.get("uid") == uid |
| 1130 | + is_title = condition.get("title") == condition_title |
| 1131 | + is_file = condition.get("type") == "file" |
| 1132 | + if all([is_uid, is_title, is_file]): |
| 1133 | + condition["value"] = api.get_uid(attachment) |
| 1134 | + sample.setServiceConditions(conditions) |
| 1135 | + return attachment |
| 1136 | + |
1089 | 1137 | def ajax_get_global_settings(self): |
1090 | 1138 | """Returns the global Bika settings |
1091 | 1139 | """ |
@@ -1563,7 +1611,8 @@ def ajax_submit(self): |
1563 | 1611 | # Extract file uploads (fields ending with _file) |
1564 | 1612 | # These files will be added later as attachments |
1565 | 1613 | file_fields = filter(lambda f: f.endswith("_file"), record) |
1566 | | - attachments[n] = map(lambda f: record.pop(f), file_fields) |
| 1614 | + uploads = map(lambda f: record.pop(f), file_fields) |
| 1615 | + attachments[n] = [self.to_attachment_record(f) for f in uploads] |
1567 | 1616 |
|
1568 | 1617 | # Required fields and their values |
1569 | 1618 | required_keys = [field.getName() for field in fields |
@@ -1606,8 +1655,23 @@ def ajax_submit(self): |
1606 | 1655 | # Missing required fields |
1607 | 1656 | missing = [f for f in required_fields if not record.get(f, None)] |
1608 | 1657 |
|
1609 | | - # Handle required fields from Service conditions |
| 1658 | + # Handle fields from Service conditions |
1610 | 1659 | for condition in record.get("ServiceConditions", []): |
| 1660 | + if condition.get("type") == "file": |
| 1661 | + # Add the file as an attachment |
| 1662 | + file_upload = condition.get("value") |
| 1663 | + att = self.to_attachment_record(file_upload) |
| 1664 | + if att: |
| 1665 | + # Add the file as an attachment |
| 1666 | + att.update({ |
| 1667 | + "Service": condition.get("uid"), |
| 1668 | + "Condition": condition.get("title"), |
| 1669 | + }) |
| 1670 | + attachments[n].append(att) |
| 1671 | + # Reset the condition value |
| 1672 | + filename = file_upload and file_upload.filename or "" |
| 1673 | + condition.value = filename |
| 1674 | + |
1611 | 1675 | if condition.get("required") == "on": |
1612 | 1676 | if not condition.get("value"): |
1613 | 1677 | title = condition.get("title") |
@@ -1670,16 +1734,16 @@ def ajax_submit(self): |
1670 | 1734 | errors["message"] = str(e) |
1671 | 1735 | logger.error(e, exc_info=True) |
1672 | 1736 | return {"errors": errors} |
| 1737 | + |
1673 | 1738 | # We keep the title to check if AR is newly created |
1674 | 1739 | # and UID to print stickers |
1675 | 1740 | ARs[ar.Title()] = ar.UID() |
1676 | | - for attachment in attachments.get(n, []): |
1677 | | - if not attachment.filename: |
1678 | | - continue |
1679 | | - att = _createObjectByType("Attachment", client, tmpID()) |
1680 | | - att.setAttachmentFile(attachment) |
1681 | | - att.processForm() |
1682 | | - ar.addAttachment(att) |
| 1741 | + |
| 1742 | + # Create the attachments |
| 1743 | + ar_attachments = filter(None, attachments.get(n, [])) |
| 1744 | + for attachment_record in ar_attachments: |
| 1745 | + self.create_attachment(ar, attachment_record) |
| 1746 | + |
1683 | 1747 | actions.resume() |
1684 | 1748 |
|
1685 | 1749 | level = "info" |
|
0 commit comments