Beispiel #1
0
class ActionForContactsForm(forms.ModelForm):
    """Create action for contacts"""
    date = forms.DateField(label=_("planned date"),
                           required=False,
                           widget=forms.TextInput())
    time = forms.TimeField(label=_("planned time"), required=False)
    contacts = forms.CharField(widget=forms.HiddenInput())

    class Meta:
        """create form from model"""
        model = Action
        fields = ('date', 'time', 'type', 'subject', 'in_charge', 'detail',
                  'planned_date', 'contacts', 'opportunity')

    def __init__(self, *args, **kwargs):
        initial = kwargs.get('initial')
        initial_contacts = ''
        if initial and 'contacts' in initial:
            initial_contacts = ';'.join(
                ['{0}'.format(c.id) for c in initial['contacts']])
            initial.pop('contacts')
        super(ActionForContactsForm, self).__init__(*args, **kwargs)
        if initial_contacts:
            self.fields['contacts'].initial = initial_contacts
        self.fields['opportunity'].widget = OpportunityAutoComplete(
            attrs={
                'placeholder': _('Enter the name of an opportunity'),
                'size': '80',
                'class': 'colorbox'
            })

    def get_contacts(self):
        """return contacts"""
        contact_ids = self.cleaned_data["contacts"].split(";")
        return Contact.objects.filter(id__in=contact_ids)

    def clean_planned_date(self):
        """validate planned date"""
        the_date = self.cleaned_data["date"]
        the_time = self.cleaned_data.get("time", None)
        if the_date:
            return datetime.combine(the_date, the_time or datetime.min.time())
        return None
