fix(backoffice): scope permission copying to the selected organization

"Copy permissions from" listed every position type in every
organization, because the dropdown read an unfiltered GET
/position-types. IAM exposes no organization-scoped route and carries no
organizationId on a position type, so the list is now narrowed
client-side to the built-in (isSystem) types plus those whose unit
belongs to the selected organization, with the type being edited
excluded.

Also in position management:

- Invalidate every position-type cache key root after a mutation. React
  Query matches prefixes element by element, so ["position-type"] never
  reached ["position-types-common", ...] and the department pickers kept
  serving a stale list. invalidatePositionTypeQueries() covers all three
  roots and is shared by the hook and the form.
- Drop getByOrganizationId and getCommonTypesByOrganizationId. Both
  issued the same requests as their unit counterparts and had no callers.
- Surface errors that were being swallowed. Three mutations had empty
  onError handlers, hiding IAM's 403 for built-in position types, and
  CreatePositionForm's bare catch discarded the reason for every failure.
- Move organization and unit into the zod schema so they validate with
  translated messages and inline errors instead of an ad-hoc toast, and
  keep submit disabled through the permission-assignment call that
  follows the save.
- Report the two outcomes the form used to hide: a save that succeeded
  while permission assignment failed, and clearing every permission,
  which assign-seconds-for-first cannot express.
- Fix the list page's loading and error states, which rendered the
  "Add User" string as a spinner, ignored the unit-scoped query, and
  left the export button stuck after a failed download.
- Halve PermissionSearch's requests. It fetched 50 rows, read the total
  off the response and immediately refetched, and it re-filtered results
  on the undebounced term, blanking the list while typing.

Remove the three record toggles. They never worked: IAM's
PositionTypeConfiguration holds only { id, organizationId,
positionTypeId, timeframe } in every published build, canAssignRecord
and canCreateBankRecord exist nowhere in the package, and the global
ValidationPipe runs with forbidNonWhitelisted, so every write was a 400.
The reads were broken too, passing a positionTypeId to a route that
filters on organizationId. A TODO records where the real flag lives:
PositionConfiguration.canReceiveRecord, keyed by positionId.

Delete ActionsColumn.tsx, which had no references.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Nathnael
2026-07-23 13:42:08 +00:00
parent 063a8799f5
commit 346d4718bf
13 changed files with 1444 additions and 1628 deletions

View File

@@ -2039,6 +2039,7 @@
"setting": "ቅንብሮች",
"loadingAdmins": "አስተዳዳሪዎችን በመጫን ላይ...",
"errorLoadingAdmins": "የአስተዳዳሪ መረጃን ማጫን ላይ ስህተት ተፈጥሯል",
"errorLoadingUnits": "ክፍሎችን ማጫን ላይ ስህተት ተፈጥሯል",
"retry": "ደግመው ይሞክሩ",
"assignAdmin": "አስተዳዳሪ መመደብ",
"addAdmin": "አስተዳዳሪ ያክሉ",
@@ -2651,6 +2652,18 @@
"selectApplicationToLoadPermissions": "ፍቃዶቹን ለማስገንዘብ አፕሊኬሽኑን ይምረጡ",
"copyPermissionsHint": "የነበረ የቦታ አይነት ይምረጡ፤ ፍቃዶቹ አስቀድመው ይሞላሉ፣ ከታች ማስተካከል ይችላሉ።",
"copyPermissionsFailed": "ፍቃዶችን መቅዳት አልተቻለም",
"selectOrganizationToCopy": "መቅዳት የሚችሏቸውን የቦታ ዓይነቶች ለማየት መጀመሪያ ድርጅት ይምረጡ",
"cannotClearAllPermissions": "ተቀምጧል። ፍቃዶቹ አልተቀየሩም — ይህ የቦታ ዓይነት ቢያንስ አንድ ፍቃድ ሊኖረው ይገባል።",
"permissionsSelected": "{{count}} ተመርጠዋል",
"positionTypeCreated": "የቦታ ዓይነት ተፈጥሯል",
"positionTypeUpdated": "የቦታ ዓይነት ተሻሽሏል",
"positionTypeDeleted": "የቦታ ዓይነት ተሰርዟል",
"positionTypeMigrated": "የቦታ ዓይነት ዝውውር ተሻሽሏል",
"positionTypeNotFound": "የቦታ ዓይነት አልተገኘም",
"permissionsAssignFailed": "የቦታ ዓይነቱ ተቀምጧል፣ ነገር ግን ፍቃዶቹን መመደብ አልተቻለም። እንደገና ለመሞከር ደግመው ይክፈቱት።",
"failedToLoadPermissions": "ፍቃዶችን መጫን አልተቻለም",
"failedToLoadPositionTypes": "የቦታ ዓይነቶችን መጫን አልተቻለም",
"exportFailed": "የቦታ ዓይነት ቁልፎችን መላክ አልተቻለም",
"perFailed": "ፍቃድ መፍጠር አልተቻለም",
"perSuccess": "የፍቃድ አይነት ተፈጠረና ፍቃዶች ተመደቡ",
"updatePerSuccess": "ፍቃድ በትክክል ተዘምኗል",

