Example #1
0
    def get_info(self, id):
        if len(self.document.xpath('//libelle[@nom="MSG_AUCUN_EVT"]')) > 0:
            return None

        p = Parcel(id)
        p.arrival = NotAvailable
        p.history = []

        for i, tr in enumerate(
                self.document.xpath('//table[@class="tabListeEnvois"]//tr')):
            tds = tr.findall('td')
            if len(tds) < 3:
                continue

            ev = Event(i)
            ev.location = unicode(tds[1].text) if tds[1].text else None
            ev.activity = unicode(tds[1].find('br').tail)
            if tds[-1].text is not None:
                ev.activity += ', ' + self.parser.tocleanstring(tds[-1])
            date = re.sub('[a-z]+', '',
                          self.parser.tocleanstring(tds[0])).strip()
            date = re.sub('(\d+)/(\d+)/(\d+)', r'\3-\2-\1', date)
            ev.date = parse_date(date)
            p.history.append(ev)

        p.info = ' '.join([
            t.strip() for t in self.document.xpath(
                '//div[@class="numeroColi2"]')[0].itertext()
        ][1:])
        if u'Livraison effectuée' in p.history[0].activity:
            p.status = p.STATUS_ARRIVED

        return p
Example #2
0
    def get_parcel_tracking(self, _id):
        # 13 is the magic length of colissimo tracking ids
        if len(_id) != 13:
            raise ParcelNotFound(
                u"Colissimo ID's must have 13 print character")
        data = self.browser.get_tracking_info(_id)
        p = Parcel(_id)
        label = data['message']
        if data['error']:
            raise ParcelNotFound(label + u" (id = %s@%s)" % (_id, self.name))
        p.info = label
        # TODO, need to know the delivery message
        if u"remis au gardien ou" in label or u"Votre colis est livré" in label:
            p.status = p.STATUS_ARRIVED
        elif u"pas encore pris en charge par La Poste" in label:
            p.status = p.STATUS_PLANNED
        else:
            p.status = p.STATUS_IN_TRANSIT

        ev = Event(0)
        ev.activity = label
        ev.date = date(*reversed([int(x) for x in data['date'].split("/")]))
        p.history = [ev]

        return p
Example #3
0
 def get_info(self, _id):
     p = Parcel(_id)
     events = self.doc["tuStatus"][0]["history"]
     p.history = [self.build_event(i, tr) for i, tr in enumerate(events)]
     p.status = self.guess_status(self.doc["tuStatus"][0]["progressBar"]["statusInfo"])
     p.info = self.doc["tuStatus"][0]["progressBar"]["statusText"]
     return p
Example #4
0
    def get_info(self, id):
        if len(self.document.xpath('//libelle[@nom="MSG_AUCUN_EVT"]')) > 0:
            return None

        p = Parcel(id)
        p.arrival = NotAvailable
        p.history = []

        for i, tr in enumerate(self.document.xpath('//table[@class="tabListeEnvois"]//tr')):
            tds = tr.findall('td')
            if len(tds) < 3:
                continue

            ev = Event(i)
            ev.location = unicode(tds[1].text) if tds[1].text else None
            ev.activity = unicode(tds[1].find('br').tail)
            if tds[-1].text is not None:
                ev.activity += ', ' + self.parser.tocleanstring(tds[-1])
            date = re.sub('[a-z]+', '', self.parser.tocleanstring(tds[0])).strip()
            date = re.sub('(\d+)/(\d+)/(\d+)', r'\3-\2-\1', date)
            ev.date = parse_date(date)
            p.history.append(ev)

        p.info = ' '.join([t.strip() for t in self.document.xpath('//div[@class="numeroColi2"]')[0].itertext()][1:])
        if u'Livraison effectuée' in p.history[0].activity:
            p.status = p.STATUS_ARRIVED

        return p
Example #5
0
 def get_info(self, _id):
     p = Parcel(_id)
     events = self.doc["tuStatus"][0]["history"]
     p.history = [self.build_event(i, tr) for i, tr in enumerate(events)]
     p.status = self.guess_status(self.doc["tuStatus"][0]["progressBar"]["statusInfo"])
     p.info = self.doc["tuStatus"][0]["progressBar"]["statusText"]
     return p
