def refresh(request): """ Returns a json response containing a new retailer_pin for the store. """ if request.session.get('account') and\ request.session.get(SESSION_KEY): data = {'success': False} settings = SESSION.get_settings(request.session) if settings == None: raise Http404 else: settings.set('retailer_pin', Settings.generate_id()) settings.update() # update the session cache request.session['settings'] = settings # notify other dashboards of these changes store = SESSION.get_store(request.session) payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSettings": settings.jsonify() } comet_receive(store.objectId, payload) data['success'] = True data['retailer_pin'] = settings.retailer_pin return HttpResponse(json.dumps(data), content_type="application/json") else: return HttpResponse(json.dumps({'success': False}), content_type="application/json")
def refresh(request): """ Returns a json response containing a new retailer_pin for the store. """ if request.session.get('account') and\ request.session.get(SESSION_KEY): data = {'success': False} settings = SESSION.get_settings(request.session) if settings == None: raise Http404 else: settings.set('retailer_pin', Settings.generate_id()) settings.update() # update the session cache request.session['settings'] = settings # notify other dashboards of these changes store = SESSION.get_store(request.session) payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSettings":settings.jsonify() } comet_receive(store.objectId, payload) data['success'] = True data['retailer_pin'] = settings.retailer_pin return HttpResponse(json.dumps(data), content_type="application/json") else: return HttpResponse(json.dumps({'success': False}), content_type="application/json")
def delete(request, employee_id): """ This will also remove the employee from the ACL, delete the employee object and also delete the Parse.User object if and only if it has no pointer to a Store or a Patron. """ # get from the employees_approved_list in session cache employees_approved_list = SESSION.get_employees_approved_list(\ request.session) i_remove, employee = 0, None for ind, m in enumerate(employees_approved_list): if m.objectId == employee_id: employee = m i_remove = ind break if not employee: return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Employee has already been removed.'})) employees_approved_list.pop(i_remove) request.session['employees_approved_list'] =\ employees_approved_list acc = Account.objects().get(Employee=employee.objectId) if not acc: # employee may have been deleted return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Employee has already been deleted.'})) # Always save session first whenever calling a cloud code request.session.save() res = cloud_call("delete_employee", {"employee_id": employee.objectId}) request.session.clear() request.session.update(SessionStore(request.session.session_key)) if 'error' not in res: store = SESSION.get_store(request.session) payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY } if acc.objectId in store.ACL and not store.is_owner(acc): del store.ACL[acc.objectId] store.update() payload["updatedStore"] = store.jsonify() request.session['store'] = store # only need to pass in the objectId deleted_employee = Employee(objectId=employee.objectId) payload["deletedEmployee"] = deleted_employee.jsonify() comet_receive(store.objectId, payload) return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Employee has been deleted.'})) return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Employee has already been deleted.'}))
def delete(request, employee_id): """ This will also remove the employee from the ACL, delete the employee object and also delete the Parse.User object if and only if it has no pointer to a Store or a Patron. """ # get from the employees_approved_list in session cache employees_approved_list = SESSION.get_employees_approved_list(\ request.session) i_remove, employee = 0, None for ind, m in enumerate(employees_approved_list): if m.objectId == employee_id: employee = m i_remove = ind break if not employee: return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Employee has already been removed.'})) employees_approved_list.pop(i_remove) request.session['employees_approved_list'] =\ employees_approved_list acc = Account.objects().get(Employee=employee.objectId) if not acc: # employee may have been deleted return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Employee has already been deleted.'})) # Always save session first whenever calling a cloud code request.session.save() res = cloud_call("delete_employee", {"employee_id": employee.objectId}) request.session.clear() request.session.update(SessionStore(request.session.session_key)) if 'error' not in res: store = SESSION.get_store(request.session) payload = {COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY} if acc.objectId in store.ACL and not store.is_owner(acc): del store.ACL[acc.objectId] store.update() payload["updatedStore"] = store.jsonify() request.session['store'] = store # only need to pass in the objectId deleted_employee = Employee(objectId=employee.objectId) payload["deletedEmployee"] = deleted_employee.jsonify() comet_receive(store.objectId, payload) return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Employee has been deleted.'})) return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Employee has already been deleted.'}))
def deny(request, employee_id): """ same as delete except this uses the pending list """ # get from the employees_pending_list in session cache employees_pending_list = SESSION.get_employees_pending_list(\ request.session) i_remove, employee = 0, None for ind, m in enumerate(employees_pending_list): if m.objectId == employee_id: employee = m i_remove = ind break if not employee: return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Pending employee not found.'})) # update session cache for employees_pending_list employees_pending_list.pop(i_remove) request.session['employees_pending_list'] =\ employees_pending_list acc = Account.objects().get(Employee=employee.objectId) if not acc: # employee may have been deleted return redirect(reverse('employees_index')+ "?show_pending&%s" %\ urllib.urlencode({'success': 'Employee has already been denied.'})) # Always save session first whenever calling a cloud code request.session.save() res = cloud_call("delete_employee", {"employee_id": employee.objectId}) request.session.clear() request.session.update(SessionStore(request.session.session_key)) if 'error' not in res: payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY } store = SESSION.get_store(request.session) # no need to check acl here but just in case if acc.objectId in store.ACL and not store.is_owner(acc): del store.ACL[acc.objectId] store.update() payload["updatedStore"] = store.jsonify() request.session['store'] = store # only need to pass in the objectId deleted_employee = Employee(objectId=employee.objectId) payload["deletedEmployee"] = deleted_employee.jsonify() comet_receive(store.objectId, payload) return redirect(reverse('employees_index')+ "?show_pending&%s" %\ urllib.urlencode({'success': 'Employee has been denied.'})) return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Employee has already been deleted.'}))
def deny(request, employee_id): """ same as delete except this uses the pending list """ # get from the employees_pending_list in session cache employees_pending_list = SESSION.get_employees_pending_list(\ request.session) i_remove, employee = 0, None for ind, m in enumerate(employees_pending_list): if m.objectId == employee_id: employee = m i_remove = ind break if not employee: return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Pending employee not found.'})) # update session cache for employees_pending_list employees_pending_list.pop(i_remove) request.session['employees_pending_list'] =\ employees_pending_list acc = Account.objects().get(Employee=employee.objectId) if not acc: # employee may have been deleted return redirect(reverse('employees_index')+ "?show_pending&%s" %\ urllib.urlencode({'success': 'Employee has already been denied.'})) # Always save session first whenever calling a cloud code request.session.save() res = cloud_call("delete_employee", {"employee_id": employee.objectId}) request.session.clear() request.session.update(SessionStore(request.session.session_key)) if 'error' not in res: payload = {COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY} store = SESSION.get_store(request.session) # no need to check acl here but just in case if acc.objectId in store.ACL and not store.is_owner(acc): del store.ACL[acc.objectId] store.update() payload["updatedStore"] = store.jsonify() request.session['store'] = store # only need to pass in the objectId deleted_employee = Employee(objectId=employee.objectId) payload["deletedEmployee"] = deleted_employee.jsonify() comet_receive(store.objectId, payload) return redirect(reverse('employees_index')+ "?show_pending&%s" %\ urllib.urlencode({'success': 'Employee has been denied.'})) return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Employee has already been deleted.'}))
def manage_admin_controls(request): """ To turn on god_mode: ...repunch.com/manage/admin-controls?action=god_mode&flag=1& [email protected]&key=9p8437wk34z5ymurukdp9w34px7iuhsruhio """ if request.method == "GET": params = request.GET.dict() key = params.get("key") action = params.get("action") if key == ADMIN_CONTROL_KEY: if action == "god_mode": flag = params.get("flag") email = params.get("email", "") acc = Account.objects().get(email=email, Store__ne=None, include="Store.Subscription") if not acc: return HttpResponse("User with email %s not found." %\ (email,)) sub = acc.store.subscription sub.god_mode = flag != "0" sub.update() payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSubscription": sub.jsonify(), } comet_receive(acc.store.objectId, payload) # go out with the latest session in case this user is # the one that triggered this action request.session.clear() request.session.update( SessionStore(request.session.session_key)) if sub.god_mode: on_off = "on" else: on_off = "off" return HttpResponse("Successfully turned god mode "+\ "%s for user with email %s" % (on_off, email)) else: return HttpResponse("Invalid action: %s" % (action, )) else: return HttpResponse("Wrong key: %s" % (key, )) return HttpResponse("Bad Request")
def settings(request): """ Renders the settings page or handles changes to it. """ data = {'settings_nav': True} store = SESSION.get_store(request.session) settings = SESSION.get_settings(request.session) # user made changes if request.method == 'POST': form = SettingsForm(request.POST) if form.is_valid(): # expect numbers so cast to int dct = request.POST.dict().copy() dct['punches_employee'] = int(dct['punches_employee']) settings.update_locally(dct, False) settings.update() # Shin chose to move punches_facebook to Store... store.set("punches_facebook", int(request.POST["punches_facebook"])) store.Settings = settings.objectId store.settings = settings store.update() # notify other dashboards of this changes payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSettings":settings.jsonify(), "updatedPunchesFacebook_int":\ store.punches_facebook, } comet_receive(store.objectId, payload) data['success'] = "Settings have been saved." else: data['error'] = 'Error saving settings.' # user navigated to this page so just render the settings template # with a filled settings form else: form = SettingsForm() form.initial = settings.__dict__.copy() # shin chose to move punches_facebook to Store... form.initial['punches_facebook'] =\ store.get('punches_facebook') # update the session cache since we may have made changes above request.session['store'] = store request.session['settings'] = settings data['form'] = form data['settings'] = settings return render(request, 'manage/settings.djhtml', data)
def manage_admin_controls(request): """ To turn on god_mode: ...repunch.com/manage/admin-controls?action=god_mode&flag=1& [email protected]&key=9p8437wk34z5ymurukdp9w34px7iuhsruhio """ if request.method == "GET": params = request.GET.dict() key = params.get("key") action = params.get("action") if key == ADMIN_CONTROL_KEY: if action == "god_mode": flag = params.get("flag") email = params.get("email", "") acc = Account.objects().get(email=email, Store__ne=None, include="Store.Subscription") if not acc: return HttpResponse("User with email %s not found." %\ (email,)) sub = acc.store.subscription sub.god_mode = flag != "0" sub.update() payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSubscription": sub.jsonify(), } comet_receive(acc.store.objectId, payload) # go out with the latest session in case this user is # the one that triggered this action request.session.clear() request.session.update(SessionStore(request.session.session_key)) if sub.god_mode: on_off = "on" else: on_off = "off" return HttpResponse("Successfully turned god mode "+\ "%s for user with email %s" % (on_off, email)) else: return HttpResponse("Invalid action: %s" % (action,)) else: return HttpResponse("Wrong key: %s" % (key,)) return HttpResponse("Bad Request")
def edit(request): account = request.session['account'] store = SESSION.get_store(request.session) email_form, pass_form, data = None, None, {} if request.method == "POST": action, success = request.POST['action'], None if action == "email": email_form = EmailForm(account, request.POST) if email_form.is_valid(): success = "Successfully updated email." # Need to make sure that the account is the latest - # User in dashboard then signs up for a mobile account # and then edits store details = bug! account.fetch_all(clear_first=True, with_cache=False) # update the account - email = username! postEmail = email_form.cleaned_data['email'] if account.email != postEmail: account.email = postEmail account.username = postEmail account.update() elif action == "password": pass_form = PasswordForm(account, request.POST) if pass_form.is_valid(): success = "Successfully updated password." account.set_password(pass_form.cleaned_data['new']) account.update(save_password=True) if success: data['success'] = success # notify other dashboards of these changes payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedAccount": account.jsonify() } comet_receive(store.objectId, payload) request.session["account"] = account if not email_form: email_form = EmailForm(None) email_form.initial = request.session['account'].__dict__.copy() if not pass_form: pass_form = PasswordForm(None) data["email_form"] = email_form data["password_form"] = pass_form return render(request, 'manage/account_edit.html', data)
def deactivate(request): """ This does not delete anything! It merely sets the store's active field to false and logs the user out. """ store = request.session['store'] store.active = False store.update() # notify other dashboards of this changes payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedStore": store.jsonify(), } comet_receive(store.objectId, payload) return redirect(reverse('manage_logout'))
def deactivate(request): """ This does not delete anything! It merely sets the store's active field to false and logs the user out. """ store = request.session['store'] store.active = False store.update() # notify other dashboards of this changes payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedStore":store.jsonify(), } comet_receive(store.objectId, payload) return redirect(reverse('manage_logout'))
def receive(request, store_id): """ Receives a get request from a foreign site and sets all of the CometSessions that have the given store Id. This is called by a currently logged in user as well as by the cloud. Need to differentiate! Note: request.POST does not contain the data! Use request.body instead! Note 2: request.body comes in Latin-1 format (ISO-8859-1). This must be converted to unicode which will then be encoded to UTF-8 by django and the browser (<meta http-equiv="Content-Type" content="text/html; charset=utf-8">) """ if request.method == "POST": try: postDict = json.loads(unicode(request.body, "ISO-8859-1")) except Exception: return HttpResponse("error") if comet_receive(store_id, postDict): return HttpResponse("success") return HttpResponse("error")
def edit(request, employee_id): data = {'employees_nav': True, 'employee_id': employee_id} # get from the employees_approved_list in session cache employees_approved_list = SESSION.get_employees_approved_list(\ request.session) employee = None for m in employees_approved_list: if m.objectId == employee_id: employee = m break acc = Account.objects().get(Employee=employee.objectId) store = SESSION.get_store(request.session) if not employee or not acc: return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Employee does not exist.'})) if request.method == "POST": store.set_access_level(acc, request.POST["ACL"]) store.update() request.session['store'] = store # notify other dashboards of this change payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedStore": store.jsonify() } comet_receive(store.objectId, payload) return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Employee has been updated.'})) form = EmployeeForm(employee.__dict__.copy()) form.data['email'] = acc.get('email') data.update({ 'ACCESS_ADMIN': ACCESS_ADMIN[0], 'ACCESS_PUNCHREDEEM': ACCESS_PUNCHREDEEM[0], 'ACCESS_NONE': ACCESS_NONE[0], 'form': form, 'employee': employee, 'employee_acl': store.get_access_level(acc)[0], }) return render(request, 'manage/employee_edit.djhtml', data)
def edit(request, employee_id): data = {'employees_nav': True, 'employee_id': employee_id} # get from the employees_approved_list in session cache employees_approved_list = SESSION.get_employees_approved_list(\ request.session) employee = None for m in employees_approved_list: if m.objectId == employee_id: employee = m break acc = Account.objects().get(Employee=employee.objectId) store = SESSION.get_store(request.session) if not employee or not acc: return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Employee does not exist.'})) if request.method == "POST": store.set_access_level(acc, request.POST["ACL"]) store.update() request.session['store'] = store # notify other dashboards of this change payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedStore":store.jsonify() } comet_receive(store.objectId, payload) return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Employee has been updated.'})) form = EmployeeForm(employee.__dict__.copy()) form.data['email'] = acc.get('email') data.update({ 'ACCESS_ADMIN': ACCESS_ADMIN[0], 'ACCESS_PUNCHREDEEM': ACCESS_PUNCHREDEEM[0], 'ACCESS_NONE': ACCESS_NONE[0], 'form': form, 'employee': employee, 'employee_acl': store.get_access_level(acc)[0], }) return render(request, 'manage/employee_edit.djhtml', data)
def delete(request, reward_id): """ Deletes a reward with the given reward_id. """ # check if the reward_id passed in is invalid and raise a 404 if so. # reward ids are integers try: reward_id = int(str(reward_id)) except ValueError: raise Http404 account = request.session['account'] store = SESSION.get_store(request.session) rewards = store.get('rewards') rewards_map = {reward['reward_id']: reward for reward in rewards} # reward cannot be found for deletion. Redirect user to the rewards # page with a success message (maybe this should be an error message instead?). try: reward = rewards_map[reward_id] except KeyError: return redirect(reverse('rewards_index')+\ "?%s" % urllib.urlencode({'success':\ 'Reward has been removed.'})) # notify other dashboards of this change payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "deletedReward": { "reward_id": reward["reward_id"] } } comet_receive(store.objectId, payload) # update session cache store.array_remove('rewards', [reward]) store.rewards = None store.get('rewards') request.session['store'] = store return redirect(reverse('rewards_index')+\ "?%s" % urllib.urlencode({'success':\ 'Reward has been removed.'}))
def approve(request, employee_id): # get from the employees_pending_list in session cache employees_pending_list = SESSION.get_employees_pending_list(\ request.session) i_remove, employee = 0, None for ind, m in enumerate(employees_pending_list): if m.objectId == employee_id: employee = m i_remove = ind break if not employee: return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Pending employee not found.'})) employee.set('status', APPROVED) employee.update() employees_pending_list.pop(i_remove) request.session['employees_pending_list'] =\ employees_pending_list # update session cache for employees_approved_list employees_approved_list = SESSION.get_employees_approved_list(\ request.session) employees_approved_list.insert(0, employee) request.session['employees_approved_list'] =\ employees_approved_list # notify other dashboards of this change store_id = SESSION.get_store(request.session).objectId approved_employee = Employee(objectId=employee.objectId) payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "approvedEmployee":approved_employee.jsonify() } comet_receive(store_id, payload) return redirect(reverse('employees_index')+ "?show_pending&%s" %\ urllib.urlencode({'success': 'Employee has been approved.'}))
def edit_store(request): """ Render the edit store template or handle a form submission from it. """ data = {'account_nav': True} store = SESSION.get_store(request.session) # validate form submission and redirect to store details if # success or re-render the store edit template with previous form # input and errors. if request.method == "POST": store_form = StoreForm(request.POST) if store_form.is_valid(): store.update_locally(request.POST.dict(), False) store.update() # notify other dashboards comet_receive( store.objectId, { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedStore": store.jsonify(), }) # make sure that we have the latest session request.session.clear() request.session.update(SessionStore(request.session.session_key)) return redirect(reverse('store_index')+ "?%s" %\ urllib.urlencode({'success': 'Store details has been updated.'})) # user navigates to this page so just render the store edit template # with a blank form. else: store_form = StoreForm() store_form.initial = store.__dict__.copy() data['store_form'] = store_form return render(request, 'manage/store_edit.html', data)
def feedback_delete(request, feedback_id): """ Handles requests to delete the feedback with the given feedback_id. """ store = SESSION.get_store(request.session) # get the feedback from the messages_received_list in session cache messages_received_list = SESSION.get_messages_received_list(\ request.session) i_remove, feedback = 0, None for ind, m in enumerate(messages_received_list): if m.objectId == feedback_id: feedback = m i_remove = ind break if not feedback: # feedback not found - it may have been deleted return redirect(reverse('messages_index')+ "?%s" %\ urllib.urlencode({'error': 'Feedback not found.'})) # we don't actually delete the feedback object, # we just remove from the store's relation store.remove_relation("ReceivedMessages_", [feedback.objectId]) # remove it from the messages_received_list in session cache messages_received_list.pop(i_remove) request.session['messages_received_list'] =\ messages_received_list # notify other dashboards logged into the same store of this change comet_receive( store.objectId, { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "deletedFeedback": Message(objectId=feedback.objectId).jsonify(), }) return redirect(reverse('messages_index')+ "?%s" %\ urllib.urlencode({'success':'Feedback has been deleted.', 'tab_feedback':1}))
def approve(request, employee_id): # get from the employees_pending_list in session cache employees_pending_list = SESSION.get_employees_pending_list(\ request.session) i_remove, employee = 0, None for ind, m in enumerate(employees_pending_list): if m.objectId == employee_id: employee = m i_remove = ind break if not employee: return redirect(reverse('employees_index')+ "?%s" %\ urllib.urlencode({'success': 'Pending employee not found.'})) employee.set('status', APPROVED) employee.update() employees_pending_list.pop(i_remove) request.session['employees_pending_list'] =\ employees_pending_list # update session cache for employees_approved_list employees_approved_list = SESSION.get_employees_approved_list(\ request.session) employees_approved_list.insert(0, employee) request.session['employees_approved_list'] =\ employees_approved_list # notify other dashboards of this change store_id = SESSION.get_store(request.session).objectId approved_employee = Employee(objectId=employee.objectId) payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "approvedEmployee": approved_employee.jsonify() } comet_receive(store_id, payload) return redirect(reverse('employees_index')+ "?show_pending&%s" %\ urllib.urlencode({'success': 'Employee has been approved.'}))
def edit_store(request): """ Render the edit store template or handle a form submission from it. """ data = {'account_nav': True} store = SESSION.get_store(request.session) # validate form submission and redirect to store details if # success or re-render the store edit template with previous form # input and errors. if request.method == "POST": store_form = StoreForm(request.POST) if store_form.is_valid(): store.update_locally(request.POST.dict(), False) store.update() # notify other dashboards comet_receive(store.objectId, { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedStore": store.jsonify(), }) # make sure that we have the latest session request.session.clear() request.session.update(SessionStore(request.session.session_key)) return redirect(reverse('store_index')+ "?%s" %\ urllib.urlencode({'success': 'Store details has been updated.'})) # user navigates to this page so just render the store edit template # with a blank form. else: store_form = StoreForm() store_form.initial = store.__dict__.copy() data['store_form'] = store_form return render(request, 'manage/store_edit.html', data)
def edit_location(request, store_location_id): """ Renders the edit location template or handle form submissions for location creation or update. """ data = {'account_nav': True, 'store_location_id': store_location_id} store = SESSION.get_store(request.session) # we are editing a new location if store_location_id is 0 new_location = store_location_id == '0' def common(store_location_form): """ Returns a rendered store location edit template with the given store location form. """ data['store_location_form'] = store_location_form return render(request, 'manage/store_location_edit.djhtml', data) # Handle form submission and return the appropriate json response if request.method == 'POST': store_location_form = StoreLocationForm(request.POST) postDict = request.POST.dict() hours = HoursInterpreter(json.loads(postDict["hours"])) # we are either creating a new store location or updating an # existing one with new values in the postDict if new_location: store_location = StoreLocation(**postDict) else: store_location = SESSION.get_store_location(\ request.session, store_location_id) store_location.update_locally(postDict, False) if store_location_form.is_valid(): # validate and format the hours hours_validation = hours.is_valid() if type(hours_validation) is bool: store_location.set("hours", hours.from_javascript_to_parse()) else: data['hours_data'] = hours._format_javascript_input() data['hours_error'] = hours_validation return HttpResponse(json.dumps({ "result": "error", "html": common(store_location_form).content, }), content_type="application/json") # set the timezone if store_location.get('zip'): store_location.store_timezone =\ get_timezone(store_location.get('zip')).zone # format the phone number store_location.phone_number =\ format_phone_number(postDict['phone_number']) # update the store's coordinates and neighborhood full_address = " ".join(\ store_location.get_full_address().split(", ")) map_data = get_map_data(full_address) store_location.set("coordinates", map_data.get("coordinates")) store_location.set("neighborhood", store_location.get_best_fit_neighborhood(\ map_data.get("neighborhood"))) if new_location: store_location.Store = store.objectId store_location.create() store.array_add_unique("store_locations", [store_location]) else: store_location.update() # if this location is the first location then update # the corresponding store columns for backwards compat sl_list = SESSION.get_store_locations_list(request.session) if sl_list[0].objectId == store_location.objectId: store.inherit_store_location(store_location) store.update() payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedStore": store.jsonify(), "updatedStoreLocation": store_location.jsonify(), } comet_receive(store.objectId, payload) # make sure that we have the latest session request.session.clear() request.session.update(SessionStore(request.session.session_key)) if new_location: success_msg = 'New store location has been added.' else: success_msg = 'Store location has been updated.' # set the active location to this one SESSION.set_active_store_location_id(request.session, store_location.objectId) return HttpResponse(json.dumps({ "result": "success", "url": reverse('store_index')+ "?%s" %\ urllib.urlencode({'success': success_msg}) }), content_type="application/json") else: data['store_location'] = store_location data['hours_data'] = hours._format_javascript_input() return HttpResponse(json.dumps({ "result": "error", "html": common(store_location_form).content, }), content_type="application/json") # user navigated to this page so just render a store location edit # template with a blank form (if new_location) or a form with fields # filled out if user is editing an existing location else: store_location_form = StoreLocationForm(None) # user is editing an existing location so fill up initial # form content if not new_location: store_location = SESSION.get_store_location(\ request.session, store_location_id) store_location_form.initial = store_location.__dict__.copy() # make sure that the phone number is unformatted store_location_form.initial['phone_number'] =\ store_location_form.initial['phone_number'].replace("(", "").replace(")","").replace(" ", "").replace("-","") data['store_location'] = store_location data['hours_data'] = HoursInterpreter(\ store_location.hours)._format_parse_input() return common(store_location_form)
def register(request): """ Adds a new employee to the currently logged in Store. This automatically sets this employee to approved. """ data = {'employees_nav': True} settings = SESSION.get_settings(request.session) store = SESSION.get_store(request.session) if request.method == "POST": from_associated_account = False # check if this post is from the associated account dialog # if it is then skip form validations aaf_nonce_id = request.POST.get('aaf-nonce') aaf_account_id = request.POST.get('aaf-account_id') if len(aaf_nonce_id) > 0 and len(aaf_account_id) > 0: aa_nonce = AssociatedAccountNonce.objects.filter(\ id=aaf_nonce_id, account_id=aaf_account_id) if len(aa_nonce) > 0 and aa_nonce[0].verified: aa_nonce[0].delete() from_associated_account = True account_form = EmployeeAccountSignUpForm(request.POST) employee_form = EmployeeForm(request.POST) if not from_associated_account: all_forms_valid = account_form.is_valid() and\ employee_form.is_valid() else: all_forms_valid = True if all_forms_valid: postDict = request.POST.dict() # make the cloud call # see cloud param for possible access level values acl = postDict['acl'] if acl == ACCESS_ADMIN[0]: access_level = "admin" elif acl == ACCESS_PUNCHREDEEM[0]: access_level = "punch_redeem" else: access_level = None params = { "retailer_pin": settings.get("retailer_pin"), "username": postDict['email'].strip().lower(), "first_name": postDict['first_name'].capitalize(), "last_name": postDict['last_name'].capitalize(), "email": postDict['email'].strip().lower(), "status": APPROVED, "access_level": access_level, } if from_associated_account: res = cloud_call("link_employee", params) else: params["password"] = postDict['password'] res = cloud_call("register_employee", params) # don't forget to retrieve the latest session request.session.clear() request.session.update(SessionStore(request.session.session_key)) # check if email already taken here to handle the case where # the user already has a patron/employee account # but also want to sign up for a Store account if "error" in res and res['error'] in ("EMAIL_TAKEN_AVAILABLE", "USERNAME_TAKEN_AVAILABLE"): aa = Account.objects().get( email=postDict['email'].strip().lower()) aan = AssociatedAccountNonce.objects.create(\ account_id=aa.objectId) return HttpResponse(json.dumps({"associated_account":\ aa.objectId, "associated_account_nonce":aan.id, "email": aa.email, "code": 0}), content_type="application/json") elif "error" in res and res['error'] in ("EMAIL_TAKEN", "USERNAME_TAKEN"): account_form._errors.setdefault( "email", ErrorList()).append(u"Email is already being used.") elif "error" not in res: # add the employee to the approved list employees_approved_list =\ SESSION.get_employees_approved_list(request.session) employees_approved_ids =\ [ emp.objectId for emp in employees_approved_list ] new_employee = Employee(**res["result"]) if new_employee.objectId not in employees_approved_ids: employees_approved_list.insert(0, new_employee) request.session['employees_approved_list'] =\ employees_approved_list # update our local store's acl - don't wait for # the cloud post store = SESSION.get_store(request.session) store.set_access_level(Account.objects().get(\ email=postDict['email'].strip().lower()), acl) request.session['store'] = store # notify other dashboards of this change payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedStore": store.jsonify() } comet_receive(store.objectId, payload) return HttpResponse(json.dumps({"code": 2}), content_type="application/json") else: return HttpResponse(json.dumps({"code": 3}), content_type="application/json") else: employee_form = EmployeeForm(initial={"acl":\ ACCESS_PUNCHREDEEM[0]}) account_form = EmployeeAccountSignUpForm() data["employee_form"] = employee_form data["account_form"] = account_form return render(request, 'manage/employee_register.djhtml', data)
def edit(request, reward_id): """ Render the reward edit template for a new or existing reward or handle forms for new or existing rewards. """ # check if the reward_id passed in is invalid and raise a 404 if so. # reward ids are integers try: reward_id = int(str(reward_id)) except ValueError: raise Http404 data = {'rewards_nav': True} store = SESSION.get_store(request.session) rewards = store.get('rewards') rewards_map = {reward['reward_id']: reward for reward in rewards} # reward id being -1 is a flag for new reward which don't exist is_new, reward = reward_id == -1, None if reward_id in rewards_map: reward = rewards_map[reward_id] elif reward_id not in rewards_map and not is_new: # the reward with the given reward id does not exist nor return redirect(reverse('rewards_index')) # user submits form if request.method == 'POST': form = RewardForm(request.POST) if form.is_valid(): # construct a reward dict from the form reward = { 'reward_name': form.data['reward_name'], "description": " ".join(form.data['description'].split()), "punches": int(form.data['punches']), "redemption_count": 0 } # create a list of sorted ids from the rewards ids, msg = [r['reward_id'] for r in rewards], "" ids.sort() if not is_new: msg = 'Reward has been updated.' # we have an existing reward - we need to carry over # the previous redemption_count if user did not # specify to reset it old_reward = rewards_map[reward_id] if not request.POST.get('reset_red_count'): reward["redemption_count"] =\ old_reward["redemption_count"] # the reward_id will not change reward['reward_id'] = old_reward['reward_id'] # remove the old_reward from Parse since we will # add our created reward instance later store.array_remove('rewards', [old_reward]) elif len(ids) == 0: # store's very first reward msg = 'Reward has been added.' reward['reward_id'] = 0 else: # reward is new so assign the highest id + 1 msg = 'Reward has been added.' reward['reward_id'] = ids[-1] + 1 # notify other dashboards of this change if is_new: comet_attr = 'newReward' else: comet_attr = 'updatedReward' comet_receive(store.objectId, { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, comet_attr: reward }) # add our reward to Parse store.array_add_unique('rewards', [reward]) # update session cache store.rewards = None store.get('rewards') request.session['store'] = store return redirect(reverse('rewards_index')+\ "?%s" % urllib.urlencode({'success':msg})) else: form = RewardForm(reward) data.update({ 'reward': reward, 'is_new': is_new, 'reward_id': reward_id, 'form': form, }) return render(request, 'manage/reward_edit.djhtml', data)
def handle(self, *args, **options): # for logging when ran by CRON print "Running passed_user_limit: " + str(timezone.now()) now = timezone.now() b4_now = now + relativedelta(hours=-1) # get 500 subscriptions at a time LIMIT = 500 # first scan though all the stores and set their # date_passed_user_limit if so # TODO optimize with a relational query? possible with Parse? #### SUB_TYPE 0 skip = 0 sub_count = Subscription.objects().count(\ date_passed_user_limit=None, subscriptionType=0) max_users = sub_type[0]['max_users'] while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=0, include="Store", date_passed_user_limit=None, god_mode=False, limit=LIMIT, skip=skip, order="createdAt"): store = sub.store if store.get("patronStores", count=1, limit=0) >\ max_users: sub.date_passed_user_limit = b4_now sub.update() # notify the dashboards of these changes payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSubscription": sub.jsonify() } comet_receive(sub.Store, payload) # end of while loop sub_count -= LIMIT skip += LIMIT # TODO optimize with a relational query? possible with Parse? #### SUB_TYPE 1 skip = 0 sub_count = Subscription.objects().count(\ date_passed_user_limit=None, subscriptionType=1) max_users = sub_type[1]['max_users'] while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=1, include="Store", date_passed_user_limit=None, god_mode=False, limit=LIMIT, skip=skip, order="createdAt"): store = sub.store if store.get("patronStores", count=1, limit=0) >\ max_users: sub.date_passed_user_limit = b4_now sub.update() # notify the dashboards of these changes payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSubscription": sub.jsonify() } comet_receive(sub.Store, payload) # end of while loop sub_count -= LIMIT skip += LIMIT ################ conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() # 1st day time range day1_end = now.replace() day1_start = day1_end + relativedelta(hours=-24) # 4th day time range day4_end = now + relativedelta(days=-4) day4_start = day4_end + relativedelta(hours=-24) # 8th day time range day8_end = now + relativedelta(days=-8) day8_start = day8_end + relativedelta(hours=-24) # 14th day time range day14_end = now + relativedelta(days=-14) day14_start = day14_end + relativedelta(hours=-24) #### SUB_TYPE 0 ## 1st day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=0, date_passed_user_limit__lte=day1_end, date_passed_user_limit__gte=day1_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=0, include="Store", date_passed_user_limit__lte=day1_end, date_passed_user_limit__gte=day1_start, limit=LIMIT, skip=skip, order="createdAt"): # with pp_cc_id if sub.pp_cc_id and len(sub.pp_cc_id) > 0: sub.subscriptionType = 1 sub.date_passed_user_limit = None sub.update() # notify the dashboards of these changes payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSubscription": sub.jsonify() } comet_receive(sub.Store, payload) package = { "status": "upgraded", "sub_type": sub_type[0]["name"], "new_sub_type": sub_type[1]["name"], "new_sub_type_cost": sub_type[1]["monthly_cost"], "new_max_patronStore_count":\ sub_type[1]["max_users"], "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), } # no pp_cc_id else: package = { "sub_type": sub_type[0]["name"], "max_patronStore_count": sub_type[0]["max_users"], "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), "disable_date": sub.date_passed_user_limit + relativedelta(days=\ USER_LIMIT_PASSED_DISABLE_DAYS), } try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT ## 4th day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=0, date_passed_user_limit__lte=day4_end, date_passed_user_limit__gte=day4_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=0, include="Store", date_passed_user_limit__lte=day4_end, date_passed_user_limit__gte=day4_start, limit=LIMIT, skip=skip, order="createdAt"): package = { "sub_type": sub_type[0]["name"], "max_patronStore_count": sub_type[0]["max_users"], "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), "disable_date": sub.date_passed_user_limit + relativedelta(days=\ USER_LIMIT_PASSED_DISABLE_DAYS), } try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT ## 8th day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=0, date_passed_user_limit__lte=day8_end, date_passed_user_limit__gte=day8_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=0, include="Store", date_passed_user_limit__lte=day8_end, date_passed_user_limit__gte=day8_start, limit=LIMIT, skip=skip, order="createdAt"): package = { "sub_type": sub_type[0]["name"], "max_patronStore_count": sub_type[0]["max_users"], "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), "disable_date": sub.date_passed_user_limit + relativedelta(days=\ USER_LIMIT_PASSED_DISABLE_DAYS), } try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT ## 14th day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=0, date_passed_user_limit__lte=day14_end, date_passed_user_limit__gte=day14_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=0, include="Store", date_passed_user_limit__lte=day14_end, date_passed_user_limit__gte=day14_start, limit=LIMIT, skip=skip, order="createdAt"): package = {"status": "disabled"} # deactivate the store sub.store.active = False sub.store.update() payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedStore": sub.store.jsonify(), } comet_receive(sub.Store, payload) try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT #### SUB_TYPE 1 ## 1st day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=1, date_passed_user_limit__lte=day1_end, date_passed_user_limit__gte=day1_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=1, include="Store", date_passed_user_limit__lte=day1_end, date_passed_user_limit__gte=day1_start, limit=LIMIT, skip=skip, order="createdAt"): # with pp_cc_id if sub.pp_cc_id and len(sub.pp_cc_id) > 0: sub.subscriptionType = 2 sub.date_passed_user_limit = None sub.update() # notify the dashboards of these changes payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSubscription": sub.jsonify() } comet_receive(sub.Store, payload) package = { "status": "upgraded", "sub_type": sub_type[1]["name"], "new_sub_type": sub_type[2]["name"], "new_sub_type_cost": sub_type[2]["monthly_cost"], "new_max_patronStore_count": "Unlimited", "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), } # no pp_cc_id else: package = { "sub_type": sub_type[1]["name"], "max_patronStore_count": sub_type[1]["max_users"], "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), "disable_date": sub.date_passed_user_limit + relativedelta(days=\ USER_LIMIT_PASSED_DISABLE_DAYS), } try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT ## 4th day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=1, date_passed_user_limit__lte=day4_end, date_passed_user_limit__gte=day4_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=1, include="Store", date_passed_user_limit__lte=day4_end, date_passed_user_limit__gte=day4_start, limit=LIMIT, skip=skip, order="createdAt"): package = { "sub_type": sub_type[1]["name"], "max_patronStore_count": sub_type[1]["max_users"], "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), "disable_date": sub.date_passed_user_limit + relativedelta(days=\ USER_LIMIT_PASSED_DISABLE_DAYS), } try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT ## 8th day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=1, date_passed_user_limit__lte=day8_end, date_passed_user_limit__gte=day8_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=1, include="Store", date_passed_user_limit__lte=day8_end, date_passed_user_limit__gte=day8_start, limit=LIMIT, skip=skip, order="createdAt"): package = { "sub_type": sub_type[1]["name"], "max_patronStore_count": sub_type[1]["max_users"], "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), "disable_date": sub.date_passed_user_limit + relativedelta(days=\ USER_LIMIT_PASSED_DISABLE_DAYS), } try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT ## 14th day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=1, date_passed_user_limit__lte=day14_end, date_passed_user_limit__gte=day14_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=1, include="Store", date_passed_user_limit__lte=day14_end, date_passed_user_limit__gte=day14_start, limit=LIMIT, skip=skip, order="createdAt"): package = {"status": "disabled"} # deactivate the store sub.store.active = False sub.store.update() payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedStore": sub.store.jsonify(), } comet_receive(sub.Store, payload) try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT try: conn.close() except Exception: pass
def image_crop(request): """ Takes in crop coordinates and creates a new png image. """ if request.method == "POST": data = {} store = SESSION.get_store(request.session) old_cover, old_thumbnail = None, None if store.get("cover_image"): old_cover = store.get("cover_image") if store.get("thumbnail_image"): old_thumbnail = store.get("thumbnail_image") # if there are 2 windows with the same session_key editing the # store image, the image will be deleted by the first window # to crop. The 2nd window will then have no image. image = UploadedImageFile.objects.filter(session_key=\ request.session.session_key) if not image: # flag the execution of image Crop Complete js function data['success'] = True return render(request, 'manage/image_crop.djhtml', data) image = image[0] # the crop coords are used for the thumbnail_image crop_coords = None if len(request.POST["x1"]) > 0: crop_coords = { "x1": int(request.POST["x1"].split(".")[0]), "y1": int(request.POST["y1"].split(".")[0]), "x2": int(request.POST["x2"].split(".")[0]), "y2": int(request.POST["y2"].split(".")[0]), } # save the session before a cloud call! request.session.save() res_cover = create_png(image.image.path) res_thumbnail = create_png(image.image.path, IMAGE_THUMBNAIL_SIZE, crop_coords) # make sure that we have the latest session session = SessionStore(request.session.session_key) store = SESSION.get_store(session) if res_cover and 'error' not in res_cover: setattr(store, "cover_image", res_cover.get('name')) setattr(store, "cover_image_url", res_cover.get('url').replace(\ "http:/", "https://s3.amazonaws.com")) if res_thumbnail and 'error' not in res_thumbnail: setattr(store, "thumbnail_image", res_thumbnail.get('name')) setattr(store, "thumbnail_image_url", res_thumbnail.get('url').replace(\ "http:/", "https://s3.amazonaws.com")) # below here for backwards compat store.store_avatar = getattr(store, "thumbnail_image") store.store_avatar_url = getattr(store, "thumbnail_image_url") store.update() # delete the model and file since it's useless to keep image.delete() # notify other dashboards of this change payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedStoreThumbnailName": store.thumbnail_image, "updatedStoreThumbnailUrl": store.thumbnail_image_url, "updatedStoreCoverName": store.cover_image, "updatedStoreCoverUrl": store.cover_image_url, } comet_receive(store.objectId, payload) # need to remove old files if old_cover: delete_file(old_cover, 'image/png') if old_thumbnail: delete_file(old_thumbnail, 'image/png') # flag the execution of image Crop Complete js function data['success'] = True # make sure we have latest session data request.session.clear() request.session.update(SessionStore(request.session.session_key)) return render(request, 'manage/image_crop.djhtml', data) raise Http404
def register(request): """ Adds a new employee to the currently logged in Store. This automatically sets this employee to approved. """ data = {'employees_nav': True} settings = SESSION.get_settings(request.session) store = SESSION.get_store(request.session) if request.method == "POST": from_associated_account = False # check if this post is from the associated account dialog # if it is then skip form validations aaf_nonce_id = request.POST.get('aaf-nonce') aaf_account_id = request.POST.get('aaf-account_id') if len(aaf_nonce_id) > 0 and len(aaf_account_id) > 0: aa_nonce = AssociatedAccountNonce.objects.filter(\ id=aaf_nonce_id, account_id=aaf_account_id) if len(aa_nonce) > 0 and aa_nonce[0].verified: aa_nonce[0].delete() from_associated_account = True account_form = EmployeeAccountSignUpForm(request.POST) employee_form = EmployeeForm(request.POST) if not from_associated_account: all_forms_valid = account_form.is_valid() and\ employee_form.is_valid() else: all_forms_valid = True if all_forms_valid: postDict = request.POST.dict() # make the cloud call # see cloud param for possible access level values acl = postDict['acl'] if acl == ACCESS_ADMIN[0]: access_level = "admin" elif acl == ACCESS_PUNCHREDEEM[0]: access_level = "punch_redeem" else: access_level = None params = { "retailer_pin": settings.get("retailer_pin"), "username": postDict['email'].strip().lower(), "first_name": postDict['first_name'].capitalize(), "last_name": postDict['last_name'].capitalize(), "email": postDict['email'].strip().lower(), "status": APPROVED, "access_level": access_level, } if from_associated_account: res = cloud_call("link_employee", params) else: params["password"] = postDict['password'] res = cloud_call("register_employee", params) # don't forget to retrieve the latest session request.session.clear() request.session.update(SessionStore(request.session.session_key)) # check if email already taken here to handle the case where # the user already has a patron/employee account # but also want to sign up for a Store account if "error" in res and res['error'] in ("EMAIL_TAKEN_AVAILABLE", "USERNAME_TAKEN_AVAILABLE"): aa = Account.objects().get(email=postDict['email'].strip().lower()) aan = AssociatedAccountNonce.objects.create(\ account_id=aa.objectId) return HttpResponse(json.dumps({"associated_account":\ aa.objectId, "associated_account_nonce":aan.id, "email": aa.email, "code": 0}), content_type="application/json") elif "error" in res and res['error'] in ("EMAIL_TAKEN", "USERNAME_TAKEN"): account_form._errors.setdefault("email", ErrorList()).append(u"Email is already being used.") elif "error" not in res: # add the employee to the approved list employees_approved_list =\ SESSION.get_employees_approved_list(request.session) employees_approved_ids =\ [ emp.objectId for emp in employees_approved_list ] new_employee = Employee(**res["result"]) if new_employee.objectId not in employees_approved_ids: employees_approved_list.insert(0, new_employee) request.session['employees_approved_list'] =\ employees_approved_list # update our local store's acl - don't wait for # the cloud post store = SESSION.get_store(request.session) store.set_access_level(Account.objects().get(\ email=postDict['email'].strip().lower()), acl) request.session['store'] = store # notify other dashboards of this change payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedStore":store.jsonify() } comet_receive(store.objectId, payload) return HttpResponse(json.dumps({"code": 2}), content_type="application/json") else: return HttpResponse(json.dumps({"code": 3}), content_type="application/json") else: employee_form = EmployeeForm(initial={"acl":\ ACCESS_PUNCHREDEEM[0]}) account_form = EmployeeAccountSignUpForm() data["employee_form"] = employee_form data["account_form"] = account_form return render(request, 'manage/employee_register.djhtml', data)
def handle(self, *args, **options): # for logging when ran by CRON print "Running passed_user_limit: " + str(timezone.now()) now = timezone.now() b4_now = now + relativedelta(hours=-1) # get 500 subscriptions at a time LIMIT = 500 # first scan though all the stores and set their # date_passed_user_limit if so # TODO optimize with a relational query? possible with Parse? #### SUB_TYPE 0 skip = 0 sub_count = Subscription.objects().count(\ date_passed_user_limit=None, subscriptionType=0) max_users = sub_type[0]['max_users'] while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=0, include="Store", date_passed_user_limit=None, god_mode=False, limit=LIMIT, skip=skip, order="createdAt"): store = sub.store if store.get("patronStores", count=1, limit=0) >\ max_users: sub.date_passed_user_limit = b4_now sub.update() # notify the dashboards of these changes payload={ COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSubscription": sub.jsonify() } comet_receive(sub.Store, payload) # end of while loop sub_count -= LIMIT skip += LIMIT # TODO optimize with a relational query? possible with Parse? #### SUB_TYPE 1 skip = 0 sub_count = Subscription.objects().count(\ date_passed_user_limit=None, subscriptionType=1) max_users = sub_type[1]['max_users'] while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=1, include="Store", date_passed_user_limit=None, god_mode=False, limit=LIMIT, skip=skip, order="createdAt"): store = sub.store if store.get("patronStores", count=1, limit=0) >\ max_users: sub.date_passed_user_limit = b4_now sub.update() # notify the dashboards of these changes payload={ COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSubscription": sub.jsonify() } comet_receive(sub.Store, payload) # end of while loop sub_count -= LIMIT skip += LIMIT ################ conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() # 1st day time range day1_end = now.replace() day1_start = day1_end + relativedelta(hours=-24) # 4th day time range day4_end = now + relativedelta(days=-4) day4_start = day4_end + relativedelta(hours=-24) # 8th day time range day8_end = now + relativedelta(days=-8) day8_start = day8_end + relativedelta(hours=-24) # 14th day time range day14_end = now + relativedelta(days=-14) day14_start = day14_end + relativedelta(hours=-24) #### SUB_TYPE 0 ## 1st day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=0, date_passed_user_limit__lte=day1_end, date_passed_user_limit__gte=day1_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=0, include="Store", date_passed_user_limit__lte=day1_end, date_passed_user_limit__gte=day1_start, limit=LIMIT, skip=skip, order="createdAt"): # with pp_cc_id if sub.pp_cc_id and len(sub.pp_cc_id) > 0: sub.subscriptionType = 1 sub.date_passed_user_limit = None sub.update() # notify the dashboards of these changes payload={ COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSubscription": sub.jsonify() } comet_receive(sub.Store, payload) package = { "status": "upgraded", "sub_type": sub_type[0]["name"], "new_sub_type": sub_type[1]["name"], "new_sub_type_cost": sub_type[1]["monthly_cost"], "new_max_patronStore_count":\ sub_type[1]["max_users"], "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), } # no pp_cc_id else: package = { "sub_type": sub_type[0]["name"], "max_patronStore_count": sub_type[0]["max_users"], "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), "disable_date": sub.date_passed_user_limit + relativedelta(days=\ USER_LIMIT_PASSED_DISABLE_DAYS), } try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT ## 4th day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=0, date_passed_user_limit__lte=day4_end, date_passed_user_limit__gte=day4_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=0, include="Store", date_passed_user_limit__lte=day4_end, date_passed_user_limit__gte=day4_start, limit=LIMIT, skip=skip, order="createdAt"): package = { "sub_type": sub_type[0]["name"], "max_patronStore_count": sub_type[0]["max_users"], "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), "disable_date": sub.date_passed_user_limit + relativedelta(days=\ USER_LIMIT_PASSED_DISABLE_DAYS), } try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT ## 8th day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=0, date_passed_user_limit__lte=day8_end, date_passed_user_limit__gte=day8_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=0, include="Store", date_passed_user_limit__lte=day8_end, date_passed_user_limit__gte=day8_start, limit=LIMIT, skip=skip, order="createdAt"): package = { "sub_type": sub_type[0]["name"], "max_patronStore_count": sub_type[0]["max_users"], "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), "disable_date": sub.date_passed_user_limit + relativedelta(days=\ USER_LIMIT_PASSED_DISABLE_DAYS), } try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT ## 14th day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=0, date_passed_user_limit__lte=day14_end, date_passed_user_limit__gte=day14_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=0, include="Store", date_passed_user_limit__lte=day14_end, date_passed_user_limit__gte=day14_start, limit=LIMIT, skip=skip, order="createdAt"): package = { "status": "disabled" } # deactivate the store sub.store.active = False sub.store.update() payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedStore":sub.store.jsonify(), } comet_receive(sub.Store, payload) try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT #### SUB_TYPE 1 ## 1st day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=1, date_passed_user_limit__lte=day1_end, date_passed_user_limit__gte=day1_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=1, include="Store", date_passed_user_limit__lte=day1_end, date_passed_user_limit__gte=day1_start, limit=LIMIT, skip=skip, order="createdAt"): # with pp_cc_id if sub.pp_cc_id and len(sub.pp_cc_id) > 0: sub.subscriptionType = 2 sub.date_passed_user_limit = None sub.update() # notify the dashboards of these changes payload={ COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSubscription": sub.jsonify() } comet_receive(sub.Store, payload) package = { "status": "upgraded", "sub_type": sub_type[1]["name"], "new_sub_type": sub_type[2]["name"], "new_sub_type_cost": sub_type[2]["monthly_cost"], "new_max_patronStore_count": "Unlimited", "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), } # no pp_cc_id else: package = { "sub_type": sub_type[1]["name"], "max_patronStore_count": sub_type[1]["max_users"], "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), "disable_date": sub.date_passed_user_limit + relativedelta(days=\ USER_LIMIT_PASSED_DISABLE_DAYS), } try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT ## 4th day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=1, date_passed_user_limit__lte=day4_end, date_passed_user_limit__gte=day4_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=1, include="Store", date_passed_user_limit__lte=day4_end, date_passed_user_limit__gte=day4_start, limit=LIMIT, skip=skip, order="createdAt"): package = { "sub_type": sub_type[1]["name"], "max_patronStore_count": sub_type[1]["max_users"], "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), "disable_date": sub.date_passed_user_limit + relativedelta(days=\ USER_LIMIT_PASSED_DISABLE_DAYS), } try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT ## 8th day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=1, date_passed_user_limit__lte=day8_end, date_passed_user_limit__gte=day8_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=1, include="Store", date_passed_user_limit__lte=day8_end, date_passed_user_limit__gte=day8_start, limit=LIMIT, skip=skip, order="createdAt"): package = { "sub_type": sub_type[1]["name"], "max_patronStore_count": sub_type[1]["max_users"], "patronStore_count": sub.store.get(\ "patronStores", limit=0, count=1), "disable_date": sub.date_passed_user_limit + relativedelta(days=\ USER_LIMIT_PASSED_DISABLE_DAYS), } try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT ## 14th day skip = 0 sub_count = Subscription.objects().count(\ subscriptionType=1, date_passed_user_limit__lte=day14_end, date_passed_user_limit__gte=day14_start) while sub_count > 0: for sub in Subscription.objects().filter(\ subscriptionType=1, include="Store", date_passed_user_limit__lte=day14_end, date_passed_user_limit__gte=day14_start, limit=LIMIT, skip=skip, order="createdAt"): package = { "status": "disabled" } # deactivate the store sub.store.active = False sub.store.update() payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedStore":sub.store.jsonify(), } comet_receive(sub.Store, payload) try: send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_passed_user_limit(Account.objects().get(\ Store=sub.Store), sub.store, package, conn) # end of while loop sub_count -= LIMIT skip += LIMIT try: conn.close() except Exception: pass
def edit(request, message_id): """ Render the message edit template for a new message and handles send message forms. """ data = {'messages_nav': True, 'message_id': message_id, "filters": FILTERS} store = SESSION.get_store(request.session) # number of patron stores mp = SESSION.get_patronStore_count(request.session) # make sure cache attr is None for future queries! store.patronStores = None data['mp_slider_value'] = int(ceil(float(mp) * 0.50)) data['mp_slider_min'] = 1 data['mp_slider_max'] = mp # redirect if no patrons if not store.get("patronStores", count=1, limit=0): return redirect(reverse("messages_index")) # user submitted a form by form submission through POST request # or user is coming from an upgrade sequence from subscription_update if request.method == 'POST' or (request.method == "GET" and\ request.GET.get("send_message") and "message_b4_upgrade" in\ request.session): if request.method == "GET": # user is coming from an upgrade sequence from subscription_update postDict = request.session['message_b4_upgrade'].copy() # cleanup temp vars in session del request.session['message_b4_upgrade'] del request.session['from_limit_reached'] else: # user submitted a form by form submission through POST request postDict = request.POST.dict().copy() # populate a message form with the POST data for validation form = MessageForm(postDict) if form.is_valid(): # form is valid so continue to send the message subscription = SESSION.get_subscription(request.session) subType = subscription.get('subscriptionType') # refresh the message count - make sure we get the one in the cloud if 'message_count' in request.session: del request.session['message_count'] message_count = SESSION.get_message_count(request.session) # get the max_messages from the user's subscriptionType # or the highest level if god_mode is on if subscription.god_mode: max_messages = sub_type[2]['max_messages'] else: max_messages = sub_type[subType]['max_messages'] # limit is reached if the amount of messages sent this # billing cycle passed the amount for that subscription type limit_reached = message_count >= max_messages # We always enforce the limit when we are in production # otherwise, we ignore it if we have message_limit_off in our session if limit_reached and (PRODUCTION_SERVER or\ (not PRODUCTION_SERVER and "message_limit_off" not in request.session)): data['limit_reached'] = limit_reached # not the highest level of subscription so an upgrade # is still possible if subType != 2: # save the dict to the session request.session['message_b4_upgrade'] =\ request.POST.dict().copy() # the highest level of subscription so no more # upgrades can occur - therefore maxed_out elif subType == 2: data['maxed_out'] = True else: # limit has not yet been reached - send the message # build the message from session and POST data message = Message(\ sender_name=store.get('store_name'), store_id=store.objectId ) message.update_locally(postDict, False) # check if attach offer is selected if 'attach_offer' in postDict: # message has an offer - extract it from the post # post data ensuring proper datetime format d = parser.parse(postDict['date_offer_expiration']) d = make_aware_to_utc( d, SESSION.get_store_timezone(request.session)) message.set('date_offer_expiration', d) message.set('message_type', OFFER) else: # make sure to delete offer information in the case # that attach offer is not checked but the form # submitted still contained offer information message.set('offer_title', None) message.set('date_offer_expiration', None) message.set('message_type', BASIC) # actually create the message to Parse message.create() # put the message in the template context for rendering data['message'] = message # add to the store's relation store.add_relation("SentMessages_", [message.objectId]) # prepare the parameters for the cloud call params = { "store_id": store.objectId, "store_name": store.get('store_name'), "subject": message.get('subject'), "message_id": message.objectId, "filter": message.filter, } # process the filter option if message.filter == "idle": # pass in the correct idle_date which is today # minus the days specified by idle_latency idle_days = postDict['idle_latency'] d = timezone.now() + relativedelta(days=\ -1*int(idle_days)) params.update({"idle_date": d.isoformat()}) elif message.filter == "most_loyal": # pass in the number of patrons params.update({"num_patrons": postDict['num_patrons']}) # update store and message_count in session cache request.session['message_count'] = message_count request.session['store'] = store # save session- cloud_call may take a while! request.session.save() # make the cloud call res = cloud_call("retailer_message", params) if "error" not in res and res.get("result"): message.set("receiver_count", res.get("result").get("receiver_count")) # notify other tabs and windows that are logged into # this store about the new message sent. payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "newMessage": message.jsonify() } comet_receive(store.objectId, payload) # Note that the new message is saved in comet_receive # make sure we have the latest session to save! request.session.clear() request.session.update( SessionStore(request.session.session_key)) return HttpResponseRedirect(message.get_absolute_url()) elif 'num_patrons' in form.errors: # form is invalid due to the number of patrons input # for most_loyal filter data['error'] = "Number of customers must be a "+\ "whole number and greater than 0." else: # form has some errors data['error'] = "The form you submitted has errors." else: # check if the incoming request is for an account upgrade if request.GET.get("do_upgrade"): # flag the upgrade view request.session["from_limit_reached"] = True # redirect to upgrade account return HttpResponseRedirect(reverse("subscription_update") +\ "?do_upgrade=1") if message_id in (0, '0'): # this is a new message so just instantiate a new form form = MessageForm() else: # this is an existing message that the user wants to view # inserting this success and error message into the template # should be done in a cleaner way - this was done by the # first guy. I just didn't bother changing it. if request.GET.get("error"): data['error'] = request.GET.get("error") if request.GET.get("success"): data['success'] = request.GET.get("success") # get from the messages_sent_list in session cache messages_sent_list = SESSION.get_messages_sent_list(\ request.session) for m in messages_sent_list: if m.objectId == message_id: data['message'] = m if data['message']: # message is found so fill up the form with its data form = MessageForm(data['message'].__dict__.copy()) else: # message not found so just instantiate a new form form = MessageForm() # update store session cache request.session['store'] = store # inject the form in the template context for rendering data['form'] = form return render(request, 'manage/message_edit.djhtml', data)
def feedback_reply(request, feedback_id): """ Render the feedback reply template. """ account = request.session['account'] store = SESSION.get_store(request.session) # data to be passed in the templace context data = { 'messages_nav': True, 'from_address': store.get("store_name"), } # get from the messages_received_list in session cache messages_received_list = SESSION.get_messages_received_list(\ request.session) i_remove, feedback = 0, None for ind, m in enumerate(messages_received_list): if m.objectId == feedback_id: feedback = m i_remove = ind break if not feedback: # feedack not found - redirect to messages page with error message return redirect(reverse('messages_index')+ "?%s" %\ urllib.urlencode({'error': 'Feedback not found.'})) if request.method == 'POST': # user submitted reply form body = request.POST.get('body') if body is not None: # strip the body so that it doesn't have trailing or # leading whitespaces body = body.strip() else: body = "" data['body'] = body if len(body) == 0: # body cannot be empty data['error'] = 'Please enter a message.' elif len(body) > 750: # body cannot exceed 750 cahracters data['error'] = 'Body must be less than 750 characters.' elif feedback.get('Reply'): # double check if feedback already has a reply # should not go here unless it is a hacker return redirect(reverse('messages_index')+ "?%s" %\ urllib.urlencode({'error':\ 'Feedback has already been replied to.'})) else: # all valid - this method of validation is dirty and not # the way to do it in Django. Use a form instead. # I just got lazy here. # create the Parse Message object msg = Message.objects().create(message_type=\ FEEDBACK, sender_name=store.get('store_name'), store_id=store.objectId, body=body) # add the created reply to the store's sent messages relation store.add_relation("SentMessages_", [msg.objectId]) # set feedback Reply pointer to message and update it feedback.set('Reply', msg.objectId) feedback.update() # store the updated feedback messages_received_list.pop(i_remove) messages_received_list.insert(i_remove, feedback) request.session['messages_received_list'] =\ messages_received_list # save the session now! cloud_call may take a bit! request.session.save() # make the cloud call cloud_call( "retailer_message", { "store_id": store.objectId, "store_name": store.get('store_name'), "message_id": feedback.objectId, "filter": 'one', "patron_id": feedback.get('patron_id'), "feedback_reply_body": body, }) # notify other tabs/browsers logged into the same store # about the newly created message. comet_receive( store.objectId, { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "newMessage": feedback.jsonify() }) # make sure we have the latest session to save! request.session.clear() request.session.update(SessionStore(request.session.session_key)) return redirect(reverse('feedback_details', args=(feedback.objectId,)) + "?%s" %\ urllib.urlencode({'success':'Reply has been sent.'})) else: # user navigated to this page if feedback.get("Reply"): # if the user manually tweaks the url, then s/he might be # able to reply to a feedback that already has a reply. return redirect(reverse('feedback_details', args=(feedback.objectId,)) + "?%s" %\ urllib.urlencode({'error':'Cannot reply more than once.'})) # update store session cache request.session['store'] = store data['feedback'] = feedback # store the updated feedback messages_received_list.pop(i_remove) messages_received_list.insert(i_remove, feedback) request.session['messages_received_list'] =\ messages_received_list return render(request, 'manage/feedback_reply.djhtml', data)
def update_subscription(request): """ This view is also used for explicit upgrades. """ do_upgrade = request.GET.get("do_upgrade") is not None if do_upgrade: data = {'account_nav': True, 'upgrade': True} else: data = {'account_nav': True, 'update': True} store = SESSION.get_store(request.session) subscription = SESSION.get_subscription(request.session) if request.method == 'POST': form = SubscriptionForm(request.POST) form.subscription = subscription # to validate cc_number all_forms_valid = form.is_valid() if all_forms_valid: # upgrade account if date_passed_user_limit is on # should fetch the most up-to-date subscription first subscription = Subscription.objects().get(objectId=\ subscription.objectId) upgraded = False if subscription.date_passed_user_limit or do_upgrade: level = subscription.get("subscriptionType") if level == 0: subscription.set("subscriptionType", 1) subscription.date_passed_user_limit = None upgraded = True elif level == 1: subscription.date_passed_user_limit = None subscription.set("subscriptionType", 2) upgraded = True # subscription.update() called in store_cc subscription.update_locally(request.POST.dict(), False) d = datetime(int(request.POST['date_cc_expiration_year']), int(request.POST['date_cc_expiration_month']), 1) subscription.set( "date_cc_expiration", make_aware_to_utc(d, SESSION.get_store_timezone(request.session))) def invalid_card(): # add some asterisk to cc_number if form.initial.get("cc_number"): form.initial['cc_number'] = "*" * 12 +\ form.initial.get('cc_number')[-4:] errs = form._errors.setdefault(\ "cc_number", ErrorList()) errs.append("Invalid credit " +\ "card. Please make sure that you provide " +\ "correct credit card information and that you " +\ "have sufficient funds, then try again.") data['form'] = form return render(request, 'manage/subscription_update.djhtml', data) res = True # only store_cc if it is a digit (new) if str(form.data['cc_number']).isdigit(): res = subscription.store_cc(form.data['cc_number'], form.data['cc_cvv'], False) if not res: return invalid_card() # if monthly billing failed if subscription.date_charge_failed: sub_cost = sub_type[subscription.get(\ "subscriptionType")]["monthly_cost"] invoice = subscription.charge_cc(\ sub_cost, EMAIL_MONTHLY_SUBJECT, MONTHLY) if invoice: subscription.date_last_billed =\ subscription.date_last_billed +\ relativedelta(days=30) subscription.date_charge_failed = None subscription.update() send_email_receipt_monthly_success(\ request.session['account'], store, subscription, invoice) else: return invalid_card() ########### if upgraded: max_users = sub_type[\ subscription.subscriptionType]["max_users"] if max_users == UNLIMITED: max_users = "Unlimited" package = { "sub_type": sub_type[\ subscription.subscriptionType-1]["name"], "new_sub_type": sub_type[\ subscription.subscriptionType]["name"], "new_sub_type_cost": sub_type[\ subscription.subscriptionType]["monthly_cost"], "new_max_patronStore_count": max_users, } send_email_account_upgrade(request.session['account'], store, package) # Important that this is last since invalid_card may be # returned! subscription.update() # update the session cache request.session['store'] = store request.session['subscription'] = subscription # notify other dashboards of these changes payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSubscription": subscription.jsonify() } comet_receive(store.objectId, payload) # if coming from the message edit limit reached if do_upgrade: if request.session.get('from_limit_reached') and\ request.session.get('message_b4_upgrade'): # redirect back to message_edit view to process return redirect(reverse('message_edit', args=(0,)) + "?%s" %\ urllib.urlencode({'send_message': '1'})) if do_upgrade: return redirect(reverse('store_index')+ "?%s" %\ urllib.urlencode({'success':\ 'Your subscription has been upgraded.'})) else: return redirect(reverse('store_index')+ "?%s" %\ urllib.urlencode({'success':\ 'Your subscription has been updated.'})) else: form = SubscriptionForm() form.initial = subscription.__dict__.copy() # add some asterisk to cc_number if form.initial.get("cc_number"): form.initial['cc_number'] = "*" * 12 +\ form.initial.get('cc_number')[-4:] if do_upgrade: from_limit_reached =\ request.session.get("from_limit_reached") if from_limit_reached: data['from_limit_reached'] = from_limit_reached # update the session cache request.session['store'] = store request.session['subscription'] = subscription data['form'] = form return render(request, 'manage/subscription_update.djhtml', data)
def handle(self, *args, **options): """ get all of the subscriptions whose stores are active & who have been last billed 30+ days ago. IMPORTANT! This includes accounts of type FREE, which are not charged or included in the email notifications """ # for logging when ran by CRON print "Running monthly_billing: " + str(timezone.now()) date_30_ago = timezone.now() + relativedelta(days=-30) date_now = timezone.now() sub_count = pointer_query("Subscription", {"date_last_billed__lte":date_30_ago}, "Store", "Store", {"active":True}, count=True) asiss = [] # get 500 subscriptions at a time LIMIT, skip = 500, 0 while sub_count > 0: for each in pointer_query("Subscription", {"date_last_billed__lte":date_30_ago}, "Store", "Store", {"active":True}, limit=LIMIT, skip=skip, order="createdAt")['results']: subscription = Subscription(**each) sub_cost = sub_type[subscription.get(\ "subscriptionType")]["monthly_cost"] store = None # prevent UnboundLocalError update_store = False if sub_cost == 0: # FREE account subscription.date_last_billed =\ subscription.date_last_billed +\ relativedelta(days=30) subscription.update() else: # PAID account account = Account.objects().get(Store=\ subscription.get("Store"), include="Store") store = account.get("store") invoice = subscription.charge_cc(\ sub_cost, "Repunch Inc. Recurring " +\ "monthly subscription charge", MONTHLY) send_user_email = True if invoice: subscription.date_last_billed =\ subscription.date_last_billed +\ relativedelta(days=30) subscription.date_charge_failed = None subscription.update() else: subscription.date_charge_failed = date_now # force entering new credit card! subscription.cc_number = None subscription.date_cc_expiration = None subscription.update() # notify user via email- payment is done via # dashboard to also validate cc realtime # 1st day time range day0_end = date_30_ago.replace() day0_start = day0_end + relativedelta(hours=-24) # 4th day time range day4_end = date_30_ago + relativedelta(days=-4) day4_start = day4_end + relativedelta(hours=-24) # 8th day time range day8_end = date_30_ago + relativedelta(days=-8) day8_start = day8_end + relativedelta(hours=-24) # 14th day time range day14_end = date_30_ago + relativedelta(days=-14) day14_start = day14_end + relativedelta(hours=-24) # only send email after 1, 4, and 8 days last_billed = subscription.date_last_billed if (last_billed >= day0_start and\ last_billed <= day0_end) or\ (last_billed >= day4_start and\ last_billed <= day4_end) or\ (last_billed >= day8_start and\ last_billed <= day8_end): send_email_receipt_monthly_failed(account, store, subscription) elif last_billed >= day14_start and\ last_billed <= day14_end: # send final notification send_email_receipt_monthly_failed(account, store, subscription, account_disabled=True) else: send_user_email = False # make sure that the store is deactivated after the 14th day if last_billed <= day14_end: store.active = False store.update() update_store = True # do not send email after account deactivation if send_user_email: asiss.append((account, store, invoice, subscription)) # update the logged in users' subscription and store payload = { COMET_RECEIVE_KEY_NAME: COMET_RECEIVE_KEY, "updatedSubscription":subscription.jsonify() } if store and update_store: payload.update({"updatedStore":store.jsonify()}) comet_receive(subscription.Store, payload) # end of while loop sub_count -= LIMIT skip += LIMIT # everything is done - send the emails send_email_receipt_monthly_batch(asiss)