Esempio n. 1
0
class Click2Call_Log(models.Model):
	callid = models.CharField(max_length=34)
	caller = models.ForeignKey(MHLUser, related_name="click2call_log_caller")
	caller_number = MHLPhoneNumberField(blank=True)
	called_user = models.ForeignKey(MHLUser, blank=True, null=True, related_name="click2call_log_called")
	called_number = MHLPhoneNumberField(blank=True)
	source = models.CharField(max_length=3, choices=CLICK2CALL_SOURCES)
	connected = models.BooleanField(default=False)

	current_site = models.ForeignKey(Site, null=True, blank=True, related_name="click2caller_current_site")

	timestamp = models.DateTimeField(auto_now=True, editable=False)

	def save(self, *args, **kwargs):
		# if new record and current_site is defined and not 0, we add count to siteAnalytics
		if ((not self.id) and (self.current_site > 0)):
			try:
				siteStat = SiteAnalytics.objects.get(dateoflog=datetime.date.today(), site=self.current_site)
			except SiteAnalytics.DoesNotExist:
				siteStat = SiteAnalytics(dateoflog=datetime.date.today(), site=self.current_site, 
					countPage=0, countMessage=0, countClick2Call=0)
				siteStat.save()
			siteStat.countClick2Call = F('countClick2Call') + 1
			siteStat.save()
		super(Click2Call_Log, self).save(*args, **kwargs)

	class Meta:
		db_table = 'DoctorCom_click2call_log'
Esempio n. 2
0
class MessageLog(models.Model):
	message = models.ForeignKey(MessageTemp, editable=False, related_name="messagelog_message")
	message_recipient = models.ForeignKey(MHLUser, editable=False, related_name="messagelog_recip")

	# Was the message successfully sent?
	success = models.BooleanField(editable=False)
	# The following field is for message confirmation numbers -- currently,
	# a set of numbers. Unfortunately, errors from the SMS service come back
	# as strings. If the message fails to be sent, we will store the error
	# in this field. Note that the following field is for Convergent Mobile SMS
	# messaging.
	confirmation = models.CharField(max_length=250, blank=True, editable=False)

	# Twilio SMS values
	twilio_sid = models.CharField(max_length=64, blank=True, editable=False, db_index=True)
	twilio_status = models.CharField(max_length=2, choices=TWILIO_SMS_STATUS_CHOICES)

	body_fragment = models.CharField(max_length=200, blank=True, editable=False)
	resend_of = models.ForeignKey('self', null=True)  # Keep track of message re-sends via this field
	current_site = models.ForeignKey(Site, null=True, blank=True, related_name="messager_current_site")

	tx_number = MHLPhoneNumberField(editable=False)  # we keep this copy since the Sender can be deleted or change their cell number
	rx_number = MHLPhoneNumberField(editable=False)  # we keep this copy since the Recipient can be deleted or change their cell number
	tx_name = models.CharField(max_length=50, editable=False)  # '' or change their name
	rx_name = models.CharField(max_length=50, editable=False)  # '' or change their name

	# Timestamp for when this message send is attempted.
	timestamp = models.DateTimeField(auto_now_add=True, editable=False)

	def save(self, *args, **kwargs):
		# if new record and current_site is defined and not 0, we add count to siteAnalytics
		if ((not self.id) and (self.current_site > 0)):
			try:
				siteStat = SiteAnalytics.objects.get(dateoflog=datetime.date.today(), 
					site=self.current_site)
			except SiteAnalytics.DoesNotExist:
				siteStat = SiteAnalytics(dateoflog=datetime.date.today(), 
					site=self.current_site, countPage=0, countMessage=0, countClick2Call=0)
				siteStat.save()
			siteStat.countMessage = F('countMessage') + 1
			siteStat.save()
		super(MessageLog, self).save(*args, **kwargs)

	def __unicode__(self):
		return "Message fragment from %s to %s" % (self.tx_name, self.rx_name)

	class Meta:
		db_table = 'DoctorCom_messagelog'
Esempio n. 3
0
class SenderLookup(models.Model):
    # "Owner" of this lookup table entry -- original outbound message sender
    user = models.ForeignKey(
        MHLUser,
        related_name="User whose mobile phone this mapping belongs to")

    # Person/number to which this mapping points -- inbound reply messages will
    # be from this person
    mapped_user = models.ForeignKey(
        MHLUser,
        null=True,
        related_name='User for whom this mapping points to')

    # The number that the mapping uses.
    number = MHLPhoneNumberField(blank=True, db_index=True)

    timestamp = models.DateTimeField(auto_now=True)

    def __unicode__(self):
        return 'SMS Map between %s %s and %s %s' % (
            self.user.first_name, self.user.last_name,
            self.mapped_user.first_name, self.mapped_user.last_name)

    class Meta:
        unique_together = (('mapped_user', 'number'), )