Example #6
0
 def get_info(self, _id):
     if u'errors' in self.doc:
         raise ParcelNotFound("No such ID: %s" % _id)
     elif u'results' in self.doc:
         result = self.doc[u'results'][0]
         p = Parcel(_id)
         p.history = [self.build_event(e) for e in result[u'checkpoints']]
         p.status = self.STATUSES.get(result[u'delivery'][u'code'], Parcel.STATUS_UNKNOWN)
         p.info = p.history[0].activity
         return p
     else:
         raise ParcelNotFound("Unexpected reply from server")
Example #7
0
 def get_info(self, _id):
     if u'errors' in self.doc:
         raise ParcelNotFound("No such ID: %s" % _id)
     elif u'results' in self.doc:
         result = self.doc[u'results'][0]
         p = Parcel(_id)
         p.history = [self.build_event(e) for e in result[u'checkpoints']]
         p.status = self.STATUSES.get(result[u'delivery'][u'code'], Parcel.STATUS_UNKNOWN)
         p.info = p.history[0].activity
         return p
     else:
         raise ParcelNotFound("Unexpected reply from server")
Example #8
0
    def get_info(self, _id):
        result_id = self.doc.xpath('//th[@class="mm_sendungsnummer"]')
        if not result_id:
            raise ParcelNotFound("No such ID: %s" % _id)
        result_id = result_id[0].text
        if result_id != _id:
            raise ParcelNotFound("ID mismatch: expecting %s, got %s" % (_id, result_id))

        p = Parcel(_id)
        events = self.doc.xpath('//div[@class="accordion-inner"]/table/tbody/tr')
        p.history = [self.build_event(i, tr) for i, tr in enumerate(events)]
        p.status, p.info = self.guess_status(p.history[-1])
        return p
Example #9
0
    def get_info(self, _id):
        result_id = self.doc.xpath('//th[@class="mm_sendungsnummer"]')
        if not result_id:
            raise ParcelNotFound("No such ID: %s" % _id)
        result_id = result_id[0].text
        if result_id != _id:
            raise ParcelNotFound("ID mismatch: expecting %s, got %s" %
                                 (_id, result_id))

        p = Parcel(_id)
        events = self.doc.xpath(
            '//div[@class="accordion-inner"]/table/tbody/tr')
        p.history = [self.build_event(i, tr) for i, tr in enumerate(events)]
        p.status, p.info = self.guess_status(p.history[-1])
        return p
Example #10
0
    def get_info(self, _id):
        result_id = self.doc.xpath('//table[@id="shipment-details-table"]//tr[position()=1]/td[@id="td-bold"]')
        if not result_id:
            raise ParcelNotFound("No such ID: %s" % _id)
        result_id = result_id[0].text
        if result_id != _id:
            raise ParcelNotFound("ID mismatch: expecting %s, got %s" % (_id, result_id))

        p = Parcel(_id)
        events = self.doc.xpath('//div[@id="shipment-event-table-cell"]')
        p.history = [self.build_event(i, div) for i, div in enumerate(events)]
        most_recent = p.history[0]
        p.status, p.info = self.guess_status(p.history)
        p.info = most_recent.activity
        return p
Example #11
0
    def get_info(self, _id):
        result_id = self.doc.get("TrackingStatusJSON", {}).get("shipmentInfo", {}).get("parcelNumber", None)
        if not result_id:
            raise ParcelNotFound("No such ID: %s" % _id)
        if not _id.startswith(result_id):
            raise ParcelNotFound("ID mismatch: expecting %s, got %s" % (_id, result_id))

        p = Parcel(_id)
        events = self.doc.get("TrackingStatusJSON", {}).get("statusInfos", [])
        p.history = [self.build_event(i, data) for i, data in enumerate(events)]
        p.status = self.guess_status(
            self.doc.get("TrackingStatusJSON", {}).
            get("shipmentInfo", {}).
            get("deliveryStatus"))
        p.info = p.history[-1].activity
        return p
Example #12
0
    def get_info(self, _id):
        result_id = self.doc.get("TrackingStatusJSON", {}).get("shipmentInfo", {}).get("parcelNumber", None)
        if not result_id:
            raise ParcelNotFound("No such ID: %s" % _id)
        if not _id.startswith(result_id):
            raise ParcelNotFound("ID mismatch: expecting %s, got %s" % (_id, result_id))

        p = Parcel(_id)
        events = self.doc.get("TrackingStatusJSON", {}).get("statusInfos", [])
        p.history = [self.build_event(i, data) for i, data in enumerate(events)]
        p.status = self.guess_status(
            self.doc.get("TrackingStatusJSON", {}).
            get("shipmentInfo", {}).
            get("deliveryStatus"))
        p.info = p.history[-1].activity
        return p
