Пример #1
0
def lookup_users_by_phone(phone_number):
    """Attempt to match the given phone number in an arbitrary format to one or more members"""
    phone_number = re.sub('\s', '', phone_number)
    if phone_number == '':
        return []

    # Perform raw query in order to use MSSQL's 'REPLACE' function to remove whitespace
    # Note that we're excluding Actors with end_code 'dublett' manually here
    actors = Actor.objects.raw(
        "select * from Actor where REPLACE(MobPh, ' ', '') = %s AND EndCd != %s;",
        [phone_number, ACTOR_ENDCODE_DUBLETT]
    )

    # Filter on personal members; we're never handling other membership types
    actors = [actor for actor in actors if actor.is_personal_member()]

    # Perform raw query in order to use MSSQL's 'REPLACE' function to remove whitespace
    # Note that we're excluding inactive Enrollments manually (like Enrollment.get_active() would have) here
    query = 'select * from %s where (("Paymethod" = %s or "Paymethod" = %s ) and ' \
            '"SubmittedDt" is null and REPLACE(Mob, \' \', \'\') = %s );' % (
                Enrollment._meta.db_table, '%s', '%s', '%s',
            )
    params = [PAYMENT_METHOD_CODES['card'], PAYMENT_METHOD_CODES['invoice'], phone_number]
    pending_actors = Enrollment.objects.raw(query, params)

    # Convert the matching actors to users
    users = [User.get_or_create_inactive(memberid=actor.memberid) for actor in actors]
    users += [User.get_or_create_inactive(memberid=actor.memberid) for actor in pending_actors]
    return users
Пример #2
0
def verify_memberid(ip_address, memberid, country_code, zipcode):
    """
    Returns a User object matching the given memberid, country code, and if
    Norwegian; also zipcode. Includes pending users by default. Raises a range
    of exceptions if the provided data is invalid or does not match any user:
    - MemberidLookupsExceeded: If the client IP address has performed more
      lookups than we allowed
    - CountryDoesNotExist: If the given country code is invalid
    - ActorIsNotPersonalMember: If the data matches an Actor in Focus who
      isn't a personal member
    - NoMatchingMemberid: If the data doesn't match any member
    """
    # Check that the memberid is correct (and retrieve the Actor-entry)
    if memberid_lookups_exceeded(ip_address):
        raise MemberidLookupsExceeded

    if not FocusCountry.objects.filter(code=country_code).exists():
        raise CountryDoesNotExist

    # Not filtering on Actor.get_personal_members() in order to raise explicit
    # exception for non-personal-membership matches; see below
    actor = Actor.objects.filter(
        memberid=memberid,
        address__country_code=country_code
    )

    # Require correct zipcode for domestic members
    if country_code == 'NO':
        actor = actor.filter(address__zipcode=zipcode)

    if actor.exists():
        actor = actor.get()

        # Check that it's a proper member object (note that we didn't filter
        # the query on Actor.get_personal_members())
        if not actor.is_personal_member():
            raise ActorIsNotPersonalMember

        return User.get_or_create_inactive(memberid=actor.memberid)

    # No matching actors, check for pending users
    enrollment = Enrollment.get_active().filter(memberid=memberid)

    # Require correct zipcode for domestic members
    if country_code == 'NO':
        enrollment = enrollment.filter(zipcode=zipcode)

    if enrollment.exists():
        return User.get_or_create_inactive(memberid=memberid)

    # No matches
    raise NoMatchingMemberid
Пример #3
0
def confirm_membership_by_token(request):
    """
    Confirm the membership with only the given token as authentication. Note that the URL to this view is hardcoded in
    Focus which sends out emails/SMS with the URL and correct token.
    """
    try:
        token = request.GET['code']
        actor = Actor.objects.get(family_youth_member_accepted_token=token)
        youth_user = User.get_or_create_inactive(memberid=actor.memberid)
        context = {
            'token': token,
            'youth_user': youth_user,
        }
    except (KeyError, Actor.DoesNotExist):
        raise Http404

    if request.method == 'GET':
        return render(request, 'common/user/membership_confirmation.html', context)
    elif request.method == 'POST':
        try:
            User.confirm_membership_by_token(token)
            librato.increment('sherpa.medlemmer.familiemedlemskap.bekreft_ungdomsmedlem')
            return redirect('%s?code=%s' % (reverse('user:confirm_membership_by_token'), token))
        except:
            context['confirmation_error'] = True
            return render(request, 'common/user/membership_confirmation.html', context)
Пример #4
0
def members(request, version, format):
    if request.method == 'GET':
        require_focus(request)

        try:
            if 'sherpa_id' in request.GET and 'medlemsnummer' in request.GET:
                user = User.get_users(include_pending=True).get(id=request.GET['sherpa_id'], memberid=request.GET['medlemsnummer'])
            elif 'sherpa_id' in request.GET:
                user = User.get_users(include_pending=True).get(id=request.GET['sherpa_id'])
            elif 'medlemsnummer' in request.GET:
                try:
                    user = User.get_or_create_inactive(memberid=request.GET['medlemsnummer'], include_pending=True)
                except (Enrollment.DoesNotExist, ValueError):
                    # No such member
                    raise User.DoesNotExist
            else:
                raise BadRequest(
                    u"You must supply either an 'sherpa_id' or 'medlemsnummer' parameter for member lookup",
                    code=error_codes.MISSING_REQUIRED_PARAMETER,
                    http_code=400
                )
            return HttpResponse(json.dumps(get_member_data(user)))
        except (User.DoesNotExist, ValueError):
            raise BadRequest(
                u"A member matching that 'sherpa_id', 'medlemsnummer', or both if both were provided, does not exist.",
                code=error_codes.RESOURCE_NOT_FOUND,
                http_code=404
            )
    else:
        raise BadRequest(
            u"Unsupported HTTP verb",
            code=error_codes.UNSUPPORTED_HTTP_VERB,
            http_code=400
        )
