diff --git a/lib/utils/entity-mapper.ts b/lib/utils/entity-mapper.ts index 595e11b..a604518 100644 --- a/lib/utils/entity-mapper.ts +++ b/lib/utils/entity-mapper.ts @@ -564,41 +564,60 @@ function mapConfigurationItem(data: any): Record { * Map Contact entity */ function mapContact(data: any): Record { + // Convert userDefinedFields array → JSONB object { name: value } + const udfs: Record = {}; + if (Array.isArray(data.userDefinedFields)) { + for (const udf of data.userDefinedFields) { + udfs[udf.name] = udf.value ?? null; + } + } + return { id: data.id, company_id: data.companyID, first_name: data.firstName, last_name: data.lastName, + middle_initial: data.middleInitial, title: data.title, - email_address: data.emailAddress || data.email_address || data.email, - email_address2: data.emailAddress2 || data.email_address2, - email_address3: data.emailAddress3 || data.email_address3, + email_address: data.emailAddress, + email_address2: data.emailAddress2, + email_address3: data.emailAddress3, phone: data.phone, extension: data.extension, - alternate_phone: data.alternate_phone, - mobile_phone: data.mobile_phone, - fax: data.faxNumber || data.fax, - address_line: data.addressLine || data.address_line, - address_line1: data.addressLine1 || data.address_line1 || data.address_line_1, + alternate_phone: data.alternatePhone, + mobile_phone: data.mobilePhone, + fax: data.faxNumber, + address_line: data.addressLine, + address_line1: data.addressLine1, city: data.city, state: data.state, - zip_code: data.zipCode || data.zip_code || data.postal_code, - country: data.country, - is_active: data.is_active !== undefined ? data.is_active : true, - name_prefix: data.name_prefix, - name_suffix: data.name_suffix, - facebook_url: data.facebook_url, - twitter_url: data.twitter_url, - linked_in_url: data.linked_in_url, - primary_contact: data.primary_contact || false, - account_physical_location_id: data.account_physical_location_id, - solicitation_opt_out: data.solicitation_opt_out || false, - room_number: data.room_number, - last_activity_date: data.last_activity_date, - last_modified_date: data.last_modified_date, - api_vendor_id: data.api_vendor_id, - synced_at: data.synced_at, - is_deleted: data.is_deleted || false, + zip_code: data.zipCode, + country_id: data.countryID, + company_location_id: data.companyLocationID, + is_active: data.isActive !== undefined ? data.isActive : true, + name_prefix: data.namePrefix, + name_suffix: data.nameSuffix, + facebook_url: data.facebookUrl, + twitter_url: data.twitterUrl, + linked_in_url: data.linkedInUrl, + primary_contact: data.primaryContact || false, + billing_contact: data.billingContact || false, + solicitation_opt_out: data.solicitationOptOut || false, + solicitation_opt_out_time: data.solicitationOptOutTime, + survey_opt_out: data.surveyOptOut || false, + is_opted_out_from_bulk_email: data.isOptedOutFromBulkEmail || false, + bulk_email_opt_out_time: data.bulkEmailOptOutTime, + receives_email_notifications: data.receivesEmailNotifications !== undefined ? data.receivesEmailNotifications : true, + room_number: data.roomNumber, + note: data.note, + external_id: data.externalID, + api_vendor_id: data.apiVendorID, + impersonator_creator_resource_id: data.impersonatorCreatorResourceID, + create_date: data.createDate, + last_activity_date: data.lastActivityDate, + last_modified_date: data.lastModifiedDate, + user_defined_fields: Object.keys(udfs).length > 0 ? JSON.stringify(udfs) : null, + is_deleted: data.isDeleted || false, }; } diff --git a/migrations/057_contacts_missing_fields.sql b/migrations/057_contacts_missing_fields.sql new file mode 100644 index 0000000..c0158f9 --- /dev/null +++ b/migrations/057_contacts_missing_fields.sql @@ -0,0 +1,20 @@ +-- Migration 057: Add missing contacts fields + UDF storage + +ALTER TABLE contacts + ADD COLUMN IF NOT EXISTS user_defined_fields JSONB, + ADD COLUMN IF NOT EXISTS middle_initial VARCHAR(10), + ADD COLUMN IF NOT EXISTS note TEXT, + ADD COLUMN IF NOT EXISTS external_id VARCHAR(50), + ADD COLUMN IF NOT EXISTS country_id INTEGER, + ADD COLUMN IF NOT EXISTS company_location_id BIGINT, + ADD COLUMN IF NOT EXISTS create_date TIMESTAMP WITHOUT TIME ZONE, + ADD COLUMN IF NOT EXISTS is_opted_out_from_bulk_email BOOLEAN DEFAULT false, + ADD COLUMN IF NOT EXISTS bulk_email_opt_out_time TIMESTAMP WITHOUT TIME ZONE, + ADD COLUMN IF NOT EXISTS solicitation_opt_out_time TIMESTAMP WITHOUT TIME ZONE, + ADD COLUMN IF NOT EXISTS survey_opt_out BOOLEAN DEFAULT false, + ADD COLUMN IF NOT EXISTS receives_email_notifications BOOLEAN DEFAULT true, + ADD COLUMN IF NOT EXISTS billing_contact BOOLEAN DEFAULT false, + ADD COLUMN IF NOT EXISTS impersonator_creator_resource_id BIGINT; + +-- GIN index for UDF queries (e.g. find by UserID, O365License) +CREATE INDEX IF NOT EXISTS idx_contacts_udfs ON contacts USING gin(user_defined_fields);