def resend_confirmation(request, confirmation_key=None, username=None): """ Resend confirmation email. If confirmation_key is None, send it to logged in user.""" if confirmation_key is None: if username is not None: if is_wellness_center(request.user): provider = get_healer(request.user, username) user = provider.user else: raise Http404 else: user = request.user if not user or user.is_anonymous(): raise Http404 email_address = get_or_create_email_address(user) else: confirmation = get_object_or_404(EmailConfirmation, confirmation_key=confirmation_key) email_address = confirmation.email_address EmailConfirmation.objects.send_confirmation(email_address) if username is not None: return redirect('friends', 'providers') return render_to_response('account/signup_thanks.html', {'email': email_address.email}, context_instance=RequestContext(request))
def get_current_users_with_schedule_permission(): def get_wcenter_users_with_setting_each_provider_pays(): return set([wc.user for wc in WellnessCenter.objects.filter( payment_schedule_setting=WellnessCenter.PAYMENT_EACH_PROVIDER_PAYS)]) def add_centers_with_active_trial_and_free_access(): # trial centers = WellnessCenter.objects.exclude(schedule_trial_started_date=None) centers = [wc for wc in centers if wc.is_schedule_trial_active()] # free centers += list(WellnessCenter.objects.filter(user__username__in=settings.SCHEDULE_USERS_WITH_FREE_ACCESS)) for wc in centers: users.add(wc.user) for healer in get_healers_in_wcenter_with_schedule_editing_perm(wc): users.add(healer.user) users = set() for user in get_users_with_active_subscription('schedule'): users.add(user) wc = is_wellness_center(user) if wc: for healer in get_healers_in_wcenter_with_schedule_editing_perm(wc): users.add(healer.user) add_centers_with_active_trial_and_free_access() users |= get_wcenter_users_with_setting_each_provider_pays() return users
def unconfirmed_appointments_processor(request): try: client = request.user.client try: healer = client.healer wcenter = is_wellness_center(healer) if wcenter: appts = get_wcenter_unconfirmed_appts(wcenter) else: appts = Appointment.objects.get_active(healer).filter( confirmed=False) number_of_unconfirmed_appts = appts.count() except Healer.DoesNotExist: number_of_unconfirmed_appts = Appointment.objects.without_relations()\ .filter(client=request.user.client)\ .filter_by_date(settings.GET_NOW().date() - timedelta(days=1))\ .order_by('start_date')\ .count() except (Client.DoesNotExist, AttributeError): number_of_unconfirmed_appts = 0 return {'number_of_unconfirmed_appts': number_of_unconfirmed_appts}
def wcenter_healer_has_treatment_types_(requesting_user, healer): wellnesscenter = is_wellnesscenter = is_wellness_center(requesting_user) if is_wellnesscenter and healer.user != requesting_user: try: return healer.wellness_center_treatment_types.get( wellness_center=wellnesscenter).treatment_types.exists() except WellnessCenterTreatmentType.DoesNotExist: pass return False
def handle(self, *args, **options): def get_providers_with_no_location(): providers = healers.filter(remote_sessions=False) providers_with_no_location = [] for provider in providers: if not provider.get_locations(): providers_with_no_location.append(provider) return providers_with_no_location healers = Healer.objects.filter(is_deleted=False, user__is_active=True) providers_blank = healers.filter( Q(user__avatar__isnull=True) | Q(about='')).distinct() providers_no_modality = healers.annotate( modality_count=Count('modality')).filter(modality_count=0) # filter wellness centers because of specialities of their providers providers_no_modality = (provider for provider in providers_no_modality if not is_wellness_center(provider) or not provider.has_specialities()) providers = set( list(providers_blank) + list(providers_no_modality) + get_providers_with_no_location()) username = options['username'] for provider in providers: if username and provider.user.username != username: continue lastdate = provider.profile_completeness_reminder_lastdate interval = provider.profile_completeness_reminder_interval if username or not lastdate or lastdate + timedelta( weeks=interval) <= date.today(): site_base = unicode(Site.objects.get_current()) ctx = { 'first_name': provider.user.first_name, 'reminder_interval_link': get_full_url('healer_edit'), 'change_reminder_interval_url': get_full_url('healer_change_profile_reminder_interval'), 'change_reminder_interval_options': Healer.PROFILE_REMINDER_INTERVAL_CHOICES, 'fill_warning_links': get_fill_warning_links(provider), 'site_base': site_base } subject = render_to_string( "healers/emails/profile_reminder_subject.txt", ctx) send_hs_mail(subject, 'healers/emails/profile_reminder_message.txt', ctx, settings.DEFAULT_FROM_EMAIL, [provider.user.email]) provider.profile_completeness_reminder_lastdate = date.today() provider.save()
def get_healer(requesting_user, requested_username): healer = get_object_or_404(Healer, user=requesting_user) healer_requesting = healer if (is_wellness_center(requesting_user) and requesting_user.username != requested_username): healer = get_object_or_404(Healer, user__username=requested_username) if (healer not in get_healers_in_wcenter_with_schedule_editing_perm(healer_requesting)): raise Http404 return healer
def get_providers(healer, order_by_id=False): wcenter = is_wellness_center(healer) if wcenter: providers = get_healers_in_wcenter_with_schedule_editing_perm(healer, order_by_id) if wcenter.payment_schedule_setting == WellnessCenter.PAYMENT_EACH_PROVIDER_PAYS: return [provider for provider in providers if provider.user.has_perm(Healer.SCHEDULE_PERMISSION)] else: return providers else: return [healer]
def email(request, username=None, **kwargs): if username and is_wellness_center(request.user): provider = get_healer(request.user, username) user = provider.user else: user = request.user form_class = kwargs.pop("form_class", AddEmailForm) template_name = kwargs.pop("template_name", "account/email.html") if request.method == "POST" and request.user.is_authenticated(): if request.POST["action"] == "add": add_email_form = form_class(user, request.POST) if add_email_form.is_valid(): add_email_form.save() add_email_form = form_class() # @@@ else: add_email_form = form_class() if request.POST["action"] == "send": email = request.POST["email"] try: email_address = EmailAddress.objects.get( user=user, email__iexact=email, ) EmailConfirmation.objects.send_confirmation(email_address) except EmailAddress.DoesNotExist: pass elif request.POST["action"] == "remove": email = request.POST["email"] try: email_address = EmailAddress.objects.get( user=user, email__iexact=email) email_address.delete() except EmailAddress.DoesNotExist: pass elif request.POST["action"] == "primary": email = request.POST["email"] email_address = EmailAddress.objects.get( user=user, email__iexact=email, ) email_address.set_as_primary() else: add_email_form = form_class() ctx = { "add_email_form": add_email_form, "edit_user": user, "username": username } return render_to_response(template_name, RequestContext(request, ctx))
def __init__(self, *args, **kwargs): self.healer = kwargs.pop('healer', False) account_setup = kwargs.pop('account_setup', False) if self.healer: self.schedule_is_visible = self.healer.scheduleVisibility != Healer.VISIBLE_DISABLED self.is_wellness_center = is_wellness_center(self.healer) super(LocationForm, self).__init__(*args, **kwargs) choices = self.fields['color'].widget.choices if self.is_wellness_center: choices = reversed(choices) self.fields['color'].widget = ColorSelect() self.fields['color'].widget.choices = choices self.fields['title'].widget = forms.TextInput(attrs={'required': ''}) if (not account_setup and self.schedule_is_visible and not self.is_wellness_center): self.fields['color'].required = True if not self.instance.pk: self.fields['color'].initial = self.get_next_color() else: del self.fields['color']
def disable_google_sync(healer): healer.google_calendar_id = '' healer.google_email = '' healer.save() Storage(Credentials, 'id', healer.user, 'google_credential').delete() UnavailableCalendar.objects.filter(healer=healer, api=GOOGLE_API).delete() UnavailableCalendar.objects.filter(healer=healer, api=GOOGLE_API).delete() UnavailableSlot.objects.filter(healer=healer, api=GOOGLE_API).delete() Appointment.objects.filter(healer=healer).update(google_event_id='') wcenter = is_wellness_center(healer) if wcenter: WellnessCenterGoogleEventId.objects.filter( wellness_center=wcenter).delete() task_filter_data = { CalendarSyncQueueTask.get_object_name(wcenter): healer, 'api': GOOGLE_API } CalendarSyncQueueTask.objects.filter(**task_filter_data).delete()
def is_healer_processor(request): healer = False beta_tester = True func = getattr(request.user, "client", None) if func: healer = is_healer(request.user) # beta_tester = request.user.client.beta_tester return { 'is_healer': healer, 'is_beta_tester': beta_tester, 'is_wellness_center': is_wellness_center(healer), 'healers_in_wcenter_with_schedule_perm': get_healers_in_wcenter_with_schedule_editing_perm(healer), 'is_stripe_connect_beta_tester': True, #request.user.username in settings.STRIPE_CONNECT_BETA_USERS 'is_gift_certificates_beta_tester': True # request.user.username in settings.GIFT_CERTIFICATES_BETA_USERS }
def handle(self, healer=None, *args, **options): def error_report(type, e): report = 'Google Calendar Error #{} {} {}'.format( type, str(e), traceback.format_exc()) ErrorReport.objects.create(report=report) if type in [2, 3, 5]: # any exceptions excluding google / auth errors mail_admins('Google Sync Error', report) return report def get_google_calendar(healer): try: google_calendar = GoogleCalendar(healer.user) healer.google_calendar_sync_retries = 0 except oauth2client.client.Error: healer.google_calendar_sync_retries += 1 google_calendar = None # exc_type = sys.exc_info()[0] # error_report(1, "Cal Sync Error %s - %s - %s" % (exc_type, str(e), healer.user)) if healer.google_calendar_sync_retries >= settings.MAX_GCAL_SYNC_RETRIES: disable_google_sync(healer) send_hs_mail( 'Google Calendar Sync Disabled', 'sync_hs/email_calendar_disabled.txt', { 'MAX_GCAL_SYNC_RETRIES': settings.MAX_GCAL_SYNC_RETRIES, 'google_calendar_sync_link': get_full_url('google_calendar_instruction') }, settings.DEFAULT_FROM_EMAIL, [healer.user.email], bcc=[admin[1] for admin in settings.ADMINS]) healer.google_calendar_sync_retries = 0 healer.save() return google_calendar def sync_cal(wcenter_sync=False): def get_objects(): """Return healers or centers who have sync tasks.""" def get_ids(): ids = CalendarSyncQueueTask.objects.values_list( object_name, flat=True).filter(api=GOOGLE_API) if wcenter_sync: ids = ids.exclude(wellness_center=None) else: ids = ids.filter(wellness_center=None) return ids.distinct() if wcenter_sync: model = WellnessCenter else: model = Healer objects = model.objects.filter(id__in=get_ids()) if healer is not None: objects = objects.filter(user=healer.user) return objects def task_error(task, type, e): report = error_report(type, e) task.status = STATUS_FAIL task.save() if task.attempts > CalendarSyncQueueTask.MAX_ATTEMPTS: report = 'username - %s, email - %s, %s' % ( object.user, object.user.email, report) mail_admins('CalendarSyncQueueTask Max Errors', report) object_name = CalendarSyncQueueTask.get_object_name(wcenter_sync) objects = get_objects() for object in objects: if CalendarSyncStatus.objects.is_running( object.user, GOOGLE_API): continue try: CalendarSyncStatus.objects.start(object.user, GOOGLE_API) google_calendar = get_google_calendar(object) if google_calendar is None: CalendarSyncStatus.objects.stop( object.user, GOOGLE_API) continue filter_data = {object_name: object} status_filter = Q(status=STATUS_WAITING) | ( Q(status=STATUS_FAIL) & Q(attempts__lte=CalendarSyncQueueTask.MAX_ATTEMPTS)) tasks = CalendarSyncQueueTask.objects.filter( api=GOOGLE_API, **filter_data).filter(status_filter) if wcenter_sync: wcenter = object else: wcenter = False tasks = tasks.filter(wellness_center=None) for task in tasks: task.status = STATUS_RUNNING task.attempts += 1 task.save() try: with Timeout(20): event_id = None if task.action == ACTION_NEW: event_id = google_calendar.create_event( object.google_calendar_id, task.appointment, wcenter_sync) self.stdout.write('Event new, %s' % task.appointment) if task.action == ACTION_UPDATE: event_id = google_calendar.update_event( object.google_calendar_id, task.appointment, wcenter) self.stdout.write('Event update, %s' % task.appointment) if task.action == ACTION_DELETE: if wcenter_sync: wcenter_event = task.appointment.wellness_center_google_event_ids.get( wellness_center=wcenter) google_calendar.delete_event( object.google_calendar_id, wcenter_event.google_event_id) wcenter_event.delete() else: google_calendar.delete_event( object.google_calendar_id, task.appointment.google_event_id) self.stdout.write('Event delete, %s' % task.appointment) if wcenter_sync: if event_id is not None: wcenter_event = WellnessCenterGoogleEventId.objects.get_or_create( wellness_center=wcenter, appointment=task.appointment)[0] wcenter_event.google_event_id = event_id wcenter_event.save() else: if event_id is not None: task.appointment.google_event_id = event_id else: task.appointment.google_event_id = '' task.appointment.save(google_sync=False) except apiclient.errors.Error as e: # save error to find out the reason for error task_error(task, 4, e) continue # left from gdata cal # if e.status == 403 and e.body == 'Cannot delete a cancelled event': # pass except TimeoutError: task.status = STATUS_FAIL task.save() except Exception as e: task_error(task, 2, e) continue task.delete() except Exception as e: error_report(3, e) finally: CalendarSyncStatus.objects.stop(object.user, GOOGLE_API) def sync_unavailable_cals(): def remove_deleted_calendars(): calendars = google_calendar.get_list() google_calendars_ids = [c['id'] for c in calendars] hs_calendars_ids = UnavailableCalendar.objects.values_list( 'calendar_id', flat=True).filter(healer=h, api=GOOGLE_API) for cal_id in hs_calendars_ids: if cal_id not in google_calendars_ids: UnavailableCalendar.objects.get( healer=h, api=GOOGLE_API, calendar_id=cal_id).delete() healers_ids = UnavailableCalendar.objects.all().values_list( 'healer__pk', flat=True).distinct() healers = Healer.objects.filter(pk__in=healers_ids) if healer is not None: healers = healers.filter(pk=healer.pk) for h in healers: google_calendar = get_google_calendar(h) if google_calendar is None: continue remove_deleted_calendars() try: added_slots = sync_unavailable_slots(h, google_calendar) # for slot in added_slots: # self.stdout.write('Unavailable slot added - %s' % slot) except Exception as e: error_report(5, e) if healer is None: sync_cal(wcenter_sync=True) sync_cal() sync_unavailable_cals() else: if is_wellness_center(healer): sync_cal(wcenter_sync=True) else: sync_cal() sync_unavailable_cals()
def post(self, request, format=None): def set_payment_schedule_to_0_for_healers_in_center(): wcenter_healers = healers.utils.get_healers_in_wcenter_with_schedule_editing_perm( wc) for h in wcenter_healers: customer = get_user_customer(h.user) customer.payment_schedule = 0 customer.save() try: customer.cancel('schedule') except stripe.error.StripeError as e: mail_admins( 'Error deleting schedule subscription', 'Error deleting schedule subscription for %s - %s' % (customer, str(e))) pass current_subscription = get_current_subscription(customer) current_subscription.schedule_status = False current_subscription.save() self.get_initial_data() SCHEDULE_PERMISSION_OBJECT = Permission.objects.get( codename='can_use_wcenter_schedule') payment_schedule = int(request.POST['payment_schedule']) is_custom_schedule_plan = request.user.is_superuser and 'user_id' in request.POST if is_custom_schedule_plan: payment_schedule_setting = WellnessCenter.PAYMENT_CENTER_PAYS user = User.objects.get(pk=request.POST['user_id']) customer = user.customer wc = WellnessCenter.objects.get(user=user) else: payment_schedule_setting = int( request.POST['payment_schedule_setting']) payment_notes = int(request.POST['payment_notes']) user = request.user customer = get_user_customer(user) # initialize customer wc = is_wellness_center(self.healer) if payment_schedule_setting in [ WellnessCenter.PAYMENT_SCHEDULE_DISABLED, WellnessCenter.PAYMENT_EACH_PROVIDER_PAYS ]: payment_schedule = 0 if payment_schedule_setting == WellnessCenter.PAYMENT_EACH_PROVIDER_PAYS: user.user_permissions.add(SCHEDULE_PERMISSION_OBJECT) errors = [] error = process_subscription(user, 'schedule', payment_schedule, wc, is_custom_schedule_plan) if error is None: customer.payment_schedule = payment_schedule customer.is_custom_schedule_plan = is_custom_schedule_plan customer.save() if wc: wc = WellnessCenter.objects.get( user=wc.user) # Refresh WellnessCenter record wc.payment_schedule_setting = payment_schedule_setting wc.save() if payment_schedule_setting in [ WellnessCenter.PAYMENT_SCHEDULE_DISABLED, WellnessCenter.PAYMENT_CENTER_PAYS ]: set_payment_schedule_to_0_for_healers_in_center() else: errors.append(error) if not is_custom_schedule_plan: error = process_subscription(user, 'notes', payment_notes, wc) if error is None: if customer.payment_notes != payment_notes: customer.payment_notes = payment_notes customer.save() else: errors.append(error) if errors: error = '<br>'.join(errors) return Response(error)
def sync_unavailable_slots(healer, google_calendar): """Get events from other calendars. Ignore requests from center.""" def clear_slots_before_now(): UnavailableSlot.objects.filter( healer=healer, api=GOOGLE_API).exclude_by_datetime(now).delete() def save_slot(calendar, title, event_id, start, end): slot = UnavailableSlot() slot.healer = healer slot.api = GOOGLE_API slot.calendar = calendar if title: slot.title = title slot.event_id = event_id slot.set_dates(start, end, True) if slot.end_date is None: slot.end_date = slot.start_date slot.save() return slot def get_datetime(event_date): date = event_date.get('dateTime', False) if not date: date = event_date['date'] return parse(date, ignoretz=True) def delete_removed_slots(calendar, event_ids): current_unavailable_slots_events_ids = UnavailableSlot.objects.filter( calendar=calendar, healer=healer, api=GOOGLE_API).values_list('event_id', flat=True) slots_event_ids_to_remove = set( current_unavailable_slots_events_ids) - set(event_ids) UnavailableSlot.objects.filter( calendar=calendar, healer=healer, api=GOOGLE_API, event_id__in=slots_event_ids_to_remove).delete() # ignore center request if is_wellness_center(healer): return added_slots = [] now = healer.get_local_time() clear_slots_before_now() for calendar in UnavailableCalendar.objects.filter(healer=healer, api=GOOGLE_API): # print calendar try: events = google_calendar.get_events(calendar.calendar_id, calendar.update_date, healer.bookAheadDays * 2) except apiclient.errors.HttpError as err: if err.resp.status == 503: events = [] else: raise # print events delete_removed_slots(calendar, [event['id'] for event in events]) event_exclude_list = {} for event in events: event_id = event['id'] if 'recurringEventId' in event: original_event_id = event['recurringEventId'] start = get_datetime(event['originalStartTime']) UnavailableSlot.objects.filter( event_id=original_event_id, start_date=start.date()).delete() if original_event_id not in event_exclude_list: event_exclude_list[original_event_id] = [] event_exclude_list[original_event_id].append(start.date()) UnavailableSlot.objects.filter(event_id=event_id).delete() if event['status'] == 'confirmed': start = get_datetime(event['start']) end = get_datetime(event['end']) if end > now and start.date() not in event_exclude_list.get( event_id, []): slot = save_slot(calendar, event.get('summary', False), event_id, start, end) added_slots.append(slot) calendar.update_date = now calendar.save() return added_slots
def reset_calendar(healer, google_calendar, soft_reset): """Delete and create new calendar, sync appointments using batch request.""" def create_google_calendar(healer, google_calendar): def remove_existing_calendars(): """Remove previous versions of calendar.""" try: calendars_list = google_calendar.get_list() for calendar in calendars_list: if calendar[ 'summary'] == Healer.GOOGLE_CALENDAR_TITLE and calendar[ 'id'] != calendar_id: google_calendar.delete_calendar(calendar['id']) except apiclient.errors.Error: # Can't get list pass """ Create new google calendar using GoogleCalendar wrapper """ calendar_id = google_calendar.create( title=Healer.GOOGLE_CALENDAR_TITLE, description='This calendar contains healersource appointments', color='#528800', timezone=Timezone.TIMEZONE_CODES[healer.timezone]) email = google_calendar.get_email() healer.google_email = email healer.google_calendar_id = calendar_id healer.save() remove_existing_calendars() return calendar_id if soft_reset: calendar_id = healer.google_calendar_id errors = google_calendar.clear(calendar_id) if errors > 0: return errors else: calendar_id = create_google_calendar(healer, google_calendar) wcenter = is_wellness_center(healer) if wcenter: healers = wcenter.get_healers_in_wcenter() WellnessCenterGoogleEventId.objects.filter( wellness_center=wcenter).delete() else: healers = [healer] errors = 0 appts_dict = {} for healer in healers: appts = Appointment.objects.filter(healer=healer, confirmed=True) if wcenter: appts = appts.filter(location__in=wcenter.get_location_ids()) if not appts.exists(): continue for appointment in appts: google_calendar.add_appointment_to_batch(calendar_id, appointment, wcenter) appts_dict[appointment.id] = appointment if appts_dict: errors = google_calendar.execute_appointments_batch( appts_dict, wcenter) return errors
def create(cls, request, healer): center = is_wellness_center(healer) if request.method == 'POST': form = ScheduleSettingsForm(request.POST) if form.is_valid(): healer.leadTime = form.cleaned_data['leadTime'] healer.manualAppointmentConfirmation = form.cleaned_data[ 'manualAppointmentConfirmation'] healer.intakeFormBooking = form.cleaned_data[ 'intakeFormBooking'] healer.booking_optional_message_allowed = form.cleaned_data[ 'booking_optional_message_allowed'] # healer.scheduleVisibility = int(form.cleaned_data['scheduleVisibility']) healer.setup_time = form.cleaned_data['setup_time'] healer.bookAheadDays = form.cleaned_data['bookAheadDays'] healer.office_hours_start = form.cleaned_data[ 'office_hours_start'] healer.office_hours_end = form.cleaned_data['office_hours_end'] healer.cancellation_policy = form.cleaned_data[ 'cancellation_policy'] healer.additional_text_for_email = form.cleaned_data[ 'additional_text_for_email'] healer.send_sms_appt_request = form.cleaned_data[ 'send_sms_appt_request'] save_phone_number(healer, form.cleaned_data['phone']) if str(healer.office_hours_end) == '00:00:00': healer.office_hours_end = time(23, 59) if center: common_availability = form.cleaned_data[ 'common_availability'] == 'True' if center.common_availability != common_availability: reset_center_and_providers_availabilities(center) center.common_availability = common_availability center.save() healer.save() else: initial_data = { "bookAheadDays": healer.bookAheadDays, "leadTime": healer.leadTime, "manualAppointmentConfirmation": healer.manualAppointmentConfirmation, "intakeFormBooking": healer.intakeFormBooking, "booking_optional_message_allowed": healer.booking_optional_message_allowed, # "scheduleVisibility": healer.scheduleVisibility, "setup_time": healer.setup_time, "office_hours_start": healer.office_hours_start, "office_hours_end": healer.office_hours_end, "cancellation_policy": healer.cancellation_policy, "additional_text_for_email": healer.additional_text_for_email, "send_sms_appt_request": healer.send_sms_appt_request, 'phone': healer.first_phone() } if center: initial_data[ 'common_availability'] = center.common_availability form = ScheduleSettingsForm(initial=initial_data) return form
def get_steps(cls, healer): if is_wellness_center(healer): return cls.wellness_center_steps else: return cls.provider_steps