import logging import requests from datetime import datetime from django.conf import settings from django.core.files.storage import default_storage from django.core.cache import cache from django.utils import timezone from pingcap_sso.models import PartnerCompatibilityCertification, User logger = logging.getLogger(__name__) CORP_ID = 'FSCID_3B3845A12FFFA4B6EEB56B17FD9D3A8B' FXIAOKE_CRM_ACCESS_TOKEN_CACHE_KEY = 'fxiaoke_crm_access_token' def get_fxiaoke_crm_access_token(): access_token = cache.get(FXIAOKE_CRM_ACCESS_TOKEN_CACHE_KEY) if access_token: return access_token resp = requests.post( 'https://open.fxiaoke.com/cgi/corpAccessToken/get/V2', json=settings.CRM_FENXIANGXIAOKE, timeout=3 ).json() if not resp['errorCode'] == 0: logger.error('CRM GET Access Token Failed: {}'.format(resp)) access_token = resp['corpAccessToken'] expires_in = resp['expiresIn'] - 10 cache.set(FXIAOKE_CRM_ACCESS_TOKEN_CACHE_KEY, access_token, timeout=expires_in) return access_token def sync_leads_to_fxiaoke_crm( crm_leads_object, # 黄漫绅 open_user_id='FSUID_EE7A00DA91B32217C313554BCDD45793', access_token=None ): # Disable sync when develop or test if settings.STAGING or settings.DEBUG: return False, None access_token = access_token or get_fxiaoke_crm_access_token() try: resp = requests.post( 'https://open.fxiaoke.com/cgi/crm/v2/data/create', json={ 'corpAccessToken': access_token, 'corpId': CORP_ID, 'currentOpenUserId': open_user_id, 'data': { 'object_data': crm_leads_object } }, timeout=3 ).json() except Exception as e: logger.error('CRM Create Leads Failed: {}, detail: {}'.format(e, crm_leads_object)) return False, None if resp['errorCode'] == 0: logger.info('CRM Create Leads Success: {}'.format(resp)) return True, resp else: logger.error('CRM Create Leads Failed: {}, detail: {}'.format(resp, crm_leads_object)) return False, resp def sync_custom_object_to_fxiaoke_crm( crm_custom_object, # 王静 open_user_id='FSUID_8D4890ED424F97459A11A7B4DCA523F0', access_token=None ): # Disable sync when develop or test if settings.STAGING or settings.DEBUG: return False, None access_token = access_token or get_fxiaoke_crm_access_token() try: resp = requests.post( 'https://open.fxiaoke.com/cgi/crm/custom/v2/data/create', json={ 'corpAccessToken': access_token, 'corpId': CORP_ID, 'currentOpenUserId': open_user_id, 'data': { 'object_data': crm_custom_object } }, timeout=3 ).json() except Exception as e: logger.error('CRM Create Custom Object Failed: {}, detail: {}'.format(e, crm_custom_object)) return False, None if resp['errorCode'] == 0: logger.info('CRM Create Custom Object Success: {}'.format(resp)) return True, resp else: logger.error('CRM Create Custom Object Failed: {}, detail: {}'.format(resp, crm_custom_object)) return False, resp def upload_file_to_fxiaoke_crm(upload_obj, access_token=None): # Disable sync when develop or test if settings.STAGING or settings.DEBUG: return False, None access_token = access_token or get_fxiaoke_crm_access_token() payload = { 'corpAccessToken': access_token, 'corpId': CORP_ID, 'type': 'document', } files = { 'media': ( upload_obj.original_filename, default_storage.open(upload_obj.path) ) } resp = requests.post( 'http://open.fxiaoke.com/media/upload', data=payload, files=files, timeout=5 ).json() if resp['errorCode'] == 0: logger.info('CRM Upload File Success: {}'.format(resp)) return True, resp['mediaId'] else: logger.error('CRM Upload File Failed: {}'.format(resp)) return False, None def _crm_timestamp_to_datetime(timestamp: int) -> datetime: if not timestamp: return None return datetime.fromtimestamp(timestamp / 1000) def sync_approved_partner_compatibility_certification_from_fxiaoke_crm(): access_token = get_fxiaoke_crm_access_token() limit = 100 offset = 0 total_num = 100 # give a default value that greater than limit, then the first request will get the total number while offset < total_num: resp = requests.post( 'https://open.fxiaoke.com/cgi/crm/custom/v2/data/query', json={ 'corpAccessToken': access_token, 'corpId': CORP_ID, 'currentOpenUserId': 'FSUID_8D4890ED424F97459A11A7B4DCA523F0', 'data': { 'dataObjectApiName': 'object_WP33j__c', 'find_explicit_total_num': True, 'search_query_info': { 'limit': limit, 'offset': offset, 'filters': [ { 'field_name': 'field_3siLt__c', 'field_values': [timezone.now().timestamp() * 1000], 'operator': 'GTE' } ] } } } ).json() if resp['errorCode'] != 0: raise Exception(f'CRM Query Partner Compatibility Certification Failed: {resp}') total_num = resp['data']['total'] offset += limit for item in resp['data']['dataList']: crm_object_id = item['_id'] try: obj = PartnerCompatibilityCertification.objects.get(crm_object_id=crm_object_id) except PartnerCompatibilityCertification.DoesNotExist: obj = PartnerCompatibilityCertification.objects.create( crm_object_id=crm_object_id, company=item['field_q61zh__c'], company_area_text=item.get('field_25Jx7__c__r', ''), contact_name=item.get('field_oS1y0__c', ''), contact_phone=item.get('field_DMbhr__c', ''), contact_email=item.get('field_C31Wx__c', ''), contact_job_title_text=item.get('field_BBBbR__c', ''), shipping_address='-', cert_owner_name='-', cert_owner_job_title='-', product_name=item.get('field_m189y__c', ''), product_description=item.get('field_93yLR__c', '')[:200], product_industry_text=item.get('field_lh83t__c__r', ''), purpose_of_certification='-', compatible_database_version_text=item.get('field_0e6BW__c__r', ''), compatible_database_version_code=item.get('field_0e6BW__c', ''), solution_type_code=item.get('field_cP4Sc__c', ''), solution_type_text=item.get('field_cP4Sc__c__r', ''), infra_category_code=item.get('field_9LTuk__c', ''), infra_category_text=item.get('field_9LTuk__c__r', ''), user=User.objects.filter(is_superuser=True).first(), status=PartnerCompatibilityCertification.STATUS_APPROVED, sync_status=PartnerCompatibilityCertification.SYNC_STATUS_SUCCESS, sync_at=timezone.now(), response_body=item, sync_from_crm=True, ) obj.status = PartnerCompatibilityCertification.STATUS_APPROVED obj.sync_status = PartnerCompatibilityCertification.SYNC_STATUS_SUCCESS obj.sync_at = timezone.now() obj.response_body = item obj.cert_number = item['name'] obj.cert_valid_from = _crm_timestamp_to_datetime(item['field_s2oU4__c']) obj.cert_valid_to = _crm_timestamp_to_datetime(item['field_3siLt__c']) obj.save() def sync_review_status_from_fxiaoke_crm(): access_token = get_fxiaoke_crm_access_token() for obj in PartnerCompatibilityCertification.objects.filter( status=PartnerCompatibilityCertification.STATUS_PENDING, crm_object_id__isnull=False, sync_from_crm=False, ): try: resp = requests.post( 'https://open.fxiaoke.com/cgi/crm/custom/v2/data/get', json={ 'corpAccessToken': access_token, 'corpId': 'FSCID_3B3845A12FFFA4B6EEB56B17FD9D3A8B', 'currentOpenUserId': 'FSUID_8D4890ED424F97459A11A7B4DCA523F0', 'data': { 'dataObjectApiName': 'object_WP33j__c', 'objectDataId': obj.crm_object_id } }, timeout=5, ).json() except Exception as e: logger.error('CRM get partner compatibility certification failed: {}, crm object id: {}'.format(e, obj.crm_object_id)) continue crm_data = resp['data'] if crm_data.get('field_s2oU4__c') and crm_data.get('field_3siLt__c'): obj.cert_valid_from = _crm_timestamp_to_datetime(crm_data['field_s2oU4__c']) obj.cert_valid_to = _crm_timestamp_to_datetime(crm_data['field_3siLt__c']) obj.cert_number = crm_data['name'] obj.status = PartnerCompatibilityCertification.STATUS_APPROVED obj.save(update_fields=['status', 'cert_valid_from', 'cert_valid_to', 'cert_number']) continue resp = requests.post( 'https://open.fxiaoke.com/cgi/crm/object/approvalInstances/query', json={ 'corpAccessToken': access_token, 'corpId': 'FSCID_3B3845A12FFFA4B6EEB56B17FD9D3A8B', 'currentOpenUserId': 'FSUID_8D4890ED424F97459A11A7B4DCA523F0', 'dataId': obj.crm_object_id }, timeout=5, ).json() if resp['errorCode'] != 0: logger.error('CRM query approval instance failed: {}, crm object id: {}'.format(resp, obj.crm_object_id)) continue approval_instance = resp['instances'][0] if approval_instance.get('state') == 'pass': logger.error('CRM approval instance was passed, but cert does not have valid from and to, object id: {}'.format(obj.crm_object_id)) continue elif approval_instance.get('state') == 'reject': approval_instance_id = approval_instance['instanceId'] try: resp = requests.post( 'https://open.fxiaoke.com/cgi/crm/approvalInstance/get', json={ 'corpAccessToken': access_token, 'corpId': 'FSCID_3B3845A12FFFA4B6EEB56B17FD9D3A8B', 'currentOpenUserId': 'FSUID_8D4890ED424F97459A11A7B4DCA523F0', 'instanceId': approval_instance_id }, timeout=5, ).json() except Exception as e: logger.error('CRM query approval instance failed: {}, crm object id: {}'.format(e, obj.crm_object_id)) continue if resp['errorCode'] != 0: logger.error('CRM query approval instance failed: {}, crm object id: {}'.format(resp, obj.crm_object_id)) continue approval_tasks = resp['instanceDetail']['tasks'] for task in approval_tasks: if task['state'] == 'reject': obj.staff_comment = task['opinions'][0]['opinion'] obj.status = PartnerCompatibilityCertification.STATUS_REJECTED obj.save(update_fields=['status', 'staff_comment'])