@@ -19,6 +19,34 @@ const externalIdentsSchema = zfd.formData(
1919 )
2020) ;
2121
22+ /**
23+ * Constructs a hierarchical identifier path from form data.
24+ * Form fields are named like: census_ident_census, census_ident_region, census_ident_surveyor, census_ident_unit_no
25+ * The labels (like "census.region.surveyor.unit_no") tell us the level names.
26+ */
27+ function constructHierarchicalPath (
28+ identTypeCode : string ,
29+ labels : string ,
30+ formData : Record < string , string | undefined >
31+ ) : string | null {
32+ const levelNames = labels . split ( "." ) ;
33+ const parts : string [ ] = [ ] ;
34+
35+ for ( const levelName of levelNames ) {
36+ const fieldKey = `${ identTypeCode } _${ levelName } ` ;
37+ const value = formData [ fieldKey ] ;
38+ if ( value ) {
39+ parts . push ( value ) ;
40+ } else {
41+ // If any level is empty, stop constructing the path
42+ break ;
43+ }
44+ }
45+
46+ // Return null if no parts, otherwise join with dots
47+ return parts . length > 0 ? parts . join ( "." ) : null ;
48+ }
49+
2250export async function updateExternalIdent (
2351 id : string ,
2452 unitType : "establishment" | "legal_unit" ,
@@ -54,18 +82,50 @@ export async function updateExternalIdent(
5482
5583 const unitIdField = `${ unitType } _id` ;
5684
57- const [ [ identTypeCode , newIdentValue ] ] = Object . entries ( validatedFields . data ) ;
58-
85+ // Get first key to determine which identifier type we're editing
86+ const firstKey = Object . keys ( validatedFields . data ) [ 0 ] ;
87+
88+ // Detect if this is a hierarchical identifier by checking for underscore pattern
89+ // e.g., "census_ident_census" -> "census_ident"
90+ const identTypeCode = firstKey . includes ( "_" ) &&
91+ externalIdentTypes . some ( t => t . shape === "hierarchical" && firstKey . startsWith ( t . code + "_" ) )
92+ ? firstKey . substring ( 0 , firstKey . lastIndexOf ( "_" ) )
93+ : firstKey ;
94+
95+ // For hierarchical types, find the actual type code by checking prefixes
5996 const identType = externalIdentTypes . find (
60- ( type ) => type . code === identTypeCode
97+ ( type ) => {
98+ if ( type . shape === "hierarchical" && type . labels ) {
99+ // Check if any form key starts with this type's code followed by underscore
100+ return Object . keys ( validatedFields . data ) . some ( key =>
101+ key . startsWith ( type . code + "_" )
102+ ) ;
103+ }
104+ return type . code === firstKey ;
105+ }
61106 ) ;
107+
62108 if ( ! identType ) {
63109 return {
64110 status : "error" ,
65- message : `Invalid external identifier type: ${ identTypeCode } ` ,
111+ message : `Invalid external identifier type: ${ firstKey } ` ,
66112 } ;
67113 }
68114 const identTypeId = identType . id ;
115+ const isHierarchical = identType . shape === "hierarchical" ;
116+
117+ // Construct the value based on identifier type
118+ let newIdentValue : string | null = null ;
119+ if ( isHierarchical && identType . labels ) {
120+ newIdentValue = constructHierarchicalPath (
121+ identType . code ! ,
122+ identType . labels ,
123+ validatedFields . data
124+ ) ;
125+ } else {
126+ newIdentValue = validatedFields . data [ firstKey ] || null ;
127+ }
128+
69129 try {
70130 const { data : exisitingIdent , error } = await client
71131 . from ( "external_ident" )
@@ -85,7 +145,7 @@ export async function updateExternalIdent(
85145 if ( count === 1 ) {
86146 return {
87147 status : "error" ,
88- message : `Cannot delete ${ identTypeCode } . Unit must have at least one external identifier.` ,
148+ message : `Cannot delete ${ identType . code } . Unit must have at least one external identifier.` ,
89149 } ;
90150 }
91151 response = await client
@@ -94,40 +154,59 @@ export async function updateExternalIdent(
94154 . eq ( "type_id" , identTypeId ! )
95155 . eq ( unitIdField , parseInt ( id ) ) ;
96156 } else if ( ! exisitingIdent || exisitingIdent . length === 0 ) {
97- response = await client . from ( "external_ident" ) . insert ( {
98- ident : newIdentValue ,
157+ // Note: 'shape' and 'labels' are derived by trigger from type_id
158+ // but TypeScript requires them. The trigger will override our value.
159+ const insertData : Record < string , unknown > = {
99160 [ unitIdField ] : parseInt ( id ) ,
100161 type_id : identTypeId ! ,
101162 edit_by_user_id : userId ,
102- } ) ;
163+ shape : identType . shape ! , // Will be overwritten by trigger
164+ } ;
165+
166+ if ( isHierarchical ) {
167+ insertData . idents = newIdentValue ;
168+ } else {
169+ insertData . ident = newIdentValue ;
170+ }
171+
172+ response = await client . from ( "external_ident" ) . insert ( insertData ) ;
103173 } else {
174+ const updateData : Record < string , unknown > = {
175+ edit_by_user_id : userId ,
176+ edit_at : new Date ( ) . toISOString ( ) ,
177+ } ;
178+
179+ if ( isHierarchical ) {
180+ updateData . idents = newIdentValue ;
181+ updateData . ident = null ; // Clear the regular ident field
182+ } else {
183+ updateData . ident = newIdentValue ;
184+ updateData . idents = null ; // Clear the hierarchical idents field
185+ }
186+
104187 response = await client
105188 . from ( "external_ident" )
106- . update ( {
107- ident : newIdentValue ,
108- edit_by_user_id : userId ,
109- edit_at : new Date ( ) . toISOString ( ) ,
110- } )
189+ . update ( updateData )
111190 . eq ( "type_id" , identTypeId ! )
112191 . eq ( unitIdField , parseInt ( id ) ) ;
113192 }
114193 if ( response ?. error ) {
115- logger . error ( response . error , `failed to update ${ identTypeCode } ` ) ;
194+ logger . error ( response . error , `failed to update ${ identType . code } ` ) ;
116195 return {
117196 status : "error" ,
118- message : `failed to update ${ identTypeCode } : ${ response . error . message } ` ,
197+ message : `failed to update ${ identType . code } : ${ response . error . message } ` ,
119198 } ;
120199 }
121200
122201 revalidatePath ( `/${ unitType } s/${ id } ` ) ;
123202 return {
124203 status : "success" ,
125- message : `${ identTypeCode } successfully updated` ,
204+ message : `${ identType . code } successfully updated` ,
126205 } ;
127206 } catch ( error ) {
128207 return {
129208 status : "error" ,
130- message : `failed to update ${ identTypeCode } ` ,
209+ message : `failed to update ${ identType . code } ` ,
131210 } ;
132211 }
133212}
0 commit comments