Example #13
0
    def get_info(self, _id):
        result_id = self.doc.xpath(
            '//table[@id="shipment-details-table"]//tr[position()=1]/td[@id="td-bold"]'
        )
        if not result_id:
            raise ParcelNotFound("No such ID: %s" % _id)
        result_id = result_id[0].text
        if result_id != _id:
            raise ParcelNotFound("ID mismatch: expecting %s, got %s" %
                                 (_id, result_id))

        p = Parcel(_id)
        events = self.doc.xpath('//div[@id="shipment-event-table-cell"]')
        p.history = [self.build_event(i, div) for i, div in enumerate(events)]
        most_recent = p.history[0]
        p.status, p.info = self.guess_status(p.history)
        p.info = most_recent.activity
        return p
Example #14
0
    def get_info(self, _id):
        shipments = self.doc["shipments"]
        if not shipments:
            raise ParcelNotFound("No such ID: %s" % _id)
        shipment = shipments[0]
        result_id = shipment["trackingCode"]
        if result_id != _id:
            raise ParcelNotFound("ID mismatch: expecting %s, got %s" % (_id, result_id))

        p = Parcel(_id)
        if shipment["estimatedDeliveryTime"]:
            p.arrival = parse_date(shipment["estimatedDeliveryTime"], ignoretz=True)
        events = shipment["events"]
        p.history = [self.build_event(i, data) for i, data in enumerate(events)]
        most_recent = p.history[0]
        p.status, p.info = self.guess_status(p.history)
        p.info = most_recent.activity
        return p
Example #15
0
    def get_info(self, _id):
        result_id = self.doc.xpath('//th[@class="mm_sendungsnummer"]')
        if not result_id:
            raise ParcelNotFound("No such ID: %s" % _id)
        result_id = result_id[0].text
        if result_id != _id:
            raise ParcelNotFound("ID mismatch: expecting %s, got %s" % (_id, result_id))

        p = Parcel(_id)
        events = self.doc.xpath('//div[@class="accordion-inner"]/table/tbody/tr')
        p.history = [self.build_event(i, tr) for i, tr in enumerate(events)]
        status_msgs = self.doc.xpath('//tr[@class="mm_mailing_process "]//img[contains(@src, "ACTIVE")]/@alt')
        if len(status_msgs) > 0:
            p.status = self.STATUSES.get(status_msgs[-1], Parcel.STATUS_UNKNOWN)
        else:
            p.status = Parcel.STATUS_UNKNOWN
        p.info = p.history[-1].activity
        return p
Example #16
0
    def get_info(self, _id):
        result_id = self.doc.xpath('//th[@class="mm_sendungsnummer"]')
        if not result_id:
            raise ParcelNotFound("No such ID: %s" % _id)
        result_id = result_id[0].text
        if result_id != _id:
            raise ParcelNotFound("ID mismatch: expecting %s, got %s" % (_id, result_id))

        p = Parcel(_id)
        events = self.doc.xpath('//div[@class="accordion-inner"]/table/tbody/tr')
        p.history = [self.build_event(i, tr) for i, tr in enumerate(events)]
        status_msgs = self.doc.xpath('//tr[@class="mm_mailing_process "]//img[contains(@src, "ACTIVE")]/@alt')
        if len(status_msgs) > 0:
            p.status = self.STATUSES.get(status_msgs[-1], Parcel.STATUS_UNKNOWN)
        else:
            p.status = Parcel.STATUS_UNKNOWN
        p.info = p.history[-1].activity
        return p
Example #17
0
    def get_info(self, _id):
        p = Parcel(_id)

        statustr = self.document.xpath('//tr[@class="bandeauText"]')[0]
        status = self.parser.tocleanstring(statustr.xpath('td')[1])

        p.info = status
        p.status = p.STATUS_UNKNOWN

        p.history = []
        for i, tr in enumerate(self.document.xpath('//div[@class="mainbloc4Evt"]//tr')):
            tds = tr.findall('td')
            try:
                if tds[0].attrib['class'] != "titrestatutdate2":
                    continue
            except:
                continue

            ev = Event(i)
            ev.location = None
            ev.activity = self.parser.tocleanstring(tds[1])
            if u"Votre colis a été expédié par votre webmarchand" in ev.activity:
                update_status(p, p.STATUS_PLANNED)
            elif (
                u"Votre colis est pris en charge par Colis Privé" in ev.activity
                or u"Votre colis est arrivé sur notre agence régionale"
                in ev.activity
                or u"Votre colis est en cours de livraison" in ev.activity
            ):
                update_status(p, p.STATUS_IN_TRANSIT)
            elif u"Votre colis a été livré" in ev.activity:
                update_status(p, p.STATUS_ARRIVED)
            ev.date = date(*reversed([int(x) for x in self.parser.tocleanstring(tds[0]).split('/')]))
            p.history.append(ev)

        try:
            datelivre = self.document.xpath('//div[@class="NoInstNoRecla"]')
            clean = self.parser.tocleanstring(datelivre[0])
            if "Votre colis a déja été livré" in clean:
                p.status = p.STATUS_ARRIVED
        except:
            pass
        return p