Esempio n. 4
0
class PagerLog(models.Model):
	pager = models.ForeignKey(MHLUser, related_name="pagerlog_pager", null=True)
	paged = models.ForeignKey(MHLUser, related_name="pagerlog_paged")
	current_site = models.ForeignKey(Site, null=True, blank=True, related_name="pager_current_site")

	callback = MHLPhoneNumberField()

	timestamp = models.DateTimeField(auto_now=True, editable=False)

	def save(self, *args, **kwargs):
		# if new record and current_site is defined and not 0, we add count to siteAnalytics
		if ((not self.id) and (self.current_site > 0)):
			try:
				siteStat = SiteAnalytics.objects.get(dateoflog=datetime.date.today(), 
						site=self.current_site)
			except SiteAnalytics.DoesNotExist:
				siteStat = SiteAnalytics(dateoflog=datetime.date.today(), site=self.current_site, 
					countPage=0, countMessage=0, countClick2Call=0)
				siteStat.save()
			siteStat.countPage = F('countPage') + 1
			siteStat.save()
		super(PagerLog, self).save(*args, **kwargs)

	class Meta:
		db_table = 'DoctorCom_pagerlog'
Esempio n. 5
0
class callLog(models.Model):
	"""
	Call session information. This keeps track of call attributes that are across 
	all Twilio requests, such as caller, called, phone numbers, call duration, etc.
	"""
	# Callers
	caller_type = models.ForeignKey(ContentType, null=True, blank=True, 
		related_name="callLog_callertype")
	caller_id = models.PositiveIntegerField(null=True, blank=True)
	mdcom_caller = generic.GenericForeignKey('caller_type', 'caller_id')
	# The following is *always* set, just so that we know what number the call
	# was made from. This should be the number the caller is coming from, *not*
	# the caller's DoctorCom number if they have one. This is intentional
	# duplicative information.
	caller_number = MHLPhoneNumberField(blank=True)

	# Calleds (recipients)
	called_type = models.ForeignKey(ContentType, null=True, blank=True, 
				related_name="callLog_calledtype")
	called_id = models.PositiveIntegerField(null=True, blank=True)
	mdcom_called = generic.GenericForeignKey('called_type', 'called_id')
	# The following is *always* set, just so that we know what number the call
	# was received at. This is intentional duplicative information. This may
	# be the user's DoctorCom number. It's the number that the user dialed.
	called_number = MHLPhoneNumberField(blank=True)

	caller_spoken_name = models.TextField()

	callSID = models.CharField(max_length=64, unique=True, db_index=True)
	call_connected = models.BooleanField(default=False)

	# C2C Call Data
	# FIXME: The following import creates a circular import, which results in
	# import failures a plenty. For the time being, we're going to use an
	# Integer field that Django would be using.
	#from MHLogin.DoctorCom.models import Click2Call_Log
	#c2c_entry = models.ForeignKey(DCom.models.Click2Call_Log, null=True, blank=True)
	c2c_entry_id = models.IntegerField(null=True, blank=True)

	call_duration = models.IntegerField(null=True)
	#current_site = models.ForeignKey(Site, null=True, blank=True, 
	#  related_name="ivr_calllog_current_site")
	# Book keeping
	timestamp = models.DateTimeField(auto_now_add=True)
	call_source = models.CharField(max_length=2, choices=SOURCE_CHOICES)
Esempio n. 6
0
class VMMessage(models.Model):
	# The "individual" whose voicemail this is. We are going with a generic
	# relation here so that messages can be associated with any object type,
	# be it a user, office, site, or something we haven't thought of.
	owner_type = models.ForeignKey(ContentType)	
	owner_id = models.PositiveIntegerField()
	owner = generic.GenericForeignKey('owner_type', 'owner_id')

	callerID = models.CharField(max_length=64)

	# Path to a recording of the user speaking his/her voice OR the twilio ID of
	# the recording. Note that the distinction shall be that paths start with a
	# forward slash character, while the Twilio recordings start with the
	# letters 'RE'.
	# 
	# Please do not get the recording field value directly. Rather, please use
	# the getRecordingUrl method instead so that the read_timestamp can be set
	# and so that the correct URL is given back, regardless of where the
	# recording is stored.
	recording = models.TextField()

	# Management Fields
	deleted = models.BooleanField(default=False)  # We don't delete just mark as deleted
	read_flag = models.BooleanField(default=False)
	read_timestamp = models.DateTimeField(null=True)

	# Book keeping
	timestamp = models.DateTimeField(auto_now_add=True)
	#answering service
	answeringservice = models.BooleanField(default=False)
	callbacknumber = MHLPhoneNumberField(blank=True)

	def delete(self, *args, **kwargs):
		# Don't delete this message. Just mark it as deleted.
		self.deleted = True
		self.save()
		# Alternatively
		#raise Exception('Voicemail messages may not be deleted.')

	def sanitize(self):
		""" Sanitizes any personally identifying data from this object. NOTE THAT THIS
		DOES NOT SAVE THE OBJECT!"""
		if (not settings.DEBUG):
			raise Exception('You must be in DEBUG mode to use this function.')
		self.callerID = '8004664411'
		self.recording = 'http://api.twilio.com/2008-08-01/Accounts/'\
			'AC087cabfd0a453a05acceb2810c100f69/Recordings/REf8afc497f43d8e1e9bc229a415ebe100'

	def getRecordingUrl(self):
		if (not self.read_timestamp):
			self.read_timestamp = datetime.datetime.now()
			self.read_flag = True
			self.save()
		# TODO_RECORDING:
		# check to see if this is a Twilio URL or a cloud storage URL, then
		# modify it appropriately if needed.
		return self.recording
