fix(worker): fix Bandel ticket sync and reactivate the integration

The status PATCH needs statusName alongside statusId or the API 400s,
so every write-back had been silently failing. The board's flat
assigneeName is null on every live ticket; the real assignee list is
ticketAssignees[]. Import now also picks up In Bearbeitung tickets,
not just Offen ones.

Both issues are live-verified against the real API, so the feature
flag flips back on.
This commit is contained in:
mika kuns
2026-09-02 09:59:06 +02:00
parent f640580463
commit 30d0611b8e
10 changed files with 185 additions and 64 deletions
@@ -55,7 +55,7 @@ public sealed class BandelTicketClientTests
public async Task GetProjectBoard_maps_items()
{
var h = new StubHandler(_ => (HttpStatusCode.OK,
"""{"success":true,"data":[{"id":12,"title":"Fix X","description":"d","statusId":1,"statusName":"Offen","assigneeID":7,"assigneeName":"mika.kuns"}],"message":"ok"}"""));
"""{"success":true,"data":[{"id":12,"title":"Fix X","description":"d","statusId":1,"statusName":"Offen","assigneeID":null,"assigneeName":null,"ticketAssignees":[{"assigneeId":26,"assigneeName":"mika.kuns"}]}],"message":"ok"}"""));
var items = await Make(h).GetProjectBoardAsync(393, CancellationToken.None);
@@ -63,20 +63,25 @@ public sealed class BandelTicketClientTests
Assert.Equal(12, item.Id);
Assert.Equal("Fix X", item.Title);
Assert.Equal(1, item.StatusId);
Assert.Equal("mika.kuns", item.AssigneeName);
Assert.Equal("mika.kuns", Assert.Single(item.TicketAssignees!).AssigneeName);
Assert.Equal("http://api.local/api/Board/project/393", h.Requests[0].RequestUri!.ToString());
}
[Fact]
public async Task SetStatus_patches_the_right_url_and_body()
// statusName ist auf der echten Route ein required-Feld: fehlt es, antwortet die API mit
// 400 "The StatusName field is required." und kein Statuswechsel wird geschrieben.
[Theory]
[InlineData(2, "InBearbeitung")]
[InlineData(3, "Fertig")]
public async Task SetStatus_patches_the_right_url_and_sends_both_status_fields(int statusId, string expectedName)
{
var h = new StubHandler(_ => (HttpStatusCode.OK, """{"success":true,"data":{},"message":"ok"}"""));
await Make(h).SetStatusAsync(12, 2, CancellationToken.None);
await Make(h).SetStatusAsync(12, statusId, CancellationToken.None);
Assert.Equal(HttpMethod.Patch, h.Requests[0].Method);
Assert.Equal("http://api.local/api/Ticket/12/status", h.Requests[0].RequestUri!.ToString());
Assert.Contains("\"statusId\":2", h.Bodies[0]);
Assert.Contains($"\"statusId\":{statusId}", h.Bodies[0]);
Assert.Contains($"\"statusName\":\"{expectedName}\"", h.Bodies[0]);
}
[Fact]