Exemple #1
0
    def __init__(self, *args, **kwargs):
        # super(BaseEditForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        self.issued_relation = None
        self.received_relation = None
        self.old_user_id = self.instance.user_id

        pk = self.instance.pk

        if pk is not None:  # Edit mode
            relations = Relation.objects.filter(
                subject_entity=pk,
                type__in=(REL_SUB_BILL_ISSUED, REL_SUB_BILL_RECEIVED))

            issued_relation = find_first(
                relations, (lambda r: r.type_id == REL_SUB_BILL_ISSUED), None)
            received_relation = find_first(
                relations, (lambda r: r.type_id == REL_SUB_BILL_RECEIVED),
                None)

            if issued_relation:
                self.issued_relation = issued_relation
                self.fields[
                    'source'].initial = issued_relation.object_entity_id

            if received_relation:
                self.received_relation = received_relation
                self.fields['target'].initial = received_relation.object_entity
Exemple #2
0
    def save(self):
        # BEWARE: chosen contacts can have already relations with the event ;
        #   we avoid several 'REL_OBJ_IS_INVITED_TO' relations,
        #   'REL_OBJ_CAME_EVENT' override existing 'REL_OBJ_NOT_CAME_EVENT' relations etc...
        event = self.event
        user = self.user
        relations = Relation.objects
        create_relation = relations.create

        related_contacts = self.cleaned_data['related_contacts']

        # NB: queries are regrouped to optimise
        relations_map = defaultdict(list)  # per contact relations lists
        for relation in relations.filter(
                subject_entity=event.id,
                type__in=_TYPES,
                object_entity__in=[
                    contact.id for relationtype, contact in related_contacts
                ],
        ):
            relations_map[relation.object_entity_id].append(relation)

        relations2del = []

        for relationtype, contact in related_contacts:
            relationtype_id = relationtype.id
            contact_relations = relations_map.get(contact.id, ())

            # REL_OBJ_CAME_EVENT or REL_OBJ_NOT_CAME_EVENT
            if relationtype_id != constants.REL_OBJ_IS_INVITED_TO:
                symmetric = _SYMMETRICS[relationtype_id]
                rel2del = find_first(
                    contact_relations,
                    lambda relation: relation.type_id == symmetric,
                    None,
                )

                if rel2del is not None:
                    relations2del.append(rel2del.id)

            if find_first(contact_relations,
                          lambda relation: relation.type_id == relationtype_id,
                          None) is None:
                create_relation(
                    subject_entity=event,
                    type=relationtype,
                    object_entity=contact,
                    user=user,
                )

        if relations2del:
            relations.filter(pk__in=relations2del).delete()

        return event
Exemple #3
0
    def test_find_first(self):
        class Info:
            def __init__(self, data): self.data = data

        i1, i2, i3, i4 = Info(1), Info(2), Info(2), Info(5)
        l = [i1, i2, i3, i4]

        self.assertIs(find_first(l, lambda i: i.data == 1), i1)
        self.assertIs(find_first(l, lambda i: i.data == 2), i2)
        self.assertIs(find_first(l, lambda i: i.data == 5), i4)

        self.assertIsNone(find_first(l, lambda i: i.data == 12, None))
        self.assertRaises(IndexError, find_first, l, lambda i: i.data == 12)