Пример #5
0
    def validate_existing(self):
        try:
            user = ExistingUser.get_or_create_inactive(memberid=self.existing_memberid)
        except (ExistingUser.DoesNotExist, ValueError):
            return False

        if not user.payment.status['is_paid']:
            return False

        if user.get_dnt_age() < settings.MEMBERSHIP['AGES']['YOUTH']:
            return False

        if user.is_related_member():
            return False

        if user.has_membership_type('family_primary'):
            return False

        if user.address.country.code != self.country:
            return False

        if self.country == 'NO' and user.address.zipcode.zipcode != self.zipcode:
            return False

        return True
Пример #6
0
    def get_children(self):
        from user.models import User

        children = cache.get('actor.%s.children' % self.actor.memberid)
        if children is None:
            actor_children = Actor.get_personal_members().filter(parent=self.actor.memberid).exclude(id=self.actor.id)
            children = [
                User.get_or_create_inactive(memberid=actor_child.memberid)
                for actor_child in actor_children
            ]
            cache.set('actor.%s.children' % self.actor.memberid, children, settings.FOCUS_MEMBER_CACHE_PERIOD)
        return children
Пример #7
0
    def get_parent(self):
        """Returns the parent pending member of this pending member, or None if it has no parent"""
        from user.models import User

        parent_memberid = self.enrollment.get_parent_memberid()
        if parent_memberid is None:
            return None

        try:
            return User.get_or_create_inactive(memberid=parent_memberid)
        except User.DoesNotExist:
            # Entirely possible that this member is connected to a parent which isn't active. Ignore it
            return None
Пример #8
0
def membership_fee(request, memberid):
    librato.increment('sherpa.api.tailored.medlemskontingent.request')
    try:
        user = User.get_or_create_inactive(memberid)
        response = json.dumps({
            'id': user.id,
            'hasPaid': user.payment.status['is_paid'],
        })
        librato.increment('sherpa.api.tailored.medlemskontingent.response.200')
        return HttpResponse(response, content_type="application/json")
    except (User.DoesNotExist, ValueError):
        librato.increment('sherpa.api.tailored.medlemskontingent.response.404')
        raise Http404
Пример #9
0
def lookup_users_by_phone(phone_number):
    """Attempt to match the given phone number in an arbitrary format to one or more members"""
    phone_number = re.sub('\s', '', phone_number)
    if phone_number == '':
        return []

    # Note that we're excluding Actors with end_code 'dublett' manually here
    actors = Actor.objects.raw(
        "select * from Actor where REPLACE(MobPh, ' ', '') = %s AND EndCd != %s;",
        [phone_number, ACTOR_ENDCODE_DUBLETT]
    )

    # Convert the matching actors to users. Filter on personal members; we're never handling other membership types
    return [User.get_or_create_inactive(memberid=actor.memberid) for actor in actors if actor.is_personal_member()]
Пример #10
0
    def get_children(self):
        from user.models import User

        # Only look for children among other pending users. There could theoretically be children that are proper
        # members, but in most such cases the current pending member would also have been accepted, so don't handle it.
        enrollment_children = Enrollment.get_active().filter(
            parent=self.enrollment.memberid,
        ).exclude(
            pk=self.enrollment.pk,
        )
        return [
            User.get_or_create_inactive(memberid=enrollment_child.memberid)
            for enrollment_child in enrollment_children
        ]
Пример #11
0
def contact_person_search(request, forening_id):
    current_forening = Forening.objects.get(id=forening_id)
    if current_forening not in request.user.all_foreninger():
        raise PermissionDenied

    MAX_HITS = 100

    if len(request.POST['q']) < settings.ADMIN_USER_SEARCH_CHAR_LENGTH:
        raise PermissionDenied

    local_nonmember_users = User.get_users().filter(memberid__isnull=True)
    for word in request.POST['q'].split():
        local_nonmember_users = local_nonmember_users.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word)
        )
    local_nonmember_users = local_nonmember_users.order_by('first_name')

    actors = Actor.get_personal_members()
    for word in request.POST['q'].split():
        actors = actors.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word) |
            Q(memberid__icontains=word)
        )
    actors = actors.order_by('first_name')

    # Get (or create) the user objects for the first MAX_HITS actor-hits
    users = [
        User.get_or_create_inactive(a.memberid)
        for a in actors[:MAX_HITS]]

    # Merge with non-members
    users = sorted(
        list(users) + list(local_nonmember_users),
        key=lambda u: u.get_full_name())

    context = {
        'current_forening': current_forening,
        'users': users[:MAX_HITS],
    }
    return HttpResponse(json.dumps({
        'results': render_to_string(
            'central/admin/foreninger/contact_person_search_results.html',
            context,
            request=request,
        ),
        'max_hits_exceeded': len(users) > MAX_HITS or len(actors) > MAX_HITS
    }))
Пример #12
0
 def get_parent(self):
     from user.models import User
     parent = cache.get('focus.enrollment.%s.parent' % self.enrollment.memberid)
     if parent is None:
         parent_memberid = self.get_parent_memberid()
         if parent_memberid is not None:
             try:
                 parent = User.get_or_create_inactive(memberid=parent_memberid, include_pending=True)
             except Enrollment.DoesNotExist:
                 # Entirely possible that this member is connected to a parent which isn't active. Ignore it
                 parent = None
         else:
             parent = None
         cache.set('focus.enrollment.%s.parent' % self.enrollment.memberid, parent, settings.FOCUS_MEMBER_CACHE_PERIOD)
     return parent
