diff --git a/logisticsClass/logisticsTail_EUR.py b/logisticsClass/logisticsTail_EUR.py index 1df8fec..726feae 100644 --- a/logisticsClass/logisticsTail_EUR.py +++ b/logisticsClass/logisticsTail_EUR.py @@ -40,9 +40,9 @@ class DPDASLLogistics(TailLogistics): detail_amount['tail_amount'] = 99999 return detail_amount for package in packages: # 逐个处理列表中的每个包裹 - # if package.weight > 31500 or package.girth > 350 or package.fst_size > 200: - # detail_amount['tail_amount'] = 99999 - # return detail_amount + if package.weight > 31500 or package.girth > 350 or package.fst_size > 200: + detail_amount['tail_amount'] = 99999 + return detail_amount detail_amount['base'] += self.base_fee detail_amount['remote'] +=self.remote_fee* isremote detail_amount['overweight'] += self.overweight if package.weight >= 20000 else 0 @@ -228,9 +228,9 @@ class DPDZGLogistics(TailLogistics): detail_amount['tail_amount'] = 99999 return detail_amount for package in packages: # 逐个处理列表中的每个包裹 - # if package.weight > 31500 or package.girth > 300 or package.fst_size >175: - # detail_amount['tail_amount'] = 99999 - # return detail_amount + if package.weight > 31500 or package.girth > 300 or package.fst_size >175: + detail_amount['tail_amount'] = 99999 + return detail_amount if package.weight <5000: detail_amount['base'] += self.base_fee[0] elif package.weight < 10000: @@ -251,7 +251,7 @@ class DPDZGLogistics_DE(DPDZGLogistics): country = 'Germany' def __init__(self): super().__init__() - self.base_fee = [7.72,8.83,11.67] + self.base_fee = [7.92,8.53,10.3] self.remote_fee=11.5 def is_remote(self,postcode): """判断是否偏远,1偏远0非偏远""" @@ -276,7 +276,7 @@ class DPDZGLogistics_FR(DPDZGLogistics): country = 'France' def __init__(self): super().__init__() - self.base_fee = [10.77,11.92,14.03] + self.base_fee = [11.27,11.72,13.73] self.remote_fee= 18.5 def is_remote(self,postcode): """判断是否偏远,1偏远0非偏远""" @@ -294,7 +294,7 @@ class DPDZGLogistics_SP(DPDZGLogistics): country = 'Spain' def __init__(self): super().__init__() - self.base_fee = [12.1,13.17,15.46] + self.base_fee = [12.8,13.37,15.16] self.remote_fee= 32 def is_remote(self,postcode): """判断是否偏远,1偏远0非偏远""" @@ -311,7 +311,7 @@ class DPDZGLogistics_IT(DPDZGLogistics): country = 'Italy' def __init__(self): super().__init__() - self.base_fee = [13.69,14.75,17.27] + self.base_fee = [14.19,14.95,16.97] self.remote_fee=19.5 def is_remote(self,postcode): """判断是否偏远,1偏远0非偏远""" @@ -337,7 +337,7 @@ class DPDZGLogistics_NL(DPDZGLogistics): country = 'Netherlands' def __init__(self): super().__init__() - self.base_fee = [8.88,9.83,11.62] + self.base_fee = [8.98,9.53,11.32] self.remote_fee=7.5 def is_remote(self,postcode): """判断是否偏远,1偏远0非偏远""" @@ -359,7 +359,7 @@ class DPDZGLogistics_PT(DPDZGLogistics): country = 'Portugal' def __init__(self): super().__init__() - self.base_fee = [8.11,9.27,10.98] + self.base_fee = [8.31,8.97,10.68] self.remote_fee=49 def is_remote(self,postcode): """判断是否偏远,1偏远0非偏远""" @@ -381,7 +381,7 @@ class DPDZGLogistics_BE(DPDZGLogistics): country = 'Belgium' def __init__(self): super().__init__() - self.base_fee = [8.62,9.72,11.51] + self.base_fee = [8.82,9.42,11.21] self.remote_fee=0 def is_remote(self,postcode): """判断是否偏远,1偏远0非偏远""" @@ -389,7 +389,20 @@ class DPDZGLogistics_BE(DPDZGLogistics): if not re.match(r'^\d{4}$', postcode): return "邮编格式不合法" return 0 - +# DPD-ZG 爱尔兰实现 +class DPDZGLogistics_IR(DPDZGLogistics): + country_code = 'IR' + country = 'Ireland' + def __init__(self): + super().__init__() + self.base_fee = [14.1,14.74,16.74] + self.remote_fee=0 + def is_remote(self,postcode): + """判断是否偏远,1偏远0非偏远""" + # 先判断邮编是否合法 + # if not re.match(r'^\d{4}$', postcode): + # return "邮编格式不合法" + return 0 # 卡派-ASL 欧洲各国基类 class KPASLLogistics(TailLogistics): @@ -510,12 +523,12 @@ class KPGELLogistics(TailLogistics): total_weight = 0 for package in packages: - # if (package.fst_size > 320 or package.sed_size>170 or package.trd_size>120) and (self.country_code != "DE"): - # detail_amount['tail_amount'] = 99999 - # return detail_amount - # if package.fst_size > 320 or package.sed_size>200 or package.trd_size>120: - # detail_amount['tail_amount'] = 99999 - # return detail_amount + if (package.fst_size > 320 or package.sed_size>170 or package.trd_size>120) and (self.country_code != "DE"): + detail_amount['tail_amount'] = 99999 + return detail_amount + if package.fst_size > 320 or package.sed_size>200 or package.trd_size>120: + detail_amount['tail_amount'] = 99999 + return detail_amount billing_weight = max(package.weight/1000,package.get_volume_weight(6000)) total_weight += billing_weight # 基础费用 @@ -652,7 +665,7 @@ class EURZGLogistics(TailLogistics): self.per_kg = None self.limit_kg = None self.remote = None - self.fuel_rate = 0.13 + self.fuel_rate = None def is_remote(self,postcode): """判断是否偏远,1偏远0非偏远""" raise NotImplementedError("Subclasses must implement remote calculation.") @@ -672,9 +685,9 @@ class EURZGLogistics(TailLogistics): detail_amount['remote'] = self.remote for package in packages: # 逐个处理列表中的每个包裹 - # if package.length+package.width+package.height > 150 or package.weight > self.limit_kg*1000: - # detail_amount['tail_amount'] = 99999 - # return detail_amount + if package.length+package.width+package.height > 150 or package.weight > self.limit_kg*1000: + detail_amount['tail_amount'] = 99999 + return detail_amount detail_amount['base'] += self.per_item+self.per_kg*package.weight/1000 for key in detail_amount: @@ -692,6 +705,7 @@ class EURZGLogistics_DE(EURZGLogistics): self.per_kg = 0.87 self.limit_kg = 30 self.remote = 0 + self.fuel_rate = 0.0125 def is_remote(self,postcode): return 0 @@ -704,6 +718,7 @@ class EURZGLogistics_FR(EURZGLogistics): self.per_kg = 1.07 self.limit_kg = 30 self.remote = [5.5,14] + self.fuel_rate = 0.0325 def calculate_fee(self,packages,postcode): """计算快递费用""" detail_amount = { @@ -718,9 +733,9 @@ class EURZGLogistics_FR(EURZGLogistics): return detail_amount for package in packages: # 逐个处理列表中的每个包裹 - # if package.length+package.width+package.height > 150 or package.weight > self.limit_kg*1000: - # detail_amount['tail_amount'] = 99999 - # return detail_amount + if package.length+package.width+package.height > 150 or package.weight > self.limit_kg*1000: + detail_amount['tail_amount'] = 99999 + return detail_amount if package.weight <=500: per_item = self.per_item[0] elif package.weight <=2000: @@ -759,6 +774,7 @@ class EURZGLogistics_IT(EURZGLogistics): self.per_kg = 1.38 self.limit_kg = 30 self.remote = 6 + self.fuel_rate = 0.06 def is_remote(self,postcode): remote_list = ["51024","67020", "67030", "67013", "67049","39030", "39032", "39040", "39043", "39054", "39058","98050", "98055","85046","89030", "89040", "89012", "89049", "89043", "80051", "80071", "80072", "80073", "80074", "80075", "80076", "80077", "80079", "80081", @@ -782,6 +798,7 @@ class EURZGLogistics_PT(EURZGLogistics): self.per_kg = 1.95 self.limit_kg = 30 self.remote = 5 + self.fuel_rate = 0 def is_remote(self,postcode): postcode = str(postcode) if postcode.startswith("9"): @@ -802,9 +819,9 @@ class EURZGLogistics_PT(EURZGLogistics): return detail_amount for package in packages: # 逐个处理列表中的每个包裹 - # if package.length+package.width+package.height > 150 or package.weight > self.limit_kg*1000: - # detail_amount['tail_amount'] = 99999 - # return detail_amount + if package.length+package.width+package.height > 150 or package.weight > self.limit_kg*1000: + detail_amount['tail_amount'] = 99999 + return detail_amount detail_amount['base'] += self.per_item+self.per_kg*package.weight/1000 if isremote == 1: detail_amount['remote'] += self.remote*package.weight/1000+15 @@ -824,10 +841,24 @@ class EURZGLogistics_ES(EURZGLogistics): self.per_kg = 1.85 self.limit_kg = 30 self.remote = 99999 + self.fuel_rate = 0.01 def is_remote(self,postcode): postcode = str(postcode) postcode_str = postcode[:2] if postcode_str in ['07','51','52','35','38']: return 1 else: + return 0 + +class EURZGLogistics_IR(EURZGLogistics): + country_code = 'IR' + country = 'Ireland' + def __init__(self): + super().__init__() + self.per_item = 3.92 + self.per_kg = 1.58 + self.limit_kg = 30 + self.remote = 999999 + self.fuel_rate = 0.01 + def is_remote(self,postcode): return 0 \ No newline at end of file diff --git a/logisticsClass/logisticsTail_UK.py b/logisticsClass/logisticsTail_UK.py index b1feb33..3f9e090 100644 --- a/logisticsClass/logisticsTail_UK.py +++ b/logisticsClass/logisticsTail_UK.py @@ -15,7 +15,7 @@ class DPDLogistics_UK(TailLogistics): currency = 'GBP' def __init__(self): super().__init__() - self.base_fee = 3.7 + self.base_fee = 3.8 self.oversize = 26 self.fuel_rate = 0.2 # BT开头的有20%燃油费 self.remote_fee = 35 @@ -34,9 +34,9 @@ class DPDLogistics_UK(TailLogistics): if self.is_remote(postcode): detail_amount['remote'] = self.remote_fee for package in packages: - # if package.weight >= 40000 or package.fst_size >= 175 or package.girth>=339: - # detail_amount['tail_amount'] =99999 - # return detail_amount + if package.weight >= 40000 or package.fst_size >= 175 or package.girth>=339: + detail_amount['tail_amount'] =99999 + return detail_amount if package.weight >= 30000 or package.fst_size >= 100 or package.sed_size >=60: detail_amount['oversize'] += self.oversize detail_amount['base'] += self.base_fee diff --git a/logisticsClass/logisticsTail_US.py b/logisticsClass/logisticsTail_US.py index e23b363..e3a6d4b 100644 --- a/logisticsClass/logisticsTail_US.py +++ b/logisticsClass/logisticsTail_US.py @@ -59,6 +59,7 @@ class WestLogistics_US(TailLogistics): def get_west_zone(self, postcode): """获取美西邮编分区""" + postcode = str(postcode) if not re.match(r'\d{5}-\d{4}|\d{5}', postcode): return "邮编格式不合法" postcode = postcode[:5] @@ -78,7 +79,6 @@ class WestLogistics_US(TailLogistics): return zone return "未查询到邮编分区" - class FedexLogistics(WestLogistics_US): """Fedex""" country = "United States" @@ -500,11 +500,11 @@ class CEVALogistics_US(TailLogistics): detail_amount['tail_amount'] += detail_amount[key] return detail_amount -class MetroLogistics_US(TailLogistics): +class MetroLALogistics_US(TailLogistics): """卡派:Metro""" country = "United States" country_code = "US" - company = "Metro-SAIR" + company = "Metro-SAIR-美西" logistics_type = LogisticsType.LTL parent_current_directory = Path(__file__).parent.parent @@ -516,15 +516,6 @@ class MetroLogistics_US(TailLogistics): 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: @@ -611,6 +602,113 @@ class MetroLogistics_US(TailLogistics): detail_amount['tail_amount'] += detail_amount[key] return detail_amount +class MetroNYLogistics_US(TailLogistics): + """卡派:Metro""" + country = "United States" + country_code = "US" + company = "Metro-SAIR-美东" + logistics_type = LogisticsType.LTL + + 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 + 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, + "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]) + # 出发地分区为 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 + volume_weight = 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) + volume_weight += package.weight/1000 + + # base费用 25立方英尺 ,美西是Zone 2 L 美东是Zone 17 L + if total_cuft < 25: + detail_amount["base"] = self.cuft_25[self.cuft_25['Origins']==zone]["Zone 17 L"].iloc[0] + elif 25<=total_cuft <35: + detail_amount["base"] = self.cuft_35[self.cuft_35['Origins']==zone]["Zone 17 L"].iloc[0] + else: + per_cuft = self.over_35_per_cuft[self.over_35_per_cuft['Origins']==zone]["Zone 17 L"].iloc[0] + base_min = self.over_35_min[self.over_35_min['Origins']==zone]["Zone 17 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 3001000: - detail_amount['tail_amount'] = 99999 + detail_amount['tail_amount'] = 999999 return detail_amount zone = self.PUZone+DLZone @@ -844,7 +943,9 @@ class AMTEastLogistics_US(TailLogistics): 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 + + detail_amount["transfer"] = 0.5*volume_weight # 美西到美东的中转费 + if detail_amount['base']==0: detail_amount['tail_amount'] = 99999 return detail_amount diff --git a/utils/apply_active_config.py b/utils/apply_active_config.py index 9e4d5a1..08bd9ce 100644 --- a/utils/apply_active_config.py +++ b/utils/apply_active_config.py @@ -2,16 +2,31 @@ from logisticsClass.logisticsBaseClass import HeadLogistics, PortType, TailLogis # logistics_config.py ACTIVE_LOGISTICS = { - "FedexPPLogistics_US": True, - "FedexKHLogistics_US": True, + # US + "FedexPPLogistics_US": False,# 需关闭 + "FedexKHLogistics_US": False,# 需关闭 "FedexHOMELogistics_US": True, "FedexGROUDLogistics_US": True, "MetroLogistics_US": True, - "GIGALogistics_US": True, - "CEVALogistics_US": True, + "GIGALogistics_US": False,# 需关闭 + "CEVALogistics_US": False,# 需关闭 "XmilesLogistics_US":True, "AMTWestLogistics_US":True, - "AMTEastLogistics_US":True + "AMTEastLogistics_US":True, + # UK + "DPDLogistics_UK": True, + "bigLogistics_UK": True, + "KPZGLogistics_UK": True, + "KPNVlogistics_UK": False,# 需关闭 + + # EUR + "DPDASLLogistics":False, # 需关闭 + + # GB + "bigLogistics_UK":False, # 需关闭 + "KPZGLogistics_UK":False, # 需关闭 + "bigLogistics_UK":False, # 需关闭,智谷旧版大件,8,新版是分区的 + } def apply_active_config(): stack = list(BaseLogistics.__subclasses__()) diff --git a/utils/logistics_name_config.py b/utils/logistics_name_config.py index 42f5f0c..6d986f7 100644 --- a/utils/logistics_name_config.py +++ b/utils/logistics_name_config.py @@ -1,20 +1,27 @@ logistics_name = { + "--":"--", + "三态带电":"--", # US + "空LAX-USPS/F":"--", # 待补 + "空LAX-USPS/P":"--", # 待补 "空LAX-FEDEX-SAIR-H": "Fedex-HOME", "空LAX-FEDEX-SAIR-G": "Fedex-GROUD", "海MS-FEDEX-SAIR-H": "Fedex-HOME", "海MS-FEDEX-SAIR-G": "Fedex-GROUD", - "海MS-METRO-SAIR": "Metro-SAIR", - "海NY-METRO-SAIR": "Metro-SAIR", # 暂时没写 - "海NY-XMILES-SAIR": "XMILES-SAIR", + "海MS-METRO-SAIR": "Metro-SAIR-美西", + "海NY-METRO-SAIR": "Metro-SAIR-美东", + "海NY-XMILES-SAIR": "XMILES-SAIR", "海MS-XMILES": "XMILES-SAIR", - "海NY-AMT-SAIR": "AM-美东", + "海NY-AMT-SAIR": "AM-美东", "海MS-AMT-SAIR": "AM-美西", - - "海MS-FEDEX02":"Fedex-彩虹小马", - "空LAX-FEDEX02":"Fedex-彩虹小马", - + "海MS-FEDEX02":"Fedex-彩虹小马", # 已关闭 + "空LAX-FEDEX02":"Fedex-彩虹小马", # 已关闭 + "海MS-美西卡派":"Metro-SAIR", # 不确定的渠道,默认为Metro + "海MS-美东卡派":"Metro-SAIR",# 不确定的渠道,默认为Metro + "空LAX-卡派":"Metro-SAIR",# 不确定的渠道,默认为Metro + "易可达/WEST-USPS":"--", # 无法计算 + "易可达/WEST-UPS":"--", # 无法计算 # AU "海SY-POST3":"POST", "海POST- TMS改重":"POST", @@ -26,6 +33,23 @@ logistics_name = { "空SYD-TOLL1":"TOLL", "海SY-ALL": "ALL", "空SYD-ALL": "ALL", + + # UK + "空LHR-DPD":"智谷-DPD", + "海GB-DPD2":"智谷-DPD", + "海GB-卡派":"卡派-NV", + "海GB-AIT-FX":"--", # 待补 + "空LHR-卡派":"卡派-ZG", + "海GB-大件":"智谷-大件", + + # 欧洲整体 + "空AMS-DPD":"DPD-ZG", + "海NL-DPD-ZG":"DPD-ZG", + "空AMS-EUR":"EUR-ZG", + "海NL-卡派2":"卡派-GEL", + "海NL-DPD-ASL":"DPD-ASL", + "海NL-DPD-NV":"--" + } #海NY-WWEX-SAIR,海MS-WWEX-SAIR没报价表,也停用了 \ No newline at end of file