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