Пример #13
0
    def get_parent(self):
        """Returns the parent of this member, or None if it has no parent"""
        from user.models import User

        if not self.is_related_member():
            return None

        # Most household members should have a parent, but some don't. Some of these are lifelong household members
        # (this membership type is now deprecated) who have lost their spouce, and memberservice has decided to keep
        # them as household members, with no parent.
        # They must be separated from main lifelong members because they're *not* entitled to receive Fjell og Vidde
        # or årboken.
        parent_memberid = self.actor.get_parent_memberid()
        if parent_memberid is None:
            return None

        return User.get_or_create_inactive(memberid=parent_memberid)
Пример #14
0
def forening(request, version, format):
    if request.method == 'GET':
        require_focus(request)
        librato.increment('sherpa.api.tailored.forening.request')

        if 'bruker_sherpa_id' in request.GET or 'bruker_medlemsnummer' in request.GET:
            try:
                # Lookup by specified members' access
                if 'bruker_sherpa_id' in request.GET and 'bruker_medlemsnummer' in request.GET:
                    user = User.get_users(include_pending=True).get(id=request.GET['bruker_sherpa_id'], memberid=request.GET['bruker_medlemsnummer'])
                elif 'bruker_sherpa_id' in request.GET:
                    user = User.get_users(include_pending=True).get(id=request.GET['bruker_sherpa_id'])
                elif 'bruker_medlemsnummer' in request.GET:
                    try:
                        user = User.get_or_create_inactive(memberid=request.GET['bruker_medlemsnummer'])
                    except (User.DoesNotExist, ValueError):
                        # No such member
                        raise User.DoesNotExist

                foreninger = [get_forening_data(f) for f in user.all_foreninger()]
                librato.increment('sherpa.api.tailored.forening.response.200')
                return HttpResponse(json.dumps(foreninger))

            except (User.DoesNotExist, ValueError):
                librato.increment('sherpa.api.tailored.forening.response.404')
                raise BadRequest(
                    "A member matching that 'sherpa_id', 'bruker_medlemsnummer', or both if both were provided, does not exist.",
                    code=error_codes.RESOURCE_NOT_FOUND,
                    http_code=404
                )
        else:
            librato.increment('sherpa.api.tailored.forening.response.400')
            raise BadRequest(
                "You must supply either a 'bruker_sherpa_id' or 'bruker_medlemsnummer' parameter for forening lookup by member. Only this form of forening-lookup is implemented in this version.",
                code=error_codes.MISSING_REQUIRED_PARAMETER,
                http_code=400
            )
    else:
        librato.increment('sherpa.api.tailored.forening.response.400')
        raise BadRequest(
            "Unsupported HTTP verb",
            code=error_codes.UNSUPPORTED_HTTP_VERB,
            http_code=400
        )
Пример #15
0
def existing(request):
    if not request.is_ajax():
        return redirect('enrollment:household')

    # Note: This logic is duplicated in validate_existing()
    data = json.loads(request.POST['data'])
    if data['country'] == 'NO' and len(data['zipcode']) != 4:
        return HttpResponse(json.dumps({'error': 'bad_zipcode'}))
    try:
        user = User.get_or_create_inactive(memberid=data['id'])
    except User.DoesNotExist:
        return HttpResponse(json.dumps({'error': 'does_not_exist'}))
    except ValueError:
        return HttpResponse(json.dumps({'error': 'invalid_id'}))

    country_matches = user.address.country.code == data['country']

    # Match both country and zipcode for norwegian members, only country for foreign members
    if data['country'] == 'NO':
        valid = country_matches and user.address.zipcode.zipcode == data['zipcode']
    else:
        valid = country_matches
    if not valid:
        return HttpResponse(json.dumps({'error': 'invalid_address'}))

    if not user.payment.status['is_paid']:
        return HttpResponse(json.dumps({'error': 'has_not_paid'}))

    if user.get_dnt_age() < settings.MEMBERSHIP['AGES']['YOUTH']:
        return HttpResponse(json.dumps({'error': 'too_young', 'age': user.get_dnt_age()}))

    if user.is_related_member():
        return HttpResponse(json.dumps({'error': 'is_related_member'}))

    if user.has_membership_type('family_primary'):
        return HttpResponse(json.dumps({'error': 'is_family_member'}))

    return HttpResponse(json.dumps({
        'name': user.get_full_name(),
        'address': user.address.format_for_oneline(),
    }))
Пример #16
0
    def get_queryset(self):
        # This method uses Focus and local users to compile a search result
        # containing valid turledere.

        # See the comment on the class definition of the lazy_queryset variable
        if self.lazy_queryset:
            return self.lazy_queryset

        SEARCH_MAX_HITS = 100
        search = self.request.query_params.get('search', '').strip()

        local_nonmember_users = User.get_users().filter(memberid__isnull=True)
        for word in search.split():
            local_nonmember_users = local_nonmember_users.filter(
                Q(first_name__icontains=word) |
                Q(last_name__icontains=word)
            )
        local_nonmember_users = local_nonmember_users.order_by('first_name')

        actors = Actor.get_personal_members()
        for word in search.split():
            actors = actors.filter(
                Q(first_name__icontains=word) |
                Q(last_name__icontains=word) |
                Q(memberid__icontains=word)
            )
        actors = actors.order_by('first_name')

        # Get (or create) the user objects for the first MAX_HITS actor-hits
        users = [
            User.get_or_create_inactive(a.memberid)
            for a in actors[:SEARCH_MAX_HITS]]

        # Merge with non-members
        users = sorted(
            list(users) + list(local_nonmember_users),
            key=lambda u: u.get_full_name())

        self.lazy_queryset = users
        return users