Esempio n. 7
0
class OfficeStaff(models.Model):
	# Be aware that if you're creating a OfficeStaff user, you need to manually
	# populate this field with the correct User object!
	user = models.ForeignKey(MHLUser, null=True, blank=True, related_name='user_officestaff')

	office_phone = MHLPhoneNumberField(blank=True, help_text=PHONE_NUMBER_HELP_TEXT)
	office_address1 = models.CharField(max_length=200, blank=True)
	office_address2 = models.CharField(max_length=200, blank=True)
	office_city = models.CharField(max_length=200, blank=True)
	office_state = models.CharField(max_length=2, choices=STATE_CHOICES, blank=True)
	office_zip = models.CharField(max_length=10, blank=True)  # 10 for zip and zip+4

	# Django IntegerField too small for US phone number with area code.
	pager = MHLPhoneNumberField(blank=True, verbose_name=_('pager'), help_text=PHONE_NUMBER_HELP_TEXT)
	pager_extension = models.CharField(max_length=100, blank=True, verbose_name=_('pager extension'))
	pager_confirmed = models.BooleanField(default=False)

	sites = models.ManyToManyField(Site, null=True, blank=True, 
					related_name='site_officestaff')
	current_site = models.ForeignKey(Site, null=True, blank=True, 
					related_name='site_officestaff_current')

	practices = models.ManyToManyField(PracticeLocation, null=True, blank=True, 
					related_name='practice_officestaff')
	current_practice = models.ForeignKey(PracticeLocation, null=True, blank=True, 
					related_name='practice_officestaff_current')
	vm_config = generic.GenericRelation(VMBox_Config,
					content_type_field='owner_type', object_id_field='owner_id')
	caller_anssvc = models.CharField(max_length=2, choices=CALLER_ANSSVC_CHOICES, default='')
	objects = models.Manager()
	active_objects = ActiveManagedUser()

	#add by xlin 120914
	search_objects = SearchOfficeStaff()

	class Meta:
		verbose_name = _("Office Staff")
		verbose_name_plural = _("Office Staff")
		ordering = ['user']

	def __unicode__(self):
		return "%s %s" % (self.user.first_name, self.user.last_name)
Esempio n. 8
0
class AnsSvcDLFailure(models.Model):
	"""
	Keeps track of which answering service messages have had message fetch failures.
	"""
	# Meta
	practice_id = models.IntegerField()  # The PK for the practice
	error_timestamp = models.DateTimeField(auto_now_add=True)
	resolved = models.BooleanField(default=False, db_index=True)
	resolution_timestamp = models.DateTimeField(null=True, blank=True)
	failure_type = models.CharField(max_length=2, choices=FAILURE_CHOICES, default='DL')
	# Call Data
	post_data = models.TextField()
	call_sid = models.CharField(max_length=255, db_index=True)
	caller = models.CharField(max_length=20)
	called = models.CharField(max_length=20)
	recording_url = models.TextField(null=True, blank=True)
	callback_number = MHLPhoneNumberField()

	# Message objects
	# The PK for the original error notice message.	
	error_message_uuid = models.CharField(max_length=32, blank=True, null=True)
	# The PK for the resolution notification message.	
	resolution_message_uuid = models.CharField(max_length=32, blank=True, null=True)

	def init_from_post_data(self, post_data_dict):
		"""
		Initialize this object based on POST data from Twilio. This is simply
		a shortcut/utility method.

		Warning: post_data_dict is assumed to be sanitized!
		"""
		self.post_data = repr(dict(post_data_dict))
		self.call_sid = post_data_dict['CallSid']
		self.caller = post_data_dict['Caller']
		self.called = post_data_dict['Called']

	def save(self, *args, **kwargs):
		if (self.pk):
			raise Exception(_('Saving existing entries is disallowed. Update this '
				'object through its access methods.'))
		super(AnsSvcDLFailure, self).save(*args, **kwargs)

		log = AnsSvcDLFailureActivityLog(call_sid=self.call_sid, action='NEW')
		log.save()

	def mark_resolved(self, message):
		self.resolved = True
		self.resolution_timestamp = datetime.datetime.now()
		if (hasattr(message, 'uuid')):
			self.resolution_message_uuid = message.uuid
		else:
			self.resolution_message_uuid = message
		self.recording_url = None
		super(AnsSvcDLFailure, self).save()
Esempio n. 9
0
class AccessNumber(models.Model):
    practice = models.ForeignKey(PracticeLocation)
    description = models.CharField(max_length=50, blank=True)
    number = MHLPhoneNumberField(blank=False)
