def find(self, table_name, order_by=None, _limit=None, _offset=None, _group_by=None, **where): table = AlchemyDB.get_table(table_name) try: func = asc if order_by and order_by.startswith('_'): order_by = order_by[1:] func = desc if _limit or _offset: sel = select([table]).where(AlchemyDB.args_to_where(table, where)).order_by(func(order_by)).limit( _limit).offset(_offset) elif _group_by: sel = select([table]).where(AlchemyDB.args_to_where(table, where)).order_by(func(order_by)).group_by( func(_group_by)) else: sel = select([table]).where(AlchemyDB.args_to_where(table, where)).order_by(func(order_by)) row = self.conn.execute(sel) tup = row.fetchall() list = [] for r in tup: list.append(dict(r)) return list except exc.SQLAlchemyError as err: Log.log_error("find error %s" % err) return False
def _handle_do_rm_choice_cmd(self, text): # /do-rm-choice-{choice_id} try: choice_id = int(text[14:]) except Exception: Log.e(f"Failed while parsing choice id: {text}") raise with model.open_session(self._Session) as s: poll_ms = _query_active_polls(s, self._chat_id) if not poll_ms: raise _ResponseException(self.RESPONSE_ERROR_POLL_NOT_EXIST) poll_m = poll_ms[0] if poll_m.creator_user_id != self._user["id"]: raise _ResponseException(self.RESPONSE_ERROR_NOT_CREATOR) if len(poll_m.choices) == 1: raise _ResponseException(self.RESPONSE_ERROR_RM_LAST_CHOICE) choice_m = next( filter(lambda c_m: c_m.poll_choice_id == choice_id, poll_m.choices)) choice = choice_m.text s.delete(choice_m) self._edit_message_text(self.RESPONSE_RM_CHOICE_PERSISTED_F % choice, parse_mode="Markdown")
def _handle_new_poll_response(self, text): try: lines = text.strip().split("\n") title = lines[0] choices = lines[1:] except Exception: # Wrong format raise _ResponseException(self.RESPONSE_ERROR_NEWPOLL_FORMAT) if not choices: # No poll choices! raise _ResponseException(self.RESPONSE_ERROR_MISSING_CHOICES) try: with model.open_session(self._Session) as s: if self._has_active_polls(s): raise _ResponseException(self.RESPONSE_ERROR_POLL_EXIST) self._persist_new_poll(s, title, choices) self._bot.sendMessage(self._glance["chat_id"], self.RESPONSE_NEWPOLL_PERSISTED_F % title, parse_mode="Markdown") except Exception: Log.i(f"Failed persisting new poll \"{title}\": {choices}") raise
def init(): try: mysql_string = manage.app.config['DATABASE_URI'] + 'happay_data' AlchemyDB.engine = create_engine(mysql_string, paramstyle='format', isolation_level="READ UNCOMMITTED") meta = MetaData() AlchemyDB.question_value = Table('question_value', meta, Column('aid', INT), Column('question', TEXT), Column('option_one', VARCHAR(255)), Column('option_two', VARCHAR(255)), Column('option_three', VARCHAR(255)), Column('option_four', VARCHAR(255)), Column('soft_delete', INT) ) AlchemyDB._table['question_value'] = AlchemyDB.question_value meta.create_all(AlchemyDB.engine) except exc.SQLAlchemyError as error: Log.log_error("CreateConnectionPool Exception: %s" % error)
def _do_handle(self): Log.v(self._msg) if self._glance["content_type"] == "text": if self._msg["text"].startswith("/"): self._handle_cmd(self._msg["text"]) else: self._handle_text(self._msg["text"])
def importar(): """ Faz a importação das categorias criadas no site para serem usadas no envio de novos produtos """ template = 'categorias/importar/form-importar.html' categorias = MagCategorias.by(parent_id=2) form = ImportarCategoriaForm() config = ConfigMagento.by_id(1) has_cat_default = config.categoria_default if config else None if form.validate_on_submit() and has_cat_default: Log.info(f'[CATEGORIAS] Iniciando a atualização das Categorias.') registrar_categorias() Log.info(f'[CATEGORIAS] Atualização das Categorias finalizado.') result = { 'title': 'Categorias', 'subtitle': 'Importar do Site', 'categorias': categorias, 'has_cat_default': has_cat_default, 'tasks': True, 'form': form } return render_template(template, **result)
def delete_row(self, table_name, **where): table = AlchemyDB.get_table(table_name) try: delete = table.delete().where(AlchemyDB.args_to_where(table, where)) self.conn.execute(delete) except exc.SQLAlchemyError as err: Log.log_error("delete error %s" % err) return False
def _handle_do_unvote_cmd(self, text): # /do-unvote-{choice_id} try: vote = int(text[11:]) except Exception: Log.e(f"Failed while parsing choice id: {text}") raise with model.open_session(self._Session) as s: poll_ms = _query_active_user_votes(s, self._chat_id, self._user["id"]) if not poll_ms: raise _ResponseException( self.RESPONSE_ERROR_NOT_VOTED % f"[{self._user['first_name']}](tg://user?id={self._user['id']})" ) poll_m = poll_ms[0] for c_m in poll_m.choices: if c_m.poll_choice_id == vote: for v_m in c_m.votes: if v_m.user_id == self._user["id"]: vote_m = v_m break try: choice_text = vote_m.choice.text s.delete(vote_m) except NameError: # User hasn't voted this option? raise _ResponseException( self.RESPONSE_ERROR_NOT_VOTED % f"[{self._user['first_name']}](tg://user?id={self._user['id']})" ) text = self.RESPONSE_UNVOTED % ( f"[{self._user['first_name']}](tg://user?id={self._user['id']})" ) announce_text = self.RESPONSE_UNVOTE_ANNOUNCE % ( f"[{self._user['first_name']}](tg://user?id={self._user['id']})", choice_text) self._edit_message_text(text, parse_mode="Markdown") self._send_message(announce_text, parse_mode="Markdown") # Start a new session to make the delete effective with model.open_session(self._Session) as s: poll_ms = _query_active_polls(s, self._chat_id) if not poll_ms: # ??? raise _ResponseException(self.RESPONSE_ERROR_POLL_NOT_EXIST) poll_m = poll_ms[0] poll_text = _repr_poll(poll_m) poll_keyboard = _make_poll_inline_keyboard( poll_m.creator_user_id == self._user["id"]) self._send_message( poll_text, parse_mode="Markdown", reply_markup=InlineKeyboardMarkup(inline_keyboard=poll_keyboard))
def _handle_do_vote_cmd(self, text): # /do-vote-{choice_id} try: vote = int(text[9:]) except Exception: Log.e(f"Failed while parsing choice id: {text}") raise with model.open_session(self._Session) as s: poll_ms = _query_active_polls(s, self._chat_id) if not poll_ms: raise _ResponseException(self.RESPONSE_ERROR_POLL_NOT_EXIST) poll_m = poll_ms[0] user_id = self._user["id"] for c_m in poll_m.choices: if c_m.poll_choice_id == vote: choice_m = c_m break # We don't need a fallback val for choice_m -- it'll raise when we # access it anyway if not poll_m.is_multiple_vote: # Make sure user hasn't voted yet for c_m in poll_m.choices: if any(user_id == v_m.user_id for v_m in c_m.votes): raise _ResponseException( self.RESPONSE_ERROR_MULTIPLE_VOTE % f"[{self._user['first_name']}](tg://user?id={self._user['id']})" ) else: # Make sure user hasn't voted for this choice yet if any(user_id == v_m.user_id for v_m in choice_m.votes): raise _ResponseException( self.RESPONSE_ERROR_IDENTICAL_VOTE % f"[{self._user['first_name']}](tg://user?id={self._user['id']})" ) vote_m = model.PollVote(user_id=user_id, user_name=self._user["first_name"], choice=choice_m) s.add(vote_m) text = self.RESPONSE_VOTED % ( f"[{self._user['first_name']}](tg://user?id={self._user['id']})" ) announce_text = self.RESPONSE_VOTE_ANNOUNCE % ( f"[{self._user['first_name']}](tg://user?id={self._user['id']})", choice_m.text) poll_text = _repr_poll(poll_m) poll_keyboard = _make_poll_inline_keyboard( poll_m.creator_user_id == self._user["id"]) self._edit_message_text(text, parse_mode="Markdown") self._send_message(announce_text, parse_mode="Markdown") self._send_message( poll_text, parse_mode="Markdown", reply_markup=InlineKeyboardMarkup(inline_keyboard=poll_keyboard))
def enviar_imagem(): """ Envia as imagens dos produtos """ template = 'produtos/form-enviar-imagem.html' if current_app.config['UPLOADS_DEFAULT_URL'] is None: warning('A URL Base do Sistema não está configurada. ' + 'Configure-a para que as imagens possam ser salvas.') return redirect(url_for('integrador.produtos_enviar_imagem')) if request.method == 'POST': import os import glob base_path = os.getcwd() + '/uploads/photos/' imagem = request.files['file'] nome = imagem.filename sku = int(nome.split('.')[0]) filepath = base_path + nome if nome == '': return 'Nenhuma Imagem Foi Selecionada', 400 if nome.rfind('.') == -1: return 'O arquivo informado não possui extensão definida', 400 ext = nome.split('.')[1].lower() if not imageSet.extension_allowed(ext): return 'A extensão informada não é válida', 400 if not validar_nome_imagem(nome): return 'O nome da imagem precisa ser um codigo válido', 400 # verifca se ja existe alguma imagem na pasta deste item # pegando o sku do item e iterando na pasta de destino, verificando # se existe alguma imagem e a removendo path = os.path.dirname(filepath) if os.path.exists(path): for im in glob.glob(os.path.join(path, f'{sku}*.*')): os.remove(os.path.join(path, im)) image = imageSet.save(imagem) image = base_path + image genImage(image, image) # busca o cadastro do produto e se existir altera para atualizar imagem produto = MagProduto.by(sku=sku) if produto: produto.atualiza_imagem = True produto.possui_imagem = True produto.update() Log.info(f'[ENVIAR IMAGEM] Enviado Imagem do produto {nome}.') result = {'title': 'Produtos', 'subtitle': 'Enviar Imagens'} return render_template(template, **result)
def _do_handle(self): Log.v(self._msg) if self._glance["content_type"] == "text": if self._msg["text"].startswith("/"): self._handle_command(self._msg["text"]) else: self._handle_text(self._msg["text"]) else: self._bot.sendMessage(self._glance["chat_id"], self.RESPONSE_NON_TEXTUAL_INPUT)
def find_one(self, table_name, **where): table = AlchemyDB.get_table(table_name) try: sel = select([table]).where(AlchemyDB.args_to_where(table, where)) row = self.conn.execute(sel) tup = row.fetchone() return dict(tup) except exc.SQLAlchemyError as err: Log.log_error("find error %s" % err) return False
def _edit_message_text(self, *args, **kwargs): try: self._bot.editMessageText( (self._chat_id, self._msg["message"]["message_id"]), *args, **kwargs) except TelegramError as e: if e.error_code == 400 \ and e.description == "Bad Request: message is not modified": # Clicked button twice? Log.d("Failed while editMessageText", e)
def handle(self): try: self._do_handle() except _ResponseException as e: Log.e("Failed while handle", e) self._bot.sendMessage(self._glance["chat_id"], e.response) except Exception as e: Log.e("Failed while handle", e) self._bot.sendMessage(self._glance["chat_id"], self.RESPONSE_EXCEPTION)
def test_init_logger(self) -> None: Log.init_logger(log_name=TEST_MODULE_NAME) mock_makedirs.assert_called_once_with('logs', exist_ok=True) (_, handler_kwargs) = mock_handler.call_args assert handler_kwargs['filename'] == LOG_FILE_PATH (_, config_kwargs) = mock_basic_config.call_args assert config_kwargs['level'] == logging.INFO
def _callback(): try: self._ensure_allowed_users() return self._do_handle() except _WhitelistException as e: Log.i("Disallowed user (%s) is chating with us" % self._msg["from"]["first_name"]) return self.RESPONSE_DISALLOWED_USER except Exception as e: Log.e("Failed while _do_handle", e) return self.RESPONSE_EXCEPTION
def _start(self): Log.i("Starting app") def _listener(msg): self._on_message(msg) def _inline_listener(msg): self._on_inline_message(msg) self._bot.setWebhook("") self._bot.message_loop({ "chat": _listener, "inline_query": _inline_listener, })
def _start(self): Log.i("Starting app") def _listener(msg): self._on_message(msg) def _callback_query_listener(msg): self._on_callback_query(msg) self._bot.setWebhook("") self._bot.message_loop({ "chat": _listener, "callback_query": _callback_query_listener, })
def handle(self): try: self._do_handle() except _ResponseException as e: Log.e("Failed while handle", e) self._send_message(e.response, parse_mode="Markdown") except Exception as e: Log.e("Failed while handle", e) self._send_message(self.RESPONSE_EXCEPTION) finally: # After the user presses a callback button, Telegram clients will # display a progress bar until you call answerCallbackQuery. It is, # therefore, necessary to react by calling answerCallbackQuery even # if no notification to the user is needed self._bot.answerCallbackQuery(self._glance["query_id"])
def handle(self): try: self._ensure_supported_chat() self._ensure_allowed_users() self._do_handle() except _ChanelException as e: pass except _WhitelistException as e: Log.i("Disallowed user (%s) is chating with us" % self._msg["from"]["first_name"]) self._bot.sendMessage(self._glance["chat_id"], self.RESPONSE_MD_DISALLOWED_USER, parse_mode = "Markdown") except Exception as e: Log.e("Failed while _do_handle", e) self._bot.sendMessage(self._glance["chat_id"], self.RESPONSE_EXCEPTION)
def test(self, q, _limit=None, _offset=None): try: if _limit or _offset: sel = q + " LIMIT " + str(_limit) + " OFFSET " + str(_offset) else: sel = q Log.log_error(sel) row = self.conn.execute(sel) tup = row.fetchall() list = [] for r in tup: list.append(dict(r)) return list except exc.SQLAlchemyError as err: Log.log_error("find error %s" % err) return False
def _build_response(self, text): query = _QueryHandler(text) if query.is_empty: return self._TextResponse(self.RESPONSE_NO_RESULTS) try: response = CustomSearchApi().list(**query.request_args) except CustomSearchApi.NetworkError as e: Log.e("Failed while list %d: %s" % (e.status_code, e.message)) if e.status_code == 404: return self._TextResponse(self.RESPONSE_NO_MORE_QUOTA) else: raise e if not response or "items" not in response: return self._TextResponse(self.RESPONSE_NO_RESULTS) if query.is_image: return self._build_image_response(response) else: return self._build_text_response(response)
def atualizar_base(produtos): """ recebe um lista dos produtos do site e atualiza a base do sistema """ Log.info('[ATUALIZA BASE] Iniciando a atualização da base') for p in produtos: sku = p['sku'] if sku.isdigit(): sku = int(sku) mag_produto = MagProduto.by(sku=sku) produto_ciss = CissProdutoGrade.by(idsubproduto=sku) if not mag_produto and produto_ciss: Log.info(f'[ATUALIZA BASE] Registrando o item {sku}') try: produto_site = productInfo(sku) except Exception: continue mag_produto = MagProduto() mag_produto.sku = sku mag_produto.idsecao = produto_site['categories'][0] mag_produto.idgrupo = produto_site['categories'][1] mag_produto.idsubgrupo = produto_site['categories'][2] mag_produto.atualiza_imagem = False mag_produto.possui_imagem = True mag_produto.update() Log.info('[ATUALIZA BASE]------ Registrado no Integrador') # salva no erp verificando se esta ativo no site status = produto_site['status'] produto_ciss.idmodelo = 4 produto_ciss.idtipo = 2 if status == '1' else 3 produto_ciss.update() Log.info('[ATUALIZA BASE]------ Registrado no ERP') Log.info('[ATUALIZA BASE] Atualização da base Finalizada')
def _do_handle(self): Log.v(self._msg) query = _QueryHandler(self._glance["query_string"]) if query.is_empty: return [] try: response = CustomSearchApi().list(**query.request_args) except CustomSearchApi.NetworkError as e: Log.e("Failed while list %d: %s" % (e.status_code, e.message)) if e.status_code == 403: return self.RESPONSE_NO_MORE_QUOTA else: raise e if not response or "items" not in response: return self.RESPONSE_NO_RESULTS if query.is_image: return self._build_image_response(response) else: return self._build_text_response(response)
def handle(self): try: self._ensure_allowed_users() response = self._do_handle() except _WhitelistException as e: Log.i("Disallowed user (%s) is chating with us" % self._msg["from"]["first_name"]) response = self.RESPONSE_DISALLOWED_USER except Exception as e: Log.e("Failed while _do_handle", e) response = self.RESPONSE_EXCEPTION if isinstance(response, list): self._bot.answerInlineQuery(self._glance["query_id"], response) elif isinstance(response, tuple): self._bot.answerInlineQuery(self._glance["query_id"], *response) elif isinstance(response, dict): self._bot.answerInlineQuery(self._glance["query_id"], **response) else: raise ValueError("Invalid response format")
def update_row(self, table_name, *keys, **row): table = AlchemyDB.get_table(table_name) try: if not isinstance(keys, (list, tuple)): keys = [keys] if not keys or len(keys) == len(row): return False clause = dict() for k in keys: clause[k] = row[k] clean_row = row.copy() for key in keys: if key in clean_row.keys(): del clean_row[key] clauses = AlchemyDB.args_to_where(table, clause) update = table.update(clauses, clean_row) self.conn.execute(update) return True except Exception as err: Log.log_error("update error %s" % err) return False
def list(self, q, **kwargs): Log.d("Searching: %s" % q) if not q: return {} args = dict(kwargs) args.update({ "key": self.API_KEY, "cx": self.SEARCH_ENGINE_ID, "safe": "medium", "q": q, }) with http_request("GET", self.URL, params=args) as response: if response.status_code != 200: Log.e("Failed while list: %d" % response.status_code) if response.text: raise self.NetworkError(url=self.URL, status_code=response.status_code, message=response.text) else: raise self.NetworkError(url=self.URL, status_code=response.status_code) else: return response.json()
def after_request(response): ip = None if os.environ["ENVIRONMENT"] == "production": ip = request.headers.get("X-Forwarded-For") else: ip = request.remote_addr method = request.method path = request.path status_code = response.status_code user_id = None if current_user.is_authenticated: user_id = current_user.id log = Log(ip, method, path, status_code, user_id) db.session.add(log) db.session.commit() return response
""" from iw import InstructionWindow from ib import InstructionBuffer from rob import ReorderBuffer from mem import DataMemory, InstructionsMemory from reg import Registers from fu import FunctionalUnit from pipeline import IF, ID, ISS, ALU, MEM, WB, COM import app.defaults as DEF from app.log import Log from datastructures import asm from datastructures.instruction import Trap l = Log( "cpu" ) class CPU: def __init__( self, mem_size=DEF.MEM_SIZE, iw_size=DEF.IW_SIZE, rob_size=DEF.ROB_SIZE, S=DEF.S ): # Initialize architecture self.rob = ReorderBuffer( rob_size ) self.dmem = DataMemory( mem_size ) self.imem = InstructionsMemory() self.ib = InstructionBuffer() self.iw = InstructionWindow( iw_size ) self.regs = Registers() self.fu = { asm.MULT : FunctionalUnit( asm.MULT ), asm.ADD : FunctionalUnit( asm.ADD ) } self.PC = 0x00
def atualiza_imagem_task(self): """ Usado para atualizar as imagens de produtos que ja estão no site """ with app.app_context(): Log.info(f'[IMAGENS] Iniciando o envio dos produtos.') db.engine.dispose() produtos = MagProduto.query.filter( MagProduto.atualiza_imagem == True ).all() imagens = read_images() concluidos = 0 erros_count = 0 erros = [] count = 0 total = len(produtos) for p in produtos: Log.info(f'[IMAGENS] Iniciando o envio do item {p.sku}.') self.update_state( state='PROGRESS', meta={ 'name': format_task_name(self.name), 'complete': concluidos, 'errors_count': erros_count, 'errors': erros, 'current': count, 'total': total, 'status': f'Enviando o produto {p.sku}' } ) try: imagem = imagens.get(p.sku, None) nome_imagem = str(p.sku) if not imagem: Log.info(f'[IMAGENS]------ Produto sem imagem') count += 1 continue imagens_site = listImage( p.sku ) # verifca se o produto possui imagens para serem excluidas # antes de enviar a nova if imagens_site: for im in imagens_site: # se ao tentar excluir a imagem gerar a exceção de que # a imagem nao existe na galeria do produto salva como # erro para ser exida ao usuario try: removeImage( p.sku, im['file'], ) except Fault as e: pass # se existir imagens altera o nome para adcionar um contador # exemplo: 13504_6 nome_imagem = f'{nome_imagem}_{len(imagens_site) + 1}' updateImage( imagem, nome_imagem, str(p.sku) ) Log.info(f'[IMAGENS]------ Imagem enviada com sucesso') p.atualiza_imagem = False p.update() Log.info(f'[IMAGENS]------ Produto Atulizado no Integrador') concluidos += 1 except Exception as e: erros_count += 1 erros.append(f'Produto: {p.sku} -------- Erro: {e}') Log.error( f'[IMAGENS] Erro ao enviar o produto {p.sku} erro: {e}') count += 1 Log.info(f'[IMAGENS] Envio de produtos finalizado.') return { 'name': format_task_name(self.name), 'complete': concluidos, 'errors_count': erros_count, 'errors': erros, 'current': total, 'total': total, 'status': 'complete' }
def run(self): import time self._start() Log.i("Running...") while True: time.sleep(10)
def __init__(self): Log.i("Initializing standalone app") self._bot = telepot.Bot(self.TELEGRAM_TOKEN)
for tweet in tweets: self.show_tweet_media(tweet) def show_rt_media(self, user: TwitterUser) -> None: logger.info( f'Show RT tweet media. user={user.id}. pages={self.tweet_page}, count={self.tweet_count}, ' f'since_id={user.since_id}') for tweets in tweepy.Cursor(self.api.user_timeline, id=user.id, tweet_mode='extended', count=self.tweet_count, since_id=user.since_id).pages( self.tweet_page): if user.since_id < tweets.since_id: user.since_id = tweets.since_id for tweet in tweets: if not has_attributes(tweet, 'retweeted_status'): continue self.show_tweet_media(tweet) logger: logging.Logger = logging.getLogger(__name__) if __name__ == '__main__': Log.init_logger(log_name='twitter') logger = logging.getLogger(__name__) twitter_user = TwitterUser(id='TwitterJP') t = Twitter() Twitter.Debug(t).show_rt_media(twitter_user)
def main(self) -> None: interval_minutes: int = int( Env.get_environment('INTERVAL', default='5')) user_ids: str = Env.get_environment('TWITTER_USER_IDS', required=True) user_list: List[TwitterUser] = [ TwitterUser(id=user_id) for user_id in user_ids.split(',') ] while True: try: for user in user_list: logger.info( f'Crawling start. user = {user.id}, mode={self.twitter.mode}' ) self.crawling_tweets(user) except Exception as e: logger.exception(f'Crawling error exception={e.args}') logger.info(f'Interval. sleep {interval_minutes} minutes.') time.sleep(interval_minutes * 60) logger: logging.Logger = logging.getLogger(__name__) if __name__ == '__main__': Log.init_logger(log_name='crawler') logger = logging.getLogger(__name__) crawler = Crawler() crawler.main()
def __init__(self): Log.i("Initializing PAW app") self._init_paw_telepot() self._bot = telepot.Bot(self.TELEGRAM_TOKEN)
with self._get_connection() as connection: with connection.cursor() as cursor: cursor.execute(query=query, vars=(tweet_ids, )) return cursor.fetchall() def fetch_all_failed_upload_medias(self) -> List[Tuple[str, str, str]]: logger.debug( 'Fetch url and description from failed_upload_media table.') query: str = 'SELECT url, description, user_id ' \ 'FROM failed_upload_media' with self._get_connection() as connection: with connection.cursor() as cursor: cursor.execute(query=query) return cursor.fetchall() def delete_failed_upload_media(self, url: str) -> None: logger.debug(f'Delete row url={url} from failed_upload_media table.') query: str = 'DELETE FROM failed_upload_media ' \ 'WHERE url = %s' with self._get_connection() as connection: with connection.cursor() as cursor: cursor.execute(query=query, vars=(url, )) logger: logging.Logger = logging.getLogger(__name__) if __name__ == '__main__': Log.init_logger(log_name='store') logger = logging.getLogger(__name__) db = Store()
from typing import Optional from fastapi import APIRouter, HTTPException, status, Query, HTTPException from app.log import Log from .rfm import RFM from .parameters_validation import DocumentIDValidation, RFMParametersValidation from .rfm_database import RFMDatabase router = APIRouter() rfm_logger = Log.get_instance().root_logger @router.post("/rfm_segmentation_with_saved_data/", response_model=str) async def rfm_segmentation_with_saved_data(document_id: DocumentIDValidation): rfm_logger.info( "Request to perform RFM Segmentation with saved parameters: {}".format(document_id)) # Get rfm parameters document_id = document_id.dict().get("document_id") rfm_parameters = RFMDatabase.get_instance().get_segmentation_parameters(document_id) if not rfm_parameters: raise HTTPException(status_code=404, detail="Document not found") # Perform RFM Segmentation rfm_obj = RFM(rfm_parameters, document_id) try: rfm_df, start_date, end_date = rfm_obj.perform_rfm_segmentation( rfm_logger) if rfm_df.empty: raise HTTPException(status_code=404)