logistics/cal_sell_price.ipynb

18 KiB

In [ ]:
from utils.gtools import MySQLconnect
import pandas as pd
ads = MySQLconnect('ads')
engine = ads.engine()
conn = ads.connect()
# sql = """   SELECT
#                 sku.SKU,
#                 包裹数据,
#                 成本价
#             FROM
#                 ods.`stg_bayshop_litfad_sku` sku
#                 LEFT JOIN ads.new_erp_sku_size size ON sku.SKU=size.SKU
# 							 WHERE sku.状态 = "启用"
# 							 AND EXISTS (SELECT 1 FROM ods.stg_bayshop_litfad_spu s1 where s1.`产品PID` = sku.`产品PID`  AND s1.状态 = "正常销售" and s1.`产品分类` regexp "light")  AND sku.添加时间 >="2024-01-01"
# """
# df = pd.read_sql(sql, conn)
In [ ]:
# 计算售价


from sell.sell_price import call_sell_and_order_price
import json
import pandas as pd
DATE_LIST =     ["2024-01-01","2024-02-01","2024-03-01","2024-04-01","2024-05-01","2024-06-01","2024-07-01","2024-08-01","2024-09-01","2024-10-01","2024-11-01","2024-12-01","2025-01-01","2025-02-01","2025-03-01"]

def cal_sell_price(df):
    """
    计算所有SKU的售价,物流分摊费
    """
    for index, row in df.iterrows():
        try:
            package_dict = json.loads(row['包裹数据'])
            sell_price,order_price,order_type = call_sell_and_order_price(row['成本价'], package_dict)
        except Exception as e:
            print(f" {row['SKU']} 报错: {e}")
            continue
        df.loc[index, '售价'] = sell_price
        df.loc[index, '物流分摊费'] = order_price
        df.loc[index, '物流类型'] = order_type
        # print(f"sku:{row['SKU']},售价:{sell_price},物流分摊费:{order_price},物流类型:{order_type}")
    return df
for date in DATE_LIST:
    sql = f"""   SELECT
	sku.SKU,
	包裹数据,
	成本价,
	产品售价,
	`产品品类`,
	`产品分类` 
FROM
	ods.`stg_bayshop_litfad_sku` sku
	LEFT JOIN ads.new_erp_sku_size size ON sku.SKU = size.SKU 
	LEFT JOIN ods.stg_bayshop_litfad_spu spu ON sku.`产品PID` =spu.`产品PID`
WHERE
	sku.状态 = "启用" 
	AND spu.`产品品类` REGEXP "66"
	AND spu.`状态` ="正常销售"
	AND DATE_FORMAT( sku.添加时间, "%Y-%m-01" )= "{date}"
    """
    df = pd.read_sql(sql, conn)
    df1 = cal_sell_price(df)
    df1.to_excel(f'售价_{date}.xlsx', index=False)
    print(f"日期:{date}, 售价计算完成")

美国2025版订单物流费

In [ ]:
import math

import pandas as pd

from utils.gtools import MySQLconnect
mat = MySQLconnect('mat')
engine = mat.engine()
df1 = pd.read_sql('select * from fedex2_0814', engine)
import math
# 美国海运订单费用,返回单个sku的订单费用和订单类型
def us_ocean_order_price(packages):
    return ocean_order_price(packages)

英国2024版订单物流费

In [ ]:
# 英国海运订单费用,返回单个sku的订单费用和订单类型
def uk_ocean_order_price(packages):
    # 计算uk经济直达费用
    order_fee = 0
    express_fee = 0
    order_type1 = ''  # 订单类型
    ltl_fee = 0
    if packages is None or len(packages) == 0:
        return 0, '包裹数为0'
    num = len(packages)
    if num > 30:
        return 0, '包裹数超过30'
    for package in packages:
        base_fee = 0
        other_fee1 = 0
        other_fee2 = 0
        girth = package.girth
        if package.fst_size <= 90 and package.sed_size <= 50 and package.trd_size <= 50 and package.weight <= 29000:
            base_fee = 2.5
        elif package.fst_size <= 165 and package.weight <= 39000:
            base_fee = 4.5
            if package.weight >= 29000:
                other_fee1 = 17.8  # 超重费
                order_type1 += '超重'
            if package.fst_size > 95 or package.sed_size > 55 or package.trd_size > 55:
                other_fee2 = 12.7  # 超长费
                order_type1 += '超长'
        elif package.fst_size <= 290 and package.weight <= 69000 and girth <= 410:
            if package.weight <= 29000:
                base_fee = (7 * 9 / 7) / 0.45
            elif 29000 < package.weight <= 49000:
                base_fee = (17.5 * 9 / 7) / 0.45
            elif 49000 < package.weight <= 69000:
                base_fee = (28 * 9 / 7) / 0.45
            order_type1 += '大包裹'
        else:
            base_fee = 999999
        express_fee += (base_fee + other_fee1 + other_fee2)
    express_fee = round(express_fee, 2)

    # 卡派 主计费实重,辅计费抛重
    order_type2 = '卡派'
    sku_total_cubic_feet = 0
    for package in packages:
        cubic_feet= package.length * package.width * package.height / 6000
        sku_total_cubic_feet += cubic_feet
        if package.length >310:
            return 999999,'包裹超尺寸'
    ltl_fee = max(151/0.45 - 2.4 /7 * sku_total_cubic_feet,2.5) 

    if express_fee <= ltl_fee:
        order_fee = express_fee
        order_type = order_type1
    else:
        order_fee = ltl_fee
        order_type = order_type2
    return round(order_fee,2), order_type

