2025-06-17 13:40:20 +08:00
|
|
|
|
""" 澳大利亚尾端物流模块实现类"""
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
import re
|
|
|
|
|
|
import math
|
|
|
|
|
|
import pandas as pd
|
|
|
|
|
|
from logisticsClass.logisticsBaseClass import TailLogistics
|
|
|
|
|
|
from utils.Package import Package, Package_group
|
|
|
|
|
|
"""
|
|
|
|
|
|
counrty:Australia
|
|
|
|
|
|
company:POST,ALL,TOLL
|
|
|
|
|
|
port:海SY,空SYD(default)
|
|
|
|
|
|
currency:str = 'AUD'(default)
|
|
|
|
|
|
logistics_type:LogisticsType (快递(default),卡派)
|
|
|
|
|
|
"""
|
|
|
|
|
|
# POST
|
|
|
|
|
|
class PostLogistics_AU(TailLogistics):
|
|
|
|
|
|
country_code = 'AU'
|
|
|
|
|
|
country = 'Australia'
|
|
|
|
|
|
company = 'POST'
|
|
|
|
|
|
currency = 'AUD'
|
|
|
|
|
|
|
|
|
|
|
|
_is_loaded = False
|
|
|
|
|
|
parent_current_directory = Path(__file__).parent.parent
|
|
|
|
|
|
remote_path = parent_current_directory.joinpath("data")
|
|
|
|
|
|
_postcode_files = remote_path.joinpath("澳洲三大渠道.xlsx")
|
|
|
|
|
|
|
|
|
|
|
|
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):
|
|
|
|
|
|
"""加载文件"""
|
|
|
|
|
|
# 获取eparcel邮编所属的分区
|
|
|
|
|
|
cls.eparcel_zone = pd.read_excel(str(cls._postcode_files),sheet_name="eparcel_postcode",usecols="A:B")
|
|
|
|
|
|
# 获取eparcel的价格
|
|
|
|
|
|
cls.eparcel_price = pd.read_excel(str(cls._postcode_files),sheet_name="eparcel",usecols="A:M")
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
|
super().__init__()
|
|
|
|
|
|
self.eparcel_zone = self.__class__.eparcel_zone
|
|
|
|
|
|
self.eparcel_price = self.__class__.eparcel_price
|
|
|
|
|
|
self.fuel_rate =0.051# 0.074 0.064
|
|
|
|
|
|
|
2025-09-10 13:37:38 +08:00
|
|
|
|
def is_remote(self, postcode):
|
|
|
|
|
|
"""判断分区"""
|
|
|
|
|
|
# 先看邮编呐
|
|
|
|
|
|
self.eparcel_zone['邮编'] = self.eparcel_zone['邮编'].astype(str).str.zfill(4)
|
|
|
|
|
|
|
|
|
|
|
|
filtered_df = self.eparcel_zone[self.eparcel_zone['邮编'] == postcode]
|
|
|
|
|
|
if filtered_df.empty:
|
|
|
|
|
|
return "不支持配送"
|
|
|
|
|
|
|
|
|
|
|
|
post = filtered_df['地区代码'].iloc[0] # 获取第一行的 '地区代码'
|
|
|
|
|
|
return post
|
2025-06-17 13:40:20 +08:00
|
|
|
|
def calculate_fee(self, packages, postcode):
|
|
|
|
|
|
"""
|
|
|
|
|
|
计费重: 常规计费, 4000
|
2025-07-16 00:05:12 +08:00
|
|
|
|
限制条件: 32kg,最长边100cm.3KG以内实重计费,3KG以上标准计费,2.5KG按3KG算
|
2025-06-17 13:40:20 +08:00
|
|
|
|
是否有燃油费:是
|
|
|
|
|
|
"""
|
|
|
|
|
|
detail_amount = {
|
|
|
|
|
|
"base":0.00,
|
|
|
|
|
|
"fuel":0.00,
|
|
|
|
|
|
"tail_amount":0.00
|
|
|
|
|
|
}
|
|
|
|
|
|
if isinstance(postcode, str):
|
|
|
|
|
|
postcode = ''.join(filter(str.isdigit, postcode)) # 只保留数字部分
|
|
|
|
|
|
if postcode: # 确保postcode不是空字符串
|
|
|
|
|
|
postcode = str(int(postcode)).zfill(4) # 转换为整数再补齐4位
|
|
|
|
|
|
else:
|
|
|
|
|
|
detail_amount['tail_amount'] = 88888
|
|
|
|
|
|
return detail_amount
|
|
|
|
|
|
|
2025-09-10 13:37:38 +08:00
|
|
|
|
post = self.is_remote(postcode)
|
|
|
|
|
|
if post == "不支持配送":
|
2025-06-17 13:40:20 +08:00
|
|
|
|
detail_amount['tail_amount'] = 99999
|
|
|
|
|
|
return detail_amount
|
|
|
|
|
|
# 根据post筛选出对应行
|
|
|
|
|
|
row = self.eparcel_price[self.eparcel_price['post'] == post]
|
|
|
|
|
|
# 检查 row 是否为空
|
|
|
|
|
|
if row.empty:
|
|
|
|
|
|
detail_amount['tail_amount'] = 99999
|
|
|
|
|
|
return detail_amount
|
|
|
|
|
|
|
|
|
|
|
|
base_data = list(zip(self.eparcel_price.columns[1:], row.values[0][1:]))
|
|
|
|
|
|
for package in packages:
|
2025-07-16 00:05:12 +08:00
|
|
|
|
# 2500g-3000g按3kg算
|
|
|
|
|
|
if 2500<=package.weight<3000:
|
|
|
|
|
|
package.weight = 3000
|
|
|
|
|
|
if package.weight > 3000:
|
|
|
|
|
|
billing_weight = max(package.weight, package.volume/4)
|
|
|
|
|
|
else:
|
|
|
|
|
|
billing_weight = package.weight
|
|
|
|
|
|
|
2025-06-17 13:40:20 +08:00
|
|
|
|
|
2025-07-16 00:05:12 +08:00
|
|
|
|
if package.fst_size > 100 or billing_weight > 22000:
|
2025-06-17 13:40:20 +08:00
|
|
|
|
detail_amount['tail_amount'] = 99999
|
|
|
|
|
|
return detail_amount
|
|
|
|
|
|
if billing_weight > 22000:
|
|
|
|
|
|
detail_amount['base'] += base_data[-2][1] + base_data[-1][1] * math.ceil(billing_weight/1000)
|
|
|
|
|
|
else:
|
|
|
|
|
|
for weight,price in base_data[:-2]:
|
|
|
|
|
|
if billing_weight <=weight*1000:
|
|
|
|
|
|
detail_amount['base'] += price
|
|
|
|
|
|
break
|
|
|
|
|
|
detail_amount['fuel'] = detail_amount['base'] * self.fuel_rate
|
|
|
|
|
|
detail_amount['tail_amount'] = detail_amount['base'] + detail_amount['fuel']
|
|
|
|
|
|
return detail_amount
|
|
|
|
|
|
|
|
|
|
|
|
# TOLL
|
|
|
|
|
|
class TollLogistics_AU(TailLogistics):
|
|
|
|
|
|
country_code = 'AU'
|
|
|
|
|
|
country = 'Australia'
|
|
|
|
|
|
company = 'TOLL'
|
|
|
|
|
|
currency = 'AUD'
|
|
|
|
|
|
|
|
|
|
|
|
_is_loaded = False
|
|
|
|
|
|
parent_current_directory = Path(__file__).parent.parent
|
|
|
|
|
|
remote_path = parent_current_directory.joinpath("data")
|
|
|
|
|
|
_postcode_files = remote_path.joinpath("澳洲三大渠道.xlsx")
|
|
|
|
|
|
|
|
|
|
|
|
def __new__(cls):
|
|
|
|
|
|
"""实现单例模式,只加载一次文件"""
|
|
|
|
|
|
if not cls._is_loaded:
|
|
|
|
|
|
cls._load_postcodes() # 第一次实例化时加载文件
|
|
|
|
|
|
cls._is_loaded = True # 标记文件已加载
|
|
|
|
|
|
return super().__new__(cls)
|
|
|
|
|
|
@classmethod
|
|
|
|
|
|
def _load_postcodes(cls):
|
|
|
|
|
|
"""加载文件"""
|
|
|
|
|
|
cls.toll_zone = pd.read_excel(str(cls._postcode_files),sheet_name="toll_postcode",usecols="A:B")
|
|
|
|
|
|
cls.toll_price = pd.read_excel(str(cls._postcode_files),sheet_name="toll",usecols="A:D")
|
|
|
|
|
|
cls.toll_remote = pd.read_excel(str(cls._postcode_files),sheet_name="toll_remote",usecols="A:D")
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
|
super().__init__()
|
|
|
|
|
|
self.toll_zone = self.__class__.toll_zone
|
|
|
|
|
|
self.toll_price = self.__class__.toll_price
|
|
|
|
|
|
self.toll_remote = self.__class__.toll_remote
|
|
|
|
|
|
self.fuel_rate = 0.0725
|
|
|
|
|
|
self.oversize_fee = [15.5,62]
|
2025-09-10 13:37:38 +08:00
|
|
|
|
|
|
|
|
|
|
def is_remote(self, postcode):
|
|
|
|
|
|
"""判断分区"""
|
|
|
|
|
|
# 先看邮编呐
|
|
|
|
|
|
self.toll_zone['postcode'] = self.toll_zone['postcode'].astype(str).str.zfill(4)
|
|
|
|
|
|
filtered_df = self.toll_zone[self.toll_zone['postcode'] == postcode]
|
|
|
|
|
|
if filtered_df.empty:
|
|
|
|
|
|
return "不支持配送"
|
|
|
|
|
|
post = filtered_df['post'].iloc[0] # 获取第一行的 '地区代码'
|
|
|
|
|
|
return post
|
2025-06-17 13:40:20 +08:00
|
|
|
|
def calculate_fee(self, packages, postcode):
|
|
|
|
|
|
# 抛重4000
|
|
|
|
|
|
detail_amount = {
|
|
|
|
|
|
"base":0.00,
|
|
|
|
|
|
"oversize":0.00,
|
|
|
|
|
|
"remote":0.00,
|
|
|
|
|
|
"fuel":0.00,
|
|
|
|
|
|
"tail_amount":0.00
|
|
|
|
|
|
}
|
|
|
|
|
|
if isinstance(postcode, str):
|
|
|
|
|
|
postcode = ''.join(filter(str.isdigit, postcode)) # 只保留数字部分
|
|
|
|
|
|
if postcode: # 确保postcode不是空字符串
|
|
|
|
|
|
postcode = str(int(postcode)).zfill(4) # 转换为整数再补齐4位
|
|
|
|
|
|
else:
|
|
|
|
|
|
detail_amount['tail_amount'] = 88888
|
|
|
|
|
|
return detail_amount
|
2025-09-10 13:37:38 +08:00
|
|
|
|
post = self.is_remote(postcode)
|
|
|
|
|
|
if post == "不支持配送":
|
2025-06-17 13:40:20 +08:00
|
|
|
|
detail_amount['tail_amount'] = 99999
|
|
|
|
|
|
return detail_amount
|
|
|
|
|
|
# 根据post筛选出对应行
|
|
|
|
|
|
row = self.toll_price[self.toll_price['post'] == post]
|
|
|
|
|
|
# 检查 row 是否为空
|
|
|
|
|
|
if row.empty:
|
|
|
|
|
|
detail_amount['tail_amount'] = 99999
|
|
|
|
|
|
return detail_amount
|
|
|
|
|
|
|
|
|
|
|
|
base = row['Base'].iloc[0]
|
|
|
|
|
|
per = self.toll_price[self.toll_price['post']==post]['Per'].iloc[0]
|
|
|
|
|
|
minimun = self.toll_price[self.toll_price['post']==post]['Minimun'].iloc[0]
|
|
|
|
|
|
for package in packages:
|
|
|
|
|
|
volume_weight = package.get_volume_weight(4)
|
|
|
|
|
|
billing_weight = max(package.weight,volume_weight)
|
|
|
|
|
|
detail_amount['base'] += max(base + per * math.ceil(billing_weight/1000), minimun)
|
2025-07-16 00:05:12 +08:00
|
|
|
|
if package.weight >= 35000 or package.fst_size >= 180 or package.volume >=700000:
|
|
|
|
|
|
# detail_amount['oversize'] += self.oversize_fee[1]
|
|
|
|
|
|
detail_amount['tail_amount'] = 99999 # ERP配置的超过这个尺寸就不派送这个了
|
2025-06-17 13:40:20 +08:00
|
|
|
|
if package.weight >30000 or package.fst_size > 120 or package.sed_size > 80:
|
|
|
|
|
|
detail_amount['oversize'] += self.oversize_fee[0]
|
2025-07-16 00:05:12 +08:00
|
|
|
|
|
2025-06-17 13:40:20 +08:00
|
|
|
|
|
|
|
|
|
|
# 计算偏远附加费,只跟地区有关,不需要放入循环内部计算
|
2025-07-16 00:05:12 +08:00
|
|
|
|
# postcode_counts = self.toll_zone[self.toll_zone['postcode'] == postcode].shape[0] # 该邮编总共多少个地区
|
|
|
|
|
|
remote_count = self.toll_remote[self.toll_remote['postcode'] == int(postcode)].shape[0] # 该邮编有多少个偏远地区
|
|
|
|
|
|
# postcode_counts = int(postcode_counts)
|
2025-06-17 13:40:20 +08:00
|
|
|
|
remote_count=int(remote_count)
|
|
|
|
|
|
# 将 price 列中的 NaN 替换为 0
|
|
|
|
|
|
self.toll_remote['price'] = self.toll_remote['price'].fillna(0)
|
|
|
|
|
|
# 该邮编偏远地区的偏远费
|
2025-07-16 00:05:12 +08:00
|
|
|
|
remote_fee = self.toll_remote[self.toll_remote['postcode'] == int(postcode)]['price'].mean()
|
2025-06-17 13:40:20 +08:00
|
|
|
|
# 检查 remote_fee 是否为 NaN,若是则设为 0
|
|
|
|
|
|
if pd.isna(remote_fee):
|
|
|
|
|
|
remote_fee = 0
|
|
|
|
|
|
|
2025-07-16 00:05:12 +08:00
|
|
|
|
# # 计算最终的偏远附加费
|
|
|
|
|
|
# if postcode_counts > 0 and remote_count > 0:
|
|
|
|
|
|
# remote_fee = remote_fee * remote_count / postcode_counts
|
|
|
|
|
|
# else:
|
|
|
|
|
|
# remote_fee = 0 # 处理为其他合适的值
|
2025-06-17 13:40:20 +08:00
|
|
|
|
|
|
|
|
|
|
detail_amount['remote'] = remote_fee * len(packages)
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
# ALL
|
|
|
|
|
|
class AllLogistics_AU(TailLogistics):
|
|
|
|
|
|
country_code = 'AU'
|
|
|
|
|
|
country = 'Australia'
|
|
|
|
|
|
company = 'ALL'
|
|
|
|
|
|
currency = 'AUD'
|
|
|
|
|
|
|
|
|
|
|
|
_is_loaded = False
|
|
|
|
|
|
parent_current_directory = Path(__file__).parent.parent
|
|
|
|
|
|
remote_path = parent_current_directory.joinpath("data")
|
|
|
|
|
|
_postcode_files = remote_path.joinpath("澳洲三大渠道.xlsx")
|
|
|
|
|
|
|
|
|
|
|
|
def __new__(cls):
|
|
|
|
|
|
"""实现单例模式,只加载一次文件"""
|
|
|
|
|
|
if not cls._is_loaded:
|
|
|
|
|
|
cls._load_postcodes() # 第一次实例化时加载文件
|
|
|
|
|
|
cls._is_loaded = True # 标记文件已加载
|
|
|
|
|
|
return super().__new__(cls)
|
|
|
|
|
|
@classmethod
|
|
|
|
|
|
def _load_postcodes(cls):
|
|
|
|
|
|
"""加载文件"""
|
|
|
|
|
|
cls.all_zone = pd.read_excel(str(cls._postcode_files),sheet_name="allied_postcode",usecols="A:C")
|
|
|
|
|
|
cls.all_price = pd.read_excel(str(cls._postcode_files),sheet_name="allied",usecols="A:D")
|
|
|
|
|
|
cls.all_remote = pd.read_excel(str(cls._postcode_files),sheet_name="allied_remote",usecols="A:E")
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
|
super().__init__()
|
|
|
|
|
|
self.all_zone = self.__class__.all_zone
|
|
|
|
|
|
self.all_price = self.__class__.all_price
|
|
|
|
|
|
self.all_remote = self.__class__.all_remote
|
|
|
|
|
|
self.fuel_rate = 0.269
|
|
|
|
|
|
self.homedelivery_fee = [5.51,11.02,38.56,82.61]
|
|
|
|
|
|
self.oversize_fee = [7.8,10.92,12.41,26.42,92.15,123.96,160.07]
|
|
|
|
|
|
self.handing_fee = 15.34 # 不收燃油费
|
|
|
|
|
|
self.twomancrew_fee = [49.92,78,124.8] # 多包裹的情况下,只收一次最大的
|
2025-09-10 13:37:38 +08:00
|
|
|
|
|
|
|
|
|
|
def is_remote(self, postcode):
|
|
|
|
|
|
"""判断分区"""
|
|
|
|
|
|
# 先看邮编呐
|
|
|
|
|
|
# 先看邮编呐
|
|
|
|
|
|
self.all_zone['postcode'] = self.all_zone['postcode'].astype(str).str.zfill(4)
|
|
|
|
|
|
filtered_df = self.all_zone[self.all_zone['postcode'] == postcode]
|
|
|
|
|
|
if filtered_df.empty:
|
|
|
|
|
|
return "不支持配送"
|
|
|
|
|
|
post = filtered_df['post'].iloc[0] # 获取第一行的 '地区代码'
|
|
|
|
|
|
return post
|
2025-06-17 13:40:20 +08:00
|
|
|
|
def calculate_fee(self, packages, postcode):
|
|
|
|
|
|
# 抛重4000
|
|
|
|
|
|
detail_amount = {
|
|
|
|
|
|
"base":0.00,
|
|
|
|
|
|
"Homedelivery":0.00,
|
|
|
|
|
|
"twomancrew":0.00, # 多包裹的情况下,只收一次最大的
|
|
|
|
|
|
"lengthover":0.00,
|
|
|
|
|
|
"fuel":0.00,
|
|
|
|
|
|
"widthover":0.00, # 240cm内不收燃油费
|
|
|
|
|
|
"handling":0.00,
|
|
|
|
|
|
"tail_amount":0.00
|
|
|
|
|
|
}
|
|
|
|
|
|
if isinstance(postcode, str):
|
|
|
|
|
|
postcode = ''.join(filter(str.isdigit, postcode)) # 只保留数字部分
|
|
|
|
|
|
if postcode: # 确保postcode不是空字符串
|
|
|
|
|
|
postcode = str(int(postcode)).zfill(4) # 转换为整数再补齐4位
|
|
|
|
|
|
else:
|
|
|
|
|
|
detail_amount['tail_amount'] = 88888
|
|
|
|
|
|
return detail_amount
|
2025-09-10 13:37:38 +08:00
|
|
|
|
post = self.is_remote(postcode)
|
|
|
|
|
|
if post == "不支持配送":
|
2025-06-17 13:40:20 +08:00
|
|
|
|
detail_amount['tail_amount'] = 99999
|
|
|
|
|
|
return detail_amount
|
|
|
|
|
|
try:
|
|
|
|
|
|
base = self.all_price[self.all_price['post']==post]['Base'].iloc[0]
|
|
|
|
|
|
per = self.all_price[self.all_price['post']==post]['Per'].iloc[0]
|
|
|
|
|
|
minimun = self.all_price[self.all_price['post']==post]['Minimun'].iloc[0]
|
|
|
|
|
|
except:
|
|
|
|
|
|
detail_amount['tail_amount'] = 99999
|
|
|
|
|
|
return detail_amount
|
|
|
|
|
|
total_weight = 0 # 总计费重,用于计算偏远附加费
|
|
|
|
|
|
for package in packages:
|
|
|
|
|
|
volume_weight = package.get_volume_weight(4)
|
|
|
|
|
|
billing_weight = max(package.weight,volume_weight)
|
|
|
|
|
|
total_weight += billing_weight # 总计费重,用于计算偏远附加费
|
|
|
|
|
|
detail_amount['base'] += max(base + per * math.ceil(billing_weight/1000), minimun)
|
|
|
|
|
|
if billing_weight <= 22000:
|
|
|
|
|
|
detail_amount['Homedelivery'] += self.homedelivery_fee[0]
|
|
|
|
|
|
elif 22000<billing_weight <=55000:
|
|
|
|
|
|
detail_amount['Homedelivery'] += self.homedelivery_fee[1]
|
|
|
|
|
|
elif 55000<package.weight<=90000 or 55000<volume_weight<=135000:
|
|
|
|
|
|
detail_amount['Homedelivery'] += self.homedelivery_fee[2]
|
|
|
|
|
|
else:
|
|
|
|
|
|
detail_amount['Homedelivery'] += self.homedelivery_fee[3]
|
|
|
|
|
|
[7.8,10.92,12.41,26.42,92.15,123.96,160.07]
|
|
|
|
|
|
if 110<package.fst_size <=160:
|
|
|
|
|
|
detail_amount['widthover'] += self.oversize_fee[0]
|
|
|
|
|
|
elif 160<package.fst_size <=240:
|
|
|
|
|
|
detail_amount['widthover'] += self.oversize_fee[1]
|
|
|
|
|
|
elif 240<package.fst_size <=359:
|
|
|
|
|
|
detail_amount['lengthover'] += self.oversize_fee[2]
|
|
|
|
|
|
elif 359<package.fst_size <=419:
|
|
|
|
|
|
detail_amount['lengthover'] += self.oversize_fee[3]
|
|
|
|
|
|
elif 419<package.fst_size <=479:
|
|
|
|
|
|
detail_amount['lengthover'] += self.oversize_fee[4]
|
|
|
|
|
|
elif 479<package.fst_size <=599:
|
|
|
|
|
|
detail_amount['lengthover'] += self.oversize_fee[5]
|
|
|
|
|
|
elif package.fst_size > 599:
|
|
|
|
|
|
detail_amount['lengthover'] += self.oversize_fee[6]
|
|
|
|
|
|
if 130<=package.fst_size <=190 and package.sed_size > 90 and (package.weight >46000 or billing_weight>91000):
|
|
|
|
|
|
detail_amount['twomancrew'] = self.twomancrew_fee[0]
|
|
|
|
|
|
if 190<=package.fst_size <=240 and package.sed_size > 130 and (package.weight >55000 or billing_weight>110000):
|
|
|
|
|
|
detail_amount['twomancrew'] = self.twomancrew_fee[1]
|
|
|
|
|
|
if 240<package.fst_size and package.sed_size > 130 and (package.weight >75000 or billing_weight>150000):
|
|
|
|
|
|
detail_amount['twomancrew'] = self.twomancrew_fee[2]
|
|
|
|
|
|
if billing_weight >30000 or package.fst_size >110:
|
|
|
|
|
|
detail_amount['handling'] += self.handing_fee
|
|
|
|
|
|
|
|
|
|
|
|
# 计算偏远附加费,只跟地区有关,不需要放入循环内部计算
|
|
|
|
|
|
postcode_counts = self.all_zone[self.all_zone['postcode'] == postcode].shape[0] # 该邮编总共多少个地区
|
|
|
|
|
|
remote_count = self.all_remote[self.all_remote['Postcode'] == postcode].shape[0] # 该邮编有多少个偏远地区
|
|
|
|
|
|
postcode_counts = int(postcode_counts)
|
|
|
|
|
|
remote_count=int(remote_count)
|
|
|
|
|
|
# 该邮编偏远地区的偏远费
|
|
|
|
|
|
remote_base_fee = self.all_remote[self.all_remote['Postcode']==postcode]['Base'].mean() # 该邮编偏远地区的偏远基础费
|
|
|
|
|
|
remote_per_fee = self.all_remote[self.all_remote['Postcode']==postcode]['Per'].mean()
|
|
|
|
|
|
# 检查 remote_base_fee 是否为 NaN,若是则设为 0
|
|
|
|
|
|
if pd.isna(remote_base_fee) or pd.isna(remote_per_fee):
|
|
|
|
|
|
remote_base_fee = 0
|
|
|
|
|
|
remote_per_fee = 0
|
|
|
|
|
|
|
|
|
|
|
|
# 计算最终的偏远附加费
|
|
|
|
|
|
if postcode_counts > 0 and remote_count > 0:
|
|
|
|
|
|
detail_amount['remote'] = remote_base_fee+remote_per_fee*math.ceil(total_weight/1000)* remote_count/postcode_counts
|
|
|
|
|
|
|
|
|
|
|
|
for key in detail_amount:
|
|
|
|
|
|
if key!= 'tail_amount' and key!= 'fuel':
|
|
|
|
|
|
detail_amount['tail_amount'] += detail_amount[key]
|
|
|
|
|
|
if key!='widthover' and key!='handling':
|
|
|
|
|
|
detail_amount['fuel'] += detail_amount[key] * self.fuel_rate
|
|
|
|
|
|
detail_amount['tail_amount'] += detail_amount['fuel']
|
|
|
|
|
|
return detail_amount
|
2025-09-10 13:37:38 +08:00
|
|
|
|
|
|
|
|
|
|
# TMS
|
|
|
|
|
|
# class TMSLogistics_AU(TailLogistics):
|
|
|
|
|
|
# country_code = 'AU'
|
|
|
|
|
|
# country = 'Australia'
|
|
|
|
|
|
# company = 'TMS'
|
|
|
|
|
|
# currency = 'AUD'
|
|
|
|
|
|
|
|
|
|
|
|
# _is_loaded = False
|
|
|
|
|
|
# parent_current_directory = Path(__file__).parent.parent
|
|
|
|
|
|
# remote_path = parent_current_directory.joinpath("data")
|
|
|
|
|
|
# _postcode_files = remote_path.joinpath("澳洲三大渠道.xlsx")
|
|
|
|
|
|
|
|
|
|
|
|
# def __new__(cls):
|
|
|
|
|
|
# """实现单例模式,只加载一次文件"""
|
|
|
|
|
|
# if not cls._is_loaded:
|
|
|
|
|
|
# cls._load_postcodes() # 第一次实例化时加载文件
|
|
|
|
|
|
# cls._is_loaded = True # 标记文件已加载
|
|
|
|
|
|
# return super().__new__(cls)
|
|
|
|
|
|
# @classmethod
|
|
|
|
|
|
# def _load_postcodes(cls):
|
|
|
|
|
|
# """加载文件"""
|
|
|
|
|
|
# cls.toll_zone = pd.read_excel(str(cls._postcode_files),sheet_name="toll_postcode",usecols="A:B")
|
|
|
|
|
|
# cls.toll_price = pd.read_excel(str(cls._postcode_files),sheet_name="toll",usecols="A:D")
|
|
|
|
|
|
# cls.toll_remote = pd.read_excel(str(cls._postcode_files),sheet_name="toll_remote",usecols="A:D")
|
|
|
|
|
|
|
|
|
|
|
|
# def __init__(self):
|
|
|
|
|
|
# super().__init__()
|
|
|
|
|
|
# self.toll_zone = self.__class__.toll_zone
|
|
|
|
|
|
# self.toll_price = self.__class__.toll_price
|
|
|
|
|
|
# self.toll_remote = self.__class__.toll_remote
|
|
|
|
|
|
# self.fuel_rate = 0.0725
|
|
|
|
|
|
# self.oversize_fee = [15.5,62]
|
|
|
|
|
|
|
|
|
|
|
|
# def is_remote(self, postcode):
|
|
|
|
|
|
# """判断分区"""
|
|
|
|
|
|
# # 先看邮编呐
|
|
|
|
|
|
# self.toll_zone['postcode'] = self.toll_zone['postcode'].astype(str).str.zfill(4)
|
|
|
|
|
|
# filtered_df = self.toll_zone[self.toll_zone['postcode'] == postcode]
|
|
|
|
|
|
# if filtered_df.empty:
|
|
|
|
|
|
# return "不支持配送"
|
|
|
|
|
|
# post = filtered_df['post'].iloc[0] # 获取第一行的 '地区代码'
|
|
|
|
|
|
# return post
|
|
|
|
|
|
# def calculate_fee(self, packages, postcode):
|
|
|
|
|
|
# # 抛重4000
|
|
|
|
|
|
# detail_amount = {
|
|
|
|
|
|
# "base":0.00,
|
|
|
|
|
|
# "oversize":0.00,
|
|
|
|
|
|
# "remote":0.00,
|
|
|
|
|
|
# "fuel":0.00,
|
|
|
|
|
|
# "tail_amount":0.00
|
|
|
|
|
|
# }
|
|
|
|
|
|
# if isinstance(postcode, str):
|
|
|
|
|
|
# postcode = ''.join(filter(str.isdigit, postcode)) # 只保留数字部分
|
|
|
|
|
|
# if postcode: # 确保postcode不是空字符串
|
|
|
|
|
|
# postcode = str(int(postcode)).zfill(4) # 转换为整数再补齐4位
|
|
|
|
|
|
# else:
|
|
|
|
|
|
# detail_amount['tail_amount'] = 88888
|
|
|
|
|
|
# return detail_amount
|
|
|
|
|
|
# post = self.is_remote(postcode)
|
|
|
|
|
|
# if post == "不支持配送":
|
|
|
|
|
|
# detail_amount['tail_amount'] = 99999
|
|
|
|
|
|
# return detail_amount
|
|
|
|
|
|
# # 根据post筛选出对应行
|
|
|
|
|
|
# row = self.toll_price[self.toll_price['post'] == post]
|
|
|
|
|
|
# # 检查 row 是否为空
|
|
|
|
|
|
# if row.empty:
|
|
|
|
|
|
# detail_amount['tail_amount'] = 99999
|
|
|
|
|
|
# return detail_amount
|
2025-06-17 13:40:20 +08:00
|
|
|
|
|
2025-09-10 13:37:38 +08:00
|
|
|
|
# base = row['Base'].iloc[0]
|
|
|
|
|
|
# per = self.toll_price[self.toll_price['post']==post]['Per'].iloc[0]
|
|
|
|
|
|
# minimun = self.toll_price[self.toll_price['post']==post]['Minimun'].iloc[0]
|
|
|
|
|
|
# for package in packages:
|
|
|
|
|
|
|
|
|
|
|
|
# return detail_amount
|
2025-06-17 13:40:20 +08:00
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
|
# 测试
|
|
|
|
|
|
aau = PostLogistics_AU()
|
|
|
|
|
|
package = Package("wxx",40,25,25,1780)
|
|
|
|
|
|
packages = Package_group([package])
|
|
|
|
|
|
aau.calculate_fee(packages,'3101')
|
|
|
|
|
|
TollLogistics_AU.active = True
|
|
|
|
|
|
PostLogistics_AU.active = True
|