Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Progress indicator for Batch listing #1544

Merged
merged 7 commits into from
Feb 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Changelog

**Added**

- #1544 Progress indicator for Batch listing
- #1536 Integrated Setup and Profiles from senaite.lims
- #1534 Integrate browser resources from senaite.lims
- #1529 Moved contentmenu provider into core
Expand Down
32 changes: 4 additions & 28 deletions bika/lims/browser/analysisrequest/analysisrequests.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ def __init__(self, context, request):
"sortable": True, }),
("Progress", {
"title": "Progress",
"sortable": False,
"index": "getProgress",
"sortable": True,
"toggle": True}),
("getId", {
"title": _("Sample ID"),
Expand Down Expand Up @@ -573,7 +574,8 @@ def folderitem(self, obj, item, index):
item["getAnalysesNum"] = ""

# Progress
progress_perc = self.get_progress_percentage(obj)
progress_perc = obj.getProgress
item["Progress"] = progress_perc
item["replace"]["Progress"] = get_progress_bar_html(progress_perc)

item["BatchID"] = obj.getBatchID
Expand Down Expand Up @@ -732,32 +734,6 @@ def folderitem(self, obj, item, index):

return item

def get_progress_percentage(self, ar_brain):
"""Returns the percentage of completeness of the Analysis Request
"""
review_state = ar_brain.review_state
if review_state == "published":
return 100

numbers = ar_brain.getAnalysesNum

num_analyses = numbers[1] or 0
if not num_analyses:
return 0

# [verified, total, not_submitted, to_be_verified]
num_to_be_verified = numbers[3] or 0
num_verified = numbers[0] or 0

# 2 steps per analysis (submit, verify) plus one step for publish
max_num_steps = (num_analyses * 2) + 1
num_steps = num_to_be_verified + (num_verified * 2)
if not num_steps:
return 0
if num_steps > max_num_steps:
return 100
return (num_steps * 100) / max_num_steps

@property
def copy_to_new_allowed(self):
mtool = api.get_tool("portal_membership")
Expand Down
15 changes: 13 additions & 2 deletions bika/lims/browser/batchfolder.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@
import collections

from bika.lims import api
from bika.lims.api.security import check_permission
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.interfaces import IClient
from bika.lims.permissions import AddBatch
from bika.lims.utils import get_link
from bika.lims.utils import get_progress_bar_html


class BatchFolderContentsView(BikaListingView):
Expand All @@ -41,7 +42,7 @@ def __init__(self, context, request):
"portal_type": "Batch",
"sort_on": "created",
"sort_order": "descending",
"is_active": True
"is_active": True,
}

self.context_actions = {}
Expand All @@ -59,6 +60,11 @@ def __init__(self, context, request):
("Title", {
"title": _("Title"),
"index": "title", }),
("Progress", {
"title": _("Progress"),
"index": "getProgress",
"sortable": True,
"toggle": True}),
("BatchID", {
"title": _("Batch ID"),
"index": "getId", }),
Expand Down Expand Up @@ -167,6 +173,11 @@ def folderitem(self, obj, item, index):
created = api.get_creation_date(obj)
date = obj.getBatchDate()

# total sample progress
progress = obj.getProgress()
item["Progress"] = progress
item["replace"]["Progress"] = get_progress_bar_html(progress)

item["BatchID"] = bid
item["ClientBatchID"] = cbid
item["replace"]["BatchID"] = get_link(url, bid)
Expand Down
1 change: 1 addition & 0 deletions bika/lims/catalog/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from .analysisrequest_catalog import CATALOG_ANALYSIS_REQUEST_LISTING # noqa
from .analysis_catalog import CATALOG_ANALYSIS_LISTING # noqa
from .autoimportlogs_catalog import CATALOG_AUTOIMPORTLOGS_LISTING # noqa
from .bika_catalog import BIKA_CATALOG # noqa
from .worksheet_catalog import CATALOG_WORKSHEET_LISTING # noqa
from .report_catalog import CATALOG_REPORT_LISTING # noqa
from .bikasetup_catalog import SETUP_CATALOG # noqa
Expand Down
1 change: 1 addition & 0 deletions bika/lims/catalog/analysisrequest_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
"getSamplingWorkflowEnabled",
"assigned_state",
"getInternalUse",
"getProgress",
]

# Adding basic indexes
Expand Down
30 changes: 30 additions & 0 deletions bika/lims/content/analysisrequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@

IMG_SRC_RX = re.compile(r'<img.*?src="(.*?)"')
IMG_DATA_SRC_RX = re.compile(r'<img.*?src="(data:image/.*?;base64,)(.*?)"')
FINAL_STATES = ["published", "retracted", "rejected", "cancelled"]