Esempio n. 10
0
class PracticeLocation(models.Model):
    """
	Practice location object. Represents physical location of practice storing 
	address, doctor.com number, and members.  Members consist of professionals, 
	office staff, and office managers, of which office managers have change rights.
	"""
    practice_name = models.CharField(max_length=100, unique=True,\
     verbose_name=_('Name'))
    practice_address1 = models.CharField(max_length=200,
                                         blank=True,
                                         verbose_name=_("Address1"))
    practice_address2 = models.CharField(max_length=200,
                                         blank=True,
                                         verbose_name=_("Address2"))
    practice_phone = MHLPhoneNumberField(blank=True,
                                         verbose_name=_("Office Phone"))
    backline_phone = MHLPhoneNumberField(blank=True,
                                         verbose_name=_("Backline Phone"))
    practice_city = models.CharField(max_length=200,
                                     blank=True,
                                     verbose_name=_("City"))
    practice_state = models.CharField(max_length=2,
                                      choices=STATE_CHOICES,
                                      blank=True,
                                      verbose_name=_("State"))
    practice_zip = models.CharField(max_length=10,
                                    blank=True,
                                    verbose_name=_("Zip"))
    practice_lat = models.FloatField(blank=True)
    practice_longit = models.FloatField(blank=True)
    practice_photo = models.ImageField(
        upload_to="images/practicepics/%Y/%m/%d",
        blank=True,
        verbose_name=_("Logo"),
        help_text=_("Recommended size 100*30"))

    #DoctorCom Provisioned Phone Number and confirmation flag
    mdcom_phone = MHLPhoneNumberField(blank=True)
    mdcom_phone_sid = models.CharField(max_length=34, blank=True)

    #time zone where practice is located, matches values in pytz
    time_zone = models.CharField(max_length=64,
                                 blank=False,
                                 choices=TIME_ZONES_CHOICES,
                                 verbose_name=_('time zone'))

    #what call group is associated with this practice
    call_group = models.ForeignKey('MHLCallGroups.CallGroup',
                                   null=True,
                                   blank=True)
    #as we develop more functionality we will put products subscribed, billing, tos etc here

    #columns needed by answering service
    pin = models.CharField(max_length=120, blank=True)
    name_greeting = models.TextField(blank=True)
    greeting_closed = models.TextField(blank=True)
    greeting_lunch = models.TextField(blank=True)
    skip_to_rmsg = models.BooleanField(
        default=False,
        help_text=_('skip to taking a nonurgent message instead of '
                    'asking during open hours'))
    config_complete = models.BooleanField(default=False)

    call_groups = models.ManyToManyField(
        'MHLCallGroups.CallGroup',
        null=True,
        blank=True,
        related_name="PracticeCallGroups",
        verbose_name=("List of all of the call groups for this practice"))
    gen_msg = models.BooleanField(
        default=True,
        help_text=
        ('read out option for leaving nonurgent message for generic mailbox of practice'
         ))

    # refactor organization added fields
    logo_position = models.IntegerField(choices=ORG_POSITION_TYPE,
                                        verbose_name=_("Logo Position"),
                                        default=0)
    logo_size = models.IntegerField(choices=ORG_SIZE_TYPE,
                                    verbose_name=_("Logo Size"),
                                    default=0)
    description = models.CharField(max_length=255,
                                   blank=True,
                                   null=True,
                                   verbose_name=_("Description"))
    create_date = models.DateTimeField(auto_now=True)
    status = models.IntegerField(default=1)
    short_name = models.CharField(max_length=30, blank=True)
    organization_type = models.ForeignKey(OrganizationType,
                                          null=True,
                                          blank=True)
    organization_setting = models.ForeignKey(
        'MHLPractices.OrganizationSetting', null=True, blank=True)

    member_orgs = models.ManyToManyField(
        'MHLPractices.PracticeLocation',
        through='MHLPractices.OrganizationMemberOrgs',
        related_name='member org',
        null=True,
        blank=True)
    member_org_pending = models.ManyToManyField('MHLPractices.PracticeLocation',
     through='MHLPractices.Pending_Org_Association',\
     related_name='member org pending', null=True, blank=True)

    delete_flag = models.BooleanField(default=False)

    objects = ActiveOrganization()
    full_objects = models.Manager()
    active_practice = ActivePractice()

    def __unicode__(self):
        return self.practice_name

    def uses_original_answering_serice(self):
        """ Will return True in case this practice was set up using one call group per location
		    version 2 requires NULL in practice.location call group and at least one entry in call_groups
			False in other case
		"""
        return self.call_group is not None

    __unicode__ = lambda self: self.practice_name

    def is_open(self, timestamp=None):
        """
		:param timestamp: A timestamp (integer UNIX timestamp or a datetime object) 
			indicating the date and time you want to check. Alternatively, set it to 
			None to use the current time. Note that datetime objects *MUST* be timezone
			aware, or an exception will be raised.
		:returns: True if the practice is open, and False if the practice is closed, 
			given the passed time.
		"""
        # Munge the timestamp argument so that we always have a datetime object
        # representative of that time, in the practice's time zone.
        if (not timestamp):
            timestamp = datetime.now(timezone(self.time_zone))
        elif (timestamp.__class__.__name__ == 'datetime'):
            # If the timestamp is a datetime object
            if (timestamp.tzinfo == None):
                raise Exception(
                    _('PracticeLocation.is_open() requires a '
                      'timezone aware datetime object.'))
            timestamp = timestamp.astimezone(tz)
        else:
            # The timestamp is a UNIX timestamp.
            timestamp = datetime.fromtimestamp(timestamp, self.time_zone)

        if (PracticeHolidays.objects.filter(
                practice_location=self.id, designated_day=timestamp).exists()):
            return False

        # Shortcut to make access of the weekday easier.
        weekday = timestamp.isoweekday()

        today_hours = PracticeHours.objects.filter(practice_location=self.id,
                                                   day_of_week=weekday)
        if (len(today_hours) == 0):
            # Days with no hours objects defined are considered closed.
            return False

        # Don't sweat len(today_hours) > 1 because the database schema forbids it.
        today_hours = today_hours[0]

        # Heavy lifting! :)
        if (timestamp.time() > today_hours.open
                and timestamp.time() < today_hours.close):
            return True
        else:
            return False

    def set_pin(self, raw_pin):
        """
		Based on Django 1.1.1's password hash generator.
		"""
        import random
        from MHLogin.DoctorCom.IVR.models import get_hexdigest
        algo = 'sha1'
        salt = get_hexdigest(algo, str(random.random()),
                             str(random.random()))[:5]
        hashe = get_hexdigest(algo, salt, raw_pin)
        self.pin = '%s$%s$%s' % (algo, salt, hashe)

    def verify_pin(self, raw_pin):
        """
		Based on Django 1.1.1's password hash generator.

		:returns: a boolean of whether the raw_password was correct. Handles
			encryption formats behind the scenes.
        """
        return check_pin(raw_pin, self.pin)

    def get_members(self):
        """ Return a queryset list of all MHLUsers belonging this practice """
        from MHLogin.MHLUsers.models import MHLUser
        users = list(self.practice_provider.all().values_list('user',
                                                              flat=True))
        users.extend(
            list(self.practice_provider_current.all().values_list('user',
                                                                  flat=True)))
        users.extend(
            list(self.practice_officestaff.all().values_list('user',
                                                             flat=True)))
        users.extend(
            list(self.practice_officestaff_current.all().values_list(
                'user', flat=True)))
        users.extend(
            list(self.practice_office_manager.all().values_list('user__user',
                                                                flat=True)))
        # unique'ify and return MHLUser list
        return MHLUser.objects.filter(id__in=set(users))

    def sanitize(self):
        "Sanitizes any personally identifying data from this object."
        "NOTE THAT THIS DOES NOT SAVE THE OBJECT!"
        if (not settings.DEBUG):
            raise Exception(
                _('You must be in DEBUG mode to use this function.'))
        self.set_pin('1234')
        self.greeting = 'http://api.twilio.com/2008-08-01/Accounts/'\
         'AC087cabfd0a453a05acceb2810c100f69/Recordings/REf8afc497f43d8e1e9bc229a415ebe100'
        self.name = 'http://api.twilio.com/2008-08-01/Accounts/'\
         'AC087cabfd0a453a05acceb2810c100f69/Recordings/REf8afc497f43d8e1e9bc229a415ebe100'

    def multi_callgroup(self):
        return not bool(self.call_group)

    def save_parent_org(self, parent_org=None, billing_flag=None):
        """ Save organization parent relationship
		:param parent_org: is an instance of PracticeLocation
		:param billing_flag: billing_flag
		"""
        if parent_org:
            try:
                org_relation = OrganizationRelationship.active_objects.get(
                    organization=self, parent=parent_org)
                org_relation.billing_flag = billing_flag
                org_relation.save()
            except OrganizationRelationship.DoesNotExist:
                org_relation = OrganizationRelationship.objects.create(
                    organization=self,
                    parent=parent_org,
                    create_time=time.time())
        else:
            OrganizationRelationship.active_objects.filter(
                organization=self, parent=parent_org).delete()

    def save_member_org(self, member_org=None, billing_flag=None):
        """ Save organization member relationship
		:param member_orgs: is an instance of PracticeLocation
		:param billing_flag: billing_flag
		"""
        if member_org:
            try:
                member = OrganizationMemberOrgs.objects.get(
                    from_practicelocation=self, to_practicelocation=member_org)
                member.billing_flag = billing_flag
                member.save()
            except OrganizationMemberOrgs.DoesNotExist:
                OrganizationMemberOrgs.objects.create(
                    from_practicelocation=self,
                    to_practicelocation=member_org,
                    create_time=time.time(),
                    billing_flag=billing_flag)
        else:
            OrganizationMemberOrgs.objects.filter(
                from_practicelocation=self,
                to_practicelocation=member_org).delete()

    def get_setting(self):
        """ Get org's setting object.
		:returns: an instance of OrganizationSetting
		"""
        if self.organization_setting and not self.organization_setting.delete_flag:
            return self.organization_setting
        else:
            org_type = self.organization_type
            if org_type and org_type.organization_setting and not \
              org_type.organization_setting.delete_flag:
                return org_type.organization_setting
            else:
                return None

    def get_setting_attr(self, key):
        """ Get org's setting's attribute value.
		:returns: setting's value
		"""
        setting = self.get_setting()
        if not setting:
            return False
        if not key or key not in dir(setting):
            return False
        return getattr(setting, key)

    def can_have_any_staff(self):
        setting = self.get_setting()
        if not setting:
            return None
        else:
            return setting.can_have_staff or setting.can_have_manager or \
             setting.can_have_nurse or setting.can_have_dietician

    def can_have_staff_member(self):
        setting = self.get_setting()
        if not setting:
            return None
        else:
            return setting.can_have_staff or setting.can_have_nurse or \
             setting.can_have_dietician

    def can_have_any_provider(self):
        setting = self.get_setting()
        if not setting:
            return None
        else:
            return setting.can_have_physician or setting.can_have_nppa or \
             setting.can_have_medical_student

    def get_org_sub_user_types_tuple(self,
                                     role_category=None,
                                     include_manager=True,
                                     include_sub_staff_type=True):
        """ Get user's types that can save for this organization.

		:param role_category: int value if role_category is 1, return provider's 
			type tuple if role_category is 2, return staff's type tuple, 
			others(include None), return all user's type tuple
		:returns: tuple
		"""
        org_setting = self.get_setting()
        if org_setting is None:
            return ()
        provider_types = ()
        staff_types = ()
        if org_setting.can_have_physician:
            provider_types += ((USER_TYPE_DOCTOR, _('Doctor')), )
        if org_setting.can_have_nppa:
            provider_types += ((USER_TYPE_NPPA, _('NP/PA/Midwife')), )
        if org_setting.can_have_medical_student:
            provider_types += ((USER_TYPE_MEDICAL_STUDENT,
                                _('Med/Dental Student')), )

        if include_manager and org_setting.can_have_manager:
            staff_types += ((USER_TYPE_OFFICE_MANAGER, _('Office Manager')), )

        if include_sub_staff_type:
            if org_setting.can_have_staff:
                staff_types += ((USER_TYPE_OFFICE_STAFF, _('Staff')), )
            if org_setting.can_have_nurse:
                staff_types += ((USER_TYPE_NURSE, _('Nurse')), )
            if org_setting.can_have_dietician:
                staff_types += ((USER_TYPE_DIETICIAN, _('Dietician')), )
        else:
            if org_setting.can_have_staff or org_setting.can_have_nurse or\
             org_setting.can_have_dietician:
                staff_types += ((USER_TYPE_OFFICE_STAFF, _('Staff')), )

        user_types = provider_types + staff_types
        if org_setting.can_have_tech_admin:
            user_types += ((USER_TYPE_TECH_ADMIN, _('Tech Admin')), )

        if role_category is None:
            return user_types
        if role_category == 1:
            return provider_types
        if role_category == 2:
            return staff_types
        return user_types

    def get_org_sub_user_types(self, format=0, role_category=None):
        """ Get user's types that can save for this organization.

		:param format: format is 0 or 1, 
			if format is 0, function will return list with user type flag
			if format is 1, function will return list with user type string
		:returns: list(id or type string)
		"""
        user_types = self.get_org_sub_user_types_tuple(
            role_category=role_category)
        return [t[format] for t in user_types]

    def get_parent_org(self):
        org_rss = OrganizationRelationship.objects.filter(organization=self)
        if org_rss and org_rss[0] and org_rss[0].parent and \
         org_rss[0].parent.id != RESERVED_ORGANIZATION_ID_SYSTEM:
            return org_rss[0].parent
        return None
