Skip to content

fix(calendar): dragging a task with an existing Compliance row creates a duplicate tile instead of moving #954

Description

@renemadsen

Summary

When a task that has an active Compliance record is dragged to a new date, the calendar shows two tiles — one on the original date and one on the new date — instead of one tile on the new date.

This affects any task that has been opened by a device worker (which creates a Compliance row with a Deadline pointing to the original date).

Root Cause (already analysed)

BackendConfigurationCalendarService.MoveTask scope = "all" updates:

  • arp.StartDate = newDate
  • planning.StartDate = newDate

But it does not update the Compliance.Deadline field. The existing Compliance row keeps Deadline = originalDate.

GetTasksForWeek then emits both:

  1. A tile from the compliance loopCompliance.Deadline = originalDate → tile on old date.
  2. A tile from the recurrence expansion loopplanning.StartDate = newDate → tile on new date.

The dedup gate (complianceDateSet, line ~296) blocks a recurrence-loop tile only when a compliance exists for the same date. Since originalDate ≠ newDate, both tiles pass the gate.

Fix required in MoveTask scope = "all" (and "thisAndFollowing" where applicable):
After updating arp.StartDate = newDate, query for active (non-Removed) Compliance rows for this planning:

var openCompliances = await dbContext.Compliances
    .Where(c => c.PlanningId == arp.ItemPlanningId
             && c.WorkflowState != Constants.WorkflowStates.Removed)
    .ToListAsync();
foreach (var c in openCompliances)
    c.Deadline = newDate;

Files to fix:

  • BackendConfigurationCalendarService.csMoveTask method, scope = "all" branch (lines ~1910–1977) and "thisAndFollowing" branch (lines ~1772–1909).

Steps to reproduce

Use Playwright against http://localhost:4200. Login: <your-admin-email> / <your-local-admin-password>.

Note: The duplicate only appears after a Compliance row exists for the task — i.e. after the task has been submitted/opened on a device, which creates the row. If no device has touched the task, the duplicate will not appear. To reproduce without a device:

  • Alternatively, you can verify by checking after any drag whether the calendar reloads and shows a tile on the original date alongside the new date.

Reproduction steps:

  1. Navigate to /plugins/backend-configuration-pn/calendar.
  2. Create a non-recurring (or any-repeat) task on any board. Note the date it is placed on (e.g. Thursday June 4).
  3. Wait for or trigger a compliance case to be created (the task must have been opened from a device, or a case worker has interacted with it — this creates the stale Compliance.Deadline row).
  4. On the web calendar, drag the task from its current date to a new date (e.g. Friday June 5).
  5. If prompted with a scope dialog, select "All in series". Confirm.
  6. Observe the calendar after reload.

Expected: One tile on Friday June 5; nothing on Thursday June 4.
Actual: Tiles appear on both Thursday June 4 and Friday June 5.

How to verify the fix

Playwright test (Angular e2e)

  1. Create a task and confirm it appears on date A.
  2. Via the test setup, insert a Compliance row with Deadline = date A for this task's PlanningId (or simulate a device case opening if a helper exists).
  3. Drag the task from date A to date B (scope = all).
  4. Assert exactly one tile is visible for this task, on date B.
  5. Assert no tile for this task is visible on date A.

C# integration test

In BackendConfiguration.Test:

  1. Seed an ARP + Planning + a Compliance row with Deadline = 2026-06-04.
  2. Call MoveTask with newDate = "2026-06-05", scope = "all".
  3. Assert the Compliance.Deadline has been updated to 2026-06-05.
  4. Call GetTasksForWeek for the week of June 1–7.
  5. Assert exactly one task entry is returned, on June 5 — not two entries.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions