b2bcenter-parser/excel_parser.py

148 lines
5.2 KiB
Python
Raw Normal View History

2024-02-15 10:56:32 +03:00
import json
2024-02-06 10:47:22 +03:00
import pathlib
2024-02-15 13:26:32 +03:00
from urllib.parse import urlparse, parse_qs
2024-02-15 10:56:32 +03:00
import numpy as np
from functools import reduce
2024-02-06 10:47:22 +03:00
import requests
2024-02-15 10:56:32 +03:00
from openpyxl import load_workbook
2024-02-06 10:47:22 +03:00
import pandas as pd
2024-02-15 10:56:32 +03:00
from storage import Storage
2024-02-06 10:47:22 +03:00
API_CALC_URL = "https://api.jde.ru/vD/calculator/PriceAddress"
TYPE = "1"
PICKUP = "1"
DELIVERY = "1"
USER = "2252130929823409"
TOKEN = "67065749269910593"
class ExcelParser:
2024-02-15 10:56:32 +03:00
def __init__(self, paths: list[pathlib.Path] | list[str], url: str):
self.url = url
self._paths = [pathlib.Path(p) for p in paths]
self.storage = Storage()
for path in self._paths:
assert path.is_file() is True, "Файл не найден"
2024-02-06 10:47:22 +03:00
def convert_to_xlsx(self, path: pathlib.Path):
import pyexcel as pe
if path.suffix == '.xlsx':
self._wb = load_workbook(str(path))
return
pe.save_book_as(file_name=str(path), dest_file_name=str(path.with_suffix('.xlsx')))
self._wb = load_workbook(str(path.with_suffix('.xlsx')))
2024-02-15 10:56:32 +03:00
def _clean_up_wb(self, path: pathlib.Path) -> pd.DataFrame:
columns = ["Адрес отгрузки", "Адрес разгрузки", "Масса", "Объем", "Дата загрузки"]
df = pd.read_excel(path)
cond = reduce(lambda x, y: x | y, (df == val for val in columns))
for row in df[cond].iterrows():
if row[1].any():
df = df[row[0]:]
2024-02-06 10:47:22 +03:00
break
2024-02-15 10:56:32 +03:00
df: pd.DataFrame = df.loc[:, df.iloc[0].dropna().index]
df.columns = df.iloc[0]
df = df.drop(df.index[0], axis=0)
not_existed_columns = list(set(columns) - set(df.columns))
2024-02-06 10:47:22 +03:00
2024-02-15 10:56:32 +03:00
if len(not_existed_columns) > 0:
2024-02-15 13:26:32 +03:00
self.add_link_to_database()
2024-02-15 10:56:32 +03:00
raise KeyError(f"Не удалось обработать заявку по причине отсутствия полей в шаблоне: {not_existed_columns}")
df = df.loc[:, columns]
2024-02-06 10:47:22 +03:00
2024-02-15 10:56:32 +03:00
df = df.drop([idx for idx, row in df.iterrows() if row.isna().all()], axis=0)
2024-02-06 10:47:22 +03:00
2024-02-15 10:56:32 +03:00
isna_values_y = list(set(np.where(df.isna())[1]))
2024-02-06 10:47:22 +03:00
2024-02-15 10:56:32 +03:00
if isna_values_y:
2024-02-15 13:26:32 +03:00
raise ValueError(
f"Не удалось обработать заявку по причине отсутствия значений в полях: {list(df.columns[isna_values_y])}")
2024-02-15 10:56:32 +03:00
return df
def clean_up_wb(self):
dfs: list[pd.DataFrame] = []
for path in self._paths:
df = self._clean_up_wb(path)
if len(df) < 1:
raise ValueError("Требуется ручная обработка, не удалось считать одно из полей.")
dfs.append(df)
concat = pd.concat(dfs)
concat = concat.set_index(pd.RangeIndex(stop=len(concat)))
return pd.DataFrame({
'Адрес отгрузки': [concat['Адрес отгрузки'][0]],
'Адрес разгрузки': [concat['Адрес разгрузки'][0]],
'Дата загрузки': [concat['Дата загрузки'][0]],
'Масса': [concat['Масса'].sum()],
'Объем': [concat['Объем'].sum()]})
def calculate(self) -> dict | None:
2024-02-06 10:47:22 +03:00
df = self.clean_up_wb()
2024-02-15 10:56:32 +03:00
2024-02-06 10:47:22 +03:00
query = {
"type": TYPE,
"token": TOKEN,
"delivery": DELIVERY,
"pickup": PICKUP,
"user": USER,
2024-02-15 10:56:32 +03:00
"addr_from": df['Адрес отгрузки'].iloc[0],
"addr_to": df['Адрес разгрузки'].iloc[0],
"weight": float(df['Масса'].iloc[0]) * 1000,
"volume": df['Объем'].iloc[0],
2024-03-15 16:47:38 +03:00
"pr_vat": "1",
"services": "LATH,TMP",
"obrVolume": df['Объем'].iloc[0],
"obrK": "1"
2024-02-06 10:47:22 +03:00
}
2024-02-15 10:56:32 +03:00
2024-02-06 10:47:22 +03:00
data = requests.get(API_CALC_URL, params=query).json()
if data.get('price', None) is not None:
2024-03-01 13:48:14 +03:00
price = int(data['price']) * 1.35
if price < 40000:
price = 40000
2024-02-15 10:56:32 +03:00
self.add_link_to_database(query, answer=data)
2024-03-01 13:48:14 +03:00
return {"price": price,
2024-02-15 10:56:32 +03:00
"vat": int(data['percent_vat']),
"max_days": int(data['maxdays']),
"transport_delivery_date": str(df["Дата загрузки"][0])}
2024-02-15 13:26:32 +03:00
self.add_link_to_database(query, answer=data)
2024-02-06 10:47:22 +03:00
return None
2024-02-15 13:26:32 +03:00
def add_link_to_database(self, query: dict | None = None, answer: dict | None = None):
idx = int(parse_qs(urlparse(self.url).query).get('id')[0])
if answer is None:
price = None
else:
price = answer.get('price', None)
answer = json.dumps(answer)
if query:
query = json.dumps(query)
2024-02-15 10:56:32 +03:00
[self.storage.add_link(
2024-02-15 13:26:32 +03:00
idx,
2024-02-15 10:56:32 +03:00
str(file.absolute()),
2024-02-15 13:26:32 +03:00
price,
query,
answer) for file in self._paths
2024-02-15 10:56:32 +03:00
]
2024-02-06 10:47:22 +03:00
if __name__ == '__main__':
2024-02-27 17:12:55 +03:00
# pass
parser = ExcelParser('./downloads/1297-РС.xls')
print(parser.calculate())
df1 = pd.read_excel('./downloads/Тендер 3574955 КГП165.1.xls')
df2 = pd.read_excel('./downloads/Тендер 3574955 КГП165.2.xls')
df3 = pd.read_excel('./downloads/Тендер 3574955 КГП165.xls')