예제 #1
0
 def has_activity_permission(owner, user, role, state):
     return has_private_permission_activities(app=None,
                                              identity=Bunch(userid=user,
                                                             role=role),
                                              model=Bunch(state=state,
                                                          username=owner),
                                              permission=Private)
예제 #2
0
 def has_permission(owner, user, role, state):
     return has_public_permission_logged_in(app=None,
                                            identity=Bunch(userid=user,
                                                           role=role),
                                            model=Bunch(state=state,
                                                        username=owner),
                                            permission=Public)
예제 #3
0
def test_translate_sponsor():

    sponsor = Sponsor(
        name="Evilcorp",
        logo={
            'de': 'das-logo.png',
            'fr': 'le-logo.png'
        },
        banners={'bookings': {
            'url': {
                'de': 'die-url',
                'fr': 'le-url'
            }
        }})

    de = sponsor.compiled(Bunch(locale='de_CH'))
    assert de.name == "Evilcorp"
    assert de.background is None
    assert de.logo == 'das-logo.png'
    assert de.banners == {'bookings': {'url': 'die-url'}}

    fr = sponsor.compiled(Bunch(locale='fr_CH'))
    assert fr.name == "Evilcorp"
    assert fr.background is None
    assert fr.logo == 'le-logo.png'
    assert fr.banners == {'bookings': {'url': 'le-url'}}
예제 #4
0
def test_vacation_activity_form(session, test_password):
    users = UserCollection(session)
    users.add(username='******',
              realname='Robert Baratheon',
              password='******',
              role='admin')
    users.add(username='******',
              realname=None,
              password='******',
              role='editor')
    users.add(username='******',
              realname=None,
              password='******',
              role='member')

    form = VacationActivityForm()
    form.request = Bunch(is_admin=True,
                         current_username='******',
                         session=session)

    form.on_request()

    assert form.username.data == '*****@*****.**'
    assert form.username.choices == [('*****@*****.**',
                                      '*****@*****.**'),
                                     ('*****@*****.**', 'Robert Baratheon')]

    form.request.is_admin = False
    form.on_request()

    assert form.username is None
예제 #5
0
 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 '*****@*****.**'))
예제 #6
0
파일: cli.py 프로젝트: OneGov/onegov.wtfs
    def load_files(path):

        prefix = 'tx_winscan_domain_model'

        files = Bunch()
        files.users = as_csv(path / 'User_Scanauftrag_neu.xlsx')
        files.bill = as_csv(path / f'{prefix}_bill.csv')
        files.date = as_csv(path / f'{prefix}_date.csv')
        files.paymenttype = as_csv(path / f'{prefix}_paymenttype.csv')
        files.township = as_csv(path / f'{prefix}_township.csv')
        files.transportorder = as_csv(path / f'{prefix}_transportorder.csv')
        files.transporttype = as_csv(path / f'{prefix}_transporttype.csv')

        return files
예제 #7
0
def test_town_create(onboarding_app, temporary_directory, smtp, redis_url):
    c = Client(onboarding_app)
    a = c.get('/for-towns/1')

    a.form['name'] = 'New York'
    a.form['user'] = '******'
    a.form['color'] = '#ff00ff'
    a = a.form.submit().follow()

    assert 'New York' in a
    assert '*****@*****.**' in a
    assert '#f0f' in a
    assert 'new-york.example.org' in a

    a = a.form.submit()

    assert 'https://new-york.example.org' in a
    assert '*****@*****.**' in a
    assert len(smtp.outbox) == 1

    username = '******'
    password = a.pyquery('.product dd:nth-child(4)').text()

    scan_morepath_modules(onegov.town.TownApp)
    morepath.commit(onegov.town.TownApp)

    town = TownApp()
    town.namespace = onboarding_app.onboarding['onegov.town']['namespace']
    town.configure_application(
        dsn=onboarding_app.dsn,
        filestorage='fs.osfs.OSFS',
        filestorage_options={
            'root_path': temporary_directory,
            'create': True
        },
        identity_secure=False,
        redis_url=redis_url,
        enable_elasticsearch=False,
        depot_backend='depot.io.memory.MemoryFileStorage')
    town.set_application_id(town.namespace + '/' + 'new_york')
    town.settings.cronjobs = Bunch(enabled=False)

    c = Client(town)
    p = c.get('/')

    assert "Willkommen bei der OneGov Cloud" in p
    assert "New York" in p

    p = c.get('/auth/login')
    p.forms[1]['username'] = username
    p.forms[1]['password'] = password
    p = p.forms[1].submit().follow()

    assert 'Benutzerprofil' in p
