""" 美国尾端物流模块实现类""" import math import re import pandas from logisticsClass.logisticsBaseClass import LogisticsType, TailLogistics from data.us_zone import zone_west, zone_east from pathlib import Path """ port:west(default),east currency:str = 'USD' logistics_type:LogisticsType (快递,卡派) """ class WestLogistics_US(TailLogistics): _is_loaded = False parent_current_directory = Path(__file__).parent.parent remote_path = parent_current_directory.joinpath("data") _postcode_files = [ remote_path.joinpath("contiguous_us.txt"), remote_path.joinpath("contiguous_us_extended.txt"), remote_path.joinpath("contiguous_us_remote.txt") ] def __new__(cls): """实现单例模式,只加载一次文件""" if not cls._is_loaded: cls._load_postcodes() # 第一次实例化时加载文件 cls._is_loaded = True # 标记文件已加载 return super().__new__(cls) # Path_current_directory = Path(__file__).parent # current_directory = os.path.dirname(__file__) @classmethod def _load_postcodes(cls): """加载邮编文件""" cls.postcodes_by_file = { 1: set(), # 用于存储contiguous_us.txt的邮政编码 2: set(), # 用于存储contiguous_us_extended.txt的邮政编码 3: set() # 用于存储contiguous_us_remote.txt的邮政编码 } # 加载每个文件,并将邮政编码存入对应的集合中 for index, file in enumerate(cls._postcode_files, start=1): with open(file, "r", encoding="utf-8") as f: for line in f: cls.postcodes_by_file[index].add(line.strip()) def is_remote(self, postcode): """判断是否偏远 0非偏远,1偏远,2超偏远Extend,3超偏远Remote""" if not re.match(r'\d{5}-\d{4}|\d{5}', postcode): raise ValueError("邮编格式不合法") if not hasattr(self, 'postcodes_by_file'): raise ValueError("Postcodes are not loaded yet.") postcode = postcode[:5] postcode = str(postcode) for index, postcodes in self.postcodes_by_file.items(): for line in postcodes: postcodes_range = line.strip().split("\t") if postcode in postcodes_range: return index return 0 def get_west_zone(self, postcode): """获取美西邮编分区""" if not re.match(r'\d{5}-\d{4}|\d{5}', postcode): return "邮编格式不合法" postcode = postcode[:5] postcode = int(postcode) for zone, postcodes in zone_west.items(): start =int(postcodes[0].split("-")[0]) end = int(postcodes[-1].split("-")[-1]) if start > postcode or postcode > end: continue for postcode_range in postcodes: if "-" in postcode_range: start, end = map(int, postcode_range.split("-")) if start <= postcode <= end: return zone else: if int(zone) == postcode: return zone return "未查询到邮编分区" class FedexLogistics(WestLogistics_US): """Fedex""" country = "United States" country_code = "US" def __init__(self): super().__init__() self.volume_weight_ratio:int # lbs抛重系数 self.base_fee:dict self.residential:float self.residential_peak:float # 报价表没写,账单有 self.oversize_2:float self.oversize_3:float self.oversize_5:float self.oversize_7:float self.overweight_2:float self.overweight_3:float self.overweight_5:float self.overweight_7:float self.overhanding_2:float # 额外操作费 这个可能用不上。 self.overhanding_3:float self.overhanding_5:float self.overhanding_7:float self.ahs_peak:float # 额外处理费旺季附加费 self.residential_das:float # 偏远费 self.residential_extended:float # 超偏远费 self.residential_remote:float # 超超偏远费 self.bigpackage_2:float # 大包裹费 self.bigpackage_3:float self.bigpackage_5:float self.bigpackage_7:float self.bigpackage_peak:float # 大包裹旺季附加费 self.return_package:float # 超大包裹(不可发) self.fuel_rate = 0.16 # 燃油费率 def calculate_fee(self,packages,postcode): """计算运费,抛重计费,系数275""" detail_amount = { "base":0.00, "oversize":0.00, "remote":0.00, "big_package":0.00, "big_package_peak":0.00, "residential_delivery":0.00, "residential_peak":0.00, "fuel":0.00, "tail_amount":0.00 } # 先看分区 zone = self.get_west_zone(postcode) if zone == 2: ahs_oversize = self.oversize_2 ahs_overweight = self.overweight_2 ahs_overhanding = self.overhanding_2 big_oversize = self.bigpackage_2 elif zone == 3 or zone == 4: ahs_oversize = self.oversize_3 ahs_overweight = self.overweight_3 ahs_overhanding = self.overhanding_3 big_oversize = self.bigpackage_3 elif zone == 5 or zone == 6: ahs_oversize = self.oversize_5 ahs_overweight = self.overweight_5 ahs_overhanding = self.overhanding_5 big_oversize = self.bigpackage_5 elif zone == 7 or zone == 8: ahs_oversize = self.oversize_7 ahs_overweight = self.overweight_7 ahs_overhanding = self.overhanding_7 big_oversize = self.bigpackage_7 else: detail_amount['tail_amount'] = 99999 return detail_amount # 再看是否偏远 0非偏远,1偏远,2超偏远Extend,3超偏远Remote is_remote = self.is_remote(postcode) if is_remote == 1: remote_fee = self.residential_das elif is_remote ==2: remote_fee = self.residential_extended elif is_remote ==3: remote_fee = self.residential_remote else: remote_fee = 0 for package in packages: if package.lbs_weight>150 or package.fst_inch>108 or package.girth_inch >165: detail_amount['tail_amount'] = self.return_package return detail_amount cal_weight = max(package.lbs_weight,package.volume_inch / self.volume_weight_ratio) ahs_fee = 0 # AHS费系列,多种存在只取最高 if package.fst_inch > 48 or package.sed_inch> 30 or package.girth_inch>105: ahs_fee = ahs_oversize +self.ahs_peak cal_weight = max(cal_weight,40) if package.lbs_weight > 50: ahs_fee = max(ahs_fee,ahs_overweight +self.ahs_peak) if package.girth_inch >130 or package.fst_inch >96: cal_weight = max(cal_weight,90) if cal_weight > 150: detail_amount['tail_amount'] = self.return_package return detail_amount detail_amount['oversize'] += 0 if package.girth_inch >130 or package.fst_inch >96 else ahs_fee detail_amount['remote'] += remote_fee detail_amount['big_package'] += big_oversize if package.girth_inch >130 or package.fst_inch >96 else 0 detail_amount['big_package_peak'] += self.bigpackage_peak if package.girth_inch >130 or package.fst_inch >96 else 0 detail_amount['residential_delivery'] += self.residential detail_amount['residential_peak'] += self.residential_peak detail_amount['base'] +=self.base_price[self.base_price['lbs.']==math.ceil(cal_weight)][zone].values[0] for key in detail_amount: if key!= 'tail_amount' and key!= 'fuel': detail_amount['tail_amount'] += detail_amount[key] detail_amount['fuel'] += detail_amount[key] * self.fuel_rate detail_amount['tail_amount'] += detail_amount['fuel'] return detail_amount class FedexPPLogistics_US(FedexLogistics): company="Fedex-彩虹小马" parent_current_directory = Path(__file__).parent.parent price_path = parent_current_directory.joinpath("data") _price_files = price_path.joinpath("美国快递.xlsx") base_price = None def __new__(cls): if cls.base_price is None: cls.base_price = pandas.read_excel(cls._price_files,sheet_name='邮差小马') return super().__new__(cls) def __init__(self): super().__init__() self.volume_weight_ratio=250 # lbs抛重系数 self.residential = 6.38 self.residential_peak = 0 # 0.33 0.6 # 报价表没写,账单有 self.oversize_2 = 4.50 self.oversize_3 = 4.99 self.oversize_5 = 5.47 self.oversize_7 = 6.11 self.overweight_2 =6.99 self.overweight_3 = 7.64 self.overweight_5 =8.12 self.overweight_7 = 8.84 self.overhanding_2 = 4.02 # 额外操作费 self.overhanding_3 = 4.66 self.overhanding_5 = 4.91 self.overhanding_7 = 5.07 self.ahs_peak = 0 # 4.16 5.36 # 操作费旺季附加费 self.residential_das = 1.58# 偏远费 self.residential_extended = 1.97 # 超偏远费 self.residential_remote = 5.82 # 超超偏远费 self.bigpackage_2 = 32.94 # 大包裹费 self.bigpackage_3 = 36.16 self.bigpackage_5 = 38.57 self.bigpackage_7 = 41.78 self.bigpackage_peak = 0 # 45.26 53.56# 大包裹旺季附加费 self.fuel_rate = 0.16 # 燃油费率 self.return_package = 1419.34 # 超大包裹(不可发) class FedexKHLogistics_US(FedexLogistics): """金宏亚""" company = "Fedex-金宏亚" parent_current_directory = Path(__file__).parent.parent price_path = parent_current_directory.joinpath("data") _price_files = price_path.joinpath("美国快递.xlsx") base_price = None def __new__(cls): if cls.base_price is None: cls.base_price = pandas.read_excel(cls._price_files,sheet_name='金宏亚') return super().__new__(cls) def __init__(self): super().__init__() self.volume_weight_ratio = 250 # lbs抛重系数 self.residential = 2.1 self.residential_peak =0 # 0.57 0.31 # 报价表没写,账单有 self.oversize_2 = 2.3 self.oversize_3 = 2.6 self.oversize_5 = 2.9 self.oversize_7 = 3.2 self.overweight_2 =3.6 self.overweight_3 = 3.9 self.overweight_5 =4.2 self.overweight_7 =4.6 self.overhanding_2 = 3.1 # 额外操作费 self.overhanding_3 = 3.6 self.overhanding_5 = 3.8 self.overhanding_7 = 3.9 self.ahs_peak = 0 #1.3 # 操作费旺季附加费 self.residential_das = 2.26 # 偏远费 self.residential_extended = 3.02 # 超偏远费 self.residential_remote = 5.64# 超超偏远费 self.bigpackage_2 = 120 # 大包裹费 self.bigpackage_3 = 130 self.bigpackage_5 = 145 self.bigpackage_7 = 152.5 self.bigpackage_peak =43.94 # 42.25# 大包裹旺季附加费 self.return_package = 1325 # 超大包裹(不可发) self.fuel_rate = 0.16 # 燃油费率 class FedexHOMELogistics_US(FedexLogistics): """FEDEX-HOME (1-35%-30%)""" company = "Fedex-HOME" parent_current_directory = Path(__file__).parent.parent price_path = parent_current_directory.joinpath("data") _price_files = price_path.joinpath("美国快递.xlsx") base_price = None def __new__(cls): if cls.base_price is None: cls.base_price = pandas.read_excel(cls._price_files,sheet_name='FEDEX') return super().__new__(cls) def __init__(self): super().__init__() self.volume_weight_ratio = 250 # lbs抛重系数 self.residential = 2.08 self.residential_peak =0 # 0.57 0.31 # 报价表没写,账单有 self.oversize_2 = 6.02 self.oversize_3 = 6.67 self.oversize_5 = 7.31 self.oversize_7 = 8.17 self.overweight_2 =9.35 self.overweight_3 = 10.21 self.overweight_5 =10.86 self.overweight_7 = 11.83 self.overhanding_2 = 5.375# 额外操作费 self.overhanding_3 = 6.235 self.overhanding_5 = 6.5575 self.overhanding_7 = 6.7725 self.ahs_peak = 0 #1.3 # 操作费旺季附加费 self.residential_das = 2.17 # 偏远费 self.residential_extended = 2.91 # 超偏远费 self.residential_remote = 5.43# 超超偏远费 self.bigpackage_2 = 45.58 # 大包裹费 self.bigpackage_3 = 49.28 self.bigpackage_5 = 55.04 self.bigpackage_7 = 57.405 self.bigpackage_peak =0 # 42.25# 大包裹旺季附加费 self.return_package = 1325 # 超大包裹(不可发) self.fuel_rate = 0.18 # 燃油费率 class FedexGROUDLogistics_US(FedexLogistics): """FEDEX-GROUD (1-35%-30%)""" company = "Fedex-GROUD" parent_current_directory = Path(__file__).parent.parent price_path = parent_current_directory.joinpath("data") _price_files = price_path.joinpath("美国快递.xlsx") base_price = None def __new__(cls): if cls.base_price is None: cls.base_price = pandas.read_excel(cls._price_files,sheet_name='FEDEX') return super().__new__(cls) def __init__(self): super().__init__() self.volume_weight_ratio = 250 # lbs抛重系数 self.residential = 5.95 self.residential_peak =0 # 0.57 0.31 # 报价表没写,账单有 self.oversize_2 = 6.02 self.oversize_3 = 6.67 self.oversize_5 = 7.31 self.oversize_7 = 8.17 self.overweight_2 =9.35 self.overweight_3 = 10.21 self.overweight_5 =10.86 self.overweight_7 = 11.83 self.overhanding_2 = 5.375# 额外操作费 self.overhanding_3 = 6.235 self.overhanding_5 = 6.5575 self.overhanding_7 = 6.7725 self.ahs_peak = 0 #1.3 # 操作费旺季附加费 self.residential_das = 6.2 # 偏远费 self.residential_extended = 8.3 # 超偏远费 self.residential_remote = 15.5# 超超偏远费 self.bigpackage_2 = 38.06 # 大包裹费 self.bigpackage_3 = 41.76 self.bigpackage_5 = 44.29 self.bigpackage_7 = 47.73 self.bigpackage_peak =0 # 42.25# 大包裹旺季附加费 self.return_package = 1325 # 超大包裹(不可发) self.fuel_rate = 0.18 # 燃油费率 class GIGALogistics_US(TailLogistics): """卡派:GIGA,美东美西不变""" country = "United States" country_code = "US" company = "大健-GIGA" logistics_type = LogisticsType.COURIER parent_current_directory = Path(__file__).parent.parent data_path = parent_current_directory.joinpath("data") _price_files = data_path.joinpath("GIGA base_fee_20240607223514.xlsx") price_df = None def __new__(cls): """实现单例模式,只加载一次文件""" if cls.price_df is None: cls.price_df = pandas.read_excel(cls._price_files) return super().__new__(cls) def __init__(self): super().__init__() self.base_fee:float self.warehouse_fee:float self.discount = 0.88 def calculate_fee(self,packages,postcode): """计算运费,基础费用只跟邮编有关""" detail_amount = { "base":0.00, "warehouse_fee":0.00, "discount":0.00, "tail_amount":0.00 } if not re.match(r'\d{5}-\d{4}|\d{5}', postcode): detail_amount['tail_amount'] = 99999 return detail_amount postcode = int(postcode[:5]) base_result = self.price_df[self.price_df['Zip Code']==postcode]['Delivery Fee Rate'] if base_result.empty: detail_amount['tail_amount'] =99999 return detail_amount self.base_fee = base_result.iloc[0] self.warehouse_fee = self.price_df[self.price_df['Zip Code']==postcode]['Warehouse Handling Fee'].iloc[0] detail_amount['base'] = self.base_fee *self.discount detail_amount['warehouse_fee'] = self.warehouse_fee * self.discount detail_amount['discount'] = self.discount detail_amount['tail_amount'] = detail_amount['base'] + detail_amount['warehouse_fee'] return detail_amount class CEVALogistics_US(TailLogistics): """卡派:CEVA""" country = "United States" country_code = "US" company = "大健-CEVA" logistics_type = LogisticsType.COURIER parent_current_directory = Path(__file__).parent.parent data_path = parent_current_directory.joinpath("data") _price_files = data_path.joinpath("CEVA.xlsx") zone_df = None price_df = None grade_df = None def __new__(cls): """实现单例模式,只加载一次文件""" if cls.price_df is None or cls.zone_df is None: cls.price_df = pandas.read_excel(cls._price_files,sheet_name="ceva_base_rate") cls.zone_df = pandas.read_excel(cls._price_files,sheet_name="remote_zone") cls.grade_df = pandas.read_excel(cls._price_files,sheet_name="ceva_zone") return super().__new__(cls) def __init__(self): super().__init__() self.surcharge_CA = 18.24 # 出发地和目的地有一个是CA 都会收 self.metro_NY = 37.99 # 出发邮编和目的邮编前三位在100-104,110-114会收 self.big_package = 30 # 单件包裹重>=250lbs,长>=75in self.oversize = [0,131.04,303,532] # 96,120,240,240以上 def calculate_fee(self,packages,postcode): """ 计算运费,in,lbs,250 from邮编固定, to邮编先根据remote_df获取State和remote_type, 再根据zone_df分组, 最后从price_df取对应价格 只有big_package和oversize是以单包裹为单位,其他费用混合计算 """ detail_amount = { "base":0.00, "remote":0.00, "surcharge_CA":0.00, "metro_NY":0.00, "oversize":0.00, "big_package":0.00, "tail_amount":0.00 } if not re.match(r'\d{5}-\d{4}|\d{5}', postcode): detail_amount['tail_amount'] = 99999 return detail_amount postcode = int(postcode[:5]) # 获取分区和偏远 result = self.zone_df[self.zone_df['PostalCode'] == postcode] if result.empty: detail_amount['tail_amount']=99999 return detail_amount zone = result['State'].iloc[0] remote = result['remote_type'].iloc[0] # standard 和remote # 假设美西出发,CA是美西,NJ是美东 zone_west = self.grade_df[self.grade_df['To'] ==zone]['CA'].iloc[0] # 最后查看价格表,磅重-grade total_weight = 0 for package in packages: billing_weight = max(package.lbs_weight,package.volume_inch/250) total_weight +=billing_weight if package.lbs_weight >=250 or package.fst_inch >=75: detail_amount["big_package"] +=self.big_package if 96<=package.fst_inch <120: detail_amount["oversize"] +=self.oversize[1] elif 120<=package.fst_inch <240: detail_amount["oversize"] +=self.oversize[2] elif package.fst_inch >=240: detail_amount["oversize"] +=self.oversize[3] billed_weight = round(min(max(101,total_weight),1000),0) extrat = 0 price_result = self.price_df[self.price_df['CEVA']==billed_weight] if total_weight >1000: per_result = self.price_df[self.price_df['CEVA']=="1000+"][zone_west].iloc[0] extrat = per_result * (total_weight -1000) detail_amount["base"] = price_result[zone_west].iloc[0] + extrat detail_amount['remote'] = price_result['Remote area surcharge'].iloc[0] if remote == 'remote' else 0 detail_amount["surcharge_CA"] = self.surcharge_CA detail_amount["metro_NY"] = self.metro_NY if 100<=postcode//100<=104 or 110<=postcode//100<=114 else 0 for key in detail_amount: if key!= 'tail_amount': detail_amount['tail_amount'] += detail_amount[key] return detail_amount class MetroLogistics_US(TailLogistics): """卡派:Metro""" country = "United States" country_code = "US" company = "Metro-SAIR" logistics_type = LogisticsType.COURIER parent_current_directory = Path(__file__).parent.parent data_path = parent_current_directory.joinpath("data") _price_files = data_path.joinpath("Metro.xlsx") cuft_25 = None cuft_35 = None over_35_per_cuft = None over_35_min = None zone_table = None remote_table = None @staticmethod def refresh(): """清空已加载的数据,以便下次重新加载""" MetroLogistics_US.cuft_25 = None MetroLogistics_US.cuft_35 = None MetroLogistics_US.over_35_per_cuft = None MetroLogistics_US.over_35_min = None MetroLogistics_US.zone_table = None MetroLogistics_US.remote_table = None def __new__(cls): """实现单例模式,只加载一次文件""" if cls.cuft_25 is None or cls.cuft_35 is None: cls.cuft_25 = pandas.read_excel(cls._price_files,sheet_name="cuft_25") cls.cuft_35 = pandas.read_excel(cls._price_files,sheet_name="cuft_35") cls.over_35_per_cuft = pandas.read_excel(cls._price_files,sheet_name="over35_per_cuft") cls.over_35_min = pandas.read_excel(cls._price_files,sheet_name="over35_min") cls.zone_table = pandas.read_excel(cls._price_files,sheet_name="zone_table") cls.remote_table = pandas.read_excel(cls._price_files,sheet_name="remote_table") return super().__new__(cls) def __init__(self): super().__init__() self.fuel_rate = 0.4 # 基础费用必*1.4,附加费不用 self.discount = 0.88 # 折扣,所有费用都吃 def calculate_fee(self,packages,postcode): """ 计算运费,in,lbs,250 from邮编固定, to邮编先根据remote_df获取State和remote_type, 再根据zone_df分组, 最后从price_df取对应价格 只有big_package和oversize是以单包裹为单位,其他费用混合计算 """ detail_amount = { "base":0.00, "oversize":0.00, "remote":0.00, "tail_amount":0.00 } if not re.match(r'\d{5}-\d{4}|\d{5}', postcode): detail_amount['tail_amount'] = 99999 return detail_amount postcode = int(postcode[:5]) # 出发地分区为 Zone 2 L # 取目的地分区 zone_result = self.zone_table[self.zone_table['Zip Code'] ==postcode]['New Zone Name'] if zone_result.empty: detail_amount["tail_amount"] = 99999 return detail_amount zone = zone_result.iloc[0] total_cuft = 0 max_weight = 0 max_length = 0 for package in packages: total_cuft += round(package.volume_inch/1728,2) # cm则为长*宽*高/28316.846592,单位是立方英尺 max_weight = max(max_weight,package.lbs_weight) max_length = max(max_length,package.fst_inch) # base费用 25立方英尺 ,美西是Zone 2 L 美东是Zone 17 L if total_cuft < 25: detail_amount["base"] = self.cuft_25[self.cuft_25['Origins']==zone]["Zone 2 L"].iloc[0] elif 25<=total_cuft <35: detail_amount["base"] = self.cuft_35[self.cuft_35['Origins']==zone]["Zone 2 L"].iloc[0] else: per_cuft = self.over_35_per_cuft[self.over_35_per_cuft['Origins']==zone]["Zone 2 L"].iloc[0] base_min = self.over_35_min[self.over_35_min['Origins']==zone]["Zone 2 L"].iloc[0] detail_amount["base"] = max(per_cuft*total_cuft,base_min) # 超尺寸,包括超重或超长 if max_weight >400 or max_length>125: # 不可派 detail_amount['tail_amount'] = 99999 return detail_amount if 300500 or package.fst_inch >144 or package.girth_inch >225: detail_amount['tail_amount'] = 99999 return detail_amount if package.lbs_weight <=90 and package.fst_inch <=96 and package.girth_inch <=130: base_fee_list.add(20) elif package.lbs_weight <=150 and package.fst_inch <=96 and package.girth_inch <=130: base_fee_list.add(38) elif package.lbs_weight <=150 and package.fst_inch <=108 and package.girth_inch <=165: base_fee_list.add(50) elif package.lbs_weight <=200 and package.fst_inch <=144 and package.girth_inch <=225: base_fee_list.add(75) else: base_fee_list.add(75+0.55*math.ceil(package.lbs_weight)) # 取所有费用,最大的费用取全部费用,其他取半价然后求和 base_fee_list = sorted(base_fee_list,reverse=True) # 计算base_fee_list最大值+其他费用的一半 if len(base_fee_list) == 0: return detail_amount elif len(base_fee_list) == 1: detail_amount["base"] = base_fee_list[0] else: detail_amount["base"] = base_fee_list[0] + sum(base_fee_list[1:])/2 # 判断邮编是美东还是美西 zone = self.postcode_table[self.postcode_table['POSTCODE'] == postcode]['地区'] if zone.empty: detail_amount['tail_amount'] = 99999 return detail_amount zone = zone.iloc[0] if zone =="NJ": detail_amount["transfer"] = 0.5*volume_weight for key in detail_amount: if key!= 'tail_amount': detail_amount['tail_amount'] += detail_amount[key] return detail_amount class AMWestLogistics_US(TailLogistics): """卡派:AM, 美西派送, """ country = "United States" country_code = "US" company = "AM-美西" logistics_type = LogisticsType.COURIER parent_current_directory = Path(__file__).parent.parent data_path = parent_current_directory.joinpath("data") _price_files = data_path.joinpath("美国卡派-AM.xlsx") postcode_table = None price_df = None def __new__(cls): """实现单例模式,只加载一次文件""" if cls.postcode_table is None or cls.price_df is None: cls.price_df = pandas.read_excel(cls._price_files,sheet_name="price") cls.postcode_table = pandas.read_excel(cls._price_files,sheet_name="postcode_table") return super().__new__(cls) def __init__(self): super().__init__() self.PUZone = "CA" # 派送起点 def calculate_fee(self,packages,postcode): """ 实重计费 lbs 重量<=1000lbs(453kg) 美西PUZone:CA, DLZone根据目的地邮编得 美东PUZone:NY, DLZone根据目的地邮编得 """ detail_amount = { "base":0.00, "surcharge":0.00, # 附加费用 "transfer":0.00, # 美西到美东的中转费 "tail_amount":0.00 } if not re.match(r'\d{5}-\d{4}|\d{5}', postcode): detail_amount['tail_amount'] = 99999 return detail_amount postcode = int(postcode[:5]) # postcode = str(postcode).zfill(5) # 先拿到目的地邮编对应的DLZone zone_match = self.postcode_table[self.postcode_table['Zip Code'] == postcode] if zone_match.empty: detail_amount['tail_amount'] = 99999 return detail_amount else: DLZone = zone_match['Zone'].iloc[0] volume_weight = 0 # 计算抛重,用于计算美西转运美东价格 total_lbs_weight = 0 # 计算总磅重 for package in packages: volume_weight +=package.get_volume_weight(6000) total_lbs_weight += package.lbs_weight if package.lbs_weight >1000: detail_amount['tail_amount'] = 99999 return detail_amount zone = self.PUZone+DLZone row = self.price_df[(self.price_df['Zone Combo']==zone) &(self.price_df['Minimum']<=total_lbs_weight) &(self.price_df['Maximum']>=total_lbs_weight)] if row.empty: detail_amount['tail_amount'] = 99999 return detail_amount detail_amount["base"] = row['w/o SC'].iloc[0] detail_amount["surcharge"] = row['Surcharge'].iloc[0] if detail_amount['base']==0: detail_amount['tail_amount'] = 99999 return detail_amount for key in detail_amount: if key!= 'tail_amount': detail_amount['tail_amount'] += detail_amount[key] return detail_amount class AMEastLogistics_US(TailLogistics): """卡派:AM, 美东派送, 美东在费用上额外+0.5*抛重6000的转运费 """ country = "United States" country_code = "US" company = "AM-美东" logistics_type = LogisticsType.COURIER parent_current_directory = Path(__file__).parent.parent data_path = parent_current_directory.joinpath("data") _price_files = data_path.joinpath("美国卡派-AM.xlsx") postcode_table = None price_df = None def __new__(cls): """实现单例模式,只加载一次文件""" if cls.postcode_table is None or cls.price_df is None: cls.price_df = pandas.read_excel(cls._price_files,sheet_name="price") cls.postcode_table = pandas.read_excel(cls._price_files,sheet_name="postcode_table") return super().__new__(cls) def __init__(self): super().__init__() self.PUZone = "NY" def calculate_fee(self,packages,postcode): """ 实重计费 lbs 重量<=1000lbs(453kg) 美西PUZone:CA, DLZone根据目的地邮编得 美东PUZone:NY, DLZone根据目的地邮编得 """ detail_amount = { "base":0.00, "surcharge":0.00, # 附加费用 "transfer":0.00, # 美西到美东的中转费 "tail_amount":0.00 } if not re.match(r'\d{5}-\d{4}|\d{5}', postcode): detail_amount['tail_amount'] = 99999 return detail_amount postcode = int(postcode[:5]) # postcode = str(postcode).zfill(5) # 先拿到目的地邮编对应的DLZone zone_match = self.postcode_table[self.postcode_table['Zip Code'] == postcode] if zone_match.empty: detail_amount['tail_amount'] = 99999 return detail_amount else: DLZone = zone_match['Zone'].iloc[0] volume_weight = 0 # 计算抛重,用于计算美西转运美东价格 total_lbs_weight = 0 # 计算总磅重 for package in packages: volume_weight +=package.get_volume_weight(6000) total_lbs_weight += package.lbs_weight if package.lbs_weight >1000: detail_amount['tail_amount'] = 99999 return detail_amount zone = self.PUZone+DLZone row = self.price_df[(self.price_df['Zone Combo']==zone) &(self.price_df['Minimum']<=total_lbs_weight) &(self.price_df['Maximum']>=total_lbs_weight)] if row.empty: detail_amount['tail_amount'] = 99999 return detail_amount detail_amount["base"] = row['w/o SC'].iloc[0] detail_amount["surcharge"] = row['Surcharge'].iloc[0] detail_amount["transfer"] = 0.5*volume_weight if detail_amount['base']==0: detail_amount['tail_amount'] = 99999 return detail_amount for key in detail_amount: if key!= 'tail_amount': detail_amount['tail_amount'] += detail_amount[key] return detail_amount if __name__ == '__main__': FedexPPLogistics_US.close_logistics() print(1)