def get_property(property_id, source): """ :param property_id: :param source: :return: """ from leads.models import Property p_id = property_id.lower() s_name = source.name.lower() obj, created = None, False try: obj = Property.objects.filter(property_ids__contains=({s_name: p_id}))[0] except IndexError: try: obj = Property( title='{0} property : {1}'.format(source.name, property_id), agency=source.agency, property_ids={s_name: p_id}, ) obj.save() created = True except Exception as e: logger.error('Error:{0} creating a property with ID: {0} for {1} '.format(str(e)), property_id, source.name) return None, False except Exception as e: logger.error('Error:{0} searching the property with ID: {0} for {1} '.format(str(e)), property_id, source.name) return None, False if created: content = 'New {0} property'.format(source.name) notify(obj, content) return obj, created
def save(self, **kwargs): from fetchmyguest.utils.notifications import notify if not self.agency: self.agency = get_agency() obj = super(Note, self).save(**kwargs) #from fetchmyguest.utils.notifications import notify notify(self.lead, 'Note for lead: {0}'.format(self.lead.customer), alert=True) return obj
def manage_generic_customer_message(msg, customer_id): """ :param msg: :param customer_id: :return: """ from leads.models import Lead, Customer leads = Lead.objects.filter(customer_id=customer_id).order_by('-modified') if leads.exists(): lead = leads[0] msg.lead = lead msg.save() lead.modified = timezone.now() content = 'Reply from {0}'.format(lead.customer) lead.hot = True lead.save() notify(msg, content, alert=True) else: # a message from a client but no leads, lets create one or update an old one customer = Customer.objects.get(pk=customer_id) create_lead(source=None, msg=msg, customer=customer) return
def has_related_lead(msg, sources): """ Obtaining the standard python email object we can check if the message has an 'In-Reply-To' field or a 'References' so can be related to a lead if exists. We can implement another strategy to identify responses like testing the sender address and other lead related indicators. :param msg: mailbox Message :param sources: :return: True or False """ # Let's see if we find a related message, linked or with a matching 'In-Reply-To' or 'References' header ref_msg = None source = None if msg.in_reply_to: # we test if there is already a related message ref_msg = msg.in_reply_to else: message_obj = msg.get_email_object() message_id = False if 'In-Reply-To' in message_obj: message_id = message_obj['In-Reply-To'] elif 'References' in message_obj: message_id = message_obj['References'] if message_id: try: from django_mailbox.models import Message ref_msg = Message.objects.get(message_id=message_id) except msg.DoesNotExist: logger.debug('Message with internal id {0} that refers to id:\n{1}\n' 'has no matching messages.'.format(msg.id, message_id)) # We want to see if there is already a lead or we can create one if ref_msg and ref_msg.lead: msg.lead = ref_msg.lead msg.save() content = 'Reply from {0}'.format(msg.lead.customer) notify(msg, content, alert=True) l = ref_msg.lead l.hot = True l.save() return True if ref_msg: is_lead, source = is_a_lead(sources, ref_msg) if is_lead: # We had a reply to a potential lead but for some reason that was not qualified lead, lead_created = create_lead(source, ref_msg) # Forcing to create a lead msg.lead = lead msg.save() content = 'Reply from {0}'.format(msg.lead.customer) notify(msg, content, alert=True) lead.hot = True lead.save() return # Here we try to relate emails incoming from known customers to the last active lead if isinstance(msg.from_address, list): from_email = get_valid_email(' '.join(msg.from_address)) else: from_email = get_valid_email(msg.from_address) if from_email: customer_id = get_customer_id(from_email, source) if customer_id: manage_generic_customer_message(msg, customer_id) return True return False
def create_lead(source=None, msg=None, customer=None): """ Main function generate leads Keyword arguments :param source object a LeadSource object :param msg object a django mailbox Message object :param customer object :return None nothing to return """ from leads.models import Lead, LeadProperty property = None lead, lead_created = None, False TODAY = timezone.now().date() try: CUT_OFF_DAYS = settings.LEADS_CUT_OFF_DAYS except: CUT_OFF_DAYS = 30 CUT_OFF_DATE = TODAY + relativedelta(days=-CUT_OFF_DAYS) ######################## Check for a property using the id in the message ################### if source: property_id = apply_rules(source, msg, target_field=PROPERTIES) if property_id: property, property_created = get_property(property_id=property_id, source=source) else: logger.warning('No property id found in message ID:{0}, source: {1}'.format(msg.id, source.name)) if not customer: customer = get_or_create_customer(source, msg) msg_arrival=date_parse(apply_rules(source, msg, target_field=ARRIVAL)).date() or TODAY msg_departure=date_parse(apply_rules(source, msg, target_field=DEPARTURE)).date() or TODAY msg_adults=int_or_0(apply_rules(source, msg, target_field=ADULTS)) msg_children=int_or_0(apply_rules(source, msg, target_field=CHILDREN)) agency = source.agency source_name = source.name elif customer: agency = customer.agency source_name = 'Customer message' msg_arrival = msg_departure = TODAY msg_adults = msg_children = 0 else: # Cannot create a lead with no source and no customer logger.error('Message id: {0} Cannot create a lead with no source and no customer'.format(msg.id)) return '', False ############################ We have all we need to create or get a lead ############################## try: lead = Lead.objects.filter(customer=customer, agency=agency, # This line below will allow to aggregate leads from the same source # source__iexact=source_name, created__gt=CUT_OFF_DATE, booked=False).order_by('-modified')[0] except (IndexError, Lead.DoesNotExist): # No leads found, let's create one try: lead = Lead( customer=customer, arrival=msg_arrival, departure=msg_departure, adults=msg_adults, children=msg_children, source=source_name, agency=agency ) lead.save() msg.lead = lead msg.is_lead_source = True msg.save() lead_created = True except Exception as e: logger.error('Message id: {0} qualified as a lead but could not be saved, Error: {1}'.format(msg.id, repr(e))) return '', False ### If we have a property and is not in the related list we add it ###### if property: # check if there is already that property attached to the lead for the same dates, otherwise we add one lp, lp_created = LeadProperty.objects.get_or_create( lead=lead, property=property, agency=source.agency, available_from= msg_arrival or lead.arrival, available_to=msg_departure or lead.departure, defaults={'status': LeadProperty.REQUESTED} ) if lp_created: # Property not already on the list New offer must be sent lead.first_response = False ################ Notify if we created this lead, otherwise is a response #################### if lead_created: content = 'New lead from {0}'.format(lead.customer) notify(msg, content) else: msg.lead = lead msg.save() lead.modified = timezone.now() lead.save() logger.debug('Message id:{0} is a double post or a generic message from customer'.format(msg.id)) content = 'New lead from {0}'.format(lead.customer) notify(msg, content) return lead, lead_created