示例#1
0
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")
示例#2
0
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")
示例#3
0
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.'}))
示例#4
0
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.'}))
示例#5
0
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.'}))
示例#6
0
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.'}))
示例#7
0
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")
示例#8
0
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)
示例#9
0
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)
示例#10
0
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")
示例#11
0
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)
示例#12
0
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'))
示例#13
0
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'))
示例#14
0
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")
示例#15
0
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")
示例#16
0
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)
示例#17
0
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)
示例#18
0
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.'}))
示例#19
0
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.'}))
示例#20
0
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)
示例#21
0
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}))
示例#22
0
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.'}))
示例#23
0
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)
示例#24
0
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)
示例#25
0
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)
示例#26
0
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)
示例#27
0
    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
示例#28
0
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
示例#29
0
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)    
示例#30
0
 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
示例#31
0
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
示例#32
0
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)
示例#33
0
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)
示例#34
0
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)
示例#35
0
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)
示例#36
0
 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)