Beispiel #2
0
class Kv17ChangeForm(forms.ModelForm):
    # This is duplication, but should work
    operatingday = forms.ChoiceField(label=_("Datum"), required=True)
    begintime_part = forms.TimeField(label=_('Ingangstijd'),
                                     required=False,
                                     widget=forms.TimeInput(format='%H:%M:%S'))
    endtime_part = forms.TimeField(label=_('Eindtijd'),
                                   required=False,
                                   widget=forms.TimeInput(format='%H:%M:%S'))
    reasontype = forms.ChoiceField(choices=REASONTYPE,
                                   label=_("Type oorzaak"),
                                   required=False)
    subreasontype = forms.ChoiceField(choices=SUBREASONTYPE,
                                      label=_("Oorzaak"),
                                      required=False)
    reasoncontent = forms.CharField(max_length=255,
                                    label=_("Uitleg oorzaak"),
                                    required=False,
                                    widget=forms.Textarea(attrs={
                                        'cols': 40,
                                        'rows': 4,
                                        'class': 'col-lg-6'
                                    }))
    advicetype = forms.ChoiceField(choices=ADVICETYPE,
                                   label=_("Type advies"),
                                   required=False)
    subadvicetype = forms.ChoiceField(choices=SUBADVICETYPE,
                                      label=_("Advies"),
                                      required=False)
    advicecontent = forms.CharField(max_length=255,
                                    label=_("Uitleg advies"),
                                    required=False,
                                    widget=forms.Textarea(attrs={
                                        'cols': 40,
                                        'rows': 4,
                                        'class': 'col-lg-6'
                                    }))

    def clean(self):
        cleaned_data = super(Kv17ChangeForm, self).clean()
        operatingday = parse_date(self.data['operatingday'])
        if operatingday is None:
            raise ValidationError(_("Er staan geen ritten in de database"))

        if 'journeys' not in self.data:
            raise ValidationError(
                _("Een of meer geselecteerde ritten zijn ongeldig"))

        if self.data['begintime_part'] != '':
            hh, mm = self.data['begintime_part'].split(':')
            begintime = make_aware(
                datetime.combine(operatingday, time(int(hh), int(mm))))
        else:
            begintime = None

        if self.data['endtime_part'] != '':
            hh_e, mm_e = self.data['endtime_part'].split(':')
            endtime = make_aware(
                datetime.combine(operatingday, time(int(hh_e), int(mm_e))))
            if begintime:
                if begintime > endtime:  # if endtime before begintime
                    endtime = endtime + timedelta(
                        days=1)  # endtime is next day
                    if endtime.time() >= time(
                            6, 0):  # and after 6 am: validation error
                        raise ValidationError(
                            _("Eindtijd valt op volgende operationele dag"))
        else:
            endtime = None

        dataownercode = self.user.userprofile.company
        if 'Alle ritten' in self.data['journeys']:
            valid_journeys = self.clean_all_journeys(operatingday,
                                                     dataownercode, begintime,
                                                     endtime)
        elif 'Hele vervoerder' in self.data['lines']:
            valid_journeys = self.clean_all_lines(operatingday, dataownercode,
                                                  begintime, endtime)
        else:
            valid_journeys = self.clean_journeys(operatingday, dataownercode)

        if valid_journeys == 0:
            raise ValidationError(
                _("Er zijn geen ritten geselecteerd om op te heffen"))

        return cleaned_data

    def clean_journeys(self, operatingday, dataownercode):
        valid_journeys = 0
        if self.data['journeys'] != '':
            for journey in self.data['journeys'].split(',')[0:-1]:
                journey_qry = Kv1Journey.objects.filter(
                    dataownercode=dataownercode,
                    pk=journey,
                    dates__date=operatingday)
                if journey_qry.count() == 0:
                    raise ValidationError(
                        _("Een of meer geselecteerde ritten zijn ongeldig"))

                # delete recovered if query is the same.
                Kv17Change.objects.filter(dataownercode=dataownercode,
                                          journey__pk=journey,
                                          line=journey_qry[0].line,
                                          operatingday=operatingday,
                                          is_recovered=True).delete()

        else:
            raise ValidationError(_("Er werd geen rit geselecteerd."))

        valid_journeys += 1

        return valid_journeys

    def clean_all_journeys(self, operatingday, dataownercode, begintime,
                           endtime):
        valid_journeys = 0

        if 'lines' in self.data:
            if self.data['lines'] != '':
                for line in self.data['lines'].split(',')[0:-1]:
                    line_qry = Kv1Line.objects.filter(pk=line)

                    if line_qry.count() == 0:
                        raise ValidationError(_("Geen lijn gevonden."))

                    database_alljourneys = Kv17Change.objects.filter(
                        dataownercode=dataownercode,
                        is_alljourneysofline=True,
                        line=line_qry[0],
                        operatingday=operatingday,
                        is_recovered=False)

                    database_alllines = Kv17Change.objects.filter(
                        dataownercode=dataownercode,
                        is_alllines=True,
                        operatingday=operatingday,
                        is_recovered=False)

                    # delete recovered if query is the same.
                    Kv17Change.objects.filter(dataownercode=dataownercode,
                                              is_alljourneysofline=True,
                                              line=line_qry[0],
                                              operatingday=operatingday,
                                              begintime=begintime,
                                              endtime=endtime,
                                              is_recovered=True).delete()

                    if operatingday == datetime.today().date():
                        begintime = make_aware(
                            datetime.now()) if begintime is None else begintime
                    else:
                        begintime = make_aware(datetime.combine(operatingday, time((int(4))))) \
                            if begintime is None else begintime

                    if database_alllines:
                        if database_alllines.filter(
                                Q(endtime__gt=begintime) | Q(endtime=None),
                                Q(begintime__lte=begintime)
                                | Q(begintime=None)):
                            raise ValidationError(
                                _("De gehele vervoerder is al aangepast voor de aangegeven ingangstijd."
                                  ))

                    elif database_alljourneys:
                        if database_alljourneys.filter(
                                Q(endtime__gt=begintime) | Q(endtime=None),
                                Q(begintime__lte=begintime)
                                | Q(begintime=None)):
                            raise ValidationError(
                                _("Een of meer geselecteerde lijnen zijn al aangepast voor de aangegeven ingangstijd."
                                  ))
        else:
            raise ValidationError(_("Geen geldige lijn geselecteerd"))

        valid_journeys += 1

        return valid_journeys

    def clean_all_lines(self, operatingday, dataownercode, begintime, endtime):
        valid_journeys = 0

        database_alllines = Kv17Change.objects.filter(
            dataownercode=dataownercode,
            is_alllines=True,
            operatingday=operatingday,
            is_recovered=False)

        # delete recovered if query is the same.
        Kv17Change.objects.filter(dataownercode=dataownercode,
                                  is_alllines=True,
                                  is_recovered=True,
                                  operatingday=operatingday,
                                  begintime=begintime,
                                  endtime=endtime).delete()

        if database_alllines:
            if operatingday == datetime.today().date():
                begintime = make_aware(
                    datetime.now()) if begintime is None else begintime
            else:
                begintime = make_aware(datetime.combine(operatingday, time((int(4))))) \
                    if begintime is None else begintime

            if database_alllines.filter(
                    Q(endtime__gt=begintime) | Q(endtime=None),
                    Q(begintime__lte=begintime) | Q(begintime=None)):
                raise ValidationError(
                    _("De ingangstijd valt al binnen een geplande operatie."))

        valid_journeys += 1

        return valid_journeys

    def save(self, force_insert=False, force_update=False, commit=True):
        ''' Save each of the journeys in the model. This is a disaster, we return the XML
        TODO: Figure out a better solution fo this! '''
        operatingday = parse_date(self.data['operatingday'])
        if self.data['begintime_part'] != '':
            hh, mm = self.data['begintime_part'].split(':')
            begintime = make_aware(
                datetime.combine(operatingday, time(int(hh), int(mm))))
        else:
            begintime = None

        if self.data['endtime_part'] != '':
            hh_end, mm_end = self.data['endtime_part'].split(':')
            # if begintime is set and endtime is earlier than begintime add 1 day to operatingday of endtime
            if begintime and time(int(hh_end), int(mm_end)) < time(
                    int(hh), int(mm)):
                if time(0, 0) <= time(int(hh_end), int(mm_end)) < time(6, 0):
                    operatingday_endtime = operatingday + timedelta(days=1)
                endtime = make_aware(
                    datetime.combine(operatingday_endtime,
                                     time(int(hh_end), int(mm_end))))
            # else, operatingday is given day
            else:
                endtime = make_aware(
                    datetime.combine(operatingday,
                                     time(int(hh_end), int(mm_end))))
        else:
            endtime = None

        if 'Alle ritten' in self.data['journeys']:
            xml_output = self.save_all_journeys(operatingday, begintime,
                                                endtime)
        elif 'Hele vervoerder' in self.data['lines']:
            xml_output = self.save_all_lines(operatingday, begintime, endtime)
        else:
            xml_output = self.save_journeys(operatingday)

        return xml_output

    def save_all_journeys(self, operatingday, begintime, endtime):
        xml_output = []

        for line in self.data['lines'].split(',')[0:-1]:
            qry = Kv1Line.objects.filter(id=line)
            if qry.count() == 1:
                self.instance.pk = None
                self.instance.is_alljourneysofline = True
                self.instance.line = qry[0]
                self.instance.operatingday = operatingday
                self.instance.begintime = begintime
                self.instance.endtime = endtime
                self.instance.is_cancel = True

                # Unfortunately, we can't place this any earlier, because we don't have the dataownercode there
                if self.instance.line.dataownercode == self.instance.dataownercode:
                    self.instance.save()

                    # Add details
                    if self.data['reasontype'] != '0' or self.data[
                            'advicetype'] != '0':
                        Kv17JourneyChange(
                            change=self.instance,
                            reasontype=self.data['reasontype'],
                            subreasontype=self.data['subreasontype'],
                            reasoncontent=self.data['reasoncontent'],
                            advicetype=self.data['advicetype'],
                            subadvicetype=self.data['subadvicetype'],
                            advicecontent=self.data['advicecontent']).save()

                    xml_output.append(self.instance.to_xml())
                else:
                    log.error(
                        "Oops! mismatch between dataownercode of line (%s) and of user (%s) when saving journey cancel"
                        % (self.instance.line.dataownercode,
                           self.instance.dataownercode))

            else:
                log.error("Failed to find line %s" % line)

        return xml_output

    def save_journeys(self, operatingday):
        xml_output = []

        for journey in self.data['journeys'].split(',')[0:-1]:
            qry = Kv1Journey.objects.filter(id=journey,
                                            dates__date=operatingday)
            if qry.count() == 1:
                self.instance.pk = None
                self.instance.journey = qry[0]
                self.instance.line = qry[0].line
                self.instance.operatingday = operatingday
                self.instance.is_cancel = True

                # Shouldn't be necessary, but just in case:
                self.instance.begintime = None
                self.instance.endtime = None

                # Unfortunately, we can't place this any earlier, because we don't have the dataownercode there
                if self.instance.journey.dataownercode == self.instance.dataownercode:
                    self.instance.save()

                    # Add details
                    if self.data['reasontype'] != '0' or self.data[
                            'advicetype'] != '0':
                        Kv17JourneyChange(
                            change=self.instance,
                            reasontype=self.data['reasontype'],
                            subreasontype=self.data['subreasontype'],
                            reasoncontent=self.data['reasoncontent'],
                            advicetype=self.data['advicetype'],
                            subadvicetype=self.data['subadvicetype'],
                            advicecontent=self.data['advicecontent']).save()

                    xml_output.append(self.instance.to_xml())
                else:
                    log.error(
                        "Oops! mismatch between dataownercode of line (%s) and of user (%s) when saving journey cancel"
                        % (self.instance.journey.dataownercode,
                           self.instance.dataownercode))
            else:
                log.error("Failed to find journey %s" % journey)

        return xml_output

    def save_all_lines(self, operatingday, begintime, endtime):
        xml_output = []

        self.instance.pk = None
        self.instance.is_alllines = True
        self.instance.operatingday = operatingday
        self.instance.begintime = begintime
        self.instance.endtime = endtime
        self.instance.is_cancel = True

        # Unfortunately, we can't place this any earlier, because we don't have the dataownercode there
        if self.instance.dataownercode == self.user.userprofile.company:
            self.instance.save()

            # Add details
            if self.data['reasontype'] != '0' or self.data['advicetype'] != '0':
                Kv17JourneyChange(
                    change=self.instance,
                    reasontype=self.data['reasontype'],
                    subreasontype=self.data['subreasontype'],
                    reasoncontent=self.data['reasoncontent'],
                    advicetype=self.data['advicetype'],
                    subadvicetype=self.data['subadvicetype'],
                    advicecontent=self.data['advicecontent']).save()

            xml_output.append(self.instance.to_xml())
        else:
            log.error(
                "Oops! mismatch between dataownercode of line (%s) and of user (%s) when saving journey cancel"
                % (self.instance.line.dataownercode,
                   self.instance.dataownercode))

        return xml_output

    class Meta(object):
        model = Kv17Change
        exclude = [
            'dataownercode', 'line', 'journey', 'is_recovered', 'reinforcement'
        ]

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user', None)
        super(Kv17ChangeForm, self).__init__(*args, **kwargs)

        days = [[
            str(d['date'].strftime('%Y-%m-%d')),
            str(d['date'].strftime('%d-%m-%Y'))
        ] for d in Kv1JourneyDate.objects.all().filter(
            date__gte=datetime.today() -
            timedelta(days=1)).values('date').distinct('date').order_by('date')
                ]

        operating_day = days[((datetime.now().hour < 4) * -1) +
                             1] if len(days) > 1 else None
        self.fields['operatingday'].choices = days
        self.fields['operatingday'].initial = operating_day
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Accordion(
                AccordionGroup(_('Datum en tijd'), 'operatingday',
                               'begintime_part', 'endtime_part'),
                AccordionGroup(_('Oorzaak'), 'reasontype', 'subreasontype',
                               'reasoncontent'),
                AccordionGroup(_('Advies'), 'advicetype', 'subadvicetype',
                               'advicecontent')))
