2025-06-17 13:40:20 +08:00
{
"cells": [
{
"cell_type": "code",
2025-06-23 16:08:03 +08:00
"execution_count": null,
2025-06-17 13:40:20 +08:00
"metadata": {},
"outputs": [],
"source": [
"from utils.gtools import MySQLconnect\n",
"import pandas as pd\n",
"ads = MySQLconnect('ads')\n",
"engine = ads.engine()\n",
"conn = ads.connect()\n",
"# sql = \"\"\" SELECT\n",
"# sku.SKU,\n",
"# 包裹数据,\n",
"# 成本价\n",
"# FROM\n",
"# ods.`stg_bayshop_litfad_sku` sku\n",
"# LEFT JOIN ads.new_erp_sku_size size ON sku.SKU=size.SKU\n",
"# \t\t\t\t\t\t\t WHERE sku.状态 = \"启用\"\n",
"# \t\t\t\t\t\t\t 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\"\n",
"# \"\"\"\n",
"# df = pd.read_sql(sql, conn)"
]
},
2025-06-23 16:08:03 +08:00
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 计算售价\n",
"\n",
"\n",
"from sell.sell_price import call_sell_and_order_price\n",
"import json\n",
"import pandas as pd\n",
"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\"]\n",
"\n",
"def cal_sell_price(df):\n",
" \"\"\"\n",
" 计算所有SKU的售价,物流分摊费\n",
" \"\"\"\n",
" for index, row in df.iterrows():\n",
" try:\n",
" package_dict = json.loads(row['包裹数据'])\n",
" sell_price,order_price,order_type = call_sell_and_order_price(row['成本价'], package_dict)\n",
" except Exception as e:\n",
" print(f\" {row['SKU']} 报错: {e}\")\n",
" continue\n",
" df.loc[index, '售价'] = sell_price\n",
" df.loc[index, '物流分摊费'] = order_price\n",
" df.loc[index, '物流类型'] = order_type\n",
" # print(f\"sku:{row['SKU']},售价:{sell_price},物流分摊费:{order_price},物流类型:{order_type}\")\n",
" return df\n",
"for date in DATE_LIST:\n",
" sql = f\"\"\" SELECT\n",
"\tsku.SKU,\n",
"\t包裹数据,\n",
"\t成本价,\n",
"\t产品售价,\n",
"\t`产品品类`,\n",
"\t`产品分类` \n",
"FROM\n",
"\tods.`stg_bayshop_litfad_sku` sku\n",
"\tLEFT JOIN ads.new_erp_sku_size size ON sku.SKU = size.SKU \n",
"\tLEFT JOIN ods.stg_bayshop_litfad_spu spu ON sku.`产品PID` =spu.`产品PID`\n",
"WHERE\n",
"\tsku.状态 = \"启用\" \n",
"\tAND spu.`产品品类` REGEXP \"66\"\n",
"\tAND spu.`状态` =\"正常销售\"\n",
"\tAND DATE_FORMAT( sku.添加时间, \"%Y-%m-01\" )= \"{date}\"\n",
" \"\"\"\n",
" df = pd.read_sql(sql, conn)\n",
" df1 = cal_sell_price(df)\n",
" df1.to_excel(f'售价_{date}.xlsx', index=False)\n",
" print(f\"日期:{date}, 售价计算完成\")\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
2025-11-26 14:34:04 +08:00
"美国2025版订单物流费\n"
2025-06-23 16:08:03 +08:00
]
},
{
"cell_type": "code",
2025-11-26 14:34:04 +08:00
"execution_count": null,
2025-06-23 16:08:03 +08:00
"metadata": {},
"outputs": [],
"source": [
"\n",
"\n",
"import math\n",
"\n",
"import pandas as pd\n",
"\n",
"from utils.gtools import MySQLconnect\n",
"mat = MySQLconnect('mat')\n",
"engine = mat.engine()\n",
"df1 = pd.read_sql('select * from fedex2_0814', engine)\n",
"import math\n",
"# 美国海运订单费用,返回单个sku的订单费用和订单类型\n",
"def us_ocean_order_price(packages):\n",
2025-11-26 14:34:04 +08:00
" return ocean_order_price(packages)\n"
2025-06-23 16:08:03 +08:00
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
2025-11-26 14:34:04 +08:00
"英国2024版订单物流费"
2025-06-23 16:08:03 +08:00
]
},
{
"cell_type": "code",
2025-11-26 14:34:04 +08:00
"execution_count": null,
2025-06-23 16:08:03 +08:00
"metadata": {},
"outputs": [],
"source": [
"# 英国海运订单费用,返回单个sku的订单费用和订单类型\n",
"def uk_ocean_order_price(packages):\n",
" # 计算uk经济直达费用\n",
" order_fee = 0\n",
" express_fee = 0\n",
" order_type1 = '' # 订单类型\n",
" ltl_fee = 0\n",
" if packages is None or len(packages) == 0:\n",
" return 0, '包裹数为0'\n",
" num = len(packages)\n",
" if num > 30:\n",
" return 0, '包裹数超过30'\n",
" for package in packages:\n",
" base_fee = 0\n",
" other_fee1 = 0\n",
" other_fee2 = 0\n",
" girth = package.girth\n",
" if package.fst_size <= 90 and package.sed_size <= 50 and package.trd_size <= 50 and package.weight <= 29000:\n",
" base_fee = 2.5\n",
" elif package.fst_size <= 165 and package.weight <= 39000:\n",
" base_fee = 4.5\n",
" if package.weight >= 29000:\n",
" other_fee1 = 17.8 # 超重费\n",
" order_type1 += '超重'\n",
" if package.fst_size > 95 or package.sed_size > 55 or package.trd_size > 55:\n",
" other_fee2 = 12.7 # 超长费\n",
" order_type1 += '超长'\n",
" elif package.fst_size <= 290 and package.weight <= 69000 and girth <= 410:\n",
" if package.weight <= 29000:\n",
" base_fee = (7 * 9 / 7) / 0.45\n",
" elif 29000 < package.weight <= 49000:\n",
" base_fee = (17.5 * 9 / 7) / 0.45\n",
" elif 49000 < package.weight <= 69000:\n",
" base_fee = (28 * 9 / 7) / 0.45\n",
" order_type1 += '大包裹'\n",
" else:\n",
" base_fee = 999999\n",
" express_fee += (base_fee + other_fee1 + other_fee2)\n",
" express_fee = round(express_fee, 2)\n",
"\n",
" # 卡派 主计费实重,辅计费抛重\n",
" order_type2 = '卡派'\n",
" sku_total_cubic_feet = 0\n",
" for package in packages:\n",
" cubic_feet= package.length * package.width * package.height / 6000\n",
" sku_total_cubic_feet += cubic_feet\n",
" if package.length >310:\n",
" return 999999,'包裹超尺寸'\n",
" ltl_fee = max(151/0.45 - 2.4 /7 * sku_total_cubic_feet,2.5) \n",
"\n",
" if express_fee <= ltl_fee:\n",
" order_fee = express_fee\n",
" order_type = order_type1\n",
" else:\n",
" order_fee = ltl_fee\n",
" order_type = order_type2\n",
" return round(order_fee,2), order_type\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"计算2024版本售价"
]
},
2025-06-17 13:40:20 +08:00
{
"cell_type": "code",
2025-11-26 14:34:04 +08:00
"execution_count": null,
2025-06-17 13:40:20 +08:00
"metadata": {},
2025-06-23 16:08:03 +08:00
"outputs": [],
"source": [
"from utils.Package import Package, Package_group\n",
"from sell.base_sell_price import SellPriceBase\n",
"import re\n",
"import json\n",
"def call_sell_price(price, packages):\n",
" if packages is None:\n",
" return 0\n",
" litfad = SellPriceBase.litfad(packages, price,1)\n",
" # 修改版本,网站售价\n",
" sell_price = litfad.cal_sell_price()\n",
2025-11-26 14:34:04 +08:00
" return sell_price[0]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from utils.gtools import MySQLconnect\n",
"from tqdm import tqdm\n",
"import pandas as pd\n",
"from utils.Package import Package, Package_group\n",
"import json\n",
"import re\n",
"from concurrent.futures import ThreadPoolExecutor\n",
"def to_package(package_data):\n",
" packages = Package_group()\n",
" def extract_number(value):\n",
" # 提取字符串中的第一个数字\n",
" match = re.search(r\"[-+]?\\d*\\.\\d+|\\d+\", str(value))\n",
" return float(match.group()) if match else 0.0\n",
" package_dict = json.loads(package_data)\n",
" for key, package in package_dict.items():\n",
" package['长'] = extract_number(package['长'])\n",
" package['宽'] = extract_number(package['宽'])\n",
" package['高'] = extract_number(package['高'])\n",
" package['重量'] = extract_number(package['重量'])\n",
" \n",
" if package['长'] == 0 or package['宽'] == 0 or package['高'] == 0 or package['重量'] == 0:\n",
" return None\n",
" packages.add_package(Package(key,package['长'], package['宽'], package['高'], package['重量']))\n",
" return package_dict\n",
"\n",
"from utils.countryOperator import OperateCountry\n",
"from utils.logisticsBill import Billing\n",
"from sell.sell_price import call_sell_price_2025, ocean_order_price\n",
"from sell.logistic_price.uk_price import uk_ocean_order_price\n",
"from sell.logistic_price.jp_price import jp_order_yamato\n",
"\n",
"if __name__ == '__main__':\n",
" sql = \"\"\"SELECT\n",
"\t* ,\n",
"\tsku.`成本价`\n",
" FROM\n",
" dwd.dim_erp_sku_package_vol_info t1 \n",
" LEFT JOIN ods.stg_bayshop_litfad_sku sku ON t1.erp_sku = sku.SKU\n",
" WHERE\n",
" NOT EXISTS ( SELECT 1 FROM ads.sku_order_compare t2 WHERE t1.erp_sku = t2.SKU ) \n",
" AND id >= %s \n",
" AND id <= %s\n",
" AND `状态` = '启用'\"\"\"\n",
" au_opCountry = OperateCountry(\"AU\")\n",
" fr_opCountry = OperateCountry('FR')\n",
" de_opCountry = OperateCountry('DE')\n",
" es_opCountry = OperateCountry('ES')\n",
" it_opCountry = OperateCountry('IT')\n",
" with MySQLconnect('ads') as db:\n",
" for i in tqdm(range(0,150)):\n",
" print(i,\"开始\")\n",
" dfsql = sql % (i*100000, (i+1)*100000-1)\n",
" df = pd.read_sql(dfsql, db.engine())\n",
" if len(df) == 0:\n",
" continue\n",
" # 包裹数据格式化\n",
" df['erp_package_vol'] = df.apply(lambda x: to_package(x['erp_package_vol']), axis=1)\n",
" # df['售价'] = df.apply(lambda x: call_sell_and_order_price(x['成本价'], x['erp_package_vol'], \"海运\")[0], axis=1)\n",
" # df[['美国海运','美国海运类型']] = df.apply(lambda x: us_ocean_order_price(x['erp_package_vol']), axis=1, result_type='expand')\n",
" # df[['英国海运','英国海运类型']] = df.apply(lambda x: uk_ocean_order_price(x['erp_package_vol']), axis=1, result_type='expand')\n",
" \n",
" \n",
" def process_row(x):\n",
" # 单行处理逻辑\n",
" try:\n",
"\n",
" sell_price=x['产品售价']\n",
" logitcs = x['物流分摊']\n",
" # print(\"售价计算完成\")\n",
" us_price, us_type = ocean_order_price(x['erp_package_vol'])\n",
" # print(\"美国海运计算完成\")\n",
" uk_price, uk_type = uk_ocean_order_price(x['erp_package_vol'],logitcs)\n",
" jp_price,jp_type = jp_order_yamato(x['erp_package_vol'], sell_price)\n",
" # print(\"英国海运计算完成\")\n",
" if x['erp_sku'] ==\"2207384162\":\n",
" au_price2 = Billing(\"1\",au_opCountry,x['erp_package_vol'],\"2911\",company_name=None,head_type=1,beizhu='1').tail_amount[0]\n",
" print(au_price2)\n",
" au_price = Billing(\"1\",au_opCountry,x['erp_package_vol'],\"2911\",company_name=None,head_type=1,beizhu='1').tail_amount[0]\n",
" fr_price = Billing(\"1\",fr_opCountry,x['erp_package_vol'],\"75000\",company_name=None,head_type=1,beizhu='1').tail_amount[0]\n",
" de_price = Billing(\"1\",de_opCountry,x['erp_package_vol'],\"12489\",company_name=None,head_type=1,beizhu='1').tail_amount[0]\n",
" es_price = Billing(\"1\",es_opCountry,x['erp_package_vol'],\"28002\",company_name=None,head_type=1,beizhu='1').tail_amount[0]\n",
" it_price = Billing(\"1\",it_opCountry,x['erp_package_vol'],\"20143\",company_name=None,head_type=1,beizhu='1').tail_amount[0]\n",
" 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]\n",
" except Exception as e:\n",
" return [None, None, None, None, None,None, None, None, None, None,None, None]\n",
"\n",
" # 用 dict 更稳妥\n",
" rows = df.to_dict(orient='records') # 转为 list of dict\n",
" with ThreadPoolExecutor(max_workers=50) as executor:\n",
" results = list(executor.map(process_row, rows))\n",
" # 组装结果\n",
" result_df = pd.DataFrame(results, columns=['售价', '美国海运', '美国海运类型', '英国海运', '英国海运类型','日本','日本类型','澳洲','法国Zone4','德国Zone2','西班牙','意大利'])\n",
" df = pd.concat([df.reset_index(drop=True), result_df], axis=1)\n",
"\n",
" # 清空临时表\n",
" db.cur.execute(\"TRUNCATE TABLE ads.temp_sku_order_compare;\")\n",
" print(\"临时表清空完成\")\n",
"\n",
" # 组装需要输出的字段\n",
" df = df.rename(columns={\n",
" 'erp_package_vol':'包裹数据'\n",
" })\n",
"\n",
" columns_needed = ['SKU', '售价','包裹数据', '美国海运', '美国海运类型', '英国海运', '英国海运类型','日本','日本类型','澳洲','法国Zone4','德国Zone2','西班牙','意大利']\n",
" df_out = df[columns_needed]\n",
" # 写入当前批次数据\n",
" df_out.to_sql(\n",
" \"temp_sku_order_compare\",\n",
" db.eng,\n",
" if_exists='append',\n",
" index=False,\n",
" method='multi',\n",
" chunksize=500 # 分批写入\n",
" )\n",
"\n",
" print(\"当前批次数据写入完成\")\n",
" # 更新主表\n",
" update_sql = \"\"\"\n",
" REPLACE INTO ads.sku_order_compare SELECT * FROM ads.temp_sku_order_compare\n",
" \"\"\"\n",
" db.cur.execute(update_sql)\n",
" print(\"主表更新完成\")\n",
" db.con.commit()\n",
" print(i,\"结束\")"
2025-06-23 16:08:03 +08:00
]
},
{
"cell_type": "code",
2025-11-26 14:34:04 +08:00
"execution_count": 2,
2025-06-23 16:08:03 +08:00
"metadata": {},
2025-06-17 13:40:20 +08:00
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
2025-11-26 14:34:04 +08:00
"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.\n",
" df = pd.read_sql(sql, conn)\n"
2025-06-23 16:08:03 +08:00
]
}
],
"source": [
2025-11-26 14:34:04 +08:00
"from utils.countryOperator import OperateCountry\n",
"from utils.logisticsBill import Billing,BillFactory\n",
2025-06-23 16:08:03 +08:00
"from utils.gtools import MySQLconnect\n",
"from tqdm import tqdm\n",
"import pandas as pd\n",
2025-11-26 14:34:04 +08:00
"from utils.Package import Package, Package_group\n",
"sql = \"\"\"\n",
"SELECT\n",
"\torder_id,\n",
"\tpostcode,\n",
"\tpackage,\n",
"\tlength,\n",
"\twidth,\n",
"\thight,\n",
"\tweight\n",
"FROM\n",
"\torder_list ol LEFT JOIN parcel ON ol.order_id = parcel.订单号\n",
"\tLEFT JOIN package_vol_info pvi ON parcel.`包裹号` = pvi.package\n",
"WHERE\n",
"site_name = \"Litfad\"\n",
"AND delivery_country REGEXP \"United Kingdom\"\n",
"AND order_date >=\"2025-03-01\"\n",
"AND fund_status NOT REGEXP \"等待\"\n",
"AND length>0\n",
"AND weight>0\n",
2025-06-23 16:08:03 +08:00
"\n",
2025-11-26 14:34:04 +08:00
"\"\"\"\n",
"with MySQLconnect('ods') as db:\n",
" conn = db.connect()\n",
" df = pd.read_sql(sql, conn)\n",
2025-06-23 16:08:03 +08:00
"\n",
2025-11-26 14:34:04 +08:00
"df_group = df.groupby(['order_id'])\n",
"opCountry = OperateCountry(\"UK\")\n",
"bills = BillFactory()\n",
"index = 0\n",
"for order_id, group in df_group:\n",
" index+=1\n",
" packages = Package_group()\n",
" postcode= group['postcode'].iloc[0]\n",
" for i, row in group.iterrows():\n",
" package = Package(row['package'], row['length'], row['width'], row['hight'], row['weight'])\n",
" packages.add_package(package)\n",
" bill = bills.create_bill(\"1\",opCountry,packages,postcode,company_name=\"智谷-DPD\",head_type=1,beizhu=index)\n",
" bills.add_bill(bill)\n",
"df_bill = bills.bills_to_df()\n",
2025-06-23 16:08:03 +08:00
" \n",
2025-11-26 14:34:04 +08:00
"df_bill.to_excel(\"英国账单.xlsx\")\n",
" "
2025-06-17 13:40:20 +08:00
]
}
],
"metadata": {
"kernelspec": {
"display_name": "base",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}