This commit is contained in:
2026-01-06 18:06:34 +03:00
parent b184dbb234
commit 58e6ef2d98
9 changed files with 112 additions and 68 deletions

View File

@@ -3,13 +3,9 @@ import xml.etree.ElementTree as ET
from base64 import b64encode from base64 import b64encode
from server.backend.schemas.pydantic import settings from server.backend.schemas.pydantic import settings
import pandas as pd import pandas as pd
from server.backend.api.session import get_session
auth_str = f"{settings.USERNAME}:{settings.PASSWORD}" session = get_session({
b64_auth_str = b64encode(auth_str.encode("utf-8")).decode("utf-8")
session = requests.Session()
session.headers.update({
"Authorization": f"Basic {b64_auth_str}",
"Accept": "application/xml", "Accept": "application/xml",
}) })

View File

@@ -3,22 +3,19 @@ import xml.etree.ElementTree as ET
from base64 import b64encode from base64 import b64encode
from server.backend.schemas.pydantic import settings from server.backend.schemas.pydantic import settings
import pandas as pd import pandas as pd
from server.backend.api.session import get_session
auth_str = f"{settings.USERNAME}:{settings.PASSWORD}" session = get_session({
b64_auth_str = b64encode(auth_str.encode("utf-8")).decode("utf-8")
session = requests.Session()
session.headers.update({
"Authorization": f"Basic {b64_auth_str}",
"Accept": "application/xml", "Accept": "application/xml",
}) })
def fetch_contragents():
def fetch_companies():
response = session.get(settings.URL_CONTRACTORS, timeout=10) response = session.get(settings.URL_CONTRACTORS, timeout=10)
response.raise_for_status() response.raise_for_status()
return response.text return response.text
def parse_contragents(xml: str): def parse_companies(xml: str):
try: try:
NS = { NS = {
"atom": "http://www.w3.org/2005/Atom", "atom": "http://www.w3.org/2005/Atom",
@@ -45,6 +42,6 @@ def parse_contragents(xml: str):
except ET.ParseError: except ET.ParseError:
raise raise
def contractor(): def contractor():
xml_data = fetch_contragents() xml_data = fetch_companies()
root = parse_contragents(xml_data) root = parse_companies(xml_data)
root.to_excel("./excel_files/contractors.xlsx") root.to_excel("./excel_files/contractors.xlsx")

View File

@@ -4,21 +4,18 @@ from base64 import b64encode
from server.backend.schemas.pydantic import settings from server.backend.schemas.pydantic import settings
from functools import lru_cache from functools import lru_cache
import pandas as pd import pandas as pd
auth_str = f"{settings.USERNAME}:{settings.PASSWORD}" from server.backend.api.session import get_session
b64_auth_str = b64encode(auth_str.encode("utf-8")).decode("utf-8")
session = requests.Session() session = get_session({
session.headers.update({
"Authorization": f"Basic {b64_auth_str}",
"Accept": "application/xml", "Accept": "application/xml",
}) })
def fetch_contragents(): def fetch_nomenclature():
response = session.get(settings.URL_NOMENCLATURE, timeout=10) response = session.get(settings.URL_NOMENCLATURE, timeout=10)
response.raise_for_status() response.raise_for_status()
return response.text return response.text
def parse_contragents(xml: str): def parse_nomenclature(xml: str):
try: try:
NS = { NS = {
"atom": "http://www.w3.org/2005/Atom", "atom": "http://www.w3.org/2005/Atom",
@@ -45,8 +42,8 @@ def parse_contragents(xml: str):
raise raise
@lru_cache(maxsize=1) @lru_cache(maxsize=1)
def nomenclature(flag=False): def nomenclature(flag=False):
xml_data = fetch_contragents() xml_data = fetch_nomenclature()
root = parse_contragents(xml_data) root = parse_nomenclature(xml_data)
if flag: if flag:
root.to_excel("./excel_files/nomenclature.xlsx") root.to_excel("./excel_files/nomenclature.xlsx")
return root return root

View File

@@ -1,20 +1,30 @@
import requests import requests
import json import json
from base64 import b64encode
from server.backend.schemas.pydantic import settings
import pandas as pd import pandas as pd
auth_str = f"{settings.USERNAME}:{settings.PASSWORD}" from server.backend.schemas.pydantic import settings, CreateDocumentParams
b64_auth_str = b64encode(auth_str.encode("utf-8")).decode("utf-8") from server.backend.api.session import get_session
session = requests.Session() session = get_session({
session.headers.update({
"Authorization": f"Basic {b64_auth_str}",
"Content-Type": "application/json", "Content-Type": "application/json",
"Accept": "application/json" "Accept": "application/json",
}) })
def fetch_contragents(): def create_document(params: CreateDocumentParams) -> int:
response = session.post(settings.URL_REPORT, data=json.dumps(data)) data = {
response.raise_for_status() "Дата": params.DATE,
return response.status_code #"ВидОперации": params.OPERATION,
"Организация_Key": settings.COMPANY,
"Контрагент_Key": params.CONTRACTOR,
"Склад_Key": settings.STORE,
"ДоговорКонтрагента_Key": params.CONTRACT,
"ДокументБезНДС": "false",
"СуммаВключаетНДС": "true",
"СчетУчетаРасчетовЗаПосредническиеУслуги_Key": params.ACCOUNT_INTERMEDIARY_SERVICES,
"СчетУчетаРасчетовПоАвансамПолученным_Key": params.ACCOUNT_ADVANCES_RECEIVED,
"СчетУчетаРасчетовПоАвансамВыданным_Key": params.ACCOUNT_ADVANCES_ISSUED,
"СчетУчетаРасчетовСКонтрагентом_Key": params.ACCOUNT_WITH_COUNTERPARTY,
}
response = session.post(settings.URL_REALISATION, json=data)
response.raise_for_status()
return response.status_code

View File

@@ -1,20 +1,30 @@
import requests import requests
import json import json
from base64 import b64encode
from server.backend.schemas.pydantic import settings
import pandas as pd import pandas as pd
auth_str = f"{settings.USERNAME}:{settings.PASSWORD}" from server.backend.schemas.pydantic import settings, CreateDocumentParams
b64_auth_str = b64encode(auth_str.encode("utf-8")).decode("utf-8") from server.backend.api.session import get_session
session = requests.Session() session = get_session({
session.headers.update({
"Authorization": f"Basic {b64_auth_str}",
"Content-Type": "application/json", "Content-Type": "application/json",
"Accept": "application/json" "Accept": "application/json",
}) })
def fetch_contragents(): def create_document(params: CreateDocumentParams) -> int:
response = session.post(settings.URL_REPORT, data=json.dumps(data)) data = {
response.raise_for_status() "Дата": params.DATE,
return response.status_code "ВидОперации": params.OPERATION,
"Организация_Key": settings.COMPANY,
"Контрагент_Key": params.CONTRACTOR,
"Склад_Key": settings.STORE,
"ДоговорКонтрагента_Key": params.CONTRACT,
"ДокументБезНДС": "false",
"СуммаВключаетНДС": "true",
"СчетУчетаРасчетовЗаПосредническиеУслуги_Key": params.ACCOUNT_INTERMEDIARY_SERVICES,
"СчетУчетаРасчетовПоАвансамПолученным_Key": params.ACCOUNT_ADVANCES_RECEIVED,
"СчетУчетаРасчетовПоАвансамВыданным_Key": params.ACCOUNT_ADVANCES_ISSUED,
"СчетУчетаРасчетовСКонтрагентом_Key": params.ACCOUNT_WITH_COUNTERPARTY,
}
response = session.post(settings.URL_REPORT, json=data)
response.raise_for_status()
return response.status_code

View File

@@ -0,0 +1,20 @@
import requests
from base64 import b64encode
from server.backend.schemas.pydantic import settings
def get_session(extra_headers=None):
"""
Создаёт и возвращает requests.Session с базовой авторизацией.
Можно менять username, password и добавлять дополнительные заголовки.
"""
session = requests.Session()
auth_str = f"{settings.USERNAME}:{settings.PASSWORD}"
b64_auth_str = b64encode(auth_str.encode("utf-8")).decode("utf-8")
headers = {
"Authorization": f"Basic {b64_auth_str}",
"Accept": "application/json"
}
if extra_headers:
headers.update(extra_headers)
session.headers.update(headers)
return session

View File

@@ -3,22 +3,19 @@ import xml.etree.ElementTree as ET
from base64 import b64encode from base64 import b64encode
from server.backend.schemas.pydantic import settings from server.backend.schemas.pydantic import settings
import pandas as pd import pandas as pd
from server.backend.api.session import get_session
auth_str = f"{settings.USERNAME}:{settings.PASSWORD}" session = get_session({
b64_auth_str = b64encode(auth_str.encode("utf-8")).decode("utf-8")
session = requests.Session()
session.headers.update({
"Authorization": f"Basic {b64_auth_str}",
"Accept": "application/xml", "Accept": "application/xml",
}) })
def fetch_contragents():
def fetch_stores():
response = session.get(settings.URL_STORAGES, timeout=10) response = session.get(settings.URL_STORAGES, timeout=10)
response.raise_for_status() response.raise_for_status()
return response.text return response.text
def parse_contragents(xml: str): def parse_stores(xml: str):
try: try:
NS = { NS = {
"atom": "http://www.w3.org/2005/Atom", "atom": "http://www.w3.org/2005/Atom",
@@ -41,6 +38,6 @@ def parse_contragents(xml: str):
except ET.ParseError: except ET.ParseError:
raise raise
def storages(): def storages():
xml_data = fetch_contragents() xml_data = fetch_stores()
root = parse_contragents(xml_data) root = parse_stores(xml_data)
root.to_excel("./excel_files/storages.xlsx") root.to_excel("./excel_files/storages.xlsx")

View File

@@ -29,9 +29,9 @@ class Settings(BaseSettings):
CONTRAGENT_RWB:str CONTRAGENT_RWB:str
CONTRAGENT_OZON:str CONTRAGENT_OZON:str
CONTRAGENT_YANDEX:str CONTRAGENT_YANDEX:str
CONTRACT_RWB0:str CONTRACT_RWB:str
CONTRACT_RWB1:str CONTRACT_YAN:str
CONTRACT_RWB2:str CONTRACT_OZON:str
MEASURE:str MEASURE:str
A60_01:str A60_01:str
A62_02:str A62_02:str
@@ -60,5 +60,13 @@ class Translit():
'Т': 'T', 'Т': 'T',
'Х': 'X', 'Х': 'X',
} }
class CreateDocumentParams(BaseModel):
DATE: str = Field(..., min_length=1)
OPERATION: str = Field(..., min_length=1)
CONTRACTOR: str = Field(..., min_length=1)
CONTRACT: str = Field(..., min_length=1)
ACCOUNT_INTERMEDIARY_SERVICES: str = Field(..., min_length=1)
ACCOUNT_ADVANCES_RECEIVED: str = Field(..., min_length=1)
ACCOUNT_ADVANCES_ISSUED: str = Field(..., min_length=1)
ACCOUNT_WITH_COUNTERPARTY: str = Field(..., min_length=1)
settings = Settings() settings = Settings()

View File

@@ -5,6 +5,7 @@ import server.backend.handlers.ozon_handler as ozon_handler
import server.backend.handlers.ozon_purchases_handler as ozon_purchases_handler import server.backend.handlers.ozon_purchases_handler as ozon_purchases_handler
import server.backend.handlers.wb_purchases_handler as wb_purchases_handler import server.backend.handlers.wb_purchases_handler as wb_purchases_handler
import server.backend.handlers.ozon_wb_yandex_com_handler as ozon_wb_yandex_com_handler import server.backend.handlers.ozon_wb_yandex_com_handler as ozon_wb_yandex_com_handler
from server.backend.schemas.pydantic import settings, CreateDocumentParams
class BaseHandler: class BaseHandler:
def __init__(self, file_path): def __init__(self, file_path):
self.file_path = file_path self.file_path = file_path
@@ -21,8 +22,6 @@ class BaseHandler:
class YandexHandler(BaseHandler): class YandexHandler(BaseHandler):
def process(self): def process(self):
# читаем Excel внутри объекта
#доставать дату
dfs = self.read(skiprows=[0,1,3]) dfs = self.read(skiprows=[0,1,3])
# проверяем наличие нужных листов # проверяем наличие нужных листов
if "Получено от потребителей" not in dfs or "Возвращено потребителям" not in dfs: if "Получено от потребителей" not in dfs or "Возвращено потребителям" not in dfs:
@@ -30,11 +29,13 @@ class YandexHandler(BaseHandler):
# вызываем функцию evaluating # вызываем функцию evaluating
validated_data = yandex_handler.evaluating(dfs) validated_data = yandex_handler.evaluating(dfs)
print("Реализация Яндекс завершена, валидированных строк:", len(validated_data[0]), "Реализация", len(validated_data[1]), "Возвраты", validated_data[2], "Дата") print("Реализация Яндекс завершена, валидированных строк:", len(validated_data[0]), "Реализация", len(validated_data[1]), "Возвраты", validated_data[2], "Дата")
status = create_document(params)
print(status)
class WBHandler(BaseHandler): class WBHandler(BaseHandler):
def process(self): def process(self):
dfs = self.read() dfs = self.read()
#доставать дату по месяцу и просто день ставить последний
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_handler.evaluating(dfs) validated_data = wb_handler.evaluating(dfs)
@@ -42,7 +43,6 @@ class WBHandler(BaseHandler):
class OZONHandler(BaseHandler): class OZONHandler(BaseHandler):
def process(self): def process(self):
#Доставать № документа и дату
dfs = self.read(skiprows=14, 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} отсутствуют необходимые листы")
@@ -50,12 +50,21 @@ class OZONHandler(BaseHandler):
print("Реализация OZON завершена, валидированных строк:", len(validated_data[0]), "Реализация", len(validated_data[1]), "Возвраты", validated_data[2], "Дата") print("Реализация OZON завершена, валидированных строк:", len(validated_data[0]), "Реализация", len(validated_data[1]), "Возвраты", validated_data[2], "Дата")
class OZONPurchasesHandler(BaseHandler): class OZONPurchasesHandler(BaseHandler):
def process(self): def process(self):
#доставать дату и номер документа
dfs = self.read(skiprows=[0,3,4,5,6,7,8,9,10,11], 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[0]), "Реализация", validated_data[1], "Дата") print("Выкупы OZON завершены, валидированных строк:", len(validated_data[0]), "Реализация", validated_data[1], "Дата")
params = CreateDocumentParams(
DATE=validated_data[1],
OPERATION="ВыкупТоваровКомиссионером",
CONTRACTOR=settings.CONTRAGENT_OZON,
CONTRACT=settings.CONTRACT_OZON,
ACCOUNT_INTERMEDIARY_SERVICES=settings.A60_01,
ACCOUNT_ADVANCES_RECEIVED=settings.A62_02,
ACCOUNT_ADVANCES_ISSUED=settings.A60_02,
ACCOUNT_WITH_COUNTERPARTY=settings.A62_01)
print(params)
class WBPurchasesHandler(BaseHandler): class WBPurchasesHandler(BaseHandler):
def process(self): def process(self):