feature/evaluating #2

Merged
MH.Dmitrii merged 28 commits from feature/evaluating into main 2026-01-09 10:17:48 +00:00
6 changed files with 62 additions and 41 deletions
Showing only changes of commit 915103766b - Show all commits

View File

@@ -1,5 +1,6 @@
DIR="/dir/dir/dir" DIR="/dir/dir/dir"
PATTERN=[A-ZА-Я]{0,1}\d{4}[A-ZА-Я]{1,2}\d{0,1} PATTERN=[A-ZА-Я]{0,1}\d{4}[A-ZА-Я]{1,2}\d{0,1}
TIMEFORMAT="%Y-%m-%dT%H:%M:%S"
USERNAME = "..." USERNAME = "..."
PASSWORD = "..." PASSWORD = "..."

View File

@@ -3,17 +3,11 @@ from server.backend.schemas.pydantic import ExcelInfo,settings,Translit
from server.backend.api.nomenclature import processing from server.backend.api.nomenclature import processing
import datetime import datetime
import re import re
def report_date(df, format: str): def last_day_of_month(format: str):
cell = str(df.iloc[0, 4]) next_month = datetime.datetime.now().replace(day=28) + datetime.timedelta(days=4)
match = re.search(r"\d{2}\.\d{2}\.\d{4}", cell) last_day = next_month - datetime.timedelta(days=next_month.day)
if not match: return last_day.strftime(format)
return None
dt = datetime.datetime.strptime(match.group(0), "%d.%m.%Y")
return dt.strftime(format)
def process_sheet(df,real_arti: int,real_quantity: int,real_sum_1: int,real_sum_2: int): def process_sheet(df,real_arti: int,real_quantity: int,real_sum_1: int,real_sum_2: int):
# пропускаем служебные строки
df = df.iloc[2:].reset_index(drop=True)
# выбираем нужные колонки по индексам # выбираем нужные колонки по индексам
df = df.iloc[:, [real_arti, real_quantity, real_sum_1, real_sum_2]].copy() df = df.iloc[:, [real_arti, real_quantity, real_sum_1, real_sum_2]].copy()
df.dropna(inplace=True) df.dropna(inplace=True)
@@ -45,5 +39,5 @@ def process_sheet(df,real_arti: int,real_quantity: int,real_sum_1: int,real_sum_
def evaluating(dfs): def evaluating(dfs):
validated_rows_1 = process_sheet(dfs["Отчет о реализации"], real_arti=2,real_quantity=8, real_sum_1=5,real_sum_2=6) # номера столбцов от озона validated_rows_1 = process_sheet(dfs["Отчет о реализации"], real_arti=2,real_quantity=8, real_sum_1=5,real_sum_2=6) # номера столбцов от озона
validated_rows_2 = process_sheet(dfs["Отчет о реализации"], real_arti=2,real_quantity=16, real_sum_1=13,real_sum_2=14)# validated_rows_2 = process_sheet(dfs["Отчет о реализации"], real_arti=2,real_quantity=16, real_sum_1=13,real_sum_2=14)#
date=report_date(dfs["Отчет о реализации"], format=settings.TIMEFORMAT) date=last_day_of_month(format=settings.TIMEFORMAT)
return validated_rows_1, validated_rows_2, date return validated_rows_1, validated_rows_2, date

View File

@@ -2,31 +2,47 @@ from pydantic import ValidationError
from server.backend.schemas.pydantic import ExcelInfo, settings,Translit from server.backend.schemas.pydantic import ExcelInfo, settings,Translit
from server.backend.api.nomenclature import processing from server.backend.api.nomenclature import processing
import re import re
import datetime
import re
import datetime
def report_date(df, format: str):
row_text = " ".join(df.iloc[0].astype(str))
match = re.search(r"по\s+(\d{2}\.\d{2}\.\d{4})", row_text)
if not match:
return None
dt = datetime.datetime.strptime(match.group(1), "%d.%m.%Y")
return dt.strftime(format)
def process_sheet(df, real_arti:int, real_quantity:int, real_sum_1:int): def process_sheet(df, real_arti:int, real_quantity:int, real_sum_1:int):
#Выборка df = df.iloc[2:].reset_index(drop=True)
df = df[[real_arti, real_quantity, real_sum_1]].copy().dropna() #copy and drop all NA values
df = df[(df != 0).all(axis=1)] #drop all 0 values
df = df[[real_arti, real_quantity, real_sum_1]]
df.rename(columns={real_arti: 'arti', real_quantity: 'counts', real_sum_1: 'price'}, inplace=True) #переименовываем для pydantic
#Нормализация # выбор нужных столбцов ПО ПОЗИЦИИ
df = df.iloc[:, [real_arti, real_quantity, real_sum_1]].copy().dropna()
df = df[(df != 0).all(axis=1)]
# сразу задаём нужные имена
df.columns = ['arti', 'counts', 'price']
# нормализация
df['arti'] = df['arti'].replace(Translit.TRANSLIT, regex=True) df['arti'] = df['arti'].replace(Translit.TRANSLIT, regex=True)
df['arti'] = df['arti'].astype(str).str.upper().str.extract(f'({settings.PATTERN})') #arti под regex df['arti'] = df['arti'].astype(str).str.upper().str.extract(f'({settings.PATTERN})')
df['price'] = df['price'].astype(float) #Float to Int, if exists df['price'] = df['price'].astype(float)
df['counts'] = df['counts'].astype(int) #Float to Int, if exists df['counts'] = df['counts'].astype(int)
#Группировка #Группировка
df = processing(df) #vlookup for ref_keys df = processing(df) #vlookup for ref_keys
validated_rows, errors = [], [] validated_rows, errors = [], []
for i, row in df.iterrows(): #проходит построчно по df, где i - индекс строки, row - данные строки for i, row in df.iterrows():
try: try:
validated_rows.append(ExcelInfo(**row.to_dict())) #добавляем в список проверенные данные полученные от pydantic, которые туда передаются в виде dict validated_rows.append(ExcelInfo(**row.to_dict()))
except ValidationError as e: except ValidationError as e:
errors.append((i, e.errors())) #выводит ошибку и пишет номер строки errors.append((i, e.errors()))
if errors: if errors:
raise Exception(f"There are some errors with validation in Отчет о выкупленных товарах, check it ", errors) raise Exception(
"There are some errors with validation in Отчет о выкупленных товарах",
errors
)
return validated_rows return validated_rows
def evaluating(dfs): def evaluating(dfs):
validated_rows_1 = process_sheet(dfs["Отчет о выкупленных товарах"], real_arti=3,real_quantity=10, real_sum_1=11) # номера столбцов от озона validated_rows_1 = process_sheet(dfs["Отчет о выкупленных товарах"], real_arti=3,real_quantity=10, real_sum_1=11) # номера столбцов от озона
return validated_rows_1 date=report_date(dfs["Отчет о выкупленных товарах"], format=settings.TIMEFORMAT)
return validated_rows_1, date

View File

@@ -2,14 +2,22 @@ from pydantic import ValidationError
from server.backend.schemas.pydantic import ExcelInfo, settings,Translit from server.backend.schemas.pydantic import ExcelInfo, settings,Translit
from server.backend.api.nomenclature import processing from server.backend.api.nomenclature import processing
import re import re
import datetime
def report_date(df, format: str):
row_text = " ".join(df.iloc[0].astype(str))
match = re.search(r"\d{4}-\d{2}-\d{2}", row_text)
if not match:
return None
dt = datetime.datetime.strptime(match.group(0), "%Y-%m-%d")
return dt.strftime(format)
def process_sheet(df, real_arti:str, real_quantity:str, real_sum_1:str): def process_sheet(df, real_arti:str, real_quantity:str, real_sum_1:str):
df = df.iloc[2:].reset_index(drop=True)
#Выборка #Выборка
df = df[[real_arti, real_quantity, real_sum_1]].copy().dropna() #copy and drop all NA values df = df.iloc[:, [real_arti, real_quantity, real_sum_1]].copy().dropna()
#df = df[[real_arti, real_quantity, real_sum_1]].copy().dropna() #copy and drop all NA values
df = df[(df != 0).all(axis=1)] #drop all 0 values df = df[(df != 0).all(axis=1)] #drop all 0 values
df = df[[real_arti, real_quantity, real_sum_1]] #df = df[[real_arti, real_quantity, real_sum_1]]
df.rename(columns={real_arti: 'arti', real_quantity: 'counts', real_sum_1: 'price'}, inplace=True) #переименовываем для pydantic df.rename(columns={"Unnamed: 1": 'arti', "Unnamed: 3": 'counts', "Unnamed: 4": 'price'}, inplace=True) #переименовываем для pydantic
#Нормализация #Нормализация
df['arti'] = df['arti'].astype(str).str.upper().str.extract(f'({settings.PATTERN})') #arti под regex df['arti'] = df['arti'].astype(str).str.upper().str.extract(f'({settings.PATTERN})') #arti под regex
df['arti'] = df['arti'].replace(Translit.TRANSLIT, regex=True) df['arti'] = df['arti'].replace(Translit.TRANSLIT, regex=True)
@@ -18,7 +26,7 @@ def process_sheet(df, real_arti:str, real_quantity:str, real_sum_1:str):
#Группировка #Группировка
df = df.groupby('arti', as_index=False).agg({'counts': 'sum', 'price': 'sum'}) #groupping df = df.groupby('arti', as_index=False).agg({'counts': 'sum', 'price': 'sum'}) #groupping
df = processing(df) #vlookup for ref_keys #df = processing(df) #vlookup for ref_keys
validated_rows, errors = [], [] validated_rows, errors = [], []
for i, row in df.iterrows(): #проходит построчно по df, где i - индекс строки, row - данные строки for i, row in df.iterrows(): #проходит построчно по df, где i - индекс строки, row - данные строки
try: try:
@@ -29,6 +37,8 @@ def process_sheet(df, real_arti:str, real_quantity:str, real_sum_1:str):
raise Exception(f"There are some errors with validation in Sheet1, check it ", errors) raise Exception(f"There are some errors with validation in Sheet1, check it ", errors)
return validated_rows return validated_rows
def evaluating(dfs): def evaluating(dfs):
validated_rows_1 = process_sheet(dfs["Sheet1"], real_arti='Артикул',real_quantity="Количество", real_sum_1='''Сумма выкупа, руб., # validated_rows_1 = process_sheet(dfs["Sheet1"], real_arti='Артикул',real_quantity="Количество", real_sum_1='''Сумма выкупа, руб.,
(вкл. НДС)''') # номера столбцов от озона # (вкл. НДС)''') # номера столбцов от озона
return validated_rows_1 validated_rows_1 = process_sheet(dfs["Sheet1"], real_arti=1,real_quantity=3, real_sum_1=4) # номера столбцов от озона
date=report_date(dfs["Sheet1"], format=settings.TIMEFORMAT)
return validated_rows_1, date

View File

@@ -4,7 +4,7 @@ class ExcelInfo(BaseModel):
arti:str = Field(..., min_length=5, max_length=12, description="arti of the clothes") arti:str = Field(..., min_length=5, max_length=12, description="arti of the clothes")
counts:int = Field(..., gt=0, description="the quantity of the clothes") counts:int = Field(..., gt=0, description="the quantity of the clothes")
price:float = Field(..., gt=0, description="the price of the clothes") price:float = Field(..., gt=0, description="the price of the clothes")
ref_key:str = Field(..., description="reffering key from db") #ref_key:str = Field(..., description="reffering key from db")
class ExcelRealization(BaseModel): class ExcelRealization(BaseModel):
pass pass
class ExcelReturning(BaseModel): class ExcelReturning(BaseModel):

View File

@@ -43,7 +43,7 @@ class WBHandler(BaseHandler):
class OZONHandler(BaseHandler): class OZONHandler(BaseHandler):
def process(self): def process(self):
#Доставать № документа и дату #Доставать № документа и дату
dfs = self.read(skiprows=[0,3,4,5,6,7,8,9,10,11,12,13], skipfooter=17) dfs = self.read(skiprows=14, skipfooter=17)
if "Отчет о реализации" not in dfs: if "Отчет о реализации" not in dfs:
raise Exception(f"В файле {self.file_path.name} отсутствуют необходимые листы") raise Exception(f"В файле {self.file_path.name} отсутствуют необходимые листы")
validated_data = ozon_handler.evaluating(dfs) validated_data = ozon_handler.evaluating(dfs)
@@ -51,19 +51,19 @@ class OZONHandler(BaseHandler):
class OZONPurchasesHandler(BaseHandler): class OZONPurchasesHandler(BaseHandler):
def process(self): def process(self):
#доставать дату и номер документа #доставать дату и номер документа
dfs = self.read(skiprows=12, skipfooter=1) dfs = self.read(skiprows=[0,3,4,5,6,7,8,9,10,11], skipfooter=1)
if "Отчет о выкупленных товарах" not in dfs: if "Отчет о выкупленных товарах" not in dfs:
raise Exception(f"В файле {self.file_path.name} отсутствуют необходимые листы") raise Exception(f"В файле {self.file_path.name} отсутствуют необходимые листы")
validated_data = ozon_purchases_handler.evaluating(dfs) validated_data = ozon_purchases_handler.evaluating(dfs)
print("Выкупы OZON завершены, валидированных строк:", len(validated_data), "Реализация") print("Выкупы OZON завершены, валидированных строк:", len(validated_data[0]), "Реализация", validated_data[1], "Дата")
class WBPurchasesHandler(BaseHandler): class WBPurchasesHandler(BaseHandler):
def process(self): def process(self):
dfs = self.read(skiprows=9, skipfooter=7) dfs = self.read(skiprows=[0,3,4,5,6,7,8], skipfooter=7)
if "Sheet1" not in dfs: if "Sheet1" not in dfs:
raise Exception(f"В файле {self.file_path.name} отсутствуют необходимые листы") raise Exception(f"В файле {self.file_path.name} отсутствуют необходимые листы")
validated_data = wb_purchases_handler.evaluating(dfs) validated_data = wb_purchases_handler.evaluating(dfs)
print("Выкупы WB завершены, валидированных строк:", len(validated_data), "Реализация") print("Выкупы WB завершены, валидированных строк:", len(validated_data[0]), "Реализация", validated_data[1], "Дата" )
class OZONComHandler(BaseHandler): class OZONComHandler(BaseHandler):
def process(self): def process(self):