Example #18
0
    def get_info(self, _id):
        p = Parcel(_id)

        statustr = self.doc.xpath('//tr[@class="bandeauText"]')[0]
        status = statustr.xpath('td')[1].text

        p.info = status
        p.status = p.STATUS_UNKNOWN

        p.history = []
        for i, tr in enumerate(self.doc.xpath('//table[@class="tableHistoriqueColis"]//tr[@class="bandeauText"]')):
            tds = tr.findall('td')
            try:
                if tds[0].attrib['class'] != "tdText":
                    continue
            except:
                continue

            ev = Event(i)
            ev.location = None
            ev.activity = tds[1].text
            if u"Votre colis a été expédié par votre webmarchand" in ev.activity:
                update_status(p, p.STATUS_PLANNED)
            elif u"Votre colis est pris en charge par Colis Privé" in ev.activity:
                update_status(p, p.STATUS_IN_TRANSIT)
            elif u"Votre colis est arrivé sur notre agence régionale" in ev.activity:
                update_status(p, p.STATUS_IN_TRANSIT)
            elif u"Votre colis est en cours de livraison" in ev.activity:
                update_status(p, p.STATUS_IN_TRANSIT)
            elif u"Votre colis a été livré" in ev.activity:
                update_status(p, p.STATUS_ARRIVED)
            ev.date = date(*reversed([int(x) for x in tds[0].text.split('/')]))
            p.history.append(ev)

        try:
            datelivre = self.doc.xpath('//div[@class="NoInstNoRecla"]')
            clean = datelivre[0].text
            if "Votre colis a déja été livré" in clean:
                p.status = p.STATUS_ARRIVED
        except:
            pass
        return p
Example #19
0
    def get_parcel_tracking(self, _id):
        # 13 is the magic length of colissimo tracking ids
        if len(_id) != 13:
            raise ParcelNotFound(u"Colissimo ID's must have 13 print character")

        events = self.browser.get_tracking_info(_id)
        p = Parcel(_id)
        p.history = events

        first = events[0]
        p.info = first.activity

        if u"remis au gardien ou" in p.info or u"Votre colis est livré" in p.info:
            p.status = p.STATUS_ARRIVED
        elif u"pas encore pris en charge par La Poste" in p.info:
            p.status = p.STATUS_PLANNED
        else:
            p.status = p.STATUS_IN_TRANSIT

        return p
Example #20
0
    def get_parcel_tracking(self, _id):
        # 13 is the magic length of colissimo tracking ids
        if len(_id) != 13:
            raise ParcelNotFound(u"Colissimo ID's must have 13 print character")

        events = self.browser.get_tracking_info(_id)
        p = Parcel(_id)
        p.history = events

        first = events[0]
        p.info = first.activity

        if u"remis au gardien ou" in p.info or u"Votre colis est livré" in p.info:
            p.status = p.STATUS_ARRIVED
        elif u"pas encore pris en charge par La Poste" in p.info:
            p.status = p.STATUS_PLANNED
        else:
            p.status = p.STATUS_IN_TRANSIT

        return p
