def create_envelope( body_content: Element, header_content: Element = None, header_prefix: str = None, body_prefix: str = None, header_tag_name: str = None, body_tag_name: str = None, envelope_prefix: str = "tns", ) -> Envelope: header = None if header_content is not None: header_content.ns_prefix_ = header_prefix or header_content.ns_prefix_ header_content.original_tagname_ = (header_tag_name or header_content.original_tagname_) header = Header() header.add_anytypeobjs_(header_content) body_content.ns_prefix_ = body_prefix or body_content.ns_prefix_ body_content.original_tagname_ = body_tag_name or body_content.original_tagname_ body = Body() body.add_anytypeobjs_(body_content) envelope = Envelope(Header=header, Body=body) envelope.ns_prefix_ = envelope_prefix envelope.Body.ns_prefix_ = envelope.ns_prefix_ if envelope.Header is not None: envelope.Header.ns_prefix_ = envelope.ns_prefix_ return envelope
def export(xml_element: Element, **kwds) -> str: """Return a XML string. invoke the export method of generated type to return the subsequent XML represented """ output = io.StringIO() xml_element.export(output, 0, **kwds) return output.getvalue()
def parse_error_response(response: Element, settings: Settings) -> List[Message]: notifications = ( response.xpath(".//*[local-name() = $name]", name="Notifications") + response.xpath(".//*[local-name() = $name]", name="Notification") ) return reduce( _extract_error(settings), notifications, extract_fault(response, settings) )
def parse_shipment_response( response: Element, settings: Settings ) -> Tuple[ShipmentDetails, List[Message]]: details = next( iter(response.xpath(".//*[local-name() = $name]", name="ShipmentResults")), None ) shipment = _extract_shipment(details, settings) if details is not None else None return shipment, parse_error_response(response, settings)
def parse_freight_ship_response( response: Element, settings: Settings) -> Tuple[ShipmentDetails, List[Message]]: details = response.xpath(".//*[local-name() = $name]", name="FreightShipResponse") shipment = _extract_shipment(details[0], settings) if len(details) > 0 else None return shipment, parse_error_response(response, settings)
def extract_fault(response: Element, settings: Type[Settings]) -> Message: faults = [build(Fault, node) for node in response.xpath(".//*[local-name() = $name]", name="Fault")] return [ Message( code=fault.faultcode, message=fault.faultstring, carrier_name=settings.carrier_name, carrier_id=settings.carrier_id ) for fault in faults ]
def parse_freight_rate_response( response: Element, settings: Settings) -> Tuple[List[RateDetails], List[Message]]: rate_reply = response.xpath(".//*[local-name() = $name]", name="FreightRateResponse") rates: List[RateDetails] = [ _extract_freight_rate(detail_node, settings) for detail_node in rate_reply ] return rates, parse_error_response(response, settings)
def parse_shipment_response( response: Element, settings: Settings ) -> Tuple[ShipmentDetails, List[Message]]: air_way_bill = next( iter(response.xpath(".//*[local-name() = $name]", name="AirwayBillNumber")), None, ) return ( _extract_shipment(response, settings) if air_way_bill is not None else None, parse_error_response(response, settings), )
def parse_rate_response( response: Element, settings: Settings) -> Tuple[List[RateDetails], List[Message]]: rate_reply = response.xpath(".//*[local-name() = $name]", name="RateReplyDetails") rate_details: List[RateDetails] = [ _extract_rate(detail_node, settings) for detail_node in rate_reply ] return ( [details for details in rate_details if details is not None], parse_error_response(response, settings), )
def extract_fault(response: Element, settings: Settings) -> List[Message]: faults = [ XMLPARSER.build(Fault, node) for node in response.xpath(".//*[local-name() = $name]", name="Fault") ] return [ Message( code=fault.faultcode, message=fault.faultstring, carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, ) for fault in faults ]
def parse_error_response(response: Element, settings: Settings) -> List[Message]: error_nodes: List[Error] = [ (lambda error: (error, error.build(node)))(Error())[0] for node in ( [response] if response.tag == "Error" else response.xpath(".//*[local-name() = $name]", name="Error") ) ] return [ Message( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, code=str(error.Number), message=error.Description, ) for error in error_nodes ]
def _extract_freight_rate(detail_node: Element, settings: Settings) -> RateDetails: detail = FreightRateResponse() detail.build(detail_node) total_charge = [r for r in detail.Rate if r.Type.Code == "AFTR_DSCNT"][0] Discounts_ = [ ChargeDetails( name=r.Type.Code, currency=r.Factor.UnitOfMeasurement.Code, amount=decimal(r.Factor.Value), ) for r in detail.Rate if r.Type.Code == "DSCNT" ] Surcharges_ = [ ChargeDetails( name=r.Type.Code, currency=r.Factor.UnitOfMeasurement.Code, amount=decimal(r.Factor.Value), ) for r in detail.Rate if r.Type.Code not in ["DSCNT", "AFTR_DSCNT", "DSCNT_RATE", "LND_GROSS"] ] extra_charges = Discounts_ + Surcharges_ currency_ = next(c.text for c in detail_node.xpath(".//*[local-name() = $name]", name="CurrencyCode")) return RateDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, currency=currency_, service=detail.Service.Description, base_charge=decimal(detail.TotalShipmentCharge.MonetaryValue), total_charge=decimal(total_charge.Factor.Value or 0.0), duties_and_taxes=decimal( reduce(lambda r, c: r + c.amount, Surcharges_, 0.0)), discount=decimal(reduce(lambda r, c: r + c.amount, Discounts_, 0.0)), extra_charges=extra_charges, )
def extract(rates: List[RateDetails], detail_node: Element) -> List[RateDetails]: rate = RatedShipmentType() rate.build(detail_node) if rate.NegotiatedRateCharges is not None: total_charges = ( rate.NegotiatedRateCharges.TotalChargesWithTaxes or rate.NegotiatedRateCharges.TotalCharge ) taxes = rate.NegotiatedRateCharges.TaxCharges itemized_charges = rate.NegotiatedRateCharges.ItemizedCharges + taxes else: total_charges = rate.TotalChargesWithTaxes or rate.TotalCharges taxes = rate.TaxCharges itemized_charges = rate.ItemizedCharges + taxes extra_charges = itemized_charges + [rate.ServiceOptionsCharges] arrival = PickupType() [ arrival.build(arrival) for arrival in detail_node.xpath( ".//*[local-name() = $name]", name="Arrival" ) ] currency_ = next( c.text for c in detail_node.xpath( ".//*[local-name() = $name]", name="CurrencyCode" ) ) service = ShippingServiceCode(rate.Service.Code).name return rates + [ RateDetails( carrier_name=settings.carrier_name, carrier_id=settings.carrier_id, currency=currency_, service=service, base_charge=decimal(rate.TransportationCharges.MonetaryValue), total_charge=decimal(total_charges.MonetaryValue), duties_and_taxes=reduce( lambda total, charge: total + decimal(charge.MonetaryValue), taxes or [], 0.0, ), extra_charges=reduce( lambda total, charge: ( total + [ ChargeDetails( name=charge.Code, amount=decimal(charge.MonetaryValue), currency=charge.CurrencyCode, ) ] ), [charge for charge in extra_charges if charge is not None], [], ), estimated_delivery=format_date(arrival.Date), ) ]
def parse_error_response(response: Element, settings: Settings) -> List[Message]: notifications = response.xpath(".//*[local-name() = $name]", name="PrimaryErrorCode") return [_extract_error(node, settings) for node in notifications]
def parse_rate_response( response: Element, settings: Settings ) -> Tuple[List[RateDetails], List[Message]]: rate_reply = response.xpath(".//*[local-name() = $name]", name="RatedShipment") rates: List[RateDetails] = reduce(_extract_package_rate(settings), rate_reply, []) return rates, parse_error_response(response, settings)
def parse_error_response(response: Element, settings: Settings) -> List[Message]: errors = response.xpath(".//*[local-name() = $name]", name="Error") return [_extract_error(node, settings) for node in errors] + extract_fault(response, settings)
def parse_error_response(response: Element, settings: Settings) -> List[Message]: messages = response.xpath(".//*[local-name() = $name]", name="message") return reduce(_extract_error(settings), messages, [])