コード例 #1
0
ファイル: checkin.py プロジェクト: educorvi/edi.checkin
class ICheckin(model.Schema):
    """ Marker interface and Dexterity Python Schema for Checkin
    """

    start = schema.Datetime(title=_(u"Beginn der Checkin-Zeit"),
                            required=False)
    end = schema.Datetime(title=_(u"Ende der Checkin-Zeit"), required=False)
コード例 #2
0
ファイル: office.py プロジェクト: educorvi/edi.checkin
class IOffice(model.Schema):
    """ Marker interface and Dexterity Python Schema for Office
    """

    notification_mail = schema.TextLine(title=_(
        u"E-Mail-Adresse für Benachrichtigungen über fehlgeschlagene Checkins"
    ),
                                        constraint=validate_email,
                                        required=True)

    adressen = schema.List(
        title=_(u"Gültige E-Mail-Adressen für diesen Raum"),
        description=
        _(u"Hier legen Sie fest, welche Adressen für diesen Raum einchecken dürfen. Wenn hier keine\
                                         Adressen eingetragen wurden findet auch keine Überprüfung der Adressen statt."
          ),
        value_type=schema.TextLine(),
        constraint=validate_adressen,
        required=False)

    beginn = schema.TextLine(
        title=_(u"Frühester Zutritt zu diesem Raum (Format: HH:MM)"),
        constraint=validate_zeit,
        required=True)

    ende = schema.TextLine(
        title=_(u"Späteste Schließung des Raumes (Format: HH:MM)"),
        constraint=validate_zeit,
        required=True)

    maxtime = schema.Int(
        title=_(u"Maximale Aufenthaltsdauer pro Person in diesem Raum"),
        description=
        _(u"Angaben von 1-24 werden als Stunden, darüber hinaus als Minuten interpretiert."
          ),
        constraint=validate_maxtime,
        required=True)

    maxperson = schema.Int(
        title=_(u"Maximale Anzahl von Personen in diesem Raum"), required=True)

    overtime = schema.Int(
        title=
        _(u"Zeitzugabe in Minuten für Raumwechsel, Verspätungen und Verzögerungen"
          ),
        description=
        _(u"Die Zeitzugabe wird nur bei den internen Berechnungen zur maximalen Raumbesetzung verwendet.\
                          Die Angabe von 0 heisst: keine Zeitzugabe."),
        default=0,
        required=True)
コード例 #3
0
ファイル: checkinview.py プロジェクト: educorvi/edi.checkin
class ICheckin(model.Schema):

    email = schema.TextLine(title=_(u"Meine E-Mail-Adresse"),
                            constraint=validate_email,
                            required=True)

    rules = schema.Bool(title=_(
        u"Ich habe die Regeln zum Infektionsschutz befolgt. Es gelten die Regeln des Bundeslandes\
                                  in dem Du wohnst."),
                        required=True)

    healthy = schema.Bool(title=_(
        u"Ich fühle mich gesund und fit. Ich habe keine Erkältungssymptome. Ich habe kein Fieber\
                                  oder trockenen Husten."),
                          required=True)
コード例 #4
0
ファイル: office.py プロジェクト: educorvi/edi.checkin
def validate_zeit(value):
    regex = re.compile('^([01]?\d|2[0-3]):([0-5]?\d)$')
    if not regex.match(value):
        raise Invalid(
            _(u'Bitte geben Sie ein korrektes Format für die Uhrzeit an (HH:MM)'
              ))
    return True
コード例 #5
0
ファイル: events_view.py プロジェクト: educorvi/edi.checkin
 def get_upcoming_veranstaltungen(self):
     entries = []
     eventquery = {'query': (datetime.datetime.now()), 'range': 'min'}
     contents = ploneapi.content.find(context=self.context,
                                      portal_type="Veranstaltung",
                                      start=eventquery,
                                      sort_on="start",
                                      sort_order="ascending")
     for i in contents:
         entry = {}
         entry['title'] = i.Title
         entry['description'] = i.Description
         entry['url'] = i.getURL()
         entry['day'] = i.start.strftime('%d.%m.')
         entry['time'] = "%s - %s" % (i.start.strftime('%H:%M'),
                                      i.end.strftime('%H:%M'))
         if datetime.date.today() == i.start.date():
             entry['btnclass'] = u'btn btn-primary btn-lg'
             entry['comment'] = u''
         else:
             entry['btnclass'] = u'btn btn-primary btn-lg disabled'
             entry['comment'] = _(
                 u'Ein Checkin ist aus Gründen des Infektionsschutzes erst am Tag der Veranstaltung möglich'
             )
         entries.append(entry)
     return entries
