Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
lib-py-b2b / package.py
Size: Mime:
from .errors import InvalidPackageError


class PackageSize:
    def __init__(self, length, width, height):
        self.length = length
        self.width = width
        self.height = height

    def get_volume(self):
        return self.length * self.width * self.height

    def get_girth(self):
        return 2*self.height + 2*self.width

    def get_total_size(self):
        return self.length + self.get_girth()

    def validate(self, profile):
        if self.length == 0 or self.width == 0 or self.height == 0:
            raise InvalidPackageError(f"Items must have a dimension in order to be shipped.")
        vol = self.get_total_size()
        if not vol:
            raise InvalidPackageError(f"The package must have a total size greater than 0 to be shipped.")
        if vol > profile.fulfillment_config.max_package_size:
            if self.length < self.width or self.length < self.height:
                raise InvalidPackageError(
                    f"The package's length must be the longest dimension. The total "
                    f"size [{self.get_total_size()}] is over the {profile.fulfillment_config.max_package_size} "
                    f"inches allowed by the carrier.")
            else:
                raise InvalidPackageError(f"The package's total size [{self.get_total_size()}] is over"
                                          f" the {profile.fulfillment_config.max_package_size} inches "
                                          f"allowed by the carrier.")
        return

    def __str__(self):
        return f"l:{self.length}, w:{self.width}, h:{self.height}, v:{self.get_volume()}, ts: {self.get_total_size()}"


class PackageWeight:
    def __init__(self, amt, units):
        self.amt = amt
        self.units = units

    def __str__(self):
        return f"{self.amt} {self.units}"

    def validate(self, profile):
        if not self.amt:
            raise InvalidPackageError(f"The package must have a weight to be shipped.")
        if self.amt > profile.fulfillment_config.maximum_package_weight \
                or self.amt < profile.fulfillment_config.minimum_package_weight:
            raise InvalidPackageError(f"The weight [{str(self)}] is outside the range"
                                      f" of {profile.fulfillment_config.minimum_package_weight} lbs "
                                      f"< weight < {profile.fulfillment_config.maximum_package_weight} lbs "
                                      f"allowed by Fedex.")
        return


class Package:
    @staticmethod
    def create_from(profile, container):
        if profile.fulfillment_config.use_standard_weight:
            weight = PackageWeight(container.attributes.standard_weight, 'LB')
        else:
            if container.attributes.actual_weight:
                weight = PackageWeight(container.attributes.actual_weight, 'LB')
            else:
                weight = PackageWeight(container.attributes.standard_weight, 'LB')
        size = PackageSize(container.attributes.length, container.attributes.width, container.attributes.height)
        package = Package(weight, size, profile)
        return package

    def __init__(self, weight: PackageWeight, size: PackageSize, profile):
        self.weight = weight
        self.size = size
        self.profile = profile
        self.dimensional_weight = self.size.get_volume() / float(profile.fulfillment_config.dimensional_weight_divisor)
        self.billable_weight = self.weight.amt if self.weight.amt > self.dimensional_weight else self.dimensional_weight

    def get_service_type(self):
        return self.profile.fulfillment_config.get_service_type(weight=self.weight.amt)

    def validate(self):
        if not self.weight:
            raise InvalidPackageError("The weight is not defined.")
        else:
            self.weight.validate(self.profile)

        if not self.size:
            raise InvalidPackageError("The size is not defined.")
        else:
            self.size.validate(self.profile)

    def __str__(self):
        return f"PackageSize: [{self.size}], PackageWeight: [{self.weight}], " \
               f"DimensionalWeight: {self.dimensional_weight}, BillableWeight: {self.billable_weight}"