Skip to content

Conversation

@BreathingFlesh
Copy link
Contributor

@BreathingFlesh BreathingFlesh commented Nov 27, 2025

Please fill in the commit message below and work through the checklist. You can delete parts that are not needed, e.g. the optional description, the link to a ticket or irrelevant options of the checklist.

Commit message

Feriennet: Delete attendees

TYPE: Feature
LINK: PRO-1436

Checklist

  • I have performed a self-review of my code
  • I considered adding a reviewer
  • I have updated the PO files
  • I have tested my code thoroughly by hand
  • I have added tests for my changes/features

@codecov
Copy link

codecov bot commented Nov 27, 2025

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
2566 1 2565 17
View the top 1 failed test(s) by shortest run time
tests/onegov/pas/permissions/test_admin_only_permissions.py::test_admin_only_collection_access[/[email protected]]
Stack Traces | 29.5s run time
self = <webassets.bundle.ContextWrapper object at 0x7faf29cbfa50>
item = 'cache'

    def __getattr__(self, item):
        try:
>           return self.getattr(self._overwrites, item)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.........................................................................../app/lib/python3.11......................../site-packages/webassets/bundle.py:45: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.........................................................................../app/lib/python3.11......................../site-packages/webassets/bundle.py:53: in getattr
    return getattr(object.config, item)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11........./site-packages/webassets/env.py:507: in _get_cache
    cache = get_cache(self._storage['cache'], self)
                      ^^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <webassets.bundle.BundleConfig object at 0x7faf29c9b9d0>, key = 'cache'

    def __getitem__(self, key):
        key = key.lower()
        value = self._get_deprecated(key)
        if not value is None:
            return value
>       return self._dict.__getitem__(key)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
E       KeyError: 'cache'

.........................................................................../app/lib/python3.11........./site-packages/webassets/env.py:806: KeyError

During handling of the above exception, another exception occurred:

client = <tests.shared.client.Client object at 0x7faf2aa5e390>
role = 'parliamentarian', user_email = '[email protected]'
should_access = False, path = '/rate-sets'

    @pytest.mark.parametrize('role,user_email,should_access', [
        ('parliamentarian', '[email protected]', False),
        ('commission_president', '[email protected]', False),
        ('admin', '[email protected]', True),
    ])
    @pytest.mark.parametrize('path', [
        '/rate-sets',
        '/settlement-runs',
        '/import-logs',
        '/usermanagement'
    ])
    def test_admin_only_collection_access(
        client: Client[TestPasApp],
        role: str,
        user_email: str,
        should_access: bool,
        path: str
    ) -> None:
        session = client.app.session()
    
        # Create user with specified role
        users = UserCollection(session)
        user = users.add(
            username=user_email,
            password='test',
            role=role
        )
        transaction.commit()
    
        # Login and test access
>       client.login(user_email, 'test')

