コード例 #1
0
    def find_rate(service_type: str, zone: int, package: Package) -> float:
        """
        After obtaining the zone, it finds the rate it needs and calculates the prices of the shipment
        even if it haves an exceeded weight it calculates it.
        :param service_type: str of service type to calculate
        :param zone: int of the calculated zone
        :param package: Package detail
        :return: float of shipment price
        """
        exceeded_price = 0
        if package.weight % 1 > 0:
            package_weight = int(
                package.weight
            ) + 1  # if it has more than an int weight it must add 1
        else:
            package_weight = int(package.weight)
        # finds the exceeded weight and rate, with that it calculates the exceeded price
        if TYPE_KG_LIMIT[service_type] < package_weight:
            exceeded_weight = package_weight - TYPE_KG_LIMIT[service_type]
            package_weight = TYPE_KG_LIMIT[service_type]
            exceeded_query = {
                'type': service_type,
                'rates_by_zone.zone': zone,
                'rates_by_zone.kg': '+'
            }
            exceeded_project = {
                '_id': 0,
                'rates_by_zone': {
                    '$elemMatch': {
                        'zone': zone,
                        'kg': '+'
                    }
                },
                'rates_by_zone.rate': 1
            }
            exceeded_rate = Database.find(
                ZONE_TO_RATE, exceeded_query,
                exceeded_project).next()['rates_by_zone'][0]['rate']
            exceeded_price = exceeded_rate * exceeded_weight

        query = {
            'type': service_type,
            'rates_by_zone.zone': zone,
            'rates_by_zone.kg': package_weight
        }
        project = {
            '_id': 0,
            'rates_by_zone': {
                '$elemMatch': {
                    'zone': zone,
                    'kg': package_weight
                }
            },
            'rates_by_zone.rate': 1
        }
        rate = Database.find(ZONE_TO_RATE, query,
                             project).next()['rates_by_zone'][0]['rate']
        return rate + exceeded_price
コード例 #2
0
    def find_rate(cls, service_type: str, package: Package) -> dict:
        if package.weight % 1 > 0:
            package_weight = int(
                package.weight
            ) + 1  # if it has more than an int weight it must add 1
        else:
            package_weight = int(package.weight)
        if package_weight >= TYPE_KG_LIMIT and service_type == SPECIAL_TYPE:
            service_type = "5522411"
        if (package.origin_zipcode in DF_ZIP_CODES and package.destiny_zipcode in DF_ZIP_CODES) and service_type != \
                TYPES_STR_TO_ID['ESTAFETA_DIA_SIGUIENTE']:
            service_type = "8608731"
        if service_type == SPECIAL_TYPE:
            price, descriptions = cls.Graph.dijkstra(0, package_weight)
            result_descriptions = dict()
            for description in descriptions:
                if result_descriptions.get(description) is None:
                    result_descriptions[description] = 1
                    if "TERRESTRE" in description:
                        rate_data = list(
                            Database.find("Estafeta_rates",
                                          {"type": description}))[0]
                        result_descriptions["cuenta"] = rate_data['_id']
                        result_descriptions['covered_kg'] = rate_data['kg']
                        result_descriptions['extra_kg_rate'] = rate_data[
                            'adicional']
                        # TODO Delete THIS when needed
                        if result_descriptions["cuenta"] in ['8646027']:
                            result_descriptions["cuenta"] = '8622603'
                else:
                    result_descriptions[description] += 1

            return {"price": price, "options": result_descriptions}
        rate = Database.find("Estafeta_rates", {"_id": service_type}).next()
        exceeded_price = 0
        exceeded_weight = 0
        if package_weight > rate['kg']:
            exceeded_weight = package_weight - rate['kg']
            exceeded_price = rate['adicional'] * exceeded_weight

        final_rate = rate['total'] + exceeded_price

        # TODO Delete THIS when needed
        if service_type in ['8646027']:
            service_type = '8622603'
        options = {
            rate['type']: 1,
            'adicional': exceeded_weight,
            "cuenta": service_type,
            'extra_kg_rate': rate['adicional'],
            'covered_kg': rate['kg']
        }
        return {'price': final_rate, "options": options}
