ERP/import_reconciliation_excel.py
2025-11-25 10:35:02 +08:00

145 lines
5.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""从Excel导入对账单数据"""
import pandas as pd
import sqlite3
import os
from datetime import datetime, timezone, timedelta
# 数据库路径
DB_PATH = os.path.join(os.path.dirname(__file__), 'server', 'data.db')
EXCEL_FILE = '25年11月份对账单-易泰勒.xlsx'
def get_beijing_time():
"""获取北京时间UTC+8的ISO格式字符串"""
beijing_tz = timezone(timedelta(hours=8))
return datetime.now(beijing_tz).isoformat()
def import_from_excel():
"""从Excel导入对账单数据"""
# 读取Excel文件
df = pd.read_excel(EXCEL_FILE)
# 打印前20行查看结构
print("Excel文件结构:")
print("=" * 80)
for i in range(min(20, len(df))):
print(f"{i}行: {df.iloc[i].tolist()}")
print("=" * 80)
# 查找表头行(包含"序号"的行)
header_row = None
for i in range(len(df)):
row_values = df.iloc[i].tolist()
if any(str(val).strip() == '序号' for val in row_values if pd.notna(val)):
header_row = i
print(f"\n找到表头行: 第{i}")
print(f"表头内容: {row_values}")
break
if header_row is None:
print("❌ 未找到表头行(包含'序号'的行)")
return
# 重新读取,跳过前面的行,使用找到的行作为表头
df = pd.read_excel(EXCEL_FILE, skiprows=header_row)
# 设置第一行为列名
df.columns = df.iloc[0]
df = df[1:] # 删除第一行(已经作为列名)
df = df.reset_index(drop=True)
print(f"\n数据形状: {df.shape}")
print(f"列名: {df.columns.tolist()}")
print(f"\n前5行数据:")
print(df.head())
# 连接数据库
conn = sqlite3.connect(DB_PATH)
c = conn.cursor()
now = get_beijing_time()
imported_count = 0
# 遍历数据行
for idx, row in df.iterrows():
# 跳过空行或无效行
if pd.isna(row.get('序号')):
continue
try:
# 提取数据
# 处理日期格式
def format_date(date_val):
if pd.isna(date_val):
return ''
if isinstance(date_val, datetime):
return date_val.strftime('%Y/%m/%d')
date_str = str(date_val).strip()
# 如果已经是 YYYY/MM/DD 格式,保持不变
if '/' in date_str:
return date_str
# 如果是 YYYY-MM-DD 格式,转换为 YYYY/MM/DD
if '-' in date_str:
return date_str.split()[0].replace('-', '/')
return date_str
order_date = format_date(row.get('下单时间'))
contract_no = str(row.get('合同编号', '')).strip() if pd.notna(row.get('合同编号')) else ''
material_name = str(row.get('物料名称', '')).strip() if pd.notna(row.get('物料名称')) else ''
spec_model = str(row.get('规格型号', '')).strip() if pd.notna(row.get('规格型号')) else ''
transport_no = str(row.get('运输单号', '')).strip() if pd.notna(row.get('运输单号')) else ''
quantity = int(row.get('数量', 0)) if pd.notna(row.get('数量')) else 0
unit = str(row.get('单位', 'pcs')).strip() if pd.notna(row.get('单位')) else 'pcs'
unit_price = float(row.get('含税单价', 0)) if pd.notna(row.get('含税单价')) else 0.0
total_amount = float(row.get('含税金额', 0)) if pd.notna(row.get('含税金额')) else 0.0
delivery_date = format_date(row.get('交货日期'))
shipment_date = format_date(row.get('出货日期'))
# 验证必填字段
if not all([order_date, contract_no, material_name, spec_model, quantity, unit, unit_price]):
print(f"⚠️ 跳过第{idx+1}行: 缺少必填字段")
continue
# 插入数据库
c.execute('''
INSERT INTO reconciliations(
order_date, contract_no, material_name, spec_model, transport_no,
quantity, unit, unit_price, total_amount, delivery_date, shipment_date,
created_by, created_at, updated_at
) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)
''', (
order_date,
contract_no,
material_name,
spec_model,
transport_no,
quantity,
unit,
unit_price,
total_amount,
delivery_date,
shipment_date,
'admin',
now,
now
))
imported_count += 1
print(f"✅ 导入第{idx+1}行: {contract_no} - {material_name}")
except Exception as e:
print(f"❌ 导入第{idx+1}行失败: {e}")
continue
conn.commit()
conn.close()
print(f"\n{'='*80}")
print(f"✅ 成功导入 {imported_count} 条对账单数据")
print(f"{'='*80}")
if __name__ == '__main__':
import_from_excel()