Пример #17
0
    def get_children_pending(self):
        """Returns existing single members who are *due to become* family members in this users' family"""
        from user.models import User

        children_pending = cache.get('actor.%s.children_pending' % self.actor.memberid)
        if children_pending is None:
            actors = Actor.get_personal_members().filter(
                pending_family_parent=self.actor.memberid,
            ).exclude(
                memberid=self.actor.memberid,
            ).exclude(
                # Exclude any actual family members. This is necessary because Focus doesn't clear the appropriate
                # fields when converting pending family members to actual family members.
                Q(services__code=get_membership_type_by_codename('family_household')['code']) |
                Q(services__code=get_membership_type_by_codename('family_primary')['code'])
            ).order_by('first_name', 'last_name')
            children_pending = [User.get_or_create_inactive(memberid=actor.memberid) for actor in actors]
            cache.set(
                'actor.%s.children_pending' % self.actor.memberid,
                children_pending,
                settings.FOCUS_MEMBER_CACHE_PERIOD,
            )
        return children_pending
Пример #18
0
def turleder_search(request):
    MAX_HITS = 100

    if len(request.POST['q']) < settings.ADMIN_USER_SEARCH_CHAR_LENGTH:
        raise PermissionDenied

    local_nonmember_users = User.get_users().filter(memberid__isnull=True)
    for word in request.POST['q'].split():
        local_nonmember_users = local_nonmember_users.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word)
        )
    local_nonmember_users = local_nonmember_users.order_by('first_name')

    actors = Actor.get_personal_members()
    for word in request.POST['q'].split():
        actors = actors.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word) |
            Q(memberid__icontains=word)
        )
    actors = actors.order_by('first_name')

    # Get (or create) the user objects for the first MAX_HITS actor-hits
    users = [User.get_or_create_inactive(a.memberid) for a in actors[:MAX_HITS]]

    # Merge with non-members
    users = sorted(list(users) + list(local_nonmember_users), key=lambda u: u.get_full_name())

    context = RequestContext(request, {
        'users': users[:MAX_HITS]
    })
    return HttpResponse(json.dumps({
        'results': render_to_string('common/admin/aktiviteter/edit/turleder_search_results.html', context),
        'max_hits_exceeded': len(users) > MAX_HITS or len(actors) > MAX_HITS
    }))
Пример #19
0
def membership(request, version, format):
    if request.method == 'GET':
        require_focus(request)
        librato.increment('sherpa.api.tailored.medlemskap.request')

        if not 'medlemsnummer' in request.GET or not 'født' in request.GET:
            librato.increment('sherpa.api.tailored.medlemskap.response.400')
            raise BadRequest(
                "Missing 'medlemsnummer' and/or 'født' parameters'",
                code=error_codes.MISSING_REQUIRED_PARAMETER,
                http_code=400
            )

        try:
            requested_date_of_birth = datetime.strptime(request.GET['født'], "%d.%m.%Y").date()
        except ValueError:
            librato.increment('sherpa.api.tailored.medlemskap.response.400')
            raise BadRequest(
                "Could not parse the 'født' parameter ('%s'), which should be in the following format: 'dd.mm.yyyy'" %
                    request.GET['født'],
                code=error_codes.MISSING_REQUIRED_PARAMETER,
                http_code=400
            )

        try:
            try:
                user = User.get_or_create_inactive(memberid=request.GET['medlemsnummer'])
            except (User.DoesNotExist, ValueError):
                # No such member
                raise User.DoesNotExist

            # Make sure we have the most up-to-date information; users will often contact membership service and
            # they'll fix their birth date directly in Focus, and then retry some service using this API resource
            user.clear_cache()

            # Verify the requested date of birth
            if user.get_birth_date() != requested_date_of_birth:
                raise User.DoesNotExist

            if 'hele_husstanden' in request.GET:
                if not user.is_related_member():
                    user_data = {
                        'hovedmedlem': get_member_data(user),
                        'husstandsmedlemmer': [get_member_data(u) for u in user.get_children()],
                    }
                else:
                    if user.get_parent() is not None:
                        user_data = {
                            'hovedmedlem': get_member_data(user.get_parent()),
                            'husstandsmedlemmer': [get_member_data(u) for u in user.get_parent().get_children()],
                        }
                    else:
                        # A household member without a parent, send it as such
                        user_data = {
                            'hovedmedlem': None,
                            'husstandsmedlemmer': [get_member_data(user)],
                        }
            else:
                user_data = get_member_data(user)

            librato.increment('sherpa.api.tailored.medlemskap.response.200')
            return HttpResponse(json.dumps(user_data))
        except (User.DoesNotExist, ValueError):
            librato.increment('sherpa.api.tailored.medlemskap.response.404')
            raise BadRequest(
                "A membership with member ID '%s' and date of birth '%s' does not exist." %
                    (request.GET['medlemsnummer'], request.GET['født']),
                code=error_codes.RESOURCE_NOT_FOUND,
                http_code=404
            )

    else:
        librato.increment('sherpa.api.tailored.medlemskap.response.400')
        raise BadRequest(
            "Unsupported HTTP verb",
            code=error_codes.UNSUPPORTED_HTTP_VERB,
            http_code=400
        )