View File

@@ -2057,6 +2057,7 @@
"setting": "Setting",
"loadingAdmins": "Loading admins...",
"errorLoadingAdmins": "Error loading admin data",
"errorLoadingUnits": "Error loading units",
"retry": "Retry",
"assignAdmin": "Assign Admin",
"addAdmin": "Add Admin",
@@ -2760,6 +2761,18 @@
"selectApplicationToLoadPermissions": "Select an application to load its permissions",
"copyPermissionsHint": "Pick an existing position type to pre-fill its permissions, then edit below.",
"copyPermissionsFailed": "Failed to copy permissions",
"selectOrganizationToCopy": "Select an organization to see the position types you can copy from",
"cannotClearAllPermissions": "Saved. Permissions were left unchanged — this position type must keep at least one permission.",
"permissionsSelected": "{{count}} selected",
"positionTypeCreated": "Position type created",
"positionTypeUpdated": "Position type updated",
"positionTypeDeleted": "Position type deleted",
"positionTypeMigrated": "Position type migration updated",
"positionTypeNotFound": "Position type not found",
"permissionsAssignFailed": "Position type saved, but assigning its permissions failed. Reopen it to try again.",
"failedToLoadPermissions": "Failed to load permissions",
"failedToLoadPositionTypes": "Failed to load position types",
"exportFailed": "Failed to export position type keys",
"perFailed": "Failed To Create Permission",
"perSuccess": "Permission type created and permissions assigned",
"updatePerSuccess": "Permission updated successfully",

View File

@@ -1525,6 +1525,7 @@
"setting": "Paramètre",
"loadingAdmins": "Chargement des administrateurs...",
"errorLoadingAdmins": "Erreur lors du chargement des données administrateur",
"errorLoadingUnits": "Erreur lors du chargement des unités",
"retry": "Réessayer",
"assignAdmin": "Assigner un administrateur",
"addAdmin": "Ajouter un administrateur",
@@ -1886,6 +1887,18 @@
"selectApplicationToLoadPermissions": "Sélectionner une application pour charger ses autorisations",
"copyPermissionsHint": "Choisissez un type de poste existant pour préremplir ses autorisations, puis modifiez ci-dessous.",
"copyPermissionsFailed": "Échec de la copie des autorisations",
"selectOrganizationToCopy": "Sélectionnez une organisation pour voir les types de poste que vous pouvez copier",
"cannotClearAllPermissions": "Enregistré. Les autorisations n'ont pas été modifiées — ce type de poste doit conserver au moins une autorisation.",
"permissionsSelected": "{{count}} sélectionné(s)",
"positionTypeCreated": "Type de poste créé",
"positionTypeUpdated": "Type de poste mis à jour",
"positionTypeDeleted": "Type de poste supprimé",
"positionTypeMigrated": "Migration du type de poste mise à jour",
"positionTypeNotFound": "Type de poste introuvable",
"permissionsAssignFailed": "Type de poste enregistré, mais l'attribution de ses autorisations a échoué. Rouvrez-le pour réessayer.",
"failedToLoadPermissions": "Échec du chargement des autorisations",
"failedToLoadPositionTypes": "Échec du chargement des types de poste",
"exportFailed": "Échec de l'exportation des clés de type de poste",
"perFailed": "Échec de la création de lautorisation",
"perSuccess": "Type dautorisation créé et autorisations assignées",
"updatePerSuccess": "Autorisation mise à jour avec succès",