import urllib.parse from django.db import models from django.conf import settings from django.utils.translation import gettext_lazy as _ from pingcap_sso.validators.phone import PhoneNumberValidator class ContactUs(models.Model): AUDIT_PENDING = 0 AUDIT_DENY = 1 AUDIT_PASS = 2 AUDIT_CHOICES = ( (AUDIT_PENDING, _('pending')), (AUDIT_DENY, _('deny')), (AUDIT_PASS, _('pass')), ) user_openid = models.CharField(max_length=64, blank=True, null=True) page_url = models.URLField(blank=False, null=False) spend_time = models.FloatField(default=0) user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, blank=True, null=True) name = models.CharField(max_length=64, blank=True, null=True) company = models.CharField(max_length=64, blank=True, null=True) department = models.CharField(max_length=64, blank=True, null=True) wechat_number = models.CharField(max_length=64, blank=True, null=True) phone = models.CharField( max_length=32, null=True, blank=True, validators=(PhoneNumberValidator(),)) body = models.JSONField(default=dict) audit_status = models.SmallIntegerField(choices=AUDIT_CHOICES, default=AUDIT_PENDING) created_at = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'customer_contact_us' class ContactUsEmergency(models.Model): EMERGENCY_TYPE_ONLINE = 'online' EMERGENCY_TYPE_OFFLINE = 'offline' EMERGENCY_CHOICES = ( (EMERGENCY_TYPE_ONLINE, _('online')), (EMERGENCY_TYPE_OFFLINE, _('offline')) ) PRIORITY_P0 = 'p0' PRIORITY_P1 = 'p1' PRIORITY_P2_AND_BELOW = 'p2_and_below' PRIORITY_CHOICES = ( (PRIORITY_P0, _('P0')), (PRIORITY_P1, _('P1')), (PRIORITY_P2_AND_BELOW, _('P2 and below')) ) STATUS_PENDING = 0 STATUS_PROCESSED = 1 STATUS_CHOICES = ( (STATUS_PENDING, _('pending')), (STATUS_PROCESSED, _('processed')) ) emergency_type = models.CharField(max_length=32, choices=EMERGENCY_CHOICES) priority = models.CharField(max_length=16, choices=PRIORITY_CHOICES) tidb_version = models.CharField(max_length=32) summary = models.TextField(max_length=500) background = models.TextField(max_length=500) appearance = models.TextField(max_length=500) problem = models.TextField(max_length=500) affect = models.TextField(max_length=500) status = models.SmallIntegerField(default=STATUS_PENDING, choices=STATUS_CHOICES) updated_at = models.DateTimeField(auto_now=True) created_at = models.DateTimeField(auto_now_add=True) created_by_user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.DO_NOTHING) followed_by_user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, related_name='follwed_contacy_us_emergencies', on_delete=models.DO_NOTHING) followed_at = models.DateTimeField(blank=True, null=True) class Meta: db_table = 'pingcap_contact_us_emergencies' class ContactUsCooperation(models.Model): COOPRTATION_TYPE_TECH = 'technology' COOPRTATION_TYPE_COMMUNITY = 'community' COOPRTATION_TYPE_OTHER = 'other' COOPRTATION_CHOICES = ( (COOPRTATION_TYPE_TECH, _('technology')), (COOPRTATION_TYPE_COMMUNITY, _('community')), (COOPRTATION_TYPE_OTHER, _('other')) ) STATUS_PENDING = 0 STATUS_PROCESSED = 1 STATUS_CHOICES = ( (STATUS_PENDING, _('pending')), (STATUS_PROCESSED, _('processed')) ) cooperation_type = models.CharField(max_length=32, choices=COOPRTATION_CHOICES) detail = models.TextField(max_length=300) status = models.SmallIntegerField(default=STATUS_PENDING, choices=STATUS_CHOICES) updated_at = models.DateTimeField(auto_now=True) created_at = models.DateTimeField(auto_now_add=True) created_by_user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.DO_NOTHING) followed_by_user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, related_name='follwed_contacy_us_cooperation', on_delete=models.DO_NOTHING) followed_at = models.DateTimeField(blank=True, null=True) class Meta: db_table = 'pingcap_contact_us_cooperation' class ContactUsCommunication(models.Model): STATUS_PENDING = 0 STATUS_PROCESSED = 1 STATUS_CHOICES = ( (STATUS_PENDING, _('pending')), (STATUS_PROCESSED, _('processed')) ) tidb_node_num = models.IntegerField() tikv_node_num = models.IntegerField() tiflash_node_num = models.IntegerField() occupation_rate_of_tidb = models.DecimalField( max_digits=4, decimal_places=2) tidb_version = models.JSONField(default=list) key_scene = models.TextField(max_length=100, blank=True, null=True) current_scenarios_and_architecture = models.TextField(max_length=100) pain_points = models.TextField(max_length=100) technical_debt = models.TextField(max_length=100) expect_benefits_from_tidb = models.TextField(max_length=100) launch_or_poc_date = models.DateField(blank=True, null=True) person_resource = models.IntegerField(blank=True, null=True) tidb_usage = models.JSONField(default=list) status = models.SmallIntegerField(default=STATUS_PENDING, choices=STATUS_CHOICES) updated_at = models.DateTimeField(auto_now=True) created_at = models.DateTimeField(auto_now_add=True) created_by_user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.DO_NOTHING) followed_by_user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, related_name='follwed_contacy_us_communication', on_delete=models.DO_NOTHING) followed_at = models.DateTimeField(blank=True, null=True) class Meta: db_table = 'pingcap_contact_us_communication' class OfficialContactUs(models.Model): user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.DO_NOTHING ) name = models.CharField(max_length=32) phone = models.CharField(max_length=16) company = models.CharField(max_length=128) job_title_code = models.CharField(max_length=64, blank=True, null=True) job_title_text = models.CharField(max_length=64, blank=True, null=True) consult_category_code = models.CharField(max_length=64, blank=True, null=True) consult_category_text = models.CharField(max_length=64, blank=True, null=True) consult_detail = models.TextField(blank=True, null=True) utm_source = models.CharField(max_length=64, blank=True, null=True) utm_medium = models.CharField(max_length=64, blank=True, null=True) utm_campaign = models.CharField(max_length=64, blank=True, null=True) utm_term = models.CharField(max_length=64, blank=True, null=True) person_source = models.CharField(max_length=100, blank=True, null=True) person_source_details = models.CharField(max_length=100, blank=True, null=True) referer = models.TextField( default='', blank=True, null=True, help_text='留资来源 URL') referer2 = models.TextField( default='', blank=True, null=True, help_text='留资前一页面 URL') current_page = models.TextField( default='', blank=True, null=True, help_text='留资当前页面 URL') created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True) class Meta: db_table = 'pingcap_official_contact_us' @classmethod def get_person_source_detail(cls, utm_source, utm_medium, referer): # https://pingcap.feishu.cn/docx/QfsGdjo4YoQFXdxLZQPcGXlpn3b if utm_source and utm_medium: return cls.get_person_source_detail_by_utm(utm_source, utm_medium) else: return cls.get_person_source_detail_by_referer(referer) @classmethod def get_person_source_detail_by_utm(cls, utm_source, utm_medium): return cls.UTM_PERSON_SOURCE_MAP.get((utm_source, utm_medium), ('Other', 'Other')) @classmethod def get_person_source_detail_by_referer(cls, referer): domain_name = urllib.parse.urlparse(referer).netloc if not domain_name: return ('Direct Traffic', 'Direct') for k, person_detail in cls.REFERER_KEYWORD_PERSON_SOURCE_MAP.items(): if k in domain_name: return person_detail return ('Website Referral', 'Referral Traffic') UTM_PERSON_SOURCE_MAP = { ('wechat', 'social'): ('Organic Social', 'Wechat'), ('scrm', 'social'): ('Organic Social', 'SCRM'), ('facebook', 'social'): ('Organic Social', 'Facebook'), ('linkedin', 'social'): ('Organic Social', 'LinkedIn'), ('youtube', 'social'): ('Organic Social', 'Youtube'), ('hackernews', 'social'): ('Organic Social', 'Hacker News'), ('twitter', 'social'): ('Organic Social', 'Twitter'), ('others', 'social'): ('Organic Social', 'Others'), ('baidu', 'cpc'): ('Paid Advertising', 'Baidu'), ('hackernews', 'cpc'): ('Paid Advertising', 'Hacker News'), ('stackoverflow', 'cpc'): ('Paid Advertising', 'Stackoverflow'), ('dbengines', 'cpc'): ('Paid Advertising', 'DBengines'), ('google_display', 'cpc'): ('Paid Advertising', 'Google - Display'), ('google_search', 'cpc'): ('Paid Advertising', 'Google - Search'), ('google_performancemax', 'cpc'): ('Paid Advertising', 'Google - Performance Max'), ('google_youtube', 'cpc'): ('Paid Advertising', 'Google - Youtube'), ('youtube', 'social_paid'): ('Paid Advertising', 'Youtube - Display'), ('linkedin_display', 'social_paid'): ('Paid Advertising', 'Linkedin - Display'), ('linkedin_inmail', 'social_paid'): ('Paid Advertising', 'Linkedin - InMail'), ('itmedia_banner', 'media_paid'): ('Paid Advertising', 'Media - Banner Ads'), ('qiita_email', 'media_paid'): ('Paid Advertising', 'Media - Email Ads'), ('content_syndication', 'third_party'): ('Paid Advertising', 'Content Syndication'), ('sales_bdm', 'sales'): ('Outbound', 'Sales Sourced'), ('sales_sdr', 'sales'): ('Outbound', 'SDR Sourced'), ('website-zh', 'referral'): ('Website Referral', 'Website-ZH'), ('asktug', 'referral'): ('Website Referral', 'AskTUG'), ('ossinsight', 'referral'): ('Website Referral', 'OSS Insight'), ('tidb-community', 'referral'): ('Website Referral', 'TiDB Community'), ('docs', 'referral'): ('Website Referral', 'Docs'), ('event_site', 'event'): ('Website Referral', 'Event Site'), ('email', 'email_blast'): ('Email', 'Email Send'), ('email', 'email_nurture'): ('Email', 'Email Nurture'), ('email', 'email_newsletter'): ('Email', 'Email Newsletter'), ('press_release', 'news_wire'): ('Press Release', 'Press Release'), ('event', 'referral'): ('Physical Event', 'Owned Event') } REFERER_KEYWORD_PERSON_SOURCE_MAP = { 'googleads': ('Paid Advertising', 'Google Search'), 'youtube': ('Organic Social', 'Youtube'), 'twitter': ('Organic Social', 'Twitter'), 'linkedin': ('Organic Social', 'LinkedIn'), 'facebook': ('Organic Social', 'Fackbook'), 'baidu': ('Organic Search', 'Baidu'), 'google': ('Organic Search', 'Google'), 'bing': ('Organic Search', 'Bing'), 'pingcap': ('Direct Traffic', 'Direct') } class CommunityContactUs(models.Model): user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.DO_NOTHING ) name = models.CharField(max_length=32) phone = models.CharField(max_length=16) company = models.CharField(max_length=128) consult_detail = models.TextField(blank=True, null=True) user_agent = models.CharField(max_length=255, blank=True, null=True) ip = models.CharField(max_length=255, blank=True, null=True) created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True) class Meta: db_table = 'pingcap_community_contact_us'