logistics/拦截订单详细数据.ipynb

25 KiB
Raw Blame History

In [3]:
# 根据订单号,查询实际包裹尺寸,实际包裹实重,实际包裹体积重,
# bill账单给头程单价实际尾端计费重预估尾端成本尾端附加费

import os
import re
import pandas as pd
from utils.Package import Package,Package_group
from utils.gtools import MySQLconnect
from utils.countryOperator import OperateCountry
from utils.logisticsBill import BillFactory, Billing
import requests
import json
ods = MySQLconnect("ods")
engine = ods.engine()
def get_SKU_info(order_id):
    """
    根据订单号获取SKU信息,以及入库采购价
    """
    SKULIST = """
        SELECT
            order_id,
            CASE WHEN COUNT(DISTINCT opl.SKU) = 1 THEN "单SKU" ELSE "多SKU" end as "SKU类型",
            CONCAT(group_concat(opl.SKU),",") as "SKU明细",
            sum(s1.`成本价`*product_num) AS "入库采购价"
        FROM
            dws.order_product_list opl LEFT JOIN ods.stg_bayshop_litfad_sku s1  on s1.sku = opl.sku
            LEFT JOIN dwd.dim_erp_sku_package_vol_info des on des.erp_sku = opl.sku
        
        WHERE
            order_id = %s
        AND order_product_id regexp "[0-9]{15}_[0-9]*$"
        GROUP BY order_id 
            
        """
    engine = ods.engine()
    sku_df = pd.read_sql(SKULIST, engine,params=(order_id,))
    if sku_df.empty:
        return None,None,None
    # print("SKU类型:",sku_df['SKU类型'][0],"SKU明细:",sku_df['SKU明细'][0],"入库采购价:",sku_df['入库采购价'][0])
    return sku_df['SKU类型'][0],sku_df['SKU明细'][0],sku_df['入库采购价'][0]

def get_package_real_vol_by_api(packages_id):
    """
    根据订单号的包裹ID,返回包裹类包裹明细包裹实重包裹体积重6000
    """
    packages = Package_group()
    packages_str = ""
    packages_weight=0
    packages_vol = 0
    for package_id in packages_id:
        url = f'https://cp.baycheer.com/index.php?main=biphp&act=package_fund&key=W6BOYJ7BH27YCGRFCA0LWBVKMU1KRU5Q&package={package_id}'
        resp = requests.get(url).json()
        if resp['code'] == "0":
            weight = int(float(resp['data'][0]['weight'])*1000)
            package_length = resp['data'][0]['l'].replace(",","") if len(resp['data'][0]['l'])>0 else "0"
            package_width = resp['data'][0]['w'].replace(",","") if len(resp['data'][0]['w'])>0 else "0"
            package_hight = resp['data'][0]['h'].replace(",","") if len(resp['data'][0]['h'])>0 else "0"
            package = Package(str(package_id),float(package_length),float(package_width),float(package_hight),weight)
            packages.add_package(package)
            # 实际包裹尺寸
            package_str = f"{weight}|{package_length}*{package_width}*{package_hight}"
            packages_str += package_str + ","
    return packages,packages_str

def get_shiji_bill(opCountry,order_id,packages_id,postcode,convey,amount):
    # print(order_id)
    beizhu = amount
    conveys = 1 if convey == "海运" else 0
    try:
        packages,packages_str = get_package_real_vol_by_api(packages_id=packages_id)
        bill = Billing(str(order_id),opCountry,packages,postcode,company_name=None,head_type=conveys,beizhu=beizhu)
        print(bill)
        tail_amount = bill.bill_dict()["预测尾端"]
        total_weight = sum([p.weight/1000 for p in packages.packages])
        _type =  bill.bill_dict()["尾端渠道"]
        head_amount = bill.bill_dict()["预测头程CNY"]
        total_amount = bill.bill_dict()["总金额USD"]
        volume_weight = bill.bill_dict()["体积重"]
        per_head = bill.bill_dict()["头程单价"]
        other_detail = bill.get_other_fee()
        return packages_str,total_weight,volume_weight,per_head,head_amount,tail_amount,other_detail,_type,total_amount
    except ZeroDivisionError as e:
        print(e)
        return "",0,0,0,0,0,"","",0