Пример #20
0
def cabin_visit(product_data, user):
    # Create an order with a cabin settlement product
    order = Order(
        amount=0, # Default to 0 and update to correct amount later
        language_code=product_data['språk'],
    )
    if not user.is_anonymous():
        order.user = user
    order.save() # Save to DB in order to create relations, even though we'll have to do an UPDATE later

    cabin_settlement = CabinSettlement(order=order)
    if 'brukerdata' in product_data:
        cabin_settlement.name = product_data['brukerdata']['navn']
        cabin_settlement.email = product_data['brukerdata']['epost']
    cabin_settlement.save()

    amount = 0
    for cabin in product_data['hytter']:
        sted = Sted.get(cabin['id'])
        # @TODO: Use private fields to get the appropriate owner: first forening of privat.juridisk_eier,
        # privat.vedlikeholdes_av
        forening = Forening.objects.get(turbasen_object_id=sted['grupper'][0])

        cabin_visit = CabinVisit(
            cabin_settlement=cabin_settlement,
            cabin_object_id=sted['_id'],
        )
        cabin_visit.save()

        for losji in cabin['losji']:
            # Business rule: Anyone claiming to be a member will get the membership price
            pays_membership_price = losji['ermedlem']

            lodging = Lodging.objects.get(
                id=losji['id'],
                forening=forening.id,
            )

            if losji['antall'] < 0:
                raise PermissionDenied

            # Try to relate this visitor to a user
            user = None
            memberid_unrecognized = None
            if losji['medlemsnummer'] is not None:
                try:
                    user = User.get_or_create_inactive(memberid=losji['medlemsnummer'])
                    # Note that this is where we could verify that the member has paid their annual fee, but it is
                    # currently ignored
                except User.DoesNotExist:
                    # We received an unrecognized memberid, but we'll still allow the purchase, so save the given
                    # memberid for future reference, whatever it is
                    memberid_unrecognized = losji['medlemsnummer']

            # Save the visitor details
            cabin_visitor = CabinVisitor(
                cabin_visit=cabin_visit,
                protocol_number=losji['protokollnummer'],
                user=user,
                memberid_unrecognized=memberid_unrecognized,
                lodging_type=lodging.name,
                price=lodging.get_price(pays_membership_price),
                nights=losji['antall'],
                paid_membership_price=pays_membership_price,
            )
            cabin_visitor.save()

            # Now calculate the lodging price and add it to the total amount
            amount += lodging.get_price(pays_membership_price) * losji['antall']

        for proviant in cabin['proviant']:
            # Business rule: The client decides whether or not supplies should have membership price
            pays_membership_price = product_data['medlemspris']

            supply = Supply.objects.get(
                id=proviant['id'],
                supply_category__forening=forening.id,
            )

            if proviant['antall'] < 0:
                raise PermissionDenied

            # Save a copy of the current products and prices
            supply_purchase = SupplyPurchase(
                cabin_visit=cabin_visit,
                category=supply.supply_category.name,
                name=supply.name,
                price=supply.get_price(pays_membership_price),
                count=proviant['antall'],
                paid_membership_price=pays_membership_price,
            )
            supply_purchase.save()

            # Now calculate the supplies price and add it to the total amount
            amount += supply.get_price(pays_membership_price) * proviant['antall']

    # Save the total amount in øre
    amount *= 100
    order.amount = amount
    order.save()
    return order
Пример #21
0
def membership(request, version, format):
    if request.method == 'GET':
        require_focus(request)

        if not 'medlemsnummer' in request.GET or not u'født' in request.GET:
            raise BadRequest(
                u"Missing 'medlemsnummer' and/or 'født' parameters'",
                code=error_codes.MISSING_REQUIRED_PARAMETER,
                http_code=400
            )

        try:
            requested_date_of_birth = datetime.strptime(request.GET[u'født'], "%d.%m.%Y").date()
        except ValueError:
            raise BadRequest(
                u"Could not parse the 'født' parameter ('%s'), which should be in the following format: 'dd.mm.yyyy'" %
                    request.GET[u'født'],
                code=error_codes.MISSING_REQUIRED_PARAMETER,
                http_code=400
            )

        try:
            try:
                user = User.get_or_create_inactive(memberid=request.GET['medlemsnummer'], include_pending=True)
            except (Enrollment.DoesNotExist, ValueError):
                # No such member
                raise User.DoesNotExist

            # Verify the requested date of birth
            if user.get_birth_date() != requested_date_of_birth:
                raise User.DoesNotExist

            if 'hele_husstanden' in request.GET:
                if not user.is_household_member():
                    user_data = {
                        'hovedmedlem': get_member_data(user),
                        'husstandsmedlemmer': [get_member_data(u) for u in user.get_children()],
                    }
                else:
                    if user.get_parent() is not None:
                        user_data = {
                            'hovedmedlem': get_member_data(user.get_parent()),
                            'husstandsmedlemmer': [get_member_data(u) for u in user.get_parent().get_children()],
                        }
                    else:
                        # A household member without a parent, send it as such
                        user_data = {
                            'hovedmedlem': None,
                            'husstandsmedlemmer': [get_member_data(user)],
                        }
            else:
                user_data = get_member_data(user)

            return HttpResponse(json.dumps(user_data))
        except (User.DoesNotExist, ValueError):
            raise BadRequest(
                u"A membership with member ID '%s' and date of birth '%s' does not exist." %
                    (request.GET['medlemsnummer'], request.GET[u'født']),
                code=error_codes.RESOURCE_NOT_FOUND,
                http_code=404
            )

    else:
        raise BadRequest(
            u"Unsupported HTTP verb",
            code=error_codes.UNSUPPORTED_HTTP_VERB,
            http_code=400
        )
Пример #22
0
    def get_pending_family_parent(self):
        from user.models import User
        if not self.is_pending_family_member():
            raise Exception("Can't retrieve pending parent if the member isn't a pending family member")

        return User.get_or_create_inactive(memberid=self.actor.pending_family_parent)