Esempio n. 11
0
class MHLUser(User):
	uuid = UUIDField(auto=True, primary_key=False)
	gender = models.CharField(max_length=1, choices=GENDER_CHOICES, 
					verbose_name=_("Gender"), default='M')
	title=models.CharField(max_length=30,blank=True,null=True)
	mobile_phone = MHLPhoneNumberField(blank=True, verbose_name=_("Mobile Phone"), 
					validators=[validate_phone])
	phone = MHLPhoneNumberField(blank=True, verbose_name=_("Other Phone"), 
					help_text=PHONE_NUMBER_HELP_TEXT, validators=[validate_phone])

	address1 = models.CharField(max_length=200, blank=True, verbose_name=_("Address1"))
	address2 = models.CharField(max_length=200, blank=True, verbose_name=_("Address2"))
	city = models.CharField(max_length=200, blank=True, verbose_name=_("City"))
	state = models.CharField(max_length=2, choices=STATE_CHOICES, blank=True, verbose_name=_("State"))
	zip = models.CharField(max_length=10, blank=True, verbose_name=_("Zip"))  # 10 for zip and zip+4
	lat = models.FloatField(blank=True, null=True)
	longit = models.FloatField(blank=True, null=True)

	photo = models.ImageField(upload_to="images/userBioPics/%Y/%m/%d", blank=True, 
					verbose_name=_("Photo"), help_text=_("Recommended size 100*130"))

	email_confirmed = models.BooleanField(default=False)
	mobile_confirmed = models.BooleanField(default=False)
	tos_accepted = models.BooleanField(default=False, 
					help_text=_("Has the user accepted the terms of service?"))
	billing_account_accepted = models.BooleanField(default=False, 
					help_text=_("Has the user created a billing account?"))

	force_pass_change = models.BooleanField(default=False)
	password_change_time = models.DateTimeField(auto_now_add=True)

	#add by xlin 20120924 to add user skill
	skill = models.CharField(max_length=200, null=True, 
		blank=True, verbose_name=_("Special Skill"))
	public_notes = models.TextField(blank=True, 
		help_text="Special notes, contact preferences, etc..")
	#add by xlin 121017 for todo1045 that add setting time field False is 24h;True is 12h
	time_setting = models.IntegerField(choices=SETTING_TIME_CHOICES, 
		default=0, verbose_name=_('Time Setting'))

	refer_to_manager = models.BooleanField(default=True,
		verbose_name=_('CC refer to manager'))

	refer_forward = models.IntegerField(choices=REFER_FORWARD_CHOICES, 
		default=REFER_FORWARD_CHOICES_BOTH, verbose_name=_('Refer Forward Setting'))

	#time zone where practice is located, matches values in pytz
	time_zone = models.CharField(max_length=64, blank=True, null=True,
					choices=TIME_ZONES_CHOICES, verbose_name=_('Time Zone'))

	def __unicode__(self):
		return "%s %s" % (self.first_name, self.last_name)

	def clean(self):
		if (self.pk):
			# This user already exists
			if (self.mobile_phone and MHLUser.objects.filter(
						mobile_phone=self.mobile_phone).exclude(pk=self.pk).exists()):
				raise ValidationError(VALIDATION_ERROR_MOBILE_EXISTS)
		else:
			# This user doesn't exist yet. This would be for new accounts.
			if (self.mobile_phone and MHLUser.objects.filter(mobile_phone=self.mobile_phone).exists()):
				raise ValidationError(VALIDATION_ERROR_MOBILE_EXISTS)

		if (self.email):
			query_set = MHLUser.objects.filter(email=self.email)
			if (self.pk):
				query_set = query_set.exclude(pk=self.pk)
			if (query_set.exists()):
				raise ValidationError(VALIDATION_ERROR_EMAIL_EXISTS)

	def save(self, *args, **kwargs):
		# Check to ensure that no other user exists with the same mobile phone
		# number.

		if (self.mobile_phone and MHLUser.objects.filter(
						mobile_phone=self.mobile_phone).exclude(pk=self.pk).exists()):
			raise Exception(VALIDATION_ERROR_MOBILE_EXISTS)
		if (self.email):
			query_set = MHLUser.objects.filter(email=self.email)
			if (self.pk):
				query_set = query_set.exclude(pk=self.pk)
			if (query_set.exists()):
				raise ValidationError(VALIDATION_ERROR_EMAIL_EXISTS)
		super(MHLUser, self).save(*args, **kwargs)

	def set_password(self, newpass):
		super(MHLUser, self).set_password(newpass)
		self.password_change_time = datetime.now()

	def change_smartphone_perm(self, is_enable=True):
		perm, is_created = Permission.objects.get_or_create(codename='access_smartphone',
				name='Can use smartphone app', 
				content_type=ContentType.objects.get_for_model(MHLUser))
		if is_enable and not self.has_perm('MHLUsers.access_smartphone'):
			self.user_permissions.add(perm)
			self.save()

		if not is_enable and self.has_perm('MHLUsers.access_smartphone'):
			self.user_permissions.remove(perm)
			self.save()

	class Meta:
		ordering = ['last_name', 'first_name']
		permissions = (
			("access_smartphone", "Can use smartphone app"),
			("can_call_transfer", "Can transfer incoming calls"),
		)
