from logisticsClass.logisticsBaseClass import HeadLogistics, PortType, TailLogistics,BaseLogistics from logisticsClass.logisticsTail_EUR import * from logisticsClass.logisticsHead_EUR import * from logisticsClass.logisticsTail_US import * from logisticsClass.logisticsHead_US import * from logisticsClass.logisticsTail_AU import * from logisticsClass.logisticsHead_AU import * from logisticsClass.logisticsTail_UK import * from logisticsClass.logisticsHead_UK import * from utils.apply_active_config import apply_active_config class OperateCountry: """操作国家""" def __init__(self, country_name,port = PortType.DEFAULT,packeges = None, postcode = None): # head表示头程方式,默认海运,0为空运 self.country_name = country_name self.port = port self.packages = packeges self.postcode = postcode self.companies = self.get_tail_subclasses() def set_packages_and_postcode(self,packages,postcode): self.packages = packages self.postcode = postcode def set_parameter(self,parameter,self_parameter): """设置参数,优先考虑函数参数,其次考虑类属性""" return parameter if parameter is not None else self_parameter def get_head_class(self,port=None,head_type=None): """获取头程类,头程与港口的关联更密切,所以可能一个头程类包含多个国家""" port = self.set_parameter(port, self.port) headclass = None apply_active_config() subclasses = HeadLogistics.get_open_subclasses() for cls in subclasses: if hasattr(cls, "country") and self.country_name in cls.country and cls.port == port and cls.logistics_type.value == head_type: headclass = cls() elif hasattr(cls, "country") and self.country_name in cls.country_code and cls.port ==port and cls.logistics_type.value == head_type: headclass = cls() if headclass is None: raise ValueError(f"No head class found for port {port}") return headclass def get_air_fee(self, packages=None,port=None): """获取空运头程费用""" packages = self.set_parameter(packages, self.packages) if packages is None: raise ValueError("No packages or port provided") air_class = self.get_head_class(port,"空运") air_head_fee = air_class.calculate_fee(packages) return air_head_fee def get_ocean_fee(self, packages=None,port=None): """获取海运头程费用""" packages = self.set_parameter(packages, self.packages) if packages is None: raise ValueError("No packages or port provided") ocean_class = self.get_head_class(port,"海运") ocean_head_fee = ocean_class.calculate_fee(packages) return ocean_head_fee def get_tail_subclasses(self): """获取该国家对应港口的尾端物流实现类列表""" # 如果没有指定 port, 则返回默认港口的物流公司及其实例 companies = {} apply_active_config() subclasses = TailLogistics.get_open_subclasses() for cls in subclasses: # 获取符合条件的公司,国家名相等且港口名相等 if hasattr(cls, "country") and self.country_name == cls.country and cls.port == self.port: if hasattr(cls, "company"): companies[cls.company] = cls() else: continue elif hasattr(cls, "country") and self.country_name == cls.country_code and cls.port ==self.port: if hasattr(cls, "company"): companies[cls.company] = cls() else: continue return companies def get_all_tail_info(self, packages=None,postcode=None): """计算所有物流公司尾端费用""" packages = self.set_parameter(packages, self.packages) postcode = self.set_parameter(postcode, self.postcode) if packages is None or postcode is None: raise ValueError("No packages or postcode provided") results = {} # 存储物流公司及其对应的实例 for company, fee_instance in self.companies.items(): results[company] = self.get_tail_amount(company,packages,postcode) return results def get_min_company(self, packages=None,postcode=None): """获取最低尾端费用公司""" packages = self.set_parameter(packages, self.packages) postcode = self.set_parameter(postcode, self.postcode) if packages is None or postcode is None: raise ValueError("No packages or postcode provided") all_fees = self.get_all_tail_info(packages,postcode) min_company = min(all_fees, key=all_fees.get) return min_company def get_company_class(self, company_name): """获取指定物流公司的物流类""" if company_name not in self.companies: raise ValueError(f"No such company: {company_name}") company_class = self.companies[company_name] return company_class def get_tail_amount(self, company_name, packages=None,postcode=None): """获取指定物流公司的费用""" packages = self.set_parameter(packages, self.packages) postcode = self.set_parameter(postcode, self.postcode) if packages is None or postcode is None: raise ValueError("No packages or postcode provided") if company_name not in self.companies: raise ValueError(f"No such company: {company_name}") detail_amount = self.get_detail_amount(company_name, packages,postcode) return round(detail_amount['tail_amount'], 2) def get_tail_currency(self, company_name): """获取指定物流公司的货币""" company = self.get_company_class(company_name) return company.currency def get_logistic_type(self, company_name): """获取指定物流公司的物流类型""" company = self.get_company_class(company_name) return company.logistics_type.value def get_detail_amount(self, company_name, packages=None,postcode=None): """获取指定物流公司的费用明细""" packages = self.set_parameter(packages, self.packages) postcode = self.set_parameter(postcode, self.postcode) if packages is None or postcode is None: raise ValueError("No packages or postcode provided") company_class = self.get_company_class(company_name) detail_amount = company_class.calculate_fee(packages,postcode) return detail_amount def convert_to_usd(self,amount,currency): """将货币转换为美元""" if currency == "USD": return amount elif currency == "EUR": # 欧元 return amount * 1.12 elif currency == "GBP": # 英镑 return amount * 1.3 elif currency == "AUD": # 澳元 return amount * 0.7 elif currency == "CAD": # 加元 return amount * 0.75 elif currency == "JPY": # 日元 return amount * 0.007 elif currency == "CNY": # 人民币 return amount * 0.14 elif currency == "HKD": # 港币 return amount * 0.13 def usd_to_currency(self,amount,currency): """将美元转换为指定货币""" if currency == "USD": return amount else: return amount / self.convert_to_usd(1,currency) def convert_currency(self,amount,current_currency,target_currency): """先转美元,再转目标货币""" if current_currency == "USD": return self.usd_to_currency(amount,target_currency) else: return self.usd_to_currency(self.convert_to_usd(amount,current_currency),target_currency)