Пример #23
0
def signup_add_participant(request, aktivitet_id, aktivitet_date_id):
    try:
        aktivitet_date = AktivitetDate.objects.select_related(
            *default_select_related,
        ).prefetch_related(
            *default_prefetch_related,
        ).get(id=aktivitet_date_id)

        for validation_func in [require_accepts_signups, require_stripe_account]:
            response = validation_func(request, aktivitet_date)
            if response is not None:
                return response
    except AktivitetDate.DoesNotExist:
        raise Http404

    signup_session = SignupSession(request, aktivitet_date)
    context = {
        'aktivitet_date': aktivitet_date,
        'signup_session': signup_session,
    }

    if request.method == 'GET':
        return render(request, 'common/aktiviteter/show/signup/add_participant.html', context)

    elif request.method == 'POST':
        if request.POST['submit'] == 'lookup_member':
            context['memberid'] = request.POST['memberid']
            context['lookup_memberid'] = True
            try:
                user = User.get_or_create_inactive(memberid=request.POST['memberid'])
                context['member'] = user

                # Is this user already added in the session, or a participant in
                # a separate group?
                session_participants = [p.user for p in signup_session.participants if p.user is not None]
                already_in_session = user in session_participants
                already_participant = signup_session.aktivitet_date.has_participant(user)
                if already_in_session or already_participant:
                    context['already_participating'] = True
                    return render(request, 'common/aktiviteter/show/signup/add_participant.html', context)

                if (aktivitet_date.only_members
                        and not user.payment.status['is_paid']):
                    context['member_has_not_paid'] = True
                    return render(
                        request,
                        'common/aktiviteter/show/signup/add_participant.html',
                        context
                    )
            except:
                messages.error(request, 'invalid_memberid')
            return render(request, 'common/aktiviteter/show/signup/add_participant.html', context)
        elif request.POST['submit'] == 'add_member_participant':
            user = User.objects.get(memberid=request.POST['memberid'])

            # Already a participant in a separate group? This was already
            # checked on lookup, but ensure they wasn't signed up somewhere
            # else in the meantime as well.
            if signup_session.aktivitet_date.has_participant(user):
                context['memberid'] = user.memberid
                context['lookup_memberid'] = True
                context['already_participating'] = True
                return render(request, 'common/aktiviteter/show/signup/add_participant.html', context)

            # Check if they're already added in the session; if so, ignore the
            # duplication and just return to participants list
            session_participants = [p.user for p in signup_session.participants if p.user is not None]
            if user not in session_participants:
                signup_session.participants.append(SignupSessionParticipant(
                    signup_session=signup_session,
                    id=None,
                    user=user,
                    first_name=user.get_first_name(),
                    last_name=user.get_last_name(),
                    birth_date=user.get_birth_date(),
                    email=user.get_email(),
                    phone=user.get_phone_mobile(),
                    state='signed_up',
                    use_parent_contact_info=False,
                    use_signee_contact_info=False,
                    discount_code='',
                    signee_relation='other',
                    answers=[],
                    extras=[],
                ))
                signup_session.save()
            return redirect('aktiviteter:signup_participants',
                            aktivitet_date.aktivitet.id, aktivitet_date.id)
        elif request.POST['submit'] == 'add_nonuser_participant':
            use_signee_contact_info = request.POST.get('use_signee_contact_info') == 'on'
            if use_signee_contact_info:
                # If using the signees contact info, don't validate contact info
                # input
                context['use_signee_contact_info'] = True
                form = ParticipantWithoutContactInfoForm(request.POST)
            else:
                form = ParticipantForm(request.POST)

            if aktivitet_date.aktivitet.participant_birth_date_required:
                form.fields['birth_date'].required = True

            context['add_nonuser'] = True
            context['form'] = form
            if not form.is_valid():
                return render(request, 'common/aktiviteter/show/signup/add_participant.html', context)
            else:
                first_name, last_name = form.cleaned_data['name'].rsplit(maxsplit=1)
                if use_signee_contact_info:
                    email = ''
                    phone = ''
                else:
                    email = form.cleaned_data['email']
                    phone = form.cleaned_data['phone']

                signup_session.participants.append(SignupSessionParticipant(
                    signup_session=signup_session,
                    id=None,
                    user=None,
                    first_name=first_name,
                    last_name=last_name,
                    birth_date=form.cleaned_data['birth_date'],
                    email=email,
                    phone=phone,
                    state='signed_up',
                    use_parent_contact_info=False,
                    use_signee_contact_info=use_signee_contact_info,
                    discount_code='',
                    signee_relation='other',
                    answers=[],
                    extras=[],
                ))

                if not use_signee_contact_info and 'confirm_nonuser' not in request.POST:
                    # Check if the submitted email and/or phone are already
                    # registered in the member system, and if so, give the
                    # signee a hint that they may add them as a member
                    email = form.cleaned_data['email']
                    phone = re.sub('\s', '', form.cleaned_data['phone'])
                    existing_email = Actor.objects.filter(email=email).exists()
                    existing_phone = len(lookup_users_by_phone(phone)) > 0

                    if existing_email or existing_phone:
                        context['existing_member'] = True
                        context['existing_email'] = existing_email
                        context['existing_phone'] = existing_phone
                        return render(
                            request,
                            'common/aktiviteter/show/signup/add_participant.html',
                            context,
                        )

                signup_session.save()
                return redirect('aktiviteter:signup_participants',
                                aktivitet_date.aktivitet.id, aktivitet_date.id)

    return render(request, 'common/aktiviteter/show/signup/add_participant.html', context)