Example #21
0
    def get_info(self, id):
        if len(
                self.parser.tocleanstring(
                    self.document.xpath('//p[@class="error"]')[0])) > 0:
            return None

        p = Parcel(id)
        for dl in self.document.xpath('//dl'):
            dt = dl.find('dt')
            dd = dl.find('dd')
            if dt is None or dd is None:
                continue
            label = self.parser.tocleanstring(dt)
            if label == 'Scheduled Delivery:':
                p.status = p.STATUS_IN_TRANSIT
            elif label == u'Delivered On:':
                p.status = p.STATUS_ARRIVED
            else:
                continue

            m = re.search('(\d+/\d+/\d+)', dd.text)
            if m:
                p.arrival = parse_date(m.group(1))

        p.history = []
        for i, tr in enumerate(
                self.document.xpath('//table[@class="dataTable"]//tr')):
            tds = tr.findall('td')
            if len(tds) < 4:
                continue

            ev = Event(i)
            ev.location = self.parser.tocleanstring(tds[0])
            ev.activity = self.parser.tocleanstring(tds[-1])
            ev.date = parse_date('%s %s' % (tds[1].text, tds[2].text))
            p.history.append(ev)

        p.info = self.document.xpath('//a[@id="tt_spStatus"]')[0].text.strip()

        return p
Example #22
0
    def get_info(self, _id):
        shipments = self.doc["shipments"]
        if not shipments:
            raise ParcelNotFound("No such ID: %s" % _id)
        shipment = shipments[0]
        result_id = shipment["trackingCode"]
        if result_id != _id:
            raise ParcelNotFound("ID mismatch: expecting %s, got %s" %
                                 (_id, result_id))

        p = Parcel(_id)
        if shipment["estimatedDeliveryTime"]:
            p.arrival = parse_date(shipment["estimatedDeliveryTime"],
                                   ignoretz=True)
        events = shipment["events"]
        p.history = [
            self.build_event(i, data) for i, data in enumerate(events)
        ]
        most_recent = p.history[0]
        p.status, p.info = self.guess_status(p.history)
        p.info = most_recent.activity
        return p
Example #23
0
    def get_parcel_tracking(self, _id):
        data = self.browser.get_tracking_info(_id)
        p = Parcel(_id)
        label = data['message']
        if data['error']:
            p.info = label
            return p
        p.info = label
        # TODO, need to know the delivery message
        if u"remis au gardien ou" in label or u"Votre colis est livré" in label:
            p.status = p.STATUS_ARRIVED
        elif u"pas encore pris en charge par La Poste" in label:
            p.status = p.STATUS_PLANNED
        else:
            p.status = p.STATUS_IN_TRANSIT

        ev = Event(0)
        ev.activity = label
        ev.date = date(*reversed([int(x) for x in data['date'].split("/")]))
        p.history = [ev]

        return p
Example #24
0
    def get_info(self, id):
        if len(self.parser.tocleanstring(self.document.xpath('//p[@class="error"]')[0])) > 0:
            return None

        p = Parcel(id)
        for dl in self.document.xpath('//dl'):
            dt = dl.find('dt')
            dd = dl.find('dd')
            if dt is None or dd is None:
                continue
            label = self.parser.tocleanstring(dt)
            if label == 'Scheduled Delivery:':
                p.status = p.STATUS_IN_TRANSIT
            elif label == u'Delivered On:':
                p.status = p.STATUS_ARRIVED
            else:
                continue

            m = re.search('(\d+/\d+/\d+)', dd.text)
            if m:
                p.arrival = parse_date(m.group(1))

        p.history = []
        for i, tr in enumerate(self.document.xpath('//table[@class="dataTable"]//tr')):
            tds = tr.findall('td')
            if len(tds) < 4:
                continue

            ev = Event(i)
            ev.location = self.parser.tocleanstring(tds[0])
            ev.activity = self.parser.tocleanstring(tds[-1])
            ev.date = parse_date('%s %s' % (tds[1].text, tds[2].text))
            p.history.append(ev)

        p.info = self.document.xpath('//a[@id="tt_spStatus"]')[0].text.strip()

        return p
Example #25
0
    def get_parcel_tracking(self, _id):
        # 13 is the magic length of colissimo tracking ids
        if len(_id) != 13:
            raise ParcelNotFound(u"Colissimo ID's must have 13 print character")
        data = self.browser.get_tracking_info(_id)
        p = Parcel(_id)
        label = data["message"]
        if data["error"]:
            raise ParcelNotFound(label + u" (id = %s@%s)" % (_id, self.name))
        p.info = label
        # TODO, need to know the delivery message
        if u"remis au gardien ou" in label or u"Votre colis est livré" in label:
            p.status = p.STATUS_ARRIVED
        elif u"pas encore pris en charge par La Poste" in label:
            p.status = p.STATUS_PLANNED
        else:
            p.status = p.STATUS_IN_TRANSIT

        ev = Event(0)
        ev.activity = label
        ev.date = date(*reversed([int(x) for x in data["date"].split("/")]))
        p.history = [ev]

        return p