Esempio n. 12
0
class Broker(models.Model):
	"""
		Broker objects which allow us to declare MHLUsers to be broker, and
		to allow us to collect additional data on these users.

		DEPRECATION WARNING:
		Please read the deprecation warning in the code before using this object.
	"""
	user = models.ForeignKey(MHLUser, null=True, blank=True, related_name='user_broker')

	office_address1 = models.CharField(max_length=200, blank=True)
	office_address2 = models.CharField(max_length=200, blank=True)
	office_phone = MHLPhoneNumberField(verbose_name=_("Office Phone"), blank=True, 
					help_text=PHONE_NUMBER_HELP_TEXT, validators=[validate_phone])
	office_city = models.CharField(max_length=200, blank=True)
	office_state = models.CharField(max_length=2, choices=STATE_CHOICES, blank=True)

	office_zip = models.CharField(max_length=10, blank=True)  # 10 for zip and zip+4
	office_lat = models.FloatField(blank=True)
	office_longit = models.FloatField(blank=True)

	# Django IntegerField too small for US phone number with area code.
	pager = MHLPhoneNumberField(blank=True, help_text=PHONE_NUMBER_HELP_TEXT)
	pager_extension = models.CharField(max_length=100, blank=True)
	pager_confirmed = models.BooleanField(default=False)

	# DoctorCom Provisioned Phone Number and confirmation flag
	mdcom_phone = MHLPhoneNumberField(blank=True)
	mdcom_phone_sid = models.CharField(max_length=34, blank=True)

	forward_mobile = models.BooleanField(default=True)
	forward_office = models.BooleanField(default=False)
	forward_other = models.BooleanField(default=False)
	forward_vmail = models.BooleanField(default=False)

	forward_voicemail = models.CharField(max_length=2, choices=FORWARD_CHOICES, default='MO')
	forward_anssvc = models.CharField(max_length=2, choices=FORWARD_CHOICES, default='VM')
	# Voicemail
	vm_config = generic.GenericRelation(VMBox_Config,
					content_type_field='owner_type', object_id_field='owner_id')
	vm_msgs = generic.GenericRelation(VMMessage,
					content_type_field='owner_type', object_id_field='owner_id')

	licensure_states = models.ManyToManyField(States, null=True, 
					blank=True, verbose_name=_("States of Licensure"))

	#Flag to set provider as a medical student
	clinical_clerk = models.BooleanField(default=False)

	status_verified = models.BooleanField(default=False)
	status_verifier = models.ForeignKey(MHLUser, null=True, blank=True, 
					related_name='verifier_broker')

	objects = models.Manager()
	active_objects = ActiveManagedUser()

	def __unicode__(self):
		return self.user.username

	def clean(self):
		pass

	class Meta:
		ordering = ['user']