Пример #24
0
def create_transaction(request):
    """This view is called by the phone app to initiate a new transaction"""
    transaction = json.loads(request.POST['data'])

    sted = Sted.get(transaction['hytte'])
    # TODO: Handle cabins with multiple owners (defaulting to first occurrence for now)
    forening = Forening.objects.get(turbase_object_id=sted.grupper[0])

    cabin_visit = CabinVisit(
        order_number=CabinVisit.generate_order_number(),
    )
    cabin_visit.save()

    amount = 0
    for gjest in transaction['gjester']:
        cabin_visitor = CabinVisitor(
            cabin_visit=cabin_visit,
            protocol_number=gjest['protokollnummer'],
        )
        cabin_visitor.save()

        if gjest['medlemsnummer'] is None:
            is_member = False
        else:
            try:
                user = User.get_or_create_inactive(memberid=gjest['medlemsnummer'], include_pending=True)
                if not user.has_paid():
                    # TODO: confirm in the client that one or more users aren't valid
                    raise NotImplementedError
                is_member = True

                cabin_visitor.user = user
                cabin_visitor.save()
            except (Actor.DoesNotExist, Enrollment.DoesNotExist):
                # TODO: handle invalid memberid
                raise NotImplementedError

        for losji in gjest['losji']:
            lodging = forening.lodging_prices.get(id=losji['id'])
            if is_member:
                amount += lodging.price_member * losji['antall']
            else:
                amount += lodging.price_nonmember * losji['antall']

        for proviant in gjest["proviant"]:
            supply = Supply.objects.get(
                id=proviant['id'],
                supply_category__forening=forening.id,
            )
            if is_member:
                amount += supply.price_member * proviant['antall']
            else:
                amount += supply.price_nonmember * proviant['antall']

    # The price to DIBS is provided in øre
    amount *= 100

    accept_return_url = u'https://dnt-backend.herokuapp.com/' # TODO implement

    callback_url = u'https://%s%s' % (
        request.site.domain,
        reverse('payment.views.callback_endpoint')
    )

    input_parameters = {
        u'acceptReturnUrl': accept_return_url,
        u'amount': amount,
        u'callbackUrl': callback_url,
        u'currency': u'NOK', # ISO 4217
        u'merchant': settings.DIBS_MERCHANT_ID,
        u'orderId': cabin_visit.order_number,
        u'test': 1, # Temporary; triggers test-environment at DIBS
    }

    sorted_pairs = sorted(input_parameters.items(), key=lambda i: i[0])
    sorted_string = [u"%s=%s" % (i[0], i[1]) for i in sorted_pairs]
    message = u'&'.join(sorted_string).encode('utf-8')

    MAC = hmac.new(settings.DIBS_HMAC_KEY.decode('hex'), message, hashlib.sha256).hexdigest()

    return HttpResponse(json.dumps({
        'MAC': MAC,
        'ticket': None, # TODO: if authenticated, return user's DIBS ticket
        'callbackUrl': callback_url,
        'orderId': cabin_visit.order_number,
        'acceptReturnUrl': accept_return_url,
        'amount': amount,
    }))
Пример #25
0
def search(request):
    if not request.is_ajax() or request.method != 'POST':
        return redirect('admin:users.index')

    if len(request.POST['q']) < settings.ADMIN_USER_SEARCH_CHAR_LENGTH:
        raise PermissionDenied

    SEARCH_MAX_HITS = 40

    # Look up non-members in the local user database
    nonmembers = User.get_users().filter(
        memberid__isnull=True,
    ).prefetch_related(
        'user_permission_grants',
        'user_permission_grants__user_permission',
        'user_permission_grants__user_permission__oauth_applications',
    )
    for word in request.POST['q'].split():
        nonmembers = nonmembers.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word) |
            Q(email__icontains=word)
        )
    nonmembers = nonmembers.order_by('first_name')[:SEARCH_MAX_HITS]

    # Look up members directly in Actors
    actors = Actor.get_personal_members().select_related(
        'address', 'address__zipcode')
    for word in request.POST['q'].split():
        actors = actors.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word) |
            Q(email__icontains=word) |
            Q(memberid__icontains=word)
        )
    actors = actors.order_by('first_name')[:SEARCH_MAX_HITS]

    # Cache all the actor objects because we will be accessing them through
    # user objects later
    Actor.cache_all(actors)

    # Look up pending members directly in Enrollment
    enrollments = Enrollment.get_active()
    for word in request.POST['q'].split():
        enrollments = enrollments.filter(
            Q(first_name__icontains=word) |
            Q(last_name__icontains=word) |
            Q(memberid__icontains=word)
        )
    enrollments = enrollments.order_by('first_name')[:SEARCH_MAX_HITS]

    # Create a list of all memberids
    focus_memberids = (
        [a.memberid for a in actors]
        + [e.memberid for e in enrollments])

    # Select user objects based on the known memberids
    members = User.get_users(
        include_pending=True,
    ).filter(
        memberid__in=focus_memberids,
    )

    # Create users for any members who don't have a User object
    memberids_existing = [u.memberid for u in members]
    memberids_missing = [
        m for m in focus_memberids
        if m not in memberids_existing]
    created_members = [
        User.get_or_create_inactive(memberid=memberid)
        for memberid in memberids_missing]

    users = list(nonmembers) + list(members) + list(created_members)

    max_hits_exceeded = len(nonmembers) >= SEARCH_MAX_HITS or \
        len(actors) >= SEARCH_MAX_HITS or \
        len(enrollments) >= SEARCH_MAX_HITS

    # Match expired users only on memberid
    expired_users = User.objects.all()
    for word in request.POST['q'].split():
        expired_users = expired_users.filter(memberid__icontains=word)
    expired_users = [
        u for u in expired_users
        if not Actor.get_personal_members().only('id').filter(
            memberid=u.memberid).exists()
        and not Enrollment.get_active().only('id').filter(
            memberid=u.memberid).exists()
    ]

    context = {
        'users': users,
        'expired_users': expired_users,
        'max_hits_exceeded': max_hits_exceeded,
    }
    return HttpResponse(render_to_string('central/admin/users/user_results.html', context, request=request))
