Preferred way to handle duplication between near-identical DELETE endpoints (person/place)...?

Hi all, I’m working on #10706, an API to delete a contact hierarchy. I’ve added a DELETE on the existing /api/v1/person/{id} and /api/v1/place/{id} endpoints. The actual delete logic lives in a shared service, so the two controllers just wrap it: same permission gate, same delete_users/dry_run query params, same service call.

The snag: because delete is entity-agnostic, the two controller handlers and t@openapieir @openapi doc blocks come out nearly identical. SonarCloud flags ~10.5% duplication on new code (threshold is 6%), and it’s coming almost entirely from the person and place delete blocks, about 70 duplicated lines each, mostly@openapithe @openapi doc.

The review guidance I got was to keep the DELETE on both the person and place controllers with the shared code in the service, which is what I have. But since the wrappers turn out identical, that’s exactly what trips the duplication check.

What’s the preferred way to handle this in cht-core? A few options I’m weighing:

  • Keep it on both controllers, but move the shared params (delete_users, dry_run) and the response into shared OpenAPI components so @openapiach @openapi block is mostly $refs.
  • Share the handler in one place and point both routes at it.
  • A single shared delete controller that documents both paths.

Is there an accepted convention for duplicated-but-intentional endpoint pairs like this…? Thanks!

Is it just the openapi JSDoc that Sonar is complaining about?

I think I would prefer your first proposal where we keep the separate controllers but reduce the duplication between the JSDoc. We should be able to add the shared query parameters directly to our generation script and then just $ref them in the controller JS doc. :+1:

Thanks @jkuester for guidance.