예제 #8
0
    def parse_definition(definition):
        for service in yaml.safe_load(definition):
            service_id = normalize_for_url(service['titel'])
            days = (d.strip() for d in service['tage'].split(','))

            yield service_id, Bunch(
                id=service_id,
                title=service['titel'],
                percentage=Decimal(service['prozent']),
                days=OrderedSet(SERVICE_DAYS[d.lower()[:2]] for d in days),
            )
예제 #9
0
def test_hint_field(wtfs_app):
    def get_translate(for_chameleon):
        return wtfs_app.chameleon_translations.get('de_CH')

    form = Form()
    field = HintField(macro='express_shipment_hint')
    field = field.bind(form, 'hint')
    field.meta.request = Bunch(app=wtfs_app, get_translate=get_translate)

    assert field.validate(form)
    assert "Für dringende Scan-Aufträge" in field()
예제 #10
0
def test_timestamp_sponsor():

    sponsor = Sponsor(name="Evilcorp",
                      logo={
                          'de': '{timestamp}',
                          'fr': '{timestamp}'
                      },
                      banners='{timestamp}')

    with freeze_time("2017-10-12 16:30"):
        de = sponsor.compiled(Bunch(locale='de_CH'))
        assert de.name == "Evilcorp"
        assert de.logo == '1507825800000'
        assert de.banners == '1507825800000'
예제 #11
0
    def ensure_no_payment_changes_after_confirmation(self):
        if isinstance(self.model, Period) and self.model.confirmed:
            preview = Bunch()
            self.populate_obj(preview)

            fields = ('all_inclusive', 'booking_cost')

            for field in fields:
                if getattr(self.model, field) != getattr(preview, field):
                    self.pass_system.errors.append(
                        _("It is no longer possible to change the execution "
                          "settings since the period has already been confirmed"
                          ))
                    return False
예제 #12
0
    def bills(self):
        bills = OrderedDict()
        invoices = self.invoices_by_period

        for username, items in groupby(invoices, lambda i: i.username):
            items = tuple(items)
            first = items[0]

            bills[username] = Bunch(
                items=items,
                first=first,
                id=first.id,
                invoice_id=first.invoice_id,
                title=first.realname or first.username,
                paid=first.invoice_paid,
                total=first.invoice_amount,
                outstanding=first.invoice_outstanding,
                discourage_changes=first.invoice_changes == 'discouraged',
                disable_changes=first.invoice_changes == 'impossible',
                has_online_payments=first.has_online_payments)

        return bills
