429 lines
18 KiB
Plaintext
429 lines
18 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"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)"
|
|
]
|
|
},
|
|
{
|
|
"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版订单物流费\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"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",
|
|
" return ocean_order_price(packages)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"英国2024版订单物流费"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"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版本售价"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"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",
|
|
" 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,\"结束\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"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"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from utils.countryOperator import OperateCountry\n",
|
|
"from utils.logisticsBill import Billing,BillFactory\n",
|
|
"from utils.gtools import MySQLconnect\n",
|
|
"from tqdm import tqdm\n",
|
|
"import pandas as pd\n",
|
|
"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",
|
|
"\n",
|
|
"\"\"\"\n",
|
|
"with MySQLconnect('ods') as db:\n",
|
|
" conn = db.connect()\n",
|
|
" df = pd.read_sql(sql, conn)\n",
|
|
"\n",
|
|
"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",
|
|
" \n",
|
|
"df_bill.to_excel(\"英国账单.xlsx\")\n",
|
|
" "
|
|
]
|
|
}
|
|
],
|
|
"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
|
|
}
|