API : l'ordre d'une fratrie s'applique aux deux liens de l'union

L'arbre ne montre qu'un lien par enfant et par union ; le lien vers l'autre
parent de la même union reçoit le même ordre, pour que les deux restent
d'accord.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
IliesAllaliandClaude Opus 5.5 committed 2026-10-16 19:08:05 +02:00
1 parent 5f968a9f22
commit 8556d32bce
2 files changed
+26 -12

No files matched your search

+14 -6
View File
@@ -2023,7 +2023,7 @@ export const treeRoutes: FastifyPluginAsync = async (app) => {
const links = await app.prisma.parentChildLink.findMany({
where: { id: { in: linkIds }, treeId: params.data.id, deletedAt: null },
select: { id: true, parentPersonId: true, childPersonId: true },
select: { id: true, parentPersonId: true, childPersonId: true, viaUnionId: true },
})
const linkById = new Map(links.map((link) => [link.id, link]))
if (links.length !== linkIds.length) {
@@ -2048,13 +2048,21 @@ export const treeRoutes: FastifyPluginAsync = async (app) => {
return reply.code(400).send({ error: 'not_siblings' })
}
// L'arbre ne montre qu'un lien par enfant et par union : le lien vers l'autre parent de la même union
// prend le même ordre, pour que les deux restent d'accord
await app.prisma.$transaction(
payload.data.order.map((entry, index) =>
app.prisma.parentChildLink.updateMany({
where: { id: { in: entry.linkIds }, treeId: params.data.id, deletedAt: null },
payload.data.order.map((entry, index) => {
const unionIds = [...new Set(entry.linkIds.map((id) => linkById.get(id)?.viaUnionId).filter((id): id is string => Boolean(id)))]
return app.prisma.parentChildLink.updateMany({
where: {
treeId: params.data.id,
deletedAt: null,
childPersonId: entry.childId,
OR: [{ id: { in: entry.linkIds } }, ...(unionIds.length ? [{ viaUnionId: { in: unionIds } }] : [])],
},
data: { displayOrder: index + 1 },
}),
),
})
}),
)
await app.prisma.auditLog.create({
+12 -6
View File
@@ -516,10 +516,10 @@ describe('API security and authz', () => {
describe('PUT /trees/:id/links/order', () => {
const siblingLinks = [
{ id: 'link-a1', parentPersonId: 'father', childPersonId: 'anne' },
{ id: 'link-a2', parentPersonId: 'mother', childPersonId: 'anne' },
{ id: 'link-h1', parentPersonId: 'father', childPersonId: 'hugo' },
{ id: 'link-h2', parentPersonId: 'mother', childPersonId: 'hugo' },
{ id: 'link-a1', parentPersonId: 'father', childPersonId: 'anne', viaUnionId: 'union-1' },
{ id: 'link-a2', parentPersonId: 'mother', childPersonId: 'anne', viaUnionId: 'union-1' },
{ id: 'link-h1', parentPersonId: 'father', childPersonId: 'hugo', viaUnionId: 'union-1' },
{ id: 'link-h2', parentPersonId: 'mother', childPersonId: 'hugo', viaUnionId: 'union-1' },
]
const order = [
{ childId: 'hugo', linkIds: ['link-h1', 'link-h2'] },
@@ -542,11 +542,17 @@ describe('API security and authz', () => {
expect(response.statusCode).toBe(200)
expect(prismaMock.$transaction).toHaveBeenCalledTimes(1)
expect(prismaMock.parentChildLink.updateMany).toHaveBeenNthCalledWith(1, {
where: { id: { in: ['link-h1', 'link-h2'] }, treeId: 'tree-1', deletedAt: null },
where: {
treeId: 'tree-1', deletedAt: null, childPersonId: 'hugo',
OR: [{ id: { in: ['link-h1', 'link-h2'] } }, { viaUnionId: { in: ['union-1'] } }],
},
data: { displayOrder: 1 },
})
expect(prismaMock.parentChildLink.updateMany).toHaveBeenNthCalledWith(2, {
where: { id: { in: ['link-a1', 'link-a2'] }, treeId: 'tree-1', deletedAt: null },
where: {
treeId: 'tree-1', deletedAt: null, childPersonId: 'anne',
OR: [{ id: { in: ['link-a1', 'link-a2'] } }, { viaUnionId: { in: ['union-1'] } }],
},
data: { displayOrder: 2 },
})
expect(prismaMock.auditLog.create).toHaveBeenCalledWith(expect.objectContaining({