예제 #13
0
def create_app(app_class,
               request,
               use_elasticsearch=False,
               reuse_filestorage=True,
               use_smtp=True,
               depot_backend='depot.io.local.LocalFileStorage',
               depot_storage_path=None):

    # filestorage can be reused between tries as it is nowadays mainly (if not
    # exclusively) used by the theme compiler
    if reuse_filestorage:
        filestorage_object = request.getfixturevalue('long_lived_filestorage')
    else:
        filestorage_object = None

    if not app_class.is_committed():
        scan_morepath_modules(app_class)
        app_class.commit()

    if use_elasticsearch:
        elasticsearch_hosts = [request.getfixturevalue('es_url')]
    else:
        elasticsearch_hosts = []

    if depot_backend == 'depot.io.local.LocalFileStorage':
        if not depot_storage_path:
            depot_storage_path = request.getfixturevalue('temporary_directory')

    temporary_path = request.getfixturevalue('temporary_path')
    signing_services = (temporary_path / 'signing-services')
    signing_services.mkdir()

    cert_file = module_path('onegov_testing', 'tests/fixtures/test.crt')
    cert_key = module_path('onegov_testing', 'tests/fixtures/test.crt')

    with (signing_services / '__default__.yml').open('w') as f:
        f.write(
            textwrap.dedent(f"""
            name: swisscom_ais
            parameters:
                customer: foo
                key_static: bar
                cert_file: {cert_file}
                cert_key: {cert_key}
        """))

    app = app_class()
    app.namespace = random_namespace()
    app.configure_application(
        dsn=request.getfixturevalue('postgres_dsn'),
        filestorage='fs.osfs.OSFS',
        filestorage_object=filestorage_object,
        depot_backend=depot_backend,
        depot_storage_path=depot_storage_path,
        identity_secure=False,
        enable_elasticsearch=use_elasticsearch,
        elasticsearch_hosts=elasticsearch_hosts,
        redis_url=request.getfixturevalue('redis_url'),
        yubikey_client_id='foo',
        yubikey_secret_key='dGhlIHdvcmxkIGlzIGNvbnRyb2xsZWQgYnkgbGl6YXJkcyE=',
        signing_services=str(signing_services))

    app.set_application_id(app.namespace + '/test')
    app.clear_request_cache()

    if hasattr(app, 'bind_depot'):
        app.bind_depot()

    # cronjobs leave lingering sessions open, in real life this is not a
    # problem, but in testing it leads to connection pool exhaustion
    app.settings.cronjobs = Bunch(enabled=False)

    if use_smtp:
        smtp = request.getfixturevalue('smtp')

        app.mail = {
            'marketing': {
                'host': smtp.address[0],
                'port': smtp.address[1],
                'force_tls': False,
                'username': None,
                'password': None,
                'use_directory': False,
                'sender': '*****@*****.**'
            },
            'transactional': {
                'host': smtp.address[0],
                'port': smtp.address[1],
                'force_tls': False,
                'username': None,
                'password': None,
                'use_directory': False,
                'sender': '*****@*****.**'
            }
        }

        app.smtp = smtp

    return app
예제 #14
0
 def app(self):
     return Bunch(org=self)
예제 #15
0
파일: cli.py 프로젝트: OneGov/onegov.wtfs
    def handle_import(request, app):
        context = Context(request.session)
        created = Bunch(towns={}, users=[], dates=[], jobs=[])
        townids = {}
        deleted = set()

        for record in files.township:

            if record.deleted == '1':
                deleted.add(record.uid)
                continue

            # towns double as user groups
            group = context.groups.add(
                name=record.name,
                bfs_number=record.bfs_nr,
                address_supplement=record.address_extension,
                gpn_number=record.gp_nr.isdigit() and int(record.gp_nr),
                payment_type=town_payment_type(record),
                type='wtfs')

            townids[record.uid] = record.bfs_nr

            assert group.bfs_number not in created.towns
            created.towns[group.bfs_number] = group

        print(f"✓ Imported {len(created.towns)} towns")

        for record in files.users:

            user = User(
                username=record.email,
                role=roles[record.rolle],
                realname=record.name,
                active=True,
                second_factor=None,
                signup_token=None,
                password_hash=password_hash,
                group_id=record.bfs and created.towns[record.bfs].id or None,
                data={'contact': record.kontakt == 'j'})

            context.session.add(user)
            created.users.append(user)

        print(f"✓ Imported {len(created.users)} users")

        for record in files.date:

            if record.township in deleted:
                continue

            if record.deleted == '1' or record.township == '0':
                continue

            dt = parse_datetime(record.date).date()

            pickup_date = PickupDate(
                date=dt,
                municipality_id=created.towns[townids[record.township]].id)

            context.session.add(pickup_date)
            created.dates.append(pickup_date)

        print(f"✓ Imported {len(created.dates)} dates")

        for record in files.transportorder:
            dispatch_date = parse_datetime(record.distribution_date).date()
            return_date = parse_datetime(record.return_date).date()

            if record.deleted == '1' or record.township == '0':
                continue

            if record.township in deleted:
                continue

            job = ScanJob(
                municipality_id=created.towns[townids[record.township]].id,
                type=types[record.transport_type],
                delivery_number=record.delivery_bill_number,

                # dispatch (in)
                dispatch_date=dispatch_date,
                dispatch_note=record.comment_delivery,
                dispatch_boxes=int(record.box_in),
                dispatch_tax_forms_current_year=int(
                    record.tax_current_year_in),
                dispatch_tax_forms_last_year=int(
                    record.tax_last_year_in),
                dispatch_tax_forms_older=int(
                    record.tax_old_in),
                dispatch_single_documents=int(
                    record.single_voucher_in),

                # targets (ribbon stands for "Bändliweg" I think)
                dispatch_cantonal_tax_office=int(
                    record.ribbon_out),
                dispatch_cantonal_scan_center=int(
                    record.cantonal_scan_center),

                # return (out)
                return_date=return_date,
                return_note=record.comment_handover,
                return_boxes=record.box_out,
                return_tax_forms_current_year=int(
                    record.tax_current_year_out),
                return_tax_forms_last_year=int(
                    record.tax_last_year_out),
                return_tax_forms_older=int(
                    record.tax_old_out),
                return_single_documents=int(
                    record.single_voucher_out),
                return_unscanned_tax_forms_current_year=int(
                    record.not_scanned_current_year),
                return_unscanned_tax_forms_last_year=int(
                    record.not_scanned_last_year),
                return_unscanned_tax_forms_older=int(
                    record.not_scanned_old),
                return_unscanned_single_documents=int(
                    record.not_scanned_voucher)
            )

            context.session.add(job)
            created.jobs.append(job)

        print(f"✓ Imported {len(created.jobs)} jobs")