# SCHEMA DEFINITION
Expand Down Expand Up @@ -2469,5 +2470,34 @@ def process_inline_images(self, html):

return html

def getProgress(self):
"""Returns the progress in percent of all analyses
"""
review_state = api.get_review_status(self)

# Consider final states as 100%
# https://github.com/senaite/senaite.core/pull/1544#discussion_r379821841
if review_state in FINAL_STATES:
return 100

numbers = self.getAnalysesNum()

num_analyses = numbers[1] or 0
if not num_analyses:
return 0

# [verified, total, not_submitted, to_be_verified]
num_to_be_verified = numbers[3] or 0
num_verified = numbers[0] or 0

# 2 steps per analysis (submit, verify) plus one step for publish
max_num_steps = (num_analyses * 2) + 1
num_steps = num_to_be_verified + (num_verified * 2)
if not num_steps:
return 0
if num_steps > max_num_steps:
return 100
return (num_steps * 100) / max_num_steps


registerType(AnalysisRequest, PROJECTNAME)
11 changes: 11 additions & 0 deletions bika/lims/content/batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,5 +249,16 @@ def getLabelNames(self):
labels = [label.getObject().title for label in uc(UID=uids)]
return labels

def getProgress(self):
"""Returns the progress in percent of all samples
"""
total_progress = 0
samples = self.getAnalysisRequests()
total = len(samples)
if total > 0:
sample_progresses = map(lambda s: s.getProgress(), samples)
total_progress = sum(sample_progresses) / total
return total_progress


registerType(Batch, PROJECTNAME)
1 change: 1 addition & 0 deletions bika/lims/setuphandlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@
("bika_catalog", "getDateReceived"),
("bika_catalog", "getDateSampled"),
("bika_catalog", "review_state"),
("bika_catalog", "getProgress"),

("bika_setup_catalog", "path"),
("bika_setup_catalog", "UID"),
Expand Down
27 changes: 26 additions & 1 deletion bika/lims/upgrade/v01_03_003.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@
# Copyright 2018-2020 by it's authors.
# Some rights reserved, see README and LICENSE.

import re
from collections import defaultdict
from operator import itemgetter

import re
import transaction
from bika.lims import api
from bika.lims import logger
from bika.lims.api.mail import is_valid_email_address
from bika.lims.catalog import BIKA_CATALOG
from bika.lims.catalog import CATALOG_ANALYSIS_LISTING
from bika.lims.catalog import CATALOG_ANALYSIS_REQUEST_LISTING
from bika.lims.catalog.bikasetup_catalog import SETUP_CATALOG
Expand All @@ -39,6 +40,7 @@
from bika.lims.upgrade import upgradestep
from bika.lims.upgrade.utils import UpgradeUtils
from Products.Archetypes.config import UID_CATALOG
from Products.ZCatalog.ProgressHandler import ZLogHandler
from zope.interface import alsoProvides

version = "1.3.3" # Remember version number in metadata.xml and setup.py
Expand Down Expand Up @@ -388,6 +390,13 @@ def upgrade(tool):
# https://github.com/senaite/senaite.core/pull/1542
fix_email_address(portal)

# Add metadata for progress bar
# https://github.com/senaite/senaite.core/pull/1544
# Add progress metadata column for Samples
add_metadata(portal, CATALOG_ANALYSIS_REQUEST_LISTING, "getProgress", True)
# Add progress metadata column for Batches
add_metadata(portal, BIKA_CATALOG, "getProgress", True)

logger.info("{0} upgraded to version {1}".format(product, version))
return True

Expand Down Expand Up @@ -863,6 +872,21 @@ def fix_email_address(portal, portal_types=None, catalog_id="portal_catalog"):
logger.info("Fixing email addresses [DONE]")


def add_metadata(portal, catalog_id, column, refresh_catalog=False):
logger.info("Adding '{}' metadata to '{}' ...".format(column, catalog_id))
catalog = api.get_tool(catalog_id)
if column in catalog.schema():
logger.info("Metadata '{}' already in catalog '{}' [SKIP]"
.format(column, catalog_id))
return
catalog.addColumn(column)

if refresh_catalog:
logger.info("Refreshing catalog '{}' ...".format(catalog_id))
handler = ZLogHandler(steps=100)
catalog.refreshCatalog(pghandler=handler)


def remove_arimports(portal):
"""Removes arimports folder
"""
Expand All @@ -876,3 +900,4 @@ def remove_arimports(portal):
portal.manage_delObjects(arimports.getId())

logger.info("Removing AR Imports folder [DONE]")