Passed
Push — 2.x ( df5950...91c842 )
by Ramon
07:45
created

InvalidatedSampleViewlet.sample()   A

Complexity

Conditions 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.CORE.
4
#
5
# SENAITE.CORE is free software: you can redistribute it and/or modify it under
6
# the terms of the GNU General Public License as published by the Free Software
7
# Foundation, version 2.
8
#
9
# This program is distributed in the hope that it will be useful, but WITHOUT
10
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
# details.
13
#
14
# You should have received a copy of the GNU General Public License along with
15
# this program; if not, write to the Free Software Foundation, Inc., 51
16
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
#
18
# Copyright 2018-2025 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
from bika.lims import api
22
from bika.lims.interfaces import IInvalidated
23
from plone.app.layout.viewlets import ViewletBase
24
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
25
from senaite.core.api.dtime import to_localized_time
26
27
28
class InvalidatedSampleViewlet(ViewletBase):
29
    """Print a viewlet to display a message stating the Sample was invalidated,
30
    along with a link to the retest and the invalidation reason
31
    """
32
    index = ViewPageTemplateFile("templates/invalidated.pt")
33
34
    @property
35
    def sample(self):
36
        """Returns the sample of current context
37
        """
38
        return self.context
39
40
    def is_visible(self):
41
        """Returns whether this viewlet must be visible or not
42
        """
43
        return self.is_invalidated()
44
45
    def is_invalidated(self):
46
        """Returns whether the current sample was invalidated
47
        """
48
        return IInvalidated.providedBy(self.sample)
49
50
    def get_invalidation_info(self):
51
        """Returns the information about the last invalidation transition that
52
        took place for the current sample
53
        """
54
        # get the review history (newest first)
55
        history = api.get_review_history(self.sample)
56
        for event in history:
57
            if event.get("action") != "invalidate":
58
                continue
59
            dt = event.get("time")
60
            actor = event.get("actor")
61
            comments = event.get("comments", "")
62
            return {
63
                "actor": actor,
64
                "fullname": self.get_fullname(actor),
65
                "date": to_localized_time(dt, long_format=True),
66
                "comment": api.safe_unicode(comments),
67
            }
68
69
        return {}
70
71
    def get_fullname(self, actor):
72
        """Returns the fullname of the user passed-in
73
        """
74
        user = api.get_user(actor)
75
        if not user:
76
            return actor
77
78
        props = api.get_user_properties(user)
79
        fullname = props.get("fullname", actor)
80
        contact = api.get_user_contact(user)
81
        fullname = contact and contact.getFullname() or fullname
82
        return fullname
83
84
85
    def get_retest(self):
86
        """Returns the retest of the current sample, if any
87
        """
88
        return self.sample.getRetest()
89