class Lead(BaseModel): user = models.ForeignKey('users.user', on_delete=models.CASCADE) contact = models.ForeignKey( 'crm.Contact', null=True, blank=True, on_delete=models.CASCADE) campaign = models.ForeignKey( 'users.Campaign', null=True, blank=True, on_delete=models.CASCADE) pincode = models.CharField(max_length=6, null=True) bookmark = models.BooleanField(default=False) is_client = models.BooleanField(default=False) ignore = models.BooleanField(default=False) class Meta: ordering = ('-bookmark',) def create_opportunity(self, validated_data): instance = Opportunity.objects.create( lead_id=self.id, category_id=validated_data['category_id']) instance.update_category_opportunity(validated_data) return instance def get_quotes(self): from sales.models import Quote return Quote.objects.filter( opportunity__lead_id=self.id, ignore=False).exclude(status='rejected') def __str__(self): return "%s - Contact: %s" % ( self.user.get_full_name(), self.contact.first_name if self.contact else 'Pending')
class Note(BaseModel): lead = models.ForeignKey('crm.Lead', on_delete=models.PROTECT) title = models.CharField(max_length=128) text = models.TextField() read = models.BooleanField(default=False) ignore = models.BooleanField(default=False) def __str__(self): return self.title
class ProductVariant(BaseModel): company_category = models.ForeignKey('product.CompanyCategory', null=True, blank=True, on_delete=models.CASCADE) parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE) name = models.CharField(max_length=256, default="", verbose_name="Product Name") parent_product = models.CharField(max_length=128, null=True, blank=True, default='GoPlannr') feature_variant = models.CharField(max_length=256, default='base') short_description = models.CharField(max_length=128, null=True, blank=True) long_description = models.TextField(null=True, blank=True) online_process = models.BooleanField(default=False) is_active = models.BooleanField(default=True) chronic = models.BooleanField(default=True) def get_product_details(self): return { 'name': self.product_short_name, 'company': self.company_category.company.name, 'logo': self.logo, 'variant_name': self.product_short_name } @cached_property def logo(self): from goplannr.settings import DEBUG return (Constants.DEBUG_HOST if DEBUG else '') + self.company_category.company.logo.url @cached_property def product_short_name(self): return self.name def get_basic_details(self): return dict(toll_free_number=', '.join( self.company_category.company.toll_free_number), brochure=self.get_help_file('sales_brochure'), claim_form=self.get_help_file('claim_form')) def get_help_file(self, file_type): from content.models import HelpFile helpfile = HelpFile.objects.filter(product_variant_id=self.id, file_type=file_type).first() return helpfile.file.url if helpfile else '-' def __str__(self): return self.product_short_name
class IPAddress(BaseModel): account = models.ForeignKey( 'users.Account', on_delete=models.PROTECT, null=True, blank=True) ip_address = models.CharField(max_length=16) company_name = models.CharField(max_length=128) authentication_required = models.BooleanField(default=True) blocked = models.BooleanField(default=False) @classmethod def _get_whitelisted_networks(cls): return cls.objects.filter( blocked=False).values_list('ip_address', flat=True)
class Member(BaseModel): application = models.ForeignKey('sales.Application', on_delete=models.CASCADE) relation = models.CharField(max_length=128, choices=get_choices( Constants.RELATION_CHOICES), db_index=True) first_name = models.CharField(max_length=128, blank=True) last_name = models.CharField(max_length=128, blank=True) dob = models.DateField(null=True) gender = models.CharField(choices=get_choices(Constants.GENDER), max_length=16, null=True) occupation = models.CharField(choices=get_choices( Constants.OCCUPATION_CHOICES), max_length=32, null=True, blank=True) height = models.FloatField(default=0.0) weight = models.FloatField(default=0.0) ignore = models.BooleanField(default=None, db_index=True, null=True) def save(self, *ar, **kw): try: self.__class__.objects.get(pk=self.id) except self.__class__.DoesNotExist: if self.relation not in [ 'son', 'daughter' ] and self.__class__.objects.filter( relation=self.relation, application_id=self.application_id).exists(): raise IntegrityError('%s relation already exists.' % self.relation) super(Member, self).save(*ar, **kw) def update_fields(self, **kw): for field in kw.keys(): setattr(self, field, kw[field]) self.save() def get_full_name(self): name = '%s %s' % (self.first_name, self.last_name) return name.strip() @property def age(self): if self.dob: return int((now().today().date() - self.dob).days / 365.2425) @property def height_foot(self): return int(self.height / 30.48) @property def height_inches(self): return round((self.height - self.height_foot * 30.48) / 2.54, 2) def __str__(self): return '%s | %s' % (self.relation.title(), self.application.__str__())
class BankAccount(BaseModel): user = models.ForeignKey('users.User', on_delete=models.CASCADE) branch = models.OneToOneField( 'content.BankBranch', on_delete=models.CASCADE) account_no = models.CharField(max_length=32) default = models.BooleanField(default=False) is_active = models.BooleanField(default=True) def save(self, *args, **kwargs): try: if self.default and BankAccount.objects.filter( default=True).exists(): self.default = False except self.__class__.DoesNotExist: self.__class__.objects.all().update(default=False) self.default = True super(BankAccount, self).save(*args, **kwargs)
class HealthPremium(BaseModel): product_variant = models.ForeignKey('product.ProductVariant', null=True, blank=True, on_delete=models.CASCADE) deductible = models.ForeignKey('product.DeductibleMaster', null=True, blank=True, on_delete=models.CASCADE) sum_insured = models.IntegerField(default=0.0) suminsured_range = IntegerRangeField(db_index=True) age_range = IntegerRangeField(db_index=True) adults = models.IntegerField(null=True, blank=True, db_index=True) childrens = models.IntegerField(null=True, blank=True, db_index=True) citytier = models.CharField(max_length=256, null=True, blank=True) base_premium = models.FloatField(default=Constants.DEFAULT_BASE_PREMIUM) gst = models.FloatField(default=Constants.DEFAULT_GST) commission = models.FloatField(default=0.0) premium = GenericRelation('sales.quote', related_query_name='healthinsurance', object_id_field='premium_id') online_process = models.BooleanField(default=True) is_active = models.BooleanField(default=True) ignore = models.BooleanField(default=False) def get_details(self): return dict(sum_insured=self.sum_insured, amount=self.amount, commision=self.commission_amount) @cached_property def commission_amount(self): company = self.product_variant.company_category.company category = self.product_variant.company_category.category return self.amount * (self.commission + company.commission + category.commission) @cached_property def amount(self): return round((self.gst * self.base_premium) + self.base_premium, 2) def __str__(self): return '%s | %s | %s' % (self.sum_insured, self.product_variant.name, self.age_range)
class CompanyCategory(BaseModel): category = models.ForeignKey('product.Category', on_delete=models.CASCADE) company = models.ForeignKey('product.Company', on_delete=models.CASCADE) claim_settlement = models.CharField(max_length=128, null=True, blank=True) offer_flag = models.BooleanField(default=False) class Meta: unique_together = ('category', 'company') def __str__(self): return '%s - %s' % (self.company.short_name, self.category.name)
class Category(BaseModel): name = models.CharField(max_length=128, db_index=True) description = models.TextField(null=True, blank=True) logo = models.ImageField(upload_to=Constants.CATEGORY_UPLOAD_PATH, default=Constants.DEFAULT_LOGO) hexa_code = models.CharField(max_length=8, default=Constants.DEFAULT_HEXA_CODE) is_active = models.BooleanField(default=False) commission = models.FloatField(default=Constants.DEFAULT_COMMISSION) def __str__(self): return self.name
class Answer(BaseModel): question = models.ForeignKey('questionnaire.Question', on_delete=models.CASCADE) answer = models.CharField(max_length=128) order = models.IntegerField(default=0) ignore = models.BooleanField(default=False) score = models.IntegerField(default=0) class Meta: ordering = ('order', ) def __str__(self): return self.answer
class Question(BaseModel): category = models.ForeignKey('product.Category', on_delete=models.CASCADE) title = models.CharField(max_length=32) question_type = models.CharField(max_length=10, choices=get_choices( constants.QUESTION_COICES), default="single") question = models.TextField() order = models.IntegerField(default=0) ignore = models.BooleanField(default=False) class Meta: ordering = ('order', ) def __str__(self): return self.title
class KYCDocument(BaseModel): account = models.ForeignKey('users.Account', on_delete=models.CASCADE) document_type = models.CharField( choices=get_choices(Constants.KYC_DOC_TYPES), max_length=16) document_number = models.CharField(max_length=64, null=True, blank=True) file = models.FileField(upload_to=get_kyc_upload_path) ignore = models.BooleanField(default=False) def save(self, *args, **kwargs): previous = self.__class__.objects.filter( document_type=self.document_type, account_id=self.id) if previous.exists(): previous.update(ignore=True) super(self.__class__, self).save(*args, **kwargs) def __str__(self): return self.document_type
class ProposerDocument(BaseModel): contact = models.ForeignKey('crm.Contact', on_delete=models.CASCADE) document_number = models.CharField(max_length=64, null=True, blank=True) document_type = models.CharField(choices=get_choices( Constants.KYC_DOC_TYPES), max_length=16) file = models.FileField(upload_to=get_proposer_upload_path, null=True, blank=True) ignore = models.BooleanField(default=False) def save(self, *args, **kwargs): previous = self.__class__.objects.filter( document_type=self.document_type, contact_id=self.contact_id) if previous.exists(): previous.update(ignore=True) super(self.__class__, self).save(*args, **kwargs)
class Nominee(BaseModel): application = models.ForeignKey('sales.Application', on_delete=models.CASCADE) relation = models.CharField(max_length=128, choices=get_choices( Constants.RELATION_CHOICES), db_index=True) first_name = models.CharField(max_length=128) last_name = models.CharField(max_length=128) phone_no = models.CharField(max_length=10) ignore = models.BooleanField(default=False) def save(self, *ar, **kw): if not self.__class__.objects.filter(pk=self.id): existing_nominee = self.__class__.objects.filter( application_id=self.application.id) if existing_nominee.exists(): existing_nominee.update(ignore=True) super(Nominee, self).save(*ar, **kw) def get_full_name(self): name = '%s %s' % (self.first_name, self.last_name) return name.strip()
class Company(BaseModel): name = models.CharField(max_length=128, db_index=True, verbose_name="Company Name") short_name = models.CharField(max_length=128) categories = models.ManyToManyField('product.Category') logo = models.ImageField(upload_to=Constants.COMPANY_UPLOAD_PATH, default=Constants.DEFAULT_LOGO) hexa_code = models.CharField(max_length=8, default=Constants.DEFAULT_HEXA_CODE) website = models.URLField(null=True, blank=True) spoc = models.TextField(null=True, blank=True) toll_free_number = ArrayField(models.CharField(max_length=32), default=list, blank=True, null=True) long_description = models.TextField(null=True, blank=True) small_description = models.TextField(null=True, blank=True) commission = models.FloatField(default=0.0) is_active = models.BooleanField(default=False) def __str__(self): return self.name
class HealthInsurance(Insurance): gastrointestinal_disease = JSONField( default=list, help_text=Constants.GASTROINTESTINAL_DISEASE) neuronal_diseases = JSONField(default=list, help_text=Constants.NEURONAL_DISEASES) oncology_disease = JSONField(default=list, help_text=Constants.ONCOLOGY_DISEASE) respiratory_diseases = JSONField(default=list, help_text=Constants.RESPIRATORY_DISEASES) cardiovascular_disease = JSONField( default=list, help_text=Constants.CARDIOVASCULAR_DISEASE) ent_diseases = JSONField(default=list, help_text=Constants.ENT_DISEASE) blood_diseases = JSONField(default=list, help_text=Constants.BLOOD_DISODER) alcohol_consumption = models.IntegerField( default=0.0, help_text=Constants.ALCOHOL_CONSUMPTION, null=True, blank=True) tobacco_consumption = models.IntegerField( default=0.0, help_text=Constants.TABBACO_CONSUMPTION, null=True, blank=True) cigarette_consumption = models.IntegerField( default=0.0, help_text=Constants.CIGARETTE_CONSUMPTION, null=True, blank=True) previous_claim = models.BooleanField(default=False, help_text=Constants.PREVIOUS_CLAIM, null=True, blank=True) proposal_terms = models.BooleanField(default=False, help_text=Constants.PROPOSAL_TERMS, null=True, blank=True) def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) def update_default_fields(self, kw): for field in Constants.HEALTHINSURANCE_FIELDS: setattr(self, field, kw) self.save() def switch_premium(self, adults, childrens): opportunity = self.application.quote.opportunity data = dict( effective_age=(now().year - self.application.active_members.aggregate( s=models.Min('dob'))['s'].year), adults=adults, product_variant_id=self.application.quote.premium. product_variant_id, # noqa childrens=childrens) for member in Constants.RELATION_CHOICES: members = self.application.active_members.filter(relation=member) if members.exists() and member not in ['son', 'daughter']: data['%s_age' % (member)] = members.get().age data[ 'customer_segment_id'] = opportunity.category_opportunity.get_customer_segment( **data).id # noqa opportunity.refresh_quote_data(**data) quote = opportunity.get_quotes().first() if not quote: raise RecommendationException('No quote found for this creteria') previous_quote = self.application.quote if quote.id != previous_quote.id: previous_quote.status = 'rejected' previous_quote.save() quote.status = 'accepted' quote.save() self.application.quote_id = quote.id self.application.premium = quote.premium.amount self.application.suminsured = quote.premium.sum_insured self.application.save() def get_summary(self): response = dict() for field in self._meta.fields: if field.name in Constants.INSURANCE_EXCLUDE_FIELDS: continue field_value = getattr(self, field.name) if isinstance(field_value, list): values = list() for row in field_value: if row['value']: values.append( Member.objects.get(id=row['id']).relation) field_value = None if values: field_value = ", ".join(values) if not field_value: continue response[field.name] = field_value return response def get_insurance_fields(self): field_data = list() from sales.serializers import (MemberSerializer, GetInsuranceFieldsSerializer) members = self.application.active_members or Member.objects.filter( application_id=self.application_id) for field in self._meta.fields: if field.name in Constants.INSURANCE_EXCLUDE_FIELDS: continue if field.__class__.__name__ not in [ 'BooleanField', 'IntegerField' ]: members_data = list() for member in getattr(self, field.name): row = MemberSerializer(members.get(id=member['id'])).data row['value'] = member['value'] members_data.append(row) if field.__class__.__name__ == 'BooleanField': data = dict(text=field.help_text, field_name=field.name, field_requirements=[{ 'relation': 'None', 'value': getattr(self, field.name) }]) elif field.__class__.__name__ == 'IntegerField': data = dict(text=field.help_text, field_name=field.name, field_requirements=[{ 'relation': 'None', 'consumption': getattr(self, field.name) }]) else: data = dict(text=field.help_text, field_name=field.name, field_requirements=members_data) serializer = GetInsuranceFieldsSerializer(data=data) serializer.is_valid(raise_exception=True) field_data.append(serializer.data) return field_data
class Bank(models.Model): name = models.CharField(max_length=256, db_index=True) is_active = models.BooleanField(default=False) def __str__(self): return self.name
class Quote(BaseModel): opportunity = models.ForeignKey('crm.Opportunity', on_delete=models.CASCADE, null=True, blank=True) status = models.CharField(max_length=16, choices=Constants.STATUS_CHOICES, default='pending') limit = models.Q(app_label='product', model='healthpremium') content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, limit_choices_to=limit) premium_id = models.PositiveIntegerField() premium = GenericForeignKey('content_type', 'premium_id') recommendation_score = models.FloatField(default=0.0) ignore = models.BooleanField(default=False) def save(self, *args, **kwargs): self.__class__.objects.filter( opportunity_id=self.opportunity_id, premium_id=self.premium_id, ignore=False).exclude(status='accepted').update(ignore=True) super(Quote, self).save(*args, **kwargs) def __str__(self): return '%s - %s' % (self.premium.amount, self.premium.product_variant. company_category.company.name) class Meta: ordering = [ '-recommendation_score', ] def get_feature_details(self): variant = self.premium.product_variant features = variant.feature_set.all() if variant.parent: features = features | variant.parent.feature_set.exclude( feature_master__name__in=features.values_list( 'feature_master__name', flat=True)) return features.order_by('feature_master__order').values( 'feature_master__name', 'short_description', 'feature_master__long_description') def get_faq(self): company_category = self.premium.product_variant.company_category return [ dict(question='Claim settlement ratio', answer=company_category.claim_settlement), dict(question='Company details', answer='Name: %s\nWebsite: %s' % (company_category.company.name, company_category.company.website or '-')) ] @cached_property def health_checkup(self): return 1500 * self.opportunity.category_opportunity.adults @cached_property def wellness_reward(self): return round(self.opportunity.category_opportunity.wellness_reward * self.premium.amount, 2) # noqa @cached_property def tax_saving(self): return round(self.opportunity.category_opportunity.tax_saving * self.premium.amount, 2) # noqa @cached_property def effective_premium(self): return round(self.premium.amount - (self.health_checkup + self.wellness_reward + self.tax_saving))
class NewsletterSubscriber(BaseModel): email = models.EmailField() unsubscribe = models.BooleanField(default=False)
class Application(BaseModel): app_client = models.ForeignKey('crm.Lead', on_delete=models.PROTECT, null=True, blank=True) reference_no = models.CharField(max_length=10, unique=True, db_index=True) premium = models.FloatField(default=0.0) suminsured = models.FloatField(default=0.0) proposer = models.ForeignKey('crm.Contact', null=True, on_delete=models.PROTECT) application_type = models.CharField(max_length=32, choices=get_choices( Constants.APPLICATION_TYPES)) quote = models.OneToOneField('sales.Quote', on_delete=models.CASCADE) status = models.CharField(max_length=32, choices=Constants.APPLICATION_STATUS, default='fresh') stage = models.CharField(max_length=32, default='proposer_details', choices=get_choices(Constants.APPLICATION_STAGES)) previous_policy = models.BooleanField(default=False) name_of_insurer = models.CharField(blank=True, max_length=128) proposer_verified = models.BooleanField(default=False) payment_failed = models.BooleanField(null=True, blank=True) payment_mode = models.CharField(max_length=64, default='offline') aggregator_error = models.CharField(max_length=256, null=True, blank=True) terms_and_conditions = models.BooleanField(null=True) def save(self, *args, **kwargs): try: current = self.__class__.objects.get(pk=self.id) if self.status != current.status: self.handle_status_change(current) if (current.payment_failed != self.payment_failed and self.payment_failed) or self.status == 'completed': # noqa self.send_slack_notification() if self.status == 'payment_due' and self.aggregator_error != current.aggregator_error: self.send_slack_notification() except self.__class__.DoesNotExist: self.generate_reference_no() self.application_type = self.company_category.category.name.lower( ).replace(' ', '') super(Application, self).save(*args, **kwargs) def handle_status_change(self, current): if self.status == 'submitted' and self.stage == 'completed': self.create_client() self.create_policy() self.create_commission(current) if current.status == 'fresh' and self.status == 'submitted': self.send_slack_notification() def send_slack_notification(self): event = None if self.quote.opportunity.lead.user.user_type == 'subscriber': event = 'Application created and payment process done' elif self.payment_mode == 'offline': event = 'Application created and payment process done' elif self.payment_failed: event = Constants.PAYMENT_ERROR elif self.aggregator_error: event = Constants.BROKER_ERROR else: event = Constants.PAYMENT_SUCCESS if event: self.send_slack_request(event) def aggregator_operation(self): premium = self.quote.premium if not premium.product_variant.online_process or not premium.online_process: # noqa return False self.status = 'payment_due' from aggregator.wallnut.models import Application as Aggregator if not hasattr(self, 'application'): Aggregator.objects.create(reference_app_id=self.id, insurance_type=self.application_type) self.payment_mode = 'Aggregated payment mode' self.save() return self.payment_mode != 'offline' def update_fields(self, **kw): updated = False for field in kw.keys(): setattr(self, field, kw[field]) if not updated: updated = True if updated: self.save() def generate_reference_no(self): self.reference_no = genrate_random_string(10) if self.__class__.objects.filter( reference_no=self.reference_no).exists(): while self.__class__.objects.filter( reference_no=self.reference_no).exists(): self.reference_no = genrate_random_string(10) def add_default_members(self): category_opportunity = self.quote.opportunity.category_opportunity today = now() members = list() def get_member_instance(gender, relation, dob=None): instance = Member(application_id=self.id, dob=dob, relation=relation, gender=gender) if relation == 'self': responses = Response.objects.filter( question__category_id=self.company_category.category.id, opportunity_id=category_opportunity.opportunity_id) occupation_res = responses.filter(question__title='Occupation') if occupation_res.exists(): instance.occupation = responses.latest( 'created').answer.answer.replace(' ', '_').lower() # noqa return instance for member, age in category_opportunity.family.items(): member = member.split('_')[0] gender = category_opportunity.gender if member == 'self' else 'male' # noqa if member == 'spouse': gender = 'male' if category_opportunity.gender == 'female' else 'female' # noqa elif member == 'mother': gender = 'female' elif member in ['son', 'daughter']: while age > 0: members.append( get_member_instance( ('male' if member == 'son' else 'female'), member)) age -= 1 continue instance = get_member_instance( gender, member, '%s-%s-%s' % (today.year - int(age), today.month, today.day)) members.append(instance) Member.objects.bulk_create(members) def verify_proposer(self, otp): from django.core.cache import cache response = otp == cache.get('APP-%s:' % self.reference_no) cache.delete('APP-%s:' % self.reference_no) return response def send_propser_otp(self): from users.models import Account Account.send_otp('APP-%s:' % self.reference_no, self.proposer.phone_no) def create_policy(self): return Policy.objects.get_or_create(application_id=self.id) def invalidate_cache(self): from django.core.cache import cache cache.delete('USER_CART:%s' % self.quote.opportunity.lead.user_id) cache.delete('USER_CONTACTS:%s' % self.quote.opportunity.lead.user_id) cache.delete('USER_EARNINGS:%s' % self.quote.opportunity.lead.user_id) def create_client(self, save=False): lead = self.quote.opportunity.lead if not lead.is_client: lead.is_client = True lead.save() self.app_client_id = lead.id def create_commission(self, current): from earnings.models import Commission cc = self.quote.premium.product_variant.company_category amount = self.quote.premium.commission + cc.company.commission + cc.category.commission + self.quote.opportunity.lead.user.enterprise.commission # noqa if not hasattr(self, 'commission'): commission = Commission(application_id=self.id, amount=self.premium * amount) if current.payment_failed != self.payment_failed and self.payment_failed is False: # noqa commission.status = 'application_submitted' commission.save() commission.updated = True commission.save() commission.earning.user.account.send_sms( commission.earning.get_earning_message(self)) def send_slack_request(self, event, mode_type='success'): import requests client = self.quote.opportunity.lead endpoint = 'https://hooks.slack.com/services/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' # noqa link = '%s://admin.%s/sales/application/%s/change/' % ( 'http' if ENV == 'localhost:8000' else 'https', ENV, self.id) text = event mode = self.payment_mode if self.aggregator_error: text += '\nError: %s' % (self.aggregator_error) mode = 'Broker Error' mode_type = 'error' data = dict(attachments=[ dict(fallback='Required plain-text summary of the attachment.', color={ 'success': '#36a64f', 'warning': '#ff9966', 'error': '#cc3300' }[mode_type], pretext=event, author_name=mode, title='Open Application', title_link=link, text=text, fields=[ dict(type='mrkdwn', value="*Application id:*\n%s" % self.reference_no), dict(type='mrkdwn', value="*Advisor Name:*\n%s" % client.user.get_full_name()), dict(type='mrkdwn', value="*Advisor phone:*\n%s" % client.user.account.phone_no) ], thumb_url='https://onecover.in/favicon.png', footer='Post application flow', footer_icon='https://onecover.in/favicon.png', ts=now().timestamp()) ]) return requests.post(endpoint, json=data) @property def adults(self): return self.active_members.filter(dob__year__lte=(now().year - 18)).count() @property def childrens(self): return self.active_members.count() - self.adults @cached_property def active_members(self): return self.member_set.filter(ignore=False) @cached_property def inactive_members(self): return self.member_set.exclude(ignore=False) @cached_property def company_category(self): return self.quote.premium.product_variant.company_category @cached_property def people_listed(self): return self.active_members.count() @cached_property def client(self): return self.app_client def __str__(self): return '%s - %s - %s' % (self.reference_no, self.application_type, self.company_category.company.name) class Meta: ordering = ('-created', )
class Application(BaseModel): _host = 'https://wallnut.in/%s' reference_app = models.OneToOneField('sales.application', on_delete=models.PROTECT) section = models.CharField(max_length=16) company_name = models.CharField(max_length=64, null=True) suminsured = models.CharField(max_length=16) premium = models.FloatField(default=0.0) insurance_type = models.CharField(max_length=16) quote_id = models.CharField(max_length=128, null=True) customer_code = models.CharField(max_length=64, null=True, blank=True) product_code = models.CharField(max_length=64, null=True, blank=True) producer_code = models.CharField(max_length=64, null=True, blank=True) city_code = models.CharField(max_length=16, null=True) state_code = models.CharField(max_length=16, null=True) dealstage = models.CharField(max_length=32, null=True) user_id = models.CharField(max_length=16, null=True) proposal_id = models.CharField(max_length=32, null=True) proposal_id2 = models.CharField(max_length=32, null=True) customer_id = models.CharField(max_length=32, null=True) city = models.CharField(max_length=16, null=True) state = models.CharField(max_length=16, null=True) pincode = models.CharField(max_length=16, null=True) payment_ready = models.BooleanField(default=False) regenerate_payment_link = models.BooleanField(default=True) payment_captured = models.BooleanField(default=False) raw_quote = JSONField(default=dict) insurer_product = None def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) if self.company_name: self.insurer_product = evaluateClassName(self.company_name, self.insurance_type)(self) def save(self, *args, **kwargs): try: self.__class__.objects.get(pk=self.id) except self.__class__.DoesNotExist: self.handle_creation() super(self.__class__, self).save(*args, **kwargs) def get_payment_link(self): return self.insurer_product.get_payment_link() def send_payment_link(self): from users.tasks import send_sms message = Constant.PAYMENT_MESSAGE % ( self.proposer.get_full_name(), self.reference_app.reference_no, self.premium, self.reference_app.quote.premium.product_variant.__str__(), self.get_payment_link()) send_sms.delay(self.reference_app.proposer.phone_no, message) def handle_creation(self): self.section = Constant.SECTION.get( self.reference_app.application_type) self.suminsured = int(self.reference_app.suminsured) self.premium = self.reference_app.premium self.pincode = self.reference_app.quote.opportunity.lead.pincode self.dealstage = 'productshortlisted' self.get_state_city() self.generate_quote_id() self.get_quote_data() def get_state_city(self): url = 'https://wallnut.in/health/proposal_aditya_birla/get_state_city?Pincode=%s' % ( # noqa self.reference_app.quote.opportunity.lead.pincode) request_log = ApplicationRequestLog.objects.create( application_id=self.reference_app.id, url=url, request_type='GET') response = requests.get(url).json() request_log.response = response request_log.save() self.city = response['city'] self.state = response['state'] def get_premium(self): url = self._host % 'mediclaim/get_premium' data = dict( health_pay_mode=self.pay_mode, health_pay_type=self.health_pay_type, health_pay_type_text=self.health_pay_type_text, health_sum_insured=self.suminsured, health_pay_mode_text=self.pay_mode_text, health_me=self.health_me, gender_age=self.gender_ages, pincode=self.pincode, health_insu_id=self.insurer_code, health_sum_insured_range=[self.suminsured, self.suminsured], health_city_id=self.city_code or '', health_state_id=self.state_code or '') request_log = ApplicationRequestLog.objects.create( application_id=self.reference_app.id, url=url, request_type='POST', payload=data) response = requests.post(url, data=data) request_log.response = response request_log.save() def generate_quote_id(self): url = self._host % 'save_quote_data' import json data = dict(section=self.section, quote_data=json.dumps( dict(health_pay_mode=self.pay_mode, health_pay_mode_text=self.pay_mode_text, health_me=self.health_me, health_pay_type=self.health_pay_type, health_pay_type_text=self.health_pay_type_text, health_sum_insured=self.suminsured, pincode=self.pincode, gender_age=self.gender_ages, health_sum_insured_range=[ self.suminsured, self.suminsured ], spouse='', child='', child_data=list())), quote='') request_log = ApplicationRequestLog.objects.create( application_id=self.reference_app.id, url=url, request_type='POST', payload=data) response = requests.post(url, data=data).json() request_log.response = response request_log.save() self.quote_id = response['quote'] def get_products(self): url = (self._host % 'mediclaim/get_products/%s') % self.quote_id data = dict(quote=self.quote_id) ApplicationRequestLog.objects.create( application_id=self.reference_app.id, url=url, request_type='POST', payload=data) response = requests.post(url, data=data) return response def get_quote_data(self): self.get_products() import requests url = (self._host % 'get_quote_data/%s') % self.quote_id log = ApplicationRequestLog.objects.create( application_id=self.reference_app.id, url=url, request_type='GET', ) response = requests.get(url).json() log.response = response log.save() self.city_code = response['data']['health_city_id'] self.state_code = response['data']['health_state_id'] self.fetch_quote_details() def fetch_quote_details(self): url = (self._host % 'mediclaim/fetch_quote/%s') % self.quote_id log = ApplicationRequestLog.objects.create( application_id=self.reference_app.id, url=url, request_type='GET') response = requests.get(url).json() log.response = response log.save() self.raw_quote = self.get_live_quote(response['quote_data']) self.company_name = re.sub('[ .]', '', self.raw_quote['company_name']) reference_app = self.reference_app reference_app.premium = self.raw_quote['total_premium'] reference_app.save() def get_live_quote(self, quote_data): data = filter( lambda product: product['company_name'] == Constant.COMPANY_NAME. get(self.reference_app.quote.premium.product_variant. company_category.company.name # noqa ), quote_data) quote = next(data) premium = int(self.reference_app.premium) product = self.reference_app.quote.premium.product_variant if product.parent and product.company_category.company.short_name == 'Aditya Birla': # noqa return quote while int(quote['total_premium']) not in range(premium - 100, premium + 100): quote = next(data) self.premium = quote['total_premium'] return quote def get_user_id(self): if self.user_id: return self.user_id url = self._host % 'save_user_info' app = self.reference_app data = dict( first_name=app.proposer.first_name, dob=app.proposer.dob.strftime('%d-%M-%Y'), last_name=app.proposer.last_name, email=app.proposer.email, gender=Constant.GENDER.get(app.proposer.gender, 'M'), mobile_no=app.proposer.phone_no, alternate_mobile='', occupation=Constant.OCCUPATION_CODE[app.proposer.occupation], pincode=self.pincode, city=self.city, state=self.state, address=app.proposer.address.full_address, user_id='', dealstage=self.dealstage, insu_id=self.insurer_code, insurance_type=self.section.title() + ' Insurance', amount=self.premium) log = ApplicationRequestLog.objects.create( application_id=self.reference_app.id, url=url, request_type='POST', payload=data) response = requests.post(url, data=data).json() log.response = response log.save() return response['user_id'] def insurer_operation(self): self.user_id = self.get_user_id() self.save() self.insurer_product.perform_creation() # self.send_payment_link() return True @cached_property def health_me(self): gender_ages = list() for member in self.reference_app.active_members.exclude( relation='self'): gender_ages.append([('M' if member.gender == 'male' else 'F'), str(member.age)]) return gender_ages @cached_property def proposer(self): self.self_insured = False proposers = self.reference_app.active_members if proposers.filter(relation='self').exists(): self.self_insured = True proposer = proposers.get(relation='self') elif proposers.filter(relation='spouse').exists(): proposer = proposers.get(relation='spouse') else: proposer = proposers.first() proposer.marital_status = Constant.get_marital_status( proposer.relation ) or self.reference_app.proposer.marital_status.title() # noqa return proposer @cached_property def health_pay_type(self): if self.reference_app.active_members.count() == 1: return '' return '%sA%sC' % (self.reference_app.adults, self.reference_app.childrens) @cached_property def health_pay_type_text(self): pay_type_text = '' if self.reference_app.active_members.count() == 1: return pay_type_text if self.reference_app.active_members.filter(relation='self').exists(): pay_type_text += 'ME ' if self.reference_app.active_members.filter( relation='spouse').exists(): # noqa pay_type_text += 'Spouse ' if self.reference_app.active_members.filter( relation__in=['son', 'daughter']).exists(): # noqa pay_type_text += '%sChild' % self.reference_app.childrens return pay_type_text.strip() @cached_property def pay_mode(self): return 'I' if len(self.reference_app.active_members) == 1 else 'F' @cached_property def pay_mode_text(self): return 'Individual' if len( self.reference_app.active_members) == 1 else 'Family' @cached_property def gender_ages(self): return [[Constant.GENDER[self.proposer.gender], self.proposer.age]] @cached_property def all_premiums(self): return self.raw_quote['all_premium'].split(',') @cached_property def insurer_code(self): return self.raw_quote['insurance_code'] def __str__(self): return '%s | %s' % (self.quote_id, self.reference_app.__str__())
class User(BaseModel): account = models.ForeignKey('users.Account', on_delete=models.CASCADE) user_type = models.CharField( choices=get_choices(Constants.USER_TYPE), max_length=16, default=Constants.DEFAULT_USER_TYPE) campaign = models.ForeignKey( 'users.Campaign', null=True, blank=True, on_delete=models.CASCADE) rating = models.IntegerField(default=5) enterprise = models.ForeignKey( 'users.Enterprise', on_delete=models.PROTECT) flag = JSONField(default=Constants.USER_FLAG) is_active = models.BooleanField(default=False) manager_id = models.CharField(max_length=48, null=True, blank=True) def save(self, *args, **kwargs): cache.delete('USER_DETAIL:%s' % self.id) super(self.__class__, self).save(*args, **kwargs) class Meta: unique_together = ('user_type', 'account') def __str__(self): return self.account.get_full_name() def get_authorization_key(self): return jwt.encode( {'user_id': str(self.id)}, JWT_SECRET, algorithm='HS256') def get_full_name(self): return self.account.get_full_name() @classmethod def get_authenticated_user(cls, token): try: payload = jwt.decode(token, JWT_SECRET) return cls.objects.get(id=payload.get('user_id')) except Exception: pass return None def get_accounts(self): return self.bankaccount_set.filter(is_active=True) def generate_referral(self, referral_reference=None): import random code = ('%s%s' % ( self.account.first_name.lower()[:3], self.account.phone_no[-5:]) ).upper() if Referral.objects.filter(code=code).exists(): while Referral.objects.filter(code=code).exists(): code = ('%s%s' % ( self.account.first_name.lower()[:3], random.randint(11111, 99999))).upper() return Referral.objects.create( code=code, reference_code=referral_reference, user_id=self.id) def get_categories(self): categories = list() from product.models import Category for category in Category.objects.only( 'name', 'id', 'hexa_code', 'logo', 'is_active'): is_active = False categorys = self.enterprise.categories.filter(id=category.id) if categorys.exists(): is_active = categorys.get().is_active categories.append(dict( id=category.id, hexa_code=category.hexa_code, name=category.name.split(' ')[0], is_active=is_active, logo=( Constants.DEBUG_HOST if DEBUG else '') + category.logo.url )) categories = sorted( categories, key=lambda category: Constants.CATEGORY_ORDER.get( category['name'], 1)) return categories def get_companies(self): return self.enterprise.companies.filter(is_active=True) def get_applications(self, status=None): from sales.models import Application query = dict(quote__opportunity__lead__user_id=self.id) if status and isinstance(status, list): query['status__in'] = status elif status: query['status'] = status return Application.objects.filter(**query) def get_policies(self): from sales.models import Policy return Policy.objects.filter( application__quote__opportunity__lead__user_id=self.id) def get_earnings(self, earning_type=None): from earnings.models import Earning return Earning.get_user_earnings(self.id, earning_type) def get_rules(self): rules = dict.fromkeys(Constants.PROMO_RULES_KEYS, False) rules['button_text'] = dict( recommendation='View plan details', product_detail='Save Plan') promo_code = self.enterprise.promocode.code.split('-')[1:] for rule_code in promo_code: if not rule_code.isdigit(): rule_code = 1 rules.update(Constants.PROMO_RULES[int(rule_code)]) if self.enterprise.enterprise_type != 'subscriber': rules['kyc_allowed'] = True rules['button_text']['recommendation'] = 'Buy Now' rules['button_text']['product_detail'] = 'Buy Now' return rules def get_collaterals(self): from content.models import Collateral return Collateral.objects.filter( promocode_id=self.enterprise.promocode_id) @staticmethod def validate_referral_code(code): return Referral.objects.filter(code=code).exists() @staticmethod def validate_promo_code(code): return PromoCode.objects.filter(code=code).exists() @staticmethod def get_referral_details(code): # To Dos: Remove this referrals = Referral.objects.filter(code=code) if not referrals.exists(): return { 'user_type': Constants.DEFAULT_USER_TYPE, 'enterprise_id': SubcriberEnterprise.objects.get( name=Constants.DEFAULT_ENTERPRISE).id } referral = referrals.get() from earnings.models import Earning Earning.objects.create( user_id=referral.user.id, earning_type='referral', amount=100) return dict( enterprise_id=( referral.enterprise or SubcriberEnterprise.objects.get( name=Constants.DEFAULT_ENTERPRISE)).id) @staticmethod def get_promo_code_details(code, name): promo_code = PromoCode.objects.get(code=code) enterprises = Enterprise.objects.filter( promocode=promo_code, enterprise_type='enterprise') if enterprises.exists(): return dict( user_type='enterprise', enterprise_id=enterprises.get().id) enterprise = Enterprise.objects.create(name=name, promocode=promo_code) from product.models import Category, Company for category_id in Category.objects.values_list('id', flat=True): enterprise.categories.add(category_id) for company_id in Company.objects.values_list('id', flat=True): enterprise.companies.add(company_id) enterprise.save() return dict( user_type=enterprise.enterprise_type, enterprise_id=enterprise.id) @property def account_no(self): return self.bankaccount_set.get(default=True).account_no @property def ifsc(self): return self.bankaccount_set.get(default=True).branch.ifsc @property def bank_name(self): return self.bankaccount_set.get(default=True).branch.bank.name