コード例 #6
0
    def validate(self, value):
        """
        """
        super(AdressenValidator, self).validate(value)

        if len(value) > self.context.maxperson:
            raise Invalid(
                _(u'Die Anzahl der eingetragenen Adressen überschreitet die maximale Anzahl von Personen für diesen Raum.'
                  ))
コード例 #7
0
    def validate(self, value):
        """
        """
        super(StartValidator, self).validate(value)

        room_start = self.context.beginn.split(':')
        room_time_start = datetime.time(int(room_start[0]), int(room_start[1]))
        if value.time() < room_time_start:
            raise Invalid(
                _(u'Der Beginn der Veranstaltung darf nicht vor Öffnung des Raumes liegen.'
                  ))
コード例 #8
0
    def validate(self, value):
        """
        """
        super(EndValidator, self).validate(value)

        room_end = self.context.ende.split(':')
        room_time_end = datetime.time(int(room_end[0]), int(room_end[1]))
        if value.time() > room_time_end:
            raise Invalid(
                _(u'Dad Ende der Veranstaltung darf nicht nach Schließung des Raumes liegen.'
                  ))
コード例 #9
0
class IVeranstaltung(model.Schema):
    """ Marker interface and Dexterity Python Schema for Veranstaltung
    """
    start = schema.Datetime(title=_(u"Beginn der Veranstaltung"),
                            required=True)
    end = schema.Datetime(title=_(u"Ende der Veranstaltung"), required=True)

    adressen = schema.List(
        title=_(u"Gültige E-Mail-Adressen für diese Veranstaltung"),
        description=
        _(u"Hier legen Sie fest, welche Adressen für diese Veranstaltung einchecken dürfen."
          ),
        value_type=schema.TextLine(),
        constraint=validate_adressen,
        required=True)

    invitation = schema.Bool(
        title=_(u"Checkin Einladungen versenden"),
        description=
        _(u"Bei Markierung dieses Feldes werden die Einladungen mit dem Link zum Checkin automatisch\
                             versendet."))

    @invariant
    def start_before_end(data):
        if data.start > data.end:
            raise Invalid(
                _(u'Der Beginn der Veranstaltung muss vor dem Ende liegen.'))

    @invariant
    def same_day(data):
        if data.start.date() != data.end.date():
            raise Invalid(
                _(u'Veranstaltungsbeginn und Veranstaltungsende müssen am gleichen Tag liegen.'
                  ))
コード例 #10
0
 def same_day(data):
     if data.start.date() != data.end.date():
         raise Invalid(
             _(u'Veranstaltungsbeginn und Veranstaltungsende müssen am gleichen Tag liegen.'
               ))
コード例 #11
0
 def start_before_end(data):
     if data.start > data.end:
         raise Invalid(
             _(u'Der Beginn der Veranstaltung muss vor dem Ende liegen.'))
コード例 #12
0
ファイル: office.py プロジェクト: educorvi/edi.checkin
def validate_adressen(value):
    regex = re.compile('^.+@.+\.[^.]{2,}$')
    for i in value:
        if not regex.match(i):
            raise Invalid(_(u'%s ist keine korrekte E-Mail-Adresse' % i))
    return True
コード例 #13
0
ファイル: office.py プロジェクト: educorvi/edi.checkin
def validate_email(value):
    regex = re.compile('^.+@.+\.[^.]{2,}$')
    if not regex.match(value):
        raise Invalid(_(u'Bitte geben Sie eine korrekte E-Mail-Adresse an.'))
    return True
