def user_show_groups_json(user_id, group_filter="all"): memberships = Membership.q.filter(Membership.user_id == user_id) if group_filter == "active": memberships = memberships.filter( # it is important to use == here, "is" does NOT work or_(Membership.begins_at == None, Membership.begins_at <= session.utcnow()) ).filter( # it is important to use == here, "is" does NOT work or_(Membership.ends_at == None, Membership.ends_at > session.utcnow()) ) return jsonify(items=[{ 'group_name': membership.group.name, 'begins_at': (datetime_filter(membership.begins_at) if membership.begins_at is not None else ''), 'ends_at': (datetime_filter(membership.ends_at) if membership.ends_at is not None else ''), 'actions': [{'href': url_for(".edit_membership", user_id=user_id, membership_id=membership.id), 'title': 'Bearbeiten', 'icon': 'glyphicon-edit'}, {'href': url_for(".end_membership", user_id=user_id, membership_id=membership.id), 'title': "Beenden", 'icon': 'glyphicon-off'} if membership.active() else {}], } for membership in memberships.all()])
def json_trafficdata(user_id, days=7): """Generate a JSON file to use with traffic and credit graphs. :param user_id: :param days: optional amount of days to be included :return: JSON with traffic and credit data formatted according to the following schema { "type": "object", "properties": { "items": { "type": "object", "properties": { "traffic": { "type": "array", "items": { "type": "object", "properties": { "egress": { "type": "integer" }, "ingress": { "type": "integer" }, "timestamp": { "type": "string" } } } } } } } } } """ interval = timedelta(days=days) result = traffic_history(user_id, session.utcnow() - interval + timedelta(days=1), session.utcnow()) return jsonify(items={'traffic': [e.__dict__ for e in result]})
def check_new_user_data(login: str, email: str, name: str, swdd_person_id: Optional[int], room: Optional[Room], move_in_date: Optional[date], ignore_similar_name: bool = False, allow_existing: bool = False): user_swdd_person_id = get_user_by_swdd_person_id(swdd_person_id) if user_swdd_person_id and not allow_existing: raise UserExistsException user_login = User.q.filter_by(login=login).first() if user_login is not None and not allow_existing: raise LoginTakenException user_email = User.q.filter_by(email=email).first() if user_email is not None and not allow_existing: raise EmailTakenException if room is not None and not ignore_similar_name: check_similar_user_in_room(name, room) if move_in_date is not None: if move_in_date > (session.utcnow() + timedelta(days=180) ).date() or move_in_date < session.utcnow().date(): raise MoveInDateInvalidException
def test_free_membership(self): self.user_membership.begins_at = session.utcnow().replace( day=self.membership_fee_current.booking_end.days + 1) end_date = last_day_of_month(session.utcnow().date()) self.assertEquals(0.00, estimate_balance(self.user, end_date))
def sync_exceeded_traffic_limits(): """Adds and removes memberships of the 'traffic_limit_exceeded group.' """ processor = User.q.get(0) # Add memberships users = User.q.join(User._current_traffic_balance) \ .filter(CurrentTrafficBalance.amount < 0) \ .except_(User.q.join(User.current_properties)\ .filter(or_(CurrentProperty.property_name == 'traffic_limit_disabled',\ CurrentProperty.property_name == 'traffic_limit_exceeded')))\ .all() for user in users: make_member_of(user, config.traffic_limit_exceeded_group, processor, closed(session.utcnow(), None)) print("Traffic-Limit exceeded: " + user.name) # End memberships users = User.q.join(User.current_properties) \ .filter(CurrentProperty.property_name == 'traffic_limit_exceeded') \ .join(User._current_traffic_balance) \ .filter(or_(CurrentTrafficBalance.amount >= 0, CurrentProperty.property_name == 'traffic_limit_disabled')) \ .all() for user in users: remove_member_of(user, config.traffic_limit_exceeded_group, processor, closed(session.utcnow(), None)) print("Traffic-Limit no longer exceeded: " + user.name)
def test_active_memberships(self): self.assertEqual(self.user.active_memberships(), []) m = self.add_membership(self.property_group) self.assertEqual(self.user.active_memberships(), [m]) when = single(session.utcnow() - timedelta(hours=1)) self.assertEqual(self.user.active_memberships(when), []) when = single(session.utcnow() + timedelta(hours=1)) self.assertEqual(self.user.active_memberships(when), [m])
def test_active_memberships(self): self.assertEqual(self.user.active_memberships(), []) m = self.add_membership(self.property_group) self.assertEqual(self.user.active_memberships(), [m]) when = single(session.utcnow() - timedelta(hours=1)) self.assertEqual(self.user.active_memberships(when), []) when = single(session.utcnow() + timedelta(hours=1)) self.assertEqual(self.user.active_memberships(when), [m])
def test_active_traffic_groups(self): self.assertEqual(self.user.active_traffic_groups(), []) self.add_membership(self.traffic_group) self.assertEqual(self.user.active_traffic_groups(), [self.traffic_group]) when = single(session.utcnow() - timedelta(hours=1)) self.assertEqual(self.user.active_traffic_groups(when), []) when = single(session.utcnow() + timedelta(hours=1)) self.assertEqual(self.user.active_traffic_groups(when), [self.traffic_group])
def test_active_traffic_groups(self): self.assertEqual(self.user.active_traffic_groups(), []) self.add_membership(self.traffic_group) self.assertEqual(self.user.active_traffic_groups(), [self.traffic_group]) when = single(session.utcnow() - timedelta(hours=1)) self.assertEqual(self.user.active_traffic_groups(when), []) when = single(session.utcnow() + timedelta(hours=1)) self.assertEqual(self.user.active_traffic_groups(when), [self.traffic_group])
def test_active_traffic_groups_expression(self): query = self.create_active_traffic_groups_query() self.assertEqual(query.all(), []) self.add_membership(self.traffic_group) query = self.create_active_traffic_groups_query() self.assertEqual(query.all(), [self.traffic_group]) when = single(session.utcnow() - timedelta(hours=1)) query = self.create_active_traffic_groups_query(when) self.assertEqual(query.all(), []) when = single(session.utcnow() + timedelta(hours=1)) query = self.create_active_traffic_groups_query(when) self.assertEqual(query.all(), [self.traffic_group])
def test_active_property_groups_expression(self): query = self.create_active_property_groups_query() self.assertEqual(query.all(), []) self.add_membership(self.property_group) query = self.create_active_property_groups_query() self.assertEqual(query.all(), [self.property_group]) when = single(session.utcnow() - timedelta(hours=1)) query = self.create_active_property_groups_query(when) self.assertEqual(query.all(), []) when = single(session.utcnow() + timedelta(hours=1)) query = self.create_active_property_groups_query(when) self.assertEqual(query.all(), [self.property_group])
class MembershipFeeFactory(BaseFactory): class Meta: model = MembershipFee name = Faker('word') regular_fee = 5.00 booking_begin = timedelta(3) booking_end = timedelta(14) payment_deadline = timedelta(14) payment_deadline_final = timedelta(62) begins_on = LazyAttribute(lambda o: session.utcnow().date().replace(day=1)) ends_on = LazyAttribute(lambda o: last_day_of_month(session.utcnow()))
def test_set_correct_dates(self): # add membership to group1 p1 = Membership(user=self.user, group=self.property_group1) p1.begins_at = session.utcnow() p1.ends_at = session.utcnow() session.session.add(p1) session.session.commit() p1.begins_at = session.utcnow() - timedelta(days=3) p1.ends_at = session.utcnow() + timedelta(days=3) session.session.commit()
def test_0040_set_correct_dates(self): # add membership to group1 p1 = Membership(user=self.user, group=self.property_group1) p1.begins_at = session.utcnow() p1.ends_at = session.utcnow() session.session.add(p1) session.session.commit() p1.begins_at = session.utcnow() - timedelta(days=3) p1.ends_at = session.utcnow() + timedelta(days=3) session.session.commit()
def schedule(self, due, user, parameters, processor): if due < session.utcnow(): raise ValueError("the due date must be in the future") task = UserTask(type=self.type, due=due, creator=processor, created=session.utcnow(), user=user) task.parameters = parameters return task
def schedule_user_task(task_type, due, user, parameters: TaskParams, processor): if due < session.utcnow(): raise ValueError("the due date must be in the future") task = UserTask(type=task_type, due=due, creator=processor, created=session.utcnow(), user=user) task.parameters = parameters session.session.add(task) return task
def create_factories(self): ConfigFactory.create() self.processor = UserFactory.create() self.last_month_last = session.utcnow().replace(day=1) - timedelta(1) self.last_month_last_date = self.last_month_last.date() self.membership_fee_last = MembershipFeeFactory.create( begins_on=self.last_month_last_date.replace(day=1), ends_on=self.last_month_last_date) payment_deadline = timedelta(14) payment_deadline_final = timedelta(62) no_pid_action_date = session.utcnow() - payment_deadline + timedelta(1) pid_state_date = no_pid_action_date - timedelta(1) pid_no_end_membership_date = session.utcnow( ) - payment_deadline_final + timedelta(1) pid_end_membership_date = pid_no_end_membership_date - timedelta(1) self.membership_fee_no_pid_action = MembershipFeeFactory.create( begins_on=no_pid_action_date, ends_on=no_pid_action_date, booking_begin=timedelta(1), booking_end=timedelta(1), ) self.membership_fee_pid_state = MembershipFeeFactory.create( begins_on=pid_state_date, ends_on=pid_state_date, booking_begin=timedelta(1), booking_end=timedelta(1), ) self.membership_fee_no_end_membership = MembershipFeeFactory.create( begins_on=pid_no_end_membership_date, ends_on=pid_no_end_membership_date, booking_begin=timedelta(1), booking_end=timedelta(1), ) self.membership_fee_pid_end_membership = MembershipFeeFactory.create( begins_on=pid_end_membership_date, ends_on=pid_end_membership_date, booking_begin=timedelta(1), booking_end=timedelta(1), )
def finish_member_request(prm: PreMember, processor: User | None, ignore_similar_name: bool = False): if prm.room is None: raise ValueError("Room is None") if prm.move_in_date is not None and prm.move_in_date < session.utcnow( ).date(): prm.move_in_date = session.utcnow().date() check_new_user_data(prm.login, prm.email, prm.name, prm.swdd_person_id, prm.room, prm.move_in_date, ignore_similar_name) user, _ = create_user(prm.name, prm.login, prm.email, prm.birthdate, groups=[], processor=processor, address=prm.room.address, passwd_hash=prm.passwd_hash) processor = processor if processor is not None else user user.swdd_person_id = prm.swdd_person_id user.email_confirmed = prm.email_confirmed move_in_datetime = utc.with_min_time(prm.move_in_date) move_in(user, prm.room.building_id, prm.room.level, prm.room.number, None, processor if processor is not None else user, when=move_in_datetime) message = deferred_gettext("Created from registration {}.").format( str(prm.id)).to_json() log_user_event(message, processor, user) if move_in_datetime > session.utcnow(): make_member_of(user, config.pre_member_group, processor, closed(session.utcnow(), None)) session.session.delete(prm) return user
def transaction_confirm_all(processor): # Confirm all transactions older than one hour that are not confirmed yet transactions = Transaction.q.filter_by(confirmed=False)\ .filter(Transaction.posted_at < session.utcnow() - timedelta(hours=1)) for transaction in transactions: transaction_confirm(transaction, processor)
def test_adding_single_membership(self): begins_at = session.utcnow() ends_at = begins_at + timedelta(hours=1) during = closed(begins_at, ends_at) self.add_membership(during) self.assertMembershipIntervalsEqual(IntervalSet(during))
def test_0030_add_timed_membership(self): # add membership to group1 now = session.utcnow() membership = Membership( begins_at=now, user=self.user, group=self.property_group1 ) membership.ends_at = membership.begins_at + timedelta(days=3) session.session.add(membership) session.session.commit() self.assertTrue(self.user.has_property(PropertyData.prop_test1.name)) self.assertFalse(self.user.has_property(PropertyData.prop_test2.name)) # add expired membership to group2 membership = Membership( begins_at=now - timedelta(hours=2), user=self.user, group=self.property_group2 ) membership.ends_at = now - timedelta(hours=1) session.session.add(membership) session.session.commit() self.assertTrue(self.user.has_property(PropertyData.prop_test1.name)) self.assertFalse(self.user.has_property(PropertyData.prop_test2.name))
def unblock(user, processor, when=None): """Unblocks a user. This removes his membership of the ``config.violation`` group. Note that for unblocking, no further asynchronous action has to be triggered, as opposed to e.g. membership termination. :param User user: The user to be unblocked. :param User processor: The admin who unblocked the user. :param datetime when: The time of membership termination. Note that in comparison to :py:func:`suspend`, you don't provide an _interval_, but a point in time, defaulting to the current time. Will be converted to ``closedopen(when, None)``. :return: The unblocked user. """ if when is None: when = session.utcnow() remove_member_of(user=user, group=config.violation_group, processor=processor, during=closedopen(when, None)) message = deferred_gettext(u"User has been unblocked.") log_user_event(message=message.to_json(), author=processor, user=user) return user
def execute_scheduled_tasks(): tasks = (session.session.query(with_polymorphic(Task, "*")) .filter(Task.status == TaskStatus.OPEN, Task.due <= session.utcnow()) .all()) print("executing {} scheduled tasks".format(len(tasks))) for task in tasks: repair_session() task_impl = task_type_to_impl.get(task.type)() try: task_impl.execute(task) except Exception as e: task_impl.errors.append(str(e)) repair_session() if task_impl.new_status is not None: task.status = task_impl.new_status if task_impl.errors: task.errors = task_impl.errors for error in task.errors: print("Error while executing task: {}".format(error)) write_task_message(task, "Processed {} task. Status: {}".format( task.type.name, task.status.name), log=True) session.session.commit()
def test_adding_single_membership(self): begins_at = session.utcnow() ends_at = begins_at + timedelta(hours=1) during = closed(begins_at, ends_at) self.add_membership(during) self.assertMembershipIntervalsEqual(IntervalSet(during))
def unblock(user, processor, when=None): """Unblocks a user. This removes his membership of the violation, blocken and payment_in_default group. Note that for unblocking, no further asynchronous action has to be triggered, as opposed to e.g. membership termination. :param User user: The user to be unblocked. :param User processor: The admin who unblocked the user. :param datetime when: The time of membership termination. Note that in comparison to :py:func:`suspend`, you don't provide an _interval_, but a point in time, defaulting to the current time. Will be converted to ``closedopen(when, None)``. :return: The unblocked user. """ if when is None: when = session.utcnow() for group in get_blocked_groups(): if user.member_of(group): remove_member_of(user=user, group=group, processor=processor, during=closedopen(when, None)) return user
def timesince_filter(dt, default="just now"): """ Returns string representing "time since" e.g. 3 days ago, 5 hours ago etc. adopted from http://flask.pocoo.org/snippets/33/ """ if dt is None: return "k/A" now = session.utcnow() diff = now - dt periods = ( (diff.days / 365, "Jahr", "Jahre"), (diff.days / 30, "Monat", "Monate"), (diff.days / 7, "Woche", "Wochen"), (diff.days, "Tag", "Tage"), (diff.seconds / 3600, "Stunde", "Stunden"), (diff.seconds / 60, "Minute", "Minuten"), (diff.seconds, "Sekunde", "Sekunden"), ) for period, singular, plural in periods: if period: return "vor {:d} {}".format(period, singular if period == 1 else plural) return default
def remove_old_traffic_data(): TrafficVolume.q.filter( TrafficVolume.timestamp < (session.utcnow() - timedelta(7))).delete() session.session.commit() print("Deleted old traffic data")
def block(user, reason, processor, during=None, violation=True): """Suspend a user during a given interval. The user is added to violation_group or blocked_group in a given interval. A reason needs to be provided. :param User user: The user to be suspended. :param unicode reason: The reason for suspending. :param User processor: The admin who suspended the user. :param Interval|None during: The interval in which the user is suspended. If None the user will be suspendeded from now on without an upper bound. :param Boolean violation: If the user should be added to the violation group :return: The suspended user. """ if during is None: during = closedopen(session.utcnow(), None) if violation: make_member_of(user, config.violation_group, processor, during) else: make_member_of(user, config.blocked_group, processor, during) message = deferred_gettext(u"Suspended during {during}. Reason: {reason}.") log_user_event(message=message.format(during=during, reason=reason) .to_json(), author=processor, user=user) return user
def timesince_filter(dt, default="just now"): """ Returns string representing "time since" e.g. 3 days ago, 5 hours ago etc. adopted from http://flask.pocoo.org/snippets/33/ """ if dt is None: return "k/A" now = session.utcnow() diff = now - dt periods = ( (diff.days / 365, "Jahr", "Jahre"), (diff.days / 30, "Monat", "Monate"), (diff.days / 7, "Woche", "Wochen"), (diff.days, "Tag", "Tage"), (diff.seconds / 3600, "Stunde", "Stunden"), (diff.seconds / 60, "Minute", "Minuten"), (diff.seconds, "Sekunde", "Sekunden"), ) for period, singular, plural in periods: if period: return f"vor {period:d} {singular if period == 1 else plural}" return default
def add_membership(user_id): user = get_user_or_404(user_id) form = UserAddGroupMembership() if form.validate_on_submit(): if form.begins_at.data is not None: begins_at = datetime.combine(form.begins_at.data, utc.time_min()) else: begins_at = session.utcnow() if not form.ends_at.unlimited.data: ends_at = datetime.combine(form.ends_at.date.data, utc.time_min()) else: ends_at = None make_member_of(user, form.group.data, current_user, closed(begins_at, ends_at)) message = u"Nutzer zur Gruppe '{}' hinzugefügt.".format(form.group.data.name) lib.logging.log_user_event(message, current_user, user) session.session.commit() flash(u'Nutzer wurde der Gruppe hinzugefügt.', 'success') return redirect(url_for(".user_show", user_id=user_id, _anchor='groups')) return render_template('user/add_membership.html', page_title=u"Neue Gruppenmitgliedschaft für Nutzer {}".format(user_id), user_id=user_id, form=form)
def create_factories(self): ConfigFactory.create() self.user = UserFactory.create() self.user_membership = MembershipFactory.create( active_during=closedopen(session.utcnow() - timedelta(weeks=52), None), user=self.user, group=config.member_group) last_month_last = session.utcnow().date().replace(day=1) - timedelta(1) self.membership_fee_current = MembershipFeeFactory.create() self.membership_fee_last = MembershipFeeFactory.create( begins_on=last_month_last.replace(day=1), ends_on=last_month_last)
def traffic_for_days(self, days): from pycroft.model.traffic import TrafficVolume return select(func.sum(TrafficVolume.amount).label('amount')) \ .where( TrafficVolume.timestamp >= (session.utcnow() - timedelta(days-1)).date() .where(TrafficVolume.user_id == self.id))
def test_0040_disable_membership(self): # add membership to group1 membership = Membership( begins_at=session.utcnow() - timedelta(hours=2), user=self.user, group=self.property_group1 ) session.session.add(membership) session.session.commit() self.assertTrue(self.user.has_property(PropertyData.prop_test1.name)) membership.disable(session.utcnow() - timedelta(hours=1)) session.session.commit() self.assertNotIn( self.property_group1, self.user.active_property_groups() ) self.assertFalse(self.user.has_property(PropertyData.prop_test1.name)) # add membership to group1 membership = Membership( begins_at=session.utcnow(), user=self.user, group=self.property_group1 ) session.session.add(membership) session.session.commit() self.assertTrue(self.user.has_property(PropertyData.prop_test1.name)) # add membership to group2 membership = Membership( begins_at=session.utcnow() - timedelta(hours=2), user=self.user, group=self.property_group2 ) session.session.add(membership) session.session.commit() self.assertTrue(self.user.has_property(PropertyData.prop_test1.name)) self.assertTrue(self.user.has_property(PropertyData.prop_test2.name)) # disables membership in group2 membership.disable(session.utcnow() - timedelta(hours=1)) session.session.commit() self.assertTrue(self.user.has_property(PropertyData.prop_test1.name)) self.assertFalse(self.user.has_property(PropertyData.prop_test2.name))
def active_memberships(self, when=None): if when is None: now = session.utcnow() when = single(now) return [ m for m in self.memberships if when.overlaps(closed(m.begins_at, m.ends_at)) ]
def test_0010_group_users(self): self.assertEqual(len(self.property_group1.users), 0) self.assertEqual(len(self.property_group1.active_users()), 0) # add membership to group1 p1 = Membership(begins_at=session.utcnow() - timedelta(hours=2), user=self.user, group=self.property_group1) session.session.add(p1) session.session.commit() self.assertEqual(len(self.property_group1.users), 1) self.assertEqual(len(self.property_group1.active_users()), 1) p1.disable(session.utcnow() - timedelta(hours=1)) session.session.commit() self.assertEqual(len(self.property_group1.users), 1) self.assertEqual(len(self.property_group1.active_users()), 0)
def create_user_from1y(self, **kwargs): reg_date = session.utcnow() - timedelta(weeks=52) return UserWithMembershipFactory(registered_at=reg_date, membership__active_during=closedopen( reg_date, None), membership__group=config.member_group, **kwargs)
def traffic_for_days(self, days): from pycroft.model.traffic import TrafficVolume return sum( v.amount for v in TrafficVolume.q.filter_by(user_id=self.id).filter( TrafficVolume.timestamp >= (session.utcnow() - timedelta(days - 1)).date()))
def test_0030_start_date_after_end(self): # add membership to group1 now = session.utcnow() self.assertRaisesRegexp( AssertionError, "begins_at must be before ends_at", Membership, user=self.user, group=self.property_group1, begins_at=now + timedelta(days=1), ends_at=now )
def test_join_overlapping_memberships(self): begins_at1 = session.utcnow() ends_at1 = begins_at1 + timedelta(hours=2) during1 = closed(begins_at1, ends_at1) begins_at2 = begins_at1 + timedelta(hours=1) ends_at2 = begins_at1 + timedelta(hours=3) during2 = closed(begins_at2, ends_at2) self.add_membership(during1) self.add_membership(during2) self.assertMembershipIntervalsEqual(IntervalSet(closed(begins_at1, ends_at2)))
def test_removing_all_memberships(self): begins_at1 = session.utcnow() ends_at1 = begins_at1 + timedelta(hours=1) during1 = closed(begins_at1, ends_at1) begins_at2 = begins_at1 + timedelta(hours=2) ends_at2 = begins_at1 + timedelta(hours=3) during2 = closed(begins_at2, ends_at2) self.add_membership(during1) self.add_membership(during2) self.remove_membership() self.assertMembershipIntervalsEqual(IntervalSet())
def end_payment_in_default_memberships(): processor = User.q.get(0) users = User.q.join(User.current_properties) \ .filter(CurrentProperty.property_name == 'payment_in_default') \ .join(Account).filter(Account.balance <= 0).all() for user in users: remove_member_of(user, config.payment_in_default_group, processor, closedopen(session.utcnow(), None)) return users
def test_removing_memberships(self): t0 = session.utcnow() t1 = t0 + timedelta(hours=1) t2 = t0 + timedelta(hours=2) t3 = t0 + timedelta(hours=3) t4 = t0 + timedelta(hours=4) t5 = t0 + timedelta(hours=5) self.add_membership(closed(t0, t2)) self.add_membership(closed(t3, t5)) self.remove_membership(closed(t1, t4)) self.assertMembershipIntervalsEqual(IntervalSet( (closed(t0, t1), closed(t4, t5))))
def generate_user_data(user): try: traffic_maxmium = effective_traffic_group(user).credit_limit except NoTrafficGroup: traffic_maxmium = None props = {prop.property_name for prop in user.current_properties} user_status = status(user) interval = timedelta(days=7) step = timedelta(days=1) traffic_history = func_traffic_history(user.id, session.utcnow() - interval + step, interval, step) finance_history = [{ 'valid_on': split.transaction.posted_at, 'amount': split.amount, 'description': split.transaction.description } for split in build_transactions_query(user.account)] last_finance_update = finance_history[-1]['valid_on'] if finance_history \ else None return jsonify( id=user.id, user_id=encode_type2_user_id(user.id), name=user.name, login=user.login, status={ 'member': user_status.member, 'traffic_exceeded': user_status.traffic_exceeded, 'network_access': user_status.network_access, 'account_balanced': user_status.account_balanced, 'violation': user_status.violation }, room=str(user.room), interfaces=[ {'mac': str(i.mac), 'ips': [str(ip.address) for ip in i.ips]} for h in user.hosts for i in h.interfaces ], mail=user.email, cache='cache_access' in props, # TODO: make `has_property` use `current_property` properties=list(props), traffic_balance=user.current_credit, traffic_maximum=traffic_maxmium, traffic_history=[e.__dict__ for e in traffic_history], # TODO: think about better way for credit finance_balance=-user.account.balance, finance_history=finance_history, last_finance_update=last_finance_update )
def test_0050_clear_end_date(self): # add membership to group1 p1 = Membership(user=self.user, group=self.property_group1) p1.begins_at = session.utcnow() p1.ends_at = session.utcnow() session.session.add(p1) session.session.commit() # test if membership in database p1 = Membership.q.filter_by( user=self.user, group=self.property_group1 ).one() self.assertIsNotNone(p1.ends_at) # clear ends_at p1.ends_at = None session.session.commit() p1 = Membership.q.filter_by( user=self.user, group=self.property_group1 ).one() self.assertIsNone(p1.ends_at)
def grant_regular_credit(user): """Grant a user's regular credit The relevant :py:cls:`TrafficGroup` is the one with the largest ``credit_amount``. :param User user: the user to grant credit to """ now = session.utcnow() group = effective_traffic_group(user) credit = TrafficCredit(timestamp=now, amount=group.credit_amount, user_id=user.id) session.session.add(credit)
def has_property(self, property_name, when=None): """ :param str property_name: name of a property :param Interval when: """ if when is None: now = session.utcnow() when = single(now) prop_granted_flags = [ group.property_grants[property_name] for group in self.active_property_groups(when) if property_name in group.property_grants ] return all(prop_granted_flags) and any(prop_granted_flags)
def handle_payments_in_default(): processor = User.q.get(0) # Add memberships and end "member" membership if threshold met users = User.q.join(User.current_properties)\ .filter(CurrentProperty.property_name == 'membership_fee') \ .join(Account).filter(Account.balance > 0).all() users_pid_membership = [] users_membership_terminated = [] ts_now = session.utcnow() for user in users: last_pid_membership = Membership.q.filter(Membership.user_id == user.id) \ .filter(Membership.group_id == config.payment_in_default_group.id) \ .order_by(Membership.ends_at.desc()) \ .first() if last_pid_membership is not None: if last_pid_membership.ends_at is not None and \ last_pid_membership.ends_at >= ts_now - timedelta(days=7): continue in_default_days = user.account.in_default_days try: fee = get_membership_fee_for_date( date.today() - timedelta(days=in_default_days)) except NoResultFound: fee = get_last_applied_membership_fee() if not fee: return [], [] if not user.has_property('payment_in_default'): if in_default_days >= fee.payment_deadline.days: make_member_of(user, config.payment_in_default_group, processor, closed(ts_now, None)) users_pid_membership.append(user) if in_default_days >= fee.payment_deadline_final.days: remove_member_of(user, config.member_group, processor, closedopen(ts_now, None)) log_user_event("Mitgliedschaftsende wegen Zahlungsrückstand ({})" .format(fee.name), processor, user) users_membership_terminated.append(user) return users_pid_membership, users_membership_terminated
def test_0020_add_membership(self): # add membership to group1 membership = Membership( begins_at=session.utcnow(), user=self.user, group=self.property_group1 ) session.session.add(membership) session.session.commit() self.assertTrue(self.user.has_property(PropertyData.prop_test1.name)) self.assertFalse(self.user.has_property(PropertyData.prop_test2.name)) # add membership to group2 membership = Membership( begins_at=session.utcnow(), user=self.user, group=self.property_group2 ) session.session.add(membership) session.session.commit() self.assertTrue(self.user.has_property(PropertyData.prop_test1.name)) self.assertTrue(self.user.has_property(PropertyData.prop_test2.name))
def test_0010_create_user_log_entry(self): user_log_entry = log_user_event(message=self.message, author=self.user, user=self.user) self.assertEqual(user_log_entry.message, self.message) self.assertAlmostEqual(user_log_entry.created_at, session.utcnow(), delta=timedelta(seconds=5)) self.assertEqual(user_log_entry.author, self.user) self.assertEqual(user_log_entry.user, self.user) self.assertIsNotNone(LogEntry.q.get(user_log_entry.id)) session.session.delete(user_log_entry) session.session.commit() self.assertIsNone(LogEntry.q.get(user_log_entry.id))
def test_0020_end_date_before_start(self): # add membership to group1 p1 = Membership(user=self.user, group=self.property_group1) p1.begins_at = session.utcnow() def set_old_date(): """ Set ends_at before begins_at """ p1.ends_at = session.utcnow() - timedelta(hours=2) self.assertRaisesRegexp( AssertionError, "begins_at must be before ends_at", set_old_date )
def complex_transaction(description, author, splits, valid_on=None): if valid_on is None: valid_on = session.utcnow().date() objects = [] new_transaction = Transaction( description=description, author=author, valid_on=valid_on ) objects.append(new_transaction) objects.extend( Split(amount=amount, account=account, transaction=new_transaction) for (account, amount) in splits ) session.session.add_all(objects) return new_transaction
def __init__(self, label=None, validators=None, format='%Y-%m-%d', **kwargs): # Move Bootstrap datepicker specific options to its own dict self.datepicker_options = dict(( (option, value) for (option, value) in kwargs.items() if option in self.available_datepicker_options )) for option in self.datepicker_options.keys(): kwargs.pop(option) defaults = {'default': session.utcnow(), 'language': 'de', 'today_highlight': 'true', 'today_btn': 'linked'} self.datepicker_options = dict(chain(defaults.items(), self.datepicker_options.items())) # The format option is used by both DateField and Bootstrap datepicker, # albeit with a different format string syntax. self.datepicker_options['format'] = self.convert_format_string(format) super(DateField, self).__init__(label, validators, format, **kwargs)
def active(cls, when=None): """ Tests if memberships overlap with a given interval. If no interval is given, it tests if the memberships are active right now. :param Interval when: :return: """ if when is None: now = session.utcnow() when = single(now) return and_( or_(cls.begins_at == null(), literal(when.end) == null(), cls.begins_at <= literal(when.end)), or_(literal(when.begin) == null(), cls.ends_at == null(), literal(when.begin) <= cls.ends_at) ).label("active")
def json_trafficdata(user_id, days=7): """Generate a JSON file to use with traffic and credit graphs. :param user_id: :param days: optional amount of days to be included :return: JSON with traffic and credit data formatted according to the following schema { "type": "object", "properties": { "items": { "type": "object", "properties": { "credit_limit": { "type": "integer" }, "traffic": { "type": "array", "items": { "type": "object", "properties": { "balance": { "type": "integer" }, "credit": { "type": "integer" }, "egress": { "type": "integer" }, "ingress": { "type": "integer" }, "timestamp": { "type": "string" } } } } } } } } } """ interval = timedelta(days=days) step = timedelta(days=1) result = traffic_history(user_id, session.utcnow() - interval + step, interval, step) credit_limit = session.session.execute(User.active_traffic_groups().where( User.id == user_id).with_only_columns( [func.max(TrafficGroup.credit_limit)])).scalar() return jsonify( items={ 'traffic': [e.__dict__ for e in result], 'credit_limit': credit_limit } )
def test_deferred_blocking_and_unblocking_works(self): u = self.user_to_block blockage = session.utcnow() + timedelta(days=1) unblockage = blockage + timedelta(days=2) blocked_user = UserHelper.suspend(u, reason=u"test", processor=u, during=closedopen(blockage, None)) session.session.commit() blocked_during = closedopen(blockage, unblockage) self.assertEqual(u.log_entries[0].author, blocked_user) self.assert_violation_membership(blocked_user, subinterval=blocked_during) unblocked_user = UserHelper.unblock(blocked_user, processor=u, when=unblockage) session.session.commit() self.assertEqual(unblocked_user.log_entries[0].author, unblocked_user) self.assert_violation_membership(unblocked_user, subinterval=blocked_during)