def get_package_info_by_sql(order_df):
    packages = Package_group()
    packages_str = ""
    for index, row in order_df.iterrows():
        if row['包裹数据'] is None:
            return None,""
        row['包裹数据'] = json.loads(row['包裹数据'])
        item_list = [
            {key: float(re.search(r"\d+\.?\d*", str(value)).group()) for key, value in package.items()}
            for package in row['包裹数据'].values()
]
        for item in item_list:
            if item['长'] == 0 or item['宽'] == 0 or item['高'] == 0 or item['重量'] == 0:
                return None,""
            package = Package(row['SKU'], item['长'], item['宽'], item['高'], item['重量'])
            packages.add_package(package)
            # 实际包裹尺寸
            package_str = f"{ item['重量']}|{item['长']}*{ item['宽']}*{item['高']}"
            packages_str += package_str + ","
    return packages,packages_str

def get_biaozhun_bill(country,order_id,postcode,convey,amount):
    print(order_id)
    # 取标准包裹数据
    sql = """SELECT
    order_id,
    opl.SKU,
    包裹数据
    FROM
    dws.order_product_list opl
    LEFT JOIN ads.new_erp_sku_size spi ON opl.SKU =spi.SKU
    WHERE
    order_id = %s
    AND
    opl.order_product_id REGEXP "[0-9]{15}_[0-9]*$"
    """
    order_package_date = pd.read_sql(sql, engine, params=(order_id,))
    print(order_package_date['SKU'])
    if order_package_date['包裹数据'] is None:
        return "",0,0,0,0,0,"",""
    # 取账单数据
    beizhu = amount
    conveys = 1 if convey == "海运" else 0
    opCountry = OperateCountry(country)
    try:
        packages,packages_str = get_package_info_by_sql(order_package_date)
        if packages is None:
            return "",0,0,0,0,0,"",""
        bill = Billing(str(order_id),opCountry,packages,postcode,company_name=None,head_type=conveys,beizhu=beizhu)
        print(bill)
        tail_amount = bill.bill_dict()["预测尾端"]
        total_weight = sum([p.weight/1000 for p in packages.packages])
        _type =  bill.bill_dict()["尾端渠道"]
        head_amount = bill.bill_dict()["预测头程CNY"]
        total_amount = bill.bill_dict()["总金额USD"]
        volume_weight = bill.bill_dict()["体积重"]
        per_head = bill.bill_dict()["头程单价"]
        other_detail = bill.get_other_fee()
        return packages_str,total_weight,volume_weight,per_head,head_amount,tail_amount,other_detail,_type
    except ZeroDivisionError as e:
        print(e)
        return "",0,0,0,0,0,"",""
In [13]:
sql = """SELECT
        ol.order_id ,
        CONCAT("[",GROUP_CONCAT(pr.包裹号),"]") AS package_group ,
        ol.postcode,
        ol.delivery_country,
        ol.convey,
				ol.`currency`,
				ol.`order_price`,
		IF( ol.payment_method IS NULL, ols.支付方式, ol.payment_method ) AS 支付方式,
        ol.order_price_dollar
    FROM
        parcel pr
        LEFT JOIN dwd.order_list ol ON ol.order_id = pr.订单号 
				left JOIN ods.order_list_supplement ols ON ol.order_id = ols.订单号
    WHERE
    NOT EXISTS (
        SELECT
            1 
        FROM
            `order_express` oe 
        WHERE
        oe.包裹号 = pr.包裹号 
        AND oe.包裹状态  REGEXP "作废|--")
    AND order_id IN (251120212802039 

)
    GROUP BY ol.order_id
"""
In [14]:
order_id_df = pd.read_sql(sql,engine)
# SKU类型和SKU明细以及入库采购价
order_id_df[['订单SKU类型','订单SKU明细','入库采购价']] = order_id_df.apply(lambda x: get_SKU_info(x['order_id']), axis=1, result_type='expand')

