src/protocols/models/managers.py
author salimr <riwad.salim@yahoo.fr>
Tue, 14 Aug 2018 20:39:55 +0200
changeset 144 8b950885ddae
parent 142 56850f5c73f6
permissions -rw-r--r--
Add local font and assets. Override Bootstrap css varriables. Add specific css files

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