src/protocols/models/managers.py
author ymh <ymh.work@gmail.com>
Tue, 29 Mar 2022 11:23:56 +0200
changeset 211 244a90638e80
parent 142 56850f5c73f6
permissions -rw-r--r--
Added tag 0.2.3 for changeset 3de92ddba2de
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
142
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
import logging
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
import uuid
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
from django.apps import apps
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
from django.core.exceptions import ValidationError
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
from django.db import models, transaction
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
logger = logging.getLogger(__name__)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
class ProtocolManager(models.Manager):
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
    #TODO: check id must be the same
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
    #TODO: check owner must be the same
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
    @transaction.atomic
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
    def create_new_revision(self, protocol_id, revision_def, app):
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
        # lock the protocol
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
        owner = revision_def.get('owner', None)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
        if not owner:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
            raise ValidationError("Must have an owner")
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
        last_revision_modified = False
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
        if protocol_id is None:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
            protocol = self.model(app=app, owner=owner)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
            protocol.save()
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
            protocol_revision_model = apps.get_model(app_label='protocols', model_name='ProtocolRevision')
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
            last_revision = protocol_revision_model(protocol=protocol)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
            last_revision_modified = True
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
        else:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
            protocol = self.select_for_update().get(ext_id=protocol_id, app=app)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
            revision_nb = revision_def.get('version')
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
            last_revision = protocol.last_revision()
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
            if last_revision is not None and (revision_nb is None or revision_nb != last_revision.version):
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
                raise ValidationError("Bad protocol revision number when creating new revision")
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
        # create new protocol revision update protocol revision title and description
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
        title = revision_def.get('title', None)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
        description = revision_def.get('description', None)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
        last_revision_modified = last_revision_modified or \
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
            (title != last_revision.title or description != last_revision.description)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
        metacategory_model = apps.get_model(app_label='protocols', model_name='Metacategory')
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
        new_metacategories = [metacategory_model.objects.get_or_create_revision(app, **metacategory_def) for metacategory_def in revision_def.get('metacategories', [])]
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
        if not last_revision_modified:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
            new_metacategories_ids = { mc.ext_id for mc in new_metacategories }
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
            old_metacategories_ids = { mc.ext_id for mc in last_revision.metacategories.all() }
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
            last_revision_modified = (new_metacategories_ids != old_metacategories_ids )
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
            if last_revision_modified:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
                logger.debug("metacategaories modified %r, %r", new_metacategories_ids, old_metacategories_ids)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
        if last_revision_modified:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
            last_revision.pk = None
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
            last_revision.ext_id = uuid.uuid4()
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
            if title is not None:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
                last_revision.title = title
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
            if description is not None:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
                last_revision.description = description
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
            last_revision.save()
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
            last_revision.metacategories.add(*new_metacategories)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
        return last_revision
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
    @transaction.atomic
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
    def create_from_default(self, title, description, owner, app):
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
        metacategory_model = apps.get_model(app_label='protocols', model_name='Metacategory')
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
        default_metacategories = metacategory_model.objects.filter(is_default=True, app=app)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
        protocol = self.create(app=app, owner=owner)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
        protocol_revision_model = apps.get_model(app_label='protocols', model_name='ProtocolRevision')
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
        protocol_revision = protocol_revision_model.objects.create(protocol=protocol, title=title, description=description)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
        protocol_revision.metacategories.set([mc.revisions.all().last() for mc in default_metacategories])
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
        protocol_revision.save()
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
        return protocol
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
class MetacategoryManager(models.Manager):
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
    @transaction.atomic
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
    def create_with_revision(self, *args, **kwargs):
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
        instance = self.create(*args, **kwargs)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
        metacategory_revision_model = apps.get_model(app_label='protocols', model_name='MetacategoryRevision')
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
        revision = metacategory_revision_model.objects.create(base=instance, **{k : kwargs.get(k) for k in ['title', 'label', 'description', 'color', 'has_comment']})
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
        return instance
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
    @transaction.atomic
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
    def get_or_create_revision(self, app, **kwargs):
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
        # cases :
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
        # id: none, base: none
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
        #   -> create metacategory + revision
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
        # id: <>, base: none
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
        #   -> error
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
        # id: <>, base: <>
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
        #   -> compare filed values
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
        #   -> if same : return current instance, if not same : create new revision
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
        # id: none, base: <>
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
        #   -> compare to last revision. if different, create new revision else return revision
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
        id = kwargs.get('id')
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
        base = kwargs.get('base')
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
        if id is not None and base is None:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
            raise ValidationError("Id is not empty and base is empty")
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
        metacategory = None
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
        metacategory_created = False
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
        if base is None:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
            metacategory_created = True
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
            metacategory = self.model(
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
                app=app,
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
                title=kwargs.get('title'),
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
                label=kwargs.get('label'),
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
                description=kwargs.get('description'),
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
                color=kwargs.get('color'),
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
                has_comment=kwargs.get('has_comment', False),
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
                is_default=False
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
            )
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
            metacategory.save()
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
        else:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
            metacategory = self.get(ext_id=base, app=app)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
        revision = None
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
        metacategory_revision_model = apps.get_model(app_label='protocols', model_name='MetacategoryRevision')
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
        if id is None and not metacategory_created:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
            revision = metacategory.last_revision()
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
        elif not metacategory_created:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
            revision = metacategory_revision_model.objects.get(ext_id=id)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
        must_create_revision = (revision is None)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
        if revision is not None:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
            must_create_revision = \
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
                (revision.title != kwargs.get('title')) or \
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
                (revision.label != kwargs.get('label')) or \
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
                (revision.description != kwargs.get('description')) or \
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
                (revision.color != kwargs.get('color')) or \
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
                (revision.has_comment != kwargs.get('has_comment', False))
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
        if must_create_revision:
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
            revision = metacategory_revision_model.objects.create(
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
                base=metacategory,
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
                title=kwargs.get('title'),
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
                label=kwargs.get('label'),
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
                description=kwargs.get('description'),
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
                color=kwargs.get('color'),
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
                has_comment=kwargs.get('has_comment', False)
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   160
            )
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   161
56850f5c73f6 - upgrade libraries
ymh <ymh.work@gmail.com>
parents:
diff changeset
   162
        return revision