projectcaluma / caluma

A collaborative form editing service
https://caluma.io/
GNU General Public License v3.0
67 stars 26 forks source link

Conditional `workItem` creation: if not exists #1512

Closed kaldras closed 2 years ago

kaldras commented 3 years ago

If multiple flows point to a task and this task is not a multiinstance task there should no workItem be created when already one of this task exists.

winged commented 3 years ago

Analysis

Currently, work items are created without checks for already existing work items.

The code that creates the follow-up work items is residing in https://github.com/projectcaluma/caluma/blob/0c193f3e84b368a742a7748356229eacecacbf68/caluma/caluma_workflow/domain_logic.py#L182 and in the implementation of that method, here: https://github.com/projectcaluma/caluma/blob/0c193f3e84b368a742a7748356229eacecacbf68/caluma/caluma_workflow/utils.py#L50

Implementation

The implementation should be fairly straightforward: When creating the work items (workflow utils), the WorkItem.objects.create() call should be replaced by get_or_create() instead. The returned work_items list needs to be filtered so as only to return the freshly created ones, so we get something like this:

    for task in tasks:
        # ... omittede code
        for groups in work_item_groups:
            work_items.append(
                models.WorkItem.objects.get_or_create(
                    addressed_groups=groups,
                    controlling_groups=controlling_groups,
                    task_id=task.pk,
                    case=case,
                    defaults=dict(
                        deadline=lambda: task.calculate_deadline(),
                        document=lambda: Document.objects.create_document_for_task(task, user),
                        status=models.WorkItem.STATUS_READY,
                        created_by_user=user.username,
                        created_by_group=user.group,
                        previous_work_item=prev_work_item if prev_work_item else None,
                    )
                )
            )
    return [work_item for work_item, created in work_items if created]

Code obviously untested, needs verification and proper test suite. (Also, TIL: defaults parameter takes callables, which is needed here to avoid procedural style)

winged commented 3 years ago

Note: the previous_work_item is currently a 1:N relationship. In this case, we would have multiple work items where we're "coming from", thus this would ideally need to be a M:N relationship. This will probably break quite a bit of code, however.

czosel commented 3 years ago

@winged I'm not sure I understand. previous_work_item is the work item whose completion lead to the creation of a specific work item. There can be only one, right?