@@ -183,4 +183,139 @@ BEGIN
183183 WHERE
184184 rn = 1 ;
185185END;
186+ $$;
187+
188+
189+
190+ CREATE OR REPLACE FUNCTION private .enrich_contacts(p_contacts_data jsonb[], p_update_empty_fields_only boolean DEFAULT true) RETURNS void
191+ LANGUAGE plpgsql
192+ SET search_path = ' '
193+ AS $$
194+ DECLARE
195+ contact_record JSONB;
196+ organization_id UUID;
197+ works_for_name TEXT ;
198+ new_name TEXT ;
199+ new_alternate_name TEXT [];
200+ old_name TEXT ;
201+ old_alternate_name TEXT [];
202+
203+ phone_number TEXT ;
204+ new_telephone TEXT [];
205+ old_telephone TEXT [];
206+ merged_telephone TEXT [];
207+
208+ BEGIN
209+ -- Assert that all records have email and user_id
210+ IF EXISTS (
211+ SELECT 1
212+ FROM unnest(p_contacts_data) AS contact
213+ WHERE contact- >> ' email' IS NULL OR contact- >> ' user_id' IS NULL
214+ ) THEN
215+ RAISE EXCEPTION ' All records in p_contacts_data must contain email and user_id fields' ;
216+ END IF;
217+
218+ FOREACH contact_record IN ARRAY p_contacts_data
219+ LOOP
220+
221+
222+ works_for_name := contact_record- >> ' works_for' ;
223+ IF works_for_name IS NOT NULL THEN
224+ SELECT id INTO organization_id
225+ FROM private .organizations
226+ WHERE name = works_for_name
227+ LIMIT 1 ;
228+
229+ IF NOT FOUND THEN
230+ INSERT INTO private .organizations (name)
231+ VALUES (works_for_name)
232+ RETURNING id INTO organization_id;
233+ END IF;
234+ ELSE
235+ organization_id := NULL ;
236+ END IF;
237+
238+ -- Merge incoming phone numbers into telephone array
239+ new_telephone := string_to_array(NULLIF(contact_record- >> ' telephone' , ' ' ), ' ,' );
240+
241+ IF new_telephone IS NOT NULL THEN
242+ SELECT p .telephone
243+ INTO old_telephone
244+ FROM private .persons p
245+ WHERE p .email = contact_record- >> ' email'
246+ AND p .user_id = (contact_record- >> ' user_id' )::UUID
247+ LIMIT 1 ;
248+
249+ IF old_telephone IS NOT NULL THEN
250+ -- append only the truly new ones
251+ FOREACH phone_number IN ARRAY new_telephone LOOP
252+ IF NOT phone_number = ANY(old_telephone) THEN
253+ old_telephone := ARRAY_APPEND(old_telephone, phone_number);
254+ END IF;
255+ END LOOP;
256+ merged_telephone := old_telephone;
257+ ELSE
258+ -- no existing array → just take new
259+ merged_telephone := new_telephone;
260+ END IF;
261+ END IF;
262+
263+ -- Add name into alternate_name if name is already filled
264+ new_name := contact_record- >> ' name' ;
265+ IF new_name IS NOT NULL THEN
266+ SELECT p .name , p .alternate_name
267+ INTO old_name, old_alternate_name
268+ FROM private .persons p
269+ WHERE p .email = contact_record- >> ' email' AND p .user_id = (contact_record- >> ' user_id' )::UUID
270+ LIMIT 1 ;
271+ IF old_name IS NOT NULL THEN
272+ IF (old_name != new_name AND (old_alternate_name IS NULL OR NOT(new_name = ANY(old_alternate_name)))) THEN
273+ new_alternate_name := ARRAY_APPEND(old_alternate_name, new_name);
274+ END IF;
275+ new_name := old_name;
276+ END IF;
277+ END IF;
278+
279+ IF p_update_empty_fields_only THEN
280+ UPDATE private .persons pp
281+ SET
282+ name = COALESCE(pp .name , new_name::TEXT ),
283+ url = COALESCE(pp .url , (contact_record- >> ' url' )::TEXT ),
284+ image = COALESCE(pp .image , (contact_record- >> ' image' )::TEXT ),
285+ location = COALESCE(pp .location , NULLIF(contact_record- >> ' location' , ' ' )),
286+ alternate_name = COALESCE(pp .alternate_name , (new_alternate_name)::TEXT []),
287+ same_as = COALESCE(pp .same_as , string_to_array(NULLIF(contact_record- >> ' same_as' , ' ' ), ' ,' )::TEXT []),
288+ given_name = COALESCE(pp .given_name , (contact_record- >> ' given_name' )::TEXT ),
289+ family_name = COALESCE(pp .family_name , (contact_record- >> ' family_name' )::TEXT ),
290+ job_title = COALESCE(pp .job_title , (contact_record- >> ' job_title' )::TEXT ),
291+ works_for = COALESCE(pp .works_for , organization_id),
292+ identifiers = COALESCE(pp .identifiers , string_to_array(NULLIF(contact_record- >> ' identifiers' , ' ' ), ' ,' )::TEXT []),
293+ status = COALESCE(pp .status , (contact_record- >> ' status' )::TEXT ),
294+ telephone = COALESCE(pp .telephone , (merged_telephone)::TEXT [])
295+ WHERE
296+ email = (contact_record- >> ' email' )::TEXT AND
297+ user_id = (contact_record- >> ' user_id' )::UUID;
298+ ELSE
299+ UPDATE private .persons pp
300+ SET
301+ name = COALESCE(new_name::TEXT , pp .name ),
302+ url = COALESCE((contact_record- >> ' url' )::TEXT , pp .url ),
303+ image = COALESCE((contact_record- >> ' image' )::TEXT , pp .image ),
304+ location = COALESCE(pp .location , NULLIF(contact_record- >> ' location' , ' ' )),
305+ alternate_name = COALESCE((new_alternate_name)::TEXT [], pp .alternate_name ),
306+ same_as = COALESCE(string_to_array(NULLIF(contact_record- >> ' same_as' , ' ' ), ' ,' )::TEXT [], pp .same_as ),
307+ given_name = COALESCE((contact_record- >> ' given_name' )::TEXT , pp .given_name ),
308+ family_name = COALESCE((contact_record- >> ' family_name' )::TEXT , pp .family_name ),
309+ job_title = COALESCE((contact_record- >> ' job_title' )::TEXT , pp .job_title ),
310+ works_for = COALESCE(organization_id, pp .works_for ),
311+ identifiers = COALESCE(string_to_array(NULLIF(contact_record- >> ' identifiers' , ' ' ), ' ,' )::TEXT [], pp .identifiers ),
312+ status = COALESCE((contact_record- >> ' status' )::TEXT , pp .status ),
313+ telephone = COALESCE((merged_telephone)::TEXT [], pp .telephone )
314+
315+ WHERE
316+ email = (contact_record- >> ' email' )::TEXT AND
317+ user_id = (contact_record- >> ' user_id' )::UUID;
318+ END IF;
319+ END LOOP;
320+ END;
186321$$;
0 commit comments