feat: 支持京东白条账单上传和清洗
This commit is contained in:
@@ -22,7 +22,7 @@ if sys.stdout.encoding != 'utf-8':
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
|
||||
|
||||
from cleaners.base import compute_date_range_from_values
|
||||
from cleaners import AlipayCleaner, WechatCleaner
|
||||
from cleaners import AlipayCleaner, WechatCleaner, JDCleaner
|
||||
from category import infer_category, get_all_categories, get_all_income_categories
|
||||
from converter import convert_bill_file
|
||||
|
||||
@@ -43,7 +43,7 @@ class CleanRequest(BaseModel):
|
||||
start: Optional[str] = None
|
||||
end: Optional[str] = None
|
||||
format: Optional[str] = "csv"
|
||||
bill_type: Optional[str] = "auto" # auto, alipay, wechat
|
||||
bill_type: Optional[str] = "auto" # auto, alipay, wechat, jd
|
||||
|
||||
|
||||
class CleanResponse(BaseModel):
|
||||
@@ -90,7 +90,7 @@ def detect_bill_type(filepath: str) -> str | None:
|
||||
检测账单类型
|
||||
|
||||
Returns:
|
||||
'alipay' | 'wechat' | None
|
||||
'alipay' | 'wechat' | 'jd' | None
|
||||
"""
|
||||
try:
|
||||
with open(filepath, "r", encoding="utf-8") as f:
|
||||
@@ -107,6 +107,14 @@ def detect_bill_type(filepath: str) -> str | None:
|
||||
if "交易类型" in line and "金额(元)" in line:
|
||||
return "wechat"
|
||||
|
||||
# 京东特征:表头包含 "商户名称" 和 "交易说明"
|
||||
if "商户名称" in line and "交易说明" in line:
|
||||
return "jd"
|
||||
|
||||
# 京东特征:头部信息包含 "京东账号名"
|
||||
if "京东账号名" in line:
|
||||
return "jd"
|
||||
|
||||
# 数据行特征
|
||||
if line.startswith("202"):
|
||||
if "¥" in line:
|
||||
@@ -155,14 +163,16 @@ def do_clean(
|
||||
try:
|
||||
if bill_type == "alipay":
|
||||
cleaner = AlipayCleaner(input_path, output_path, output_format)
|
||||
elif bill_type == "jd":
|
||||
cleaner = JDCleaner(input_path, output_path, output_format)
|
||||
else:
|
||||
cleaner = WechatCleaner(input_path, output_path, output_format)
|
||||
|
||||
cleaner.set_date_range(start_date, end_date)
|
||||
cleaner.clean()
|
||||
|
||||
type_names = {"alipay": "支付宝", "wechat": "微信"}
|
||||
return True, bill_type, f"✅ {type_names[bill_type]}账单清洗完成"
|
||||
type_names = {"alipay": "支付宝", "wechat": "微信", "jd": "京东白条"}
|
||||
return True, bill_type, f"✅ {type_names.get(bill_type, bill_type)}账单清洗完成"
|
||||
|
||||
except Exception as e:
|
||||
return False, bill_type, f"清洗失败: {str(e)}"
|
||||
@@ -324,7 +334,7 @@ async def detect_bill_type_api(file: UploadFile = File(...)):
|
||||
"""
|
||||
检测账单类型
|
||||
|
||||
上传文件后自动检测是支付宝还是微信账单
|
||||
上传文件后自动检测是支付宝、微信还是京东账单
|
||||
"""
|
||||
suffix = Path(file.filename).suffix or ".csv"
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
|
||||
@@ -336,10 +346,10 @@ async def detect_bill_type_api(file: UploadFile = File(...)):
|
||||
if bill_type is None:
|
||||
raise HTTPException(status_code=400, detail="无法识别账单类型")
|
||||
|
||||
type_names = {"alipay": "支付宝", "wechat": "微信"}
|
||||
type_names = {"alipay": "支付宝", "wechat": "微信", "jd": "京东白条"}
|
||||
return {
|
||||
"bill_type": bill_type,
|
||||
"display_name": type_names[bill_type]
|
||||
"display_name": type_names.get(bill_type, bill_type)
|
||||
}
|
||||
finally:
|
||||
if os.path.exists(tmp_path):
|
||||
|
||||
Reference in New Issue
Block a user