# 获取标准账单
order_id_df[["标准包裹尺寸详情","标准实重","标准体积重","标准头程单价","标准头程费用(CNY)","标准尾端费用(当地货币)","标准尾端附加费","标准尾端渠道"]] = order_id_df.apply(lambda x: get_biaozhun_bill(
                                                                                                                x['delivery_country'],
                                                                                                                        x['order_id'],
                                                                                                                    x['postcode'],    
                                                                                                                    x['convey'],
                                                                                                                    x['order_price_dollar']),axis=1,result_type='expand')
# 获取实际采购价
# order_id_df['实际采购价'] = order_id_df['order_id'].apply(lambda x: get_purchase_price(x))

# 获取实际账单
order_id_df[["实际包裹尺寸详情","实际实重","实际体积重","实际头程单价","实际头程费用(CNY)","实际尾端费用(当地货币)","实际尾端附加费","实际尾端渠道","总金额(USD)"]] = order_id_df.apply(lambda x: get_shiji_bill(OperateCountry(x['delivery_country']),
                                                                                                                        x['order_id'],
                                                                                                                    eval(x['package_group']),
                                                                                                                    x['postcode'],    
                                                                                                                    x['convey'],
                                                                                                                    x['order_price_dollar']),axis=1,result_type='expand')

order_id_df.to_clipboard()
251120212802039
0    2200885770
1    2201683904
2    2201886758
Name: SKU, dtype: int64
账单名称: 251120212802039
账单项: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
账单名称: 251120212802039
账单项: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
In [33]:
order_id_df.to_clipboard()
In [ ]:
# 取订单号和包裹号
sql = """
SELECT
        pr.包裹号,pr.订单号
    FROM
        parcel pr 	
    WHERE
    订单号 IN (251120212802039 

)
"""
package_df = pd.read_sql(sql,engine)
package_df.to_clipboard(index=False)
In [ ]:
from utils.gtools import MySQLconnect
import pandas as pd
import os
# date = "2025/3/5"
# 连接数据库
ods = MySQLconnect("ods")
engine = ods.engine()

# 读取 Excel 数据
excel_path = r"D:\test\logistics\拦截数据\拦截订单登记明细.xlsx"
order_df = pd.read_excel(excel_path, sheet_name="拦截明细", skiprows=1)
# 读取 Excel 数据时,指定 '订单号' 列为字符串类型
order_df = pd.read_excel(excel_path, sheet_name="拦截明细", skiprows=1, dtype={'订单号': str})
# order_df = order_df[order_df['拦截计算日期'] == date]
order_df = order_df[['订单号', '提交拦截申请时间']]

# 提取订单号并转为字符串
order_id = [str(x) for x in order_df["订单号"].dropna()]

if not order_id:
    print("没有符合条件的订单号,查询终止。")
