diff --git a/app/pipedrive/_schema.py b/app/pipedrive/_schema.py index 8bd57ea..24f00f9 100644 --- a/app/pipedrive/_schema.py +++ b/app/pipedrive/_schema.py @@ -392,7 +392,12 @@ async def handle_duplicate_hermes_ids(hermes_ids: str, object_type: str) -> int: await pipedrive_request(f'deals/{main_object.pd_deal_id}', method='PUT', data=hermes_deal_data) app_logger.info(f'Updated deal {main_object.pd_deal_id} from deal {main_object.id} by deal.pd_deal_id') - return main_object.id + + + # we should actually break here, as if we continue, we will be updating with the incorrect data, and we have just updated, which should in turn trigger the webhook again + + else: + raise ValueError(f'Unknown object type {object_type}') class PipedriveEvent(HermesBaseModel): diff --git a/app/pipedrive/views.py b/app/pipedrive/views.py index a549e89..9e241bd 100644 --- a/app/pipedrive/views.py +++ b/app/pipedrive/views.py @@ -11,7 +11,7 @@ _process_pd_pipeline, _process_pd_stage, ) -from app.pipedrive._schema import PDObjectNames, PDStatus, PipedriveEvent +from app.pipedrive._schema import PDObjectNames, PDStatus, PipedriveEvent, handle_duplicate_hermes_ids from app.pipedrive._utils import app_logger from app.tc2.tasks import update_client_from_company @@ -28,21 +28,26 @@ async def prepare_event_data(event_data: dict) -> dict: different. If they are, it sets the current value back to the previous value. """ - async def handle_custom_field(data: dict, field_name: str, handle_func: Union[Callable, str] = None): + async def handle_custom_field(data: dict, field_name: str, handle_func: str) -> Union[dict, None]: cf_fields = await CustomField.filter(machine_name=field_name).values_list('pd_field_id', flat=True) for pd_field_id in cf_fields: for state in [PDStatus.PREVIOUS, PDStatus.CURRENT]: + # check if the field exists in the data and if the value is a string if data.get(state) and pd_field_id in data[state] and isinstance(data[state][pd_field_id], str): if handle_func == 'revert changes': if state == PDStatus.PREVIOUS: data[PDStatus.CURRENT][pd_field_id] = data[PDStatus.PREVIOUS][pd_field_id] - if callable(handle_func): - data[state][pd_field_id] = await handle_func(data[state][pd_field_id], data['meta']['object']) + if handle_func == 'handle_duplicate_hermes_ids': + # if current value is a string, handle duplicate hermes_id + if state == PDStatus.CURRENT: + data[state][pd_field_id] = await handle_duplicate_hermes_ids(data[state][pd_field_id], data['meta']['object']) + + # overwrite the previous value with the current value to avoid duplicate hermes_id validation error later + data[PDStatus.PREVIOUS][pd_field_id] = data[state][pd_field_id] return data - ## TODO: Re-enable in #282 - # event_data = await handle_custom_field(event_data, 'hermes_id', handle_duplicate_hermes_ids) + event_data = await handle_custom_field(event_data, 'hermes_id', 'handle_duplicate_hermes_ids') event_data = await handle_custom_field(event_data, 'signup_questionnaire', 'revert changes') diff --git a/tests/test_combined.py b/tests/test_combined.py index 8527bab..6da5343 100644 --- a/tests/test_combined.py +++ b/tests/test_combined.py @@ -1278,423 +1278,422 @@ async def test_pd_post_process_client_event_value_error(self, mock_pd_request): await sales_person.delete() await build_custom_field_schema() - ## TODO: Re-enable in #282 - # @mock.patch('app.pipedrive.api.session.request') - # async def test_duplicate_hermes_ids_in_pd(self, mock_pd_request): - # mock_pd_request.side_effect = fake_pd_request(self.pipedrive) - # - # admin = await Admin.create( - # tc2_admin_id=30, - # first_name='Brain', - # last_name='Johnson', - # username='brian@tc.com', - # password='foo', - # pd_owner_id=10, - # ) - # - # await Company.create(id=1, name='Old test company', sales_person=admin, pd_org_id=1) - # await Company.create(id=2, name='Another test company', sales_person=admin, pd_org_id=2) - # - # self.pipedrive.db['organizations'] = { - # 1: { - # 'id': 1, - # 'name': 'Old test company', - # 'address_country': None, - # 'owner_id': 10, - # '123_hermes_id_456': '1, 2', - # '123_sales_person_456': admin.id, - # }, - # } - # - # data = copy.deepcopy(basic_pd_org_data()) - # data[PDStatus.PREVIOUS] = copy.deepcopy(data[PDStatus.CURRENT]) - # data[PDStatus.CURRENT].update({'123_hermes_id_456': '1, 2'}) - # r = await self.client.post(self.pipedrive_callback, json=data) - # assert r.status_code == 200 - # - # assert await Company.exists(id=1) - # assert not await Company.exists(id=2) - # - # assert self.pipedrive.db['organizations'] == { - # 1: { - # 'id': 1, - # 'name': 'Old test company', - # 'address_country': None, - # 'owner_id': 10, - # '123_hermes_id_456': 1, - # '123_sales_person_456': admin.id, - # }, - # } - # - # @mock.patch('app.pipedrive.api.session.request') - # async def test_deal_update_merged_please(self, mock_pd_request): - # mock_pd_request.side_effect = fake_pd_request(self.pipedrive) - # - # self.pipedrive.db = { - # 'organizations': { - # 1: { - # 'id': 1, - # 'name': 'Test company', - # 'address_country': 'GB', - # 'owner_id': None, - # '123_hermes_id_456': 1, - # } - # }, - # 'deals': { - # 1: { - # 'title': 'Old test deal', - # 'org_id': 1, - # 'person_id': None, - # 'pipeline_id': 1, - # 'stage_id': 1, - # 'status': 'open', - # 'id': 1, - # 'user_id': 1, - # '345_hermes_id_678': 1, - # }, - # 2: { - # 'title': 'Old test deal2', - # 'org_id': 1, - # 'person_id': None, - # 'pipeline_id': 1, - # 'stage_id': 1, - # 'status': 'open', - # 'id': 2, - # 'user_id': 1, - # '345_hermes_id_678': 2, - # }, - # }, - # 'persons': { - # 1: { - # 'id': 1, - # 'name': 'Brian Blessed', - # 'email': 'brian@tc.com', - # 'org_id': 1, - # '234_hermes_id_567': 1, - # } - # }, - # 'pipelines': { - # 1: { - # 'id': 1, - # 'name': 'Pipeline 1', - # 'dft_entry_stage_id': 1, - # } - # }, - # 'stages': { - # 1: { - # 'id': 1, - # 'name': 'Stage 2', - # } - # }, - # } - # - # admin = await Admin.create( - # tc2_admin_id=30, - # first_name='Brain', - # last_name='Johnson', - # username='brian@tc.com', - # password='foo', - # pd_owner_id=1, - # ) - # - # company = await Company.create(name='Test company', pd_org_id=1, sales_person=admin) - # contact = await Contact.create(first_name='Brian', last_name='Blessed', pd_person_id=1, company=company) - # deal = await Deal.create( - # name='Old test deal', - # pd_deal_id=1, - # company=company, - # contact=contact, - # pipeline=self.pipeline, - # stage=self.stage, - # admin=admin, - # ) - # deal2 = await Deal.create( - # name='Old test deal2', - # pd_deal_id=2, - # company=company, - # contact=contact, - # pipeline=self.pipeline, - # stage=self.stage, - # admin=admin, - # ) - # - # start = datetime(2023, 1, 1, tzinfo=timezone.utc) - # meeting = await Meeting.create( - # company=company, - # contact=contact, - # meeting_type=Meeting.TYPE_SALES, - # start_time=start, - # end_time=start + timedelta(hours=1), - # admin=admin, - # deal=deal2, - # ) - # - # assert await Deal.exists() - # - # data = copy.deepcopy(basic_pd_deal_data()) - # data[PDStatus.CURRENT].update( - # **{ - # '345_hermes_id_678': f'{deal.id},{deal2.id}', - # 'title': 'Old test deal', - # 'org_id': 1, - # 'person_id': 1, - # 'pipeline_id': 1, - # 'stage_id': 1, - # 'status': 'open', - # 'user_id': 1, - # } - # ) - # data[PDStatus.PREVIOUS] = copy.deepcopy(data[PDStatus.CURRENT]) - # - # r = await self.client.post(self.pipedrive_callback, json=data) - # assert r.status_code == 200, r.json() - # deal = await Deal.get(id=deal.id) - # assert not await Deal.exists(id=deal2.id) - # - # assert deal.name == 'Old test deal' - # meeting2 = await Meeting.get(id=meeting.id) - # assert await meeting2.deal == deal - # - # @mock.patch('app.pipedrive.api.session.request') - # async def test_deal_update_merged_previous(self, mock_pd_request): - # mock_pd_request.side_effect = fake_pd_request(self.pipedrive) - # - # self.pipedrive.db = { - # 'organizations': { - # 1: { - # 'id': 1, - # 'name': 'Test company', - # 'address_country': 'GB', - # 'owner_id': None, - # '123_hermes_id_456': 1, - # } - # }, - # 'deals': { - # 1: { - # 'title': 'Old test deal', - # 'org_id': 1, - # 'person_id': None, - # 'pipeline_id': 1, - # 'stage_id': 1, - # 'status': 'open', - # 'id': 1, - # 'user_id': 1, - # '345_hermes_id_678': 1, - # }, - # 2: { - # 'title': 'Old test deal2', - # 'org_id': 1, - # 'person_id': None, - # 'pipeline_id': 1, - # 'stage_id': 1, - # 'status': 'open', - # 'id': 2, - # 'user_id': 1, - # '345_hermes_id_678': 2, - # }, - # }, - # 'persons': { - # 1: { - # 'id': 1, - # 'name': 'Brian Blessed', - # 'email': 'brian@tc.com', - # 'org_id': 1, - # '234_hermes_id_567': 1, - # } - # }, - # 'pipelines': { - # 1: { - # 'id': 1, - # 'name': 'Pipeline 1', - # 'dft_entry_stage_id': 1, - # } - # }, - # 'stages': { - # 1: { - # 'id': 1, - # 'name': 'Stage 2', - # } - # }, - # } - # - # admin = await Admin.create( - # tc2_admin_id=30, - # first_name='Brain', - # last_name='Johnson', - # username='brian@tc.com', - # password='foo', - # pd_owner_id=1, - # ) - # - # company = await Company.create(name='Test company', pd_org_id=1, sales_person=admin) - # contact = await Contact.create(first_name='Brian', last_name='Blessed', pd_person_id=1, company=company) - # deal = await Deal.create( - # name='Old test deal', - # pd_deal_id=1, - # company=company, - # contact=contact, - # pipeline=self.pipeline, - # stage=self.stage, - # admin=admin, - # ) - # deal2 = await Deal.create( - # name='Old test deal2', - # pd_deal_id=2, - # company=company, - # contact=contact, - # pipeline=self.pipeline, - # stage=self.stage, - # admin=admin, - # ) - # - # start = datetime(2023, 1, 1, tzinfo=timezone.utc) - # meeting = await Meeting.create( - # company=company, - # contact=contact, - # meeting_type=Meeting.TYPE_SALES, - # start_time=start, - # end_time=start + timedelta(hours=1), - # admin=admin, - # deal=deal2, - # ) - # - # assert await Deal.exists() - # - # data = copy.deepcopy(basic_pd_deal_data()) - # data[PDStatus.CURRENT].update( - # **{ - # '345_hermes_id_678': f'{deal.id},{deal2.id}', - # 'title': 'Old test deal', - # 'org_id': 1, - # 'person_id': 1, - # 'pipeline_id': 1, - # 'stage_id': 1, - # 'status': 'open', - # 'user_id': 1, - # } - # ) - # data[PDStatus.PREVIOUS] = copy.deepcopy(data[PDStatus.CURRENT]) - # data[PDStatus.CURRENT].update(title='New test deal') - # r = await self.client.post(self.pipedrive_callback, json=data) - # assert r.status_code == 200, r.json() - # deal = await Deal.get() - # assert deal.name == 'New test deal' - # meeting2 = await Meeting.get(id=meeting.id) - # assert await meeting2.deal == deal - # - # @mock.patch('app.pipedrive.api.session.request') - # async def test_person_merged_hermes_ids(self, mock_pd_request): - # mock_pd_request.side_effect = fake_pd_request(self.pipedrive) - # - # self.pipedrive.db = { - # 'organizations': { - # 1: { - # 'id': 1, - # 'name': 'Test company', - # 'address_country': 'GB', - # 'owner_id': None, - # '123_hermes_id_456': 1, - # } - # }, - # 'deals': { - # 1: { - # 'title': 'Old test deal', - # 'org_id': 1, - # 'person_id': None, - # 'pipeline_id': 1, - # 'stage_id': 1, - # 'status': 'open', - # 'id': 1, - # 'user_id': 1, - # '345_hermes_id_678': 1, - # }, - # 2: { - # 'title': 'Old test deal2', - # 'org_id': 1, - # 'person_id': None, - # 'pipeline_id': 1, - # 'stage_id': 1, - # 'status': 'open', - # 'id': 2, - # 'user_id': 1, - # '345_hermes_id_678': 2, - # }, - # }, - # 'persons': { - # 1: { - # 'id': 1, - # 'name': 'Brian Blessed', - # 'email': 'brian@tc.com', - # 'org_id': 1, - # '234_hermes_id_567': 1, - # }, - # 2: { - # 'id': 2, - # 'name': 'Brian Blessed', - # 'email': 'brian@tc.com', - # 'org_id': 1, - # '234_hermes_id_567': 2, - # }, - # }, - # 'pipelines': { - # 1: { - # 'id': 1, - # 'name': 'Pipeline 1', - # 'dft_entry_stage_id': 1, - # } - # }, - # 'stages': { - # 1: { - # 'id': 1, - # 'name': 'Stage 2', - # } - # }, - # } - # - # admin = await Admin.create( - # tc2_admin_id=30, - # first_name='Brain', - # last_name='Johnson', - # username='brian@tc.com', - # password='foo', - # pd_owner_id=1, - # ) - # - # company = await Company.create(name='Test company', pd_org_id=1, sales_person=admin) - # contact = await Contact.create(first_name='Brian', last_name='Blessed', pd_person_id=1, company=company) - # contact2 = await Contact.create(first_name='Brian', last_name='Blessed', pd_person_id=2, company=company) - # await Deal.create( - # name='Old test deal', - # pd_deal_id=1, - # company=company, - # contact=contact, - # pipeline=self.pipeline, - # stage=self.stage, - # admin=admin, - # ) - # await Deal.create( - # name='Old test deal2', - # pd_deal_id=2, - # company=company, - # contact=contact2, - # pipeline=self.pipeline, - # stage=self.stage, - # admin=admin, - # ) - # - # data = copy.deepcopy(basic_pd_person_data()) - # data[PDStatus.CURRENT].update( - # **{ - # '234_hermes_id_567': f'{contact.id},{contact2.id}', - # 'name': 'Brian Blessed', - # 'email': 'brian@tc.com', - # 'org_id': 1, - # 'owner_id': 1, - # } - # ) - # data[PDStatus.PREVIOUS] = copy.deepcopy(data[PDStatus.CURRENT]) - # - # r = await self.client.post(self.pipedrive_callback, json=data) - # assert r.status_code == 200, r.json() - # contact = await Contact.get() - # assert contact.name == 'Brian Blessed' + @mock.patch('app.pipedrive.api.session.request') + async def test_duplicate_hermes_ids_in_pd(self, mock_pd_request): + mock_pd_request.side_effect = fake_pd_request(self.pipedrive) + + admin = await Admin.create( + tc2_admin_id=30, + first_name='Brain', + last_name='Johnson', + username='brian@tc.com', + password='foo', + pd_owner_id=10, + ) + + await Company.create(id=1, name='Old test company', sales_person=admin, pd_org_id=1) + await Company.create(id=2, name='Another test company', sales_person=admin, pd_org_id=2) + + self.pipedrive.db['organizations'] = { + 1: { + 'id': 1, + 'name': 'Old test company', + 'address_country': None, + 'owner_id': 10, + '123_hermes_id_456': '1, 2', + '123_sales_person_456': admin.id, + }, + } + + data = copy.deepcopy(basic_pd_org_data()) + data[PDStatus.PREVIOUS] = copy.deepcopy(data[PDStatus.CURRENT]) + data[PDStatus.CURRENT].update({'123_hermes_id_456': '1, 2'}) + r = await self.client.post(self.pipedrive_callback, json=data) + assert r.status_code == 200 + + assert await Company.exists(id=1) + assert not await Company.exists(id=2) + + assert self.pipedrive.db['organizations'] == { + 1: { + 'id': 1, + 'name': 'Old test company', + 'address_country': None, + 'owner_id': 10, + '123_hermes_id_456': 1, + '123_sales_person_456': admin.id, + }, + } + + @mock.patch('app.pipedrive.api.session.request') + async def test_deal_update_merged_please(self, mock_pd_request): + mock_pd_request.side_effect = fake_pd_request(self.pipedrive) + + self.pipedrive.db = { + 'organizations': { + 1: { + 'id': 1, + 'name': 'Test company', + 'address_country': 'GB', + 'owner_id': None, + '123_hermes_id_456': 1, + } + }, + 'deals': { + 1: { + 'title': 'Old test deal', + 'org_id': 1, + 'person_id': None, + 'pipeline_id': 1, + 'stage_id': 1, + 'status': 'open', + 'id': 1, + 'user_id': 1, + '345_hermes_id_678': 1, + }, + 2: { + 'title': 'Old test deal2', + 'org_id': 1, + 'person_id': None, + 'pipeline_id': 1, + 'stage_id': 1, + 'status': 'open', + 'id': 2, + 'user_id': 1, + '345_hermes_id_678': 2, + }, + }, + 'persons': { + 1: { + 'id': 1, + 'name': 'Brian Blessed', + 'email': 'brian@tc.com', + 'org_id': 1, + '234_hermes_id_567': 1, + } + }, + 'pipelines': { + 1: { + 'id': 1, + 'name': 'Pipeline 1', + 'dft_entry_stage_id': 1, + } + }, + 'stages': { + 1: { + 'id': 1, + 'name': 'Stage 2', + } + }, + } + + admin = await Admin.create( + tc2_admin_id=30, + first_name='Brain', + last_name='Johnson', + username='brian@tc.com', + password='foo', + pd_owner_id=1, + ) + + company = await Company.create(name='Test company', pd_org_id=1, sales_person=admin) + contact = await Contact.create(first_name='Brian', last_name='Blessed', pd_person_id=1, company=company) + deal = await Deal.create( + name='Old test deal', + pd_deal_id=1, + company=company, + contact=contact, + pipeline=self.pipeline, + stage=self.stage, + admin=admin, + ) + deal2 = await Deal.create( + name='Old test deal2', + pd_deal_id=2, + company=company, + contact=contact, + pipeline=self.pipeline, + stage=self.stage, + admin=admin, + ) + + start = datetime(2023, 1, 1, tzinfo=timezone.utc) + meeting = await Meeting.create( + company=company, + contact=contact, + meeting_type=Meeting.TYPE_SALES, + start_time=start, + end_time=start + timedelta(hours=1), + admin=admin, + deal=deal2, + ) + + assert await Deal.exists() + + data = copy.deepcopy(basic_pd_deal_data()) + data[PDStatus.CURRENT].update( + **{ + '345_hermes_id_678': f'{deal.id},{deal2.id}', + 'title': 'Old test deal', + 'org_id': 1, + 'person_id': 1, + 'pipeline_id': 1, + 'stage_id': 1, + 'status': 'open', + 'user_id': 1, + } + ) + data[PDStatus.PREVIOUS] = copy.deepcopy(data[PDStatus.CURRENT]) + + r = await self.client.post(self.pipedrive_callback, json=data) + assert r.status_code == 200, r.json() + deal = await Deal.get(id=deal.id) + assert not await Deal.exists(id=deal2.id) + + assert deal.name == 'Old test deal' + meeting2 = await Meeting.get(id=meeting.id) + assert await meeting2.deal == deal + + @mock.patch('app.pipedrive.api.session.request') + async def test_deal_update_merged_previous(self, mock_pd_request): + mock_pd_request.side_effect = fake_pd_request(self.pipedrive) + + self.pipedrive.db = { + 'organizations': { + 1: { + 'id': 1, + 'name': 'Test company', + 'address_country': 'GB', + 'owner_id': None, + '123_hermes_id_456': 1, + } + }, + 'deals': { + 1: { + 'title': 'Old test deal', + 'org_id': 1, + 'person_id': None, + 'pipeline_id': 1, + 'stage_id': 1, + 'status': 'open', + 'id': 1, + 'user_id': 1, + '345_hermes_id_678': 1, + }, + 2: { + 'title': 'Old test deal2', + 'org_id': 1, + 'person_id': None, + 'pipeline_id': 1, + 'stage_id': 1, + 'status': 'open', + 'id': 2, + 'user_id': 1, + '345_hermes_id_678': 2, + }, + }, + 'persons': { + 1: { + 'id': 1, + 'name': 'Brian Blessed', + 'email': 'brian@tc.com', + 'org_id': 1, + '234_hermes_id_567': 1, + } + }, + 'pipelines': { + 1: { + 'id': 1, + 'name': 'Pipeline 1', + 'dft_entry_stage_id': 1, + } + }, + 'stages': { + 1: { + 'id': 1, + 'name': 'Stage 2', + } + }, + } + + admin = await Admin.create( + tc2_admin_id=30, + first_name='Brain', + last_name='Johnson', + username='brian@tc.com', + password='foo', + pd_owner_id=1, + ) + + company = await Company.create(name='Test company', pd_org_id=1, sales_person=admin) + contact = await Contact.create(first_name='Brian', last_name='Blessed', pd_person_id=1, company=company) + deal = await Deal.create( + name='Old test deal', + pd_deal_id=1, + company=company, + contact=contact, + pipeline=self.pipeline, + stage=self.stage, + admin=admin, + ) + deal2 = await Deal.create( + name='Old test deal2', + pd_deal_id=2, + company=company, + contact=contact, + pipeline=self.pipeline, + stage=self.stage, + admin=admin, + ) + + start = datetime(2023, 1, 1, tzinfo=timezone.utc) + meeting = await Meeting.create( + company=company, + contact=contact, + meeting_type=Meeting.TYPE_SALES, + start_time=start, + end_time=start + timedelta(hours=1), + admin=admin, + deal=deal2, + ) + + assert await Deal.exists() + + data = copy.deepcopy(basic_pd_deal_data()) + data[PDStatus.CURRENT].update( + **{ + '345_hermes_id_678': f'{deal.id},{deal2.id}', + 'title': 'Old test deal', + 'org_id': 1, + 'person_id': 1, + 'pipeline_id': 1, + 'stage_id': 1, + 'status': 'open', + 'user_id': 1, + } + ) + data[PDStatus.PREVIOUS] = copy.deepcopy(data[PDStatus.CURRENT]) + data[PDStatus.CURRENT].update(title='New test deal') + r = await self.client.post(self.pipedrive_callback, json=data) + assert r.status_code == 200, r.json() + deal = await Deal.get() + assert deal.name == 'New test deal' + meeting2 = await Meeting.get(id=meeting.id) + assert await meeting2.deal == deal + + @mock.patch('app.pipedrive.api.session.request') + async def test_person_merged_hermes_ids(self, mock_pd_request): + mock_pd_request.side_effect = fake_pd_request(self.pipedrive) + + self.pipedrive.db = { + 'organizations': { + 1: { + 'id': 1, + 'name': 'Test company', + 'address_country': 'GB', + 'owner_id': None, + '123_hermes_id_456': 1, + } + }, + 'deals': { + 1: { + 'title': 'Old test deal', + 'org_id': 1, + 'person_id': None, + 'pipeline_id': 1, + 'stage_id': 1, + 'status': 'open', + 'id': 1, + 'user_id': 1, + '345_hermes_id_678': 1, + }, + 2: { + 'title': 'Old test deal2', + 'org_id': 1, + 'person_id': None, + 'pipeline_id': 1, + 'stage_id': 1, + 'status': 'open', + 'id': 2, + 'user_id': 1, + '345_hermes_id_678': 2, + }, + }, + 'persons': { + 1: { + 'id': 1, + 'name': 'Brian Blessed', + 'email': 'brian@tc.com', + 'org_id': 1, + '234_hermes_id_567': 1, + }, + 2: { + 'id': 2, + 'name': 'Brian Blessed', + 'email': 'brian@tc.com', + 'org_id': 1, + '234_hermes_id_567': 2, + }, + }, + 'pipelines': { + 1: { + 'id': 1, + 'name': 'Pipeline 1', + 'dft_entry_stage_id': 1, + } + }, + 'stages': { + 1: { + 'id': 1, + 'name': 'Stage 2', + } + }, + } + + admin = await Admin.create( + tc2_admin_id=30, + first_name='Brain', + last_name='Johnson', + username='brian@tc.com', + password='foo', + pd_owner_id=1, + ) + + company = await Company.create(name='Test company', pd_org_id=1, sales_person=admin) + contact = await Contact.create(first_name='Brian', last_name='Blessed', pd_person_id=1, company=company) + contact2 = await Contact.create(first_name='Brian', last_name='Blessed', pd_person_id=2, company=company) + await Deal.create( + name='Old test deal', + pd_deal_id=1, + company=company, + contact=contact, + pipeline=self.pipeline, + stage=self.stage, + admin=admin, + ) + await Deal.create( + name='Old test deal2', + pd_deal_id=2, + company=company, + contact=contact2, + pipeline=self.pipeline, + stage=self.stage, + admin=admin, + ) + + data = copy.deepcopy(basic_pd_person_data()) + data[PDStatus.CURRENT].update( + **{ + '234_hermes_id_567': f'{contact.id},{contact2.id}', + 'name': 'Brian Blessed', + 'email': 'brian@tc.com', + 'org_id': 1, + 'owner_id': 1, + } + ) + data[PDStatus.PREVIOUS] = copy.deepcopy(data[PDStatus.CURRENT]) + + r = await self.client.post(self.pipedrive_callback, json=data) + assert r.status_code == 200, r.json() + contact = await Contact.get() + assert contact.name == 'Brian Blessed'