Exemple #4
0
    def __init__(self, section=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.section = section

        # Lines which are in the section where we create our line.
        self.section_lines = section_lines = []

        # The lines after the one we create (but not in the same section):
        # their order have to be incremented
        self.next_lines = next_lines = []

        # Order of the last line before our section (used if our section is empty).
        self.empty_section_order = 1

        nodes = [*SectionTree(self.pform)]
        section_id = section.id if section else None

        # Filling of 'section_lines' & 'next_lines'
        node_it = reversed(nodes)
        try:
            while True:
                node = next(node_it)

                if not node.is_section:
                    if node.section_id == section_id:
                        section_lines.append(node)
                    else:
                        next_lines.append(node)
                elif node.id == section_id:
                    previous_line = find_first(
                        node_it, (lambda node: not node.is_section), None)

                    if previous_line:
                        self.empty_section_order = previous_line.order + 1

                    break
        except StopIteration:
            pass

        if section_lines:
            section_lines.reverse()

            # TODO: cached_gettext ??
            msg_fmt = gettext('Before: «{question}» (#{number})').format
            choices = [
                (0, gettext('Start of section')),
                *((i, msg_fmt(question=node.question, number=node.number))
                  for i, node in enumerate(section_lines[1:], start=1)),
                (len(section_lines), gettext('End of section')),
            ]

            self.fields['index'] = TypedChoiceField(
                label=gettext('Order'),
                coerce=int,
                choices=choices,
                initial=len(choices) - 1,
            )
Exemple #5
0
    def clean_old_choices(self):
        old_choices = self.cleaned_data['old_choices']
        self.choices_2_keep = choices_2_keep = []
        self.choices_2_del = choices_2_del = []

        for existing_choice, choice in zip(self.initial_choices, old_choices):
            if choice is None:
                choices_2_del.append(existing_choice)
            else:
                choice = choice.strip()

                if not choice:
                    raise ValidationError(
                        self.error_messages['empty_choices'],
                        code='empty_choices',
                    )  # TODO: move this validation to the field ??

                choices_2_keep.append((existing_choice[0], choice))

        if choices_2_del:
            condition = PollFormLineCondition.objects \
                                             .filter(source=self.instance,
                                                     raw_answer__in=[str(c[0]) for c in choices_2_del],
                                                    ) \
                                             .first()

            if condition is not None:
                choice_id = int(condition.raw_answer)

                raise ValidationError(
                    self.error_messages['used_choice'],
                    params={
                        'choice':
                        find_first(choices_2_del,
                                   (lambda c: c[0] == choice_id))[1],
                        'question':
                        condition.line.question,
                    },
                    code='used_choice',
                )

        return old_choices
Exemple #6
0
        def _post_instance_creation(self, instance, line, updated):
            super()._post_instance_creation(instance, line, updated)
            cdata = self.cleaned_data
            user = self.user

            append_error = self.append_error
            source, err_msg = cdata['source'].extract_value(line, user)
            append_error(err_msg)

            target, err_msg = cdata['target'].extract_value(line, user)
            append_error(err_msg)

            create_rel = partial(
                Relation.objects.safe_create,
                subject_entity=instance,
                user=instance.user,
            )

            # TODO: move this intelligence in models.Base.save() (see regular Forms)
            if not updated:
                create_rel(type_id=REL_SUB_BILL_ISSUED, object_entity=source)
                create_rel(type_id=REL_SUB_BILL_RECEIVED, object_entity=target)

                instance.billing_address = copy_or_create_address(
                    target.billing_address, instance, _('Billing address'))
                instance.shipping_address = copy_or_create_address(
                    target.shipping_address, instance, _('Shipping address'))
                instance.save()
            else:  # Update mode
                relations = Relation.objects.filter(
                    subject_entity=instance.pk,
                    type__in=(REL_SUB_BILL_ISSUED, REL_SUB_BILL_RECEIVED))

                issued_relation = find_first(
                    relations, (lambda r: r.type_id == REL_SUB_BILL_ISSUED),
                    None)
                received_relation = find_first(
                    relations, (lambda r: r.type_id == REL_SUB_BILL_RECEIVED),
                    None)

                assert issued_relation is not None
                assert received_relation is not None

                if issued_relation.object_entity_id != source:
                    issued_relation.delete()
                    create_rel(type_id=REL_SUB_BILL_ISSUED,
                               object_entity=source)

                if received_relation.object_entity_id != target:
                    received_relation.delete()
                    create_rel(type_id=REL_SUB_BILL_RECEIVED,
                               object_entity=target)

                b_change = s_change = False

                if cdata['override_billing_addr']:
                    b_change = _copy_or_update_address(
                        target,
                        instance,
                        'billing_address',
                        _('Billing address'),
                    )

                if cdata['override_shipping_addr']:
                    s_change = _copy_or_update_address(
                        target,
                        instance,
                        'shipping_address',
                        _('Shipping address'),
                    )

                if b_change or s_change:
                    instance.save()