else:
    try:
        # 生成占位符并执行查询
        placeholders = ', '.join(['%s'] * len(order_id))
        sql = f"""
        SELECT
            单号,
            包裹号,
            包裹状态,
            快递跟踪号,
            `关联卡板号`,
            关联提单号,
            打包时间,
            `快递公司` AS 打单渠道,
            `包裹测量时间`,
            运单生成时间 AS 打单时间,
            绑定卡板时间,
            绑定提单时间,
            `提单发货时间`
        FROM
            ods.`order_express`
        WHERE
            单号 IN ({placeholders})
        """
        df = pd.read_sql(sql, engine, params=tuple(order_id))

        # 合并数据
        order_df["订单号"] = order_df["订单号"].astype(str)
        df["单号"] = df["单号"].astype(str)
        merged_df = df.merge(order_df, left_on="单号", right_on="订单号", how="left")
        merged_df = merged_df.drop(columns=["订单号"])  # 删除重复的 '订单号' 列

        # 重新排列列顺序
        merged_df = merged_df[[
            "单号",
            "包裹号",
            "提交拦截申请时间",
            "包裹状态",
            "快递跟踪号",
            "关联卡板号",
            "关联提单号",
            "打包时间",
            "包裹测量时间",
            "打单时间",
            "打单渠道",
            "绑定卡板时间",
            "绑定提单时间",
            "提单发货时间"
        ]]

        # 检查文件是否存在,并读取目标工作表
        if os.path.exists(excel_path):
            with pd.ExcelFile(excel_path) as xls:
                sheets = xls.sheet_names
                if "包裹时间记录" in sheets:
                    existing_df = pd.read_excel(excel_path, sheet_name="包裹时间记录")
                else:
                    existing_df = pd.DataFrame(columns=merged_df.columns)  # 如果表不存在,创建一个空 DataFrame
        else:
            existing_df = pd.DataFrame(columns=merged_df.columns)  # 如果文件不存在,创建一个空 DataFrame

        # 过滤掉已存在的包裹号
        existing_package_ids = existing_df["包裹号"].astype(str).tolist()
        new_data = merged_df[~merged_df["包裹号"].astype(str).isin(existing_package_ids)]

        # 如果没有新数据,直接退出
        if new_data.empty:
            print("没有新数据需要追加。")
        else:
            # 追加新数据
            
            combined_df = pd.concat([existing_df, new_data], ignore_index=True)

            # 写入 Excel保留其他工作表
            with pd.ExcelWriter(excel_path, engine='openpyxl', mode='a' if os.path.exists(excel_path) else 'w', if_sheet_exists='replace') as writer:
                combined_df.to_excel(writer, sheet_name="包裹时间记录", index=False)
                print("数据已成功追加到工作表!")
        
    except Exception as e:
        print(f"操作失败,错误详情:{e}")
In [ ]:
# 手动输入包裹的包裹信息
from logisticsClass.logisticsTail_EUR import KPASLLogistics_FR
from utils.Package import Package,Package_group
from utils.gtools import MySQLconnect
from utils.countryOperator import OperateCountry
from utils.logisticsBill import BillFactory, Billing
packages = Package_group()

packages.add_package(Package("包裹1", 50,50,14, 30000))
# packages.add_package(Package("包裹1", 125,109,16, 600000))
# packages.add_package(Package("包裹1",180 ,35,13, 17000))
# packages.add_package(Package("包裹1", 132,62,3, 6500))


country = 'UK'
postcode ='AB43 7JB'
conveys= 0 # 1海运0空运


opCountry = OperateCountry(country)
bill = Billing(str(1),opCountry,packages,postcode,company_name=None,head_type=conveys,beizhu="1")
print(bill)
tail_amount = bill.bill_dict()["预测尾端"]
total_weight = sum([p.weight/1000 for p in packages.packages])
_type =  bill.bill_dict()["尾端渠道"]
head_amount = bill.bill_dict()["预测头程CNY"]
total_amount = bill.bill_dict()["总金额USD"]
volume_weight = bill.bill_dict()["体积重"]
per_head = bill.bill_dict()["头程单价"]
other_detail = bill.items
base_amount = [item.amount for item in other_detail if item.item_detail == "base"][0]

packages_str = ""
for package in packages.packages:
    package_str = f"{package.weight}|{package.length}*{package.width}*{package.height}"
    packages_str += package_str + ","
print(f"packages_str:{packages_str}")
print(f"实重:{total_weight}")
print(f"体积重:{volume_weight}")
print(f"头程单价:{per_head}")
print(f"预测头程CNY:{head_amount}")
print(f"基础运费:{base_amount}")
print(f"其他费用:{other_detail}")
print(f"预测尾端(当地货币):{tail_amount}")
print(f"尾端渠道:{_type}")
print(f"总金额USD:{total_amount}")

查找供应商退货退款金额

In [ ]:

In [ ]:
import pandas as pd
import numpy as np
from utils.gtools import MySQLconnect
ods = MySQLconnect('ods')
engine = ods.engine()

# 读取 Excel 数据
excel_path = r"D:\test\logistics\拦截数据\拦截订单登记明细.xlsx"
order_df = pd.read_excel(excel_path, sheet_name="拦截明细", skiprows=1)
# 读取 Excel 数据时,指定 '订单号' 列为字符串类型
order_df = pd.read_excel(excel_path, sheet_name="拦截明细", skiprows=1, dtype={'订单号': str})

# 提取订单号并转为字符串
order_id = [str(x) for x in order_df["订单号"].dropna()]
placeholders = ','.join(['%s'] * len(order_id))
sql = f"""
WITH
t1 AS (
SELECT
  -- 提取交易号
  TRIM(SUBSTRING(
    `外部关联信息`,
    LOCATE('交易号:', `外部关联信息`) + CHAR_LENGTH('交易号:'),
    CASE 
      WHEN LOCATE('单品号:', `外部关联信息`) > 0
      THEN LOCATE('单品号:', `外部关联信息`) - LOCATE('交易号:', `外部关联信息`) - CHAR_LENGTH('交易号:')
      ELSE LOCATE('[', `外部关联信息`) - LOCATE('交易号:', `外部关联信息`) - CHAR_LENGTH('交易号:')
    END
  )) AS 交易号,

  -- 提取单品号(如果存在)
  CASE 
    WHEN LOCATE('单品号:', `外部关联信息`) > 0 THEN
      TRIM(SUBSTRING(
        `外部关联信息`,
        LOCATE('单品号:', `外部关联信息`) + CHAR_LENGTH('单品号:'),
        LOCATE('[', `外部关联信息`) - LOCATE('单品号:', `外部关联信息`) - CHAR_LENGTH('单品号:')
      ))
    ELSE NULL
  END AS 单品号,

  `支付账号`,
  `处理金额`,
  `添加时间`,
  `资金状态`,
  `完成时间`,
  备注

FROM cpmaso_procurement_fund_manage
WHERE `添加时间` >= DATE_SUB(NOW(), INTERVAL 8 MONTH)
)
SELECT
LEFT(order_product_id,15) AS 订单号,
	order_product_id,
	buy_audit AS 状态,
	trans_pay_date AS 采购时间,
	log_receiving_date AS 到货时间,
	t1.*
FROM
	`warehouse_purchasing` wp
LEFT JOIN t1 ON wp.trans_id = t1.交易号
WHERE
交易号>0 AND
LEFT(wp.order_product_id,15) IN ({placeholders})
ORDER BY 添加时间,订单号
"""
df = pd.read_sql(sql, engine,params=tuple(order_id))
df.to_clipboard(index = False)

入库

In [ ]:
import pandas as pd
import numpy as np
from sqlalchemy import text
from utils.gtools import MySQLconnect
ods = MySQLconnect('ods')
engine = ods.engine()

# 读取 Excel 数据
excel_path = r"D:\test\logistics\拦截数据\拦截订单登记明细.xlsx"
# 读取 Excel 数据时,指定 '订单号' 列为字符串类型
order_df = pd.read_excel(excel_path, sheet_name="拦截明细", skiprows=1, dtype={'订单号': str})

# 提取订单号并转为字符串
order_id = df['订单号'].astype(str).tolist()


bind_names = [f":p{i}" for i in range(len(order_id))]
placeholders = ', '.join(bind_names)

sql = text(f"""
SELECT
REGEXP_SUBSTR(note, '[0-9]{{15}}') AS 订单号,
stock_in_id AS `入库单号`,
instock_date AS `入库时间`
FROM stockinid_list
WHERE note REGEXP '[0-9]{{15}}_'
AND REGEXP_SUBSTR(note, '[0-9]{{15}}') IN ({placeholders})
""")

params = {f"p{i}": v for i, v in enumerate(order_id)}
df = pd.read_sql(sql, engine, params=params)
df.to_clipboard(index = False)