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 pickup_request(payload: PickupRequest, _) -> Serializable: shipments: List[ShipmentDetails] = payload.options.get('shipments', []) after = DF.date(f"{payload.pickup_date} {payload.ready_time}", current_format="%Y-%m-%d %H:%M") before = DF.date(f"{payload.pickup_date} {payload.ready_time}", current_format="%Y-%m-%d %H:%M") request = BoxKnightPickupRequest( packageCount=len(payload.parcels), recipient=Recipient( name=payload.address.person_name, phone=payload.address.phone_number, notes=None, email=payload.address.email, ), recipientAddress=PickupRequestRecipientAddress( street=SF.concat_str(payload.address.address_line1, payload.address.address_line2, join=True), city=payload.address.city, province=payload.address.state_code, country=payload.address.country_code, postalCode=payload.address.postal_code, unit=None ), notes=payload.instruction, completeAfter=int(after.timestamp() * 1000.0), completeBefore=int(before.timestamp() * 1000.0), orderIds=[shipment.shipment_identifier for shipment in shipments], ) return Serializable(request)
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_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_quote(qtdshp_node: Element, settings: Settings) -> RateDetails: qtdshp = ResponseQtdShpType() qtdshp.build(qtdshp_node) if qtdshp.ShippingCharge is None or qtdshp.ShippingCharge == 0: return None ExtraCharges = list( map( lambda s: ChargeDetails(name=s.LocalServiceTypeName, amount=NF.decimal(s.ChargeValue or 0)), qtdshp.QtdShpExChrg, )) Discount_ = reduce( lambda d, ec: d + ec.amount if "Discount" in ec.name else d, ExtraCharges, 0.0) DutiesAndTaxes_ = reduce( lambda d, ec: d + ec.amount if "TAXES PAID" in ec.name else d, ExtraCharges, 0.0) delivery_date = DF.date(qtdshp.DeliveryDate[0].DlvyDateTime, "%Y-%m-%d %H:%M:%S") pricing_date = DF.date(qtdshp.PricingDate) transit = ((delivery_date - pricing_date).days if all([delivery_date, pricing_date]) else None) service_name = next( (p.name for p in ProductCode if p.value == qtdshp.GlobalProductCode), None, ) return RateDetails(carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, currency=qtdshp.CurrencyCode, transit_days=transit, service=(service_name or qtdshp.GlobalProductCode), base_charge=NF.decimal(qtdshp.WeightCharge), total_charge=NF.decimal(qtdshp.ShippingCharge), duties_and_taxes=NF.decimal(DutiesAndTaxes_), discount=NF.decimal(Discount_), extra_charges=list( map( lambda s: ChargeDetails( name=s.LocalServiceTypeName, amount=NF.decimal(s.ChargeValue), currency=qtdshp.CurrencyCode, ), qtdshp.QtdShpExChrg, )), meta=(dict(service=qtdshp.GlobalProductCode, service_name=qtdshp.ProductShortName) if service_name is None else None))
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_details(service_node: Element, settings: Settings) -> RateDetails: service: ServiceType = ServiceType() service.build(service_node) currency = "USD" special_services: List[ExtraServiceType] = [ XP.build(ExtraServiceType, svc) for svc in service_node.xpath(".//*[local-name() = $name]", name="ExtraService") ] delivery_date = DF.date(service.GuaranteeAvailability, "%m/%d/%Y") transit = ((delivery_date - datetime.now()).days if delivery_date is not None else None) rate_service: Service = Service.find(service.SvcDescription) return RateDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, service=rate_service.value, base_charge=NF.decimal(service.Postage), total_charge=NF.decimal(service.Postage), currency=currency, transit_days=transit, extra_charges=[ ChargeDetails( name=ExtraService(special.ServiceID).name, amount=NF.decimal(special.Price), currency=currency, ) for special in special_services ], )
def _extract_details(postage_node: Element, settings: Settings) -> RateDetails: postage: PostageType = XP.to_object(PostageType, postage_node) service = ServiceClassID.map(str(postage.CLASSID)) charges: List[SpecialServiceType] = getattr(postage.SpecialServices, 'SpecialService', []) rate = NF.decimal(XP.find('Rate', postage_node, first=True).text) estimated_date = DF.date( getattr(XP.find('CommitmentDate', postage_node, first=True), 'text', None)) transit = ((estimated_date.date() - datetime.now().date()).days if estimated_date is not None else None) return RateDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, service=service.name_or_key, base_charge=rate, total_charge=rate, currency=Currency.USD.name, transit_days=transit, extra_charges=[ ChargeDetails( name=charge.ServiceName, amount=NF.decimal(charge.Price), currency=Currency.USD.name, ) for charge in charges ], meta=dict(service_name=(service.name or postage.MailService)))
def _extract_details(postage_node: Element, settings: Settings) -> RateDetails: postage: PostageType = PostageType() postage.build(postage_node) currency = Currency.USD.name services: List[SpecialServiceType] = [ XP.build(SpecialServiceType, svc) for svc in postage_node.xpath(".//*[local-name() = $name]", name="SpecialService") ] estimated_date = DF.date(postage.CommitmentDate) transit = ((estimated_date - datetime.now()).days if estimated_date is not None else None) postage_rate = postage_node.find("Rate").text def get(key: str) -> Any: return reduce(lambda r, v: v.text, postage_node.findall(key), None) return RateDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, service=Service.find(get("MailService")).name, total_charge=NF.decimal(postage_rate), currency=currency, transit_days=transit, extra_charges=[ ChargeDetails( name=SpecialService(str(svc.ServiceID)).name, amount=NF.decimal(svc.Price), currency=currency, ) for svc in services ], )
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_details(postage_node: Element, settings: Settings) -> RateDetails: postage: ServiceType = XP.to_object(ServiceType, postage_node) service = ServiceClassID.map(str(postage.ID)) charges: List[ExtraServiceType] = postage.ExtraServices.ExtraService delivery_date = DF.date(postage.GuaranteeAvailability, "%m/%d/%Y") transit = ((delivery_date.date() - datetime.now().date()).days if delivery_date is not None else None) return RateDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, service=service.name_or_key, base_charge=NF.decimal(postage.Postage), total_charge=NF.decimal(postage.Postage), currency=Currency.USD.name, transit_days=transit, extra_charges=[ ChargeDetails( name=charge.ServiceName, amount=NF.decimal(charge.Price), currency=Currency.USD.name, ) for charge in charges ], meta=dict(service_name=service.name or postage.SvcDescription) )
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(service_node: Element, settings: Settings) -> RateDetails: service: ServiceType = XP.build(ServiceType, service_node) charges: List[ExtraServiceType] = service.ExtraServices.ExtraService delivery_date = DF.date(service.GuaranteeAvailability, "%m/%d/%Y") transit = ( (delivery_date - datetime.now()).days if delivery_date is not None else None ) return RateDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, service=ServiceClassID(str(service.ID)), base_charge=NF.decimal(service.Postage), total_charge=NF.decimal(service.Postage), currency=Currency.USD.name, transit_days=transit, extra_charges=[ ChargeDetails( name=charge.ServiceID, amount=NF.decimal(charge.Price), currency=Currency.USD.name, ) for charge in charges ], )
def _extract_details(postage_node: Element, settings: Settings) -> RateDetails: postage: PostageType = XP.build(PostageType, postage_node) charges: List[SpecialServiceType] = postage.SpecialServices.SpecialService estimated_date = DF.date(postage.CommitmentDate) transit = ( (estimated_date - datetime.now()).days if estimated_date is not None else None ) return RateDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, service=ServiceClassID(str(postage.CLASSID)), total_charge=NF.decimal(postage.Rate), currency=Currency.USD.name, transit_days=transit, extra_charges=[ ChargeDetails( name=charge.ServiceName, amount=NF.decimal(charge.Price), currency=Currency.USD.name, ) for charge in charges ] )
def pickup_rate_request(payload: PickupRequest, settings: Settings) -> Serializable[Envelope]: pickup_date = DF.date(payload.pickup_date) same_day = pickup_date.date() == datetime.today().date() request = create_envelope( header_content=settings.Security, body_content=PickupRateRequest( Request=RequestType(), ShipperAccount=None, PickupAddress=PickupAddressType( CompanyName=payload.address.company_name, ContactName=payload.address.person_name, AddressLine=SF.concat_str(payload.address.address_line1, payload.address.address_line2), Room=None, Floor=None, City=payload.address.city, StateProvince=payload.address.state_code, Urbanization=None, PostalCode=payload.address.postal_code, CountryCode=payload.address.country_code, ResidentialIndicator=("Y" if payload.address.residential else "N"), PickupPoint=payload.package_location, Phone=PhoneType(Number=payload.address.phone_number, Extension=None) if payload.address.phone_number is not None else None, ), AlternateAddressIndicator="Y", ServiceDateOption=("01" if same_day else "02"), PickupDateInfo=PickupDateInfoType( CloseTime=DF.ftime(payload.closing_time, "%H:%M", "%H%M"), ReadyTime=DF.ftime(payload.ready_time, "%H:%M", "%H%M"), PickupDate=pickup_date.strftime("%Y%m%d"), ), TaxInformationIndicator=None, UserLevelDiscountIndicator=None, ), ) return Serializable( request, default_request_serializer( "v11", 'xmlns:v11="http://www.ups.com/XMLSchema/XOLTWS/Pickup/v1.1"'), )
def _extract_detail(node: Element, settings: Settings) -> TrackingDetails: detail = XP.build(TrackingResult, node) return TrackingDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, tracking_number=detail.WaybillNumber, events=[ TrackingEvent( date=DF.date(detail.UpdateDateTime, '%Y-%m-%dT%H:%M:%S'), description=detail.UpdateDescription, location=detail.UpdateLocation, code=detail.UpdateCode, time=DF.ftime(detail.UpdateDateTime, '%Y-%m-%dT%H:%M:%S'), ) ], )
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: 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: 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_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_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(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(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_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_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 parse_pickup_response(response: Element, settings: Settings) -> Tuple[PickupDetails, List[Message]]: pickup_node = next(iter(response.xpath(".//*[local-name() = $name]", name="pickup")), None) pickup = XP.build(PickupV2, pickup_node) details: PickupDetails = PickupDetails( carrier_id=settings.carrier_id, carrier_name=settings.carrier_name, confirmation_number=str(pickup.id), pickup_date=DF.fdatetime(pickup.pickup_date, '%Y-%m-%dT%H:%M:%S') ) return details, parse_error_response(response, settings)