from django.apps import apps
from django.conf import settings
from django.db.models.signals import post_save

from .models import Action
from .verbs import Verbs


def _extract_target(instance):
    target = None
    if hasattr(instance, 'content_object'):
        target = instance.content_object
    elif hasattr(instance, 'project'):
        target = instance.project
    return target


def add_action(sender, instance, created, **kwargs):
    actor = instance.creator if hasattr(instance, 'creator') else None
    target = None
    if created:
        target = _extract_target(instance)
        if target:
            verb = Verbs.ADD.value
        else:
            verb = Verbs.CREATE.value

    else:
        verb = Verbs.UPDATE.value

    action = Action(
        actor=actor,
        verb=verb,
        obj=instance,
        target=target,
    )

    if hasattr(instance, 'project'):
        action.project = instance.project

    action.save()


for app, model in settings.A4_ACTIONABLES:
    post_save.connect(add_action, apps.get_model(app, model))

from itertools import chain
from django.apps import apps
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.db.models.signals import post_delete, post_save

from .models import Action
from .verbs import Verbs


SYSTEM_ACTIONABLES = (
    ('a4phases', 'Phase'),
    ('a4projects', 'Project')
)


def _extract_target(instance):
    target = None
    if hasattr(instance, 'content_object'):
        target = instance.content_object
    elif hasattr(instance, 'project'):
        target = instance.project
    return target


def _add_action(sender, instance, created, **kwargs):
    actor = instance.creator if hasattr(instance, 'creator') else None
    target = None
    if created:
        target = _extract_target(instance)
        if target:
            verb = Verbs.ADD.value
        else:
            verb = Verbs.CREATE.value

    else:
        verb = Verbs.UPDATE.value

    action = Action(
        actor=actor,
        verb=verb,
        obj=instance,
        target=target,
    )

    if hasattr(instance, 'project'):
        action.project = instance.project

    action.save()


for app, model in settings.A4_ACTIONABLES:
    post_save.connect(_add_action, apps.get_model(app, model))


def _delete_action(sender, instance, **kwargs):
    contenttype = ContentType.objects.get_for_model(sender)
    Action.objects\
        .filter(obj_content_type=contenttype, obj_object_id=instance.id)\
        .delete()


for app, model in chain(SYSTEM_ACTIONABLES, settings.A4_ACTIONABLES):
    post_delete.connect(_delete_action, apps.get_model(app, model))

Delete Actions if the related object is deleted
Delete Actions if the related object is deleted

As we are loosing all the information when the object of an action is
deleted, the action itself may be deleted, too.