Пример #26
0
def verification(request):
    enrollment = get_or_create_enrollment(request)

    if enrollment.state == 'payment':
        # Payment has been initiated but the user goes back here - why?
        # Reset the state and let them reinitiate payment when they're ready.
        enrollment.state = 'registration'
        enrollment.save()
    elif enrollment.state == 'complete':
        # A previous registration has been completed, so why would the user come directly here?
        # Just redirect them back to registration which will restart a new registration.
        return redirect("enrollment:registration")

    # If existing member is specified, save details and change to that address
    existing_name = ''
    if enrollment.existing_memberid != '':
        user = User.get_or_create_inactive(memberid=enrollment.existing_memberid)
        existing_name = user.get_full_name()
        enrollment.country = user.address.country.code
        if user.address.country.code == 'NO':
            enrollment.address1 = user.address.field1
        elif user.address.country.code in ['DK', 'SE']:
            # Don't change the user-provided address.
            # The user might potentially provide a different address than the existing member, which isn't allowed,
            # but this is preferable to trying to parse the existing address into zipcode, area etc. In order to
            # enforce the same address, the address logic for DK and SE in enrollment.User.save_to_focus would have to
            # be rewritten.
            pass
        else:
            # Uppercase the country code as Focus doesn't use consistent casing
            enrollment.country = user.address.country.code
            enrollment.address1 = user.address.field1
            enrollment.address2 = user.address.field2
            enrollment.address3 = user.address.field3

    # Get the area name for this zipcode
    if enrollment.country == 'NO':
        enrollment.area = Zipcode.get_by_zipcode(zipcode=enrollment.zipcode).area

    # Figure out which forening this member/these members will belong to
    if enrollment.existing_memberid != '':
        # Use main members' forening if applicable
        existing_user = User.get_or_create_inactive(memberid=enrollment.existing_memberid)
        forening = existing_user.main_forening(convert_dnt_oslo_for_youth=False)
    else:
        if enrollment.country == 'NO':
            focus_forening_id = cache.get('focus.zipcode_forening.%s' % enrollment.zipcode)
            if focus_forening_id is None:
                focus_forening_id = FocusZipcode.objects.get(zipcode=enrollment.zipcode).main_forening_id
                cache.set('focus.zipcode_forening.%s' % enrollment.zipcode, focus_forening_id, 60 * 60 * 24 * 7)
            forening = cache.get('forening.focus.%s' % focus_forening_id)
            if forening is None:
                forening = Forening.objects.get(focus_id=focus_forening_id)
                cache.set('forening.focus.%s' % focus_forening_id, forening, 60 * 60 * 24 * 7)
        else:
            # Foreign members are registered with DNT Oslo og Omegn
            forening = cache.get('forening.%s' % Forening.DNT_OSLO_ID)
            if forening is None:
                forening = Forening.objects.get(id=Forening.DNT_OSLO_ID)
                cache.set('forening.%s' % Forening.DNT_OSLO_ID, forening, 60 * 60 * 24 * 7)
    enrollment.forening = forening
    enrollment.save()

    context = {
        'enrollment': enrollment,
        'existing_name': existing_name,
        'age_senior': settings.MEMBERSHIP['AGES']['SENIOR'],
        'age_main': settings.MEMBERSHIP['AGES']['MAIN'],
        'age_youth': settings.MEMBERSHIP['AGES']['YOUTH'],
        'age_school': settings.MEMBERSHIP['AGES']['SCHOOL'],
        'membership_type_names': {
            'family_primary': get_membership_type_by_codename('family_primary')['name'],
            'main': get_membership_type_by_codename('main')['name'],
            'youth': get_membership_type_by_codename('youth')['name'],
            'senior': get_membership_type_by_codename('senior')['name'],
            'child': get_membership_type_by_codename('child')['name'],
            'school': get_membership_type_by_codename('school')['name'],
            'household': get_membership_type_by_codename('household')['name'],
            'family_household': get_membership_type_by_codename('family_household')['name'],
        },
        'foreign_shipment_price': FOREIGN_SHIPMENT_PRICE,
    }
    context.update(current_template_layout(request))
    return render(request, 'central/enrollment/verification.html', context)
Пример #27
0
    def get_queryset(self):
        # This method uses Focus and local users to compile a search result
        # containing users.

        # See the comment on the class definition of the lazy_queryset variable
        if self.lazy_queryset:
            return self.lazy_queryset

        SEARCH_MAX_HITS = 100
        search = self.request.query_params.get('search', '').strip()

        if len(search) < settings.ADMIN_USER_SEARCH_CHAR_LENGTH:
            raise PermissionDenied

        local_users = User.get_users().filter(memberid__isnull=True)
        for word in search.split():
            local_users = local_users.filter(
                Q(first_name__icontains=word) |
                Q(last_name__icontains=word) |
                Q(email__icontains=word))
        local_users = local_users.order_by('first_name')[:SEARCH_MAX_HITS]

        actors = Actor.get_personal_members().select_related(
            'address', 'address__zipcode')
        for word in search.split():
            actors = actors.filter(
                Q(first_name__icontains=word) |
                Q(last_name__icontains=word) |
                Q(memberid__icontains=word) |
                Q(email__icontains=word))
        actors = actors.order_by('first_name')[:SEARCH_MAX_HITS]

        # Cache all the actor objects because we will be accessing them through
        # user objects later
        Actor.cache_all(actors)

        # Match expired users only on memberid
        expired_users = User.objects.all()
        for word in search.split():
            expired_users = expired_users.filter(memberid__icontains=word)
        expired_users = [
            u for u in expired_users
            if not Actor.get_personal_members().only('id').filter(
                memberid=u.memberid).exists() and not Enrollment.get_active()
            .only('id').filter(memberid=u.memberid).exists()
        ]

        # Pending users
        pending_enrollment = Enrollment.get_active()
        for word in search.split():
            pending_enrollment = pending_enrollment.filter(
                Q(first_name__icontains=word) |
                Q(last_name__icontains=word) |
                Q(memberid__icontains=word))
        pending_enrollment = pending_enrollment.order_by(
            'first_name')[:SEARCH_MAX_HITS]

        members = User.get_users().filter(
            memberid__in=[a.memberid for a in actors])
        user_member_ids = list(members.values_list('memberid', flat=True))
        pending_users = User.get_users(include_pending=True).filter(
            memberid__in=[e.memberid for e in pending_enrollment])

        # Create inactive users for any actor hit without a corresponding user
        newly_created_members = [
            User.get_or_create_inactive(memberid=a.memberid) for a in actors
            if a.memberid not in user_member_ids
        ]

        users = sorted(
            list(local_users) + list(members) + list(pending_users) +
            list(newly_created_members),
            key=lambda u: u.get_full_name())

        self.lazy_queryset = users
        return users