Esempio n. 13
0
class Provider(MHLUser):  # TODO_KCV new provider this will inherit from models.Model
	"""
		Provider objects which allow us to declare MHLUsers to be providers, and
		to allow us to collect additional data on these users.

		Changing model to not inherit from MHLUser and just use foreign key into MHLUser
		grep for TODO_PROVINH tags in code for places where we assume inheritance
	"""
	# Be aware that if you're creating a Provider, you need to manually populate
	# this field with the correct User object!
	user = models.ForeignKey(MHLUser, null=True, blank=True, related_name='user_provider')

	office_address1 = models.CharField(max_length=200, blank=True, verbose_name=_("Office address1"))
	office_address2 = models.CharField(max_length=200, blank=True, verbose_name=_("Office address2"))
	office_phone = MHLPhoneNumberField(verbose_name=_("Office Phone"), blank=True, 
					help_text=PHONE_NUMBER_HELP_TEXT, validators=[validate_phone])

	office_city = models.CharField(max_length=200, blank=True, verbose_name=_("Office city"))
	office_state = models.CharField(max_length=2, choices=STATE_CHOICES, blank=True, 
					verbose_name=_("Office state"))
	office_zip = models.CharField(max_length=10, blank=True, 
					verbose_name=_("Office zip"))  # 10 for zip and zip+4
	office_lat = models.FloatField(blank=True)
	office_longit = models.FloatField(blank=True)
	# Django IntegerField too small for US phone number with area code.
	pager = MHLPhoneNumberField(blank=True, verbose_name=_("Pager"), help_text=PHONE_NUMBER_HELP_TEXT)
	pager_extension = models.CharField(max_length=100, blank=True, verbose_name=_("Pager extension"))
	pager_confirmed = models.BooleanField(default=False)

	#DoctorCom Provisioned Phone Number and confirmation flag
	mdcom_phone = MHLPhoneNumberField(blank=True)
	mdcom_phone_sid = models.CharField(max_length=34, blank=True)

	forward_mobile = models.BooleanField(default=True)
	forward_office = models.BooleanField(default=False)
	forward_other = models.BooleanField(default=False)
	forward_vmail = models.BooleanField(default=False)

	forward_voicemail = models.CharField(max_length=2, choices=FORWARD_CHOICES, default='MO')
	forward_anssvc = models.CharField(max_length=2, choices=FORWARD_CHOICES, default='VM')
	# Voicemail
	vm_config = generic.GenericRelation(VMBox_Config,
					content_type_field='owner_type', object_id_field='owner_id')
	vm_msgs = generic.GenericRelation(VMMessage,
					content_type_field='owner_type', object_id_field='owner_id')

	sites = models.ManyToManyField(Site, null=True, blank=True, 
					related_name='site_provider')
	current_site = models.ForeignKey(Site, null=True, blank=True, 
					related_name='site_provider_current')

	practices = models.ManyToManyField(PracticeLocation, null=True, blank=True, 
					related_name='practice_provider')
	current_practice = models.ForeignKey(PracticeLocation, null=True, blank=True, 
					related_name='practice_provider_current')

	licensure_states = models.ManyToManyField(States, null=True, blank=True, 
					verbose_name=_("States of Licensure"))

	#Flag to set provider as a medical student
	clinical_clerk = models.BooleanField(default=False)

	status_verified = models.BooleanField(default=False)
	status_verifier = models.ForeignKey(MHLUser, null=True, blank=True, 
					related_name='verifier_provider')

	certification = models.TextField(null=True, blank=True,
					verbose_name=_("certification"))

	objects = models.Manager()
	active_objects = ActiveManagedUser()

	#add by xlin 120914
	search_objects = SearchProviders()

	def __unicode__(self):
		return "%s %s" % (self.first_name, self.last_name)

	def __getattribute__(self, name):
		if settings.DEBUG_PROVIDER == True and name in MHLUSER_FIELDS:
			# array of sets (file, line#, function, expr)
			tracebuf = traceback.extract_stack()
			buf = ""
			for t in tracebuf:
				buf = buf + "File: ..." + t[0][-30:] + " line: " + str(t[1]) + \
					" func: " + t[2] + " expr: " + t[3] + "\n"
			logger.warn("Provider will soon no longer inherit from MHLUser,"\
					"use foreign key 'user' to get to field '%s', stacktrace:"\
					"\n%s\n" % (name, buf)) 
		return super(Provider, self).__getattribute__(name)

	def clean(self):
		if (self.pk):
			# This user already exists
			if (self.mobile_phone and MHLUser.objects.filter(
					mobile_phone=self.mobile_phone).exclude(pk=self.pk).exists()):
				raise ValidationError(VALIDATION_ERROR_MOBILE_EXISTS)
		else:
			# This user doesn't exist yet. This would be for new accounts.
			if (self.mobile_phone and MHLUser.objects.filter(
					mobile_phone=self.mobile_phone).exists()):
				raise ValidationError(VALIDATION_ERROR_MOBILE_EXISTS)

		if (self.email):
			query_set = MHLUser.objects.filter(email=self.email)
			if (self.pk):
				query_set = query_set.exclude(pk=self.pk)
			if (query_set.exists()):
				raise ValidationError(VALIDATION_ERROR_EMAIL_EXISTS)

	def save(self, *args, **kwargs):
		# Check to ensure that no other user exists with the same mobile phone number.
		if (self.mobile_phone and MHLUser.objects.filter(
					mobile_phone=self.mobile_phone).exclude(pk=self.pk).exists()):
			raise Exception(VALIDATION_ERROR_MOBILE_EXISTS)

		if (self.email):
			query_set = MHLUser.objects.filter(email=self.email)
			if (self.pk):
				query_set = query_set.exclude(pk=self.pk)
			if (query_set.exists()):
				raise ValidationError(VALIDATION_ERROR_EMAIL_EXISTS)

		super(MHLUser, self).save(*args, **kwargs)

	class Meta:
		ordering = ['user']