.../pas/permissions/test_admin_only_permissions.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
tests/shared/client.py:68: in login
    login_page = self.get(url)
                 ^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11....../site-packages/webtest/app.py:328: in get
    return self.do_request(req, status=status,
tests/shared/client.py:167: in do_request
    return self.extend_response(super().do_request(*args, **kwargs))
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11....../site-packages/webtest/app.py:627: in do_request
    res = req.get_response(app, catch_exc_info=True)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11....../site-packages/webob/request.py:1309: in send
    status, headers, app_iter, exc_info = self.call_application(
.........................................................................../app/lib/python3.11....../site-packages/webob/request.py:1278: in call_application
    app_iter = application(self.environ, start_response)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11.../site-packages/webtest/lint.py:196: in lint_app
    iterator = application(environ, start_response_wrapper)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.../onegov/core/framework.py:216: in with_request_cache_wrapper
    return fn(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^
.../onegov/core/framework.py:231: in with_print_exceptions_wrapper
    return fn(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11.../site-packages/morepath/app.py:138: in __call__
    response = self.publish(request)
               ^^^^^^^^^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11.../site-packages/morepath/core.py:201: in poisoned_host_header_protection_tween
    return handler(request)
           ^^^^^^^^^^^^^^^^
.../onegov/core/framework.py:1703: in http_conflict_tween
    return handler(request)
           ^^^^^^^^^^^^^^^^
.../onegov/core/framework.py:1728: in activate_session_manager
    return handler(request)
           ^^^^^^^^^^^^^^^^
.../onegov/core/framework.py:1746: in close_session_after_request
    return handler(request)
           ^^^^^^^^^^^^^^^^
.../onegov/file/integration.py:448: in configure_depot_tween
    return handler(request)
           ^^^^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11.../more/transaction/main.py:67: in transaction_tween
    response = handler(request)
               ^^^^^^^^^^^^^^^^
.../onegov/core/framework.py:1580: in fix_webassets_url
    response = handler(request)
               ^^^^^^^^^^^^^^^^
.../onegov/user/integration.py:312: in auto_login_tween
    return handler(request)
           ^^^^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11.../more/webassets/tweens.py:132: in __call__
    return self.handler(request)
           ^^^^^^^^^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11.../more/webassets/tweens.py:95: in __call__
    scripts = '\n'.join(
.........................................................................../app/lib/python3.11.../more/webassets/tweens.py:95: in <genexpr>
    scripts = '\n'.join(
.........................................................................../app/lib/python3.11.../more/webassets/tweens.py:75: in urls_to_inject
    for url in self.urls_by_resource(resource):
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11.../more/webassets/tweens.py:64: in urls_by_resource
    self._urls[resource].extend(bundle.urls())
                                ^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11......................../site-packages/webassets/bundle.py:827: in urls
    urls.extend(bundle._urls(new_ctx, extra_filters, *args, **kwargs))
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11......................../site-packages/webassets/bundle.py:761: in _urls
    self._build(ctx, extra_filters=extra_filters, force=False,
.........................................................................../app/lib/python3.11......................../site-packages/webassets/bundle.py:612: in _build
    hunk = self._merge_and_apply(
.........................................................................../app/lib/python3.11......................../site-packages/webassets/bundle.py:488: in _merge_and_apply
    ctx.cache, no_cache_read=actually_skip_cache_here,
    ^^^^^^^^^
.........................................................................../app/lib/python3.11......................../site-packages/webassets/bundle.py:47: in __getattr__
    return self.getattr(self._parent, item)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11......................../site-packages/webassets/bundle.py:55: in getattr
    return getattr(object, item)
           ^^^^^^^^^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11........./site-packages/webassets/env.py:507: in _get_cache
    cache = get_cache(self._storage['cache'], self)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.........................................................................../app/lib/python3.11.../site-packages/webassets/cache.py:235: in get_cache
    os.makedirs(directory)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

name = '.../assets/bundles/.webassets-cache'
mode = 511, exist_ok = False

>   ???
E   FileExistsError: [Errno 17] File exists: '.../assets/bundles/.webassets-cache'

<frozen os>:225: FileExistsError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a feature allowing users to delete attendees (children) in the Feriennet application. Deletion is restricted when attendees have bookings in the active period, but allowed for attendees with only non-active period bookings. The feature includes proper UI elements, confirmation dialogs, and internationalization support.

  • Adds DELETE endpoint for attendees with active period booking restrictions
  • Implements delete button UI with confirmation dialog and accessibility support
  • Updates templates to show attendees even without bookings (for deletion purposes)

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/onegov/feriennet/views/attendee.py Implements DELETE endpoint with validation logic to prevent deletion of attendees with active period bookings
src/onegov/feriennet/views/booking.py Adds attendee_delete_link function to generate delete links with confirmation dialogs
src/onegov/feriennet/templates/bookings.pt Integrates delete button into attendee cards and removes conditional rendering to show attendees without bookings
src/onegov/town6/templates/elements.pt Adds screen reader text support for icon-only links to improve accessibility
src/onegov/feriennet/theme/styles/feriennet.scss Adds delete-icon styling and removes padding-left from icon elements
tests/onegov/feriennet/test_views.py Adds test coverage for attendee deletion with active/inactive period scenarios
src/onegov/feriennet/locale/de_CH/LC_MESSAGES/onegov.feriennet.po Adds German translations for deletion messages
src/onegov/feriennet/locale/fr_CH/LC_MESSAGES/onegov.feriennet.po Adds French translations for deletion messages
src/onegov/feriennet/locale/it_CH/LC_MESSAGES/onegov.feriennet.po Adds Italian translations for deletion messages

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants