{ "cells": [ { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# 根据订单号,查询实际包裹尺寸,实际包裹实重,实际包裹体积重,\n", "# bill账单给头程单价,实际尾端计费重,预估尾端成本,尾端附加费\n", "\n", "import os\n", "import re\n", "import pandas as pd\n", "from utils.Package import Package,Package_group\n", "from utils.gtools import MySQLconnect\n", "from utils.countryOperator import OperateCountry\n", "from utils.logisticsBill import BillFactory, Billing\n", "import requests\n", "import json\n", "ods = MySQLconnect(\"ods\")\n", "engine = ods.engine()\n", "def get_SKU_info(order_id):\n", " \"\"\"\n", " 根据订单号获取SKU信息,以及入库采购价\n", " \"\"\"\n", " SKULIST = \"\"\"\n", " SELECT\n", " order_id,\n", " CASE WHEN COUNT(DISTINCT opl.SKU) = 1 THEN \"单SKU\" ELSE \"多SKU\" end as \"SKU类型\",\n", " CONCAT(group_concat(opl.SKU),\",\") as \"SKU明细\",\n", " sum(s1.`成本价`*product_num) AS \"入库采购价\"\n", " FROM\n", " dws.order_product_list opl LEFT JOIN ods.stg_bayshop_litfad_sku s1 on s1.sku = opl.sku\n", " LEFT JOIN dwd.dim_erp_sku_package_vol_info des on des.erp_sku = opl.sku\n", " \n", " WHERE\n", " order_id = %s\n", " AND order_product_id regexp \"[0-9]{15}_[0-9]*$\"\n", " GROUP BY order_id \n", " \n", " \"\"\"\n", " engine = ods.engine()\n", " sku_df = pd.read_sql(SKULIST, engine,params=(order_id,))\n", " if sku_df.empty:\n", " return None,None,None\n", " # print(\"SKU类型:\",sku_df['SKU类型'][0],\"SKU明细:\",sku_df['SKU明细'][0],\"入库采购价:\",sku_df['入库采购价'][0])\n", " return sku_df['SKU类型'][0],sku_df['SKU明细'][0],sku_df['入库采购价'][0]\n", "\n", "def get_package_real_vol_by_api(packages_id):\n", " \"\"\"\n", " 根据订单号的包裹ID,返回包裹类,包裹明细,包裹实重,包裹体积重6000\n", " \"\"\"\n", " packages = Package_group()\n", " packages_str = \"\"\n", " packages_weight=0\n", " packages_vol = 0\n", " for package_id in packages_id:\n", " url = f'https://cp.baycheer.com/index.php?main=biphp&act=package_fund&key=W6BOYJ7BH27YCGRFCA0LWBVKMU1KRU5Q&package={package_id}'\n", " resp = requests.get(url).json()\n", " if resp['code'] == \"0\":\n", " weight = int(float(resp['data'][0]['weight'])*1000)\n", " package_length = resp['data'][0]['l'].replace(\",\",\"\") if len(resp['data'][0]['l'])>0 else \"0\"\n", " package_width = resp['data'][0]['w'].replace(\",\",\"\") if len(resp['data'][0]['w'])>0 else \"0\"\n", " package_hight = resp['data'][0]['h'].replace(\",\",\"\") if len(resp['data'][0]['h'])>0 else \"0\"\n", " package = Package(str(package_id),float(package_length),float(package_width),float(package_hight),weight)\n", " packages.add_package(package)\n", " # 实际包裹尺寸\n", " package_str = f\"{weight}|{package_length}*{package_width}*{package_hight}\"\n", " packages_str += package_str + \",\"\n", " return packages,packages_str\n", "\n", "def get_shiji_bill(opCountry,order_id,packages_id,postcode,convey,amount):\n", " # print(order_id)\n", " beizhu = amount\n", " conveys = 1 if convey == \"海运\" else 0\n", " try:\n", " packages,packages_str = get_package_real_vol_by_api(packages_id=packages_id)\n", " bill = Billing(str(order_id),opCountry,packages,postcode,company_name=None,head_type=conveys,beizhu=beizhu)\n", " print(bill)\n", " tail_amount = bill.bill_dict()[\"预测尾端\"]\n", " total_weight = sum([p.weight/1000 for p in packages.packages])\n", " _type = bill.bill_dict()[\"尾端渠道\"]\n", " head_amount = bill.bill_dict()[\"预测头程CNY\"]\n", " total_amount = bill.bill_dict()[\"总金额USD\"]\n", " volume_weight = bill.bill_dict()[\"体积重\"]\n", " per_head = bill.bill_dict()[\"头程单价\"]\n", " other_detail = bill.get_other_fee()\n", " return packages_str,total_weight,volume_weight,per_head,head_amount,tail_amount,other_detail,_type,total_amount\n", " except ZeroDivisionError as e:\n", " print(e)\n", " return \"\",0,0,0,0,0,\"\",\"\",0\n", "def get_package_info_by_sql(order_df):\n", " packages = Package_group()\n", " packages_str = \"\"\n", " for index, row in order_df.iterrows():\n", " if row['包裹数据'] is None:\n", " return None,\"\"\n", " row['包裹数据'] = json.loads(row['包裹数据'])\n", " item_list = [\n", " {key: float(re.search(r\"\\d+\\.?\\d*\", str(value)).group()) for key, value in package.items()}\n", " for package in row['包裹数据'].values()\n", "]\n", " for item in item_list:\n", " if item['长'] == 0 or item['宽'] == 0 or item['高'] == 0 or item['重量'] == 0:\n", " return None,\"\"\n", " package = Package(row['SKU'], item['长'], item['宽'], item['高'], item['重量'])\n", " packages.add_package(package)\n", " # 实际包裹尺寸\n", " package_str = f\"{ item['重量']}|{item['长']}*{ item['宽']}*{item['高']}\"\n", " packages_str += package_str + \",\"\n", " return packages,packages_str\n", "\n", "def get_biaozhun_bill(country,order_id,postcode,convey,amount):\n", " print(order_id)\n", " # 取标准包裹数据\n", " sql = \"\"\"SELECT\n", " order_id,\n", " opl.SKU,\n", " 包裹数据\n", " FROM\n", " dws.order_product_list opl\n", " LEFT JOIN ads.new_erp_sku_size spi ON opl.SKU =spi.SKU\n", " WHERE\n", " order_id = %s\n", " AND\n", " opl.order_product_id REGEXP \"[0-9]{15}_[0-9]*$\"\n", " \"\"\"\n", " order_package_date = pd.read_sql(sql, engine, params=(order_id,))\n", " print(order_package_date['SKU'])\n", " if order_package_date['包裹数据'] is None:\n", " return \"\",0,0,0,0,0,\"\",\"\"\n", " # 取账单数据\n", " beizhu = amount\n", " conveys = 1 if convey == \"海运\" else 0\n", " opCountry = OperateCountry(country)\n", " try:\n", " packages,packages_str = get_package_info_by_sql(order_package_date)\n", " if packages is None:\n", " return \"\",0,0,0,0,0,\"\",\"\"\n", " bill = Billing(str(order_id),opCountry,packages,postcode,company_name=None,head_type=conveys,beizhu=beizhu)\n", " print(bill)\n", " tail_amount = bill.bill_dict()[\"预测尾端\"]\n", " total_weight = sum([p.weight/1000 for p in packages.packages])\n", " _type = bill.bill_dict()[\"尾端渠道\"]\n", " head_amount = bill.bill_dict()[\"预测头程CNY\"]\n", " total_amount = bill.bill_dict()[\"总金额USD\"]\n", " volume_weight = bill.bill_dict()[\"体积重\"]\n", " per_head = bill.bill_dict()[\"头程单价\"]\n", " other_detail = bill.get_other_fee()\n", " return packages_str,total_weight,volume_weight,per_head,head_amount,tail_amount,other_detail,_type\n", " except ZeroDivisionError as e:\n", " print(e)\n", " return \"\",0,0,0,0,0,\"\",\"\"" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "sql = \"\"\"SELECT\n", " ol.order_id ,\n", " CONCAT(\"[\",GROUP_CONCAT(pr.包裹号),\"]\") AS package_group ,\n", " ol.postcode,\n", " ol.delivery_country,\n", " ol.convey,\n", "\t\t\t\tol.`currency`,\n", "\t\t\t\tol.`order_price`,\n", "\t\tIF( ol.payment_method IS NULL, ols.支付方式, ol.payment_method ) AS 支付方式,\n", " ol.order_price_dollar\n", " FROM\n", " parcel pr\n", " LEFT JOIN dwd.order_list ol ON ol.order_id = pr.订单号 \n", "\t\t\t\tleft JOIN ods.order_list_supplement ols ON ol.order_id = ols.订单号\n", " WHERE\n", " NOT EXISTS (\n", " SELECT\n", " 1 \n", " FROM\n", " `order_express` oe \n", " WHERE\n", " oe.包裹号 = pr.包裹号 \n", " AND oe.包裹状态 REGEXP \"作废|--\")\n", " AND order_id IN (251120212802039 \n", "\n", ")\n", " GROUP BY ol.order_id\n", "\"\"\"" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "251120212802039\n", "0 2200885770\n", "1 2201683904\n", "2 2201886758\n", "Name: SKU, dtype: int64\n", "账单名称: 251120212802039\n", "账单项:head_amount: 50.0 CNY base: 10.5 GBP transportation: 0.11 GBP fuel: 0.53 GBP tail_amount: 11.14 GBP 总金额: 21.482000000000003 USD\n", "账单名称: 251120212802039\n", "账单项:head_amount: 349.14 CNY base: 10.5 GBP transportation: 0.11 GBP fuel: 0.53 GBP tail_amount: 11.14 GBP 总金额: 63.3616 USD\n" ] } ], "source": [ "\n", "order_id_df = pd.read_sql(sql,engine)\n", "# SKU类型和SKU明细,以及入库采购价\n", "order_id_df[['订单SKU类型','订单SKU明细','入库采购价']] = order_id_df.apply(lambda x: get_SKU_info(x['order_id']), axis=1, result_type='expand')\n", "\n", "# 获取标准账单\n", "order_id_df[[\"标准包裹尺寸详情\",\"标准实重\",\"标准体积重\",\"标准头程单价\",\"标准头程费用(CNY)\",\"标准尾端费用(当地货币)\",\"标准尾端附加费\",\"标准尾端渠道\"]] = order_id_df.apply(lambda x: get_biaozhun_bill(\n", " x['delivery_country'],\n", " x['order_id'],\n", " x['postcode'], \n", " x['convey'],\n", " x['order_price_dollar']),axis=1,result_type='expand')\n", "# 获取实际采购价\n", "# order_id_df['实际采购价'] = order_id_df['order_id'].apply(lambda x: get_purchase_price(x))\n", "\n", "# 获取实际账单\n", "order_id_df[[\"实际包裹尺寸详情\",\"实际实重\",\"实际体积重\",\"实际头程单价\",\"实际头程费用(CNY)\",\"实际尾端费用(当地货币)\",\"实际尾端附加费\",\"实际尾端渠道\",\"总金额(USD)\"]] = order_id_df.apply(lambda x: get_shiji_bill(OperateCountry(x['delivery_country']),\n", " x['order_id'],\n", " eval(x['package_group']),\n", " x['postcode'], \n", " x['convey'],\n", " x['order_price_dollar']),axis=1,result_type='expand')\n", "\n", "order_id_df.to_clipboard()" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "order_id_df.to_clipboard()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 取订单号和包裹号\n", "sql = \"\"\"\n", "SELECT\n", " pr.包裹号,pr.订单号\n", " FROM\n", " parcel pr \t\n", " WHERE\n", " 订单号 IN (251120212802039 \n", "\n", ")\n", "\"\"\"\n", "package_df = pd.read_sql(sql,engine)\n", "package_df.to_clipboard(index=False)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from utils.gtools import MySQLconnect\n", "import pandas as pd\n", "import os\n", "# date = \"2025/3/5\"\n", "# 连接数据库\n", "ods = MySQLconnect(\"ods\")\n", "engine = ods.engine()\n", "\n", "# 读取 Excel 数据\n", "excel_path = r\"D:\\test\\logistics\\拦截数据\\拦截订单登记明细.xlsx\"\n", "order_df = pd.read_excel(excel_path, sheet_name=\"拦截明细\", skiprows=1)\n", "# 读取 Excel 数据时,指定 '订单号' 列为字符串类型\n", "order_df = pd.read_excel(excel_path, sheet_name=\"拦截明细\", skiprows=1, dtype={'订单号': str})\n", "# order_df = order_df[order_df['拦截计算日期'] == date]\n", "order_df = order_df[['订单号', '提交拦截申请时间']]\n", "\n", "# 提取订单号并转为字符串\n", "order_id = [str(x) for x in order_df[\"订单号\"].dropna()]\n", "\n", "if not order_id:\n", " print(\"没有符合条件的订单号,查询终止。\")\n", "else:\n", " try:\n", " # 生成占位符并执行查询\n", " placeholders = ', '.join(['%s'] * len(order_id))\n", " sql = f\"\"\"\n", " SELECT\n", " 单号,\n", " 包裹号,\n", " 包裹状态,\n", " 快递跟踪号,\n", " `关联卡板号`,\n", " 关联提单号,\n", " 打包时间,\n", " `快递公司` AS 打单渠道,\n", " `包裹测量时间`,\n", " 运单生成时间 AS 打单时间,\n", " 绑定卡板时间,\n", " 绑定提单时间,\n", " `提单发货时间`\n", " FROM\n", " ods.`order_express`\n", " WHERE\n", " 单号 IN ({placeholders})\n", " \"\"\"\n", " df = pd.read_sql(sql, engine, params=tuple(order_id))\n", "\n", " # 合并数据\n", " order_df[\"订单号\"] = order_df[\"订单号\"].astype(str)\n", " df[\"单号\"] = df[\"单号\"].astype(str)\n", " merged_df = df.merge(order_df, left_on=\"单号\", right_on=\"订单号\", how=\"left\")\n", " merged_df = merged_df.drop(columns=[\"订单号\"]) # 删除重复的 '订单号' 列\n", "\n", " # 重新排列列顺序\n", " merged_df = merged_df[[\n", " \"单号\",\n", " \"包裹号\",\n", " \"提交拦截申请时间\",\n", " \"包裹状态\",\n", " \"快递跟踪号\",\n", " \"关联卡板号\",\n", " \"关联提单号\",\n", " \"打包时间\",\n", " \"包裹测量时间\",\n", " \"打单时间\",\n", " \"打单渠道\",\n", " \"绑定卡板时间\",\n", " \"绑定提单时间\",\n", " \"提单发货时间\"\n", " ]]\n", "\n", " # 检查文件是否存在,并读取目标工作表\n", " if os.path.exists(excel_path):\n", " with pd.ExcelFile(excel_path) as xls:\n", " sheets = xls.sheet_names\n", " if \"包裹时间记录\" in sheets:\n", " existing_df = pd.read_excel(excel_path, sheet_name=\"包裹时间记录\")\n", " else:\n", " existing_df = pd.DataFrame(columns=merged_df.columns) # 如果表不存在,创建一个空 DataFrame\n", " else:\n", " existing_df = pd.DataFrame(columns=merged_df.columns) # 如果文件不存在,创建一个空 DataFrame\n", "\n", " # 过滤掉已存在的包裹号\n", " existing_package_ids = existing_df[\"包裹号\"].astype(str).tolist()\n", " new_data = merged_df[~merged_df[\"包裹号\"].astype(str).isin(existing_package_ids)]\n", "\n", " # 如果没有新数据,直接退出\n", " if new_data.empty:\n", " print(\"没有新数据需要追加。\")\n", " else:\n", " # 追加新数据\n", " \n", " combined_df = pd.concat([existing_df, new_data], ignore_index=True)\n", "\n", " # 写入 Excel(保留其他工作表)\n", " with pd.ExcelWriter(excel_path, engine='openpyxl', mode='a' if os.path.exists(excel_path) else 'w', if_sheet_exists='replace') as writer:\n", " combined_df.to_excel(writer, sheet_name=\"包裹时间记录\", index=False)\n", " print(\"数据已成功追加到工作表!\")\n", " \n", " except Exception as e:\n", " print(f\"操作失败,错误详情:{e}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 手动输入包裹的包裹信息\n", "from logisticsClass.logisticsTail_EUR import KPASLLogistics_FR\n", "from utils.Package import Package,Package_group\n", "from utils.gtools import MySQLconnect\n", "from utils.countryOperator import OperateCountry\n", "from utils.logisticsBill import BillFactory, Billing\n", "packages = Package_group()\n", "\n", "packages.add_package(Package(\"包裹1\", 50,50,14, 30000))\n", "# packages.add_package(Package(\"包裹1\", 125,109,16, 600000))\n", "# packages.add_package(Package(\"包裹1\",180 ,35,13, 17000))\n", "# packages.add_package(Package(\"包裹1\", 132,62,3, 6500))\n", "\n", "\n", "country = 'UK'\n", "postcode ='AB43 7JB'\n", "conveys= 0 # 1海运0空运\n", "\n", "\n", "opCountry = OperateCountry(country)\n", "bill = Billing(str(1),opCountry,packages,postcode,company_name=None,head_type=conveys,beizhu=\"1\")\n", "print(bill)\n", "tail_amount = bill.bill_dict()[\"预测尾端\"]\n", "total_weight = sum([p.weight/1000 for p in packages.packages])\n", "_type = bill.bill_dict()[\"尾端渠道\"]\n", "head_amount = bill.bill_dict()[\"预测头程CNY\"]\n", "total_amount = bill.bill_dict()[\"总金额USD\"]\n", "volume_weight = bill.bill_dict()[\"体积重\"]\n", "per_head = bill.bill_dict()[\"头程单价\"]\n", "other_detail = bill.items\n", "base_amount = [item.amount for item in other_detail if item.item_detail == \"base\"][0]\n", "\n", "packages_str = \"\"\n", "for package in packages.packages:\n", " package_str = f\"{package.weight}|{package.length}*{package.width}*{package.height}\"\n", " packages_str += package_str + \",\"\n", "print(f\"packages_str:{packages_str}\")\n", "print(f\"实重:{total_weight}\")\n", "print(f\"体积重:{volume_weight}\")\n", "print(f\"头程单价:{per_head}\")\n", "print(f\"预测头程CNY:{head_amount}\")\n", "print(f\"基础运费:{base_amount}\")\n", "print(f\"其他费用:{other_detail}\")\n", "print(f\"预测尾端(当地货币):{tail_amount}\")\n", "print(f\"尾端渠道:{_type}\")\n", "print(f\"总金额USD:{total_amount}\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "查找供应商退货退款金额" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np\n", "from utils.gtools import MySQLconnect\n", "ods = MySQLconnect('ods')\n", "engine = ods.engine()\n", "\n", "# 读取 Excel 数据\n", "excel_path = r\"D:\\test\\logistics\\拦截数据\\拦截订单登记明细.xlsx\"\n", "order_df = pd.read_excel(excel_path, sheet_name=\"拦截明细\", skiprows=1)\n", "# 读取 Excel 数据时,指定 '订单号' 列为字符串类型\n", "order_df = pd.read_excel(excel_path, sheet_name=\"拦截明细\", skiprows=1, dtype={'订单号': str})\n", "\n", "# 提取订单号并转为字符串\n", "order_id = [str(x) for x in order_df[\"订单号\"].dropna()]\n", "placeholders = ','.join(['%s'] * len(order_id))\n", "sql = f\"\"\"\n", "WITH\n", "t1 AS (\n", "SELECT\n", " -- 提取交易号\n", " TRIM(SUBSTRING(\n", " `外部关联信息`,\n", " LOCATE('交易号:', `外部关联信息`) + CHAR_LENGTH('交易号:'),\n", " CASE \n", " WHEN LOCATE('单品号:', `外部关联信息`) > 0\n", " THEN LOCATE('单品号:', `外部关联信息`) - LOCATE('交易号:', `外部关联信息`) - CHAR_LENGTH('交易号:')\n", " ELSE LOCATE('[', `外部关联信息`) - LOCATE('交易号:', `外部关联信息`) - CHAR_LENGTH('交易号:')\n", " END\n", " )) AS 交易号,\n", "\n", " -- 提取单品号(如果存在)\n", " CASE \n", " WHEN LOCATE('单品号:', `外部关联信息`) > 0 THEN\n", " TRIM(SUBSTRING(\n", " `外部关联信息`,\n", " LOCATE('单品号:', `外部关联信息`) + CHAR_LENGTH('单品号:'),\n", " LOCATE('[', `外部关联信息`) - LOCATE('单品号:', `外部关联信息`) - CHAR_LENGTH('单品号:')\n", " ))\n", " ELSE NULL\n", " END AS 单品号,\n", "\n", " `支付账号`,\n", " `处理金额`,\n", " `添加时间`,\n", " `资金状态`,\n", " `完成时间`,\n", " 备注\n", "\n", "FROM cpmaso_procurement_fund_manage\n", "WHERE `添加时间` >= DATE_SUB(NOW(), INTERVAL 8 MONTH)\n", ")\n", "SELECT\n", "LEFT(order_product_id,15) AS 订单号,\n", "\torder_product_id,\n", "\tbuy_audit AS 状态,\n", "\ttrans_pay_date AS 采购时间,\n", "\tlog_receiving_date AS 到货时间,\n", "\tt1.*\n", "FROM\n", "\t`warehouse_purchasing` wp\n", "LEFT JOIN t1 ON wp.trans_id = t1.交易号\n", "WHERE\n", "交易号>0 AND\n", "LEFT(wp.order_product_id,15) IN ({placeholders})\n", "ORDER BY 添加时间,订单号\n", "\"\"\"\n", "df = pd.read_sql(sql, engine,params=tuple(order_id))\n", "df.to_clipboard(index = False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "入库\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np\n", "from sqlalchemy import text\n", "from utils.gtools import MySQLconnect\n", "ods = MySQLconnect('ods')\n", "engine = ods.engine()\n", "\n", "# 读取 Excel 数据\n", "excel_path = r\"D:\\test\\logistics\\拦截数据\\拦截订单登记明细.xlsx\"\n", "# 读取 Excel 数据时,指定 '订单号' 列为字符串类型\n", "order_df = pd.read_excel(excel_path, sheet_name=\"拦截明细\", skiprows=1, dtype={'订单号': str})\n", "\n", "# 提取订单号并转为字符串\n", "order_id = df['订单号'].astype(str).tolist()\n", "\n", "\n", "bind_names = [f\":p{i}\" for i in range(len(order_id))]\n", "placeholders = ', '.join(bind_names)\n", "\n", "sql = text(f\"\"\"\n", "SELECT\n", "REGEXP_SUBSTR(note, '[0-9]{{15}}') AS 订单号,\n", "stock_in_id AS `入库单号`,\n", "instock_date AS `入库时间`\n", "FROM stockinid_list\n", "WHERE note REGEXP '[0-9]{{15}}_'\n", "AND REGEXP_SUBSTR(note, '[0-9]{{15}}') IN ({placeholders})\n", "\"\"\")\n", "\n", "params = {f\"p{i}\": v for i, v in enumerate(order_id)}\n", "df = pd.read_sql(sql, engine, params=params)\n", "df.to_clipboard(index = False)" ] } ], "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 }