コード例 #14
0
ファイル: checkinview.py プロジェクト: educorvi/edi.checkin
class CheckinForm(AutoExtensibleForm, form.Form):

    label = _(u"Check In")
    description = _(
        u"Ein erfolgreich durchgeführter Checkin ist Voraussetzung für den Zutritt zu diesem Raum.\
                    Zur Gewährleistung des Infektionsschutzes besteht eine Pflicht zu wahren und vollständigen Angaben."
    )

    ignoreContext = True

    schema = ICheckin

    def check_times(self):
        """Prueft, ob der Checkin vor oder während der Öffnungszeit erfolgt und gibt den möglichen
           Zeitraum der Anwesenheit zurück.
           Es gilt: 
             Checkin vor Öffnungszeit -> Start = Bürozeit | Ende = Start + max Aufenthaltsdauer
             Checkin während der Öffnungszeit -> Start = Aktuelle Zeit | Ende = Aktuelle Zeit + max Aufenthaltsdauer oder Schliesszeit
        """
        start_data = [int(i) for i in self.context.beginn.split(':')]
        beginn = datetime.time(start_data[0], start_data[1])
        end_data = [int(i) for i in self.context.ende.split(':')]
        ende = datetime.time(end_data[0], end_data[1])
        heute = datetime.date.today()  #Datum
        jetzt = datetime.time(datetime.datetime.now().hour,
                              datetime.datetime.now().minute)  #Uhrzeit
        timezone = datetime.datetime.now(
            datetime.timezone.utc).astimezone().tzinfo
        if jetzt <= beginn:
            start = datetime.datetime.combine(heute, beginn, tzinfo=timezone)
            if self.context.maxtime <= 24:
                end = datetime.datetime.combine(
                    heute, beginn, tzinfo=timezone) + datetime.timedelta(
                        hours=self.context.maxtime)
            else:
                end = datetime.datetime.combine(
                    heute, beginn, tzinfo=timezone) + datetime.timedelta(
                        minutes=self.context.maxtime)
            checktimes = (start, end)
            return checktimes  #Datetime-Objekte mit Angabe der Zeitzone
        elif beginn < jetzt < ende:
            start = datetime.datetime.combine(heute, jetzt, tzinfo=timezone)
            finaltime = datetime.datetime.combine(heute, ende, tzinfo=timezone)
            end = finaltime
            if self.context.maxtime <= 24:
                if (start + datetime.timedelta(hours=self.context.maxtime)
                    ) <= finaltime:
                    end = start + datetime.timedelta(
                        hours=self.context.maxtime)
            else:
                if (start + datetime.timedelta(minutes=self.context.maxtime)
                    ) <= finaltime:
                    end = start + datetime.timedelta(
                        minutes=self.context.maxtime)
            checktimes = (start, end)
            return checktimes  #Datetime-Objekte mit Angabe der Zeitzone
        else:
            return None

    def alternate_checktimes(self, checktimes):
        """ Sucht innerhalb der Öffnungszeit in 5 Minuten Schritten nach alternativen Checkinzeiten. 
        """
        portal_catalog = ploneapi.portal.get_tool('portal_catalog')
        office_path = '/'.join(self.context.getPhysicalPath())
        end_hour = int(self.context.ende.split(':')[0])
        end_minutes = int(self.context.ende.split(':')[1])
        ende = datetime.time(end_hour, end_minutes)
        heute = datetime.date.today()
        timezone = datetime.datetime.now(
            datetime.timezone.utc).astimezone().tzinfo
        schliessung = datetime.datetime.combine(heute, ende, tzinfo=timezone)
        available_time = True
        check_start = checktimes[0]
        check_end = checktimes[1]
        maxtime = self.context.maxtime
        overtime = self.context.overtime
        maxperson = self.context.maxperson
        while available_time:
            check_start = check_start + datetime.timedelta(minutes=5)
            check_end = check_end + datetime.timedelta(minutes=5)
            query_current = {}
            if self.context.maxtime <= 24:
                query_current['start'] = {
                    'query':
                    (DateTime(check_start - datetime.timedelta(hours=maxtime) -
                              datetime.timedelta(minutes=overtime)),
                     DateTime(check_start + datetime.timedelta(minutes=1))),
                    'range':
                    'min:max'
                }
            else:
                query_current['start'] = {
                    'query':
                    (DateTime(check_start -
                              datetime.timedelta(minutes=maxtime) -
                              datetime.timedelta(minutes=overtime)),
                     DateTime(check_start + datetime.timedelta(minutes=1))),
                    'range':
                    'min:max'
                }
            query_current['portal_type'] = "Checkin"
            query_current['path'] = office_path
            brains = portal_catalog.unrestrictedSearchResults(**query_current)
            if len(brains) < maxperson:
                return (check_start, check_end
                        )  # neue Checkinzeit wird zurückgegeben
            else:
                if self.context.maxtime <= 24:
                    if schliessung - datetime.timedelta(
                            hours=maxtime) < check_start:
                        available_time = False
                else:
                    if schliessung - datetime.timedelta(
                            minutes=maxtime) < check_start:
                        available_time = False
        return ()  # es wurde keine alternative Checkinzeit gefunden

    def check_persons(self, email, checktimes):
        """ Prüft die Checkins (Personenzahl) im entsprechenden Zeitraum und legt einen neuen Checkin an,
            wenn der Zeitraum verfügbar ist.
        """
        portal_catalog = ploneapi.portal.get_tool('portal_catalog')
        office_path = '/'.join(self.context.getPhysicalPath())
        query_current = {}
        overtime = self.context.overtime  #Zeitzugabe
        maxtime = self.context.maxtime  #max. Aufenthaltsdauer
        maxperson = self.context.maxperson  #max. Personenzahl
        if maxtime <= 24:
            query_current['start'] = {
                'query':
                (DateTime(checktimes[0] - datetime.timedelta(hours=maxtime) -
                          datetime.timedelta(minutes=overtime)),
                 DateTime(checktimes[0] + datetime.timedelta(minutes=5))),
                'range':
                'min:max'
            }
        else:
            query_current['start'] = {
                'query':
                (DateTime(checktimes[0] - datetime.timedelta(minutes=maxtime) -
                          datetime.timedelta(minutes=overtime)),
                 DateTime(checktimes[0] + datetime.timedelta(minutes=5))),
                'range':
                'min:max'
            }
        query_current['portal_type'] = "Checkin"
        query_current['path'] = office_path
        query_current['Title'] = email
        brains = portal_catalog.unrestrictedSearchResults(**query_current)
        if len(brains) > 0:
            return {'status': 'warning', 'reason': u'alreadychecked'}
        del query_current['Title']
        brains = portal_catalog.unrestrictedSearchResults(**query_current)
        if len(brains) >= maxperson:
            checktimes = self.alternate_checktimes(checktimes)
            if checktimes:
                retcode = self.create_checkin(email, checktimes)
            else:
                return {'status': 'warning', 'reason': u'maxpersons'}
        else:
            retcode = self.create_checkin(email, checktimes)
        if retcode == 201:
            return {'status': 'success', 'times': checktimes}
        return {'status': 'error'}

    def create_checkin(self, email, checktimes):
        adminuser = ploneapi.portal.get_registry_record(
            'edi.checkin.browser.settings.ICheckinSettings.adminuser')
        adminpassword = ploneapi.portal.get_registry_record(
            'edi.checkin.browser.settings.ICheckinSettings.adminpassword')
        portal = ploneapi.portal.get().EffectiveDate().encode('utf-8')
        m = hashlib.sha256()
        m.update(portal)
        m.update(checktimes[0].isoformat().encode('utf-8'))
        m.update(email.encode('utf-8'))
        objid = m.hexdigest()
        endtime = checktimes[1] + datetime.timedelta(
            minutes=self.context.overtime)
        objjson = {
            '@type': 'Checkin',
            'id': objid,
            'title': email,
            'start': checktimes[0].isoformat(),
            'end': endtime.isoformat()
        }
        retcode = requests.post(self.context.absolute_url(),
                                headers={
                                    'Accept': 'application/json',
                                    'Content-Type': 'application/json'
                                },
                                json=objjson,
                                auth=(adminuser, adminpassword))
        status = retcode.status_code
        return status

    def create_qrcode(self, data, checktimes):
        portal = ploneapi.portal.get().EffectiveDate().encode('utf-8')
        m = hashlib.sha256()
        m.update(portal)
        m.update(checktimes[0].isoformat().encode('utf-8'))
        m.update(data.get('email').encode('utf-8'))
        checksum = m.hexdigest()
        url = self.context.absolute_url(
        ) + "/checkinchecker?checksum=%s" % checksum
        filehandle = tempfile.TemporaryFile()
        img = qrcode.make(url)
        img.save(filehandle)
        return filehandle

    def sendmails(self, data, checktimes):
        portal = ploneapi.portal.get().absolute_url()
        logo = portal + '/++theme++plonetheme.siguv/logo/bg-etem.svg'
        checkinurl = self.context.absolute_url()
        mime_msg = MIMEMultipart('related')
        mime_msg['Subject'] = u"Status des Checkins: %s (%s)" % (
            data.get('status'), data.get('email'))
        mime_msg['From'] = ploneapi.portal.get_registry_record(
            'plone.email_from_address')
        if data.get('status') == 'fail':
            mime_msg['CC'] = self.context.notification_mail
        mime_msg['To'] = data.get('email')
        mime_msg.preamble = 'This is a multi-part message in MIME format.'
        msgAlternative = MIMEMultipart('alternative')
        mime_msg.attach(msgAlternative)

        if data.get('status') == 'success':
            htmltext = successbody(data, checktimes, self.context.title,
                                   portal, logo, checkinurl)
        else:
            htmltext = dangerbody(data, self.context.title, portal, logo,
                                  checkinurl)

        msg_txt = MIMEText(htmltext, _subtype='html', _charset='utf-8')
        msgAlternative.attach(msg_txt)

        if data.get('status') == 'success':
            filehandle = self.create_qrcode(data, checktimes)
            filehandle.seek(0)
            msgImage = MIMEImage(filehandle.read())
            msgImage.add_header('Content-ID', '<image1>')
            mime_msg.attach(msgImage)

        mail_host = ploneapi.portal.get_tool(name='MailHost')
        mail_host.send(mime_msg.as_string())

    @button.buttonAndHandler(u'Checkin durchführen')
    def handleApply(self, action):
        data, errors = self.extractData()
        url = self.context.absolute_url()
        if errors:
            ploneapi.portal.show_message(message=_(
                u"Bitte überprüfe Deine E-Mail-Adresse und versuche es erneut."
            ),
                                         request=self.request,
                                         type='error')
            return self.request.response.redirect(url)

        if self.context.adressen:
            if data.get('email') not in self.context.adressen:
                ploneapi.portal.show_message(message=_(
                    "Mit dieser E-Mail-Adresse kannst Du nicht in diesen Raum einchecken."
                ),
                                             request=self.request,
                                             type='error')
                return self.request.response.redirect(url)

        if data.get('rules') and data.get('healthy'):
            checktimes = self.check_times()
            if checktimes:  #Tuple mit Datetime Objekten
                checkpersons = self.check_persons(data.get('email'),
                                                  checktimes)
                if checkpersons.get('status') == u'warning':
                    data['status'] = u'warning'
                    data['class'] = u'card text-white bg-warning'
                    data['date'] = datetime.datetime.now().strftime('%d.%m.%Y')
                    data['reason'] = checkpersons.get('reason')
                elif checkpersons.get('status') == u'success':
                    checktimes = checkpersons.get('times')
                    data['status'] = u'success'
                    data['class'] = u'card border-success'
                    data['date'] = datetime.datetime.now().strftime('%d.%m.%Y')
                    data['start'] = checktimes[0].strftime('%H:%M')
                    data['end'] = checktimes[1].strftime('%H:%M')
                    data['qrimage'] = '<img src="cid:image1" alt="img" />'
                else:
                    ploneapi.portal.show_message(
                        message=
                        "Ein Fehler ist aufgetreten. Bitte benachrichtige den Administrator.",
                        request=self.request,
                        type='error')
                    return self.request.response.redirect(url)
            else:
                data['status'] = u'warning'
                data['class'] = u'card text-white bg-warning'
                data['date'] = datetime.datetime.now().strftime('%d.%m.%Y')
                data['reason'] = 'outoftime'
        else:
            checktimes = None
            data['status'] = u'fail'
            data['class'] = u'card text-white bg-danger'
            data['date'] = (datetime.datetime.now() +
                            datetime.timedelta(days=14)).strftime('%d.%m.%Y')

        if data['status'] in ['success', 'fail']:
            mails = self.sendmails(data, checktimes)

        url += '/checked-hint'
        url += '?status=%s&class=%s&date=%s&start=%s&end=%s&reason=%s' % (
            data.get('status'), data.get('class'), data.get('date'),
            data.get('start'), data.get('end'), data.get('reason'))
        return self.request.response.redirect(url)