Beispiel #3
0
class ActionForm(FormWithFieldsetMixin, BetterBsModelForm):
    """form for creating or editing action"""

    date = forms.DateField(label=_(u"planned date"), required=False, widget=forms.TextInput())
    time = forms.TimeField(label=_(u"planned time"), required=False)

    end_date = forms.DateField(label=_(u"end date"), required=False, widget=forms.TextInput())
    end_time = forms.TimeField(label=_(u"end time"), required=False)

    amount = forms.DecimalField(label=_("Amount"), required=False)

    class Meta:
        """form from model"""
        model = models.Action
        fields = (
            'type', 'subject', 'date', 'time', 'status', 'status2', 'in_charge', 'detail',
            'amount', 'number', 'planned_date', 'end_date', 'end_time', 'end_datetime', 'opportunity'
        )
        fieldsets = [
            ('summary', {
                'fields': [
                    'subject', 'in_charge', 'date', 'time', 'planned_date', 'end_date', 'end_time', 'end_datetime',
                    'opportunity'
                ],
                'legend': _('Summary')
            }),
            ('type', {'fields': ['type', 'status', 'status2', 'amount', 'number'], 'legend': _('Type')}),
            ('details', {'fields': ['detail'], 'legend': _('Details')}),
        ]
        help_texts = {
            'amount': _('Amount is disabled when value is calculated'),
        }

    def __init__(self, *args, **kwargs):
        kwargs.pop('entity', None)
        instance = kwargs.get('instance', None)
        action_type = kwargs.pop('action_type', None)
        super(ActionForm, self).__init__(*args, **kwargs)
        self.title = u""
        if instance:
            action_type = instance.type
        self.action_type = action_type

        is_amount_calculated = False
        if action_type:
            is_amount_calculated = action_type.is_amount_calculated
            self.calculated_amount = Decimal("0")
            for fieldset_name, fieldset_attrs in self.Meta.fieldsets:
                if fieldset_name == 'type':
                    fieldset_attrs['legend'] = action_type.name
                    break
            self.fields['type'].widget = forms.HiddenInput()
            self.fields['type'].initial = action_type
            if instance:
                self.title = ugettext(u"Edition {0}").format(action_type.name)
            else:
                self.title = ugettext(u"Creation {0}").format(action_type.name)
        else:
            self.title = ugettext(u"Edit action") if instance else ugettext(u"Create action")

        is_auto_generated = (action_type and action_type.number_auto_generated) or \
                            (instance and instance.type and instance.type.number_auto_generated)
        if is_auto_generated:
            self.fields['number'].widget.attrs['disabled'] = 'disabled'
            self.fields['number'].required = False

        self.fields['amount'].widget.attrs['step'] = 'any'
        if is_amount_calculated:
            self.fields['amount'].widget.attrs['disabled'] = 'disabled'
        self.is_amount_calculated = is_amount_calculated

        if action_type and action_type.allowed_status.count():
            # let javascript disable the blank value if default_status
            choices = [('', "---------")]
            allowed_status = action_type.allowed_status.all()
            if instance and instance.frozen:
                allowed_status = allowed_status.filter(allowed_on_frozen=True)
            self.fields['status'].choices = choices + [
                (status.id, status.name) for status in allowed_status
            ]
            if action_type.default_status:
                self.fields['status'].initial = action_type.default_status.id
            else:
                self.fields['status'].initial = ''

        if action_type and action_type.allowed_status2.count():
            # let javascript disable the blank value if default_status2
            allowed_status2 = action_type.allowed_status2.all()
            if instance and instance.frozen:
                allowed_status2 = allowed_status2.filter(allowed_on_frozen=True)
            choices = [('', "---------")]
            self.fields['status2'].choices = choices + [
                (status.id, status.name) for status in allowed_status2
            ]
            if action_type.default_status2:
                self.fields['status2'].initial = action_type.default_status2.id
            else:
                self.fields['status2'].initial = ''
        else:
            self.fields['status2'].widget = forms.HiddenInput()

        self.fields['opportunity'].widget = forms.HiddenInput()
        self.fields['detail'].widget = forms.Textarea(attrs={'placeholder': _('enter details'), 'cols': '72'})

        self._init_dt_field("planned_date", "date", "time")
        self._init_dt_field("end_datetime", "end_date", "end_time")

    def _init_dt_field(self, dt_field, date_field, time_field):
        """init datetime fields"""
        self.fields[dt_field].widget = CalcHiddenInput()
        the_datetime = getattr(self.instance, dt_field) if self.instance else self.fields[dt_field].initial
        if the_datetime:
            self.fields[date_field].initial = the_datetime.date()
            if settings.USE_TZ:
                utc_dt = the_datetime.replace(tzinfo=timezone.utc)
                loc_dt = utc_dt.astimezone(timezone.get_current_timezone())
                self.fields[time_field].initial = loc_dt.time()
            else:
                self.fields[time_field].initial = the_datetime.time()

        is_frozen = self.instance.frozen if self.instance else False
        if is_frozen:
            self.fields[date_field].widget.attrs['disabled'] = 'disabled'
            self.fields[time_field].widget.attrs['disabled'] = 'disabled'

    def clean_status(self):
        """status validation"""
        type_of = self.cleaned_data.get('type') or self.action_type
        status = self.cleaned_data['status']
        if type_of:
            allowed_status = ([] if type_of.default_status else [None]) + list(type_of.allowed_status.all())
            if len(allowed_status) > 0 and status not in allowed_status:
                raise ValidationError(ugettext(u"This status can't not be used for this action type"))
        else:
            if status:
                raise ValidationError(ugettext(u"Please select a type before defining the status"))
        return status

    def clean_status2(self):
        """status validation"""
        type_of = self.cleaned_data['type']
        status = self.cleaned_data['status2']
        if type_of:
            allowed_status = ([] if type_of.default_status2 else [None]) + list(type_of.allowed_status2.all())
            if len(allowed_status) > 0 and status not in allowed_status:
                raise ValidationError(ugettext(u"This status can't not be used for this action type"))
        else:
            if status:
                raise ValidationError(ugettext(u"Please select a type before defining the status"))
        return status

    def clean_planned_date(self):
        """planned date validation"""
        the_date = self.cleaned_data.get("date", None)
        the_time = self.cleaned_data.get("time", None)
        if the_date:
            return datetime.combine(the_date, the_time or datetime.min.time())
        return None

    def clean_time(self):
        """time validation"""
        the_date = self.cleaned_data.get("date", None)
        the_time = self.cleaned_data.get("time", None)
        if the_time and not the_date:
            raise ValidationError(_(u"You must set a date"))
        return the_time

    def clean_end_date(self):
        """end date validation"""
        date1 = self.cleaned_data.get("date", None)
        date2 = self.cleaned_data.get("end_date", None)
        if date2:
            start_dt = self.cleaned_data["planned_date"]
            if not start_dt:
                raise ValidationError(_(u"The planned date is not defined"))
            if date1 > date2:
                raise ValidationError(_(u"The end date must be after the planned date"))
        return date2

    def clean_end_time(self):
        """end time validation"""
        date1 = self.cleaned_data.get("date", None)
        date2 = self.cleaned_data.get("end_date", None)
        time1 = self.cleaned_data.get("time", None)
        time2 = self.cleaned_data.get("end_time", None)

        if time2:
            if time2 and not date2:
                raise ValidationError(_(u"You must set a end date"))

            if date1 == date2 and (time1 or datetime.min.time()) >= time2:
                raise ValidationError(_(u"The end time must be after the planned time"))

        elif time1:
            if date1 == date2 and time1 >= datetime.min.time():
                raise ValidationError(_(u"The end time must be set"))
        return time2

    def clean_end_datetime(self):
        """clean end datetime"""
        end_date = self.cleaned_data.get("end_date", None)
        end_time = self.cleaned_data.get("end_time", None)
        if end_date:
            return datetime.combine(end_date, end_time or datetime.min.time())
        return None

    def clean_amount(self):
        if self.is_amount_calculated:
            return self.calculated_amount
        else:
            return self.cleaned_data['amount']

    def save(self, *args, **kwargs):
        return super(ActionForm, self).save(*args, **kwargs)