From 4e1211a1e1b2b9f2367440577b8c8e16c7758a5b Mon Sep 17 00:00:00 2001
From: Hermes Agent
Date: Sun, 25 Oct 2026 13:34:52 +0200
Subject: [PATCH] Fixed idNumber missed assignment when updating organisation
---
.../src/pages/GovernancePage.tsx | 117 +++++++++++++++++-
1 file changed, 115 insertions(+), 2 deletions(-)
diff --git a/PostFundManagement.ConsoleUI/src/pages/GovernancePage.tsx b/PostFundManagement.ConsoleUI/src/pages/GovernancePage.tsx
index 56c8e30..029073e 100644
--- a/PostFundManagement.ConsoleUI/src/pages/GovernancePage.tsx
+++ b/PostFundManagement.ConsoleUI/src/pages/GovernancePage.tsx
@@ -29,6 +29,7 @@ import {
CheckCircle2,
Loader2,
Lock,
+ AlertTriangle,
} from 'lucide-react';
import {
getOrganisations,
@@ -113,6 +114,7 @@ const organisationSchema = z.object({
registrationNo: z.string().min(4, 'Registration number is mandatory'),
email: z.string().email('Enter a valid email address'),
organisationUser: z.string().min(1, 'Please select a linked executive or manager user'),
+ idNumber: z.string().optional(),
type: z.coerce.number().min(1).max(27),
status: z.coerce.number().optional(),
});
@@ -593,11 +595,23 @@ export const GovernancePage: React.FC = () => {
registrationNo: '',
email: '',
organisationUser: '',
+ idNumber: '',
type: OrganisationType.Enterprise,
status: ActivityStatus.Active,
},
});
+ const watchedOrgUser = orgForm.watch('organisationUser');
+ const selectedExecutiveUser = React.useMemo(() => {
+ if (!watchedOrgUser) return null;
+ const str = String(watchedOrgUser).toLowerCase();
+ return (
+ usersDirectory.find((u) => u.id && String(u.id).toLowerCase() === str) ||
+ modalExecutiveUsers.find((u) => u.id && String(u.id).toLowerCase() === str) ||
+ null
+ );
+ }, [watchedOrgUser, usersDirectory, modalExecutiveUsers]);
+
const portfolioForm = useForm({
resolver: zodResolver(portfolioSchema),
defaultValues: {
@@ -622,11 +636,20 @@ export const GovernancePage: React.FC = () => {
const orgMutation = useMutation({
mutationFn: (data: OrganisationFormValues) => {
if (editingOrg) {
+ if (!data.idNumber || !data.idNumber.trim()) {
+ orgForm.setError('idNumber', {
+ type: 'manual',
+ message: 'Government ID number is required to assign this executive user.',
+ });
+ throw new Error('Executive user ID number is required when updating an organisation.');
+ }
+
return updateOrganisation({
organisationId: editingOrg.id,
name: data.name,
registrationNo: data.registrationNo,
email: data.email,
+ idNumber: data.idNumber.trim(),
organisationUser: data.organisationUser,
type: Number(data.type),
status: data.status !== undefined ? Number(data.status) : ActivityStatus.Active,
@@ -636,6 +659,7 @@ export const GovernancePage: React.FC = () => {
name: data.name,
registrationNo: data.registrationNo,
email: data.email,
+ idNumber: data.idNumber?.trim() || null,
organisationUser: data.organisationUser,
type: Number(data.type),
});
@@ -753,6 +777,7 @@ export const GovernancePage: React.FC = () => {
registrationNo: '',
email: '',
organisationUser: defaultUser?.id || '',
+ idNumber: defaultUser?.idNumber || '',
type: OrganisationType.Enterprise,
status: ActivityStatus.Active,
});
@@ -770,9 +795,10 @@ export const GovernancePage: React.FC = () => {
'';
let selectedUserId = '';
+ let matchedUser: User | undefined;
if (targetUserId) {
const targetStr = String(targetUserId).toLowerCase();
- const matchedUser = usersDirectory.find(
+ matchedUser = usersDirectory.find(
(u) =>
(u.id && String(u.id).toLowerCase() === targetStr) ||
(u.email && u.email.toLowerCase() === targetStr)
@@ -792,15 +818,25 @@ export const GovernancePage: React.FC = () => {
}
}
+ const resolvedIdNumber = matchedUser?.idNumber || org.idNumber || '';
+
orgForm.reset({
name: org.name || '',
registrationNo: org.registrationNo || '',
email: org.email || '',
organisationUser: selectedUserId,
+ idNumber: resolvedIdNumber,
type: org.type || OrganisationType.Enterprise,
status: org.status ?? ActivityStatus.Active,
});
+ if (selectedUserId && !resolvedIdNumber) {
+ orgForm.setError('idNumber', {
+ type: 'manual',
+ message: 'This executive user has no ID number on file. An ID number is required to update the organisation.',
+ });
+ }
+
setIsQuickAddUserOpen(false);
setQuickUserError(null);
setIsOrgModalOpen(true);
@@ -1760,7 +1796,32 @@ export const GovernancePage: React.FC = () => {
)}
{
+ const selectedId = e.target.value;
+ if (!selectedId) {
+ orgForm.setValue('idNumber', '');
+ return;
+ }
+ const str = String(selectedId).toLowerCase();
+ const matched =
+ usersDirectory.find((u) => u.id && String(u.id).toLowerCase() === str) ||
+ modalExecutiveUsers.find((u) => u.id && String(u.id).toLowerCase() === str);
+
+ if (matched?.idNumber && matched.idNumber.trim()) {
+ orgForm.setValue('idNumber', matched.idNumber.trim(), { shouldValidate: true });
+ orgForm.clearErrors('idNumber');
+ } else {
+ orgForm.setValue('idNumber', '', { shouldValidate: true });
+ if (editingOrg) {
+ orgForm.setError('idNumber', {
+ type: 'manual',
+ message: 'Selected user has no ID number on file. Please enter their ID number to enable executive assignment.',
+ });
+ }
+ }
+ },
+ })}
className="w-full px-3 py-2 text-xs border border-slate-700/80 rounded-xl focus:outline-none focus:ring-1 focus:ring-blue-500 bg-[#090d16] text-white font-medium"
>
-- Select linked executive or manager account --
@@ -1778,9 +1839,61 @@ export const GovernancePage: React.FC = () => {
No Executive or Manager user found. Create one below to continue.
)}
+ {watchedOrgUser && selectedExecutiveUser && selectedExecutiveUser.idNumber && selectedExecutiveUser.idNumber.trim() && (
+
+
+ ID on file: {selectedExecutiveUser.idNumber}
+
+ )}
+ {/* Missing ID Number Alert */}
+ {watchedOrgUser && selectedExecutiveUser && (!selectedExecutiveUser.idNumber || !selectedExecutiveUser.idNumber.trim()) && (
+
+
+
+
+ Missing Executive ID Number
+
+
+ The selected executive ({selectedExecutiveUser.email || watchedOrgUser} ) does not have a Government ID Number on file. An ID number is required to assign this executive user; otherwise the update will be ignored. Please enter their ID number below.
+
+
+
+ )}
+
+ {/* Executive User ID Number Input */}
+
+
+
+
+ Executive ID Number {editingOrg ? '*' : '(Optional)'}
+
+
+
+ {selectedExecutiveUser?.idNumber && (
+
Sourced from profile
+ )}
+
+
+ {orgForm.formState.errors.idNumber && (
+
{orgForm.formState.errors.idNumber.message}
+ )}
+
+
{/* Inline Collapsible Subform to Create Executive User */}
{isQuickAddUserOpen && !editingOrg && (