예제 #1
0
def test_multi_choice_field_process_form_data_price_change_deselected(multi_choice_field):
    # reg linked to old version, a currently selected item had its price changed and another changed
    # item was deselected.
    # field data should be upgraded to a new version containing both the new items and the old-priced one
    multi_choice_field.versioned_data = _update_data(multi_choice_field.versioned_data,
                                                     {_id(2): {'is_billable': True, 'price': 100},
                                                      _id(3): {'price': 500}})
    old_version = multi_choice_field.current_data
    old_data = RegistrationData(field_data=old_version, data={_id(2): 1, _id(3): 1})
    assert old_data.price == 600
    multi_choice_field.versioned_data = _update_data(multi_choice_field.versioned_data, {_id(2): {'price': 10},
                                                                                         _id(3): {'price': 50}})
    form_data = {_id(3): 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
    new_data = RegistrationData(**rv)
    assert new_data.price == 500
    old_choices = old_version.versioned_data['choices']
    new_choices = multi_choice_field.versioned_data['choices']
    combined = [old_choices[-1]] + new_choices[:-1]
    _assert_same_choices(rv['field_data'].versioned_data['choices'], combined)
    # now we re-check the previously deselected option and should get the NEW price
    form_data = {_id(2): 1, _id(3): 1}
    rv = multi_choice_field.field_impl.process_form_data(None, form_data, new_data)
    assert RegistrationData(**rv).price == 510
예제 #2
0
파일: util.py 프로젝트: stomanin/indico
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
예제 #3
0
 def _create_accompanying_persons_field(max_persons,
                                        persons_count_against_limit,
                                        registration=None,
                                        data=None,
                                        num_persons=0):
     section = RegistrationFormSection(registration_form=dummy_regform,
                                       title='dummy_section',
                                       is_manager_only=False)
     db.session.add(section)
     db.session.flush()
     field = RegistrationFormField(input_type='accompanying_persons',
                                   title='Field',
                                   parent=section,
                                   registration_form=dummy_regform)
     field.field_impl.form_item.data = {
         'max_persons': max_persons,
         'persons_count_against_limit': persons_count_against_limit,
     }
     field.versioned_data = field.field_impl.form_item.data
     if registration:
         registration.data.append(
             RegistrationData(
                 field_data=field.current_data,
                 data=(data if data is not None else
                       _create_accompanying_persons(num_persons))))
         db.session.flush()
     return field
예제 #4
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,
                                                       previous_state=None)
예제 #5
0
 def _migrate_participant_data(self, old_part, registration):
     for pd_type, field in self.pd_field_map.iteritems():
         if pd_type.column:
             friendly_value = value = getattr(registration, pd_type.column)
         elif pd_type == PersonalDataType.title:
             try:
                 value = {self.title_map[old_part._title]: 1}
             except KeyError:
                 value = None
             friendly_value = convert_to_unicode(old_part._title)
         elif pd_type == PersonalDataType.position:
             continue
         else:
             value = convert_to_unicode(
                 getattr(old_part, PARTICIPANT_ATTR_MAP[pd_type]))
             if pd_type == PersonalDataType.phone and value:
                 value = normalize_phone_number(value)
             friendly_value = value
         if value:
             field.is_enabled = True
         if not self.importer.quiet:
             self.importer.print_info(
                 cformat('%{yellow!}{}%{reset} %{cyan!}{}%{reset}').format(
                     pd_type.name, friendly_value))
         registration.data.append(
             RegistrationData(field_data=field.current_data, data=value))
예제 #6
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.iteritems():
            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)
    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',
        'Registration modified: {}'.format(registration.full_name),
        session.user,
        data={'Email': registration.email})
예제 #7
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).items():
            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.query
                      .filter_by(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, data=data)
    notify_registration_creation(registration, notify_user)
    logger.info('New registration %s by %s', registration, user)
    registration.log(EventLogRealm.management if management else EventLogRealm.participants,
                     EventLogKind.positive, 'Registration',
                     f'New registration: {registration.full_name}', user, data={'Email': registration.email})
    return registration
예제 #8
0
def test_multi_choice_field_process_form_data_item_removed(multi_choice_field):
    # reg linked to old version, one selected item removed from there
    # 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(1): 1, _id(2): 1})
    multi_choice_field.versioned_data = _update_data(multi_choice_field.versioned_data, {_id(1): None})
    form_data = {_id(1): 1, _id(2): 1}
    assert multi_choice_field.field_impl.process_form_data(None, form_data, old_data) == {}
예제 #9
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) == {}
예제 #10
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
예제 #11
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
예제 #12
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) == {}
예제 #13
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)
예제 #14
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))
예제 #15
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)
예제 #16
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)
예제 #17
0
파일: util.py 프로젝트: javfg/indico
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})