def register_rand_employee(store_id): name = "Employee" + str(randint(0, 9999)) username = name + "@repunch.com" store = Store.objects().get(objectId=store_id, include="Settings") return register_employee(name, name, username, username, "repunch7575", store.settings.retailer_pin)
def register_rand_employee(store_id): name = "Employee" + str(randint(0,9999)) username = name+"@repunch.com" store = Store.objects().get(objectId=store_id, include="Settings") return register_employee(name, name, username, username, "repunch7575", store.settings.retailer_pin)
def activate(request): """ Handles account activation from email form sent at user sign up. """ if request.method == "POST": store_id = request.POST['store_id'] act_id = request.POST['act_id'] act = StoreActivate.objects.filter(id=act_id, store_id=store_id) if len(act) > 0: act[0].delete() store = Store.objects().get(objectId=store_id) if store: store.active = True store.update() return HttpResponse(store.get(\ "store_name").capitalize() +\ " has been activated.") else: return HttpResponse("Account/store not found.") else: return HttpResponse("This form has already "+\ "been used.") return HttpResponse("Bad request")
def store_avatar_to_thumbnail(): """ Created column thumbnail_image in Store. This just copies the store_avatar in Store to thumbnail_image. The store_avatar column is kept for backwards compatibility. """ for i, store in enumerate(Store.objects().filter(limit=999)): store.thumbnail_image = store.store_avatar store.update() print "Updated Store #" + str(i) + ": " + store.objectId
def supported_chain_stores(): """ Created the StoreLocation class, which contains Store location information. A Store may have multiple StoreLocations. Punches also now have store_location_id. This assigns a new StoreLocation to the store_locations aray of pointers of each store. All existing Punches are also assigned the newly created StoreLocation's id. All existing RedeemRewards are also assigned the newly created StoreLocation's id. WARNING! Assumes this assumes that # Stores < 1000 and that each store has less than 1000 punches/redeemRewards in their respective relations. """ for i, store in enumerate(Store.objects().filter(limit=999)): if store.store_locations: # just in case we re-run this script store_location = store.store_locations[0] else: # empty or None store_location = StoreLocation.objects().create(**{ "street": store.street, "city": store.city, "state": store.state, "zip": store.zip, "country": store.country, "phone_number": store.phone_number, "store_timezone": store.store_timezone, "neighborhood": store.neighborhood, "coordinates": store.coordinates, "hours": store.hours, "Store": store.objectId, }) store.store_locations = [store_location] store.update() # update all the punches for this store punches = store.get("punches", order="createdAt", limit=1000) if punches: for punch in punches: if not punch.store_location_id: punch.store_location_id = store_location.objectId punch.update() # update all the redeemRewards for this store redeem_rewards = store.get("redeemRewards", order="createdAt", limit=1000) if redeem_rewards: for rr in redeem_rewards: if not rr.store_location_id: rr.store_location_id = store_location.objectId rr.update() print "Updated Store #" + str(i) + ": " + store.objectId
def get_store_locations(session): """ limit of 100 store locations for now """ if "store_locations" not in session: store = get_store(session) store_tmp = Store.objects().get(objectId=store.objectId, include="store_locations") store_locations = {} for sl in store_tmp.store_locations: store_locations[sl.objectId] = sl session['store_locations'] = store_locations return session['store_locations']
def resize_thumbnails(self): for i, store in enumerate(Store.objects().filter(limit=999)): old_thumbnail = store.thumbnail_image self.get_store_location_image(0, store.thumbnail_image_url) thumbnail = create_png(TMP_IMG_PATH, IMAGE_THUMBNAIL_SIZE) while "error" in thumbnail: print "Retrying create_png" thumbnail = create_png(TMP_IMG_PATH, IMAGE_THUMBNAIL_SIZE) store.thumbnail_image = thumbnail.get("name") store.store_avatar = store.thumbnail_image store.update() # delete thumbnail if exist if old_thumbnail: delete_file(old_thumbnail, "image/png") print "Updated Store #%d: %s" % (i, store.objectId)
def sign_up(request): """ Creates User, store, subscription, and settings objects. """ # renders the signup page on GET and returns a json object on POST. data = {'sign_up_nav': True} if request.method == 'POST': # this conversion to a regular dictionay is important postDict = request.POST.dict() from_associated_account = False # check if this post is from the associated account dialog # if it is then skip form validations aaf_nonce_id = postDict.get('aaf-nonce') aaf_account_id = postDict.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 # some keys are repeated so must catch this at init store_form = StoreSignUpForm(request.POST) store_location_form = StoreLocationForm(request.POST) account_form = AccountSignUpForm(request.POST) cats = postDict.get("categories") category_names = None if cats and len(cats) > 0: category_names = cats.split("|")[:-1] # make sure that there are only up to 2 categories while len(category_names) > 2: category_names.pop() data["category_names"] = category_names if not from_associated_account: all_forms_valid = store_form.is_valid() and\ store_location_form.is_valid() and account_form.is_valid() else: all_forms_valid = True if all_forms_valid: # 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 hasattr(account_form, "associated_account"): aa = account_form.associated_account 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") ######################################################### # create store store = Store(**postDict) # set defaults for these guys to prevent # ParseObjects from making parse calls repeatedly store.punches_facebook = 1 store.set("rewards", []) store.set("categories", []) if category_names: for name in category_names: alias = Category.objects.filter(name__iexact=name) if len(alias) > 0: store.categories.append({ "alias": alias[0].alias, "name": name }) # create settings settings = Settings(Store=store.objectId) store.set('settings', settings) # create account if not from_associated_account: account = Account(**postDict) # username = email # we should be doing this in the form but ehh account.set("username", postDict['email'].strip().lower()) account.set("email", postDict['email'].strip().lower()) account.set_password(postDict.get('password')) else: account =\ Account.objects().get(objectId=aaf_account_id) account.set("store", store) # create subscription subscription = Subscription() subscription.subscriptionType = 0 subscription.date_last_billed = timezone.now() subscription.create() # create settings settings.create() # create store store.Settings = settings.objectId store.Subscription = subscription.objectId store.create() # add the pointer to the created store settings.Store = store.objectId settings.update() subscription.Store = store.objectId subscription.update() # create the store location store_location = StoreLocation(**postDict) # format the phone number store_location.store_timezone =\ rputils.get_timezone(postDict.get("zip")).zone store_location.set("hours", []) # coordinates and neighborhood # the call to get map data is actually also in the clean full_address = " ".join(\ store_location.get_full_address().split(", ")) map_data = rputils.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"))) store_location.phone_number =\ format_phone_number(postDict["phone_number"]) store_location.Store = store.objectId store_location.create() # add the StoreLocation to the relation store.store_locations = [store_location] store.update() # create account account.Store = store.objectId if not from_associated_account: account.create() else: account.update() # create the store ACL with the account having r/w access store.ACL = { "*": { "read": True, "write": True }, account.objectId: { "read": True, "write": True }, } store.owner_id = account.objectId store.update() # note that username has been fed the email # this shouldn't change anything though shouldn't matter # need to put username and pass in request postDict['username'] = account.username postDict['password'] = account.password # send matt and new user a pretty email. send_email_signup(account) # auto login user_login = login(request, postDict, no_recaptcha=True) if user_login != None: data = {"code": -1} # response to signup.js - not login returns # 0 - Associated account already exists # 2 - subscription is not active # 3 - success (login now) if type(user_login) is int: # subscription not active data['code'] = 2 else: # required for datetime awareness! rputils.set_timezone(request, tz) data['code'] = 3 return HttpResponse(json.dumps(data), content_type="application/json") else: store_form = StoreSignUpForm() store_location_form = StoreLocationForm() account_form = AccountSignUpForm() data['store_form'] = store_form data['store_location_form'] = store_location_form data['account_form'] = account_form return render(request, 'public/signup.djhtml', data)
def create_random_stores(self, amount): for i in range(amount): print "Creating store %s" % (str(i), ) # create the store street, city, state, zip, country, phone_number =\ self.addrs[i].split(", ") first_name, last_name = self.owners[i].split(" ") neighborhood = self.neighborhoods[i] store_name = self.stores[i] store_i = STORE.copy() store_location_i = STORE_LOCATION.copy() # create the thumbnaiil and cover (same image different size) self.get_store_location_image(i) thumbnail = create_png(TMP_IMG_PATH, IMAGE_THUMBNAIL_SIZE) while "error" in image: print "Retrying create_png" thumbnail = create_png(TMP_IMG_PATH) cover = create_png(TMP_IMG_PATH) while "error" in cover: print "Retrying create_png" cover = create_png(TMP_IMG_PATH) store_i.update({ "store_name": store_name, "first_name": first_name, "last_name": last_name, "thumbnail_image": thumbnail.get("name"), "cover_image": cover.get("name"), }) store_location_i.update({ "street": street, "city": city, "state": state, "zip": zip, "neighborhood": neighborhood, "country": country, "phone_number": phone_number, "coordinates": self.get_random_coordinates(), }) # create the store store = Store.objects().create(**store_i) # create the store location store_location = StoreLocation(**store_location_i) store_location.Store = store.objectId store_location.update() # create the settings settings = Settings.objects().create(Store=store.objectId) # create the subscription subscription =\ Subscription.objects().create(Store=store.objectId, date_last_billed=timezone.now()) # create the user email = first_name + str(randint(0, 99)) + USER_EMAIL_POSTFIX email = email.lower() acc = Account.objects().create(\ username=email, email=email, password=USER_PASSWORD, Store=store.objectId) if not acc.objectId: raise Exception("Account creation failed.") # link the store store.Settings = settings.objectId store.Subscription = subscription.objectId store.owner_id = acc.objectId store.ACL[acc.objectId] = {"read": True, "write": True} store.store_locations = [store_location] store.update()
def processCometReceivedDict(session, postDict): employees_pending_list =\ SESSION.get_employees_pending_list(session) employees_approved_list =\ SESSION.get_employees_approved_list(session) messages_received_list =\ SESSION.get_messages_received_list(session) redemptions_pending =\ SESSION.get_redemptions_pending(session) redemptions_past =\ SESSION.get_redemptions_past(session) ############################################################# # FEEDBACKS_UNREAD ################################## newFeedback = postDict.get('newFeedback') if newFeedback: messages_received_ids =\ [ fb.objectId for fb in messages_received_list ] m = Message(**newFeedback) if m.objectId not in messages_received_ids: messages_received_list.insert(0, m) session['messages_received_list'] =\ messages_received_list ############################################################# # FEEDBACK DELETED ################################## deletedFeedback = postDict.get("deletedFeedback") if deletedFeedback: fb = Message(**deletedFeedback) for i, mro in enumerate(messages_received_list): if fb.objectId == mro.objectId: messages_received_list.pop(i) break session['messages_received_list'] =\ messages_received_list ############################################################# # MESSAGE SENT ################################## # need to check if this new message is an original message # or a reply to a feedback (the message sent by the patron)! # also may increment the message count! newMessage = postDict.get("newMessage") if newMessage: messages_received_ids =\ [ fb.objectId for fb in messages_received_list ] messages_sent_list =\ SESSION.get_messages_sent_list(session) messages_sent_ids =\ [ msg.objectId for msg in messages_sent_list ] m = Message(**newMessage) if m.objectId not in messages_sent_ids and\ m.message_type != FEEDBACK: messages_sent_list.insert(0, m) if 'message_count' in session: session['message_count'] =\ int(session['message_count']) + 1 # update an existing feedback if m.objectId in messages_received_ids and\ m.message_type == FEEDBACK: for i, mrl in enumerate(messages_received_list): if mrl.objectId == m.objectId: messages_received_list.pop(i) messages_received_list.insert(i, m) break session['messages_received_list'] =\ messages_received_list session['messages_sent_list'] = messages_sent_list ############################################################# # EMPLOYEES_PENDING ################################## # must also check if employee is already approved! pendingEmployee = postDict.get("pendingEmployee") if pendingEmployee: employees_approved_ids =\ [ emp.objectId for emp in employees_approved_list ] employees_pending_ids =\ [ emp.objectId for emp in employees_pending_list ] e = Employee(**pendingEmployee) if e.objectId not in employees_pending_ids and\ e.objectId not in employees_approved_ids: employees_pending_list.insert(0, e) session['employees_pending_list'] =\ employees_pending_list ############################################################# # EMPLOYEES APPROVED (pending to approved) ################# approvedEmployee = postDict.get("approvedEmployee") if approvedEmployee: emp = Employee(**approvedEmployee) # first check if the employee is in the pending list # if not then check if it is already approved for i, emp_pending in\ enumerate(employees_pending_list): if emp.objectId == emp_pending.objectId: emp = employees_pending_list.pop(i) emp.status = APPROVED employees_approved_list.insert(0, emp) break session['employees_pending_list'] =\ employees_pending_list session['employees_approved_list'] =\ employees_approved_list ############################################################# # EMPLOYEES NEW (straight to approved) ################# newEmployee = postDict.get("newEmployee") if newEmployee: employees_approved_ids =\ [ emp.objectId for emp in employees_approved_list ] emp = Employee(**newEmployee) if emp.objectId not in employees_approved_ids: employees_approved_list.insert(0, emp) session['employees_approved_list'] =\ employees_approved_list ############################################################# # EMPLOYEES DELETED/DENIED/REJECTED (pending/approved to pop)! deletedEmployee = postDict.get("deletedEmployee") if deletedEmployee: emp = Employee(**deletedEmployee) # check in approved emps for i, cop in enumerate(employees_approved_list): if cop.objectId == emp.objectId: employees_approved_list.pop(i) break # check in pending emps for i, cop in enumerate(employees_pending_list): if cop.objectId == emp.objectId: employees_pending_list.pop(i) break session['employees_approved_list'] =\ employees_approved_list session['employees_pending_list'] =\ employees_pending_list ############################################################# # EMPLOYEE UPDATED PUNCHES updatedEmployeePunch = postDict.get("updatedEmployeePunch") if updatedEmployeePunch: u_emp = Employee(**updatedEmployeePunch) for emp in employees_approved_list: if u_emp.objectId == emp.objectId: emp.set("lifetime_punches", u_emp.lifetime_punches) break session['employees_approved_list'] =\ employees_approved_list ############################################################# # REDEMPTIONS PENDING ### Only added to cache if it has the store_location_id as ### active_store_location_id pendingRedemption = postDict.get("pendingRedemption") if pendingRedemption: rr = RedeemReward(**pendingRedemption) # store_location_id can be null for backwards compat if not rr.store_location_id or rr.store_location_id ==\ session.get('active_store_location_id'): redemptions_pending_ids =\ [ red.objectId for red in redemptions_pending ] redemptions_past_ids =\ [ red.objectId for red in redemptions_past ] # need to check here if the redemption is new because # the dashboard that validated it will also receive # the validated redemption back. if rr.objectId not in redemptions_past_ids and\ rr.objectId not in redemptions_pending_ids: redemptions_pending.insert(0, rr) session['redemptions_pending'] =\ redemptions_pending ############################################################# # REDEMPTIONS APPROVED (pending to history) # Save cpu by skipping those that do not have the same # store_location_id as active_store_location_id approvedRedemption = postDict.get("approvedRedemption") if approvedRedemption: redemp = RedeemReward(**approvedRedemption) # store_location_id can be null for backwards compat if not redemp.store_location_id or redemp.store_location_id ==\ session.get('active_store_location_id'): # check if redemp is still in pending for i, redem in enumerate(redemptions_pending): if redem.objectId == redemp.objectId: r = redemptions_pending.pop(i) r.is_redeemed = True r.updatedAt = redemp.updatedAt redemptions_past.insert(0, r) break # if not then check if it is in the history already # the above shouldn't happen! session['redemptions_pending'] =\ redemptions_pending session['redemptions_past'] =\ redemptions_past ############################################################# # REDEMPTIONS DELETED ############################## # remove from pending (should not be in history!) # Save cpu by skipping those that do not have the same # store_location_id as active_store_location_id deletedRedemption = postDict.get("deletedRedemption") if deletedRedemption: redemp = RedeemReward(**deletedRedemption) # store_location_id can be null for backwards compat if not redemp.store_location_id or redemp.store_location_id ==\ session.get('active_store_location_id'): # check if redemp is still in pending for i, redem in enumerate(redemptions_pending): if redem.objectId == redemp.objectId: redemptions_pending.pop(i) break session['redemptions_pending'] =\ redemptions_pending ############################################################# # STORE UPDATED ############################## updatedStore = postDict.get("updatedStore") if updatedStore: store = Store(**updatedStore) # have to add the image url manually store.thumbnail_image_url = updatedStore.get("thumbnail_image_url") store.cover_image_url = updatedStore.get("cover_image_url") # below here for backwards compat store.store_avatar_url = store.thumbnail_image_url session['store'] = store updatedStoreThumbnailName = postDict.get("updatedStoreThumbnailName") if updatedStoreThumbnailName: store = session['store'] store.thumbnail_image = updatedStoreThumbnailName store.thumbnail_image_url = postDict.get("updatedStoreThumbnailUrl") # below here for backwards compat store.store_avatar = store.thumbnail_image store.store_avatar_url = store.thumbnail_image_url session['store'] = store updatedStoreCoverName = postDict.get("updatedStoreCoverName") if updatedStoreCoverName: store = session['store'] store.cover_image = updatedStoreCoverName store.cover_image_url = postDict.get("updatedStoreCoverUrl") session['store'] = store # this is in the settings tab in the dashboard but the field # is in the Store class updatedPunchesFacebook_int =\ postDict.get("updatedPunchesFacebook_int") if updatedPunchesFacebook_int: store = session['store'] store.punches_facebook = int(updatedPunchesFacebook_int) session['store'] = store ############################################################# # STORE LOCATION UPDATED ############################## ### Note that this is also being used to insert new StoreLocations updatedStoreLocation = postDict.get("updatedStoreLocation") if updatedStoreLocation: store_location = StoreLocation(**updatedStoreLocation) session['store_locations'][store_location.objectId] =\ store_location try: # also update the store_timezone session['store_timezone'] =\ pytz.timezone(store_location.get('store_timezone')) except Exception: # assign a default timezone session['store_timezone'] =\ pytz.timezone(TIME_ZONE) ############################################################# # ACCOUNT UPDATED ############################## updatedAccount = postDict.get("updatedAccount") if updatedAccount: updatedAccountObject = Account(**updatedAccount) # need to make sure that these are the same accounts! if session['account'].objectId ==\ updatedAccountObject.objectId: session['account'] = updatedAccountObject ############################################################# # SUBSCRIPTION UPDATED ############################## updatedSubscription =\ postDict.get("updatedSubscription") if updatedSubscription: subscription = Subscription(**updatedSubscription) store = session["store"] store.set('subscription', subscription) store.set('Subscription', subscription.objectId) session['subscription'] = subscription session['store'] = store ############################################################# # SETTINGS UPDATED ############################## updatedSettings = postDict.get("updatedSettings") if updatedSettings: settings = Settings(**updatedSettings) store = session["store"] store.set('settings', settings) store.set("Settings", settings.objectId) session['settings'] = settings session['store'] = store ############################################################# # REWARDS NEW ############################## newReward = postDict.get("newReward") if newReward: store = session['store'] rewards = store.get("rewards") rewards_ids = [ r['reward_id'] for r in rewards ] if newReward['reward_id'] not in rewards_ids: rewards.append(newReward) store.rewards = rewards session['store'] = store ############################################################# # REWARDS UPDATED ############################## updatedReward = postDict.get('updatedReward') if updatedReward: store = session['store'] mod_rewards = store.get("rewards") for i, mreward in enumerate(mod_rewards): # [{"reward_name":"Free bottle of wine", # "description":"Must be under $25 in value", # "punches":10,"redemption_count":0,reward_id:0},] if updatedReward['reward_id']==mreward['reward_id']: if updatedReward.has_key("redemption_count"): mod_rewards[i]['redemption_count'] =\ updatedReward['redemption_count'] if updatedReward.has_key("reward_name"): mod_rewards[i]['reward_name'] =\ updatedReward['reward_name'] if updatedReward.has_key("punches"): mod_rewards[i]['punches'] =\ updatedReward['punches'] if updatedReward.has_key("description"): mod_rewards[i]['description'] =\ updatedReward['description'] break store.rewards = mod_rewards session['store'] = store ############################################################# # REWARDS DELETED ############################## deletedReward = postDict.get("deletedReward") if deletedReward: store = session['store'] rewards = store.get("rewards") rewards_ids = [ r['reward_id'] for r in rewards ] if deletedReward['reward_id'] in rewards_ids: for i, r in enumerate(rewards): if r['reward_id'] == deletedReward['reward_id']: rewards.pop(i) break store.rewards = rewards session['store'] = store ############################################################# # PATRONSTORE_COUNT ################################## patronStore_int = postDict.get('patronStore_int') if patronStore_int: patronStore_int = int(patronStore_int) session['patronStore_count'] = patronStore_int
def sign_up(request): """ Creates User, store, subscription, and settings objects. """ # renders the signup page on GET and returns a json object on POST. data = {'sign_up_nav': True} if request.method == 'POST': # this conversion to a regular dictionay is important postDict = request.POST.dict() from_associated_account = False # check if this post is from the associated account dialog # if it is then skip form validations aaf_nonce_id = postDict.get('aaf-nonce') aaf_account_id = postDict.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 # some keys are repeated so must catch this at init store_form = StoreSignUpForm(request.POST) store_location_form = StoreLocationForm(request.POST) account_form = AccountSignUpForm(request.POST) cats = postDict.get("categories") category_names = None if cats and len(cats) > 0: category_names = cats.split("|")[:-1] # make sure that there are only up to 2 categories while len(category_names) > 2: category_names.pop() data["category_names"] = category_names if not from_associated_account: all_forms_valid = store_form.is_valid() and\ store_location_form.is_valid() and account_form.is_valid() else: all_forms_valid = True if all_forms_valid: # 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 hasattr(account_form, "associated_account"): aa = account_form.associated_account 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") ######################################################### # create store store = Store(**postDict) # set defaults for these guys to prevent # ParseObjects from making parse calls repeatedly store.punches_facebook = 1 store.set("rewards", []) store.set("categories", []) if category_names: for name in category_names: alias = Category.objects.filter(name__iexact=name) if len(alias) > 0: store.categories.append({ "alias":alias[0].alias, "name":name }) # create settings settings = Settings(Store=store.objectId) store.set('settings', settings) # create account if not from_associated_account: account = Account(**postDict) # username = email # we should be doing this in the form but ehh account.set("username", postDict['email'].strip().lower()) account.set("email", postDict['email'].strip().lower()) account.set_password(postDict.get('password')) else: account =\ Account.objects().get(objectId=aaf_account_id) account.set("store", store) # create subscription subscription = Subscription() subscription.subscriptionType = 0 subscription.date_last_billed = timezone.now() subscription.create() # create settings settings.create() # create store store.Settings = settings.objectId store.Subscription = subscription.objectId store.create() # add the pointer to the created store settings.Store = store.objectId settings.update() subscription.Store = store.objectId subscription.update() # create the store location store_location = StoreLocation(**postDict) # format the phone number store_location.store_timezone =\ rputils.get_timezone(postDict.get("zip")).zone store_location.set("hours", []) # coordinates and neighborhood # the call to get map data is actually also in the clean full_address = " ".join(\ store_location.get_full_address().split(", ")) map_data = rputils.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"))) store_location.phone_number =\ format_phone_number(postDict["phone_number"]) store_location.Store = store.objectId store_location.create() # add the StoreLocation to the relation store.store_locations = [store_location] store.update() # create account account.Store = store.objectId if not from_associated_account: account.create() else: account.update() # create the store ACL with the account having r/w access store.ACL = { "*": {"read": True, "write": True}, account.objectId: {"read": True, "write": True}, } store.owner_id = account.objectId store.update() # note that username has been fed the email # this shouldn't change anything though shouldn't matter # need to put username and pass in request postDict['username'] = account.username postDict['password'] = account.password # send matt and new user a pretty email. send_email_signup(account) # auto login user_login = login(request, postDict, no_recaptcha=True) if user_login != None: data = {"code":-1} # response to signup.js - not login returns # 0 - Associated account already exists # 2 - subscription is not active # 3 - success (login now) if type(user_login) is int: # subscription not active data['code'] = 2 else: # required for datetime awareness! rputils.set_timezone(request, tz) data['code'] = 3 return HttpResponse(json.dumps(data), content_type="application/json") else: store_form = StoreSignUpForm() store_location_form = StoreLocationForm() account_form = AccountSignUpForm() data['store_form'] = store_form data['store_location_form'] = store_location_form data['account_form'] = account_form return render(request, 'public/signup.djhtml', data)
def create_random_stores(self, amount): for i in range(amount): print "Creating store %s" % (str(i),) # create the store street, city, state, zip, country, phone_number =\ self.addrs[i].split(", ") first_name, last_name = self.owners[i].split(" ") neighborhood = self.neighborhoods[i] store_name = self.stores[i] store_i = STORE.copy() store_location_i = STORE_LOCATION.copy() # create the thumbnaiil and cover (same image different size) self.get_store_location_image(i) thumbnail = create_png(TMP_IMG_PATH, IMAGE_THUMBNAIL_SIZE) while "error" in image: print "Retrying create_png" thumbnail = create_png(TMP_IMG_PATH) cover = create_png(TMP_IMG_PATH) while "error" in cover: print "Retrying create_png" cover = create_png(TMP_IMG_PATH) store_i.update({ "store_name": store_name, "first_name": first_name, "last_name": last_name, "thumbnail_image": thumbnail.get("name"), "cover_image": cover.get("name"), }) store_location_i.update({ "street": street, "city": city, "state": state, "zip": zip, "neighborhood": neighborhood, "country": country, "phone_number": phone_number, "coordinates": self.get_random_coordinates(), }) # create the store store = Store.objects().create(**store_i) # create the store location store_location = StoreLocation(**store_location_i) store_location.Store = store.objectId store_location.update() # create the settings settings = Settings.objects().create(Store=store.objectId) # create the subscription subscription =\ Subscription.objects().create(Store=store.objectId, date_last_billed=timezone.now()) # create the user email = first_name+str(randint(0, 99))+USER_EMAIL_POSTFIX email = email.lower() acc = Account.objects().create(\ username=email, email=email, password=USER_PASSWORD, Store=store.objectId) if not acc.objectId: raise Exception("Account creation failed.") # link the store store.Settings = settings.objectId store.Subscription = subscription.objectId store.owner_id = acc.objectId store.ACL[acc.objectId] = {"read": True,"write": True} store.store_locations = [store_location] store.update()
def processCometReceivedDict(session, postDict): employees_pending_list =\ SESSION.get_employees_pending_list(session) employees_approved_list =\ SESSION.get_employees_approved_list(session) messages_received_list =\ SESSION.get_messages_received_list(session) redemptions_pending =\ SESSION.get_redemptions_pending(session) redemptions_past =\ SESSION.get_redemptions_past(session) ############################################################# # FEEDBACKS_UNREAD ################################## newFeedback = postDict.get('newFeedback') if newFeedback: messages_received_ids =\ [ fb.objectId for fb in messages_received_list ] m = Message(**newFeedback) if m.objectId not in messages_received_ids: messages_received_list.insert(0, m) session['messages_received_list'] =\ messages_received_list ############################################################# # FEEDBACK DELETED ################################## deletedFeedback = postDict.get("deletedFeedback") if deletedFeedback: fb = Message(**deletedFeedback) for i, mro in enumerate(messages_received_list): if fb.objectId == mro.objectId: messages_received_list.pop(i) break session['messages_received_list'] =\ messages_received_list ############################################################# # MESSAGE SENT ################################## # need to check if this new message is an original message # or a reply to a feedback (the message sent by the patron)! # also may increment the message count! newMessage = postDict.get("newMessage") if newMessage: messages_received_ids =\ [ fb.objectId for fb in messages_received_list ] messages_sent_list =\ SESSION.get_messages_sent_list(session) messages_sent_ids =\ [ msg.objectId for msg in messages_sent_list ] m = Message(**newMessage) if m.objectId not in messages_sent_ids and\ m.message_type != FEEDBACK: messages_sent_list.insert(0, m) if 'message_count' in session: session['message_count'] =\ int(session['message_count']) + 1 # update an existing feedback if m.objectId in messages_received_ids and\ m.message_type == FEEDBACK: for i, mrl in enumerate(messages_received_list): if mrl.objectId == m.objectId: messages_received_list.pop(i) messages_received_list.insert(i, m) break session['messages_received_list'] =\ messages_received_list session['messages_sent_list'] = messages_sent_list ############################################################# # EMPLOYEES_PENDING ################################## # must also check if employee is already approved! pendingEmployee = postDict.get("pendingEmployee") if pendingEmployee: employees_approved_ids =\ [ emp.objectId for emp in employees_approved_list ] employees_pending_ids =\ [ emp.objectId for emp in employees_pending_list ] e = Employee(**pendingEmployee) if e.objectId not in employees_pending_ids and\ e.objectId not in employees_approved_ids: employees_pending_list.insert(0, e) session['employees_pending_list'] =\ employees_pending_list ############################################################# # EMPLOYEES APPROVED (pending to approved) ################# approvedEmployee = postDict.get("approvedEmployee") if approvedEmployee: emp = Employee(**approvedEmployee) # first check if the employee is in the pending list # if not then check if it is already approved for i, emp_pending in\ enumerate(employees_pending_list): if emp.objectId == emp_pending.objectId: emp = employees_pending_list.pop(i) emp.status = APPROVED employees_approved_list.insert(0, emp) break session['employees_pending_list'] =\ employees_pending_list session['employees_approved_list'] =\ employees_approved_list ############################################################# # EMPLOYEES NEW (straight to approved) ################# newEmployee = postDict.get("newEmployee") if newEmployee: employees_approved_ids =\ [ emp.objectId for emp in employees_approved_list ] emp = Employee(**newEmployee) if emp.objectId not in employees_approved_ids: employees_approved_list.insert(0, emp) session['employees_approved_list'] =\ employees_approved_list ############################################################# # EMPLOYEES DELETED/DENIED/REJECTED (pending/approved to pop)! deletedEmployee = postDict.get("deletedEmployee") if deletedEmployee: emp = Employee(**deletedEmployee) # check in approved emps for i, cop in enumerate(employees_approved_list): if cop.objectId == emp.objectId: employees_approved_list.pop(i) break # check in pending emps for i, cop in enumerate(employees_pending_list): if cop.objectId == emp.objectId: employees_pending_list.pop(i) break session['employees_approved_list'] =\ employees_approved_list session['employees_pending_list'] =\ employees_pending_list ############################################################# # EMPLOYEE UPDATED PUNCHES updatedEmployeePunch = postDict.get("updatedEmployeePunch") if updatedEmployeePunch: u_emp = Employee(**updatedEmployeePunch) for emp in employees_approved_list: if u_emp.objectId == emp.objectId: emp.set("lifetime_punches", u_emp.lifetime_punches) break session['employees_approved_list'] =\ employees_approved_list ############################################################# # REDEMPTIONS PENDING ### Only added to cache if it has the store_location_id as ### active_store_location_id pendingRedemption = postDict.get("pendingRedemption") if pendingRedemption: rr = RedeemReward(**pendingRedemption) # store_location_id can be null for backwards compat if not rr.store_location_id or rr.store_location_id ==\ session.get('active_store_location_id'): redemptions_pending_ids =\ [ red.objectId for red in redemptions_pending ] redemptions_past_ids =\ [ red.objectId for red in redemptions_past ] # need to check here if the redemption is new because # the dashboard that validated it will also receive # the validated redemption back. if rr.objectId not in redemptions_past_ids and\ rr.objectId not in redemptions_pending_ids: redemptions_pending.insert(0, rr) session['redemptions_pending'] =\ redemptions_pending ############################################################# # REDEMPTIONS APPROVED (pending to history) # Save cpu by skipping those that do not have the same # store_location_id as active_store_location_id approvedRedemption = postDict.get("approvedRedemption") if approvedRedemption: redemp = RedeemReward(**approvedRedemption) # store_location_id can be null for backwards compat if not redemp.store_location_id or redemp.store_location_id ==\ session.get('active_store_location_id'): # check if redemp is still in pending for i, redem in enumerate(redemptions_pending): if redem.objectId == redemp.objectId: r = redemptions_pending.pop(i) r.is_redeemed = True r.updatedAt = redemp.updatedAt redemptions_past.insert(0, r) break # if not then check if it is in the history already # the above shouldn't happen! session['redemptions_pending'] =\ redemptions_pending session['redemptions_past'] =\ redemptions_past ############################################################# # REDEMPTIONS DELETED ############################## # remove from pending (should not be in history!) # Save cpu by skipping those that do not have the same # store_location_id as active_store_location_id deletedRedemption = postDict.get("deletedRedemption") if deletedRedemption: redemp = RedeemReward(**deletedRedemption) # store_location_id can be null for backwards compat if not redemp.store_location_id or redemp.store_location_id ==\ session.get('active_store_location_id'): # check if redemp is still in pending for i, redem in enumerate(redemptions_pending): if redem.objectId == redemp.objectId: redemptions_pending.pop(i) break session['redemptions_pending'] =\ redemptions_pending ############################################################# # STORE UPDATED ############################## updatedStore = postDict.get("updatedStore") if updatedStore: store = Store(**updatedStore) # have to add the image url manually store.thumbnail_image_url = updatedStore.get("thumbnail_image_url") store.cover_image_url = updatedStore.get("cover_image_url") # below here for backwards compat store.store_avatar_url = store.thumbnail_image_url session['store'] = store updatedStoreThumbnailName = postDict.get("updatedStoreThumbnailName") if updatedStoreThumbnailName: store = session['store'] store.thumbnail_image = updatedStoreThumbnailName store.thumbnail_image_url = postDict.get( "updatedStoreThumbnailUrl") # below here for backwards compat store.store_avatar = store.thumbnail_image store.store_avatar_url = store.thumbnail_image_url session['store'] = store updatedStoreCoverName = postDict.get("updatedStoreCoverName") if updatedStoreCoverName: store = session['store'] store.cover_image = updatedStoreCoverName store.cover_image_url = postDict.get("updatedStoreCoverUrl") session['store'] = store # this is in the settings tab in the dashboard but the field # is in the Store class updatedPunchesFacebook_int =\ postDict.get("updatedPunchesFacebook_int") if updatedPunchesFacebook_int: store = session['store'] store.punches_facebook = int(updatedPunchesFacebook_int) session['store'] = store ############################################################# # STORE LOCATION UPDATED ############################## ### Note that this is also being used to insert new StoreLocations updatedStoreLocation = postDict.get("updatedStoreLocation") if updatedStoreLocation: store_location = StoreLocation(**updatedStoreLocation) session['store_locations'][store_location.objectId] =\ store_location try: # also update the store_timezone session['store_timezone'] =\ pytz.timezone(store_location.get('store_timezone')) except Exception: # assign a default timezone session['store_timezone'] =\ pytz.timezone(TIME_ZONE) ############################################################# # ACCOUNT UPDATED ############################## updatedAccount = postDict.get("updatedAccount") if updatedAccount: updatedAccountObject = Account(**updatedAccount) # need to make sure that these are the same accounts! if session['account'].objectId ==\ updatedAccountObject.objectId: session['account'] = updatedAccountObject ############################################################# # SUBSCRIPTION UPDATED ############################## updatedSubscription =\ postDict.get("updatedSubscription") if updatedSubscription: subscription = Subscription(**updatedSubscription) store = session["store"] store.set('subscription', subscription) store.set('Subscription', subscription.objectId) session['subscription'] = subscription session['store'] = store ############################################################# # SETTINGS UPDATED ############################## updatedSettings = postDict.get("updatedSettings") if updatedSettings: settings = Settings(**updatedSettings) store = session["store"] store.set('settings', settings) store.set("Settings", settings.objectId) session['settings'] = settings session['store'] = store ############################################################# # REWARDS NEW ############################## newReward = postDict.get("newReward") if newReward: store = session['store'] rewards = store.get("rewards") rewards_ids = [r['reward_id'] for r in rewards] if newReward['reward_id'] not in rewards_ids: rewards.append(newReward) store.rewards = rewards session['store'] = store ############################################################# # REWARDS UPDATED ############################## updatedReward = postDict.get('updatedReward') if updatedReward: store = session['store'] mod_rewards = store.get("rewards") for i, mreward in enumerate(mod_rewards): # [{"reward_name":"Free bottle of wine", # "description":"Must be under $25 in value", # "punches":10,"redemption_count":0,reward_id:0},] if updatedReward['reward_id'] == mreward['reward_id']: if updatedReward.has_key("redemption_count"): mod_rewards[i]['redemption_count'] =\ updatedReward['redemption_count'] if updatedReward.has_key("reward_name"): mod_rewards[i]['reward_name'] =\ updatedReward['reward_name'] if updatedReward.has_key("punches"): mod_rewards[i]['punches'] =\ updatedReward['punches'] if updatedReward.has_key("description"): mod_rewards[i]['description'] =\ updatedReward['description'] break store.rewards = mod_rewards session['store'] = store ############################################################# # REWARDS DELETED ############################## deletedReward = postDict.get("deletedReward") if deletedReward: store = session['store'] rewards = store.get("rewards") rewards_ids = [r['reward_id'] for r in rewards] if deletedReward['reward_id'] in rewards_ids: for i, r in enumerate(rewards): if r['reward_id'] == deletedReward['reward_id']: rewards.pop(i) break store.rewards = rewards session['store'] = store ############################################################# # PATRONSTORE_COUNT ################################## patronStore_int = postDict.get('patronStore_int') if patronStore_int: patronStore_int = int(patronStore_int) session['patronStore_count'] = patronStore_int
def handle(self, *args, **options): # for logging when ran by CRON print "Running detect_suspicious_activity: " + str(timezone.now()) # first count the number of active stores store_count = Store.objects().count(active=True) # store_count = Store.objects().count(objectId="o72LmDy0YK") end = timezone.now() start = end + relativedelta(hours=-24) conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() # to send to the admins admin_chunks = [] # get 500 stores at a time LIMIT, skip = 500, 0 while store_count > 0: for store in Store.objects().filter(active=True, include="store_locations", limit=LIMIT, skip=skip, order="createdAt"): # for store in Store.objects().filter(\ # objectId="o72LmDy0YK", include="store_locations"): ### CHUNK1 #################################### chunk1, account_patron, patron_punch = {}, {}, {} total_punches = [] # check approved EMPLOYEES employees = store.get("employees", status=APPROVED, limit=900) employee_punches = [] def add_to_patron_punch(punch, employee=None): if punch.Patron not in patron_punch: patron_punch[punch.Patron] =\ [{"punch":punch, "employee": employee}] else: patron_punch[punch.Patron].append({"punch":\ punch, "employee":employee}) def get_location(location_id): for loc in store.store_locations: if loc.objectId == location_id: return loc if employees and len(employees) > 0: # check all the punches of each employee for employee in employees: # get all the punches for today punches = employee.get("punches", limit=900, createdAt__lte=end, createdAt__gte=start) if not punches: continue # for querying the dashboard punches employee_punches.extend([p.objectId for p in\ punches]) # group the punches by patron for punch in punches: add_to_patron_punch(punch, employee) # now check DASHBOARD punches = store.get("punches", limit=900, createdAt__lte=end, createdAt__gte=start, objectId__nin=employee_punches) # group the punches by patron if punches: for punch in punches: add_to_patron_punch(punch, None) # check for a group with a list >= 6 for key, val in patron_punch.iteritems(): suspicious_punches = [] if val and len(val) >= 6: for punch in val: suspicious_punches.append({ "store_location":\ get_location(punch["punch"].store_location_id), "punch": punch["punch"], "employee": punch["employee"] }) # cache the account and patron if key not in account_patron: acc = Account.objects().get(Patron=key, include="Patron") account_patron[key] = { "account": acc, "patron": acc.patron, } if key not in chunk1: chunk1[key] = { "account":\ account_patron[key]['account'], "patron":\ account_patron[key]['patron'], "punches": suspicious_punches } else: chunk1[key]['punches'].extend(suspicious_punches) ### CHUNK2 #################################### # hours per location # punches are still grouped per patron chunk2 = {} for loc in store.store_locations: if loc.hours and len(loc.hours) > 0 and\ loc.hours[0]['day'] != 0: # 24/7 # check for punches out of hours tz = pytz.timezone(loc.store_timezone) start = timezone.localtime(start, tz) end = timezone.localtime(end, tz) # isoweekday is from 1-7 monday to sunday # convert to 1-7 sunday to saturday day1_weekday = (start.isoweekday()) % 7 + 1 day2_weekday = (end.isoweekday()) % 7 + 1 # get the hours for day1 and day2 def get_hours_range(weekday, d): for hr in loc.hours: if hr["day"] == weekday: hr_start_hour =\ int(hr["open_time"][:2]) hr_start_minute =\ int(hr["open_time"][2:]) hr_end_hour =\ int(hr["close_time"][:2]) hr_end_minute =\ int(hr["close_time"][2:]) return d.replace(hour=hr_start_hour, minute=hr_start_minute),\ d.replace(hour=hr_end_hour, minute=hr_end_minute) return None, None (hours1_start, hours1_end) =\ get_hours_range(day1_weekday, start) (hours2_start, hours2_end) =\ get_hours_range(day2_weekday, end) # now convert to utc since punch times are in utc if hours1_start: hours1_start =\ timezone.localtime(hours1_start, tzutc()) hours1_end =\ timezone.localtime(hours1_end, tzutc()) if hours2_start: hours2_start =\ timezone.localtime(hours2_start, tzutc()) hours2_end =\ timezone.localtime(hours2_end, tzutc()) for key, val in patron_punch.iteritems(): if not val: continue suspicious_punches = [] # process only those punches that are in this location for p in [ x for x in val if x["punch"].store_location_id == loc.objectId ]: punch = p["punch"] # suspicious if not in hours1 and 2 if not (hours1_start and\ punch.createdAt>hours1_start and\ punch.createdAt<hours1_end) and\ not (hours2_start and\ punch.createdAt>hours2_start and\ punch.createdAt<hours2_end): # not in hours1 or 2 so suspicious! suspicious_punches.append({ "store_location": loc, "punch": punch, "employee": p["employee"], }) if len(suspicious_punches) == 0: continue # cache the account and patron if key not in account_patron: acc = Account.objects().get(Patron=key, include="Patron") account_patron[key] = { "account": acc, "patron": acc.patron, } if key not in chunk2: chunk2[key] = { "account":\ account_patron[key]['account'], "patron":\ account_patron[key]['patron'], "punches": suspicious_punches } else: chunk2[key]['punches'].extend( suspicious_punches) # all tasks are done for this store - send email if len(chunk1) > 0 or len(chunk2) > 0: store_acc = Account.objects().get(Store=store.objectId) admin_chunks.append({ "store_acc": store_acc, "store": store, "data": (chunk1, chunk2), }) try: send_email_suspicious_activity(store_acc, store, chunk1, chunk2, conn) except SMTPServerDisconnected: conn = mail.get_connection(fail_silently=(not DEBUG)) conn.open() send_email_suspicious_activity(store_acc, store, chunk1, chunk2, conn) # end of while loop store_count -= LIMIT skip += LIMIT if len(admin_chunks) > 0: send_email_suspicious_activity_admin(admin_chunks, start, end, conn) # everything is done. close the connection try: conn.close() except Exception: pass