From 6d87bbb863666cde7157b0d64a0323b82f9d5d69 Mon Sep 17 00:00:00 2001 From: aditya-balachander Date: Fri, 2 Feb 2024 02:41:10 +0530 Subject: [PATCH] Fix `is_person_type` `AttributeError` in record type handling (#3739) Fix for [issue](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007XIPZMSA5) related to your recent PR ([3702](https://github.com/SFDO-Tooling/CumulusCI/pull/3702)). **Error Message:** `AttributeError: is_person_type` **Issue Reason:** During load, the tasks expects the column `is+person_type` to be present in the record type table `rt_mapping_table`. This column is present for sql files which do extract after the new release of CumulusCI (v3.84.0) but will not be present for existing sql files. **Fix:** Previously the `outerjoins_to_add` function of the `AddRecordTypesToQuery` class checks if the combination of `is_person_type` and `developer_name` is unique. Now, if the `rt_mapping_table` does not have the `is_person_type` table, the task ignores the condition to check for record types based on `is_person_type` and only checks for `developer_name` (as it was previous to this PR [3702](https://github.com/SFDO-Tooling/CumulusCI/pull/3702)) --------- Co-authored-by: Jaipal Reddy Kasturi --- .../tasks/bulkdata/query_transformers.py | 15 +++++++-- .../tasks/bulkdata/tests/recordtypes.sql | 5 ++- .../tasks/bulkdata/tests/recordtypes_2.sql | 5 ++- .../tests/recordtypes_with_ispersontype.sql | 33 +++++++++++++++++++ .../tests/recordtypes_with_ispersontype.yml | 8 +++++ cumulusci/tasks/bulkdata/tests/test_load.py | 13 +++++++- 6 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.sql create mode 100644 cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.yml diff --git a/cumulusci/tasks/bulkdata/query_transformers.py b/cumulusci/tasks/bulkdata/query_transformers.py index cbc50e389a..61d42cd8cb 100644 --- a/cumulusci/tasks/bulkdata/query_transformers.py +++ b/cumulusci/tasks/bulkdata/query_transformers.py @@ -128,6 +128,18 @@ def outerjoins_to_add(self): rt_dest_table = self.metadata.tables[ self.mapping.get_destination_record_type_table() ] + + # Check if 'is_person_type' column exists in rt_source_table.columns + is_person_type_column = getattr( + rt_source_table.columns, "is_person_type", None + ) + # If it does not exist, set condition to True + is_person_type_condition = ( + rt_dest_table.columns.is_person_type == is_person_type_column + if is_person_type_column is not None + else True + ) + return [ ( rt_source_table, @@ -140,8 +152,7 @@ def outerjoins_to_add(self): and_( rt_dest_table.columns.developer_name == rt_source_table.columns.developer_name, - rt_dest_table.columns.is_person_type - == rt_source_table.columns.is_person_type, + is_person_type_condition, ), ), ] diff --git a/cumulusci/tasks/bulkdata/tests/recordtypes.sql b/cumulusci/tasks/bulkdata/tests/recordtypes.sql index be1f7f370d..5d3e08c9d6 100644 --- a/cumulusci/tasks/bulkdata/tests/recordtypes.sql +++ b/cumulusci/tasks/bulkdata/tests/recordtypes.sql @@ -2,11 +2,10 @@ BEGIN TRANSACTION; CREATE TABLE "Account_rt_mapping" ( record_type_id VARCHAR(18) NOT NULL, developer_name VARCHAR(255), - is_person_type BOOLEAN, PRIMARY KEY (record_type_id) ); -INSERT INTO "Account_rt_mapping" VALUES('012P0000000bCMdIAM','Organization',0); -INSERT INTO "Account_rt_mapping" VALUES('012P0000000bCQqIAM','Subsidiary',0); +INSERT INTO "Account_rt_mapping" VALUES('012P0000000bCMdIAM','Organization'); +INSERT INTO "Account_rt_mapping" VALUES('012P0000000bCQqIAM','Subsidiary'); CREATE TABLE accounts ( sf_id VARCHAR(255) NOT NULL, "Name" VARCHAR(255), diff --git a/cumulusci/tasks/bulkdata/tests/recordtypes_2.sql b/cumulusci/tasks/bulkdata/tests/recordtypes_2.sql index 1d23fc4a8d..9415a439e4 100644 --- a/cumulusci/tasks/bulkdata/tests/recordtypes_2.sql +++ b/cumulusci/tasks/bulkdata/tests/recordtypes_2.sql @@ -2,11 +2,10 @@ BEGIN TRANSACTION; CREATE TABLE Beta_rt_mapping ( record_type_id VARCHAR(18) NOT NULL, developer_name VARCHAR(255), - is_person_type BOOLEAN, PRIMARY KEY (record_type_id) ); -INSERT INTO "Beta_rt_mapping" VALUES('012H40000003jCoIAI','recordtype2',0); -INSERT INTO "Beta_rt_mapping" VALUES('012H40000003jCZIAY','recordtype1',0); +INSERT INTO "Beta_rt_mapping" VALUES('012H40000003jCoIAI','recordtype2'); +INSERT INTO "Beta_rt_mapping" VALUES('012H40000003jCZIAY','recordtype1'); CREATE TABLE Beta ( id INTEGER NOT NULL, "Name" VARCHAR(255), diff --git a/cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.sql b/cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.sql new file mode 100644 index 0000000000..be1f7f370d --- /dev/null +++ b/cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.sql @@ -0,0 +1,33 @@ +BEGIN TRANSACTION; +CREATE TABLE "Account_rt_mapping" ( + record_type_id VARCHAR(18) NOT NULL, + developer_name VARCHAR(255), + is_person_type BOOLEAN, + PRIMARY KEY (record_type_id) +); +INSERT INTO "Account_rt_mapping" VALUES('012P0000000bCMdIAM','Organization',0); +INSERT INTO "Account_rt_mapping" VALUES('012P0000000bCQqIAM','Subsidiary',0); +CREATE TABLE accounts ( + sf_id VARCHAR(255) NOT NULL, + "Name" VARCHAR(255), + "Description" VARCHAR(255), + "Street" VARCHAR(255), + "City" VARCHAR(255), + "State" VARCHAR(255), + "PostalCode" VARCHAR(255), + "Country" VARCHAR(255), + "Phone" VARCHAR(255), + "Fax" VARCHAR(255), + "Website" VARCHAR(255), + "NumberOfEmployees" VARCHAR(255), + "AccountNumber" VARCHAR(255), + "Site" VARCHAR(255), + "Type" VARCHAR(255), + "RecordTypeId" VARCHAR(255), + parent_id VARCHAR(255), + PRIMARY KEY (sf_id) +); +INSERT INTO "accounts" VALUES('001P000001ZgnJYIAZ','','This is the parent account.','111 Main St.','Nowhereton','NE','11111','USA','5055551212','5055551213','www.acme.com','100','1','Local','Prospect','012P0000000bCMdIAM',''); +INSERT INTO "accounts" VALUES('001P000001ZgnJZIAZ','','','','','','','','','','','','','','','012P0000000bCQqIAM','001P000001ZgnJYIAZ'); +INSERT INTO "accounts" VALUES('001P000001ZgnJaIAJ','','','','','','','','','','','','','','','',''); +INSERT INTO "accounts" VALUES('001P000001ZgnTHIAZ','','','','','','','','','','','','','','','012P0000000bCQqIAM','001P000001ZgnJZIAZ'); diff --git a/cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.yml b/cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.yml new file mode 100644 index 0000000000..5f8ec1fc6e --- /dev/null +++ b/cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.yml @@ -0,0 +1,8 @@ +Insert Accounts: + api: bulk + sf_object: Account + table: accounts + fields: + Id: sf_id + Name: Name + RecordTypeId: RecordTypeId diff --git a/cumulusci/tasks/bulkdata/tests/test_load.py b/cumulusci/tasks/bulkdata/tests/test_load.py index a4293910dd..3be11dbdac 100644 --- a/cumulusci/tasks/bulkdata/tests/test_load.py +++ b/cumulusci/tasks/bulkdata/tests/test_load.py @@ -1931,6 +1931,18 @@ def test_query_db__record_type_mapping(self): sql_path="cumulusci/tasks/bulkdata/tests/recordtypes.sql", mapping="cumulusci/tasks/bulkdata/tests/recordtypes.yml", mapping_step_name="Insert Accounts", + expected="""SELECT accounts.sf_id AS accounts_sf_id, accounts."Name" AS "accounts_Name", "Account_rt_target_mapping".record_type_id AS "Account_rt_target_mapping_record_type_id" + FROM accounts + LEFT OUTER JOIN "Account_rt_mapping" ON "Account_rt_mapping".record_type_id = accounts."RecordTypeId" + LEFT OUTER JOIN "Account_rt_target_mapping" ON "Account_rt_target_mapping".developer_name = "Account_rt_mapping".developer_name + """, + ) + + def test_query_db__record_type_mapping__with_ispersontype(self): + _validate_query_for_mapping_step( + sql_path="cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.sql", + mapping="cumulusci/tasks/bulkdata/tests/recordtypes_with_ispersontype.yml", + mapping_step_name="Insert Accounts", expected="""SELECT accounts.sf_id AS accounts_sf_id, accounts."Name" AS "accounts_Name", "Account_rt_target_mapping".record_type_id AS "Account_rt_target_mapping_record_type_id" FROM accounts LEFT OUTER JOIN "Account_rt_mapping" ON "Account_rt_mapping".record_type_id = accounts."RecordTypeId" @@ -1948,7 +1960,6 @@ def test_query_db__record_type_mapping_table_from_tablename(self): FROM "Beta" LEFT OUTER JOIN "Beta_rt_mapping" ON "Beta_rt_mapping".record_type_id = "Beta"."RecordType" LEFT OUTER JOIN "Account_rt_target_mapping" ON "Account_rt_target_mapping".developer_name = "Beta_rt_mapping".developer_name - AND "Account_rt_target_mapping".is_person_type = "Beta_rt_mapping".is_person_type """, )