计算2024版本售价

In [ ]:
from utils.Package import Package, Package_group
from sell.base_sell_price import SellPriceBase
import re
import json
def call_sell_price(price, packages):
    if packages is None:
        return 0
    litfad = SellPriceBase.litfad(packages, price,1)
    # 修改版本,网站售价
    sell_price = litfad.cal_sell_price()
    return sell_price[0]
In [ ]:
from utils.gtools import MySQLconnect
from tqdm import tqdm
import pandas as pd
from utils.Package import Package, Package_group
import json
import re
from concurrent.futures import ThreadPoolExecutor
def to_package(package_data):
    packages = Package_group()
    def extract_number(value):
    # 提取字符串中的第一个数字
        match = re.search(r"[-+]?\d*\.\d+|\d+", str(value))
        return float(match.group()) if match else 0.0
    package_dict = json.loads(package_data)
    for key, package in package_dict.items():
        package['长'] = extract_number(package['长'])
        package['宽'] = extract_number(package['宽'])
        package['高'] = extract_number(package['高'])
        package['重量'] = extract_number(package['重量'])
    
        if package['长'] == 0 or package['宽'] == 0 or package['高'] == 0 or package['重量'] == 0:
            return None
        packages.add_package(Package(key,package['长'], package['宽'], package['高'], package['重量']))
    return package_dict

from utils.countryOperator import OperateCountry
from utils.logisticsBill import Billing
from sell.sell_price import call_sell_price_2025, ocean_order_price
from sell.logistic_price.uk_price import uk_ocean_order_price
from sell.logistic_price.jp_price import jp_order_yamato

