--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/models/managers.py Wed Jul 18 17:32:09 2018 +0200
@@ -0,0 +1,162 @@
+import logging
+import uuid
+
+from django.apps import apps
+from django.core.exceptions import ValidationError
+from django.db import models, transaction
+
+logger = logging.getLogger(__name__)
+
+class ProtocolManager(models.Manager):
+ #TODO: check id must be the same
+ #TODO: check owner must be the same
+ @transaction.atomic
+ def create_new_revision(self, protocol_id, revision_def, app):
+ # lock the protocol
+ owner = revision_def.get('owner', None)
+ if not owner:
+ raise ValidationError("Must have an owner")
+
+ last_revision_modified = False
+
+ if protocol_id is None:
+ protocol = self.model(app=app, owner=owner)
+ protocol.save()
+ protocol_revision_model = apps.get_model(app_label='protocols', model_name='ProtocolRevision')
+ last_revision = protocol_revision_model(protocol=protocol)
+ last_revision_modified = True
+ else:
+ protocol = self.select_for_update().get(ext_id=protocol_id, app=app)
+ revision_nb = revision_def.get('version')
+ last_revision = protocol.last_revision()
+ if last_revision is not None and (revision_nb is None or revision_nb != last_revision.version):
+ raise ValidationError("Bad protocol revision number when creating new revision")
+
+
+ # create new protocol revision update protocol revision title and description
+
+ title = revision_def.get('title', None)
+ description = revision_def.get('description', None)
+
+ last_revision_modified = last_revision_modified or \
+ (title != last_revision.title or description != last_revision.description)
+
+ metacategory_model = apps.get_model(app_label='protocols', model_name='Metacategory')
+ new_metacategories = [metacategory_model.objects.get_or_create_revision(app, **metacategory_def) for metacategory_def in revision_def.get('metacategories', [])]
+
+ if not last_revision_modified:
+ new_metacategories_ids = { mc.ext_id for mc in new_metacategories }
+ old_metacategories_ids = { mc.ext_id for mc in last_revision.metacategories.all() }
+
+ last_revision_modified = (new_metacategories_ids != old_metacategories_ids )
+
+ if last_revision_modified:
+ logger.debug("metacategaories modified %r, %r", new_metacategories_ids, old_metacategories_ids)
+
+
+ if last_revision_modified:
+ last_revision.pk = None
+ last_revision.ext_id = uuid.uuid4()
+ if title is not None:
+ last_revision.title = title
+ if description is not None:
+ last_revision.description = description
+ last_revision.save()
+
+ last_revision.metacategories.add(*new_metacategories)
+
+ return last_revision
+
+ @transaction.atomic
+ def create_from_default(self, title, description, owner, app):
+ metacategory_model = apps.get_model(app_label='protocols', model_name='Metacategory')
+ default_metacategories = metacategory_model.objects.filter(is_default=True, app=app)
+
+ protocol = self.create(app=app, owner=owner)
+
+ protocol_revision_model = apps.get_model(app_label='protocols', model_name='ProtocolRevision')
+
+ protocol_revision = protocol_revision_model.objects.create(protocol=protocol, title=title, description=description)
+
+ protocol_revision.metacategories.set([mc.revisions.all().last() for mc in default_metacategories])
+ protocol_revision.save()
+
+ return protocol
+
+
+class MetacategoryManager(models.Manager):
+
+
+ @transaction.atomic
+ def create_with_revision(self, *args, **kwargs):
+ instance = self.create(*args, **kwargs)
+ metacategory_revision_model = apps.get_model(app_label='protocols', model_name='MetacategoryRevision')
+ revision = metacategory_revision_model.objects.create(base=instance, **{k : kwargs.get(k) for k in ['title', 'label', 'description', 'color', 'has_comment']})
+
+ return instance
+
+
+ @transaction.atomic
+ def get_or_create_revision(self, app, **kwargs):
+
+ # cases :
+ # id: none, base: none
+ # -> create metacategory + revision
+ # id: <>, base: none
+ # -> error
+ # id: <>, base: <>
+ # -> compare filed values
+ # -> if same : return current instance, if not same : create new revision
+ # id: none, base: <>
+ # -> compare to last revision. if different, create new revision else return revision
+ id = kwargs.get('id')
+ base = kwargs.get('base')
+
+ if id is not None and base is None:
+ raise ValidationError("Id is not empty and base is empty")
+
+ metacategory = None
+ metacategory_created = False
+ if base is None:
+ metacategory_created = True
+ metacategory = self.model(
+ app=app,
+ title=kwargs.get('title'),
+ label=kwargs.get('label'),
+ description=kwargs.get('description'),
+ color=kwargs.get('color'),
+ has_comment=kwargs.get('has_comment', False),
+ is_default=False
+ )
+ metacategory.save()
+ else:
+ metacategory = self.get(ext_id=base, app=app)
+
+ revision = None
+ metacategory_revision_model = apps.get_model(app_label='protocols', model_name='MetacategoryRevision')
+
+ if id is None and not metacategory_created:
+ revision = metacategory.last_revision()
+ elif not metacategory_created:
+ revision = metacategory_revision_model.objects.get(ext_id=id)
+
+ must_create_revision = (revision is None)
+ if revision is not None:
+ must_create_revision = \
+ (revision.title != kwargs.get('title')) or \
+ (revision.label != kwargs.get('label')) or \
+ (revision.description != kwargs.get('description')) or \
+ (revision.color != kwargs.get('color')) or \
+ (revision.has_comment != kwargs.get('has_comment', False))
+
+ if must_create_revision:
+ revision = metacategory_revision_model.objects.create(
+ base=metacategory,
+ title=kwargs.get('title'),
+ label=kwargs.get('label'),
+ description=kwargs.get('description'),
+ color=kwargs.get('color'),
+ has_comment=kwargs.get('has_comment', False)
+ )
+
+ return revision