Passed
Push — 2.x ( ac9ec3...712fca )
by Jordi
07:17
created

AfterCreateSampleHook.get_copy_partitions()   A

Complexity

Conditions 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
# -*- coding: utf-8 -*-
2
3
from bika.lims import api
4
from bika.lims.utils.analysisrequest import create_partition
5
from senaite.core import logger
6
from senaite.core.interfaces import IAfterCreateSampleHook
7
from senaite.core.registry import get_registry_record
8
from zope.interface import implementer
9
10
# Registry key constants
11
REGISTRY_KEY_COPY_PARTITIONS = "sample_add_form_copy_partitions"
12
13
14
@implementer(IAfterCreateSampleHook)
15
class AfterCreateSampleHook(object):
16
    """Copy sample structure with partitions
17
    """
18
19
    def __init__(self, sample, request):
20
        self.sample = sample
21
        self.request = request
22
23
    def update(self, sample, source=None):
24
        """Update handler
25
26
        :param sample: The newly created sample
27
        :param source: The source sample to copy from (optional)
28
        """
29
        # Return immediately if we do not have a source sample
30
        # or the registry settings is set to False
31
        if not source or not self.get_copy_partitions():
32
            return
33
34
        # Check if the source sample has partitions
35
        if not self.has_partitions(source):
36
            return
37
38
        # Get the partition config from the source sample
39
        configs = self.get_partition_configurations(source)
40
41
        # Nothing to do if we have no configs
42
        if not configs:
43
            return
44
45
        # Create the partitions in the target sample
46
        self.create_partitions_from_config(sample, configs)
47
48
    def get_copy_partitions(self):
49
        """Returns whether to copy the sample structure with partitions
50
51
        :return: Boolean indicating if partition copying is enabled
52
        """
53
        record = get_registry_record(REGISTRY_KEY_COPY_PARTITIONS)
54
        return bool(record)
55
56
    def has_partitions(self, sample):
57
        """Check if the sample has partitions
58
59
        :param source: The source sample object
60
        :return: True if valid, False otherwise
61
        """
62
        if not sample:
63
            return False
64
65
        partitions = sample.getDescendantsUIDs()
66
67
        if not partitions:
68
            return False
69
70
        return True
71
72
    def get_partition_configurations(self, source):
73
        """Extract partition configurations from the source sample
74
75
        Returns a list of dictionaries containing partition configuration:
76
        - analyses: list of analysis objects
77
        - sample_type: SampleType UID or None
78
        - container: Container UID or None
79
        - preservation: Preservation UID or None
80
81
        :param source: The source sample object
82
        :return: List of partition configuration dictionaries
83
        """
84
        if not source:
85
            return []
86
87
        # Get all partitions from the source
88
        partitions = source.getDescendants(all_descendants=False)
89
        if not partitions:
90
            return []
91
92
        configurations = []
93
        for partition in partitions:
94
            # Get analyses that belong to this partition
95
            analyses = partition.getAnalyses(full_objects=True)
96
97
            # Get partition-specific settings
98
            sample_type = partition.getSampleType()
99
            container = partition.getContainer()
100
            preservation = partition.getPreservation()
101
            internal_use = partition.getInternalUse()
102
103
            config = {
104
                "analyses": analyses,
105
                "sample_type": sample_type,
106
                "container": container,
107
                "preservation": preservation,
108
                "internal_use": internal_use,
109
            }
110
            configurations.append(config)
111
112
        return configurations
113
114
    def create_partitions_from_config(self, primary_sample, configurations):
115
        """Create partitions for a sample based on configurations
116
117
        :param primary_sample: The primary sample object
118
        :param configurations: List of partition configuration dicts
119
        :return: List of created partition objects
120
        """
121
        if not configurations:
122
            return []
123
124
        created_partitions = []
125
        for idx, config in enumerate(configurations):
126
            analyses = config.get("analyses", [])
127
            sample_type = config.get("sample_type")
128
            container = config.get("container")
129
            preservation = config.get("preservation")
130
            internal_use = config.get("internal_use")
131
132
            logger.debug(
133
                "Creating partition {} of {} for sample {}".format(
134
                    idx + 1, len(configurations), api.get_id(primary_sample))
135
            )
136
137
            # Create the partition
138
            partition = create_partition(
139
                analysis_request=primary_sample,
140
                request=self.request,
141
                analyses=analyses,
142
                sample_type=sample_type,
143
                container=container,
144
                preservation=preservation,
145
                internal_use=internal_use,
146
            )
147
            created_partitions.append(partition)
148
149
        return created_partitions
150