Добавлен статус заказа и общие действия в декораторах
This commit is contained in:
@@ -45,7 +45,7 @@ class MailOrderBot(ConfigManager):
|
|||||||
|
|
||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
# Получить список айдишников письма
|
#Получить список айдишников письма
|
||||||
|
|
||||||
folder = self.config.get("folder")
|
folder = self.config.get("folder")
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ class ExcelFileParcer:
|
|||||||
|
|
||||||
def _parse_file(self, file_bytes):
|
def _parse_file(self, file_bytes):
|
||||||
"""Парсит вложение в формате эл таблиц"""
|
"""Парсит вложение в формате эл таблиц"""
|
||||||
try:
|
df = pd.read_excel(file_bytes, sheet_name=self.sheet_name, header=None)
|
||||||
df = pd.read_excel(file_bytes, sheet_name=self.sheet_name, header=None)
|
|
||||||
except Exception as e:
|
|
||||||
df = None
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
def set_value(self, sku, manufacturer, column, value):
|
def set_value(self, sku, manufacturer, column, value):
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
from .processor import TaskProcessor
|
from .processor import TaskProcessor
|
||||||
from .message import LogMessage, LogMessageLevel, LogMessageStorage
|
from .message import LogMessage, LogMessageLevel, LogMessageStorage
|
||||||
|
|
||||||
|
from .abstract_task import AbstractTask, pass_if_error, handle_errors
|
||||||
@@ -1,11 +1,60 @@
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import Dict, Any
|
import logging
|
||||||
|
import functools
|
||||||
|
|
||||||
from mail_order_bot.context import Context
|
from mail_order_bot.context import Context
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_errors(func):
|
||||||
|
"""
|
||||||
|
Декоратор для обработки ошибок в методе do класса AbstractTask.
|
||||||
|
Оборачивает выполнение метода в try-except, при ошибке устанавливает статус "error",
|
||||||
|
логирует ошибку и пробрасывает исключение дальше.
|
||||||
|
Применяется везде к методу do.
|
||||||
|
"""
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrapper(self, attachment) -> None:
|
||||||
|
file_name = attachment.get("name", "неизвестный файл")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Выполняем метод do
|
||||||
|
return func(self, attachment)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# При ошибке устанавливаем статус и логируем
|
||||||
|
if attachment:
|
||||||
|
attachment["status"] = "error"
|
||||||
|
logger.error(f"Ошибка при обработке файла {file_name} на стадии {self.STEP} \n{e}", exc_info=True)
|
||||||
|
# Пробрасываем исключение дальше
|
||||||
|
# raise
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def pass_if_error(func):
|
||||||
|
"""
|
||||||
|
Декоратор для проверки статуса attachment перед выполнением метода do.
|
||||||
|
Если статус attachment["status"] != "ok", метод не выполняется.
|
||||||
|
Применяется опционально в конкретных классах, где нужна проверка статуса.
|
||||||
|
"""
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrapper(self, attachment) -> None:
|
||||||
|
# Проверяем статус перед выполнением
|
||||||
|
if attachment and attachment.get("status") != "ok":
|
||||||
|
file_name = attachment.get("name", "неизвестный файл")
|
||||||
|
logger.warning(f"Пропускаем шаг для файла {file_name}, статус {attachment.get('status')}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Выполняем метод do
|
||||||
|
return func(self, attachment)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
class AbstractTask():
|
class AbstractTask():
|
||||||
RESULT_SECTION = "section"
|
STEP = "Название шага обработки"
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Абстрактный базовый класс для всех хэндлеров.
|
Абстрактный базовый класс для всех хэндлеров.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
from .abcp.api_get_stock import APIGetStock
|
from .abcp._api_get_stock import APIGetStock
|
||||||
from .delivery_time.local_store import DeliveryPeriodLocalStore
|
from .delivery_time.local_store import DeliveryPeriodLocalStore
|
||||||
from .delivery_time.from_config import DeliveryPeriodFromConfig
|
from .delivery_time.from_config import DeliveryPeriodFromConfig
|
||||||
from .notifications.test_notifier import TestNotifier
|
from .notifications.test_notifier import TestNotifier
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class APIGetStock(AbstractTask):
|
|||||||
self.client_provider = AbcpProvider(login=client_login, password=client_password)
|
self.client_provider = AbcpProvider(login=client_login, password=client_password)
|
||||||
|
|
||||||
def do(self, attachment) -> None:
|
def do(self, attachment) -> None:
|
||||||
|
#
|
||||||
order = attachment.get("order", None)
|
order = attachment.get("order", None)
|
||||||
for position in order.positions:
|
for position in order.positions:
|
||||||
# Получаем остатки из-под учетной записи клиента
|
# Получаем остатки из-под учетной записи клиента
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from mail_order_bot.task_processor.abstract_task import AbstractTask
|
from ...abstract_task import AbstractTask, pass_if_error, handle_errors
|
||||||
from mail_order_bot.abcp_api.abcp_provider import AbcpProvider
|
from mail_order_bot.abcp_api.abcp_provider import AbcpProvider
|
||||||
from mail_order_bot.credential_provider import CredentialProvider
|
from mail_order_bot.credential_provider import CredentialProvider
|
||||||
|
|
||||||
@@ -14,47 +14,47 @@ from mail_order_bot.telegram.client import TelegramClient
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SaveOrderToTelegram(AbstractTask):
|
class SaveOrderToTelegram(AbstractTask):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
@pass_if_error
|
||||||
|
@handle_errors
|
||||||
def do(self, attachment) -> None:
|
def do(self, attachment) -> None:
|
||||||
client = TelegramClient()
|
client = TelegramClient()
|
||||||
|
|
||||||
try:
|
order = attachment["order"]
|
||||||
order = attachment["order"]
|
positions = order.positions
|
||||||
positions = order.positions
|
message = "\nОбработка заказа {указать название контрагента}\n"
|
||||||
message = "\nОбработка заказа {указать название контрагента}\n"
|
message += f"\nПолучено {len(positions)} позиций от {order.client_id}\n"
|
||||||
message += f"\nПолучено {len(positions)} позиций от {order.client_id}\n"
|
message += "===============================\n"
|
||||||
message += "===============================\n"
|
for position in positions:
|
||||||
for position in positions:
|
message += f"{position.sku} - {position.manufacturer} - {position.name} \n"
|
||||||
message += f"{position.sku} - {position.manufacturer} - {position.name} \n"
|
message += f"{position.asking_quantity} x {position.asking_price} = {position.total} \n"
|
||||||
message += f"{position.asking_quantity} x {position.asking_price} = {position.total} \n"
|
|
||||||
|
|
||||||
rejected = position.asking_quantity - position.order_quantity
|
rejected = position.asking_quantity - position.order_quantity
|
||||||
if position.order_quantity == 0:
|
if position.order_quantity == 0:
|
||||||
message += f"Отказ\n"
|
message += f"Отказ\n"
|
||||||
elif rejected:
|
elif rejected:
|
||||||
message += (f"Отказ: {rejected}, запрошено, {position.asking_quantity}, "
|
message += (f"Отказ: {rejected}, запрошено, {position.asking_quantity}, "
|
||||||
f"отгружено {position.order_quantity}, профит {position.profit}\n")
|
f"отгружено {position.order_quantity}, профит {position.profit}\n")
|
||||||
else:
|
else:
|
||||||
message += f"Позиция отгружена полностью, профит {position.profit}\n"
|
message += f"Позиция отгружена полностью, профит {position.profit}\n"
|
||||||
message += "-------------------------------\n"
|
message += "-------------------------------\n"
|
||||||
|
|
||||||
result = client.send_message(message)
|
result = client.send_message(message)
|
||||||
|
|
||||||
# Отправка экселя в телеграм
|
# Отправка экселя в телеграм
|
||||||
excel = attachment["excel"]
|
excel = attachment["excel"]
|
||||||
file = excel.get_file_bytes()
|
file = excel.get_file_bytes()
|
||||||
|
|
||||||
client.send_document(
|
client.send_document(
|
||||||
document=file,
|
document=file,
|
||||||
filename="document.xlsx"
|
filename="document.xlsx"
|
||||||
)
|
)
|
||||||
except Exception as e:
|
|
||||||
logger.error("Ошибка при отправке инфо по заказу в телеграм")
|
logger.warning("Инфо по заказу отправлено в телеграм")
|
||||||
else:
|
|
||||||
logger.warning("Инфо по заказу отправлено в телеграм")
|
|
||||||
|
|
||||||
#===============================
|
#===============================
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from mail_order_bot.task_processor.abstract_task import AbstractTask
|
from ...abstract_task import AbstractTask, pass_if_error, handle_errors
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -13,17 +13,9 @@ class DeliveryPeriodFromConfig(AbstractTask):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
@pass_if_error
|
||||||
|
@handle_errors
|
||||||
def do(self, attachment) -> None:
|
def do(self, attachment) -> None:
|
||||||
try:
|
delivery_period = self.config.get("delivery_period")
|
||||||
delivery_period = self.config.get("delivery_period")
|
attachment["delivery_period"] = delivery_period
|
||||||
|
logger.warning(f"Срок доставки установлен из конфига - {delivery_period} (ч.)")
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Ошибка при получении срока доставки из конфига: {e}")
|
|
||||||
|
|
||||||
else:
|
|
||||||
attachment["delivery_period"] = delivery_period
|
|
||||||
logger.warning(f"Срок доставки установлен из конфига - {delivery_period} (ч.)")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
Парсер срока доставки из темы письма
|
Парсер срока доставки из темы письма
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from mail_order_bot.task_processor.abstract_task import AbstractTask
|
from ...abstract_task import AbstractTask, pass_if_error, handle_errors
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from mail_order_bot.task_processor.abstract_task import AbstractTask
|
from ...abstract_task import AbstractTask, pass_if_error, handle_errors
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from mail_order_bot.task_processor.abstract_task import AbstractTask
|
from ...abstract_task import AbstractTask, pass_if_error, handle_errors
|
||||||
from mail_order_bot.email_client.utils import EmailUtils
|
from mail_order_bot.email_client.utils import EmailUtils
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from email.utils import formatdate
|
|||||||
from email import encoders
|
from email import encoders
|
||||||
|
|
||||||
|
|
||||||
from mail_order_bot.task_processor.abstract_task import AbstractTask
|
from ...abstract_task import AbstractTask, pass_if_error, handle_errors
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -19,40 +19,40 @@ class EmailReplyTask(AbstractTask):
|
|||||||
"""Формирует ответ на входящее письмо с запросом на заказ°"""
|
"""Формирует ответ на входящее письмо с запросом на заказ°"""
|
||||||
EMAIl = "zosimovaa@yandex.ru" #"noreply@zapchastiya.ru"
|
EMAIl = "zosimovaa@yandex.ru" #"noreply@zapchastiya.ru"
|
||||||
|
|
||||||
|
@pass_if_error
|
||||||
|
@handle_errors
|
||||||
def do(self, attachment):
|
def do(self, attachment):
|
||||||
|
|
||||||
try:
|
email = self.context.data.get("email")
|
||||||
email = self.context.data.get("email")
|
|
||||||
|
|
||||||
if not email:
|
if not email:
|
||||||
raise ValueError("В контексте нет входящего сообщения")
|
raise ValueError("В контексте нет входящего сообщения")
|
||||||
|
|
||||||
email_from = self.context.data.get("email_from")
|
email_from = self.context.data.get("email_from")
|
||||||
if not email_from:
|
if not email_from:
|
||||||
raise ValueError("В контексте не определен адрес отправителя")
|
raise ValueError("В контексте не определен адрес отправителя")
|
||||||
|
|
||||||
|
|
||||||
reply_message = MIMEMultipart()
|
reply_message = MIMEMultipart()
|
||||||
|
|
||||||
email_subj = self.context.data.get("email_subj")
|
email_subj = self.context.data.get("email_subj")
|
||||||
|
|
||||||
reply_message["From"] = self.EMAIl
|
reply_message["From"] = self.EMAIl
|
||||||
reply_message["To"] = email_from
|
reply_message["To"] = email_from
|
||||||
#reply_message["Cc"] = self.config.get("reply_to", "")
|
#reply_message["Cc"] = self.config.get("reply_to", "")
|
||||||
reply_message["Subject"] = f"Re: {email_subj}"
|
reply_message["Subject"] = f"Re: {email_subj}"
|
||||||
reply_message["Date"] = formatdate(localtime=True)
|
reply_message["Date"] = formatdate(localtime=True)
|
||||||
|
|
||||||
body = "Автоматический ответ на создание заказа"
|
body = "Автоматический ответ на создание заказа"
|
||||||
reply_message.attach(MIMEText(body, "plain", "utf-8"))
|
reply_message.attach(MIMEText(body, "plain", "utf-8"))
|
||||||
|
|
||||||
|
|
||||||
self._attach_file(reply_message, attachment)
|
self._attach_file(reply_message, attachment)
|
||||||
|
|
||||||
|
self.context.email_client.send_email(reply_message)
|
||||||
|
|
||||||
|
logger.warning(f"Сформирован ответ на заказ на email")
|
||||||
|
|
||||||
self.context.email_client.send_email(reply_message)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Ошибка при отправке ответа по заказу на email \n{e}")
|
|
||||||
else:
|
|
||||||
logger.warning(f"Сформирован ответ на заказ на email")
|
|
||||||
|
|
||||||
def _attach_file(self, reply_message, attachment):
|
def _attach_file(self, reply_message, attachment):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import pandas as pd
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
from ...abstract_task import AbstractTask, pass_if_error, handle_errors
|
||||||
from mail_order_bot.email_client import EmailUtils
|
from ....parsers.excel_parcer import ExcelFileParcer
|
||||||
#from mail_order_bot.task_processor.handlers.order_position import OrderPosition
|
|
||||||
from mail_order_bot.task_processor.abstract_task import AbstractTask
|
|
||||||
|
|
||||||
from mail_order_bot.parsers.excel_parcer import ExcelFileParcer
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -19,20 +14,10 @@ class ExcelExtractor(AbstractTask):
|
|||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.excel_config = self.config.get("excel", {})
|
self.excel_config = self.config.get("excel", {})
|
||||||
|
|
||||||
|
@pass_if_error
|
||||||
|
@handle_errors
|
||||||
def do(self, attachment) -> None:
|
def do(self, attachment) -> None:
|
||||||
try:
|
file_bytes = BytesIO(attachment['bytes'])
|
||||||
file_bytes = BytesIO(attachment['bytes'])
|
excel_file = ExcelFileParcer(file_bytes, self.excel_config)
|
||||||
excel_file = ExcelFileParcer(file_bytes, self.excel_config)
|
attachment["excel"] = excel_file
|
||||||
|
logger.warning(f"Произведен успешный парсинг файла {attachment.get('name', 'неизвестный файл')}")
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Не удалось распарсить файл: \n{e}")
|
|
||||||
attachment["excel"] = None
|
|
||||||
|
|
||||||
else:
|
|
||||||
attachment["excel"] = excel_file
|
|
||||||
logger.warning(f"Произведен успешный парсинг файла")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import logging
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from mail_order_bot.parsers.order_parcer import OrderParser
|
from mail_order_bot.parsers.order_parcer import OrderParser
|
||||||
from mail_order_bot.task_processor.abstract_task import AbstractTask
|
from ...abstract_task import AbstractTask, pass_if_error, handle_errors
|
||||||
|
|
||||||
from mail_order_bot.parsers.excel_parcer import ExcelFileParcer
|
from mail_order_bot.parsers.excel_parcer import ExcelFileParcer
|
||||||
|
|
||||||
@@ -10,6 +10,7 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class OrderExtractor(AbstractTask):
|
class OrderExtractor(AbstractTask):
|
||||||
|
STEP = "Извлечение заказа"
|
||||||
"""
|
"""
|
||||||
Хендлер для каждого вложения считывает эксель файл и сохраняет его контекст
|
Хендлер для каждого вложения считывает эксель файл и сохраняет его контекст
|
||||||
"""
|
"""
|
||||||
@@ -17,28 +18,24 @@ class OrderExtractor(AbstractTask):
|
|||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.excel_config = self.config.get("excel", {})
|
self.excel_config = self.config.get("excel", {})
|
||||||
|
|
||||||
|
@pass_if_error
|
||||||
|
@handle_errors
|
||||||
def do(self, attachment) -> None:
|
def do(self, attachment) -> None:
|
||||||
# todo сделать проверку на наличие файла и его тип
|
# todo сделать проверку на наличие файла и его тип
|
||||||
|
delivery_period = attachment.get("delivery_period", 0)
|
||||||
|
mapping = self.excel_config.get("mapping")
|
||||||
|
|
||||||
try:
|
excel_file = attachment.get("excel")
|
||||||
delivery_period = attachment.get("delivery_period", 0)
|
client_id = self.config.get("client_id")
|
||||||
mapping = self.excel_config.get("mapping")
|
|
||||||
|
|
||||||
excel_file = attachment.get("excel")
|
order_parcer = OrderParser(mapping, delivery_period, client_id)
|
||||||
client_id = self.config.get("client_id")
|
|
||||||
|
|
||||||
order_parcer = OrderParser(mapping, delivery_period, client_id)
|
order_dataframe = excel_file.get_order_rows()
|
||||||
|
order = order_parcer.parse(order_dataframe)
|
||||||
|
|
||||||
order_dataframe = excel_file.get_order_rows()
|
attachment["order"] = order
|
||||||
order = order_parcer.parse(order_dataframe)
|
|
||||||
|
|
||||||
except Exception as e:
|
logger.warning(f"Файл заказа обработан успешно, извлечено {len(order.positions)} позиций")
|
||||||
logger.error(f"Ошибка при парсинге заказа файла: \n{e}")
|
|
||||||
|
|
||||||
else:
|
|
||||||
attachment["order"] = order
|
|
||||||
logger.warning(f"Обработан файл с заказом, извлечено позиций, {len(order.positions)}")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
import logging
|
import logging
|
||||||
import pandas as pd
|
from ...abstract_task import AbstractTask, pass_if_error, handle_errors
|
||||||
from io import BytesIO
|
|
||||||
# from mail_order_bot.task_processor.handlers.order_position import OrderPosition
|
|
||||||
from mail_order_bot.task_processor.abstract_task import AbstractTask
|
|
||||||
|
|
||||||
|
|
||||||
from mail_order_bot.order.auto_part_position import PositionStatus
|
|
||||||
from mail_order_bot.parsers.excel_parcer import ExcelFileParcer
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -20,35 +13,31 @@ class UpdateExcelFile(AbstractTask):
|
|||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.excel_config = self.config.get("excel", {})
|
self.excel_config = self.config.get("excel", {})
|
||||||
|
|
||||||
|
@pass_if_error
|
||||||
|
@handle_errors
|
||||||
def do(self, attachment) -> None:
|
def do(self, attachment) -> None:
|
||||||
# todo сделать проверку на наличие файла и его тип
|
# todo сделать проверку на наличие файла и его тип
|
||||||
|
excel_file = attachment.get("excel")
|
||||||
|
order = attachment.get("order")
|
||||||
|
config = self.context.data.get("config", {})
|
||||||
|
excel_config = config.get("excel", {})
|
||||||
|
updatable_fields = excel_config.get("updatable_fields", {})
|
||||||
|
|
||||||
try:
|
for position in order.positions:
|
||||||
excel_file = attachment.get("excel")
|
|
||||||
order = attachment.get("order")
|
|
||||||
config = self.context.data.get("config", {})
|
|
||||||
excel_config = config.get("excel", {})
|
|
||||||
updatable_fields = excel_config.get("updatable_fields", {})
|
|
||||||
|
|
||||||
for position in order.positions:
|
sku = position.sku
|
||||||
|
manufacturer = position.manufacturer
|
||||||
|
|
||||||
sku = position.sku
|
for key, value in updatable_fields.items():
|
||||||
manufacturer = position.manufacturer
|
|
||||||
|
|
||||||
for key, value in updatable_fields.items():
|
if key == "ordered_quantity":
|
||||||
|
column = value
|
||||||
|
value = position.order_quantity
|
||||||
|
excel_file.set_value(sku, manufacturer, column, value)
|
||||||
|
|
||||||
if key == "ordered_quantity":
|
if key == "ordered_price":
|
||||||
column = value
|
column = value
|
||||||
value = position.order_quantity
|
value = position.order_price
|
||||||
excel_file.set_value(sku, manufacturer, column, value)
|
excel_file.set_value(sku, manufacturer, column, value)
|
||||||
|
|
||||||
if key == "ordered_price":
|
|
||||||
column = value
|
|
||||||
value = position.order_price
|
|
||||||
excel_file.set_value(sku, manufacturer, column, value)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Ошибка при правке excel файла: \n{e}")
|
|
||||||
|
|
||||||
else:
|
|
||||||
logger.warning(f"Файл excel успешно обновлен")
|
|
||||||
|
|
||||||
|
logger.warning(f"Файла {attachment.get('name', 'неизвестный файл')} отредактирован")
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from mail_order_bot.order.auto_part_position import AutoPartPosition, PositionSt
|
|||||||
from mail_order_bot.parsers.excel_parcer import ExcelFileParcer
|
from mail_order_bot.parsers.excel_parcer import ExcelFileParcer
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
from mail_order_bot.task_processor.abstract_task import AbstractTask
|
from ...abstract_task import AbstractTask, pass_if_error, handle_errors
|
||||||
from mail_order_bot.abcp_api.abcp_provider import AbcpProvider
|
from mail_order_bot.abcp_api.abcp_provider import AbcpProvider
|
||||||
from mail_order_bot.credential_provider import CredentialProvider
|
from mail_order_bot.credential_provider import CredentialProvider
|
||||||
from mail_order_bot.order.auto_part_order import OrderStatus
|
from mail_order_bot.order.auto_part_order import OrderStatus
|
||||||
@@ -35,39 +35,37 @@ class StockSelector(AbstractTask):
|
|||||||
client_login, client_password = credential_provider.get_system_credentials()
|
client_login, client_password = credential_provider.get_system_credentials()
|
||||||
self.client_provider = AbcpProvider(login=client_login, password=client_password)
|
self.client_provider = AbcpProvider(login=client_login, password=client_password)
|
||||||
|
|
||||||
|
@pass_if_error
|
||||||
|
@handle_errors
|
||||||
def do(self, attachment) -> None:
|
def do(self, attachment) -> None:
|
||||||
# todo сделать проверку на наличие файла и его тип
|
# todo сделать проверку на наличие файла и его тип
|
||||||
|
order = attachment.get("order", None)
|
||||||
|
delivery_period = attachment.get("delivery_period")
|
||||||
|
for position in order.positions:
|
||||||
|
|
||||||
try:
|
#1. Получаем остатки со складов
|
||||||
order = attachment.get("order", None)
|
stock_data = self.client_provider.get_stock(position.sku, position.manufacturer)
|
||||||
delivery_period = attachment.get("delivery_period")
|
|
||||||
for position in order.positions:
|
|
||||||
|
|
||||||
#1. Получаем остатки со складов
|
#2. Из данных остатков выбираем оптимальное значение по стратегии
|
||||||
stock_data = self.client_provider.get_stock(position.sku, position.manufacturer)
|
if stock_data["success"]:
|
||||||
|
stock_list = stock_data.get("data", [])
|
||||||
#2. Из данных остатков выбираем оптимальное значение по стратегии
|
asking_price = position.asking_price
|
||||||
if stock_data["success"]:
|
asking_quantity = position.asking_quantity
|
||||||
stock_list = stock_data.get("data", [])
|
|
||||||
asking_price = position.asking_price
|
|
||||||
asking_quantity = position.asking_quantity
|
|
||||||
|
|
||||||
|
|
||||||
optimal_stock_positions = self.get_optimal_stock(stock_list, asking_price, asking_quantity, delivery_period)
|
optimal_stock_positions = self.get_optimal_stock(stock_list, asking_price, asking_quantity, delivery_period)
|
||||||
|
|
||||||
# 3. Устанавливаем выбранное значение в позицию
|
# 3. Устанавливаем выбранное значение в позицию
|
||||||
if len(optimal_stock_positions):
|
if len(optimal_stock_positions):
|
||||||
position.set_order_item(optimal_stock_positions[0])
|
position.set_order_item(optimal_stock_positions[0])
|
||||||
else:
|
|
||||||
position.status = PositionStatus.NO_AVAILABLE_STOCK
|
|
||||||
# Мне не очень нравится управление статусами в этом месте, кажется что лучше это делать внутри AutoPartPosition
|
|
||||||
else:
|
else:
|
||||||
position.status = PositionStatus.STOCK_FAILED
|
position.status = PositionStatus.NO_AVAILABLE_STOCK
|
||||||
except Exception as e:
|
# Мне не очень нравится управление статусами в этом месте, кажется что лучше это делать внутри AutoPartPosition
|
||||||
logger.error(f"Ошибка при выборе позиции со складов: {e}")
|
else:
|
||||||
|
position.status = PositionStatus.STOCK_FAILED
|
||||||
|
|
||||||
|
logger.warning("Определены оптимальные позиции со складов")
|
||||||
|
|
||||||
else:
|
|
||||||
logger.warning("Определены оптимальные позиции со складов")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ class TaskProcessor:
|
|||||||
file_name = attachment["name"]
|
file_name = attachment["name"]
|
||||||
logger.warning(f"Начата обработка файла: {file_name} =>")
|
logger.warning(f"Начата обработка файла: {file_name} =>")
|
||||||
|
|
||||||
attachment["log_messages"] = LogMessageStorage(file_name)
|
#attachment["log_messages"] = LogMessageStorage(file_name)
|
||||||
|
attachment["status"] = "ok"
|
||||||
|
|
||||||
# Запустить обработку пайплайна
|
# Запустить обработку пайплайна
|
||||||
for handler_name in pipeline:
|
for handler_name in pipeline:
|
||||||
|
|||||||
Reference in New Issue
Block a user