コード例 #3
0
    def is_available(package: Package) -> (dict, dict):
        try:
            area_from = Database.find(AREAS_COLLECTION, {
                'zip_codes': package.origin_zipcode
            }).next()
            area_to = Database.find(AREAS_COLLECTION, {
                'zip_codes': package.destiny_zipcode
            }).next()
        except StopIteration:
            raise ZipCodesNotFound("No Hay Disponibilidad")

        return area_from, area_to
コード例 #4
0
 def discard_types(self, package):
     option_types = list(
         Database.find("STF_ZP", {"zip_code": package.destiny_zipcode}))
     terrain_flag = False
     for opt in option_types:
         if opt['service_type'] == 'TERRESTRE':
             terrain_flag = True
             break
     if not option_types or not terrain_flag:
         option_types += [{
             'zip_code': package.destiny_zipcode,
             'periodicity': 'SEMANAL',
             'extra': 1,
             'service_type': 'TERRESTRE',
             'availability': [1, 1, 1, 1, 1, 0, 0]
         }]
     result = list()
     if isinstance(self.type, list):
         for type in self.type:
             for opt_type in option_types:
                 if TYPES_ID_TOSERVICE_TYPE.get(
                         opt_type['service_type']) == type:
                     result.append(type)
                     continue
     if result:
         self.type = result
コード例 #5
0
def create_graph() -> GraphUndirectedWeighted:
    rates = list(
        Database.find("Estafeta_rates", {
            "description": "TERRESTRE",
            "type": {
                "$ne": "METROPOLITANO"
            }
        }, {"_id": 0}))
    rates = {rate.pop('type'): dict(**rate) for rate in rates}
    graph = GraphUndirectedWeighted(22)
    for i in range(1, 21):
        if i <= rates['TERRESTRE_2']['kg']:
            description = 'TERRESTRE_2'
            rate = rates[description]['total']
        elif rates['TERRESTRE_2']['kg'] < i <= rates['TERRESTRE_5']['kg']:
            description = 'TERRESTRE_5'
            rate = rates[description]['total']
        elif rates['TERRESTRE_5']['kg'] < i <= rates['TERRESTRE_10']['kg']:
            description = 'TERRESTRE_10'
            rate = rates[description]['total']
        else:
            description = 'TERRESTRE_20'
            rate = rates[description]['total']
        graph.add_edge(0, i, rate, description)
        if i == 1:
            continue
        graph.add_edge(i, i + 1, rates['TERRESTRE_2']['adicional'],
                       "adicional")

    return graph
コード例 #6
0
    def find_area(package: Package) -> (int, int):
        """
        Given the package it determines the area of the destiny zipcode and the origin zipcode
        :param package: Package
        :return: tuple of areas
        """
        try:
            area_from = Database.find(AREAS_COLLECTION, {
                'zip_codes': package.origin_zipcode
            }).next()['Area']
            area_to = Database.find(AREAS_COLLECTION, {
                'zip_codes': package.destiny_zipcode
            }).next()['Area']
        except StopIteration:
            raise ZipCodesNotFound("No Hay Disponibilidad")

        return area_from, area_to
コード例 #7
0
 def find_zone(area_from: int, area_to: int) -> int:
     """
     given the areas from which they are sending and receiving it gets the zone to which the rate will be
     calculates
     :param area_from:
     :param area_to:
     :return:
     """
     zone = Database.find(AREA_TO_ZONE_COLLECTION, {
         'x': area_from,
         'y': area_to
     }).next()
     return zone['value']
コード例 #8
0
 def find_delivery_data(package: Package) -> dict:
     try:
         return Database.find("STF_ZP", {
             "zip_code": package.destiny_zipcode
         }).next()
     except StopIteration:
         not_found_dict = {
             'zip_code': package.destiny_zipcode,
             'periodicity': 'SEMANAL',
             'extra': 1,
             'service_type': 'TERRESTRE',
             'availability': [1, 1, 1, 1, 1, 0, 0]
         }
         return not_found_dict
コード例 #9
0
    def _get_extra_fees(self, package: Package) -> float:
        ext_zone = list(
            Database.find('DHL_EXT', {"_id": package.destiny_zipcode}))
        extra_fees = 0
        if ext_zone:
            extra_fees += 133.67

        if package.weight > 70.0:
            extra_fees += 244.90

        if package.width > 120 or package.length > 120 or package.height > 120:
            extra_fees += 244.90

        return extra_fees