diff --git a/server/backend/api/companies.py b/server/backend/api/companies.py index 822978e..40ad4ef 100644 --- a/server/backend/api/companies.py +++ b/server/backend/api/companies.py @@ -3,13 +3,9 @@ import xml.etree.ElementTree as ET from base64 import b64encode from server.backend.schemas.pydantic import settings import pandas as pd +from server.backend.api.session import get_session -auth_str = f"{settings.USERNAME}:{settings.PASSWORD}" -b64_auth_str = b64encode(auth_str.encode("utf-8")).decode("utf-8") - -session = requests.Session() -session.headers.update({ - "Authorization": f"Basic {b64_auth_str}", +session = get_session({ "Accept": "application/xml", }) diff --git a/server/backend/api/contractors.py b/server/backend/api/contractors.py index d2afa40..12e63f2 100644 --- a/server/backend/api/contractors.py +++ b/server/backend/api/contractors.py @@ -3,22 +3,19 @@ import xml.etree.ElementTree as ET from base64 import b64encode from server.backend.schemas.pydantic import settings import pandas as pd +from server.backend.api.session import get_session -auth_str = f"{settings.USERNAME}:{settings.PASSWORD}" -b64_auth_str = b64encode(auth_str.encode("utf-8")).decode("utf-8") - -session = requests.Session() -session.headers.update({ - "Authorization": f"Basic {b64_auth_str}", +session = get_session({ "Accept": "application/xml", }) -def fetch_contragents(): + +def fetch_companies(): response = session.get(settings.URL_CONTRACTORS, timeout=10) response.raise_for_status() return response.text -def parse_contragents(xml: str): +def parse_companies(xml: str): try: NS = { "atom": "http://www.w3.org/2005/Atom", @@ -45,6 +42,6 @@ def parse_contragents(xml: str): except ET.ParseError: raise def contractor(): - xml_data = fetch_contragents() - root = parse_contragents(xml_data) + xml_data = fetch_companies() + root = parse_companies(xml_data) root.to_excel("./excel_files/contractors.xlsx") \ No newline at end of file diff --git a/server/backend/api/nomenclature.py b/server/backend/api/nomenclature.py index 71f3953..7969b30 100644 --- a/server/backend/api/nomenclature.py +++ b/server/backend/api/nomenclature.py @@ -4,21 +4,18 @@ from base64 import b64encode from server.backend.schemas.pydantic import settings from functools import lru_cache import pandas as pd -auth_str = f"{settings.USERNAME}:{settings.PASSWORD}" -b64_auth_str = b64encode(auth_str.encode("utf-8")).decode("utf-8") +from server.backend.api.session import get_session -session = requests.Session() -session.headers.update({ - "Authorization": f"Basic {b64_auth_str}", +session = get_session({ "Accept": "application/xml", }) -def fetch_contragents(): +def fetch_nomenclature(): response = session.get(settings.URL_NOMENCLATURE, timeout=10) response.raise_for_status() return response.text -def parse_contragents(xml: str): +def parse_nomenclature(xml: str): try: NS = { "atom": "http://www.w3.org/2005/Atom", @@ -45,8 +42,8 @@ def parse_contragents(xml: str): raise @lru_cache(maxsize=1) def nomenclature(flag=False): - xml_data = fetch_contragents() - root = parse_contragents(xml_data) + xml_data = fetch_nomenclature() + root = parse_nomenclature(xml_data) if flag: root.to_excel("./excel_files/nomenclature.xlsx") return root diff --git a/server/backend/api/realisation.py b/server/backend/api/realisation.py index 0057c07..72127da 100644 --- a/server/backend/api/realisation.py +++ b/server/backend/api/realisation.py @@ -1,20 +1,30 @@ import requests import json -from base64 import b64encode -from server.backend.schemas.pydantic import settings import pandas as pd -auth_str = f"{settings.USERNAME}:{settings.PASSWORD}" -b64_auth_str = b64encode(auth_str.encode("utf-8")).decode("utf-8") +from server.backend.schemas.pydantic import settings, CreateDocumentParams +from server.backend.api.session import get_session -session = requests.Session() -session.headers.update({ - "Authorization": f"Basic {b64_auth_str}", +session = get_session({ "Content-Type": "application/json", - "Accept": "application/json" + "Accept": "application/json", }) -def fetch_contragents(): - response = session.post(settings.URL_REPORT, data=json.dumps(data)) - response.raise_for_status() - return response.status_code +def create_document(params: CreateDocumentParams) -> int: + data = { + "Дата": params.DATE, + #"ВидОперации": 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 \ No newline at end of file diff --git a/server/backend/api/report.py b/server/backend/api/report.py index 0057c07..c15ad74 100644 --- a/server/backend/api/report.py +++ b/server/backend/api/report.py @@ -1,20 +1,30 @@ import requests import json -from base64 import b64encode -from server.backend.schemas.pydantic import settings import pandas as pd -auth_str = f"{settings.USERNAME}:{settings.PASSWORD}" -b64_auth_str = b64encode(auth_str.encode("utf-8")).decode("utf-8") +from server.backend.schemas.pydantic import settings, CreateDocumentParams +from server.backend.api.session import get_session -session = requests.Session() -session.headers.update({ - "Authorization": f"Basic {b64_auth_str}", +session = get_session({ "Content-Type": "application/json", - "Accept": "application/json" + "Accept": "application/json", }) -def fetch_contragents(): - response = session.post(settings.URL_REPORT, data=json.dumps(data)) - response.raise_for_status() - return response.status_code +def create_document(params: CreateDocumentParams) -> int: + data = { + "Дата": params.DATE, + "ВидОперации": 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 \ No newline at end of file diff --git a/server/backend/api/session.py b/server/backend/api/session.py new file mode 100644 index 0000000..0405704 --- /dev/null +++ b/server/backend/api/session.py @@ -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 \ No newline at end of file diff --git a/server/backend/api/storages.py b/server/backend/api/storages.py index 77122cd..4205ef1 100644 --- a/server/backend/api/storages.py +++ b/server/backend/api/storages.py @@ -3,22 +3,19 @@ import xml.etree.ElementTree as ET from base64 import b64encode from server.backend.schemas.pydantic import settings import pandas as pd +from server.backend.api.session import get_session -auth_str = f"{settings.USERNAME}:{settings.PASSWORD}" -b64_auth_str = b64encode(auth_str.encode("utf-8")).decode("utf-8") - -session = requests.Session() -session.headers.update({ - "Authorization": f"Basic {b64_auth_str}", +session = get_session({ "Accept": "application/xml", }) -def fetch_contragents(): + +def fetch_stores(): response = session.get(settings.URL_STORAGES, timeout=10) response.raise_for_status() return response.text -def parse_contragents(xml: str): +def parse_stores(xml: str): try: NS = { "atom": "http://www.w3.org/2005/Atom", @@ -41,6 +38,6 @@ def parse_contragents(xml: str): except ET.ParseError: raise def storages(): - xml_data = fetch_contragents() - root = parse_contragents(xml_data) + xml_data = fetch_stores() + root = parse_stores(xml_data) root.to_excel("./excel_files/storages.xlsx") \ No newline at end of file diff --git a/server/backend/schemas/pydantic.py b/server/backend/schemas/pydantic.py index ac6b70b..0903e53 100644 --- a/server/backend/schemas/pydantic.py +++ b/server/backend/schemas/pydantic.py @@ -29,9 +29,9 @@ class Settings(BaseSettings): CONTRAGENT_RWB:str CONTRAGENT_OZON:str CONTRAGENT_YANDEX:str - CONTRACT_RWB0:str - CONTRACT_RWB1:str - CONTRACT_RWB2:str + CONTRACT_RWB:str + CONTRACT_YAN:str + CONTRACT_OZON:str MEASURE:str A60_01:str A62_02:str @@ -60,5 +60,13 @@ class Translit(): 'Т': 'T', 'Х': '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() \ No newline at end of file diff --git a/server/backend/services/excel.py b/server/backend/services/excel.py index fe8d07e..99df4b3 100644 --- a/server/backend/services/excel.py +++ b/server/backend/services/excel.py @@ -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.wb_purchases_handler as wb_purchases_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: def __init__(self, file_path): self.file_path = file_path @@ -21,8 +22,6 @@ class BaseHandler: class YandexHandler(BaseHandler): def process(self): - # читаем Excel внутри объекта - #доставать дату dfs = self.read(skiprows=[0,1,3]) # проверяем наличие нужных листов if "Получено от потребителей" not in dfs or "Возвращено потребителям" not in dfs: @@ -30,11 +29,13 @@ class YandexHandler(BaseHandler): # вызываем функцию evaluating validated_data = yandex_handler.evaluating(dfs) print("Реализация Яндекс завершена, валидированных строк:", len(validated_data[0]), "Реализация", len(validated_data[1]), "Возвраты", validated_data[2], "Дата") + status = create_document(params) + print(status) + class WBHandler(BaseHandler): def process(self): dfs = self.read() - #доставать дату по месяцу и просто день ставить последний if "Sheet1" not in dfs : raise Exception(f"В файле {self.file_path.name} отсутствуют необходимые листы") validated_data = wb_handler.evaluating(dfs) @@ -42,7 +43,6 @@ class WBHandler(BaseHandler): class OZONHandler(BaseHandler): def process(self): - #Доставать № документа и дату dfs = self.read(skiprows=14, skipfooter=17) if "Отчет о реализации" not in dfs: 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], "Дата") class OZONPurchasesHandler(BaseHandler): def process(self): - #доставать дату и номер документа dfs = self.read(skiprows=[0,3,4,5,6,7,8,9,10,11], skipfooter=1) if "Отчет о выкупленных товарах" not in dfs: raise Exception(f"В файле {self.file_path.name} отсутствуют необходимые листы") validated_data = ozon_purchases_handler.evaluating(dfs) 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): def process(self):