if __name__ == '__main__':
    sql = """SELECT
	* ,
	sku.`成本价`
        FROM
            dwd.dim_erp_sku_package_vol_info t1 
            LEFT JOIN ods.stg_bayshop_litfad_sku sku ON t1.erp_sku = sku.SKU
        WHERE
            NOT EXISTS ( SELECT 1 FROM ads.sku_order_compare t2 WHERE t1.erp_sku = t2.SKU ) 
            AND id >= %s 
            AND id <= %s
            AND `状态` = '启用'"""
    au_opCountry = OperateCountry("AU")
    fr_opCountry = OperateCountry('FR')
    de_opCountry = OperateCountry('DE')
    es_opCountry = OperateCountry('ES')
    it_opCountry = OperateCountry('IT')
    with MySQLconnect('ads') as db:
        for i in tqdm(range(0,150)):
            print(i,"开始")
            dfsql = sql % (i*100000, (i+1)*100000-1)
            df = pd.read_sql(dfsql, db.engine())
            if len(df) == 0:
                continue
            # 包裹数据格式化
            df['erp_package_vol'] = df.apply(lambda x: to_package(x['erp_package_vol']), axis=1)
            # df['售价'] = df.apply(lambda x: call_sell_and_order_price(x['成本价'], x['erp_package_vol'], "海运")[0], axis=1)
            # df[['美国海运','美国海运类型']] = df.apply(lambda x: us_ocean_order_price(x['erp_package_vol']), axis=1, result_type='expand')
            # df[['英国海运','英国海运类型']] = df.apply(lambda x: uk_ocean_order_price(x['erp_package_vol']), axis=1, result_type='expand')
            
            
            def process_row(x):
                # 单行处理逻辑
                try:

                    sell_price=x['产品售价']
                    logitcs = x['物流分摊']
                    # print("售价计算完成")
                    us_price, us_type = ocean_order_price(x['erp_package_vol'])
                    # print("美国海运计算完成")
                    uk_price, uk_type = uk_ocean_order_price(x['erp_package_vol'],logitcs)
                    jp_price,jp_type = jp_order_yamato(x['erp_package_vol'], sell_price)
                    # print("英国海运计算完成")
                    if x['erp_sku'] =="2207384162":
                        au_price2 = Billing("1",au_opCountry,x['erp_package_vol'],"2911",company_name=None,head_type=1,beizhu='1').tail_amount[0]
                        print(au_price2)
                    au_price = Billing("1",au_opCountry,x['erp_package_vol'],"2911",company_name=None,head_type=1,beizhu='1').tail_amount[0]
                    fr_price = Billing("1",fr_opCountry,x['erp_package_vol'],"75000",company_name=None,head_type=1,beizhu='1').tail_amount[0]
                    de_price = Billing("1",de_opCountry,x['erp_package_vol'],"12489",company_name=None,head_type=1,beizhu='1').tail_amount[0]
                    es_price = Billing("1",es_opCountry,x['erp_package_vol'],"28002",company_name=None,head_type=1,beizhu='1').tail_amount[0]
                    it_price = Billing("1",it_opCountry,x['erp_package_vol'],"20143",company_name=None,head_type=1,beizhu='1').tail_amount[0]
                    return [round(sell_price, 2), us_price, us_type, uk_price, uk_type,jp_price,jp_type,au_price,fr_price,de_price,es_price,it_price]
                except Exception as e:
                    return [None, None, None, None, None,None, None, None, None, None,None, None]

            # 用 dict 更稳妥
            rows = df.to_dict(orient='records')  # 转为 list of dict
            with ThreadPoolExecutor(max_workers=50) as executor:
                results = list(executor.map(process_row, rows))
            # 组装结果
            result_df = pd.DataFrame(results, columns=['售价', '美国海运', '美国海运类型', '英国海运', '英国海运类型','日本','日本类型','澳洲','法国Zone4','德国Zone2','西班牙','意大利'])
            df = pd.concat([df.reset_index(drop=True), result_df], axis=1)

            # 清空临时表
            db.cur.execute("TRUNCATE TABLE ads.temp_sku_order_compare;")
            print("临时表清空完成")

            # 组装需要输出的字段
            df = df.rename(columns={
                'erp_package_vol':'包裹数据'
            })

            columns_needed = ['SKU', '售价','包裹数据',  '美国海运', '美国海运类型', '英国海运', '英国海运类型','日本','日本类型','澳洲','法国Zone4','德国Zone2','西班牙','意大利']
            df_out = df[columns_needed]
            # 写入当前批次数据
            df_out.to_sql(
                "temp_sku_order_compare",
                db.eng,
                if_exists='append',
                index=False,
                method='multi',
                chunksize=500  # 分批写入
            )

            print("当前批次数据写入完成")
            # 更新主表
            update_sql = """
            REPLACE INTO ads.sku_order_compare SELECT * FROM ads.temp_sku_order_compare
            """
            db.cur.execute(update_sql)
            print("主表更新完成")
            db.con.commit()
            print(i,"结束")
In [2]:
from utils.countryOperator import OperateCountry
from utils.logisticsBill import Billing,BillFactory
from utils.gtools import MySQLconnect
from tqdm import tqdm
import pandas as pd
from utils.Package import Package, Package_group
sql = """
SELECT
	order_id,
	postcode,
	package,
	length,
	width,
	hight,
	weight
FROM
	order_list ol LEFT JOIN parcel ON ol.order_id = parcel.订单号
	LEFT JOIN package_vol_info pvi ON parcel.`包裹号` = pvi.package
WHERE
site_name = "Litfad"
AND delivery_country REGEXP "United Kingdom"
AND order_date >="2025-03-01"
AND fund_status NOT REGEXP "等待"
AND length>0
AND weight>0

"""
with MySQLconnect('ods') as db:
    conn = db.connect()
    df = pd.read_sql(sql, conn)

df_group = df.groupby(['order_id'])
opCountry = OperateCountry("UK")
bills = BillFactory()
index = 0
for order_id, group in df_group:
    index+=1
    packages = Package_group()
    postcode= group['postcode'].iloc[0]
    for i, row in group.iterrows():
        package = Package(row['package'], row['length'], row['width'], row['hight'], row['weight'])
        packages.add_package(package)
    bill = bills.create_bill("1",opCountry,packages,postcode,company_name="智谷-DPD",head_type=1,beizhu=index)
    bills.add_bill(bill)
df_bill = bills.bills_to_df()
    
df_bill.to_excel("英国账单.xlsx")
C:\Users\Admin\AppData\Local\Temp\ipykernel_27996\1408839972.py:30: UserWarning: pandas only supports SQLAlchemy connectable (engine/connection) or database string URI or sqlite3 DBAPI2 connection. Other DBAPI2 objects are not tested. Please consider using SQLAlchemy.
  df = pd.read_sql(sql, conn)