Commit c7f4617e authored by 邱阿朋's avatar 邱阿朋

回款

parent f947f988
...@@ -70,6 +70,7 @@ def remove_last_comma(csv_file, skip_rows=2): ...@@ -70,6 +70,7 @@ def remove_last_comma(csv_file, skip_rows=2):
# 不添加换行符,待会写入时统一处理 # 不添加换行符,待会写入时统一处理
cleaned_lines.append(cleaned_line) cleaned_lines.append(cleaned_line)
# 将处理后的数据写入同一个文件 # 将处理后的数据逐行写回文件
with open(csv_file, 'w', encoding='utf-8', newline='') as cleaned_file: with open(csv_file, 'w', encoding='utf-8', newline='') as cleaned_file:
cleaned_file.write('\n'.join(cleaned_lines) + '\n') # 使用 join 处理换行符 for line in cleaned_lines:
cleaned_file.write(line + '\n') # 每一行单独写入,确保每行独立处理
# coding: utf-8 # coding: utf-8
import os import os
import shutil
import time import time
...@@ -25,3 +26,27 @@ def make_dir(path): ...@@ -25,3 +26,27 @@ def make_dir(path):
return False return False
return True return True
def move_file(src, dest):
"""
将文件从 src 移动到 dest。
:param src: 源文件路径
:param dest: 目标文件路径
:return: None
"""
try:
# 检查源文件是否存在
if not os.path.exists(src):
raise FileNotFoundError(f"源文件 {src} 不存在")
# 检查目标文件夹是否存在,如果不存在则创建
dest_dir = os.path.dirname(dest)
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
# 使用 shutil.move 来移动文件
shutil.move(src, dest)
except Exception as e:
print(f"移动文件时出错: {e}")
\ No newline at end of file
...@@ -10,7 +10,7 @@ class RedisClient: ...@@ -10,7 +10,7 @@ class RedisClient:
cls._instance._initialize(*args, **kwargs) cls._instance._initialize(*args, **kwargs)
return cls._instance return cls._instance
def _initialize(self, host='39.108.185.244', port=6379, db=12, password="khd2022!", decode_responses=True): def _initialize(self, host='47.119.182.76', port=6379, db=12, password="khd2022!", decode_responses=True):
self.client = redis.StrictRedis(host=host, port=port, db=db, password=password, self.client = redis.StrictRedis(host=host, port=port, db=db, password=password,
decode_responses=decode_responses) decode_responses=decode_responses)
......
...@@ -12,6 +12,7 @@ import pandas as pd ...@@ -12,6 +12,7 @@ import pandas as pd
from DrissionPage import ChromiumPage from DrissionPage import ChromiumPage
from DrissionPage.errors import ElementNotFoundError from DrissionPage.errors import ElementNotFoundError
from lxml import etree from lxml import etree
from numpy.ma.core import append
from helper import helper, excel, file, domain, logger, redisx from helper import helper, excel, file, domain, logger, redisx
...@@ -148,7 +149,7 @@ def get_po_code(index, po_id) -> dict: ...@@ -148,7 +149,7 @@ def get_po_code(index, po_id) -> dict:
# 获取 Vendor 内容 # 获取 Vendor 内容
result["vendor"] = get_content(tree, 2, 2) result["vendor"] = get_content(tree, 2, 2)
# 正则表达式查找数字和%之间的内容 # 正则表达式查找数字和%之间的内容
match = re.search(r'Payment Terms.*?(\d+%)', po_table) match = re.search(r'Payment .*?(\d+%)', po_table)
if match: if match:
result["payment_terms"] = match.group(1)[:-1] # 去掉% result["payment_terms"] = match.group(1)[:-1] # 去掉%
else: else:
...@@ -199,40 +200,85 @@ def price_extract_data(html_content): ...@@ -199,40 +200,85 @@ def price_extract_data(html_content):
return data_list return data_list
def click_get_price_data(): def line_items_data(html_content):
while True: # 使用正则表达式删除所有 HTML 注释
try: html_content = re.sub(r'<!--.*?-->', '', html_content)
# 点击争议价tab
page.ele("#pd").click() # 使用 lxml 解析 HTML
log.debug("等待争议数据加载,5秒后获取表单数据") tree = etree.HTML(html_content)
page.wait(5) # 提取所有行的数据
table_html = page.ele("#priceDiscrepancyWithDMSGridForm", timeout=5).html rows = tree.xpath('//tr[contains(@class, "mt-row")]')
# 抓取表单数据
price_data = price_extract_data(table_html) data_list = []
return price_data
except ElementNotFoundError: for row in rows:
log.warning("未获取到表数据") # 定义 data 字典,提取并去除多余字符
break data = {
'PO': row.xpath('string(./td[@data-column="PO_NUMBER"]/span/span/a)').strip(),
'External ID': row.xpath('string(./td[@data-column="EXTERNAL_ID"])').strip(),
'ASIN': row.xpath('string(./td[@data-column="ASIN"]/span/span/a)').strip(),
'TITLE': row.xpath('string(./td[@data-column="DESCRIPTION"])').strip(),
'Model': row.xpath('string(./td[@data-column="MODEL_NUMBER"])').strip(),
'Freight Term': row.xpath('string(./td[@data-column="FREIGHT_TERM"])').strip(),
'Qty': row.xpath('string(./td[@data-column="QUANTITY"])').strip(),
'Unit Cost': row.xpath('string(./td[@data-column="UNIT_COST"])').strip(),
'Amount': row.xpath('string(./td[@data-column="TOTAL_AMOUNT"])').strip(),
'Shortage quantity': row.xpath('string(./td[@data-column="SHORTAGE_QUANTITY"])').strip(),
'Amount shortage': row.xpath('string(./td[@data-column="SHORTAGE_AMOUNT"])').strip(),
'Last received date': row.xpath('string(./td[@data-column="LAST_RECEIVED_DATE"])').strip(),
'ASIN received': row.xpath('string(./td[@data-column="RECEIVED_ASIN"])').strip(),
'Quantity received': row.xpath('string(./td[@data-column="RECEIVED_QUANTITY"])').strip(),
'Unit cost': row.xpath('string(./td[@data-column="RECEIVED_COST_PRICE"])').strip(),
'Amount received': row.xpath('string(./td[@data-column="RECEIVED_AMOUNT"])').strip(),
}
# 如果字段为空则设为空字符串
for key in data:
if not data[key]:
data[key] = "" # 将 None 转为 ""
data_list.append(data)
return data_list
def calculate_unit_cost(data_list):
"""计算差异金额单价并返回金额"""
unit_cost_float = Decimal(data_list['INVOICE_COST']) - Decimal(data_list['INITIAL_RESEARCH_COST'])
unit_cost = unit_cost_float * int(data_list['QUANTITY'])
return unit_cost_float, float(f"{unit_cost:.2f}")
def handle_price_data(price_data_list, invoice_amount): def handle_price_data(price_data_list, invoice_amount):
result = {} total_price_data_amount = 0
# 计算总金额
for data_list in price_data_list:
unit_cost_float, amount = calculate_unit_cost(data_list)
total_price_data_amount += amount
result = []
invoice_amount = abs(float(f"{invoice_amount:.2f}")) invoice_amount = abs(float(f"{invoice_amount:.2f}"))
"""处理争议数据"""
# 如果总金额等于列表金额则已回款
if total_price_data_amount == invoice_amount:
for data_list in price_data_list: for data_list in price_data_list:
# 计算差异金额单价 unit_cost_float, amount = calculate_unit_cost(data_list)
unit_cost_float = Decimal(data_list['INVOICE_COST']) - Decimal(data_list['INITIAL_RESEARCH_COST']) data = data_list.copy()
unit_cost = unit_cost_float * int(data_list['QUANTITY']) data['Quantity received'] = data_list['QUANTITY']
amount = float(f"{unit_cost:.2f}") data['UnitCost'] = unit_cost_float
if amount == invoice_amount: data['Amount'] = f"${amount:.2f}"
result = data_list data['Shortage quantity'] = '0'
result['Quantity received'] = data_list['QUANTITY'] result.append(data)
result['UnitCost'] = unit_cost_float
result['Amount'] = f"${amount:.2f}"
if data_list['RESOLUTION_DECISION'] == "Approved":
result['Shortage quantity'] = 0
else: else:
result['Shortage quantity'] = 1 for data_list in price_data_list:
unit_cost_float, amount = calculate_unit_cost(data_list)
if amount == invoice_amount:
data = data_list.copy()
data['Quantity received'] = data_list['QUANTITY']
data['UnitCost'] = unit_cost_float
data['Amount'] = f"${amount:.2f}"
data['Shortage quantity'] = '0' if data_list['RESOLUTION_DECISION'] == "Approved" else '1'
result.append(data)
break break
return result return result
...@@ -244,7 +290,8 @@ def handle_data(detail_datum, vendor, deduction_points): ...@@ -244,7 +290,8 @@ def handle_data(detail_datum, vendor, deduction_points):
amount = float(amount.replace('$', '').replace(',', '')) amount = float(amount.replace('$', '').replace(',', ''))
# 如果是0则回款完成 # 如果是0则回款完成
is_finished = "否" is_finished = "否"
if detail_datum.get('Shortage quantity', -1) == 0: shortage_quantity = detail_datum.get('Shortage quantity', -1)
if shortage_quantity == '0':
is_finished = "是" is_finished = "是"
amount_after_deduction = amount amount_after_deduction = amount
...@@ -268,7 +315,7 @@ def main(): ...@@ -268,7 +315,7 @@ def main():
# list_data = list_data[25:] # list_data = list_data[25:]
# 获取当前日期和时间并格式化 # 获取当前日期和时间并格式化
current_datetime = datetime.now().strftime('%Y-%m-%d_%H-%M') # 格式化为 'YYYY-MM-DD_HH-MM-SS' current_datetime = datetime.now().strftime('%Y%m%d%H%M') # 格式化为 'YYYY-MM-DD_HH-MM-SS'
# 原文件名 # 原文件名
file_name = "回款数据.xlsx" file_name = "回款数据.xlsx"
# 拼接新的文件名 # 拼接新的文件名
...@@ -304,30 +351,44 @@ def main(): ...@@ -304,30 +351,44 @@ def main():
else: else:
# 进入详情页 # 进入详情页
invoice_details(invoice_number, last_two, last_three) invoice_details(invoice_number, last_two, last_three)
# 获取争议数据 # 点击争议价tab
price_data = click_get_price_data() page.ele("#pd").click()
log.debug("等待争议数据加载,10秒后获取表单数据")
page.wait(10)
table_html = page.ele("#priceDiscrepancyWithDMSGridForm", timeout=5).html
# 抓取表单数据
price_data = price_extract_data(table_html)
# 缓存数据 # 缓存数据
rdb.get_client().hset(cache_key, invoice_number, json.dumps(price_data)) rdb.get_client().hset(cache_key, invoice_number, json.dumps(price_data))
# 争议回款 # 争议回款
handle_after_price_data = handle_price_data(price_data, invoice_amount) price_data = handle_price_data(price_data, invoice_amount)
format_price_data = handle_data(handle_after_price_data, vendor, deduction_points) price_pay_data = []
all_price_pay_data.append(pd.DataFrame(format_price_data, index=[0])) for detail_datum in price_data:
# 争议回款数据
format_price_data = handle_data(detail_datum, vendor, deduction_points)
# 将处理后的记录添加到临时列表
price_pay_data.append(format_price_data)
# 添加到汇总列表
all_price_pay_data.append(pd.DataFrame(price_pay_data))
else: else:
file_name = f"payment\\{invoice_number}.csv" cache_key = "item_data"
if os.path.isfile(file_name): detail_data = rdb.get_client().hget(cache_key, invoice_number)
detail_data = pd.read_csv(file_name) if detail_data:
detail_data = json.loads(detail_data)
else: else:
# 进入详情页 # 进入详情页
invoice_details(invoice_number, last_two, last_three) invoice_details(invoice_number, last_two, last_three)
# 下载excel文件并读取数据 page.wait(3)
detail_data = export_details_read_data(file_name) table_html = page.ele("#invoiceLineItems", timeout=5).html
if detail_data is None: # 抓取表单数据
log.error("数据存在问题,请手动处理") detail_data = line_items_data(table_html)
continue # 缓存数据
rdb.get_client().hset(cache_key, invoice_number, json.dumps(detail_data))
# 初始化列表存储新字段数据 # 初始化列表存储新字段数据
normal_pay_data = [] normal_pay_data = []
for index, detail_datum in detail_data.iterrows(): for detail_datum in detail_data:
# 正常回款数据 # 正常回款数据
success_data = handle_data(detail_datum, vendor, deduction_points) success_data = handle_data(detail_datum, vendor, deduction_points)
# 将处理后的记录添加到临时列表 # 将处理后的记录添加到临时列表
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment