Пример #1
0
 def _clone_registrations(self, old_form, new_form, field_data_map):
     registration_attrs = get_simple_column_attrs(Registration) - {'uuid', 'ticket_uuid'}
     for old_registration in old_form.registrations:
         if old_registration.is_deleted:
             continue
         new_registration = Registration(user=old_registration.user, registration_form=new_form,
                                         **{attr: getattr(old_registration, attr) for attr in registration_attrs})
         reg_data_attrs = get_simple_column_attrs(RegistrationData) - {'storage_file_id', 'storage_backend', 'size'}
         for old_registration_data in old_registration.data:
             new_registration_data = RegistrationData(registration=new_registration,
                                                      **{attr: getattr(old_registration_data, attr)
                                                         for attr in reg_data_attrs})
             new_registration_data.field_data = field_data_map[old_registration_data.field_data]
             if old_registration_data.storage_file_id is not None:
                 with old_registration_data.open() as fd:
                     new_registration_data.save(fd)
         db.session.flush()
         signals.event.registration_state_updated.send(new_registration)
Пример #2
0
 def _checkParams(self, params):
     RHManageRegFormsBase._checkParams(self, params)
     self.field_data = (
         RegistrationData.find(
             RegistrationData.registration_id == request.view_args["registration_id"],
             RegistrationData.field_data_id == request.view_args["field_data_id"],
             RegistrationData.filename != None,
         )  # noqa
         .options(joinedload("registration").joinedload("registration_form"))
         .one()
     )
Пример #3
0
 def _migrate_participant_status(self, old_part, registration):
     if not self.status_used:
         return
     if old_part._status not in {'added', 'pending'}:
         status_info = self.status_map[old_part._status]
         data = {status_info['uuid']: 1}
         caption = status_info['caption']
     else:
         data = None
         caption = ''
     if not self.quiet and data:
         self.print_info('%[red]STATUS%[reset] %[cyan]{}'.format(caption))
     registration.data.append(
         RegistrationData(field_data=self.status_field.current_data,
                          data=data))
Пример #4
0
def modify_registration(registration, data, management=False, notify_user=True):
    old_price = registration.price
    personal_data_changes = {}
    regform = registration.registration_form
    data_by_field = registration.data_by_field
    if management or not registration.user:
        registration.user = get_user_by_email(data['email'])

    billable_items_locked = not management and registration.is_paid
    for form_item in regform.active_fields:
        field_impl = form_item.field_impl
        if management or not form_item.parent.is_manager_only:
            value = data.get(form_item.html_field_name)
        elif form_item.id not in data_by_field:
            # set default value for manager-only field if it didn't have one before
            value = field_impl.default_value
        else:
            # manager-only field that has data which should be preserved
            continue

        if form_item.id not in data_by_field:
            data_by_field[form_item.id] = RegistrationData(registration=registration,
                                                           field_data=form_item.current_data)

        attrs = field_impl.process_form_data(registration, value, data_by_field[form_item.id],
                                             billable_items_locked=billable_items_locked)
        for key, val in attrs.items():
            setattr(data_by_field[form_item.id], key, val)
        if form_item.type == RegistrationFormItemType.field_pd and form_item.personal_data_type.column:
            key = form_item.personal_data_type.column
            if getattr(registration, key) != value:
                personal_data_changes[key] = value
            setattr(registration, key, value)
    registration.sync_state()
    db.session.flush()
    # sanity check
    if billable_items_locked and old_price != registration.price:
        raise Exception("There was an error while modifying your registration (price mismatch: %s / %s)",
                        old_price, registration.price)
    if personal_data_changes:
        signals.event.registration_personal_data_modified.send(registration, change=personal_data_changes)
    signals.event.registration_updated.send(registration, management=management, data=data)
    notify_registration_modification(registration, notify_user)
    logger.info('Registration %s modified by %s', registration, session.user)
    registration.log(EventLogRealm.management if management else EventLogRealm.participants,
                     EventLogKind.change, 'Registration',
                     f'Registration modified: {registration.full_name}',
                     session.user, data={'Email': registration.email})
Пример #5
0
def create_registration(regform,
                        data,
                        invitation=None,
                        management=False,
                        notify_user=True,
                        skip_moderation=None):
    user = session.user if session else None
    registration = Registration(registration_form=regform,
                                user=get_user_by_email(data['email']),
                                base_price=regform.base_price,
                                currency=regform.currency)
    if skip_moderation is None:
        skip_moderation = management
    for form_item in regform.active_fields:
        if form_item.parent.is_manager_only:
            value = form_item.field_impl.default_value
        else:
            value = data.get(form_item.html_field_name)
        data_entry = RegistrationData()
        registration.data.append(data_entry)
        for attr, value in form_item.field_impl.process_form_data(
                registration, value).iteritems():
            setattr(data_entry, attr, value)
        if form_item.type == RegistrationFormItemType.field_pd and form_item.personal_data_type.column:
            setattr(registration, form_item.personal_data_type.column, value)
    if invitation is None:
        # Associate invitation based on email in case the user did not use the link
        invitation = (RegistrationInvitation.find(
            email=data['email'],
            registration_id=None).with_parent(regform).first())
    if invitation:
        invitation.state = InvitationState.accepted
        invitation.registration = registration
    registration.sync_state(_skip_moderation=skip_moderation)
    db.session.flush()
    signals.event.registration_created.send(registration,
                                            management=management)
    notify_registration_creation(registration, notify_user)
    logger.info('New registration %s by %s', registration, user)
    regform.event.log(
        EventLogRealm.management if management else EventLogRealm.participants,
        EventLogKind.positive,
        'Registration',
        'New registration: {}'.format(registration.full_name),
        user,
        data={'Email': registration.email},
        meta={'registration_id': registration.id})
    return registration
Пример #6
0
def test_multi_choice_field_process_form_data_old_version(multi_choice_field):
    # reg linked to old version, price changed in new version, nothing changed
    # in this case everything should remain linked to the old version
    old_version = multi_choice_field.current_data
    old_data = RegistrationData(field_data=old_version,
                                data={
                                    _id(2): 1,
                                    _id(3): 1
                                })
    multi_choice_field.versioned_data = _update_data(
        multi_choice_field.versioned_data, {_id(3): {
                                                'price': 1000
                                            }})
    form_data = {_id(2): 1, _id(3): 1}
    assert multi_choice_field.field_impl.process_form_data(
        None, form_data, old_data) == {}
Пример #7
0
def modify_registration(registration,
                        data,
                        management=False,
                        notify_user=True):
    old_price = registration.price
    with db.session.no_autoflush:
        regform = registration.registration_form
        data_by_field = registration.data_by_field
        if management or not registration.user:
            registration.user = get_user_by_email(data['email'])

        billable_items_locked = not management and registration.is_paid
        for form_item in regform.active_fields:
            field_impl = form_item.field_impl
            if management or not form_item.parent.is_manager_only:
                value = data.get(form_item.html_field_name)
            elif form_item.id not in data_by_field:
                # set default value for manager-only field if it didn't have one before
                value = field_impl.default_value
            else:
                # manager-only field that has data which should be preserved
                continue

            if form_item.id not in data_by_field:
                data_by_field[form_item.id] = RegistrationData(
                    registration=registration,
                    field_data=form_item.current_data)

            attrs = field_impl.process_form_data(
                registration,
                value,
                data_by_field[form_item.id],
                billable_items_locked=billable_items_locked)
            for key, val in attrs.iteritems():
                setattr(data_by_field[form_item.id], key, val)
            if form_item.type == RegistrationFormItemType.field_pd and form_item.personal_data_type.column:
                setattr(registration, form_item.personal_data_type.column,
                        value)
        registration.sync_state()
    db.session.flush()
    # sanity check
    if billable_items_locked and old_price != registration.price:
        raise Exception(
            "There was an error while modifying your registration (price mismatch: %s / %s)",
            old_price, registration.price)
    notify_registration_modification(registration, notify_user)
    logger.info('Registration %s modified by %s', registration, session.user)
Пример #8
0
def test_multi_choice_field_process_form_data_item_removed_deselected(
        multi_choice_field):
    # reg linked to old version, one selected item removed from there and deselected
    # since all other items are available in the latest version we upgrade to it
    old_version = multi_choice_field.current_data
    old_data = RegistrationData(field_data=old_version,
                                data={
                                    _id(1): 1,
                                    _id(2): 1
                                })
    multi_choice_field.versioned_data = _update_data(
        multi_choice_field.versioned_data, {_id(1): None})
    form_data = {_id(2): 1}
    rv = multi_choice_field.field_impl.process_form_data(
        None, form_data, old_data)
    assert rv['field_data'] == multi_choice_field.current_data
    assert rv['data'] == form_data
Пример #9
0
def test_multi_choice_field_process_form_data_only_new(multi_choice_field):
    # reg linked to old version, but all old items deselected
    # field data should be upgraded to the current version
    old_version = multi_choice_field.current_data
    old_data = RegistrationData(field_data=old_version,
                                data={
                                    _id(1): 1,
                                    _id(2): 1
                                })
    multi_choice_field.versioned_data = _update_data(
        multi_choice_field.versioned_data, {
            _id(1): None,
            _id(4): {}
        })
    form_data = {_id(4): 1}
    rv = multi_choice_field.field_impl.process_form_data(
        None, form_data, old_data)
    assert rv['field_data'] == multi_choice_field.current_data
    assert rv['data'] == form_data
Пример #10
0
def test_multi_choice_field_process_form_data_mixed(multi_choice_field):
    # reg linked to old version, a currently selected item was deleted and a new item is selected
    # field data should be upgraded to a new version containing both the new items and the deleted one
    old_version = multi_choice_field.current_data
    old_data = RegistrationData(field_data=old_version, data={_id(1): 1})
    multi_choice_field.versioned_data = _update_data(
        multi_choice_field.versioned_data, {
            _id(1): None,
            _id(4): {}
        })
    form_data = {_id(1): 1, _id(4): 1}
    rv = multi_choice_field.field_impl.process_form_data(
        None, form_data, old_data)
    assert rv['field_data'] not in {
        multi_choice_field.current_data, old_version
    }
    assert rv['data'] == form_data
    combined = multi_choice_field.versioned_data['choices'] + [
        old_version.versioned_data['choices'][0]
    ]
    _assert_same_choices(rv['field_data'].versioned_data['choices'], combined)
Пример #11
0
def create_registration(regform,
                        data,
                        invitation=None,
                        management=False,
                        notify_user=True):
    registration = Registration(registration_form=regform,
                                user=get_user_by_email(data['email']),
                                base_price=regform.base_price,
                                currency=regform.currency)
    for form_item in regform.active_fields:
        if form_item.parent.is_manager_only:
            with db.session.no_autoflush:
                value = form_item.field_impl.default_value
        else:
            value = data.get(form_item.html_field_name)
        with db.session.no_autoflush:
            data_entry = RegistrationData()
            registration.data.append(data_entry)
            for attr, value in form_item.field_impl.process_form_data(
                    registration, value).iteritems():
                setattr(data_entry, attr, value)
        if form_item.type == RegistrationFormItemType.field_pd and form_item.personal_data_type.column:
            setattr(registration, form_item.personal_data_type.column, value)
    if invitation is None:
        # Associate invitation based on email in case the user did not use the link
        with db.session.no_autoflush:
            invitation = (RegistrationInvitation.find(
                email=data['email'],
                registration_id=None).with_parent(regform).first())
    if invitation:
        invitation.state = InvitationState.accepted
        invitation.registration = registration
    registration.sync_state(_skip_moderation=management)
    db.session.flush()
    notify_registration_creation(registration, notify_user)
    logger.info('New registration %s by %s', registration, session.user)
    return registration
Пример #12
0
def test_multi_choice_field_process_form_data_mixed_price_change(
        multi_choice_field):
    # reg linked to old version, a currently selected item had its price changed and a new item is selected
    # field data should be upgraded to a new version containing both the new items and the old-priced one
    old_version = multi_choice_field.current_data
    old_data = RegistrationData(field_data=old_version, data={_id(3): 1})
    multi_choice_field.versioned_data = _update_data(
        multi_choice_field.versioned_data, {
            _id(3): {
                'price': 1000
            },
            _id(4): {}
        })
    form_data = {_id(3): 1, _id(4): 1}
    rv = multi_choice_field.field_impl.process_form_data(
        None, form_data, old_data)
    assert rv['field_data'] not in {
        multi_choice_field.current_data, old_version
    }
    assert rv['data'] == form_data
    old_choices = old_version.versioned_data['choices']
    new_choices = multi_choice_field.versioned_data['choices']
    combined = new_choices[:2] + [old_choices[2]] + [new_choices[-1]]
    _assert_same_choices(rv['field_data'].versioned_data['choices'], combined)
Пример #13
0
 def _get_registration_data(self, field):
     registration_ids = [r.id for r in field.registration_form.active_registrations]
     field_data_ids = [data.id for data in field.data_versions]
     return RegistrationData.find_all(RegistrationData.registration_id.in_(registration_ids),
                                      RegistrationData.field_data_id.in_(field_data_ids),
                                      RegistrationData.data != {})
Пример #14
0
def test_multi_choice_field_process_form_data_current_version(multi_choice_field):
    # nothing changed
    old_data = RegistrationData(field_data=multi_choice_field.current_data, data={_id(1): 1, _id(2): 1})
    form_data = {_id(1): 1, _id(2): 1}
    assert multi_choice_field.field_impl.process_form_data(None, form_data, old_data) == {}
Пример #15
0
 def _get_registration_data(self, field):
     registration_ids = [r.id for r in field.registration_form.active_registrations]
     field_data_ids = [data.id for data in field.data_versions]
     return RegistrationData.find_all(RegistrationData.registration_id.in_(registration_ids),
                                      RegistrationData.field_data_id.in_(field_data_ids),
                                      RegistrationData.data != {})
Пример #16
0
def modify_registration(registration,
                        data,
                        management=False,
                        notify_user=True):
    old_data = snapshot_registration_data(registration)
    old_price = registration.price
    personal_data_changes = {}
    regform = registration.registration_form
    data_by_field = registration.data_by_field
    if 'email' in data and (management or not registration.user):
        registration.user = get_user_by_email(data['email'])

    billable_items_locked = not management and registration.is_paid
    for form_item in regform.active_fields:
        if form_item.is_purged:
            continue

        field_impl = form_item.field_impl
        has_data = form_item.html_field_name in data
        can_modify = management or not form_item.parent.is_manager_only

        if has_data and can_modify:
            value = data.get(form_item.html_field_name)
        elif not has_data and form_item.id not in data_by_field:
            # set default value for a field if it didn't have one before (including manager-only fields)
            value = field_impl.default_value
        else:
            # keep current value
            continue

        if form_item.id not in data_by_field:
            data_by_field[form_item.id] = RegistrationData(
                registration=registration, field_data=form_item.current_data)

        attrs = field_impl.process_form_data(
            registration,
            value,
            data_by_field[form_item.id],
            billable_items_locked=billable_items_locked)
        for key, val in attrs.items():
            setattr(data_by_field[form_item.id], key, val)
        if form_item.type == RegistrationFormItemType.field_pd and form_item.personal_data_type.column:
            key = form_item.personal_data_type.column
            if getattr(registration, key) != value:
                personal_data_changes[key] = value
            setattr(registration, key, value)
    if not management and regform.needs_publish_consent:
        registration.consent_to_publish = data.get(
            'consent_to_publish', RegistrationVisibility.nobody)
    registration.sync_state()
    db.session.flush()
    # sanity check
    if billable_items_locked and old_price != registration.price:
        raise Exception(
            'There was an error while modifying your registration (price mismatch: %s / %s)',
            old_price, registration.price)
    if personal_data_changes:
        signals.event.registration_personal_data_modified.send(
            registration, change=personal_data_changes)
    signals.event.registration_updated.send(registration,
                                            management=management,
                                            data=data)

    new_data = snapshot_registration_data(registration)
    diff = diff_registration_data(old_data, new_data)
    notify_registration_modification(registration,
                                     notify_user,
                                     diff=diff,
                                     old_price=old_price)
    logger.info('Registration %s modified by %s', registration, session.user)
    registration.log(
        EventLogRealm.management if management else EventLogRealm.participants,
        LogKind.change,
        'Registration',
        f'Registration modified: {registration.full_name}',
        session.user,
        data={'Email': registration.email})