• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

inclusion-numerique / coop-mediation-numerique / d8de6e05-24d8-4280-aae0-2589f3d40ae1

19 May 2026 04:35PM UTC coverage: 9.989% (+3.0%) from 7.008%
d8de6e05-24d8-4280-aae0-2589f3d40ae1

Pull #497

circleci

marc-gavanier
feat: improve structure fusion scoring and review export

Significantly reduces the manual review burden by detecting more
true duplicates automatically and avoiding false positives.

Scoring improvements (detect-duplicate-structures, generate-structures-action-plan):
- Treat clusters of type 'mixte' like 'doublon_certain' with per-pair
  scoring (instead of bulk verification_manuelle), uncovering hundreds
  of auto/probable fusions previously hidden in mixed clusters.
- Boost address score to 1.0 when one normalized address is contained
  in the other (e.g. "Lupino" vs "LUPINO PARVIS NOTRE DAME VICTOIRE").
- Add address abbreviations: VC (voie communale), RT (route), ZA, ZI, CH.
- Redistribute geo weight when coords are unavailable, OR when address
  strongly indicates the same place (>=0.85): prevents penalizing
  structures with missing or erroneous coords.
- Normalize "commune de/du", "mairie de/du", "ville de/du" to a single
  "ville" canonical token so variants match.
- Detect "service keywords" (EPN, médiathèque, CCAS, France services,
  MJC, etc.): when one name has such a keyword and the other does not,
  they are distinct entities even with shared SIRET/address. Disables
  the address-contained heuristic and keeps geo in the score.

Sync resilience (findOrCreateStructure):
- After strict siret+codeInsee miss, fall back to siret-only with
  normalized contained-name match. This catches Dataspace structures
  whose codeInsee diverges from the coop's, without merging an EPN
  with its parent town hall (asymmetric-service-keyword guard).

Review output:
- generate-structures-action-plan: structures-fusion-review.csv now
  uses cluster-grouped format (CIBLE + sources + empty line between
  clusters, sorted by ascending score), matching the existing format
  Tim uses for his manual reviews.
- export-duplicate-sirets: cluster-grouped CSV (empty line between
  SIRETs) and exclude empty-string siret. Enrich each row with
  nom_api, adresse_api, corre... (continued)
Pull Request #497: feat: improve structure fusion scoring and review export

688 of 10878 branches covered (6.32%)

Branch coverage included in aggregate %.

26 of 153 new or added lines in 4 files covered. (16.99%)

1111 existing lines in 95 files now uncovered.

2111 of 17142 relevant lines covered (12.31%)

1.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

33.33
/apps/web/src/app/api/v1/transformJsonApiQueryParamsToObject.ts
1
import { set } from 'lodash-es'
1✔
2

3
/**
4
 * Json:api query params are given as string in brackets, e.g. "page[size]"
5
 * So the NextUrl SearchParams looks like { 'page[size]': '10' }
6
 * This function transforms them to object, e.g. { page: { size: 10 } }
7
 * To be able to be passed later to zod validation.
8
 *
9
 * A parameter with multiple values is given as a comma separated string, e.g. "sort=age,city"
10
 * and is transformed to an array, e.g. { sort: ['age', 'city'] }
11
 *
12
 * See https://jsonapi.org/format/#query-parameters-families
13
 */
14

15
export const transformJsonApiQueryParamsToObject = (
1✔
16
  params: URLSearchParams,
17
): Record<string, unknown> => {
18
  const result: Record<string, unknown> = {}
1✔
19

20
  for (const [rawKey, rawValue] of params.entries()) {
1✔
21
    // split rawKey into nested keys: e.g. "page[size]" -> ["page", "size"]
UNCOV
22
    const keys = rawKey.match(/[^[\]]+/g) || []
×
23

24
    // handle multiple values by splitting on comma
UNCOV
25
    const values = rawValue.includes(',') ? rawValue.split(',') : [rawValue]
×
26

UNCOV
27
    const finalValue = values.length === 1 ? values[0] : values
×
28

UNCOV
29
    set(result, keys, finalValue)
×
30
  }
31

32
  return result
1✔
33
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc