Skip to content

Commit

Permalink
Merge branch '2.x' into late-icon-when-turnaround-time-is-zero
Browse files Browse the repository at this point in the history
  • Loading branch information
DanE417 committed Aug 8, 2024
2 parents 0585adf + 89f9cba commit c2dc0e4
Show file tree
Hide file tree
Showing 118 changed files with 1,537 additions and 485 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ Changelog
------------------

- #2569 Fix samples are indicated as late when Turnaround Time is zero
- #2604 Fix allowable and default output type for Html field in the ARReport
- #2584 Migrate SampleTypes to Dexterity
- #2602 Fix getAnalyses returns a LazyMap instead of a list
- #2593 Always do a full reindex of the object after transition
- #2593 Store Analyses UIDs as raw data in a Sample's attr (Analyses)
Expand Down
2 changes: 2 additions & 0 deletions src/bika/lims/content/arreport.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@

TextField(
"Html",
allowable_content_types=("text/html",),
default_output_type="text/html",
widget=TextAreaWidget(
label=_("HTML"),
cols=30,
Expand Down
138 changes: 1 addition & 137 deletions src/bika/lims/controlpanel/bika_sampletypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,156 +18,20 @@
# Copyright 2018-2024 by it's authors.
# Some rights reserved, see README and LICENSE.

import collections

from bika.lims import api
from bika.lims import bikaMessageFactory as _
from bika.lims.browser.bika_listing import BikaListingView
from bika.lims.catalog import SETUP_CATALOG
from bika.lims.config import PROJECTNAME
from bika.lims.interfaces import ISampleTypes
from bika.lims.utils import get_link_for
from plone.app.folder.folder import ATFolder
from plone.app.folder.folder import ATFolderSchema
from Products.Archetypes import atapi
from Products.ATContentTypes.content import schemata
from senaite.core.interfaces import IHideActionsMenu
from senaite.core.permissions import AddSampleType
from zope.interface.declarations import implements

# TODO: Separate content and view into own modules!


class SampleTypesView(BikaListingView):

def __init__(self, context, request):
super(SampleTypesView, self).__init__(context, request)

self.catalog = SETUP_CATALOG
self.contentFilter = {
"portal_type": "SampleType",
"sort_on": "sortable_title",
"sort_order": "ascending",
"path": {
"query": api.get_path(self.context),
"depth": 1,
}
}

self.context_actions = {
_("Add"): {
"url": "createObject?type_name=SampleType",
"permission": AddSampleType,
"icon": "++resource++bika.lims.images/add.png"}
}

self.title = self.context.translate(_("Sample Types"))
self.icon = "{}/{}".format(
self.portal_url,
"/++resource++bika.lims.images/sampletype_big.png"
)

self.description = ""

self.show_select_row = False
self.show_select_column = True
self.pagesize = 25

self.columns = collections.OrderedDict((
("Title", {
"title": _("Sample Type"),
"index": "sortable_title"}),
("Description", {
"title": _("Description"),
"index": "description",
"toggle": True}),
("getHazardous", {
"title": _("Hazardous"),
"toggle": True}),
("getPrefix", {
"title": _("Prefix"),
"toggle": True}),
("getMinimumVolume", {
"title": _("Minimum Volume"),
"toggle": True}),
("RetentionPeriod", {
"title": _("Retention Period"),
"toggle": True}),
("SampleMatrix", {
"title": _("SampleMatrix"),
"toggle": True}),
("ContainerType", {
"title": _("Default Container"),
"toggle": True}),
))

self.review_states = [
{
"id": "default",
"title": _("Active"),
"contentFilter": {"is_active": True},
"transitions": [{"id": "deactivate"}, ],
"columns": self.columns.keys(),
}, {
"id": "inactive",
"title": _("Inactive"),
"contentFilter": {'is_active': False},
"transitions": [{"id": "activate"}, ],
"columns": self.columns.keys(),
}, {
"id": "all",
"title": _("All"),
"contentFilter": {},
"columns": self.columns.keys(),
}
]

def folderitem(self, obj, item, index):
"""Service triggered each time an item is iterated in folderitems.
The use of this service prevents the extra-loops in child objects.
:obj: the instance of the class to be foldered
:item: dict containing the properties of the object to be used by
the template
:index: current index of the item
"""
obj = api.get_object(obj)
item["replace"]["Title"] = get_link_for(obj)
item["Description"] = obj.Description()

retention_period = obj.getRetentionPeriod()
if retention_period:
hours = retention_period.get("hours", "0")
minutes = retention_period.get("minutes", "0")
days = retention_period.get("days", "0")
item["RetentionPeriod"] = _("hours: {} minutes: {} days: {}"
.format(hours, minutes, days))

sample_matrix = obj.getSampleMatrix()
item["replace"]["SampleMatrix"] = get_link_for(sample_matrix)

container_type = obj.getContainerType()
item["replace"]["ContainerType"] = get_link_for(container_type)

# Hazardous
hazardous = obj.getHazardous()
item["getHazardous"] = hazardous

# Prefix
prefix = obj.getPrefix()
item["getPrefix"] = prefix

# Minimum Volume
vol = obj.getMinimumVolume()
item["getMinimumVolume"] = vol

return item


schema = ATFolderSchema.copy()


# TODO: Migrated to DX - https://github.com/senaite/senaite.core/pull/XXXX
class SampleTypes(ATFolder):
"""Sample Types Folder
"""
Expand Down
8 changes: 0 additions & 8 deletions src/bika/lims/controlpanel/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,6 @@
layer="bika.lims.interfaces.IBikaLIMS"
/>

<browser:page
for="bika.lims.interfaces.ISampleTypes"
name="folder_view"
class=".bika_sampletypes.SampleTypesView"
permission="senaite.core.permissions.ManageBika"
layer="bika.lims.interfaces.IBikaLIMS"
/>

<browser:page
for="bika.lims.interfaces.IAnalysisSpecs"
name="folder_view"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@ bika_calculations,Calculations
bika_instruments,Instruments
bika_labcontacts,LabContacts
bika_referencedefinitions,ReferenceDefinitions
bika_sampletypes,SampleTypes
bika_worksheettemplates,WorksheetTemplates
laboratory,Laboratory
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ bika_calculations
bika_instruments
bika_labcontacts
bika_referencedefinitions
bika_sampletypes
bika_worksheettemplates
laboratory

This file was deleted.

2 changes: 0 additions & 2 deletions src/bika/lims/profiles/default/types.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@
<object name="ReferenceSample" meta_type="Factory-based Type Information with dynamic views"/>
<object name="ReferenceSamplesFolder" meta_type="Factory-based Type Information with dynamic views"/>
<object name="RejectAnalysis" meta_type="Factory-based Type Information with dynamic views"/>
<object name="SampleType" meta_type="Factory-based Type Information with dynamic views"/>
<object name="SampleTypes" meta_type="Factory-based Type Information with dynamic views"/>
<object name="SupplierContact" meta_type="Factory-based Type Information with dynamic views"/>
<object name="Worksheet" meta_type="Factory-based Type Information with dynamic views"/>
<object name="WorksheetFolder" meta_type="Factory-based Type Information with dynamic views"/>
Expand Down
47 changes: 0 additions & 47 deletions src/bika/lims/profiles/default/types/SampleType.xml

This file was deleted.

29 changes: 0 additions & 29 deletions src/bika/lims/profiles/default/types/SampleTypes.xml

This file was deleted.

69 changes: 69 additions & 0 deletions src/senaite/core/api/dtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import time
from datetime import date
from datetime import datetime
from datetime import timedelta
from dateutil.relativedelta import relativedelta
from string import Template

Expand All @@ -32,6 +33,7 @@
from bika.lims import logger
from bika.lims.api import APIError
from bika.lims.api import get_tool
from bika.lims.api import to_int
from DateTime import DateTime
from DateTime.DateTime import DateError
from DateTime.DateTime import DateTimeError
Expand All @@ -40,6 +42,9 @@
from zope.i18n import translate


_marker = object()


def is_str(obj):
"""Check if the given object is a string
Expand Down Expand Up @@ -513,3 +518,67 @@ def get_relative_delta(dt1, dt2=None):
dt2 = dt2.replace(tzinfo=tzinfo)

return relativedelta(dt2, dt1)


def timedelta_to_dict(value, default=_marker):
"""Converts timedelta value to dict object
{
"days": 10,
"hours": 10,
"minutes": 10,
"seconds": 10,
}
:param value: timedelta object for conversion
:type value: timedelta
:param value: timedelta object for conversion
:type value: timedelta
:returns converted timedelta as dict or default object
:rtype: dict or default object
"""

if not isinstance(value, timedelta):
if default is _marker:
raise TypeError("%r is not supported" % type(value))
logger.warn(
"Invalid value passed to timedelta->dict conversion. "
"Falling back to default: %s." % default)
return default

# Note timedelta keeps days and seconds a part!
return {
"days": value.days,
"hours": value.seconds // 3600, # hours within a day
"minutes": (value.seconds % 3600) // 60, # minutes within an hour
"seconds": value.seconds % 60, # seconds within a minute
}


def to_timedelta(value, default=_marker):
"""Converts dict object w/ days, hours, minutes, seconds keys to
timedelta format
:param value: dict object for conversion
:type value: dict
:returns converted timedelta
:rtype: timedelta
"""

if isinstance(value, timedelta):
return value

if not isinstance(value, dict):
if default is _marker:
raise TypeError("%r is not supported" % type(value))
logger.warn(
"Invalid value passed to dict->timedelta conversion. "
"Falling back to default: %s." % default)
return default

return timedelta(
days=to_int(value.get('days', 0), 0),
hours=to_int(value.get('hours', 0), 0),
minutes=to_int(value.get('minutes', 0), 0),
seconds=to_int(value.get('seconds', 0), 0)
)
Loading

0 comments on commit c2dc0e4

Please sign in to comment.