コード例 #15
0
ファイル: checkinview.py プロジェクト: educorvi/edi.checkin
    def handleApply(self, action):
        data, errors = self.extractData()
        url = self.context.absolute_url()
        if errors:
            ploneapi.portal.show_message(message=_(
                u"Bitte überprüfe Deine E-Mail-Adresse und versuche es erneut."
            ),
                                         request=self.request,
                                         type='error')
            return self.request.response.redirect(url)

        if self.context.adressen:
            if data.get('email') not in self.context.adressen:
                ploneapi.portal.show_message(message=_(
                    "Mit dieser E-Mail-Adresse kannst Du nicht in diesen Raum einchecken."
                ),
                                             request=self.request,
                                             type='error')
                return self.request.response.redirect(url)

        if data.get('rules') and data.get('healthy'):
            checktimes = self.check_times()
            if checktimes:  #Tuple mit Datetime Objekten
                checkpersons = self.check_persons(data.get('email'),
                                                  checktimes)
                if checkpersons.get('status') == u'warning':
                    data['status'] = u'warning'
                    data['class'] = u'card text-white bg-warning'
                    data['date'] = datetime.datetime.now().strftime('%d.%m.%Y')
                    data['reason'] = checkpersons.get('reason')
                elif checkpersons.get('status') == u'success':
                    checktimes = checkpersons.get('times')
                    data['status'] = u'success'
                    data['class'] = u'card border-success'
                    data['date'] = datetime.datetime.now().strftime('%d.%m.%Y')
                    data['start'] = checktimes[0].strftime('%H:%M')
                    data['end'] = checktimes[1].strftime('%H:%M')
                    data['qrimage'] = '<img src="cid:image1" alt="img" />'
                else:
                    ploneapi.portal.show_message(
                        message=
                        "Ein Fehler ist aufgetreten. Bitte benachrichtige den Administrator.",
                        request=self.request,
                        type='error')
                    return self.request.response.redirect(url)
            else:
                data['status'] = u'warning'
                data['class'] = u'card text-white bg-warning'
                data['date'] = datetime.datetime.now().strftime('%d.%m.%Y')
                data['reason'] = 'outoftime'
        else:
            checktimes = None
            data['status'] = u'fail'
            data['class'] = u'card text-white bg-danger'
            data['date'] = (datetime.datetime.now() +
                            datetime.timedelta(days=14)).strftime('%d.%m.%Y')

        if data['status'] in ['success', 'fail']:
            mails = self.sendmails(data, checktimes)

        url += '/checked-hint'
        url += '?status=%s&class=%s&date=%s&start=%s&end=%s&reason=%s' % (
            data.get('status'), data.get('class'), data.get('date'),
            data.get('start'), data.get('end'), data.get('reason'))
        return self.request.response.redirect(url)
