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
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
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)
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 )
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
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
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
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
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()]
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 ]
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 }))
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
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)
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 )
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(), }))
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
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
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 }))
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 )
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
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 )
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)
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)
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, }))
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))
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)
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