def validate_period(self, field): periods = PeriodCollection(self.request.session) period = periods.by_id(field.data) if not period.finalized: raise ValidationError( "The billing of this period has not been finalized yet")
def clone_occasion(self, request, form): if form.submitted(request): occasions = OccasionCollection(request.session) periods = PeriodCollection(request.session) form.populate_obj(occasions.add( activity=self.activity, start=form.parsed_dates[0].start, end=form.parsed_dates[0].end, timezone=form.timezone, period=periods.by_id(form.period_id.data) )) request.success(_("Your changes were saved")) return request.redirect(request.link(self.activity)) elif not request.POST: form.process(obj=self) return { 'layout': OccasionFormLayout( self.activity, request, _("Clone Occasion")), 'title': _("Clone Occasion"), 'form': form }
def period_choices(self): periods = PeriodCollection(self.request.session) q = periods.query() q = q.with_entities(Period.id, Period.title) q = q.order_by(desc(Period.active), desc(Period.prebooking_start)) def choice(row): return row.id.hex, row.title return [choice(p) for p in q]
def get_occasion_attendee_collection(request, app, activity_name, period_id=None): # load the activity activity = get_vacation_activity(request, app, activity_name) if not activity: return None # the default period is the active period or the first we can find if not period_id: period = app.default_period else: period = PeriodCollection(app.session()).by_id(period_id) if not period: return None # non-admins are automatically limited to the activites they own if request.is_admin: username = None else: username = request.current_username return OccasionAttendeeCollection( app.session(), period, activity, username)
def setup_period_choices(self): query = PeriodCollection(self.request.session).query() query = query.order_by(desc(Period.active), Period.title) def choice(period): return str(period.id), '{} ({:%d.%m.%Y} - {:%d.%m.%Y})'.format( period.title, period.execution_start, period.execution_end ) periods = query.all() self.period_id.choices = [choice(p) for p in periods] if self.period_id.data == '0xdeadbeef': self.period_id.data = periods[0].id
def get_variables(request): period = PeriodCollection(request.session).active() variables = TemplateVariables(request, period).bound return OrderedDict( (token, variables[token].__doc__) for token in sorted(variables) )
def handle_send_notification(self, request, form): period = PeriodCollection(request.session).active() variables = TemplateVariables(request, period) layout = NotificationTemplateLayout(self, request) if form.submitted(request): recipients = form.recipients if not recipients: request.alert(_("There are no recipients matching the selection")) else: current = request.current_username if current not in recipients: recipients.add(current) subject = variables.render(self.subject) content = render_template('mail_notification.pt', request, { 'layout': DefaultMailLayout(self, request), 'title': subject, 'notification': variables.render(self.text) }) plaintext = html_to_text(content) for recipient in recipients: request.app.send_marketing_email( receivers=(recipient, ), subject=subject, content=content, plaintext=plaintext, ) self.last_sent = utcnow() request.success(_( "Successfully sent the e-mail to ${count} recipients", mapping={ 'count': len(recipients) } )) return request.redirect( request.class_link(NotificationTemplateCollection)) return { 'title': _("Mailing"), 'layout': layout, 'form': form, 'preview_subject': variables.render(self.subject), 'preview_body': variables.render(self.text), 'edit_link': request.return_here(request.link(self, 'edit')), 'button_text': _("Send E-Mail Now") }
def get_billing(request, app, period_id, username=None, expand=False): # the default period is the active period or the first we can find if not period_id: period = app.default_period else: period = PeriodCollection(app.session()).by_id(period_id) if not period: return None return BillingCollection(request, period, username, expand)
def get_matches(request, app, period_id, states=None): # the default period is the active period or the first we can find if not period_id: period = app.default_period else: period = PeriodCollection(app.session()).by_id(period_id) if not period: return None return MatchCollection(app.session(), period, states)
def get_period(request, app, id): return PeriodCollection(app.session()).by_id(id)
def selected_period(self): return PeriodCollection(self.request.session).by_id(self.period.data)
def period_choices(self): q = PeriodCollection(self.request.session).query() q = q.with_entities(Period.id, Period.title) q = q.order_by(Period.execution_start) return [(row.id.hex, row.title) for row in q]
def periods_by_id(self): return { p.id.hex: p for p in PeriodCollection(self.session()).query() }
def periods(self): p = PeriodCollection(self.session()).query() p = p.order_by(Period.execution_start) return p
def active_period(self): return PeriodCollection(self.session()).active()
def get_periods(request, app): return PeriodCollection(app.session())
def test_notification_template_send_form(session): activities = ActivityCollection(session, type='vacation') attendees = AttendeeCollection(session) periods = PeriodCollection(session) occasions = OccasionCollection(session) bookings = BookingCollection(session) users = UserCollection(session) admin = users.add(username='******', realname='Robert Baratheon', password='******', role='admin') organiser = users.add(username='******', realname=None, password='******', role='editor') users.add(username='******', realname=None, password='******', role='member') prebooking = tuple(d.date() for d in (datetime.now() - timedelta(days=1), datetime.now() + timedelta(days=1))) execution = tuple(d.date() for d in (datetime.now() + timedelta(days=10), datetime.now() + timedelta(days=12))) period = periods.add(title="Ferienpass 2016", prebooking=prebooking, execution=execution, active=True) foo = activities.add("Foo", username='******') foo.propose().accept() bar = activities.add("Bar", username='******') bar.propose().accept() o1 = occasions.add( start=datetime(2016, 11, 25, 8), end=datetime(2016, 11, 25, 16), age=(0, 10), spots=(0, 2), timezone="Europe/Zurich", activity=foo, period=period, ) o1.username = admin.username o2 = occasions.add( start=datetime(2016, 11, 25, 17), end=datetime(2016, 11, 25, 20), age=(0, 10), spots=(0, 2), timezone="Europe/Zurich", activity=bar, period=period, ) o2.username = organiser.username a1 = attendees.add(admin, 'Dustin', date(2000, 1, 1), 'male') a2 = attendees.add(organiser, 'Mike', date(2000, 1, 1), 'female') b1 = bookings.add(admin, a1, o1) b1.state = 'accepted' b1.cost = 100 b2 = bookings.add(organiser, a2, o2) b2.state = 'accepted' b2.cost = 100 transaction.commit() # create a mock request def invoice_collection(user_id=None, period_id=None): return InvoiceCollection(session, user_id=user_id, period_id=period_id) def request(admin): return Bunch(app=Bunch( active_period=periods.active(), org=Bunch(geo_provider='geo-mapbox'), invoice_collection=invoice_collection, periods=periods.query().all(), ), session=session, include=lambda *args: None, model=None, is_admin=admin, is_organiser_only=not admin and True or False, is_manager=admin and True or False, translate=lambda text, *args, **kwargs: text, locale='de_CH', current_username=(admin and '*****@*****.**' or '*****@*****.**')) # in the beginning there are no recipients form = NotificationTemplateSendForm() form.model = None form.request = request(admin=True) assert form.has_choices # we still have choices (like send to users) assert not form.occasion.choices # once the request is processed, the occasions are added form.on_request() assert form.has_choices assert len(form.occasion.choices) == 2 assert len(form.send_to.choices) == 7 # if the period is inactive, there are no occasions periods.query().one().active = False transaction.commit() form = NotificationTemplateSendForm() form.model = None form.request = request(admin=True) form.on_request() assert len(form.occasion.choices) == 0 # if the period is active but not confirmed, there are no recipients period = periods.query().one() period.active = True period.confirmed = False transaction.commit() form = NotificationTemplateSendForm() form.model = None form.request = request(admin=True) form.on_request() occasions = [c[0] for c in form.occasion.choices] # with organisers assert len(form.recipients_by_occasion(occasions, True)) == 2 # without assert len(form.recipients_by_occasion(occasions, False)) == 0 # the number of users is indepenedent of the period assert len(form.recipients_by_role(('admin', 'editor', 'member'))) == 3 assert len(form.recipients_by_role(('admin', 'editor'))) == 2 assert len(form.recipients_by_role(('admin', ))) == 1 # if the period is confirmed, there are accepted recipients period = periods.query().one() period.active = True period.confirmed = True transaction.commit() assert len(form.recipients_by_occasion(occasions)) == 2 # only accepted bookings are counted parent = admin.username bookings.query().filter_by(username=parent).one().state = 'cancelled' transaction.commit() # without organisers assert len(form.recipients_by_occasion(occasions, False)) == 1 # with assert len(form.recipients_by_occasion(occasions, True)) == 2 # inactive users may be exluded form.state.data = ['active'] assert len(form.recipients_pool) == 3 form.state.data = ['active', 'inactive'] assert len(form.recipients_pool) == 3 form.state.data = ['inactive'] assert len(form.recipients_pool) == 0 # bookings count towards the wishlist if the period is active, period = periods.query().one() period.active = True period.confirmed = False transaction.commit() form.request = request(admin=True) # do not count cancelled bookings... assert len(form.recipients_with_wishes()) == 2 assert len(form.recipients_with_bookings()) == 0 # otherwise they count towards the bookings period = periods.query().one() period.confirmed = True transaction.commit() form.request = request(admin=True) assert len(form.recipients_with_wishes()) == 0 assert len(form.recipients_with_bookings()) == 2 # count the active organisers form.request = request(admin=True) assert len(form.recipients_which_are_active_organisers()) == 2 # count the users with unpaid bills form.request = request(admin=True) assert len(form.recipients_with_unpaid_bills()) == 0 period = periods.query().one() billing = BillingCollection(request=Bunch( session=session, app=Bunch(invoice_collection=invoice_collection)), period=period) billing.create_invoices() transaction.commit() form.request = request(admin=True) assert len(form.recipients_with_unpaid_bills()) == 1 # organisers are not counted as active if the occasion has been cancelled occasions = OccasionCollection(session) occasions.query().first().cancelled = True transaction.commit() form.request = request(admin=True) assert len(form.recipients_which_are_active_organisers()) == 1 for occasion in occasions.query(): occasion.cancelled = False transaction.commit() form.request = request(admin=True) assert len(form.recipients_which_are_active_organisers()) == 2