예제 #16
0
    def calculate_precisely(self, daycare, services, income, wealth, rebate):
        """ Creates a detailed calculation of the subsidy paid by Winterthur.

        The reslt is a list of tables with explanations.

        :param daycare:
            The selected daycare (a :class:`Daycare` instance).

        :param services:
            Services used (a :class:`Services` instance)

        :param income:
            The income as a decimal.

        :param wealth:
            The wealth as decimal.

        :param rebate:
            True if a rebate is applied

        Note, due to the specific nature of the content here, which is probably
        not going to be translated, we use German. For consistency we want to
        limit this, but with Winterthur these kinds of things crop up as the
        wording is quite specific and adding translations would just make
        this a lot harder.

        """

        cfg = self.settings
        fmt = format_precise

        # Base Rate
        # ---------
        base = Block('base', "Berechnungsgrundlage für die Elternbeiträge")

        base.op(title="Steuerbares Einkommen",
                amount=income,
                note="""
                Steuerbares Einkommen gemäss letzter Veranlagung.
            """)

        base.op(title="Vermögenszuschlag",
                amount=max((wealth - cfg.max_wealth) * cfg.wealth_premium /
                           Decimal('100'), 0),
                operation="+",
                note=f"""
                Der Vermögenszuschlag beträgt
                {fmt(cfg.wealth_premium).rstrip('.0')}% des
                Vermögens, für das tatsächlich Steuern anfallen
                (ab {fmt(cfg.max_wealth)} CHF).
            """)

        base.op(title="Massgebendes Gesamteinkommen", operation="=")

        base.op(title="Abzüglich Minimaleinkommen",
                operation="-",
                amount=cfg.min_income)

        base.op(title="Berechnungsgrundlage", operation="=")

        # Gross Contribution
        # ------------------
        gross = Block('gross', "Berechnung des Brutto-Elternbeitrags")

        gross.op(title="Übertrag", amount=base.total)

        gross.op(title="Faktor",
                 amount=cfg.factor(daycare),
                 currency=None,
                 operation="×",
                 note="""
                Ihr Elternbeitrag wird aufgrund eines Faktors berechnet
                (Kita-Reglement Art. 20 Abs 3).
            """,
                 output_format=format_precise,
                 amount_places=10)

        gross.op(title="Einkommensabhängiger Elternbeitragsbestandteil",
                 operation="=")

        gross.op(title="Mindestbeitrag Eltern",
                 amount=cfg.min_rate,
                 operation="+")

        gross.op(title="Elternbeitrag brutto",
                 operation="=",
                 amount=min(gross.total, daycare.rate))

        # Rebate
        # ------
        rebate = gross.total * cfg.rebate / 100 if rebate else 0

        net = Block('net', "Berechnung des Rabatts")

        net.op(title="Übertrag", amount=gross.total)

        net.op(title="Rabatt",
               amount=rebate,
               operation="-",
               note=f"""
                Bei einem Betreuungsumfang von insgesamt mehr als 2 ganzen
                Tagen pro Woche gilt ein Rabatt von
                {fmt(cfg.rebate).rstrip('0.')}%.
            """)

        net.op(title="Elternbeitrag netto",
               operation="=",
               amount=max(cfg.min_rate, gross.total - rebate))

        # Actual contribution
        # -------------------
        actual = Block('actual', ("Berechnung des Elternbeitrags und des "
                                  "städtischen Beitrags pro Tag"))

        actual.op(title="Übertrag", amount=net.total)

        actual.op(title="Zusatzbeitrag Eltern",
                  amount=max(daycare.rate - cfg.max_rate, 0),
                  operation="+",
                  note=f"""
                Zusatzbeitrag für Kitas, deren Tagestarif über
                {cfg.max_rate} CHF liegt.
            """)

        parent_share_per_day = actual.op(title="Elternbeitrag pro Tag",
                                         operation="=",
                                         note="""
                Ihr Beitrag pro Tag (100%) und Kind.
            """,
                                         important=True)

        city_share_per_day = actual.op(title="Städtischer Beitrag pro Tag",
                                       amount=max(
                                           daycare.rate - parent_share_per_day,
                                           Decimal('0.00')),
                                       important=True,
                                       note="""
                Städtischer Beitrag für Ihr Kind pro Tag.
            """)

        # Monthly contribution
        # --------------------
        monthly = Block('monthly',
                        ("Berechnung des Elternbeitrags und des städtischen "
                         "Beitrags pro Monat"))

        monthly.op(title="Wochentarif",
                   amount=parent_share_per_day * services.total / 100,
                   note="""
                Wochentarif: Elternbeiträge der gewählten Betreuungstage.
            """)

        monthly.op(title="Faktor",
                   amount=daycare.factor,
                   currency=None,
                   operation="×",
                   note="""
                Faktor für jährliche Öffnungswochen Ihrer Kita.
            """,
                   output_format=format_precise,
                   amount_places=4)

        parent_share_per_month = monthly.op(title="Elternbeitrag pro Monat",
                                            operation="=",
                                            important=True,
                                            output_format=format_5_cents)

        city_share_per_month = monthly.op(
            title="Städtischer Beitrag pro Monat",
            amount=city_share_per_day * services.total / 100 * daycare.factor,
            important=True,
            output_format=format_5_cents)

        # Services table
        # --------------
        def services_table():
            total = Decimal(0)
            total_percentage = Decimal(0)

            for day in SERVICE_DAYS.values():
                for service_id in services.selected:
                    if day in services.selected[service_id]:
                        service = services.available[service_id]
                        cost = parent_share_per_day * service.percentage / 100

                        total += cost
                        total_percentage += service.percentage

                        label = SERVICE_DAYS_LABELS[day]
                        yield (label, service.title, format_5_cents(cost))

            yield (_("Total"), None, format_5_cents(total))

        total = round_to(parent_share_per_month, '0.05')\
            + round_to(city_share_per_month, '0.05')

        return Bunch(
            blocks=(base, gross, net, actual, monthly),
            parent_share_per_month=format_5_cents(parent_share_per_month),
            city_share_per_month=format_5_cents(city_share_per_month),
            total_per_month=format_5_cents(total),
            agenda=tuple(services_table()),
        )
예제 #17
0
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
예제 #18
0
 def has_permission(state):
     return has_public_permission_not_logged_in(app=None,
                                                identity=None,
                                                model=Bunch(state=state),
                                                permission=Public)
예제 #19
0
def test_is_owner():
    assert not is_owner(username=None, activity=Bunch(username=None))
    assert is_owner(username='******', activity=Bunch(username='******'))