Skip to content

Commit

Permalink
Allow to edit the analysis service sort keys in the services listing (s…
Browse files Browse the repository at this point in the history
…enaite#2131)

* Added datamanager for analysis services

* Allow to edit the service sortkey in the listing

* Changelog updated

* Set refetch flag

* Added column help text

* Change help key to be equal to the colum key

Co-authored-by: Jordi Puiggené <jp@naralabs.com>
  • Loading branch information
ramonski and xispa committed Sep 19, 2022
1 parent 1c3f4a9 commit 8a073ab
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Changelog
2.3.0 (unreleased)
------------------

- #2131 Allow to edit the analysis service sort keys in the services listing
- #2133 Filter Contact and CCContact by Client on first click
- #2134 Render unit after result and interim fields
- #2129 Fix Traceback when invalidating a Sample with Remarks
Expand Down
2 changes: 1 addition & 1 deletion src/bika/lims/browser/analyses/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,7 @@ def _folder_item_result(self, analysis_brain, item):

else:
item["result_type"] = "numeric"
item["help"]["result"] = _(
item["help"]["Result"] = _(
"Enter the result either in decimal or scientific "
"notation, e.g. 0.00005 or 1e-5, 10000 or 1e5")

Expand Down
15 changes: 15 additions & 0 deletions src/bika/lims/controlpanel/bika_analysisservices.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

from bika.lims import api
from bika.lims import bikaMessageFactory as _
from bika.lims.api.security import check_permission
from bika.lims.browser.bika_listing import BikaListingView
from bika.lims.config import PROJECTNAME
from bika.lims.idserver import renameAfterCreation
Expand All @@ -38,6 +39,7 @@
from plone.app.layout.globals.interfaces import IViewView
from Products.Archetypes import atapi
from Products.ATContentTypes.content.schemata import finalizeATCTSchema
from Products.CMFCore.permissions import ModifyPortalContent
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.utils import _createObjectByType
from Products.CMFPlone.utils import safe_unicode
Expand Down Expand Up @@ -248,6 +250,11 @@ def __init__(self, context, request):
"title": _("Calculation"),
"sortable": False}),
("SortKey", {
"ajax": True,
"help": _(
"Float value from 0.0 - 1000.0 indicating the sort order. "
"Duplicate values are ordered alphabetically."),
"refetch": True,
"title": _("Sort Key"),
"sortable": False}),
))
Expand Down Expand Up @@ -284,6 +291,11 @@ def __init__(self, context, request):
for i in range(len(self.review_states)):
self.review_states[i]["columns"].remove("Price")

def can_edit(self, service):
"""Check if manage is allowed
"""
return check_permission(ModifyPortalContent, self.context)

def get_decimal_mark(self):
"""Returns the decimal mark
"""
Expand Down Expand Up @@ -399,6 +411,9 @@ def folderitem(self, obj, item, index):
sortkey = obj.getSortKey()
item["SortKey"] = sortkey

if self.can_edit(obj):
item["allow_edit"].append("SortKey")

# Icons
after_icons = ""
if obj.getAccredited():
Expand Down
97 changes: 97 additions & 0 deletions src/senaite/core/datamanagers/analysisservice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@

# -*- coding: utf-8 -*-

from AccessControl import Unauthorized
from bika.lims import api
from bika.lims.interfaces import IAnalysisService
from Products.Archetypes.utils import mapply
from senaite.core import logger
from senaite.core.datamanagers import DataManager
from zope.component import adapter


@adapter(IAnalysisService)
class AnalysisServiceDataManager(DataManager):
"""Data Manager for Analysis Services
"""

@property
def fields(self):
return api.get_fields(self.context)

def is_field_readable(self, field):
"""Checks if the field is readable
"""
return field.checkPermission("get", self.context)

def is_field_writeable(self, field, context=None):
"""Checks if the field is writeable
"""
if context is None:
context = self.context
return field.checkPermission("set", context)

def get_field_by_name(self, name):
"""Get the field by name
"""
field = self.fields.get(name)

# try to fetch the field w/o the `get` prefix
# this might be the case is some listings
if field is None:
# ensure we do not have the field setter as column
name = name.split("get", 1)[-1]
field = self.fields.get(name)

return field

def get(self, name):
"""Get sample field
"""
# get the schema field
field = self.get_field_by_name(name)

# check if the field exists
if field is None:
raise AttributeError("Field '{}' not found".format(name))

# Check the permission of the field
if not self.is_field_readable(field):
raise Unauthorized("Field '{}' not readable!".format(name))

# return the value with the field accessor
if hasattr(field, "getAccessor"):
accessor = field.getAccessor(self.context)
return accessor()
else:
# Set the value on the field directly
return field.get(self.context)

def set(self, name, value):
"""Set sample field or analysis result
"""
# set of updated objects
updated_objects = set()

# get the schema field
field = self.get_field_by_name(name)

if field is None:
raise AttributeError("Field '{}' not found".format(name))

# Check the permission of the field
if not self.is_field_writeable(field):
logger.error("Field '{}' not writeable!".format(name))
return []
# get the field mutator (works only for AT content types)
if hasattr(field, "getMutator"):
mutator = field.getMutator(self.context)
mapply(mutator, value)
else:
# Set the value on the field directly
field.set(self.context, value)

updated_objects.add(self.context)

# return a unified list of the updated objects
return list(updated_objects)
3 changes: 3 additions & 0 deletions src/senaite/core/datamanagers/configure.zcml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<configure xmlns="http://namespaces.zope.org/zope"
i18n_domain="senaite.core">

<!-- Data Manager for Analysis Services -->
<adapter factory=".analysisservice.AnalysisServiceDataManager" />

<!-- Data Manager for Analyses -->
<adapter factory=".sample.SampleDataManager" />

Expand Down

0 comments on commit 8a073ab

Please sign in to comment.