コード例 #16
0
class CheckinForm(AutoExtensibleForm, form.Form):

    label = _(u"Check In")
    description = _(
        u"Ein erfolgreich durchgeführter Checkin ist Voraussetzung für den Zutritt zu dieser Veranstaltung.\
                    Zur Gewährleistung des Infektionsschutzes besteht eine Pflicht zu wahren und vollständigen Angaben."
    )

    ignoreContext = True

    schema = ICheckin

    def check_times(self):
        """Prueft, ob der Checkin vor oder während der Veranstaltungszeit erfolgt.
           Es gilt: 
             Checkin vor Veranstaltungsbeginn -> Start = Aktuelle Veranstaltungsbeginn| Ende = Veranstaltungsende 
             Checkin vor Ende der Veranstaltung -> Start = Aktuelle Zeit | Ende = Veranstaltungsende
             Checkin nach Ende der Veranstaltung = Kein Checkin möglich
        """
        beginn = self.context.start
        ende = self.context.end
        timezone = datetime.datetime.now(
            datetime.timezone.utc).astimezone().tzinfo
        current_datetime = datetime.datetime.now()
        if current_datetime <= beginn:
            start = beginn.replace(tzinfo=timezone)
            end = ende.replace(tzinfo=timezone)
            return (start, end)
        elif beginn < current_datetime < ende:
            start = current_datetime.replace(tzinfo=timezone)
            end = ende.replace(tzinfo=timezone)
            return (start, end)
        else:
            return None

    def check_persons(self, email, checktimes):
        """ Prüft die Checkins im Zeitraum und legt einen neuen Checkin an, wenn der Zeitraum verfügbar ist.
        """
        portal_catalog = ploneapi.portal.get_tool('portal_catalog')
        office_path = '/'.join(self.context.getPhysicalPath())
        query_current = {}
        query_current['start'] = {
            'query':
            (DateTime(self.context.start - datetime.timedelta(minutes=5)),
             DateTime(self.context.end + datetime.timedelta(minutes=5))),
            'range':
            'min:max'
        }
        query_current['portal_type'] = "Checkin"
        query_current['path'] = office_path
        query_current['Title'] = email
        brains = portal_catalog.unrestrictedSearchResults(**query_current)
        if len(brains) > 0:
            return {'status': 'warning', 'reason': u'alreadychecked'}
        del query_current['Title']
        print(query_current)
        brains = portal_catalog.unrestrictedSearchResults(**query_current)
        if len(brains) >= self.context.maxperson:
            return {'status': 'warning', 'reason': u'maxpersons'}
        else:
            retcode = self.create_checkin(email, checktimes)
        if retcode == 201:
            return {'status': 'success', 'times': checktimes}
        return {'status': 'error'}

    def create_checkin(self, email, checktimes):
        adminuser = ploneapi.portal.get_registry_record(
            'edi.checkin.browser.settings.ICheckinSettings.adminuser')
        adminpassword = ploneapi.portal.get_registry_record(
            'edi.checkin.browser.settings.ICheckinSettings.adminpassword')
        portal = ploneapi.portal.get().EffectiveDate().encode('utf-8')
        m = hashlib.sha256()
        m.update(portal)
        m.update(checktimes[0].isoformat().encode('utf-8'))
        m.update(email.encode('utf-8'))
        objid = m.hexdigest()
        endtime = checktimes[1] + datetime.timedelta(
            minutes=self.context.overtime)
        objjson = {
            '@type': 'Checkin',
            'id': objid,
            'title': email,
            'start': checktimes[0].isoformat(),
            'end': endtime.isoformat()
        }
        retcode = requests.post(self.context.absolute_url(),
                                headers={
                                    'Accept': 'application/json',
                                    'Content-Type': 'application/json'
                                },
                                json=objjson,
                                auth=(adminuser, adminpassword))
        status = retcode.status_code
        return status

    def create_qrcode(self, data, checktimes):
        portal = ploneapi.portal.get().EffectiveDate().encode('utf-8')
        m = hashlib.sha256()
        m.update(portal)
        m.update(checktimes[0].isoformat().encode('utf-8'))
        m.update(data.get('email').encode('utf-8'))
        checksum = m.hexdigest()
        url = self.context.absolute_url(
        ) + "/checkinchecker?checksum=%s" % checksum
        filehandle = tempfile.TemporaryFile()
        img = qrcode.make(url)
        img.save(filehandle)
        return filehandle

    def sendmails(self, data, checktimes):
        portal = ploneapi.portal.get().absolute_url()
        logo = portal + '/++theme++plonetheme.siguv/logo/bg-etem.svg'
        checkinurl = self.context.absolute_url()
        mime_msg = MIMEMultipart('related')
        mime_msg['Subject'] = u"Status des Checkins: %s (%s)" % (
            data.get('status'), data.get('email'))
        mime_msg['From'] = ploneapi.portal.get_registry_record(
            'plone.email_from_address')
        if data.get('status') == 'fail':
            mime_msg['CC'] = self.context.notification_mail
        mime_msg['To'] = data.get('email')
        mime_msg.preamble = 'This is a multi-part message in MIME format.'
        msgAlternative = MIMEMultipart('alternative')
        mime_msg.attach(msgAlternative)

        if data.get('status') == 'success':
            htmltext = successbody(data, checktimes, self.context.title,
                                   portal, logo, checkinurl)
        else:
            htmltext = dangerbody(data, self.context.title, portal, logo,
                                  checkinurl)

        msg_txt = MIMEText(htmltext, _subtype='html', _charset='utf-8')
        msgAlternative.attach(msg_txt)

        if data.get('status') == 'success':
            filehandle = self.create_qrcode(data, checktimes)
            filehandle.seek(0)
            msgImage = MIMEImage(filehandle.read())
            msgImage.add_header('Content-ID', '<image1>')
            mime_msg.attach(msgImage)

        mail_host = ploneapi.portal.get_tool(name='MailHost')
        mail_host.send(mime_msg.as_string())

    @button.buttonAndHandler(u'Checkin durchführen')
    def handleApply(self, action):
        data, errors = self.extractData()
        url = self.context.absolute_url()
        if errors:
            ploneapi.portal.show_message(
                message=
                "Bitte trage Deine E-Mail-Adresse ein und versuche es erneut.",
                request=self.request,
                type='error')
            return self.request.response.redirect(url)

        if self.context.adressen:
            if data.get('email') not in self.context.adressen:
                ploneapi.portal.show_message(
                    message=
                    "Mit dieser E-Mail-Adresse kannst Du nicht in diesen Raum einchecken.",
                    request=self.request,
                    type='error')
                return self.request.response.redirect(url)

        if data.get('rules') and data.get('healthy'):
            checktimes = self.check_times()
            if checktimes:
                checkpersons = self.check_persons(data.get('email'),
                                                  checktimes)
                if checkpersons.get('status') == u'warning':
                    data['status'] = u'warning'
                    data['class'] = u'card text-white bg-warning'
                    data['date'] = datetime.datetime.now().strftime('%d.%m.%Y')
                    data['reason'] = checkpersons.get('reason')
                elif checkpersons.get('status') == u'success':
                    checktimes = checkpersons.get('times')
                    data['status'] = u'success'
                    data['class'] = u'card border-success'
                    data['date'] = datetime.datetime.now().strftime('%d.%m.%Y')
                    data['start'] = checktimes[0].strftime('%H:%M')
                    data['end'] = checktimes[1].strftime('%H:%M')
                    data['qrimage'] = '<img src="cid:image1" alt="img" />'
                else:
                    ploneapi.portal.show_message(
                        message=
                        "Ein Fehler ist aufgetreten. Bitte benachrichtige den Administrator.",
                        request=self.request,
                        type='error')
                    return self.request.response.redirect(url)
            else:
                data['status'] = u'warning'
                data['class'] = u'card text-white bg-warning'
                data['date'] = datetime.datetime.now().strftime('%d.%m.%Y')
                data['reason'] = 'outoftime'
        else:
            checktimes = None
            data['status'] = u'fail'
            data['class'] = u'card text-white bg-danger'
            data['date'] = (datetime.datetime.now() +
                            datetime.timedelta(days=14)).strftime('%d.%m.%Y')

        if data['status'] in ['success', 'fail']:
            mails = self.sendmails(data, checktimes)

        url += '/checked-hint'
        url += '?status=%s&class=%s&date=%s&start=%s&end=%s&reason=%s' % (
            data.get('status'), data.get('class'), data.get('date'),
            data.get('start'), data.get('end'), data.get('reason'))
        return self.request.response.redirect(url)
コード例 #17
0
ファイル: office.py プロジェクト: educorvi/edi.checkin
def validate_maxtime(value):
    if value == 0:
        raise Invalid(
            _(u'Eine Angabe von 0 Stunden ergibt in diesem Kontext keinen Sinn. Bitte korrigieren.'
              ))
    return True