def _extract_details(node: Element, settings) -> TrackingDetails: info = XP.to_object(TrackInfoType, node) details: List[TrackDetailType] = [ *([info.TrackSummary] or []), *info.TrackDetail ] delivered = info.StatusCategory.lower() == "delivered" return TrackingDetails(carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=info.ID, events=[ TrackingEvent( code=str(event.EventCode), date=DF.fdate(event.EventDate, "%B %d, %Y"), time=DF.ftime(event.EventTime, "%H:%M %p"), description=event.Event, location=", ".join([ location for location in [ event.EventCity, event.EventState, event.EventCountry, str(event.EventZIPCode), ] if location is not None ]), ) for event in details ], delivered=delivered)
def _extract_tracking( track_detail_node: Element, settings: Settings ) -> Optional[TrackingDetails]: track_detail = TrackDetail() track_detail.build(track_detail_node) if track_detail.Notification.Severity == "ERROR": return None delivered = any(e.EventType == 'DL' for e in track_detail.Events) return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=track_detail.TrackingNumber, events=list( map( lambda e: TrackingEvent( date=DF.fdate(e.Timestamp, "%Y-%m-%d %H:%M:%S%z"), time=DF.ftime(e.Timestamp, "%Y-%m-%d %H:%M:%S%z"), code=e.EventType, location=e.ArrivalLocation, description=e.EventDescription, ), track_detail.Events, ) ), delivered=delivered )
def _extract_tracking_details(node: Element, settings: Settings) -> TrackingDetails: result = XP.build(TrackingResult, node) is_en = settings.language == "en" events = [ TrackingEvent( date=DF.fdate(event.local_date_time, '%Y%m%d %H%M%S'), description=(event.code_description_en if is_en else event.code_description_fr), location=SF.concat_str(event.address.address_line_1, event.address.address_line_2, event.address.city, event.address.province, event.address.country, join=True, separator=", "), code=event.code, time=DF.ftime(event.local_date_time, '%Y%m%d %H%M%S'), ) for event in cast(List[CanparTrackingEvent], result.events) ] return TrackingDetails(carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=result.barcode, events=events, delivered=any(event.code == 'DEL' for event in events))
def _extract_tracking( info_node: Element, settings: Settings ) -> Optional[TrackingDetails]: info = AWBInfo() info.build(info_node) if info.ShipmentInfo is None: return None return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=info.AWBNumber, events=list( map( lambda e: TrackingEvent( date=DF.fdate(e.Date), time=DF.ftime(e.Time), signatory=e.Signatory, code=e.ServiceEvent.EventCode, location=e.ServiceArea.Description, description=e.ServiceEvent.Description, ), info.ShipmentInfo.ShipmentEvent, ) ), )
def _extract_pickup_details(response: Element, settings: Settings) -> PickupDetails: header = next((XP.build(PickupRequestHeaderType, elt) for elt in response.xpath(".//*[local-name() = $name]", name="pickup-request-header"))) price = next((XP.build(PickupRequestPriceType, elt) for elt in response.xpath(".//*[local-name() = $name]", name="pickup-request-price")), None) price_amount = sum( [ NF.decimal(price.hst_amount or 0.0), NF.decimal(price.gst_amount or 0.0), NF.decimal(price.due_amount or 0.0), ], 0.0, ) if price is not None else None return PickupDetails( carrier_id=settings.carrier_id, carrier_name=settings.carrier_name, confirmation_number=header.request_id, pickup_date=DF.fdate(header.next_pickup_date), pickup_charge=ChargeDetails(name="Pickup fees", amount=NF.decimal(price_amount), currency="CAD") if price is not None else None, )
def _extract_details(shipment_node: Element, settings: Settings) -> TrackingDetails: track_detail = XP.build(ShipmentType, shipment_node) activities = [ XP.build(ActivityType, node) for node in shipment_node.xpath(".//*[local-name() = $name]", name="Activity") ] delivered = any(a.Status.Type == 'D' for a in activities) return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=track_detail.InquiryNumber.Value, events=list( map( lambda a: TrackingEvent( date=DF.fdate(a.Date, "%Y%m%d"), description=a.Status.Description if a.Status else None, location=(_format_location(a.ActivityLocation.Address) if a.ActivityLocation is not None and a. ActivityLocation.Address is not None else None), time=DF.ftime(a.Time, "%H%M%S"), code=a.Status.Code if a.Status else None, ), activities, )), delivered=delivered)
def _extract_pickup(response: Element, settings: Settings) -> PickupDetails: pickup = ModifyPUResponse() pickup.build(response) pickup_charge = ( ChargeDetails( name="Pickup Charge", amount=NF.decimal(pickup.PickupCharge), currency=pickup.CurrencyCode, ) if pickup.PickupCharge is not None else None ) pickup_date = ( DF.fdate(pickup.NextPickupDate) if pickup.NextPickupDate is not None else None ) return PickupDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, confirmation_number=str(pickup.ConfirmationNumber[0]), pickup_date=pickup_date, pickup_charge=pickup_charge, ready_time=DF.ftime(pickup.ReadyByTime), closing_time=DF.ftime(pickup.CallInTime), )
def _extract_detail(detail: Tracking, settings: Settings) -> TrackingDetails: return TrackingDetails(carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=detail.trackingNumber, events=[ TrackingEvent( date=DF.fdate(event.activityDate, '%Y-%m-%dT%H:%M:%SZ'), description=event.statusDetail, location=event.terminal, code=event.status, time=DF.ftime(event.activityDate, '%Y-%m-%dT%H:%M:%SZ'), ) for event in detail.activities ])
def _extract_detail(detail: MailPieces, settings: Settings) -> TrackingDetails: return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=detail.mailPieceId, events=[ TrackingEvent( date=DF.fdate(event.eventDateTime, '%Y-%m-%dT%H:%M:%S%z'), description=event.eventName, location=event.locationName, code=event.eventCode, time=DF.ftime(event.eventDateTime, '%Y-%m-%dT%H:%M:%S%z'), ) for event in detail.events ], )
def _extract_detail(detail: RouteResp, settings: Settings) -> TrackingDetails: return TrackingDetails(carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=detail.mailNo, events=[ TrackingEvent( date=DF.fdate(event.acceptTime, "%Y-%m-%d %H:%M:%S"), description=event.remark, location=event.acceptAddress, code=event.opCode, time=DF.ftime(event.acceptTime, "%Y-%m-%d %H:%M:%S"), ) for event in detail.routes ])
def _extract_detail(detail: dict, settings: Settings) -> TrackingDetails: result = DP.to_object(Result, detail) return TrackingDetails(carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=result.tracking_number, events=[ TrackingEvent( date=DF.fdate(event.time_stamp, '2019-08-15T18:52:19'), description=event.message, location=event.location, code=event.tracking_status, time=DF.ftime(event.time_stamp, '2019-08-15T18:52:19'), ) for event in result.checkpoints ], delivered=(result.tracking_status == 'LM40'))
def _extract_detail(detail: Shipment, settings: Settings) -> TrackingDetails: return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=str(detail.id), events=[ TrackingEvent( date=DF.fdate(event.timestamp, '%Y-%m-%dT%H:%M:%S'), description=event.description, location=(event.location.address.addressLocality if event.location is not None and event.location.address is not None else None), code=event.statusCode, time=DF.ftime(event.timestamp, '%Y-%m-%dT%H:%M:%S'), ) for event in detail.events ], delivered=detail.status.status.lower() == "delivered")
def _extract_detail(detail: Tuple[str, Tracking], settings: Settings) -> TrackingDetails: tracking_number, tracking_details = detail return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=tracking_number, events=[ TrackingEvent( date=DF.fdate(event.scan_time, '%Y-%m-%dT%H:%M:%SZ'), description=event.description, location=event.location, code=event.event_type, time=DF.ftime(event.scan_time, '%Y-%m-%dT%H:%M:%SZ'), ) for event in reversed(tracking_details.tracking_events) ], delivered=(tracking_details.state == 'Delivered'))
def _extract_detail(detail: TrackingResult, settings: Settings) -> TrackingDetails: item = detail.trackable_items[0] return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=detail.tracking_id, events=[ TrackingEvent( date=DF.fdate(event.date, '%Y-%m-%dT%H:%M:%S%z'), description=event.description, location=event.location, time=DF.ftime(event.date, '%Y-%m-%dT%H:%M:%S%z'), ) for event in item.events ], delivered=(detail.status == 'Delivered') )
def _extract_tracking(node: Element, settings: Settings) -> TrackingDetails: track = TrackingInformation() track.build(node) return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=str(track.PIN.Value), events=[ TrackingEvent( date=DF.fdate(cast(Scan, scan).ScanDate), time=DF.ftimestamp(cast(Scan, scan).ScanTime), description=cast(Scan, scan).Description, location=cast(Depot, cast(Scan, scan).Depot).Name, code=cast(Scan, scan).ScanType, ) for scan in track.Scans.Scan ], )
def _extract_tracking(node: Element, settings: Settings) -> TrackingDetails: track = XP.to_object(TrackingInformation, node) return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=str(track.PIN.Value), events=[ TrackingEvent( date=DF.fdate(scan.ScanDate), time=DF.ftime(scan.ScanTime, '%H%M%S'), description=scan.Description, location=scan.Depot.Name, code=scan.ScanType, ) for scan in track.Scans.Scan ], delivered=any(scan.ScanType == "Delivery" for scan in track.Scans.Scan) )
def _extract_tracking(pin_summary_node: Element, settings: Settings) -> TrackingDetails: pin_summary_ = pin_summary() pin_summary_.build(pin_summary_node) return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=pin_summary_.pin, events=[ TrackingEvent( date=DF.fdate(pin_summary_.event_date_time, "%Y%m%d:%H%M%S"), time=DF.ftime(pin_summary_.event_date_time, "%Y%m%d:%H%M%S"), signatory=pin_summary_.signatory_name, code=pin_summary_.event_type, location=pin_summary_.event_location, description=pin_summary_.event_description, ) ], )
def _extract_tracking(detail_node: Element, settings: Settings) -> TrackingDetails: pin = XP.find("pin", detail_node, first=True) events: List[occurrenceType] = XP.find("occurrence", detail_node, occurrenceType) return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=pin.text, events=[ TrackingEvent( date=DF.fdate(event.event_date, "%Y-%m-%d"), time=DF.ftime(event.event_time, "%H:%M:%S"), code=event.event_identifier, location=SF.concat_str(event.event_site, event.event_province, join=True, separator=', '), description=event.event_description ) for event in events ], delivered=any(e.event_identifier in TRACKING_DELIVERED_EVENT_CODES for e in events) )
def _extract_detail(node: Element, settings: Settings) -> TrackingDetails: detail = XP.build(ConsignmentType, node) return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=detail.ConsignmentNumber, events=[ TrackingEvent( date=DF.fdate(status.LocalEventDate.valueOf_, '%Y%m%d'), description=status.StatusDescription, location=SF.concat_str(status.Depot, status.DepotName, join=True, separator='-'), code=status.StatusCode, time=DF.ftime(status.LocalEventTime.valueOf_, '%H%M') ) for status in cast(List[StatusStructure], detail.StatusData) ], delivered=(detail.SummaryCode == "DEL") )
def _extract_detail(detail: dict, settings: Settings) -> TrackingDetails: tracking = DP.to_object(Tracking, detail) delivered = (tracking.trackingMilestoneEvents[0].eventCode == 'Delivered' if len(tracking.trackingMilestoneEvents) > 0 else False) return TrackingDetails(carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=tracking.trackingNumberVendor, events=[ TrackingEvent( date=DF.fdate(event.eventOn, _date_format(event.eventOn)), time=DF.ftime(event.eventOn, _date_format(event.eventOn)), description=event.eventDescription, location=event.eventLocation, code=event.eventCode, ) for event in tracking.trackingMilestoneEvents ], delivered=delivered)
def _extract_tracking_details(infos: Tuple[str, TrackingInfo], settings: Settings) -> TrackingDetails: tracking_number, events = infos ordered_events = [ *reversed( sorted(events, key=lambda e: DF.date(e.StatusDate, "%Y-%m-%dT%H:%M:%S"))) ] return TrackingDetails(carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=tracking_number, events=[ TrackingEvent( date=DF.fdate(event.StatusDate, "%Y-%m-%dT%H:%M:%S"), time=DF.ftime(event.StatusDate, "%Y-%m-%dT%H:%M:%S"), description=event.Status, ) for event in ordered_events ], delivered=('Delivered' in ordered_events[0].Status))
def _extract_tracking(info_node: Element, settings: Settings) -> Optional[TrackingDetails]: tracking_number = XP.find('AWBNumber', info_node, first=True).text events: List[ShipmentEvent] = XP.find('ShipmentEvent', info_node, ShipmentEvent) delivered = any(e.ServiceEvent.EventCode == 'OK' for e in events) return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=tracking_number, events=[ TrackingEvent( date=DF.fdate(e.Date), time=DF.ftime(e.Time), code=e.ServiceEvent.EventCode, location=e.ServiceArea.Description, description=f'{e.ServiceEvent.Description} {e.Signatory}'. strip(), ) for e in reversed(events) ], delivered=delivered)
def create_shipment_tracker(shipment: Optional[models.Shipment], context): rate_provider = (shipment.meta or {}).get("rate_provider") or shipment.carrier_name carrier = shipment.selected_rate_carrier if (rate_provider != shipment.carrier_name) and rate_provider in MODELS: carrier = (MODELS[rate_provider].access_by(context).filter( test=shipment.test_mode).first()) if carrier is not None: try: tracker = models.Tracking.objects.create( tracking_number=shipment.tracking_number, events=[ DP.to_dict( datatypes.TrackingEvent( date=DF.fdate(shipment.updated_at), description="Label created and ready for shipment", location="", code="CREATED", time=DF.ftime(shipment.updated_at), )) ], delivered=False, status=TrackerStatus.pending.value, test_mode=carrier.test, tracking_carrier=carrier, created_by=shipment.created_by, shipment=shipment, ) tracker.save() link_org(tracker, context) logger.info( f"Successfully added a tracker to the shipment {shipment.id}") except Exception as e: logger.exception("Failed to create new label tracker", e)
def rate_request(payload: RateRequest, settings: Settings) -> Serializable[RateV4Request]: """Create the appropriate USPS rate request depending on the destination :param payload: Purplship unified API rate request data :param settings: USPS connection and auth settings :return: a domestic or international USPS compatible request :raises: an OriginNotServicedError when origin country is not serviced by the carrier """ if payload.shipper.country_code is not None and payload.shipper.country_code != Country.US.name: raise OriginNotServicedError(payload.shipper.country_code) if payload.recipient.country_code is not None and payload.recipient.country_code == Country.US.name: raise DestinationNotServicedError(payload.recipient.country_code) package = Packages(payload.parcels).single options = Options(payload.options, ShipmentOption) service = (Services(payload.services, ShipmentService).first or ShipmentService.usps_all) special_services = [ getattr(option, 'value', option) for key, option in options if 'usps_option' not in key ] insurance = next( (option.value for key, option in options if 'usps_insurance' in key), options.insurance) container = PackagingType[package.packaging_type or "your_packaging"] sort_level = (SortLevelType[container.name].value if service.value in ["All", "Online"] else None) mail_type = (FirstClassMailType[container.name].value if 'first_class' in service.value else None) request = RateV4Request( USERID=settings.username, Revision="2", Package=[ PackageType( ID=0, Service=service.value, FirstClassMailType=mail_type, ZipOrigination=payload.shipper.postal_code, ZipDestination=payload.recipient.postal_code, Pounds=package.weight.LB, Ounces=package.weight.OZ, Container=container.value, Width=package.width.IN, Length=package.length.IN, Height=package.height.IN, Girth=package.girth.value, Value=insurance, AmountToCollect=options.cash_on_delivery, SpecialServices=(SpecialServicesType( SpecialService=[s for s in special_services]) if any(special_services) else None), Content=None, GroundOnly=options.usps_option_ground_only, SortBy=sort_level, Machinable=(options.usps_option_machinable_item or False), ReturnLocations=options.usps_option_return_service_info, ReturnServiceInfo=options.usps_option_return_service_info, DropOffTime=('13:30' if options.shipment_date is not None else None), ShipDate=(ShipDateType( valueOf_=DF.fdate(options.shipment_date)) if options.shipment_date is not None else None), ) ], ) return Serializable(request, XP.export)