Example #26
0
    def get_parcel_tracking(self, _id):
        """
        Get information about a parcel.

        :param _id: _id of the parcel
        :type _id: :class:`str`
        :rtype: :class:`Parcel`
        :raises: :class:`ParcelNotFound`
        """
        # Tracking number format:
        # - 2 chars: optional merchant identifier (eg, AM for Amazon, 85 for cdiscount, ...)
        # - 10 digits: shipment tracking number
        # - 2 digits: optional suffix, seems to always be "01" when present but is never sent to the API
        #
        # Many merchants seem to give only the 10 digits tracking number so the user needs to
        # manually select the merchant from a list in that case.

        merchant = None
        code = None

        _id = _id.strip().upper()

        if len(_id) == 10:
            code = _id
        elif len(_id) in (12, 14):
            merchant = _id[:2]
            code = _id[2:12]
        else:
            raise ParcelNotFound(
                "Tracking number must be 10, 12 or 14 characters long."
            )

        merchant = merchant or self.config['merchant'].get()

        if not merchant:
            # No merchant info in the tracking number
            # we have to ask the user to select it
            merchants = self.browser.get_merchants()
            raise BrowserQuestion(Value(
                'merchant', label='Merchant prefix (prepend to tracking number): ', tiny=False,
                choices=merchants,
            ))

        self.config['merchant'].set(None)
        name = self.config['last_name'].get()[:4].ljust(4).upper()

        events = list(self.browser.iter_events(merchant, code, name))

        parcel = Parcel(merchant + code)
        parcel.arrival = NotAvailable

        # This is what the legacy tracking website used to show
        # when there are no events yet
        parcel.info = "Votre commande est en cours d'acheminement dans notre réseau."

        parcel.history = events
        parcel.status = Parcel.STATUS_IN_TRANSIT

        if not events:
            parcel.status = Parcel.STATUS_PLANNED
            return parcel

        parcel.info = events[0].activity

        arrived_event = next((event for event in events
                             if "Votre colis est disponible" in event.activity),
                             None)

        if arrived_event:
            parcel.status = Parcel.STATUS_ARRIVED
            parcel.arrival = arrived_event.date

        return parcel
Example #27
0
    def get_parcel_tracking(self, _id):
        """
        Get information about a parcel.

        :param _id: _id of the parcel
        :type _id: :class:`str`
        :rtype: :class:`Parcel`
        :raises: :class:`ParcelNotFound`
        """
        # Tracking number format:
        # - 2 chars: optional merchant identifier (eg, AM for Amazon, 85 for cdiscount, ...)
        # - 10 digits: shipment tracking number
        # - 2 digits: optional suffix, seems to always be "01" when present but is never sent to the API
        #
        # Many merchants seem to give only the 10 digits tracking number so the user needs to
        # manually select the merchant from a list in that case.

        merchant = None
        code = None

        _id = _id.strip().upper()

        if len(_id) == 10:
            code = _id
        elif len(_id) in (12, 14):
            merchant = _id[:2]
            code = _id[2:12]
        else:
            raise ParcelNotFound(
                "Tracking number must be 10, 12 or 14 characters long.")

        merchant = merchant or self.config['merchant'].get()

        if not merchant:
            # No merchant info in the tracking number
            # we have to ask the user to select it
            merchants = self.browser.get_merchants()
            raise BrowserQuestion(
                Value(
                    'merchant',
                    label='Merchant prefix (prepend to tracking number): ',
                    tiny=False,
                    choices=merchants,
                ))

        self.config['merchant'].set(None)
        name = self.config['last_name'].get()[:4].ljust(4).upper()

        events = list(self.browser.iter_events(merchant, code, name))

        parcel = Parcel(merchant + code)
        parcel.arrival = NotAvailable

        # This is what the legacy tracking website used to show
        # when there are no events yet
        parcel.info = "Votre commande est en cours d'acheminement dans notre réseau."

        parcel.history = events
        parcel.status = Parcel.STATUS_IN_TRANSIT

        if not events:
            parcel.status = Parcel.STATUS_PLANNED
            return parcel

        parcel.info = events[0].activity

        arrived_event = next(
            (event for event in events
             if "Votre colis est disponible" in event.activity), None)

        if arrived_event:
            parcel.status = Parcel.STATUS_ARRIVED
            parcel.arrival = arrived_event.date

        return parcel